Commit Graph
7783 Commits
Author SHA1 Message Date
Charles YaoandClaude Opus 4.8 de8a5745ea fix(dify_builder): always emit a terminal SSE frame so held version can't go stale
Two paths ended a streaming advance without a terminal `state`/`error`
frame, leaving the SSE client stalled to the deadline with a stale held
version -> its next action 409s:

1. advance_session published the terminal `state` frame outside the
   try/finally and unguarded. If the post-advance view projection
   (get_session_view -> read_graph) or the publish itself raised after a
   SUCCESSFUL advance, the exception escaped and no terminal frame was
   sent. Guard it and fall back to a terminal `error` frame.

2. submit_action_stream emitted a terminal `state` frame on settle only
   for `message`. `update_model` also settles synchronously while bumping
   the version, so it now emits one too -- otherwise the FE keeps the old
   version and 409s on its next action.

Adds regression tests for both (projection-failure -> error frame;
update_model -> state frame).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-03 08:48:23 +08:00
twwu 3eacff14a6 feat: add typed SSE interactions to Dify Builder 2026-09-03 08:48:23 +08:00
Charles YaoandClaude Opus 4.8 1eb5bb1dd1 fix(dify_builder): publish adapter unpacked publish_workflow's return as a tuple
WorkflowService.publish_workflow returns a single Workflow (-> Workflow), but
dify_port.publish still unpacked it as (workflow, retirement_candidates) -- a
stale signature. Every other caller was updated when the return type changed
(via the main merge); only the Dify Builder port was missed, so every publish
crashed with "TypeError: cannot unpack non-iterable Workflow object", surfaced
to the user as a generic "step failed" SSE frame.

Assign the single return value (retirement_candidates was unused anyway). The
existing test_dify_port publish test mocked publish_workflow as a 2-tuple, which
masked the bug -- corrected it to the real -> Workflow signature so it now guards
the regression.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 16:11:49 -07:00
Charles YaoandClaude Opus 4.8 e7e14ab888 fix(dify_builder): stop empty/mode-mismatched builds silently emptying the canvas
A build for a workflow app whose goal reads like a chatbot produced an empty
canvas while the assistant reported "Workflow built on the canvas.": the plan
was chatbot-shaped, build_nodes fed it to the generator (mode="workflow"), the
LLM emitted a chatflow graph (answer node / no end node), the generator
rejected it as MISSING_TERMINAL -- a class it does NOT retry -- and build_nodes
swallowed the error into []. handle_plan_approval then treated [] as a
successful build: it deleted the placeholder start and advanced to
build.execution, leaving nothing on the canvas.

Two parts:

1. build_nodes now prepends an explicit workflow-topology directive (one
   start + >=1 end node, no answer nodes) to the generator instruction, and
   retries ONCE on an error/empty result with the specific error fed back as
   a corrective nudge -- covering the terminal-node failure the shared
   generator skips.

2. handle_plan_approval refuses to fake success: when build_nodes yields zero
   create_node intents it surfaces an honest error and stays in
   build.plan_approval (retryable) without deleting the placeholder, instead
   of emptying the canvas and claiming a build. A loop-back re-approve still
   returns the fixed create intents (only filtered as already-present), so
   zero create intents unambiguously means a genuine generation failure.

Adds regression tests for both. Note: part 1 improves LLM reliability
(verifiable live); part 2 is the deterministic guarantee against the
false-success empty canvas.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 14:39:56 -07:00
twwu 3152ba3faa Merge branch 'main' into feat/dify-builder 2026-09-01 17:09:54 +08:00
Charles YaoandClaude Opus 4.8 1ef298e5fd Fix dify-builder contract gen script cwd and stale docstring paths
uv run --project selects the venv but doesn't chdir, so invoking
gen-dify-builder-contract from packages/contracts (as autofix.yml does)
raised ModuleNotFoundError: No module named 'core'. Switch to
--directory so uv chdirs into api/ before running the module. Also
update two contract_gen.py docstrings that still pointed at the old
web/app/components/dify-builder/contract/types.ts output path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-01 00:06:31 -07:00
yyh 8e064ffe98 chore: upgrade Node.js runtime to 24 LTS (#41573) 2026-09-01 06:57:38 +00:00
Charles YaoandClaude Opus 4.8 cad5919220 refactor(dify-builder): generate contract TS into @dify/contracts/dify-builder
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-31 23:34:45 -07:00
Keith 566b8857dd refactor(models): remove legacy db.session property wrappers on Dataset (#41569) 2026-09-01 06:28:24 +00:00
elyar1124 3ed28dce33 refactor(models): pass session into DocumentSegment and AppDatasetJoin accessors (#41568) 2026-09-01 06:24:04 +00:00
Eddy ZHANG 6411d6235c refactor(service_api): dep-inject query params with @model_validate (#41562) 2026-09-01 05:55:50 +00:00
Charles YaoandClaude Opus 4.8 9fe2e2a3fa feat(dify-builder): response_mode streaming returns SSE on create/action/message POSTs
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-31 22:18:42 -07:00
Charles YaoandClaude Opus 4.8 52d241d754 feat(dify-builder): streaming create_fix/build/edit_session with subscribe-before-dispatch
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-31 22:18:42 -07:00
Charles YaoandClaude Opus 4.8 6888282e95 feat(dify-builder): subscribe-before-dispatch streaming submit_action/message
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-31 22:18:42 -07:00
Charles YaoandClaude Opus 4.8 fa4921eff0 feat(dify-builder): stream_advance_frames terminal-aware SSE generator
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-31 22:18:42 -07:00
Charles YaoandClaude Opus 4.8 390eea61fb feat(dify-builder): terminal state frame carries the full SessionView
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-31 22:18:42 -07:00
Eddy ZHANG 1977355dd1 refactor(console): dep-inject model provider payloads with @model_validate (#41539) 2026-09-01 04:24:45 +00:00
Joel 5cbc42cd38 chore: Revert "feat: use app.acl.access_point_manage to control access point page access" (#41563) 2026-09-01 03:46:03 +00:00
twwu e3cbd7b90b fix(api): linearize Dify Builder migrations 2026-09-01 11:25:21 +08:00
twwu 22be55af5f feat: redesign app builder fix flow 2026-08-31 18:18:30 +08:00
zyssyz123andautofix-ci[bot] 762019a160 fix(workflow): block manual runs for trigger workflows (#41519)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-31 09:30:52 +00:00
Asuka Minato 1952cff091 test: migrate model and agent sessions to SQLite (#40087) 2026-08-31 05:57:40 +00:00
Asuka Minato f8f71fdc68 test: migrate audit findings sessions and ORM models to SQLite (#40551) 2026-08-31 05:55:38 +00:00
Asuka Minato 9398482b53 test: migrate console dataset sessions and ORM models to SQLite (#40521) 2026-08-31 05:55:12 +00:00
Asuka Minato 5db79a77e4 test: migrate advanced chat generator sessions and ORM models to SQLite (#40585) 2026-08-31 05:51:30 +00:00
twwu cb53f02905 Merge branch 'main' into feat/dify-builder 2026-08-31 13:31:50 +08:00
d25e2b51fc refactor(api): decouple onboarding and notification services (#40759)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: hjlarry <hjlarry@163.com>
2026-08-31 04:37:07 +00:00
Wu Tianwei 7167d7d662 fix(rbac): grant agent access to all legacy roles (#41511) 2026-08-31 03:33:09 +00:00
Byron.wangandhjlarry 9e07c2dac6 refactor(api): extract email registration application service (#41108)
Co-authored-by: hjlarry <hjlarry@163.com>
2026-08-31 03:22:01 +00:00
wangxiaoleiandtwwu 6a00c23e49 feat: use app.acl.access_point_manage to control access point page access (#41462)
Co-authored-by: twwu <twwu@dify.ai>
2026-08-31 03:05:19 +00:00
Xiyuan Chen 750810ea81 fix(api): keep workspace owner consistent on ownership transfer (#41267) 2026-08-31 02:51:19 +00:00
zyssyz123 ad86351cc1 fix(agent): reject incompatible session snapshots (#41447) 2026-08-31 02:26:07 +00:00
Eddy ZHANG 6130f081e0 refactor(console): dep-inject account payloads with @model_validate (#41500) 2026-08-31 00:52:10 +00:00
Eddy ZHANG 8894b09c3b refactor(web): dep-inject payloads with @model_validate (#41501) 2026-08-31 00:50:12 +00:00
Charles YaoandClaude Opus 4.8 ba7692e2e9 feat(dify-builder): log build_nodes empty/failed generation and starved resource sources
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-30 10:03:48 -07:00
Charles YaoandClaude Opus 4.8 6f27a709ba feat(dify-builder): log llm-agent model-resolution failure once per advance
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-30 10:03:48 -07:00
Charles YaoandClaude Opus 4.8 133e8fdc0c refactor(dify-builder): remove unused propose_build_repair from agent Protocol
It was stubbed to [] in LlmBuilderAgent, canned in PlaceholderAgent, and never
called by any handler — the Build failure path reuses Fix cognition (diagnose +
propose_repair). Removed from the DifyBuilderAgent Protocol, both implementations,
and all test doubles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-30 10:03:48 -07:00
Charles YaoandClaude Opus 4.8 d2cfaf7f72 fix(dify_builder): narrow input-failure signals, fix build delete/create id collision
Final-review fix wave for the testdata-gate + start-selector slice:

- I1 (Important): is_input_failure's signal list included the bare
  "required" (and generic "variable not found"), which also fire on
  config/runtime faults unrelated to test inputs -- misrouting those
  failures to the *_AWAIT_TESTDATA gate, where the diagnosed auto-repair
  is never offered and re-running just loops at the gate. Narrowed
  _INPUT_FAILURE_SIGNALS to ("file variable", "not provided", "missing
  input"), favoring precision per the spec's ambiguous-failure ->
  config-repair safe default. The real file-input E2E error ("File
  variable not found for selector: [...]") still matches via "file
  variable".

- M2 (Minor, latent): handle_plan_approval's from-scratch delete-then-
  create-filter path could drop a generator create_node/connect that
  reuses a just-deleted placeholder start's id, since _already_present
  compared against the PRE-delete existing_node_ids/existing_edges --
  delete with no re-create, silently vanishing the node. Deleted ids are
  now excluded from that comparison set; the loop-back path (no deletes)
  is unaffected.

- Cleanups: state.py's Build/Edit state-count comments (14->15, 9->10,
  verified against the actual enum members), FormCard's docstring now
  lists the "testdata" variant, and handle_plan_approval binds
  current_graph's nodes to one local instead of calling .get() 3x and
  documents the delete-placeholder branch.

Tests: extended test_is_input_failure_matches_input_signals's sibling
with a config "required" case (red before the signal-list fix, green
after), and added a plan_approval test where the generator's create_node
reuses the deleted placeholder start's id (red before the id-exclusion
fix -- a dangling connect ValueError -- green after).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-30 10:03:48 -07:00
Charles YaoandClaude Opus 4.8 db150d1a43 feat(dify-builder): Edit live test reuses prepared input, routes input-failures to testdata gate
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-30 10:03:47 -07:00
Charles YaoandClaude Opus 4.8 ef88f6532c feat(dify-builder): EDIT_AWAIT_TESTDATA gate + run_affected_tests routing
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-30 10:03:47 -07:00
Charles YaoandClaude Opus 4.8 cea65957bb feat(dify-builder): Build live test reuses prepared input, routes input-failures to testdata gate
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-30 10:03:47 -07:00
Charles YaoandClaude Opus 4.8 4f6a5f07b7 feat(dify-builder): BUILD_AWAIT_TESTDATA gate + run_test routing
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-30 10:03:47 -07:00
Charles YaoandClaude Opus 4.8 1dda1d3326 feat(dify-builder): is_input_failure + testdata_form_fields core helpers
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-30 10:03:47 -07:00
Charles YaoandClaude Opus 4.8 20d932177c fix(dify-builder): drop draft placeholder start on from-scratch build
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-30 10:03:47 -07:00
Charles YaoandClaude Opus 4.8 86341638df fix(dify-builder): keep generator node ids in graph_translate (no start rename)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-30 10:03:47 -07:00
Eddy ZHANG 884ece570e refactor(service_api): dep-inject dataset payloads with @model_validate (#41490) 2026-08-30 15:06:36 +00:00
Eddy ZHANG 8b3c2ee274 refactor(service_api): dep-inject app payloads with @model_validate (#41491) 2026-08-30 12:51:50 +00:00
twwu 433046e0de Merge branch 'main' into feat/dify-builder 2026-08-30 14:25:22 +08:00
Charles YaoandClaude Opus 4.8 8b640e44de Fix Dify Builder live-test escape paths to reset stale test inputs
Clear fc.test_input_ref and fc.verify_run_id on the four re-plan/revert
escape branches in Build and Edit (handle_review's continue_adjusting
and handle_reverted's retry_after_revert) so a rebuild+retest
regenerates fresh schema-shaped mock inputs instead of reusing the
first build's stale ones -- the approve_repair retest path is left
untouched since it must fairly retest against the same failing case.
Also corrects three doc/comment mismatches (llm_agent's 12->13 method
count, an await_repair docstring describing a branch that doesn't
exist, and state.py's Build state-count banner), and adds tests for
the run_draft-raises degrade path and Build/Edit pass-path canvas
event symmetry.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-29 19:26:48 -07:00
Charles YaoandClaude Opus 4.8 53f805dbf7 test(dify-builder): restore canvas + summary-variant assertions on Edit test pass path
Task B2 review found that removing the old canned test_test_affected_paths_
emits_result_and_reaches_review test dropped two pass-path assertions that
none of the 4 replacement tests reproduced: that the success path fires both
the mark_test_success and mark_review_ready canvas events, and that the
emitted SummaryCard's variant is "review". Restore both onto
test_edit_test_pass_goes_to_review_with_real_run so a regression on either
point is caught again.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-29 19:11:20 -07:00