Observe Builder commands and native tests on one session stream. Reconnect to the retained Run without submitting another test.
Use Stop and Resume for task control during native tests and keep approval details available. Allow retained local sandbox bindings to be checked without reading restricted ancestor directories.
Refs: ENG-1448
Move fixed copy into the difyBuilder i18n namespace and resolve scene IDs
using reply_language. Preserve dynamic streaming, historical receipts,
and submitted values.
Show fixed replies immediately with a short transition, detect language
before initial progress, and retire new notices and recovery messages.
Keep recovery and publication validation in place.
Update generated contracts and regression coverage, including progress
snapshot and execution context expectations and test type annotations.
Restore cumulative worker progress before live SSE updates and recover missed terminal state on idle heartbeats. Keep submitted interactions hidden while the command runs and record reconnect state in trace exports.
Add authenticated prepare/confirm/execute/status routes for one explicit
native Tool consent with strict request DTOs, public receipt/disclosure
responses, sanitized refusals, a typed 403 union and a fixed 400 for
non-JSON bodies. Execute uses the existing confirmed dispatch coordinator.
Regenerate the dify-builder console contracts (also carrying the Task 6
TestResultCard fields that were not yet regenerated).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
- test_wiring.py: expected dict was missing SessionView's new `model` field
- model_resolver.normalize_completion_params: a string `stop` was being
char-split into a list of letters instead of wrapped in a single-element
list; added a regression test
- controllers/console/dify_builder._ping: log the exception server-side
before returning the ok:false envelope
- ruff-clean the slice's new/extended test files (ARG001/ARG002/ARG005 via
precise noqa, PT018 compound-assert splits, E306, E501) with no change
to test behavior or assertion meaning
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>