mirror of
https://github.com/langgenius/dify.git
synced 2026-10-04 13:47:55 +08:00
feat(dify-builder): name apps from their prompt, and turn gate actions into card options
Two App Builder spec changes that share the Builder session contract.
Naming (spec N1-N3): an app created from the homepage prompt is no longer named
by the user. core/dify_builder/naming.py cuts the prompt's opening clause at
create time -- instant and infallible, since it runs inside POST /apps -- and
CreateAppPayload.name becomes optional alongside a new prompt field. The Builder
then refines that name once during goal analysis, where a model and the detected
reply language are already in hand, so the judgement calls that are
English-shaped in pure Python (dropping an imperative lead-in, spotting a
contentless prompt) work in any language. Plan approval freezes the name.
Card options: SessionView gains a Decision carrying the gate's choice as options
inside the card plus a fixed confirm/cancel pair, replacing a button row whose
shape changed at every state. Option ids are the old action ids untouched, so
resolve_action_kind and the per-state legality check are unchanged, and
SessionView.actions keeps being populated -- the deployed web client goes on
working until it reads decision instead.
The regenerated console OpenAPI doc also picks up ErrorCard.diagnostics, missed
when cc9ca8b1dd landed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
cc9ca8b1dd
commit
aa2b4fe4ab
30 files changed
+1163
-18
No files matched your search
@@ -156,7 +156,13 @@ class StarredAppListQuery(AppListBaseQuery):
|
||||
|
||||
|
||||
class CreateAppPayload(BaseModel):
|
||||
name: str = Field(..., min_length=1, description="App name")
|
||||
# Optional since App Builder: an app created from the homepage prompt sends
|
||||
# ``prompt`` and no ``name``. A supplied name still wins -- that is
|
||||
# create-from-blank, where the user names the app and Builder inherits it.
|
||||
name: str | None = Field(default=None, min_length=1, description="App name; derived from prompt when omitted")
|
||||
prompt: str | None = Field(
|
||||
default=None, description="Goal prompt the app was created from; used to derive the name"
|
||||
)
|
||||
description: str | None = Field(default=None, description="App description (max 400 chars)", max_length=400)
|
||||
mode: Literal["chat", "agent-chat", "advanced-chat", "workflow", "completion"] = Field(..., description="App mode")
|
||||
icon_type: IconType | None = Field(default=None, description="Icon type")
|
||||
@@ -708,6 +714,7 @@ class AppListApi(Resource):
|
||||
"""Create app"""
|
||||
params = CreateAppParams(
|
||||
name=req_data.name,
|
||||
prompt=req_data.prompt,
|
||||
description=req_data.description,
|
||||
mode=req_data.mode,
|
||||
icon_type=req_data.icon_type,
|
||||
|
||||
@@ -52,7 +52,7 @@ from core.dify_builder.models import Action, Actor
|
||||
from libs.helper import dump_response
|
||||
from libs.login import login_required
|
||||
from services.dify_builder import progress_bus
|
||||
from services.dify_builder.service import resolve_action_kind
|
||||
from services.dify_builder.service import resolve_submitted_action
|
||||
from services.dify_builder.wiring import (
|
||||
build_service,
|
||||
dify_builder_error_response,
|
||||
@@ -140,6 +140,7 @@ def _create(body, actor: Actor) -> Response | tuple[dict, int]:
|
||||
actor=actor,
|
||||
goal_text=payload.goal_text,
|
||||
model_config=model_config,
|
||||
derive_app_name=payload.derive_app_name,
|
||||
)
|
||||
)
|
||||
if isinstance(payload, DifyBuilderCreateEditSessionPayload):
|
||||
@@ -179,7 +180,7 @@ def _action(session_id: str, body, actor: Actor) -> Response | tuple[dict, int]:
|
||||
except ValidationError:
|
||||
return {"code": "bad_request"}, 400
|
||||
action = Action(
|
||||
kind=resolve_action_kind(payload.action_id),
|
||||
kind=resolve_submitted_action(payload.action_id, payload.payload),
|
||||
payload=payload.payload,
|
||||
base_version=payload.base_version,
|
||||
base_app_revision=payload.base_app_revision,
|
||||
|
||||
@@ -16,6 +16,7 @@ from core.dify_builder.contract import (
|
||||
ChangeSetCard,
|
||||
CheckpointCard,
|
||||
CheckpointRef,
|
||||
Decision,
|
||||
DecisionItem,
|
||||
ErrorCard,
|
||||
ErrorEventData,
|
||||
@@ -52,6 +53,10 @@ class DifyBuilderCreateBuildSessionPayload(DifyBuilderPayload):
|
||||
app_id: NonEmptyString
|
||||
scenario: Literal["build"]
|
||||
goal_text: NonEmptyString
|
||||
# True when the app was created from this same prompt and still carries the
|
||||
# name cut from it, so Builder may rewrite it once it understands the goal.
|
||||
# False is create-from-blank: the user named the app, Builder inherits it.
|
||||
derive_app_name: bool = False
|
||||
model_config_data: SessionModel | None = Field(default=None, alias="model_config")
|
||||
|
||||
|
||||
@@ -252,6 +257,7 @@ class DifyBuilderSessionViewResponse(ResponseModel):
|
||||
entry_mode: EntryMode = EntryMode.FIX
|
||||
phase: Phase = Phase.UNDERSTAND
|
||||
actions: list[Action] = Field(default_factory=list)
|
||||
decision: Decision | None = None
|
||||
active_interaction: DifyBuilderActiveInteractionResponse | None = None
|
||||
checkpoint: CheckpointRef | None = None
|
||||
recovery: RecoveryRef | None = None
|
||||
|
||||
Reference in new issue
Block a user