next action hints

This commit is contained in:
lda
2026-05-31 17:09:22 +07:00 Verified
parent f407326562
commit a15747c0a2
7 changed files with 702 additions and 2 deletions
+101 -1
View File
@@ -833,7 +833,15 @@ class WorkflowSurfaceHandlers:
error_message_source=error_message_source,
title=title,
)
return {**result, "wrapper_hints": hints}
return {
**result,
"wrapper_hints": hints,
"next_actions": _wrapper_draft_next_actions(
workspace_id=workspace_id,
revision=int(result["revision"]),
hints=hints,
),
}
async def create_artifact_from_workspace(
self,
@@ -1478,6 +1486,98 @@ def _draft_name_from_capability(capability_name: str) -> str:
return capability_name.replace(".", "_").replace("-", "_")
def _wrapper_draft_next_actions(
*,
workspace_id: str,
revision: int,
hints: dict[str, Any],
) -> dict[str, Any]:
"""Convert wrapper_hints into advisory next-tool guidance for MCP clients."""
confidence = str(hints.get("confidence", "low"))
missing_decisions = hints.get("missing_decisions")
notes = [str(note) for note in hints.get("notes", []) if isinstance(note, str)]
has_missing = isinstance(missing_decisions, list) and len(missing_decisions) > 0
can_save_now = confidence == "high" and not has_missing
if can_save_now:
return {
"can_save_now": True,
"recommended_next_tool": "wf.workflow.validate_draft_workspace",
"reason": "Wrapper hints are high confidence and have no missing decisions.",
"patch_examples": [],
"warnings": [],
}
return {
"can_save_now": False,
"recommended_next_tool": "wf.workflow.patch_draft_workspace",
"reason": "Review missing wrapper decisions before saving.",
"patch_examples": _wrapper_draft_patch_examples(
workspace_id=workspace_id,
revision=revision,
hints=hints,
),
"warnings": notes,
}
def _wrapper_draft_patch_examples(
*,
workspace_id: str,
revision: int,
hints: dict[str, Any],
) -> list[dict[str, Any]]:
"""Return conservative JSON Patch examples without guessing semantics."""
examples: list[dict[str, Any]] = []
missing_decisions = hints.get("missing_decisions")
if not isinstance(missing_decisions, list):
return examples
decision_kinds = {
str(decision.get("kind"))
for decision in missing_decisions
if isinstance(decision, dict)
}
if {
"choose_output_fields",
"review_nested_output",
} & decision_kinds:
examples.append(
{
"description": (
"Replace output bindings after choosing which capability "
"outputs should be written to workflow state."
),
"tool": "wf.workflow.patch_draft_workspace",
"request": {
"workspace_id": workspace_id,
"revision": revision,
"patch": [
{
"op": "replace",
"path": "/draft/steps/call/output",
"value": [],
}
],
},
}
)
if "confirm_boolean_outcomes" in decision_kinds:
examples.append(
{
"description": (
"Review boolean output candidates before adding routing; "
"do not route on boolean fields automatically."
),
"tool": "wf.workflow.patch_draft_workspace",
"request": {
"workspace_id": workspace_id,
"revision": revision,
"patch": [],
},
}
)
return examples
def _source_id_for_capability(
sources: dict[str, CapabilitySource],
qualified_name: str,
+43 -1
View File
@@ -353,8 +353,44 @@ class CreateDraftWorkspaceFromCapabilityRequest(BaseModel):
)
class WrapperDraftPatchExample(BaseModel):
"""Concrete patch-workspace example for a likely next authoring edit."""
description: str = Field(description="Human-readable reason for this patch.")
tool: str = Field(description="MCP tool to call for this example.")
request: dict[str, Any] = Field(
description="JSON request payload to pass to the tool."
)
class WrapperDraftNextActions(BaseModel):
"""Advisory continuation hints after bootstrapping a wrapper draft."""
can_save_now: bool = Field(
description=(
"Advisory only. False means the scaffold likely needs review before "
"saving, but the server does not enforce this."
)
)
recommended_next_tool: str = Field(
description=(
"Suggested next MCP tool, usually wf.workflow.validate_draft_workspace "
"or wf.workflow.patch_draft_workspace."
)
)
reason: str = Field(description="Short explanation for the recommendation.")
patch_examples: list[WrapperDraftPatchExample] = Field(
default_factory=list,
description="Concrete JSON Patch examples for common missing decisions.",
)
warnings: list[str] = Field(
default_factory=list,
description="Non-blocking warnings copied from low-confidence wrapper hints.",
)
class CreateDraftWorkspaceFromCapabilityResult(DraftWorkspaceResult):
"""Draft workspace result plus the wrapper hints used to bootstrap it."""
"""Draft workspace result plus wrapper hints and advisory next actions."""
wrapper_hints: dict[str, Any] = Field(
description=(
@@ -362,6 +398,12 @@ class CreateDraftWorkspaceFromCapabilityResult(DraftWorkspaceResult):
"Use this to patch uncertain maps or schemas by revision."
)
)
next_actions: WrapperDraftNextActions = Field(
description=(
"Advisory next step guidance derived from wrapper_hints. "
"The server does not enforce can_save_now."
)
)
class CreateArtifactFromWorkspaceRequest(BaseModel):