capability-runtime 0.1.2__tar.gz → 0.1.3.post1__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 (141) hide show
  1. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/PKG-INFO +1 -1
  2. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/pyproject.toml +1 -1
  3. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/__init__.py +1 -1
  4. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/adapters/agent_adapter.py +54 -10
  5. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/adapters/triggerflow_workflow_engine.py +2 -3
  6. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/host_protocol.py +9 -1
  7. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/runtime.py +46 -9
  8. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/sdk_lifecycle.py +87 -3
  9. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/structured_output.py +42 -16
  10. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime.egg-info/PKG-INFO +1 -1
  11. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime.egg-info/SOURCES.txt +1 -0
  12. capability_runtime-0.1.3.post1/tests/test_agently_backend.py +630 -0
  13. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_release_tag_version_guardrail.py +2 -2
  14. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_runtime_hitl_host_protocol.py +41 -0
  15. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_runtime_hooks_and_schema_gate.py +60 -0
  16. capability_runtime-0.1.3.post1/tests/test_runtime_result_prompt_hardening.py +284 -0
  17. capability_runtime-0.1.2/tests/test_agently_backend.py +0 -285
  18. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/README.md +0 -0
  19. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/setup.cfg +0 -0
  20. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/adapters/__init__.py +0 -0
  21. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/adapters/agently_backend.py +0 -0
  22. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/adapters/workflow_engine.py +0 -0
  23. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/config.py +0 -0
  24. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/errors.py +0 -0
  25. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/guards.py +0 -0
  26. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/host_toolkit/__init__.py +0 -0
  27. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/host_toolkit/approvals_profiles.py +0 -0
  28. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/host_toolkit/evidence_hooks.py +0 -0
  29. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/host_toolkit/history.py +0 -0
  30. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/host_toolkit/invoke_capability.py +0 -0
  31. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/host_toolkit/resume.py +0 -0
  32. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/host_toolkit/system_prompt.py +0 -0
  33. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/host_toolkit/turn_delta.py +0 -0
  34. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/logging_utils.py +0 -0
  35. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/manifest.py +0 -0
  36. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/output_validator.py +0 -0
  37. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/protocol/__init__.py +0 -0
  38. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/protocol/agent.py +0 -0
  39. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/protocol/capability.py +0 -0
  40. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/protocol/chat_backend.py +0 -0
  41. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/protocol/context.py +0 -0
  42. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/protocol/workflow.py +0 -0
  43. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/registry.py +0 -0
  44. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/reporting/__init__.py +0 -0
  45. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/reporting/node_report.py +0 -0
  46. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/runtime_ui_events_mixin.py +0 -0
  47. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/service_facade.py +0 -0
  48. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/services.py +0 -0
  49. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/structured_stream.py +0 -0
  50. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/types.py +0 -0
  51. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/ui_events/__init__.py +0 -0
  52. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/ui_events/projector.py +0 -0
  53. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/ui_events/session.py +0 -0
  54. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/ui_events/store.py +0 -0
  55. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/ui_events/transport.py +0 -0
  56. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/ui_events/v1.py +0 -0
  57. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/upstream_compat.py +0 -0
  58. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/utils/__init__.py +0 -0
  59. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/utils/usage.py +0 -0
  60. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime/workflow_runtime.py +0 -0
  61. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime.egg-info/dependency_links.txt +0 -0
  62. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime.egg-info/requires.txt +0 -0
  63. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/src/capability_runtime.egg-info/top_level.txt +0 -0
  64. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_agently_backend_replay.py +0 -0
  65. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_backend_mode.py +0 -0
  66. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_bilingual_docs_surface.py +0 -0
  67. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_bridge_artifacts_passthrough.py +0 -0
  68. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_bridge_register_tool_public_api.py +0 -0
  69. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_coding_agent_examples_atomic.py +0 -0
  70. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_coding_agent_examples_recipes.py +0 -0
  71. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_config_glue.py +0 -0
  72. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_dependency_pins.py +0 -0
  73. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_docs_pinned_dependency_versions.py +0 -0
  74. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_docs_scheme2_no_skilladapter_residue.py +0 -0
  75. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_error_observability.py +0 -0
  76. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_examples_alignment_fixes_l1.py +0 -0
  77. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_examples_no_agent_sdk_imports.py +0 -0
  78. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_examples_real_evidence_strict_integration.py +0 -0
  79. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_examples_real_integration.py +0 -0
  80. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_examples_smoke.py +0 -0
  81. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_examples_ui_events_showcase_offline.py +0 -0
  82. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_examples_ui_events_showcase_real_fallback.py +0 -0
  83. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_examples_ui_events_showcase_real_integration.py +0 -0
  84. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_examples_ui_events_showcase_ui_contract.py +0 -0
  85. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_examples_workflow_skills_first_smoke.py +0 -0
  86. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_guards.py +0 -0
  87. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_host_toolkit_approvals_profiles.py +0 -0
  88. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_host_toolkit_history_assembler.py +0 -0
  89. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_host_toolkit_invoke_capability.py +0 -0
  90. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_host_toolkit_invoke_capability_shared_runtime.py +0 -0
  91. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_host_toolkit_resume_helper.py +0 -0
  92. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_host_toolkit_system_prompt_evidence.py +0 -0
  93. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_host_toolkit_turn_delta.py +0 -0
  94. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_integration_agently_requester_smoke.py +0 -0
  95. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_integration_approval_event_shape.py +0 -0
  96. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_integration_sources_redis_pgsql_smoke.py +0 -0
  97. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_loop.py +0 -0
  98. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_node_report_builder.py +0 -0
  99. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_node_report_contract_v1.py +0 -0
  100. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_node_report_engine_identity_contract.py +0 -0
  101. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_offline_backend_injection_evidence.py +0 -0
  102. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_per_capability_llm_config_model_routing.py +0 -0
  103. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_preflight_gate.py +0 -0
  104. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_project_identity_naming_matrix.py +0 -0
  105. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_public_api_exports.py +0 -0
  106. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_public_repo_hygiene.py +0 -0
  107. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_qa_agent.py +0 -0
  108. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_registry.py +0 -0
  109. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_replay_tool_calls_alignment.py +0 -0
  110. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_repo_hygiene_no_tracked_env_or_pyc.py +0 -0
  111. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_repo_no_deep_imports_in_user_facing_docs.py +0 -0
  112. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_review_followups_module_contracts.py +0 -0
  113. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_runtime_bridge_fake_backend.py +0 -0
  114. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_runtime_concurrency.py +0 -0
  115. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_runtime_engine.py +0 -0
  116. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_runtime_initial_history_and_meta.py +0 -0
  117. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_runtime_manifest.py +0 -0
  118. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_runtime_run_stream_semantics_v1.py +0 -0
  119. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_runtime_service_facade_rpc_mapping.py +0 -0
  120. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_runtime_service_session_bridge.py +0 -0
  121. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_runtime_status_mapping.py +0 -0
  122. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_runtime_structured_output_bridge.py +0 -0
  123. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_runtime_structured_stream.py +0 -0
  124. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_sandbox_permissions_passthrough_contract.py +0 -0
  125. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_services_call_callback.py +0 -0
  126. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_services_map_node_status.py +0 -0
  127. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_skills_conformance_smoke.py +0 -0
  128. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_upstream_adapter_tool_registration.py +0 -0
  129. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_upstream_chat_backend_protocol_contract.py +0 -0
  130. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_upstream_chat_sse_usage_contract.py +0 -0
  131. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_upstream_compat_spaces_schema.py +0 -0
  132. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_upstream_prompt_profile_contract.py +0 -0
  133. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_upstream_runtime_client_server_contract.py +0 -0
  134. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_upstream_sandbox_profile_precedence_contract.py +0 -0
  135. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_upstream_skills_bundles_contract.py +0 -0
  136. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_upstream_tool_descriptor_compat.py +0 -0
  137. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_upstream_verification.py +0 -0
  138. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_versioning_strategy_guard.py +0 -0
  139. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_wal_backend_injection_contract.py +0 -0
  140. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_wal_locator_resolution_contract.py +0 -0
  141. {capability_runtime-0.1.2 → capability_runtime-0.1.3.post1}/tests/test_workflow_host_runtime_surface.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: capability-runtime
3
- Version: 0.1.2
3
+ Version: 0.1.3.post1
4
4
  Summary: Bridge/glue layer that composes Agently (LLM/TriggerFlow) with skills-runtime-sdk (skills/tools/WAL/events).
5
5
  License-Expression: MIT
6
6
  Requires-Python: >=3.10
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "capability-runtime"
3
- version = "0.1.2"
3
+ version = "0.1.3.post1"
4
4
  description = "Bridge/glue layer that composes Agently (LLM/TriggerFlow) with skills-runtime-sdk (skills/tools/WAL/events)."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -1,7 +1,7 @@
1
1
  """capability-runtime:统一 Runtime 入口(能力协议 + 执行 + 报告)。"""
2
2
  from __future__ import annotations
3
3
 
4
- __version__ = "0.1.2"
4
+ __version__ = "0.1.3.post1"
5
5
 
6
6
  # === 统一入口 ===
7
7
  from .config import CustomTool, RuntimeConfig
@@ -80,6 +80,7 @@ class AgentAdapter:
80
80
  spec: AgentSpec,
81
81
  input: Dict[str, Any],
82
82
  context: ExecutionContext,
83
+ prompt_control: Optional[Dict[str, Any]] = None,
83
84
  ) -> AsyncIterator[Union[AgentEvent, CapabilityResult]]:
84
85
  """
85
86
  流式执行 AgentSpec:先 yield AgentEvent(若为真实执行),最后 yield CapabilityResult。
@@ -93,6 +94,7 @@ class AgentAdapter:
93
94
 
94
95
  备注:
95
96
  - 每条 `AgentEvent` 也会通过 Runtime 的内部 tap 旁路分发(用于 UI events 投影;不改变对外 `AgentEvent` 转发语义)。
97
+ - `prompt_control` 为显式 prompt 控制面,优先于兼容入口 `input["_runtime_prompt"]`。
96
98
  """
97
99
 
98
100
  mode = str(getattr(self._services.config, "mode", "mock"))
@@ -100,7 +102,12 @@ class AgentAdapter:
100
102
  yield await self._mock_execute(spec=spec, input=input, context=context)
101
103
  return
102
104
 
103
- async for item in self._bridge_execute_stream(spec=spec, input=input, context=context):
105
+ async for item in self._bridge_execute_stream(
106
+ spec=spec,
107
+ input=input,
108
+ context=context,
109
+ prompt_control=prompt_control,
110
+ ):
104
111
  yield item
105
112
 
106
113
  async def _mock_execute(self, *, spec: AgentSpec, input: Dict[str, Any], context: ExecutionContext) -> CapabilityResult:
@@ -193,14 +200,26 @@ class AgentAdapter:
193
200
  )
194
201
 
195
202
  async def _bridge_execute_stream(
196
- self, *, spec: AgentSpec, input: Dict[str, Any], context: ExecutionContext
203
+ self,
204
+ *,
205
+ spec: AgentSpec,
206
+ input: Dict[str, Any],
207
+ context: ExecutionContext,
208
+ prompt_control: Optional[Dict[str, Any]] = None,
197
209
  ) -> AsyncIterator[Union[AgentEvent, CapabilityResult]]:
198
210
  """
199
211
  真实执行(bridge/sdk_native):驱动 SDK Agent.run_stream_async 并聚合 NodeReport。
212
+
213
+ 参数:
214
+ - prompt_control:显式 prompt 控制面;为空时回退读取 `input["_runtime_prompt"]`。
200
215
  """
201
216
 
202
217
  try:
203
- prompt_plan = self._resolve_prompt_render_plan(spec=spec, input=input)
218
+ prompt_plan = self._resolve_prompt_render_plan(
219
+ spec=spec,
220
+ input=input,
221
+ prompt_control=prompt_control,
222
+ )
204
223
  except _InvalidPromptMessages as exc:
205
224
  report = self._services.build_fail_closed_report(
206
225
  run_id=context.run_id,
@@ -283,6 +302,19 @@ class AgentAdapter:
283
302
  events: List[AgentEvent] = []
284
303
  host_meta = self._services.get_host_meta(context=context)
285
304
  initial_history = host_meta.get("initial_history") if isinstance(host_meta.get("initial_history"), list) else None
305
+ on_event_error_count = 0
306
+ on_event_last_error_type: Optional[str] = None
307
+
308
+ def _apply_on_event_error_evidence(report: Any) -> None:
309
+ """把 on_event fail-open 错误摘要写入 NodeReport.meta。"""
310
+
311
+ if on_event_error_count <= 0:
312
+ return
313
+ meta = getattr(report, "meta", None)
314
+ if isinstance(meta, dict):
315
+ meta["on_event_error_count"] = on_event_error_count
316
+ if on_event_last_error_type:
317
+ meta["on_event_last_error_type"] = on_event_last_error_type
286
318
 
287
319
  try:
288
320
  async for ev in agent.run_stream_async(task, run_id=context.run_id, initial_history=initial_history):
@@ -306,6 +338,8 @@ class AgentAdapter:
306
338
  {"run_id": context.run_id, "capability_id": spec.base.id},
307
339
  )
308
340
  except Exception as cb_exc:
341
+ on_event_error_count += 1
342
+ on_event_last_error_type = type(cb_exc).__name__
309
343
  log_suppressed_exception(
310
344
  context="on_event_callback",
311
345
  exc=cb_exc,
@@ -323,6 +357,7 @@ class AgentAdapter:
323
357
  meta={"capability_id": spec.base.id, "source": "sdk_agent"},
324
358
  )
325
359
  self._apply_prompt_evidence(report=report, evidence=prompt_plan.evidence)
360
+ _apply_on_event_error_evidence(report)
326
361
  yield CapabilityResult(
327
362
  status=CapabilityStatus.CANCELLED,
328
363
  error="execution cancelled",
@@ -339,6 +374,7 @@ class AgentAdapter:
339
374
  completion_reason="engine_exception",
340
375
  meta={"engine_exception": type(exc).__name__, **prompt_plan.evidence},
341
376
  )
