refactor(api): rename placeholder to default_value in various parts

Previously the fields / classes are named with `placeholder`. However,
the actual purpose is to use as default values. This commit addresses
this problem by correcting names for relevant fields / classes.

- FormInputPlaceholder
- FormInput.placeholder
- HumanInputRequiredResponse.resolved_placeholder_values
- HumanInputFormDefinition.resolved_placeholder_values
- FormCreateParams.resolved_placeholder_values
- HumanInputRequired.resolved_placeholder_values
- The `resolved_placeholder_values` argument of _create_human_input_delivery_test_form
- The `resolved_placeholder_values` inside _jsonify_form_definition
This commit is contained in:
QuantumGhost
2026-01-23 15:04:46 +08:00
parent 9e56d65612
commit 33a830cbc9
27 changed files with 103 additions and 139 deletions

View File

@ -22,16 +22,16 @@ class HumanInputRequired(BaseModel):
node_id: str
node_title: str
# The `resolved_placeholder_values` stores the resolved values of variable placeholders. It's a mapping from
# The `resolved_default_values` stores the resolved values of variable defaults. It's a mapping from
# `output_variable_name` to their resolved values.
#
# For example, The form contains a input with output variable name `name` and placeholder type `VARIABLE`, its
# selector is ["start", "name"]. While the HumanInputNode is executed, the correspond value of variable
# `start.name` in variable pool is `John`. Thus, the resolved value of the output variable `name` is `John`. The
# `resolved_placeholder_values` is `{"name": "John"}`.
# `resolved_default_values` is `{"name": "John"}`.
#
# Only form inputs with placeholder type `VARIABLE` will be resolved and stored in `resolved_placeholder_values`.
resolved_placeholder_values: Mapping[str, Any] = Field(default_factory=dict)
# Only form inputs with default value type `VARIABLE` will be resolved and stored in `resolved_default_values`.
resolved_default_values: Mapping[str, Any] = Field(default_factory=dict)
# The `form_token` is the token used to submit the form via UI surfaces. It corresponds to
# `HumanInputFormRecipient.access_token`.

View File

@ -153,20 +153,20 @@ def apply_debug_email_recipient(
return method.model_copy(update={"config": debug_config})
class FormInputPlaceholder(BaseModel):
"""Placeholder configuration for form inputs."""
class FormInputDefault(BaseModel):
"""Default configuration for form inputs."""
# NOTE: Ideally, a discriminated union would be used to model
# FormInputPlaceholder. However, the UI requires preserving the previous
# FormInputDefault. However, the UI requires preserving the previous
# value when switching between `VARIABLE` and `CONSTANT` types. This
# necessitates retaining all fields, making a discriminated union unsuitable.
type: PlaceholderType
# The selector of placeholder variable, used when `type` is `VARIABLE`
# The selector of default variable, used when `type` is `VARIABLE`.
selector: Sequence[str] = Field(default_factory=tuple) #
# The value of the placeholder, used when `type` is `CONSTANT`.
# The value of the default, used when `type` is `CONSTANT`.
# TODO: How should we express JSON values?
value: str = ""
@ -184,7 +184,7 @@ class FormInput(BaseModel):
type: FormInputType
output_variable_name: str
placeholder: Optional[FormInputPlaceholder] = None
default: Optional[FormInputDefault] = None
_IDENTIFIER_PATTERN = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$")
@ -286,14 +286,14 @@ class HumanInputNodeData(BaseNodeData):
_add_variable_selectors(delivery_method.extract_variable_selectors())
for input in self.inputs:
placeholder = input.placeholder
if placeholder is None:
default_value = input.default
if default_value is None:
continue
if placeholder.type == PlaceholderType.CONSTANT:
if default_value.type == PlaceholderType.CONSTANT:
continue
placeholder_key = ".".join(placeholder.selector)
qualified_variable_mapping_key = f"{node_id}.#{placeholder_key}#"
variable_mappings[qualified_variable_mapping_key] = placeholder.selector
default_value_key = ".".join(default_value.selector)
qualified_variable_mapping_key = f"{node_id}.#{default_value_key}#"
variable_mappings[qualified_variable_mapping_key] = default_value.selector
return variable_mappings
@ -316,8 +316,8 @@ class FormDefinition(BaseModel):
timeout: int
timeout_unit: TimeoutUnit
# this is used to store the values of the placeholders
placeholder_values: dict[str, Any] = Field(default_factory=dict)
# this is used to store the resolved default values
default_values: dict[str, Any] = Field(default_factory=dict)
# node_title records the title of the HumanInput node.
node_title: str | None = None

View File

@ -51,7 +51,7 @@ class FormInputType(enum.StrEnum):
class PlaceholderType(enum.StrEnum):
"""Placeholder types for form inputs."""
"""Default value types for form inputs."""
VARIABLE = enum.auto()
CONSTANT = enum.auto()

View File

@ -136,23 +136,23 @@ class HumanInputNode(Node[HumanInputNodeData]):
pause_requested_event = PauseRequestedEvent(reason=required_event)
return pause_requested_event
def _resolve_inputs(self) -> Mapping[str, Any]:
def _resolve_default_values(self) -> Mapping[str, Any]:
variable_pool = self.graph_runtime_state.variable_pool
resolved_inputs = {}
resolved_defaults: dict[str, Any] = {}
for input in self._node_data.inputs:
if (placeholder := input.placeholder) is None:
if (default_value := input.default) is None:
continue
if placeholder.type == PlaceholderType.CONSTANT:
if default_value.type == PlaceholderType.CONSTANT:
continue
placeholder_value = variable_pool.get(placeholder.selector)
if placeholder_value is None:
resolved_value = variable_pool.get(default_value.selector)
if resolved_value is None:
# TODO: How should we handle this?
continue
resolved_inputs[input.output_variable_name] = (
WorkflowRuntimeTypeConverter().value_to_json_encodable_recursive(placeholder_value.value)
resolved_defaults[input.output_variable_name] = (
WorkflowRuntimeTypeConverter().value_to_json_encodable_recursive(resolved_value.value)
)
return resolved_inputs
return resolved_defaults
def _should_require_console_recipient(self) -> bool:
if self.invoke_from == InvokeFrom.DEBUGGER:
@ -181,7 +181,7 @@ class HumanInputNode(Node[HumanInputNodeData]):
def _human_input_required_event(self, form_entity: HumanInputFormEntity) -> HumanInputRequired:
node_data = self._node_data
resolved_placeholder_values = self._resolve_inputs()
resolved_default_values = self._resolve_default_values()
display_in_ui = self._display_in_ui()
form_token = form_entity.web_app_token
if display_in_ui and form_token is None:
@ -195,7 +195,7 @@ class HumanInputNode(Node[HumanInputNodeData]):
node_id=self.id,
node_title=node_data.title,
form_token=form_token,
resolved_placeholder_values=resolved_placeholder_values,
resolved_default_values=resolved_default_values,
)
def _run(self) -> Generator[NodeEventBase, None, None]:
@ -222,7 +222,7 @@ class HumanInputNode(Node[HumanInputNodeData]):
rendered_content=self._render_form_content_before_submission(),
delivery_methods=self._effective_delivery_methods(),
display_in_ui=display_in_ui,
resolved_placeholder_values=self._resolve_inputs(),
resolved_default_values=self._resolve_default_values(),
console_recipient_required=self._should_require_console_recipient(),
console_creator_account_id=(
self.user_id if self.invoke_from in {InvokeFrom.DEBUGGER, InvokeFrom.EXPLORE} else None
@ -330,11 +330,11 @@ class HumanInputNode(Node[HumanInputNodeData]):
node_data: Mapping[str, Any],
) -> Mapping[str, Sequence[str]]:
"""
Extract variable selectors referenced in form content and input placeholders.
Extract variable selectors referenced in form content and input default values.
This method should parse:
1. Variables referenced in form_content ({{#node_name.var_name#}})
2. Variables referenced in input placeholders
2. Variables referenced in input default values
"""
validated_node_data = HumanInputNodeData.model_validate(node_data)
return validated_node_data.extract_variable_selector_to_variable_mapping(node_id)

View File

@ -36,11 +36,11 @@ class FormCreateParams:
# UI display flag computed by runtime context.
display_in_ui: bool
# resolved_placeholder_values saves the values for placeholders with
# resolved_default_values saves the values for defaults with
# type = VARIABLE.
#
# For type = CONSTANT, the value is not stored inside `resolved_placeholder_values`
resolved_placeholder_values: Mapping[str, Any]
# For type = CONSTANT, the value is not stored inside `resolved_default_values`
resolved_default_values: Mapping[str, Any]
form_kind: HumanInputFormKind = HumanInputFormKind.RUNTIME
# Force creating a console-only recipient for submission in Console.