fix: smooth challenge-driven cli ux gaps

This commit is contained in:
lda
2026-06-28 23:18:33 +07:00 Verified
parent 8b751da402
commit bf9abda1c3
10 changed files with 164 additions and 7 deletions
+21 -4
View File
@@ -199,7 +199,10 @@ class WorkflowArtifactApi:
"version": workflow_artifact.version,
"saved": True,
"required_logical_sources": required_sources,
"suggested_bindings": _suggested_self_bindings(required_sources),
"suggested_bindings": _suggested_self_bindings(
required_sources,
self.context.specs.capability_sources,
),
}
async def create_artifact_from_workspace(
@@ -302,9 +305,23 @@ class WorkflowArtifactApi:
}
def _suggested_self_bindings(required_sources: Sequence[str]) -> dict[str, str]:
"""Suggest local bindings for external sources that deploy to themselves."""
return {}
def _suggested_self_bindings(
required_sources: Sequence[str],
sources: Mapping[str, CapabilitySource],
) -> dict[str, str]:
"""Suggest only exact, enabled concrete sources as deployment bindings.
Ambiguous logical sources such as ``drive`` with multiple concrete accounts
must stay unsuggested. Exact ids such as ``local.report`` are safe because
the same source is already present in the active inventory.
"""
return {
source_id: source_id
for source_id in required_sources
if (source := sources.get(source_id)) is not None
and source.enabled
and source.policy.binding_required
}
def _binding_required_sources(
+26 -1
View File
@@ -10,6 +10,7 @@ from wf_cli.context import load_cli_context_from_typer as load_cli_context
from wf_cli.formats import ListOutputFormat, emit_list_payload
from wf_cli.io import CliInputError, emit_json, parse_bindings, parse_json_value
from wf_cli.remote_errors import run_cli_operation
from wf_core.paths import LocalPath, PathResolutionError, StatePath
def _parse_assignment_flags(
@@ -37,6 +38,30 @@ def _parse_map_flags(values: list[str] | None) -> dict[str, str]:
)
def _parse_output_map_flags(values: list[str] | None) -> dict[str, str]:
parsed = _parse_assignment_flags(
values,
option_name="--bind-output",
expected="LOCAL_OUTPUT=STATE_TARGET",
)
for local_output, state_target in parsed.items():
try:
LocalPath.parse(local_output)
except PathResolutionError as exc:
raise typer.BadParameter(
f"--bind-output source {local_output!r} must be a node-local "
"output path such as value or ."
) from exc
try:
StatePath.parse(state_target)
except PathResolutionError as exc:
raise typer.BadParameter(
f"--bind-output target {state_target!r} must be a state path "
"such as state.value"
) from exc
return parsed
def _parse_route_flags(values: list[str] | None) -> dict[str, str]:
return _parse_assignment_flags(
values,
@@ -396,7 +421,7 @@ def add_step_from_capability(
want, then run `wf draft validate <workspace_id>`.
"""
input_map = _parse_map_flags(input_mapping)
bind_outputs = _parse_map_flags(output_mapping)
bind_outputs = _parse_output_map_flags(output_mapping)
routes = _parse_route_flags(route)
context = load_cli_context(ctx)
emit_json(
+1
View File
@@ -19,6 +19,7 @@ def schema_command(
verbose: bool = typer.Option(
False,
"--verbose",
"--full",
"-v",
help="Print complete valid JSON Schema; output may be large.",
),