377
+ _apply_on_event_error_evidence(report)
342
378
  yield CapabilityResult(
343
379
  status=CapabilityStatus.FAILED,
344
380
  error=str(exc),
@@ -350,6 +386,7 @@ class AgentAdapter:
350
386
 
351
387
  report = NodeReportBuilder().build(events=events)
352
388
  self._apply_prompt_evidence(report=report, evidence=prompt_plan.evidence)
389
+ _apply_on_event_error_evidence(report)
353
390
  if issues and getattr(self._services.config, "preflight_mode", "error") == "warn":
354
391
  report.meta["preflight_mode"] = "warn"
355
392
  report.meta["preflight_issues"] = [self._services.redact_issue(i) for i in issues]
@@ -389,13 +426,20 @@ class AgentAdapter:
389
426
  artifacts=list(report.artifacts),
390
427
  )
391
428
 
392
- def _resolve_prompt_render_plan(self, *, spec: AgentSpec, input: Dict[str, Any]) -> _PromptRenderPlan:
429
+ def _resolve_prompt_render_plan(
430
+ self,
431
+ *,
432
+ spec: AgentSpec,
433
+ input: Dict[str, Any],
434
+ prompt_control: Optional[Dict[str, Any]] = None,
435
+ ) -> _PromptRenderPlan:
393
436
  """
394
437
  解析 AgentSpec + run-level `_runtime_prompt`,生成 prompt 渲染计划。
395
438
 
396
439
  参数:
397
440
  - spec:Agent 声明
398
441
  - input:run 输入,其中 `_runtime_prompt` 为保留控制面
442
+ - prompt_control:显式控制面;若提供则优先于 input 内兼容保留键
399
443
 
400
444
  返回:
401
445
  - `_PromptRenderPlan`
@@ -404,13 +448,14 @@ class AgentAdapter:
404
448
  - `_InvalidPromptMessages`:控制面非法,调用方应 fail-fast。
405
449
  """
406
450
 
407
- envelope_raw = input.get(_RUNTIME_PROMPT_KEY)
451
+ envelope_raw = prompt_control if prompt_control is not None else input.get(_RUNTIME_PROMPT_KEY)
452
+ envelope_name = "prompt_control" if prompt_control is not None else "_runtime_prompt"
408
453
  if envelope_raw is None:
409
454
  envelope: Dict[str, Any] = {}
410
455
  elif isinstance(envelope_raw, dict):
411
456
  envelope = dict(envelope_raw)
412
457
  else:
413
- raise _InvalidPromptMessages("_runtime_prompt must be a dict")
458
+ raise _InvalidPromptMessages(f"{envelope_name} must be a dict")
414
459
 
415
460
  raw_mode = envelope.get("mode") if "mode" in envelope else getattr(spec, "prompt_render_mode", "structured_task")
416
461
  if raw_mode is None:
@@ -570,10 +615,9 @@ class AgentAdapter:
570
615
  if business_input:
571
616
  lines: List[str] = []
572
617
  for k, v in business_input.items():
573
- if isinstance(v, str):
574
- lines.append(f"- {k}: {v}")
575
- else:
576
- lines.append(f"- {k}: {json.dumps(v, ensure_ascii=False)}")
618
+ key_text = json.dumps(str(k), ensure_ascii=False)
619
+ value_text = json.dumps(v, ensure_ascii=False)
620
+ lines.append(f"- {key_text}: {value_text}")
577
621
  parts.append(f"{_SECTION_INPUT}\n" + "\n".join(lines))
578
622
 
579
623
  if spec.output_schema and spec.output_schema.fields:
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
  import asyncio
5
5
  import uuid
6
6
  from contextlib import suppress
7
- from dataclasses import dataclass
7
+ from dataclasses import dataclass, replace
8
8
  from types import MappingProxyType
9
9
  from typing import Any, AsyncIterator, Dict, List, Optional, cast
10
10
 
@@ -598,8 +598,7 @@ class TriggerFlowWorkflowEngine:
598
598
  completion_reason="loop_iteration_failed",
599
599
  meta={"step_id": step.id, "capability_id": step.capability.id},
600
600
  )
601
- result.report = report
602
- result.node_report = report
601
+ result = replace(result, report=report, node_report=report)
603
602
 
604
603
  context.step_outputs[step.id] = result.output
605
604
  context.step_results[step.id] = _to_step_result_dict(result)
@@ -2,6 +2,8 @@ from __future__ import annotations
2
2
 
3
3
  """HITL / wait-resume / approval 的宿主协议收敛层。"""
4
4
 
5
+ import html
6
+ import re
5
7
  from dataclasses import dataclass, field
6
8
  from enum import Enum
7
9
  from typing import Any, Optional
@@ -397,4 +399,10 @@ def _build_message_preview(value: Any) -> str | None:
397
399
  normalized = " ".join(value.split())
398
400
  if not normalized:
399
401
  return None
400
- return normalized[:120]
402
+ secret_pattern = re.compile(
403
+ r"(?i)\b(password|passwd|api_key|apikey|token|access_token|secret)\s*=\s*"
404
+ r"(\"[^\"]*\"|'[^']*'|[^\s&]+)"
405
+ )
406
+ redacted = secret_pattern.sub(lambda m: f"{m.group(1)}=[REDACTED]", normalized)
407
+ redacted = re.sub(r"(?i)\bBearer\s+[A-Za-z0-9._~+/=-]+", "Bearer [REDACTED]", redacted)
408
+ return html.escape(redacted, quote=True)[:120]
@@ -10,6 +10,7 @@ from __future__ import annotations
10
10
  """
11
11
 
12
12
  import asyncio
13
+ import copy
13
14
  import time
14
15
  import uuid
15
16
  from dataclasses import replace
@@ -344,6 +345,7 @@ class Runtime(RuntimeUIEventsMixin):
344
345
  *,
345
346
  input: Optional[Dict[str, Any]] = None,
346
347
  context: Optional[ExecutionContext] = None,
348
+ prompt_control: Optional[Dict[str, Any]] = None,
347
349
  ) -> CapabilityResult:
348
350
  """
349
351
  非流式执行(等待完成后返回)。
@@ -352,10 +354,14 @@ class Runtime(RuntimeUIEventsMixin):
352
354
  - capability_id:能力 ID
353
355
  - input:输入参数 dict
354
356
  - context:可选执行上下文(宿主控制;若不传则由 Runtime 创建)
357
+ - prompt_control:可选 prompt 控制面;优先于兼容入口 `input["_runtime_prompt"]`
355
358
  """
356
359
 
357
360
  result: Optional[CapabilityResult] = None
358
- async for item in self.run_stream(capability_id, input=input, context=context):
361
+ stream_kwargs: Dict[str, Any] = {"input": input, "context": context}
362
+ if prompt_control is not None:
363
+ stream_kwargs["prompt_control"] = prompt_control
364
+ async for item in self.run_stream(capability_id, **stream_kwargs):
359
365
  if isinstance(item, CapabilityResult):
360
366
  result = item
361
367
  if result is None:
@@ -373,6 +379,7 @@ class Runtime(RuntimeUIEventsMixin):
373
379
  *,
374
380
  input: Optional[Dict[str, Any]] = None,
375
381
  context: Optional[ExecutionContext] = None,
382
+ prompt_control: Optional[Dict[str, Any]] = None,
376
383
  ) -> CapabilityResult:
377
384
  """
378
385
  强结构输出入口:成功时返回 `dict` 输出。
@@ -380,11 +387,12 @@ class Runtime(RuntimeUIEventsMixin):
380
387
  约束:
381
388
  - 仅支持带 `output_schema` 的 Agent capability;
382
389
  - 不改变 `run()` 的既有语义,而是在其之上做强结构收口。
390
+ - `prompt_control` 透传给底层 `run()`,用于显式控制 prompt rendering。
383
391
  """
384
392
 
385
393
  spec = self._registry.get(capability_id)
386
394
  if spec is None:
387
- return await self.run(capability_id, input=input, context=context)
395
+ return await self.run(capability_id, input=input, context=context, prompt_control=prompt_control)
388
396
  if not isinstance(spec, AgentSpec):
389
397
  run_id = context.run_id if context is not None else uuid.uuid4().hex
390
398
  return self._build_fail_closed_result(
@@ -408,7 +416,7 @@ class Runtime(RuntimeUIEventsMixin):
408
416
  completion_reason="structured_output_schema_missing",
409
417
  )
410
418
 
411
- result = await self.run(capability_id, input=input, context=context)
419
+ result = await self.run(capability_id, input=input, context=context, prompt_control=prompt_control)
412
420
  if result.status != CapabilityStatus.SUCCESS:
413
421
  return result
414
422
 
@@ -426,6 +434,7 @@ class Runtime(RuntimeUIEventsMixin):
426
434
  *,
427
435
  input: Optional[Dict[str, Any]] = None,
428
436
  context: Optional[ExecutionContext] = None,
437
+ prompt_control: Optional[Dict[str, Any]] = None,
429
438
  ) -> AsyncIterator[StructuredStreamEvent]:
430
439
  """
431
440
  结构化输出流式消费入口。
@@ -433,6 +442,7 @@ class Runtime(RuntimeUIEventsMixin):
433
442
  说明:
434
443
  - 面向业务代码,不透传 mixed stream / UI events 的全部细节;
435
444
  - 仅在观察到 `llm_response_delta(text)` 时产出中途快照与字段更新。
445
+ - `prompt_control` 透传给底层 `run_stream()`,优先于 `input["_runtime_prompt"]`。
436
446
  """
437
447
 
438
448
  spec = self._registry.get(capability_id)
@@ -474,7 +484,10 @@ class Runtime(RuntimeUIEventsMixin):
474
484
  previous_snapshot: Optional[Dict[str, Any]] = None
475
485
  terminal: Optional[CapabilityResult] = None
476
486
 
477
- async for item in self.run_stream(capability_id, input=input, context=ctx):
487
+ stream_kwargs: Dict[str, Any] = {"input": input, "context": ctx}
488
+ if prompt_control is not None:
489
+ stream_kwargs["prompt_control"] = prompt_control
490
+ async for item in self.run_stream(capability_id, **stream_kwargs):
478
491
  if isinstance(item, CapabilityResult):
479
492
  terminal = item
480
493
  continue
@@ -564,6 +577,7 @@ class Runtime(RuntimeUIEventsMixin):
564
577
  *,
565
578
  input: Optional[Dict[str, Any]] = None,
566
579
  context: Optional[ExecutionContext] = None,
580
+ prompt_control: Optional[Dict[str, Any]] = None,
567
581
  ) -> AsyncIterator[Union[AgentEvent, WorkflowStreamEvent, CapabilityResult]]:
568
582
  """
569
583
  流式执行(执行层混合流):过程中可能产出事件,最后产出终态 CapabilityResult。
@@ -610,15 +624,30 @@ class Runtime(RuntimeUIEventsMixin):
610
624
 
611
625
  started = time.monotonic()
612
626
  if _get_base(spec).kind == CapabilityKind.AGENT:
613
- async for x in self._execute_agent_stream(spec=spec, input=input or {}, context=ctx):
627
+ async for x in self._execute_agent_stream(
628
+ spec=spec,
629
+ input=input or {},
630
+ context=ctx,
631
+ prompt_control=prompt_control,
632
+ ):
614
633
  if isinstance(x, CapabilityResult):
615
- x.duration_ms = (time.monotonic() - started) * 1000
634
+ x = replace(
635
+ x,
636
+ duration_ms=(time.monotonic() - started) * 1000,
637
+ artifacts=list(x.artifacts or []),
638
+ metadata=copy.deepcopy(x.metadata or {}),
639
+ )
616
640
  yield x
617
641
  return
618
642
 
619
643
  async for x in self._execute_workflow_stream(spec=spec, input=input or {}, context=ctx):
620
644
  if isinstance(x, CapabilityResult):
621
- x.duration_ms = (time.monotonic() - started) * 1000
645
+ x = replace(
646
+ x,
647
+ duration_ms=(time.monotonic() - started) * 1000,
648
+ artifacts=list(x.artifacts or []),
649
+ metadata=copy.deepcopy(x.metadata or {}),
650
+ )
622
651
  yield x
623
652
  return
624
653
 
@@ -826,7 +855,12 @@ class Runtime(RuntimeUIEventsMixin):
826
855
  yield item
827
856
 
828
857
  async def _execute_agent_stream(
829
- self, *, spec: AnySpec, input: Dict[str, Any], context: ExecutionContext
858
+ self,
859
+ *,
860
+ spec: AnySpec,
861
+ input: Dict[str, Any],
862
+ context: ExecutionContext,
863
+ prompt_control: Optional[Dict[str, Any]] = None,
830
864
  ) -> AsyncIterator[Union[AgentEvent, CapabilityResult]]:
831
865
  """
832
866
  执行 AgentSpec(流式)。
@@ -849,7 +883,10 @@ class Runtime(RuntimeUIEventsMixin):
849
883
  )
850
884
  return
851
885
 
852
- async for item in self._agent_adapter.execute_stream(spec=spec, input=input, context=context):
886
+ execute_kwargs: Dict[str, Any] = {"spec": spec, "input": input, "context": context}
887
+ if prompt_control is not None:
888
+ execute_kwargs["prompt_control"] = prompt_control
889
+ async for item in self._agent_adapter.execute_stream(**execute_kwargs):
853
890
  yield item
854
891
 
855
892
  def build_fail_closed_report(
@@ -19,6 +19,7 @@ from skills_runtime.skills.manager import SkillsManager
19
19
  from .config import CustomTool, RuntimeConfig, RuntimeMode, normalize_workspace_root
20
20
  from .logging_utils import log_suppressed_exception
21
21
  from .protocol.chat_backend import ChatBackendProtocol
22
+ from .utils.usage import extract_usage_metrics
22
23
 
23
24
 
24
25
  @dataclass(frozen=True)
@@ -668,7 +669,7 @@ class _UsageTapBackend:
668
669
 
669
670
  class _AgentUsageEventBridge:
670
671
  """
671
- Agent 薄代理:在底层未主动发出 `llm_usage` 时,补发 bridge 收集到的 usage AgentEvent。
672
+ Agent 薄代理:补齐 bridge usage metadata,或在底层未主动发出 `llm_usage` 时补发 usage 事件。
672
673
  """
673
674
 
674
675
  def __init__(self, *, agent: Any, usage_bridge_backend: _UsageTapBackend) -> None:
@@ -683,16 +684,32 @@ class _AgentUsageEventBridge:
683
684
  initial_history: Optional[List[Dict[str, Any]]] = None,
684
685
  ) -> AsyncIterator[AgentEvent]:
685
686
  """
