Files
lda-wf/src/wf_api/service.py
T

1090 lines
34 KiB
Python

from __future__ import annotations
from collections.abc import Mapping, Sequence
from typing import Any, Literal, overload
from wf_artifacts import ArtifactKind, compile_workflow_draft
from wf_artifacts.drafts.models import DraftStep
from wf_core.analysis.context_scopes import context_analysis_warnings
from wf_core.models.steps import InputBinding, OutputBinding, StepInputBinding
from wf_core.models.workflow import Workflow
from .artifacts import WorkflowArtifactApi
from .authoring_contracts import (
context_path_options_for_node,
project_authoring_contract_inventory,
project_authoring_step_contract,
schema_path_options,
)
from .capabilities import WorkflowCapabilityApi
from .deployments import WorkflowDeploymentApi
from .draft_authoring import RouteSource, WorkflowDraftAuthoringApi
from .draft_updates import CapabilityStepUpdate
from .drafts import WorkflowDraftApi
from .models import (
AuthoringContractInventoryPayload,
CapabilityCallResult,
CompileDraftWorkspaceResult,
CompileDraftWorkspaceSuccess,
CreateArtifactFromWorkspaceResult,
CreateDraftWorkspaceFromCapabilityResult,
DeleteArtifactResult,
DeleteDeploymentResult,
DeleteDraftWorkspaceResult,
DraftWorkspaceResult,
DraftWorkspaceWithDocument,
InspectCapabilityResult,
ListArtifactsResult,
ListCapabilitiesResult,
ListDeploymentsResult,
ListDraftWorkspacesResult,
ListRunsResult,
PatchDraftResult,
RawWorkflowPlan,
RunResult,
RunTraceResult,
SaveArtifactResult,
SavedDraftArtifactResult,
SaveDeploymentResult,
ValidateArtifactPlanResult,
ValidateDeploymentResult,
ValidateDraftResult,
WorkflowArtifactPayload,
WorkflowDeploymentPayload,
)
from .operation_context import WorkflowOperationContext
from .runs import TraceRangeLike, WorkflowRunApi
def _authoring_schema(
value: object,
*,
field_name: str,
root: str,
warnings: list[str],
) -> dict[str, Any]:
"""Return one valid persisted schema, isolating invalid projections."""
if not isinstance(value, Mapping):
warnings.append(
f"{field_name} authoring choices unavailable: expected a schema object"
)
return {}
schema = dict(value)
try:
schema_path_options(schema, root=root, uses=[])
except ValueError as exc:
warnings.append(f"{field_name} authoring choices unavailable: {exc}")
return {}
return schema
def _authoring_outcomes(value: object) -> list[str]:
"""Keep only a complete string outcome list for tolerant inventory output."""
if not isinstance(value, list) or not all(
isinstance(outcome, str) for outcome in value
):
return []
return list(value)
def _step_label(step_id: str) -> str:
"""Humanize a keyed draft step for compact executable choices."""
return step_id.replace("_", " ").replace("-", " ").title()
class WorkflowApi:
"""Protocol-neutral workflow application facade.
This facade owns the stable application entry point. It composes the
domain APIs from a WorkflowOperationContext so MCP, CLI, and future HTTP
callers share one operation surface without importing wf_mcp.
"""
def __init__(
self,
context: WorkflowOperationContext,
*,
drafts: bool = False,
) -> None:
self.context = context
self.capabilities = WorkflowCapabilityApi(context, drafts=drafts)
# ``drafts`` keeps server composition explicit. Disabled APIs are None,
# so artifact/deployment/run initialization has no draft dependency.
self.drafts_enabled = drafts
if self.drafts_enabled:
self.drafts = WorkflowDraftApi(context)
self.draft_authoring = WorkflowDraftAuthoringApi(context, self.drafts)
else:
self.drafts = None
self.draft_authoring = None
self.artifacts = WorkflowArtifactApi(context, drafts=drafts)
self.deployments = WorkflowDeploymentApi(context)
self.runs = WorkflowRunApi(context)
def _require_drafts(self) -> WorkflowDraftApi:
"""Return the draft service for an explicitly draft-enabled API."""
if self.drafts is None:
raise ValueError("workflow draft APIs are disabled; pass drafts=True")
return self.drafts
def _require_draft_authoring(self) -> WorkflowDraftAuthoringApi:
"""Return draft authoring for an explicitly draft-enabled API."""
if self.draft_authoring is None:
raise ValueError("workflow draft APIs are disabled; pass drafts=True")
return self.draft_authoring
# -- capabilities --
async def list_capabilities(
self,
*,
query: str | None = None,
source_id: str | None = None,
cursor: str | None = None,
limit: int = 50,
) -> ListCapabilitiesResult:
return await self.capabilities.list_capabilities(
query=query,
source_id=source_id,
cursor=cursor,
limit=limit,
)
async def inspect_capability(
self,
*,
qualified_name: str,
) -> InspectCapabilityResult:
return await self.capabilities.inspect_capability(qualified_name=qualified_name)
async def call_capability(
self,
*,
qualified_name: str,
payload: dict[str, Any],
deployment_id: str | None = None,
) -> CapabilityCallResult:
return await self.capabilities.call_capability(
qualified_name=qualified_name,
payload=payload,
deployment_id=deployment_id,
)
# -- artifacts --
async def list_artifacts(
self,
*,
query: str | None = None,
kind: ArtifactKind | None = None,
cursor: str | None = None,
limit: int = 50,
) -> ListArtifactsResult:
return await self.artifacts.list_artifacts(
query=query,
kind=kind,
cursor=cursor,
limit=limit,
)
async def inspect_artifact(
self,
*,
artifact_id: str,
version: int,
) -> WorkflowArtifactPayload:
return await self.artifacts.inspect_artifact(
artifact_id=artifact_id,
version=version,
)
async def delete_artifact(
self,
*,
artifact_id: str,
version: int,
) -> DeleteArtifactResult:
return await self.artifacts.delete_artifact(
artifact_id=artifact_id,
version=version,
)
async def save_artifact(
self,
artifact: dict[str, Any],
) -> SaveArtifactResult:
return await self.artifacts.save_artifact(artifact)
async def create_artifact_from_plan(
self,
*,
artifact_id: str,
version: int,
title: str,
plan: RawWorkflowPlan | dict[str, Any],
outcomes: Sequence[str],
kind: ArtifactKind = "workflow",
description: str | None = None,
required_capabilities: dict[str, dict[str, Any]] | None = None,
source_bindings: dict[str, str] | None = None,
created_from_catalog_version: str | None = None,
) -> SaveArtifactResult:
return await self.artifacts.create_artifact_from_plan(
artifact_id=artifact_id,
version=version,
title=title,
plan=plan,
outcomes=outcomes,
kind=kind,
description=description,
required_capabilities=required_capabilities,
source_bindings=source_bindings,
created_from_catalog_version=created_from_catalog_version,
)
async def validate_artifact_plan(
self,
*,
plan: dict[str, Any],
outcomes: Sequence[str],
required_capabilities: dict[str, dict[str, Any]] | None = None,
source_bindings: dict[str, str] | None = None,
) -> ValidateArtifactPlanResult:
return await self.artifacts.validate_artifact_plan(
plan=plan,
outcomes=outcomes,
required_capabilities=required_capabilities,
source_bindings=source_bindings,
)
async def create_artifact_from_draft(
self,
*,
artifact_id: str,
version: int,
title: str,
draft: dict[str, Any],
outcomes: Sequence[str],
kind: ArtifactKind = "workflow",
description: str | None = None,
required_capabilities: dict[str, dict[str, Any]] | None = None,
source_bindings: dict[str, str] | None = None,
created_from_catalog_version: str | None = None,
) -> SavedDraftArtifactResult:
return await self.artifacts.create_artifact_from_draft(
artifact_id=artifact_id,
version=version,
title=title,
draft=draft,
outcomes=outcomes,
kind=kind,
description=description,
required_capabilities=required_capabilities,
source_bindings=source_bindings,
created_from_catalog_version=created_from_catalog_version,
)
async def create_artifact_from_workspace(
self,
*,
workspace_id: str,
artifact_id: str,
version: int,
title: str,
outcomes: Sequence[str],
kind: ArtifactKind = "workflow",
description: str | None = None,
required_capabilities: dict[str, dict[str, Any]] | None = None,
source_bindings: dict[str, str] | None = None,
created_from_catalog_version: str | None = None,
) -> CreateArtifactFromWorkspaceResult:
return await self.artifacts.create_artifact_from_workspace(
workspace_id=workspace_id,
artifact_id=artifact_id,
version=version,
title=title,
outcomes=outcomes,
kind=kind,
description=description,
required_capabilities=required_capabilities,
source_bindings=source_bindings,
created_from_catalog_version=created_from_catalog_version,
)
async def create_wrapper_from_workspace(
self,
*,
workspace_id: str,
artifact_id: str,
version: int,
title: str,
outcomes: Sequence[str],
description: str | None = None,
required_capabilities: dict[str, dict[str, Any]] | None = None,
source_bindings: dict[str, str] | None = None,
created_from_catalog_version: str | None = None,
) -> CreateArtifactFromWorkspaceResult:
return await self.artifacts.create_wrapper_from_workspace(
workspace_id=workspace_id,
artifact_id=artifact_id,
version=version,
title=title,
outcomes=outcomes,
description=description,
required_capabilities=required_capabilities,
source_bindings=source_bindings,
created_from_catalog_version=created_from_catalog_version,
)
# -- drafts --
async def validate_draft(
self,
*,
draft: dict[str, Any],
) -> ValidateDraftResult:
return await self._require_drafts().validate_draft(draft=draft)
async def compile_draft(
self,
*,
draft: dict[str, Any],
) -> CompileDraftWorkspaceSuccess:
return await self._require_drafts().compile_draft(draft=draft)
async def patch_draft(
self,
*,
draft: dict[str, Any],
patch: list[dict[str, Any]],
) -> PatchDraftResult:
return await self._require_drafts().patch_draft(draft=draft, patch=patch)
# -- draft workspaces --
async def list_draft_workspaces(self) -> ListDraftWorkspacesResult:
return await self._require_drafts().list_draft_workspaces()
async def create_draft_workspace(
self,
*,
workspace_id: str,
draft: dict[str, Any],
title: str | None = None,
) -> DraftWorkspaceResult:
return await self._require_drafts().create_draft_workspace(
workspace_id=workspace_id,
draft=draft,
title=title,
)
async def create_empty_draft_workspace(
self,
*,
workspace_id: str,
name: str,
title: str | None = None,
input_schema: dict[str, Any] | None = None,
state_schema: dict[str, Any] | None = None,
output_schema: dict[str, Any] | None = None,
outcomes: Sequence[str] = ("ok",),
) -> DraftWorkspaceResult:
return await self._require_drafts().create_empty_draft_workspace(
workspace_id=workspace_id,
name=name,
title=title,
input_schema=input_schema,
state_schema=state_schema,
output_schema=output_schema,
outcomes=outcomes,
)
@overload
async def get_draft_workspace(
self,
*,
workspace_id: str,
include_draft: Literal[True],
) -> DraftWorkspaceWithDocument: ...
@overload
async def get_draft_workspace(
self,
*,
workspace_id: str,
include_draft: Literal[False] = False,
) -> DraftWorkspaceResult: ...
async def get_draft_workspace(
self,
*,
workspace_id: str,
include_draft: bool = False,
) -> DraftWorkspaceResult | DraftWorkspaceWithDocument:
return await self._require_drafts().get_draft_workspace(
workspace_id=workspace_id,
include_draft=include_draft,
)
async def inspect_draft_authoring_contract(
self,
*,
workspace_id: str,
revision: int,
selected_step_id: str | None = None,
) -> AuthoringContractInventoryPayload | DraftWorkspaceResult:
"""Inspect revision-scoped authoring choices without persisting changes.
The workspace revision check deliberately happens before interpreting a
selected step. This preserves the draft APIs' canonical conflict
precedence when an authoring client is holding an old revision.
"""
checked = self._require_drafts()._workspace_if_revision_matches(
workspace_id=workspace_id,
revision=revision,
)
if isinstance(checked, dict):
return checked
draft = checked.draft
raw_steps = draft.get("steps")
steps = raw_steps if isinstance(raw_steps, Mapping) else {}
if selected_step_id is not None and selected_step_id not in steps:
raise KeyError(f"unknown draft step {selected_step_id!r}")
warnings: list[str] = []
entry_steps = []
selected_contract = None
for raw_step_id, raw_step in steps.items():
if not isinstance(raw_step_id, str) or raw_step_id == "__end__":
continue
if not isinstance(raw_step, Mapping):
continue
capability_name = raw_step.get("use")
if not isinstance(capability_name, str):
if raw_step_id == selected_step_id:
warnings.append(
f"selected step {raw_step_id!r} is not an executable capability"
)
continue
try:
resolved_contract = self.capabilities.resolve_capability_contract(
capability_name
)
except (KeyError, TypeError, ValueError) as exc:
if raw_step_id == selected_step_id:
warnings.append(
f"selected step {raw_step_id!r} cannot be interpreted: {exc}"
)
continue
description = raw_step.get("desc")
if not isinstance(description, str):
description = resolved_contract.description
input_schema = _authoring_schema(
resolved_contract.input_schema,
field_name=f"step {raw_step_id!r} input schema",
root="step_input",
warnings=warnings,
)
output_schema = _authoring_schema(
resolved_contract.output_schema,
field_name=f"step {raw_step_id!r} output schema",
root="step_output",
warnings=warnings,
)
projected_contract = project_authoring_step_contract(
step_id=raw_step_id,
label=_step_label(raw_step_id),
description=description,
input_schema=input_schema,
output_schema=output_schema,
outcomes=resolved_contract.outcomes,
)
entry_steps.append(projected_contract)
if raw_step_id == selected_step_id:
selected_contract = projected_contract
context_entries = []
if selected_step_id is not None:
try:
compiled_plan = compile_workflow_draft(draft)
workflow = Workflow.model_validate(compiled_plan)
context_entries = context_path_options_for_node(
workflow,
selected_step_id,
)
warnings.extend(context_analysis_warnings(workflow))
except (KeyError, TypeError, ValueError) as exc:
warnings.append(
f"runtime context unavailable for selected step "
f"{selected_step_id!r}: {exc}"
)
selected_input_targets = []
selected_output_sources = []
if selected_contract is not None and selected_step_id is not None:
if selected_contract["step_id"] == selected_step_id:
selected_input_targets = selected_contract.get("input_targets", [])
selected_output_sources = selected_contract.get("output_sources", [])
return project_authoring_contract_inventory(
workspace_id=workspace_id,
revision=checked.revision,
selected_step_id=selected_step_id,
input_schema=_authoring_schema(
draft.get("input_schema"),
field_name="input_schema",
root="input",
warnings=warnings,
),
state_schema=_authoring_schema(
draft.get("state_schema"),
field_name="state_schema",
root="state",
warnings=warnings,
),
output_schema=_authoring_schema(
draft.get("output_schema"),
field_name="output_schema",
root="output",
warnings=warnings,
),
context_entries=context_entries,
step_input_targets=selected_input_targets,
step_output_sources=selected_output_sources,
entry_steps=entry_steps,
workflow_outcomes=_authoring_outcomes(draft.get("outcomes")),
warnings=warnings,
)
async def delete_draft_workspace(
self,
*,
workspace_id: str,
) -> DeleteDraftWorkspaceResult:
return await self._require_drafts().delete_draft_workspace(
workspace_id=workspace_id
)
async def validate_draft_workspace(
self,
*,
workspace_id: str,
) -> DraftWorkspaceResult:
return await self._require_drafts().validate_draft_workspace(
workspace_id=workspace_id
)
async def compile_draft_workspace(
self,
*,
workspace_id: str,
) -> CompileDraftWorkspaceResult:
return await self._require_drafts().compile_draft_workspace(
workspace_id=workspace_id
)
async def patch_draft_workspace(
self,
*,
workspace_id: str,
revision: int,
patch: list[dict[str, Any]],
) -> DraftWorkspaceResult:
return await self._require_drafts().patch_draft_workspace(
workspace_id=workspace_id,
revision=revision,
patch=patch,
)
async def replace_draft_workspace_document(
self,
*,
workspace_id: str,
revision: int,
draft: dict[str, Any],
) -> DraftWorkspaceResult:
"""Replace and semantically revalidate one complete workspace draft."""
return await self._require_drafts().replace_draft_workspace_document(
workspace_id=workspace_id,
revision=revision,
draft=draft,
)
async def set_draft_name(
self,
*,
workspace_id: str,
revision: int,
name: str,
) -> DraftWorkspaceResult:
return await self._require_drafts().set_draft_name(
workspace_id=workspace_id,
revision=revision,
name=name,
)
async def set_draft_start(
self,
*,
workspace_id: str,
revision: int,
step_id: str,
) -> DraftWorkspaceResult:
return await self._require_drafts().set_draft_start(
workspace_id=workspace_id,
revision=revision,
step_id=step_id,
)
async def set_draft_contract(
self,
*,
workspace_id: str,
revision: int,
input_schema: dict[str, Any] | None = None,
state_schema: dict[str, Any] | None = None,
output_schema: dict[str, Any] | None = None,
outcomes: Sequence[str] | None = None,
) -> DraftWorkspaceResult:
return await self._require_drafts().set_draft_contract(
workspace_id=workspace_id,
revision=revision,
input_schema=input_schema,
state_schema=state_schema,
output_schema=output_schema,
outcomes=outcomes,
)
async def set_draft_route(
self,
*,
workspace_id: str,
revision: int,
step_id: str,
outcome: str,
target: str,
) -> DraftWorkspaceResult:
return await self._require_drafts().set_draft_route(
workspace_id=workspace_id,
revision=revision,
step_id=step_id,
outcome=outcome,
target=target,
)
async def set_step_input_map(
self,
*,
workspace_id: str,
revision: int,
step_id: str,
input_map: dict[str, str],
merge: bool = False,
) -> DraftWorkspaceResult:
return await self._require_drafts().set_step_input_map(
workspace_id=workspace_id,
revision=revision,
step_id=step_id,
input_map=input_map,
merge=merge,
)
async def set_step_input_bindings(
self,
*,
workspace_id: str,
revision: int,
step_id: str,
bindings: Sequence[StepInputBinding],
) -> DraftWorkspaceResult:
return await self._require_draft_authoring().set_step_input_bindings(
workspace_id=workspace_id,
revision=revision,
step_id=step_id,
bindings=bindings,
)
async def set_step_output_bindings(
self,
*,
workspace_id: str,
revision: int,
step_id: str,
bindings: Sequence[OutputBinding],
) -> DraftWorkspaceResult:
return await self._require_draft_authoring().set_step_output_bindings(
workspace_id=workspace_id,
revision=revision,
step_id=step_id,
bindings=bindings,
)
async def update_capability_step(
self,
*,
workspace_id: str,
revision: int,
step_id: str,
update: CapabilityStepUpdate,
) -> DraftWorkspaceResult:
"""Return the updated workspace summary or a revision-conflict payload."""
return await self._require_draft_authoring().update_capability_step(
workspace_id=workspace_id,
revision=revision,
step_id=step_id,
update=update,
)
async def set_step_output_map(
self,
*,
workspace_id: str,
revision: int,
step_id: str,
output_map: dict[str, str],
merge: bool = False,
) -> DraftWorkspaceResult:
return await self._require_drafts().set_step_output_map(
workspace_id=workspace_id,
revision=revision,
step_id=step_id,
output_map=output_map,
merge=merge,
)
async def set_workflow_output_map(
self,
*,
workspace_id: str,
revision: int,
output_map: dict[str, str],
merge: bool = False,
) -> DraftWorkspaceResult:
return await self._require_drafts().set_workflow_output_map(
workspace_id=workspace_id,
revision=revision,
output_map=output_map,
merge=merge,
)
async def set_workflow_output_bindings(
self,
*,
workspace_id: str,
revision: int,
bindings: Sequence[InputBinding],
) -> DraftWorkspaceResult:
return await self._require_draft_authoring().set_workflow_output_bindings(
workspace_id=workspace_id,
revision=revision,
bindings=bindings,
)
async def bind_draft(
self,
*,
workspace_id: str,
revision: int,
step_id: str,
source_path: str,
target_path: str,
) -> DraftWorkspaceResult:
return await self._require_draft_authoring().bind_draft(
workspace_id=workspace_id,
revision=revision,
step_id=step_id,
source_path=source_path,
target_path=target_path,
)
async def add_step_from_capability(
self,
*,
workspace_id: str,
revision: int,
step_id: str,
capability_name: str,
route_from_step: str | None = None,
route_from_outcome: str = "ok",
routes: dict[str, str] | None = None,
input_map: dict[str, str] | None = None,
input_bindings: Sequence[StepInputBinding] | None = None,
bind_outputs: dict[str, str] | None = None,
desc: str | None = None,
retry: int | None = None,
timeout_seconds: int | None = None,
) -> DraftWorkspaceResult:
return await self._require_draft_authoring().add_step_from_capability(
workspace_id=workspace_id,
revision=revision,
step_id=step_id,
capability_name=capability_name,
route_from_step=route_from_step,
route_from_outcome=route_from_outcome,
routes=routes,
input_map=input_map,
input_bindings=input_bindings,
bind_outputs=bind_outputs,
desc=desc,
retry=retry,
timeout_seconds=timeout_seconds,
)
async def add_step(
self,
*,
workspace_id: str,
revision: int,
step_id: str,
step: DraftStep,
incoming: RouteSource | None = None,
routes: dict[str, str] | None = None,
) -> DraftWorkspaceResult:
return await self._require_draft_authoring().add_step(
workspace_id=workspace_id,
revision=revision,
step_id=step_id,
step=step,
incoming=incoming,
routes=routes,
)
async def branch_draft(
self,
*,
workspace_id: str,
revision: int,
step_id: str,
routes: dict[str, str],
) -> DraftWorkspaceResult:
return await self._require_draft_authoring().branch_draft(
workspace_id=workspace_id,
revision=revision,
step_id=step_id,
routes=routes,
)
async def handle_draft(
self,
*,
workspace_id: str,
revision: int,
branches: list[dict[str, str]],
target: str,
) -> DraftWorkspaceResult:
refs = [
RouteSource(step_id=b["step_id"], outcome=b["outcome"]) for b in branches
]
return await self._require_draft_authoring().handle_draft(
workspace_id=workspace_id,
revision=revision,
branches=refs,
target=target,
)
async def create_minimal_draft_workspace(
self,
*,
workspace_id: str,
name: str,
capability_name: str,
input_schema: dict[str, Any],
state_schema: dict[str, Any],
output_schema: dict[str, Any],
input: Sequence[StepInputBinding] | None = None,
output: Sequence[OutputBinding] | None = None,
input_map: dict[str, str] | None = None,
output_map: dict[str, str] | None = None,
error_message_source: Any | None = None,
title: str | None = None,
) -> DraftWorkspaceResult:
return await self._require_draft_authoring().create_minimal_draft_workspace(
workspace_id=workspace_id,
name=name,
capability_name=capability_name,
input_schema=input_schema,
state_schema=state_schema,
output_schema=output_schema,
input=input,
output=output,
input_map=input_map,
output_map=output_map,
error_message_source=error_message_source,
title=title,
)
async def remove_draft_route(
self,
*,
workspace_id: str,
revision: int,
step_id: str,
outcome: str,
) -> DraftWorkspaceResult:
return await self._require_draft_authoring().remove_draft_route(
workspace_id=workspace_id,
revision=revision,
step_id=step_id,
outcome=outcome,
)
async def remove_draft_step(
self,
*,
workspace_id: str,
revision: int,
step_id: str,
) -> DraftWorkspaceResult:
return await self._require_draft_authoring().remove_draft_step(
workspace_id=workspace_id,
revision=revision,
step_id=step_id,
)
async def remove_draft_binding(
self,
*,
workspace_id: str,
revision: int,
step_id: str,
inputs: Sequence[str] = (),
outputs: Sequence[str] = (),
) -> DraftWorkspaceResult:
return await self._require_draft_authoring().remove_draft_binding(
workspace_id=workspace_id,
revision=revision,
step_id=step_id,
inputs=inputs,
outputs=outputs,
)
async def create_draft_workspace_from_capability(
self,
*,
workspace_id: str,
capability_name: str,
name: str | None = None,
title: str | None = None,
input_schema: dict[str, Any] | None = None,
state_schema: dict[str, Any] | None = None,
output_schema: dict[str, Any] | None = None,
input: Sequence[StepInputBinding] | None = None,
output: Sequence[OutputBinding] | None = None,
input_map: dict[str, str] | None = None,
output_map: dict[str, str] | None = None,
error_message_source: Any | None = None,
) -> CreateDraftWorkspaceFromCapabilityResult:
return await self.capabilities.create_draft_workspace_from_capability(
workspace_id=workspace_id,
capability_name=capability_name,
name=name,
title=title,
input_schema=input_schema,
state_schema=state_schema,
output_schema=output_schema,
input=input,
output=output,
input_map=input_map,
output_map=output_map,
error_message_source=error_message_source,
)
# -- deployments --
async def list_deployments(self) -> ListDeploymentsResult:
return await self.deployments.list_deployments()
async def inspect_deployment(
self,
*,
deployment_id: str,
) -> WorkflowDeploymentPayload:
return await self.deployments.inspect_deployment(deployment_id=deployment_id)
async def save_deployment(
self,
deployment: dict[str, Any],
) -> SaveDeploymentResult:
return await self.deployments.save_deployment(deployment)
async def delete_deployment(
self,
*,
deployment_id: str,
) -> DeleteDeploymentResult:
return await self.deployments.delete_deployment(deployment_id=deployment_id)
async def validate_deployment(
self,
*,
deployment_id: str,
live_check: bool = False,
) -> ValidateDeploymentResult:
return await self.deployments.validate_deployment(
deployment_id=deployment_id,
live_check=live_check,
)
# -- runs --
async def list_runs(
self,
*,
status: str | None = None,
cursor: str | None = None,
limit: int = 50,
) -> ListRunsResult:
return await self.runs.list_runs(
status=status,
cursor=cursor,
limit=limit,
)
async def run_deployment(
self,
*,
deployment_id: str,
workflow_input: dict[str, Any],
trace_range: TraceRangeLike | None = None,
) -> RunResult:
return await self.runs.run_deployment(
deployment_id=deployment_id,
workflow_input=workflow_input,
trace_range=trace_range,
)
async def resume_run(
self,
*,
run_id: str,
resume_payload: dict[str, Any],
resume_outcome: str = "submitted",
trace_range: TraceRangeLike | None = None,
) -> RunResult:
return await self.runs.resume_run(
run_id=run_id,
resume_payload=resume_payload,
resume_outcome=resume_outcome,
trace_range=trace_range,
)
async def inspect_run(
self,
*,
run_id: str,
) -> RunResult:
return await self.runs.inspect_run(run_id=run_id)
async def read_run_trace(
self,
*,
run_id: str,
trace_range: TraceRangeLike,
) -> RunTraceResult:
return await self.runs.read_run_trace(
run_id=run_id,
trace_range=trace_range,
)