Commit Graph
7821 Commits
Author SHA1 Message Date
Charles YaoandClaude Opus 4.8 f623dc3fe1 feat(dify_builder): recover an interrupted working step via Retry/Start over
When a session crashes mid working-step (e.g. build.publish; the async advance
raised and released the lock), it was a locked dead-end: working states surface
no UI actions and the composer locked with no way forward.

- Surface a RecoveryRef offer (can_continue=Retry, can_restart=Start over,
  recovery_class="") on an interrupted working-state view -- built directly so a
  real drift class still wins.
- Allow recovery_continue / recovery_restart at an interrupted working state in
  _internal_action_allowed. recovery_continue returns the working state
  (non-settled) so the runner re-runs the stalled handler; recovery_restart
  resets working fields and re-enters the entry state -- both reuse existing
  recovery machinery, no new action kinds / no runner change.

Adds unit tests (offer surfaced, allowance) + regression tests (recovery_continue
re-runs handle_publish and advances; recovery_restart resets to entry state;
repeat-failure re-surfaces the offer with no wedge).

This reconciler was reviewed as a standalone plan on the pre-merge base; here it
is re-applied onto feat/dify-builder after PR #41677 merged in the reworked
service.py + _internal_action_allowed gate (which makes the allowance necessary).
The apply_repair idempotency + delete-guard commits (safe fix.apply Retry) land
alongside it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-04 00:07:14 -07:00
Charles YaoandClaude Opus 4.8 3dcb06db01 fix(dify-builder): exclude in-batch delete_node ids from apply_repair idempotency filter
apply_repair's already-present filter (added for interrupted-step Retry
idempotency) compared create_node/connect intents against before_graph
alone, with no awareness of delete_node intents in the same batch. A
from-scratch build sends delete_node(placeholder_start) + create_node(same
id) in one apply_repair call to replace the canvas's default placeholder
start with the generator's own start node -- the filter dropped the
create_node as "already present" while the delete_node still ran, deleting
the start node with no re-create, so the following connect raised
ValueError: node not found. Mirror handlers_build.py's existing M2 guard:
subtract in-batch delete_node targets from the present-node/edge sets
before filtering, so a delete+recreate of the same id in one batch survives.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-04 00:01:42 -07:00
Charles YaoandClaude Opus 4.8 61b35a36b7 fix(dify_builder): make apply_repair idempotent for already-present create/connect
Drops create_node intents whose id already exists and connect intents whose
edge already exists (referenced against the original draft graph), so a
fix.apply Retry re-applying the same intents is a clean no-op instead of a
duplicate/ValueError. graph_ops validation (raise on a genuinely fresh
duplicate id) is preserved.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-04 00:01:42 -07:00
twwu 537d2a3178 Merge branch 'main' into feat/dify-builder 2026-09-04 09:44:01 +08:00
Keith e6a38fd793 refactor(models): remove legacy db.session property wrappers on Document (#41721) 2026-09-03 13:34:49 +00:00
zyssyz123 a702b3bb2b fix(agent): surface missing tool credentials (#41726) 2026-09-03 08:53:55 +00:00
Byron.wangandautofix-ci[bot] 692010f0fc refactor(api): decouple console OAuth flow from legacy account services (#41188)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-09-03 08:47:14 +00:00
Byron.wang b015aa416f refactor(api): extract account login service and consolidate adapters (#41184) 2026-09-03 06:20:21 +00:00
非法操作 ba1d5ba172 refactor(api): centralize remote file handling (#41627) 2026-09-03 06:00:13 +00:00
zyssyz123 688107c3e5 fix(api): bound suggested question generation latency (#41705) 2026-09-03 05:02:09 +00:00
非法操作 d8c3f7c5ee refactor(openapi): inject file upload service (#41606) 2026-09-03 04:42:31 +00:00
非法操作 69484a07e1 refactor(console): inject file service (#41603) 2026-09-03 04:42:30 +00:00
非法操作 5f4b1f867d refactor(web): inject file upload service (#41586) 2026-09-03 04:42:30 +00:00
Eddy ZHANG fc7193cf04 refactor(service_api): dep-inject the dataset create payload with @model_validate (#41651) 2026-09-03 03:52:41 +00:00
非法操作 ab0e92b893 refactor(service-api): inject file upload service (#41585) 2026-09-03 03:41:45 +00:00
twwu c00852cf97 fix(api): linearize Dify Builder migration after main 2026-09-03 11:28:53 +08:00
twwu a257ac4dee Merge branch 'main' into feat/dify-builder 2026-09-03 11:12:22 +08:00
dependabot[bot] 907bc2558b chore(deps): bump transformers from 5.5.0 to 5.10.1 in /api (#41609)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-03 01:50:39 +00:00
Eddy ZHANG 95a6a14ed5 refactor(console,web): dep-inject query params with @model_validate (#41646) 2026-09-03 01:50:22 +00:00
Byron.wangandautofix-ci[bot] be7d11ca1d refactor(api): extract forgot password application service (#41111)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-09-03 01:38:59 +00:00
Charles YaoandClaude Opus 4.8 2b4df02305 fix(dify_builder): close SSE subscription even when the response is never iterated
progress_bus.subscribe() eagerly enters the pub/sub subscription (opening a
Redis connection + starting a listener thread) BEFORE the SSE generator
exists, so the subscribe completes before the Celery advance can publish.
But the only close() lived in the generator's finally -- which Python does
not run if the generator is never started. A streaming Response dropped
before its first frame (client aborted, or an after_request/teardown error)
therefore leaked the connection + thread until process restart.

stream_advance_frames now returns a small _ClosingFrameStream wrapper whose
close() closes the subscription directly (idempotent); the WSGI server calls
close() on the response iterable even on early disconnect, so cleanup fires
regardless of iteration. The inner generator keeps its own finally for the
iterated/disconnect paths, so this is strictly additive -- no happy-path
change. All seven call sites get it unchanged.

Adds a regression test (never-iterated stream -> close() -> subscription closed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-03 08:48:23 +08:00
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
Asuka Minato 8129555642 chore: Site to typebase (#35632) 2026-09-02 14:44:08 +00:00
YungLeandautofix-ci[bot] 3cd1fc098c feat: allow knowledge base API keys to be scoped to a single dataset (#37569)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-09-02 10:30:42 +00:00
Yunlu Wen b1eafb0d82 fix: validate rule for provider scoped credentials (#41659) 2026-09-02 10:07:44 +00:00
Ingram Zandautofix-ci[bot] a1a10f17e3 fix(dify-agent): harden E2B binding lifecycle (#41623)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-09-02 09:47:24 +00:00
非法操作 59ee8878f9 refactor(api): require active workspace in request context (#41280) 2026-09-02 06:54:47 +00:00
Wu Tianweiandfatelei 82d86dcf98 feat: app access point permission (#41631)
Co-authored-by: fatelei <fatelei@gmail.com>
2026-09-02 06:34:33 +00:00
QuantumGhost 324ee5f036 fix(api): tolerate workflow pause snapshot cleanup failure (#41581) 2026-09-02 04:33:04 +00:00
Eddy ZHANG 4d9bda7422 refactor(inner_api): dep-inject request payloads with @model_validate (#41575) 2026-09-02 03:40:46 +00:00
Eddy ZHANG a5445f2424 refactor(service_api): dep-inject segment payloads with @model_validate (#41571) 2026-09-02 02:59:30 +00:00
dependabot[bot] 334a3043bc chore(deps): bump pypdf from 6.15.0 to 6.16.1 in /api (#41607)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-02 01:56:41 +00:00
Xiyuan Chenandyunlu.wen 93dae7d8a0 fix(rbac): let agent.manage operate every agent page (#41583)
Co-authored-by: yunlu.wen <yunlu.wen@dify.ai>
2026-09-02 01:45:42 +00:00
dependabot[bot] a3dbf9293a chore(deps-dev): bump nltk from 3.10.0 to 3.10.3 in /api (#41602)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-02 01:20:41 +00:00
Byron.wangandautofix-ci[bot] c4ea406586 refactor(api): decouple system features and web adapters (#40772)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-09-01 11:50:52 +00:00
Asuka Minato 7978352262 test: migrate dataset download sessions and ORM models to SQLite (#40630) 2026-09-01 09:28:50 +00:00
Asuka Minato 980a9d4ed4 test: migrate dataset retrieval sessions and ORM models to SQLite (#40548) 2026-09-01 09:28:33 +00:00
Asuka Minato d337c59916 test: migrate workspace member sessions and ORM models to SQLite (#40523) 2026-09-01 09:27:46 +00:00
Asuka Minato c45e5386fb test: migrate agent-v2 workflow sessions and ORM models to SQLite (#40514) 2026-09-01 09:25:46 +00: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