686
- 转发 SDK Agent 事件流;若未见上游 `llm_usage`,在流结束后补发 bridge usage 事件。
687
+ 转发 SDK Agent 事件流,并按 token usage bridge 规格处理 supplemental usage
688
+
689
+ 参数:
690
+ - task:传给上游 Agent 的任务文本
691
+ - run_id:可选 run 标识
692
+ - initial_history:可选初始历史
693
+
694
+ 返回:
695
+ - AgentEvent 异步流;上游 `llm_usage` 存在时只补齐缺失 metadata,不重复补 token
687
696
  """
688
697
 
689
698
  saw_llm_usage = False
699
+ pending_supplemental_usage: List[Dict[str, Any]] = []
690
700
  last_run_id = run_id or ""
691
701
  last_turn_id: Optional[str] = None
692
702
 
693
703
  async for ev in self._agent.run_stream_async(task, run_id=run_id, initial_history=initial_history):
694
704
  if ev.type == "llm_usage":
695
705
  saw_llm_usage = True
706
+ pending_supplemental_usage.extend(self._usage_bridge_backend.drain_usage_payloads())
707
+ if pending_supplemental_usage:
708
+ ev = _merge_supplemental_usage_metadata_event(
709
+ ev=ev,
710
+ supplemental_payloads=pending_supplemental_usage,
711
+ )
712
+ pending_supplemental_usage.clear()
696
713
  if isinstance(ev.run_id, str) and ev.run_id:
697
714
  last_run_id = ev.run_id
698
715
  if isinstance(ev.turn_id, str) and ev.turn_id:
@@ -700,10 +717,12 @@ class _AgentUsageEventBridge:
700
717
  yield ev
701
718
 
702
719
  if saw_llm_usage:
720
+ # 上游 usage 已是 token 权威来源;清空未配对 payload,避免作为新 usage 事件造成双计。
703
721
  self._usage_bridge_backend.drain_usage_payloads()
704
722
  return
705
723
 
706
- for payload in self._usage_bridge_backend.drain_usage_payloads():
724
+ pending_supplemental_usage.extend(self._usage_bridge_backend.drain_usage_payloads())
725
+ for payload in pending_supplemental_usage:
707
726
  yield AgentEvent(
708
727
  type="llm_usage",
709
728
  timestamp=_now_rfc3339(),
@@ -719,6 +738,71 @@ def _now_rfc3339() -> str:
719
738
  return datetime.now(timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
720
739
 
721
740
 
741
+ _USAGE_PROVIDER_PLACEHOLDERS = {"openai", "openai-compatible"}
742
+
743
+
744
+ def _merge_supplemental_usage_metadata_event(*, ev: AgentEvent, supplemental_payloads: List[Dict[str, Any]]) -> AgentEvent:
745
+ """
746
+ 把 sink payload 作为 supplemental metadata patch 合并到上游 `llm_usage` 事件。
747
+
748
+ 参数:
749
+ - ev:上游 SDK / agent loop 已发出的 `llm_usage` AgentEvent
750
+ - supplemental_payloads:`_caprt_usage_sink` 收集到的 provider/gateway usage payload 列表
751
+
752
+ 返回:
753
+ - 新 AgentEvent;仅在上游 metadata 缺失时补 `model/request_id/provider`,不写入 token 字段;
754
+ `provider` 可在上游为 OpenAI-compatible 占位值时被 effective provider 受控覆盖。
755
+ """
756
+
757
+ upstream_payload = dict(ev.payload) if isinstance(ev.payload, dict) else {}
758
+ merged_payload = dict(upstream_payload)
759
+
760
+ for supplemental_payload in supplemental_payloads:
761
+ supplemental_summary = extract_usage_metrics(supplemental_payload)
762
+ for field in ("model", "request_id"):
763
+ current_value = extract_usage_metrics(merged_payload).get(field)
764
+ if isinstance(current_value, str) and current_value.strip():
765
+ continue
766
+ supplemental_value = supplemental_summary.get(field)
767
+ if isinstance(supplemental_value, str) and supplemental_value.strip():
768
+ merged_payload[field] = supplemental_value.strip()
769
+ current_provider = extract_usage_metrics(merged_payload).get("provider")
770
+ supplemental_provider = supplemental_summary.get("provider")
771
+ if not (isinstance(supplemental_provider, str) and supplemental_provider.strip()):
772
+ continue
773
+ supplemental_provider = supplemental_provider.strip()
774
+ supplemental_provider_is_placeholder = supplemental_provider in _USAGE_PROVIDER_PLACEHOLDERS
775
+ if not (isinstance(current_provider, str) and current_provider.strip()):
776
+ merged_payload["provider"] = supplemental_provider
777
+ continue
778
+ current_provider = current_provider.strip()
779
+ if (
780
+ current_provider in _USAGE_PROVIDER_PLACEHOLDERS
781
+ and not supplemental_provider_is_placeholder
782
+ and current_provider != supplemental_provider
783
+ ):
784
+ merged_payload.setdefault("provider_upstream", current_provider)
785
+ merged_payload["provider"] = supplemental_provider
786
+
787
+ if merged_payload == upstream_payload:
788
+ return ev
789
+ try:
790
+ return ev.model_copy(update={"payload": merged_payload})
791
+ except Exception as exc: # pragma: no cover - 当前 AgentEvent 为 Pydantic v2,保留兼容兜底。
792
+ log_suppressed_exception(
793
+ context="supplemental_usage_event_model_copy",
794
+ exc=exc,
795
+ )
796
+ return AgentEvent(
797
+ type=ev.type,
798
+ timestamp=ev.timestamp,
799
+ run_id=ev.run_id,
800
+ turn_id=ev.turn_id,
801
+ step_id=ev.step_id,
802
+ payload=merged_payload,
803
+ )
804
+
805
+
722
806
  def _merge_usage_sink(*, extra: Dict[str, Any], sink: Any) -> Dict[str, Any]:
723
807
  """
724
808
  合并 `_caprt_usage_sink` 回调,保留已有 sink 并保证两者都被调用。
@@ -2,9 +2,10 @@ from __future__ import annotations
2
2
 
3
3
  """结构化输出桥接:`output_schema` 校验、摘要留痕与结果收敛。"""
4
4
 
5
+ import copy
5
6
  import hashlib
6
7
  import json
7
- from dataclasses import dataclass
8
+ from dataclasses import dataclass, replace
8
9
  from typing import Any, Dict, List, Optional
9
10
 
10
11
  from .config import OutputValidationMode
@@ -183,26 +184,51 @@ def finalize_structured_result(
183
184
  validation: StructuredOutputValidation,
184
185
  fail_on_error: bool,
185
186
  ) -> CapabilityResult:
186
- """把普通 CapabilityResult 收敛为结构化结果。"""
187
+ """把普通 CapabilityResult 收敛为结构化结果,并返回新的 terminal 对象。"""
187
188
 
188
- result.metadata["raw_output"] = validation.raw_output
189
- result.metadata["structured_output"] = dict(validation.summary)
189
+ metadata = copy.deepcopy(result.metadata or {})
190
+ metadata["raw_output"] = validation.raw_output
191
+ metadata["structured_output"] = dict(validation.summary)
190
192
 
191
- if result.node_report is not None:
193
+ node_report = copy.deepcopy(result.node_report) if result.node_report is not None else None
194
+ if node_report is not None:
192
195
  apply_structured_output_summary(
193
- report=result.node_report,
196
+ report=node_report,
194
197
  validation=validation,
195
198
  fail_on_error=fail_on_error,
196
199
  )
197
200
 
201
+ if result.report is result.node_report:
202
+ report = node_report
203
+ else:
204
+ report = copy.deepcopy(result.report) if result.report is not None else None
205
+ if isinstance(report, NodeReport):
206
+ apply_structured_output_summary(
207
+ report=report,
208
+ validation=validation,
209
+ fail_on_error=fail_on_error,
210
+ )
211
+
198
212
  if not validation.ok:
199
- result.status = CapabilityStatus.FAILED
200
- result.output = None
201
- result.error = "Structured output contract violated"
202
- result.error_code = "STRUCTURED_OUTPUT_INVALID"
203
- return result
204
-
205
- result.output = dict(validation.normalized_output or {})
206
- result.error = None
207
- result.error_code = None
208
- return result
213
+ return replace(
214
+ result,
215
+ status=CapabilityStatus.FAILED,
216
+ output=None,
217
+ error="Structured output contract violated",
218
+ error_code="STRUCTURED_OUTPUT_INVALID",
219
+ report=report,
220
+ node_report=node_report,
221
+ artifacts=list(result.artifacts or []),
222
+ metadata=metadata,
223
+ )
224
+
225
+ return replace(
226
+ result,
227
+ output=dict(validation.normalized_output or {}),
228
+ error=None,
229
+ error_code=None,
230
+ report=report,
231
+ node_report=node_report,
232
+ artifacts=list(result.artifacts or []),
233
+ metadata=metadata,
234
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: capability-runtime
3
- Version: 0.1.2
3
+ Version: 0.1.3.post1
4
4
  Summary: Bridge/glue layer that composes Agently (LLM/TriggerFlow) with skills-runtime-sdk (skills/tools/WAL/events).
5
5
  License-Expression: MIT
6
6
  Requires-Python: >=3.10
@@ -111,6 +111,7 @@ tests/test_runtime_hitl_host_protocol.py
111
111
  tests/test_runtime_hooks_and_schema_gate.py
112
112
  tests/test_runtime_initial_history_and_meta.py
113
113
  tests/test_runtime_manifest.py
114
+ tests/test_runtime_result_prompt_hardening.py
114
115
  tests/test_runtime_run_stream_semantics_v1.py
115
116
  tests/test_runtime_service_facade_rpc_mapping.py
116
117
  tests/test_runtime_service_session_bridge.py