capability-runtime 0.1.3__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 (140) hide show
  1. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/PKG-INFO +1 -1
  2. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/pyproject.toml +1 -1
  3. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/__init__.py +1 -1
  4. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/sdk_lifecycle.py +23 -2
  5. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime.egg-info/PKG-INFO +1 -1
  6. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_agently_backend.py +152 -1
  7. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_release_tag_version_guardrail.py +2 -2
  8. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/README.md +0 -0
  9. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/setup.cfg +0 -0
  10. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/adapters/__init__.py +0 -0
  11. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/adapters/agent_adapter.py +0 -0
  12. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/adapters/agently_backend.py +0 -0
  13. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/adapters/triggerflow_workflow_engine.py +0 -0
  14. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/adapters/workflow_engine.py +0 -0
  15. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/config.py +0 -0
  16. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/errors.py +0 -0
  17. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/guards.py +0 -0
  18. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/host_protocol.py +0 -0
  19. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/host_toolkit/__init__.py +0 -0
  20. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/host_toolkit/approvals_profiles.py +0 -0
  21. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/host_toolkit/evidence_hooks.py +0 -0
  22. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/host_toolkit/history.py +0 -0
  23. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/host_toolkit/invoke_capability.py +0 -0
  24. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/host_toolkit/resume.py +0 -0
  25. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/host_toolkit/system_prompt.py +0 -0
  26. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/host_toolkit/turn_delta.py +0 -0
  27. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/logging_utils.py +0 -0
  28. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/manifest.py +0 -0
  29. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/output_validator.py +0 -0
  30. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/protocol/__init__.py +0 -0
  31. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/protocol/agent.py +0 -0
  32. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/protocol/capability.py +0 -0
  33. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/protocol/chat_backend.py +0 -0
  34. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/protocol/context.py +0 -0
  35. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/protocol/workflow.py +0 -0
  36. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/registry.py +0 -0
  37. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/reporting/__init__.py +0 -0
  38. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/reporting/node_report.py +0 -0
  39. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/runtime.py +0 -0
  40. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/runtime_ui_events_mixin.py +0 -0
  41. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/service_facade.py +0 -0
  42. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/services.py +0 -0
  43. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/structured_output.py +0 -0
  44. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/structured_stream.py +0 -0
  45. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/types.py +0 -0
  46. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/ui_events/__init__.py +0 -0
  47. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/ui_events/projector.py +0 -0
  48. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/ui_events/session.py +0 -0
  49. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/ui_events/store.py +0 -0
  50. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/ui_events/transport.py +0 -0
  51. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/ui_events/v1.py +0 -0
  52. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/upstream_compat.py +0 -0
  53. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/utils/__init__.py +0 -0
  54. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/utils/usage.py +0 -0
  55. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime/workflow_runtime.py +0 -0
  56. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime.egg-info/SOURCES.txt +0 -0
  57. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime.egg-info/dependency_links.txt +0 -0
  58. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime.egg-info/requires.txt +0 -0
  59. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/src/capability_runtime.egg-info/top_level.txt +0 -0
  60. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_agently_backend_replay.py +0 -0
  61. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_backend_mode.py +0 -0
  62. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_bilingual_docs_surface.py +0 -0
  63. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_bridge_artifacts_passthrough.py +0 -0
  64. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_bridge_register_tool_public_api.py +0 -0
  65. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_coding_agent_examples_atomic.py +0 -0
  66. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_coding_agent_examples_recipes.py +0 -0
  67. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_config_glue.py +0 -0
  68. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_dependency_pins.py +0 -0
  69. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_docs_pinned_dependency_versions.py +0 -0
  70. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_docs_scheme2_no_skilladapter_residue.py +0 -0
  71. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_error_observability.py +0 -0
  72. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_examples_alignment_fixes_l1.py +0 -0
  73. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_examples_no_agent_sdk_imports.py +0 -0
  74. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_examples_real_evidence_strict_integration.py +0 -0
  75. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_examples_real_integration.py +0 -0
  76. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_examples_smoke.py +0 -0
  77. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_examples_ui_events_showcase_offline.py +0 -0
  78. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_examples_ui_events_showcase_real_fallback.py +0 -0
  79. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_examples_ui_events_showcase_real_integration.py +0 -0
  80. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_examples_ui_events_showcase_ui_contract.py +0 -0
  81. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_examples_workflow_skills_first_smoke.py +0 -0
  82. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_guards.py +0 -0
  83. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_host_toolkit_approvals_profiles.py +0 -0
  84. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_host_toolkit_history_assembler.py +0 -0
  85. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_host_toolkit_invoke_capability.py +0 -0
  86. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_host_toolkit_invoke_capability_shared_runtime.py +0 -0
  87. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_host_toolkit_resume_helper.py +0 -0
  88. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_host_toolkit_system_prompt_evidence.py +0 -0
  89. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_host_toolkit_turn_delta.py +0 -0
  90. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_integration_agently_requester_smoke.py +0 -0
  91. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_integration_approval_event_shape.py +0 -0
  92. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_integration_sources_redis_pgsql_smoke.py +0 -0
  93. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_loop.py +0 -0
  94. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_node_report_builder.py +0 -0
  95. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_node_report_contract_v1.py +0 -0
  96. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_node_report_engine_identity_contract.py +0 -0
  97. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_offline_backend_injection_evidence.py +0 -0
  98. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_per_capability_llm_config_model_routing.py +0 -0
  99. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_preflight_gate.py +0 -0
  100. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_project_identity_naming_matrix.py +0 -0
  101. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_public_api_exports.py +0 -0
  102. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_public_repo_hygiene.py +0 -0
  103. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_qa_agent.py +0 -0
  104. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_registry.py +0 -0
  105. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_replay_tool_calls_alignment.py +0 -0
  106. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_repo_hygiene_no_tracked_env_or_pyc.py +0 -0
  107. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_repo_no_deep_imports_in_user_facing_docs.py +0 -0
  108. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_review_followups_module_contracts.py +0 -0
  109. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_runtime_bridge_fake_backend.py +0 -0
  110. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_runtime_concurrency.py +0 -0
  111. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_runtime_engine.py +0 -0
  112. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_runtime_hitl_host_protocol.py +0 -0
  113. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_runtime_hooks_and_schema_gate.py +0 -0
  114. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_runtime_initial_history_and_meta.py +0 -0
  115. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_runtime_manifest.py +0 -0
  116. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_runtime_result_prompt_hardening.py +0 -0
  117. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_runtime_run_stream_semantics_v1.py +0 -0
  118. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_runtime_service_facade_rpc_mapping.py +0 -0
  119. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_runtime_service_session_bridge.py +0 -0
  120. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_runtime_status_mapping.py +0 -0
  121. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_runtime_structured_output_bridge.py +0 -0
  122. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_runtime_structured_stream.py +0 -0
  123. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_sandbox_permissions_passthrough_contract.py +0 -0
  124. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_services_call_callback.py +0 -0
  125. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_services_map_node_status.py +0 -0
  126. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_skills_conformance_smoke.py +0 -0
  127. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_upstream_adapter_tool_registration.py +0 -0
  128. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_upstream_chat_backend_protocol_contract.py +0 -0
  129. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_upstream_chat_sse_usage_contract.py +0 -0
  130. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_upstream_compat_spaces_schema.py +0 -0
  131. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_upstream_prompt_profile_contract.py +0 -0
  132. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_upstream_runtime_client_server_contract.py +0 -0
  133. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_upstream_sandbox_profile_precedence_contract.py +0 -0
  134. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_upstream_skills_bundles_contract.py +0 -0
  135. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_upstream_tool_descriptor_compat.py +0 -0
  136. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_upstream_verification.py +0 -0
  137. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_versioning_strategy_guard.py +0 -0
  138. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_wal_backend_injection_contract.py +0 -0
  139. {capability_runtime-0.1.3 → capability_runtime-0.1.3.post1}/tests/test_wal_locator_resolution_contract.py +0 -0
  140. {capability_runtime-0.1.3 → 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.3
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.3"
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.3"
4
+ __version__ = "0.1.3.post1"
5
5
 
6
6
  # === 统一入口 ===
7
7
  from .config import CustomTool, RuntimeConfig
@@ -738,6 +738,9 @@ def _now_rfc3339() -> str:
738
738
  return datetime.now(timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
739
739
 
740
740
 
741
+ _USAGE_PROVIDER_PLACEHOLDERS = {"openai", "openai-compatible"}
742
+
743
+
741
744
  def _merge_supplemental_usage_metadata_event(*, ev: AgentEvent, supplemental_payloads: List[Dict[str, Any]]) -> AgentEvent:
742
745
  """
743
746
  把 sink payload 作为 supplemental metadata patch 合并到上游 `llm_usage` 事件。
@@ -747,7 +750,8 @@ def _merge_supplemental_usage_metadata_event(*, ev: AgentEvent, supplemental_pay
747
750
  - supplemental_payloads:`_caprt_usage_sink` 收集到的 provider/gateway usage payload 列表
748
751
 
749
752
  返回:
750
- - 新 AgentEvent;仅在上游 metadata 缺失时补 `model/request_id/provider`,不写入 token 字段
753
+ - 新 AgentEvent;仅在上游 metadata 缺失时补 `model/request_id/provider`,不写入 token 字段;
754
+ `provider` 可在上游为 OpenAI-compatible 占位值时被 effective provider 受控覆盖。
751
755
  """
752
756
 
753
757
  upstream_payload = dict(ev.payload) if isinstance(ev.payload, dict) else {}
@@ -755,13 +759,30 @@ def _merge_supplemental_usage_metadata_event(*, ev: AgentEvent, supplemental_pay
755
759
 
756
760
  for supplemental_payload in supplemental_payloads:
757
761
  supplemental_summary = extract_usage_metrics(supplemental_payload)
758
- for field in ("model", "request_id", "provider"):
762
+ for field in ("model", "request_id"):
759
763
  current_value = extract_usage_metrics(merged_payload).get(field)
760
764
  if isinstance(current_value, str) and current_value.strip():
761
765
  continue
762
766
  supplemental_value = supplemental_summary.get(field)
763
767
  if isinstance(supplemental_value, str) and supplemental_value.strip():
764
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
765
786
 
766
787
  if merged_payload == upstream_payload:
767
788
  return ev
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: capability-runtime
3
- Version: 0.1.3
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
@@ -118,6 +118,13 @@ def _backend_from_items(items):
118
118
  async def _run_usage_backend(backend, tmp_path):
119
119
  """用 sdk_native Runtime 运行测试 backend,并返回 CapabilityResult。"""
120
120
 
121
+ rt = _make_usage_runtime(backend, tmp_path)
122
+ return await rt.run("agent.upstream_usage_with_sink", input={"prompt": "x"})
123
+
124
+
125
+ def _make_usage_runtime(backend, tmp_path):
126
+ """构造注册了 usage 测试 Agent 的 sdk_native Runtime。"""
127
+
121
128
  rt = Runtime(
122
129
  RuntimeConfig(
123
130
  mode="sdk_native",
@@ -137,7 +144,7 @@ async def _run_usage_backend(backend, tmp_path):
137
144
  ),
138
145
  )
139
146
  )
140
- return await rt.run("agent.upstream_usage_with_sink", input={"prompt": "x"})
147
+ return rt
141
148
 
142
149
 
143
150
  @pytest.mark.asyncio
@@ -384,6 +391,150 @@ def test_supplemental_usage_metadata_helper_does_not_overwrite_existing_model()
384
391
  }
385
392
 
386
393
 
394
+ @pytest.mark.parametrize("placeholder_provider", ["openai", "openai-compatible"])
395
+ def test_supplemental_usage_metadata_helper_overwrites_placeholder_provider(placeholder_provider: str) -> None:
396
+ ev = AgentEvent(
397
+ type="llm_usage",
398
+ timestamp="2026-05-05T00:00:00Z",
399
+ run_id="run_1",
400
+ payload={
401
+ "model": "upstream-model",
402
+ "input_tokens": 5,
403
+ "output_tokens": 6,
404
+ "total_tokens": 11,
405
+ "request_id": "req_upstream",
406
+ "provider": placeholder_provider,
407
+ },
408
+ )
409
+
410
+ merged = _merge_supplemental_usage_metadata_event(
411
+ ev=ev,
412
+ supplemental_payloads=[
413
+ {
414
+ "model": "sink-model",
415
+ "input_tokens": 99,
416
+ "output_tokens": 99,
417
+ "total_tokens": 198,
418
+ "request_id": "req_sink",
419
+ "provider": "gateway-provider",
420
+ }
421
+ ],
422
+ )
423
+
424
+ assert merged.payload == {
425
+ "model": "upstream-model",
426
+ "input_tokens": 5,
427
+ "output_tokens": 6,
428
+ "total_tokens": 11,
429
+ "request_id": "req_upstream",
430
+ "provider": "gateway-provider",
431
+ "provider_upstream": placeholder_provider,
432
+ }
433
+
434
+
435
+ @pytest.mark.parametrize("sink_provider", ["", " ", "openai", "openai-compatible"])
436
+ def test_supplemental_usage_metadata_helper_keeps_placeholder_when_sink_is_not_effective(
437
+ sink_provider: str,
438
+ ) -> None:
439
+ ev = AgentEvent(
440
+ type="llm_usage",
441
+ timestamp="2026-05-05T00:00:00Z",
442
+ run_id="run_1",
443
+ payload={
444
+ "input_tokens": 5,
445
+ "output_tokens": 6,
446
+ "total_tokens": 11,
447
+ "provider": "openai",
448
+ },
449
+ )
450
+
451
+ merged = _merge_supplemental_usage_metadata_event(
452
+ ev=ev,
453
+ supplemental_payloads=[{"provider": sink_provider}],
454
+ )
455
+
456
+ assert merged.payload == {
457
+ "input_tokens": 5,
458
+ "output_tokens": 6,
459
+ "total_tokens": 11,
460
+ "provider": "openai",
461
+ }
462
+
463
+
464
+ @pytest.mark.parametrize("placeholder_provider", ["openai", "openai-compatible"])
465
+ @pytest.mark.asyncio
466
+ async def test_upstream_placeholder_provider_is_replaced_by_sink_effective_provider(
467
+ tmp_path,
468
+ placeholder_provider: str,
469
+ ):
470
+ backend = _UpstreamUsageWithSinkBackend(
471
+ sink_payload={
472
+ "input_tokens": 99,
473
+ "output_tokens": 99,
474
+ "total_tokens": 198,
475
+ "request_id": "req_sink_gateway",
476
+ "provider": "gateway-provider",
477
+ },
478
+ completed_usage={"input_tokens": 5, "output_tokens": 6, "total_tokens": 11},
479
+ completed_request_id="req_gateway",
480
+ completed_provider=placeholder_provider,
481
+ )
482
+ rt = _make_usage_runtime(backend, tmp_path)
483
+
484
+ items = [
485
+ item
486
+ async for item in rt.run_stream("agent.upstream_usage_with_sink", input={"prompt": "x"})
487
+ ]
488
+ usage_events = [item for item in items if isinstance(item, AgentEvent) and item.type == "llm_usage"]
489
+ result = items[-1]
490
+
491
+ assert usage_events
492
+ assert usage_events[-1].payload["provider"] == "gateway-provider"
493
+ assert usage_events[-1].payload["provider_upstream"] == placeholder_provider
494
+ assert result.node_report is not None
495
+ assert result.node_report.usage is not None
496
+ assert result.node_report.usage.input_tokens == 5
497
+ assert result.node_report.usage.output_tokens == 6
498
+ assert result.node_report.usage.total_tokens == 11
499
+ assert result.node_report.usage.request_id == "req_gateway"
500
+ assert result.node_report.usage.provider == "gateway-provider"
501
+
502
+
503
+ @pytest.mark.asyncio
504
+ async def test_upstream_placeholder_provider_keeps_placeholder_when_sink_is_placeholder(tmp_path):
505
+ backend = _UpstreamUsageWithSinkBackend(
506
+ sink_payload={
507
+ "input_tokens": 99,
508
+ "output_tokens": 99,
509
+ "total_tokens": 198,
510
+ "request_id": "req_sink_gateway",
511
+ "provider": "openai-compatible",
512
+ },
513
+ completed_usage={"input_tokens": 5, "output_tokens": 6, "total_tokens": 11},
514
+ completed_request_id="req_gateway",
515
+ completed_provider="openai",
516
+ )
517
+ rt = _make_usage_runtime(backend, tmp_path)
518
+
519
+ items = [
520
+ item
521
+ async for item in rt.run_stream("agent.upstream_usage_with_sink", input={"prompt": "x"})
522
+ ]
523
+ usage_events = [item for item in items if isinstance(item, AgentEvent) and item.type == "llm_usage"]
524
+ result = items[-1]
525
+
526
+ assert usage_events
527
+ assert usage_events[-1].payload["provider"] == "openai"
528
+ assert "provider_upstream" not in usage_events[-1].payload
529
+ assert result.node_report is not None
530
+ assert result.node_report.usage is not None
531
+ assert result.node_report.usage.input_tokens == 5
532
+ assert result.node_report.usage.output_tokens == 6
533
+ assert result.node_report.usage.total_tokens == 11
534
+ assert result.node_report.usage.request_id == "req_gateway"
535
+ assert result.node_report.usage.provider == "openai"
536
+
537
+
387
538
  @pytest.mark.asyncio
388
539
  async def test_agently_backend_requests_include_usage_by_default_and_preserves_existing_stream_options():
389
540
  requester = _FakeRequester(
@@ -22,11 +22,11 @@ def _load_release_guard_module():
22
22
  def test_release_guard_accepts_current_tag() -> None:
23
23
  module = _load_release_guard_module()
24
24
  tag_version, pyproject_version, module_version = module.validate_versions(
25
- release_tag="v0.1.3",
25
+ release_tag="v0.1.3.post1",
26
26
  pyproject_path=_REPO_ROOT / "pyproject.toml",
27
27
  init_path=_REPO_ROOT / "src" / "capability_runtime" / "__init__.py",
28
28
  )
29
- assert tag_version == pyproject_version == module_version == "0.1.3"
29
+ assert tag_version == pyproject_version == module_version == "0.1.3.post1"
30
30
 
31
31
 
32
32
  def test_release_guard_rejects_mismatch() -> None: