fix: hide platform sources from binding prompts
This commit is contained in:
+21
-10
@@ -6,7 +6,7 @@ WorkflowOperationContext so this module stays protocol-neutral.
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Sequence
|
from collections.abc import Mapping, Sequence
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from wf_artifacts import (
|
from wf_artifacts import (
|
||||||
@@ -18,6 +18,7 @@ from wf_artifacts import (
|
|||||||
from wf_artifacts import (
|
from wf_artifacts import (
|
||||||
create_workflow_artifact_from_plan as build_workflow_artifact_from_plan,
|
create_workflow_artifact_from_plan as build_workflow_artifact_from_plan,
|
||||||
)
|
)
|
||||||
|
from wf_platform import CapabilitySource
|
||||||
|
|
||||||
from .artifact_refs import artifact_capability_id
|
from .artifact_refs import artifact_capability_id
|
||||||
from .capability_requirements import observed_node_specs
|
from .capability_requirements import observed_node_specs
|
||||||
@@ -189,11 +190,9 @@ class WorkflowArtifactApi:
|
|||||||
"created_from_draft": True,
|
"created_from_draft": True,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
required_sources = sorted(
|
required_sources = _binding_required_sources(
|
||||||
{
|
workflow_artifact.required_capability_map(),
|
||||||
capability.logical_source
|
self.context.specs.capability_sources,
|
||||||
for capability in workflow_artifact.required_capability_map().values()
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
return {
|
return {
|
||||||
"artifact_id": workflow_artifact.id,
|
"artifact_id": workflow_artifact.id,
|
||||||
@@ -304,10 +303,22 @@ class WorkflowArtifactApi:
|
|||||||
|
|
||||||
|
|
||||||
def _suggested_self_bindings(required_sources: Sequence[str]) -> dict[str, str]:
|
def _suggested_self_bindings(required_sources: Sequence[str]) -> dict[str, str]:
|
||||||
"""Suggest local bindings for built-in sources that deploy to themselves."""
|
"""Suggest local bindings for external sources that deploy to themselves."""
|
||||||
return {
|
return {}
|
||||||
source: source for source in required_sources if source in {"wf.std", "wf.mcp"}
|
|
||||||
}
|
|
||||||
|
def _binding_required_sources(
|
||||||
|
required_capabilities: dict[str, RequiredCapability],
|
||||||
|
sources: Mapping[str, CapabilitySource],
|
||||||
|
) -> list[str]:
|
||||||
|
return sorted(
|
||||||
|
{
|
||||||
|
capability.logical_source
|
||||||
|
for capability in required_capabilities.values()
|
||||||
|
if sources.get(capability.logical_source) is None
|
||||||
|
or sources[capability.logical_source].policy.binding_required
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from typing import Any
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from tests.wf_mcp.test_support import echo_tool
|
from tests.wf_mcp.test_support import echo_tool
|
||||||
|
from wf_api import WorkflowApi
|
||||||
from wf_api.artifacts import WorkflowArtifactApi
|
from wf_api.artifacts import WorkflowArtifactApi
|
||||||
from wf_artifacts import (
|
from wf_artifacts import (
|
||||||
FileDraftWorkspaceStore,
|
FileDraftWorkspaceStore,
|
||||||
@@ -312,3 +313,37 @@ async def test_delete_artifact_rejects_referenced_version(tmp_path: Path) -> Non
|
|||||||
assert result["deleted"] is False
|
assert result["deleted"] is False
|
||||||
assert result["blocked_by_deployments"] == ["echo.default"]
|
assert result["blocked_by_deployments"] == ["echo.default"]
|
||||||
assert artifact_store.get_artifact("echo", 1).id == "echo"
|
assert artifact_store.get_artifact("echo", 1).id == "echo"
|
||||||
|
|
||||||
|
|
||||||
|
def _api(root: Path) -> WorkflowApi:
|
||||||
|
mcp_root = root / "mcp"
|
||||||
|
service = WfMcpService(
|
||||||
|
store=FileStore(mcp_root),
|
||||||
|
artifact_store=FileWorkflowArtifactStore(root),
|
||||||
|
draft_workspace_store=FileDraftWorkspaceStore(mcp_root),
|
||||||
|
)
|
||||||
|
return WorkflowApi(context_from_service(service))
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_create_artifact_from_workspace_excludes_platform_sources_from_required_bindings(
|
||||||
|
tmp_path: Path,
|
||||||
|
) -> None:
|
||||||
|
api = _api(tmp_path)
|
||||||
|
workspace = await api.create_draft_workspace_from_capability(
|
||||||
|
workspace_id="constant_ws",
|
||||||
|
capability_name="wf.std.constant",
|
||||||
|
name="constant_value",
|
||||||
|
)
|
||||||
|
|
||||||
|
saved = await api.create_artifact_from_workspace(
|
||||||
|
workspace_id=workspace["workspace_id"],
|
||||||
|
artifact_id="constant_artifact",
|
||||||
|
version=1,
|
||||||
|
title="Constant Artifact",
|
||||||
|
outcomes=["ok"],
|
||||||
|
)
|
||||||
|
|
||||||
|
assert saved["saved"] is True
|
||||||
|
assert saved["required_logical_sources"] == []
|
||||||
|
assert saved["suggested_bindings"] == {}
|
||||||
|
|||||||
Reference in New Issue
Block a user