Compare commits

...

987 Commits

Author SHA1 Message Date
zhaohao1004
ce47204564 fix(retention): verify archive marker deletion 2026-09-02 12:26:17 +08:00
zhaohao1004
2de2d52bbd fix(retention): tolerate nullable archive schema evolution 2026-09-02 12:19:01 +08:00
yyh
8707d0c82f docs(e2e): refine Playwright and Cucumber skill guidance (#41617) 2026-09-02 03:45:41 +00:00
Eddy ZHANG
4d9bda7422 refactor(inner_api): dep-inject request payloads with @model_validate (#41575) 2026-09-02 03:40:46 +00:00
yyh
88c64a8db9 refactor(web): migrate access point mutations (#41614) 2026-09-02 03:17:03 +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 Chen
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
yyh
ea98d38c3d refactor(web): migrate webhook table input (#41612) 2026-09-02 01:44:52 +00:00
yyh
18ac946e2b refactor(web): migrate dataset settings name input (#41611) 2026-09-02 01:44:51 +00:00
yyh
baf629dd36 refactor(web): migrate external API selection input (#41610) 2026-09-02 01:44:51 +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
yyh
3f982e3dc8 ci(e2e): shard pull request browser tests (#41596) 2026-09-02 01:19:08 +00:00
yyh
6bc7f01261 fix(web): announce agent draft status (#41595) 2026-09-01 11:53:05 +00:00
Byron.wang
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
QuantumGhost
d6e4f48526 fix(web): merge workflow tool outputs from all End nodes (#41517)
Co-authored-by: twwu <twwu@dify.ai>
2026-09-01 08:50:37 +00:00
QuantumGhost
27c2f058fe fix(web): publish workflow before creating tool (#41528) 2026-09-01 07:52:07 +00:00
yyh
8e064ffe98 chore: upgrade Node.js runtime to 24 LTS (#41573) 2026-09-01 06:57:38 +00:00
zyssyz123
fe39211aac fix(agent): bound Redis run event streams (#41566)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-09-01 06:47:16 +00:00
Joel
770b83d9cc fix: handle published workflow request failures in access points (#41572) 2026-09-01 06:37:25 +00: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
Joel
fdca3e2a1a chore: enforce titles on CSS-truncated elements (#41438) 2026-09-01 06:18:53 +00:00
Eddy ZHANG
6411d6235c refactor(service_api): dep-inject query params with @model_validate (#41562) 2026-09-01 05:55:50 +00:00
Eddy ZHANG
1977355dd1 refactor(console): dep-inject model provider payloads with @model_validate (#41539) 2026-09-01 04:24:45 +00:00
yyh
520e5e2beb chore(deps): upgrade workspace dependencies (#41564) 2026-09-01 04:19:06 +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
yyh
765e6338d2 fix(plugin): prevent install dialog error overflow (#41561) 2026-09-01 03:34:23 +00:00
yyh
62221bf8b8 refactor(web): align skills card semantics (#41559) 2026-09-01 02:36:21 +00:00
yyh
8f2ff3a8fb refactor(plugins): migrate credential rename input (#41552) 2026-09-01 01:44:44 +00:00
yyh
f92f7e92c3 refactor(workflow): migrate email subject input (#41551) 2026-09-01 01:44:43 +00:00
yyh
72458d5750 refactor(workflow): migrate schedule cron input (#41550) 2026-09-01 01:44:43 +00:00
Xiyuan Chen
ce801f4445 fix(web): hide Open in Explore for SSO-restricted apps (#41518)
Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
2026-09-01 01:10:03 +00:00
yyh
57144b0094 docs(frontend): clarify transient state ownership (#41541) 2026-08-31 13:37:22 +00:00
Xiyuan Chen
b71dcb8253 fix(web): reset test-email sender state when reopening the modal (#41515)
Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
2026-08-31 12:15:40 +00:00
zyssyz123
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
Yunlu Wen
39f06b6f05 chore(dify-agent): make local dev work with defaults out of the box (#41533)
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-31 08:37:30 +00:00
-LAN-
d0a86cfd4e fix(workflow): allow human input in iteration and loop (#40061) 2026-08-31 08:28:17 +00:00
Joel
336dd0b8c0 fix: hide chat features drawer while opener dialog is active (#41530) 2026-08-31 08:01:55 +00:00
Jingyi
6da1b473e6 fix(web): align tool plugin card layout (#41525) 2026-08-31 07:25:06 +00:00
Joel
f021ee4dc0 fix: prevent the exit versions button from shrinking (#41527) 2026-08-31 07:23:45 +00:00
Joel
280f81757d fix: stabilize node block selectors and restore start tabs (#41523) 2026-08-31 06:58:56 +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
Jingyi
02222e8fce fix(web): preserve plugin footer text layout (#41514) 2026-08-31 05:50:29 +00:00
yyh
5a5b9c6fec fix(web): make plugin detail drawer non-modal (#41473) 2026-08-31 05:46:55 +00:00
Byron.wang
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
Coding On Star
c6ca395042 fix(web): make registration tracking consent-safe and retryable (#41365)
Co-authored-by: CodingOnStar <hanxujiang@dify.com>
2026-08-31 03:39:37 +00:00
Wu Tianwei
7167d7d662 fix(rbac): grant agent access to all legacy roles (#41511) 2026-08-31 03:33:09 +00:00
Byron.wang
9e07c2dac6 refactor(api): extract email registration application service (#41108)
Co-authored-by: hjlarry <hjlarry@163.com>
2026-08-31 03:22:01 +00:00
wangxiaolei
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
非法操作
b70ad7d424 fix(web): show DSL import warning details (#41502) 2026-08-31 02:36:32 +00:00
zyssyz123
ad86351cc1 fix(agent): reject incompatible session snapshots (#41447) 2026-08-31 02:26:07 +00:00
dependabot[bot]
8b8031710b chore(deps): bump anthropics/claude-code-action from 1.0.199 to 1.0.210 in the github-actions-dependencies group (#41504)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-31 01:25:59 +00:00
yyh
94dff4dddc fix(web): unify tool plugin selection state (#41470) 2026-08-31 01:24:49 +00:00
yyh
17ae89ff22 fix(e2e): target agent roster list items (#41453) 2026-08-31 01:24:04 +00:00
yyh
fce29e6f6a fix(web): refine agent dialog form sessions (#41492) 2026-08-31 01:24:03 +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
yyh
bf64390d7c revert(web): revert dataset button a11y changes (#41493) 2026-08-30 16:00:14 +00:00
Eddy ZHANG
884ece570e refactor(service_api): dep-inject dataset payloads with @model_validate (#41490) 2026-08-30 15:06:36 +00:00
LuckTerence
9d396524b9 fix(web): improve a11y of dataset clickable divs with native buttons (#41319) 2026-08-30 13:00:42 +00:00
Eddy ZHANG
8b3c2ee274 refactor(service_api): dep-inject app payloads with @model_validate (#41491) 2026-08-30 12:51:50 +00:00
Weike Zhang
02f9b3ca7c refactor: pass db.session explicitly in instruction_modify_workflow (#37403) (#40827) 2026-08-30 00:48:00 +00:00
jjj-n
09054169c4 refactor(models): pass session into Workflow accessors (#41464) 2026-08-29 14:28:15 +00:00
Asuka Minato
0f3cde8120 test: migrate application DSL sessions and ORM models to SQLite (#40554) 2026-08-29 14:06:07 +00:00
Asuka Minato
2bdcbe96c5 test: enforce centralized config overrides (#40869) 2026-08-29 14:05:35 +00:00
Asuka Minato
3824323fe7 test: centralize core and service config overrides (#40868) 2026-08-29 14:05:34 +00:00
lin
1264d29a4f chore: remove unnecessary type conversions (#41454) 2026-08-29 07:04:18 +00:00
Terminator666666
f8dd276e2c refactor(controllers/console): dep-inject workflow payloads with @model_validate (#41244)
Co-authored-by: Terminator666666 <Terminator666666@users.noreply.github.com>
2026-08-28 14:49:46 +00:00
Eddy ZHANG
37988de678 refactor(service_api): dep-inject payloads with @model_validate (#41374) 2026-08-28 14:47:18 +00:00
Asuka Minato
92110e1982 test: centralize controller and storage config overrides (#40867) 2026-08-28 14:47:17 +00:00
Asuka Minato
d8e7a97b25 test: centralize account and feature config overrides (#40864) 2026-08-28 14:47:16 +00:00
Keith
e6fc0a8ba8 refactor(models): pass session into WorkflowAppLog accessors (#41440) 2026-08-28 14:32:27 +00:00
yyh
28e9a52ea5 feat(web): enhance app and agent card interactions (#41449) 2026-08-28 12:24:56 +00:00
Joel
efd90de70a fix: avoid duplicate error toast when applying agent build drafts (#41442) 2026-08-28 09:18:10 +00:00
Benjamin
aa208d2dd7 fix(web): give the favicon a single owner in root metadata (#41433)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-28 08:57:04 +00:00
yyh
11bb82c731 fix(web): align agent roster card interactions (#41436) 2026-08-28 08:50:30 +00:00
yyh
78c85ae7c1 fix(agent): add roster publication status contract (#41435)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-28 08:50:30 +00:00
Joel
4c414988ee fix: improve accessibility across the apps list (#41393)
Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
2026-08-28 07:55:59 +00:00
Xiyuan Chen
3bc4ac44e5 fix(ci): correct difyctl release and e2e workflow gates (#41355) 2026-08-28 06:56:25 +00:00
Jingyi
94fdda18e2 fix(web): prevent tool card footer clipping (#41430) 2026-08-28 05:36:13 +00:00
yyh
0b11d34d4b fix(web): align web app sidebar spacing (#41425) 2026-08-28 05:34:32 +00:00
wangxiaolei
ff5d431efd feat: hide skill_entry when use has no skill.view permission (#41429) 2026-08-28 05:13:38 +00:00
alanhuangyoo
97b5d8092c ci: run the dify-agent test suite (#41327) 2026-08-28 05:09:34 +00:00
Wu Tianwei
f7d6cd1afe fix(web): block resource access for Agent apps (#41424) 2026-08-28 03:43:48 +00:00
Wu Tianwei
1971450ad8 fix: protect workspace owners in resource access (#41423) 2026-08-28 03:03:40 +00:00
Keith
c8606db16b refactor(models): pass session into ChildChunk accessors (#41370)
Co-authored-by: ke-yu <ke-yu@pepabo.com>
2026-08-28 02:30:10 +00:00
chenshiyang
654324c0d9 refactor(models): pass session into PipelineCustomizedTemplate.created_user_name (#41394)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-28 02:26:41 +00:00
huyua9
650f8880ea docs: correct UUIDv7 helper docstring (#41419)
Co-authored-by: huyua9 <huyua9@users.noreply.github.com>
2026-08-28 02:26:40 +00:00
yyh
f7e71ca9e1 refactor(web): simplify pricing components (#41416) 2026-08-28 01:37:01 +00:00
yyh
290acf1b73 fix(ui): keep scroll area focus indicator visible (#41404) 2026-08-28 01:37:00 +00:00
-LAN-
458c96d5ba fix(api): preserve tracing configuration boundaries (#41403) 2026-08-27 22:11:32 +08:00
Benjamin
2a554ab2d1 perf(web): virtualize the Web Apps sidebar list again (#41397)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
2026-08-27 13:45:50 +00:00
Asuka Minato
3ce262de05 test: migrate agent service sessions and ORM models to SQLite (#40598) 2026-08-27 12:15:36 +00:00
Asuka Minato
3ea5f38e92 test: migrate human input sessions and ORM models to SQLite (#40597) 2026-08-27 12:15:07 +00:00
lei_lei
8c25190713 fix(api): raise Socket.IO max_http_buffer_size for large workflows (#41347) 2026-08-27 11:48:42 +00:00
yyh
9c16c86597 revert(web): restore Agentation devtool (#41387) 2026-08-27 09:09:44 +00:00
wangxiaolei
d84088ef74 feat: new user add automatic add to app / dataset whitelist (#41363) 2026-08-27 08:51:05 +00:00
yyh
a38ddd9d02 fix: align documentation links with stable anchors (#41384) 2026-08-27 08:38:41 +00:00
Joel
d94204ec33 feat: track inline agent and preview mode events (#41373) 2026-08-27 08:09:09 +00:00
HelloSrauker
1db542c706 fix(workflow): correct loop boolean break condition values (#41186) 2026-08-27 08:02:52 +00:00
yyh
15021ad350 chore(web): remove Agentation devtool (#41372) 2026-08-27 07:54:27 +00:00
yyh
59383e88c2 fix(web): refine agent configure section states (#41371) 2026-08-27 07:51:07 +00:00
wangxiaolei
05b00574aa chore: add permission check back (#41369) 2026-08-27 07:45:50 +00:00
yyh
5aac67f570 test(e2e): wait for apps console readiness (#41357) 2026-08-27 07:40:23 +00:00
Joel
1be72af661 fix: allow publishing workflows with legacy Agent nodes (#41368) 2026-08-27 07:26:48 +00:00
Asuka Minato
1ccac4792c test: migrate knowledge file access sessions and ORM models to SQLite (#40596) 2026-08-27 07:19:20 +00:00
Asuka Minato
d67a8323c5 test: migrate agent observability sessions and ORM models to SQLite (#40588) 2026-08-27 07:18:58 +00:00
Asuka Minato
ef20a16a2f test: migrate explore installed app sessions and ORM models to SQLite (#40525) 2026-08-27 07:18:32 +00:00
Asuka Minato
1efc71c624 test: migrate Service API dataset segment sessions and ORM models to SQLite (#40517) 2026-08-27 07:17:41 +00:00
Joel
54298abf2d fix: improve home page accessibility (#41310)
Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
2026-08-27 07:03:01 +00:00
非法操作
735d814dc0 fix(web): use management provider list for MCP integrations (#41360) 2026-08-27 06:49:47 +00:00
QuantumGhost
3e12f0b9fb fix(api): ignore broken pipe during app stop checks 🤖🤖🤖 (#41356) 2026-08-27 06:39:06 +00:00
yyh
85b4626ac6 fix(web): route Agent V2 documentation links correctly (#41353) 2026-08-27 06:20:03 +00:00
yyh
8266d741e8 refactor(web): migrate tracing inputs (#41341) 2026-08-27 06:13:10 +00:00
yyh
3765a41b8c refactor(web): migrate workflow variable inputs (#41340) 2026-08-27 05:43:10 +00:00
wangxiaolei
6a1b23935f chore: remove permission check (#41349) 2026-08-27 05:29:38 +00:00
非法操作
bf54dd7814 refactor(api): remove unused workflow archived logs endpoint (#41345) 2026-08-27 03:48:57 +00:00
dependabot[bot]
1aa7ee29a1 chore(deps): bump h2 from 4.3.0 to 4.4.1 in /api (#40120)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-27 03:12:26 +00:00
非法操作
a9319c86ee refactor(api): extract workflow run archive application service (#41253) 2026-08-27 02:41:43 +00:00
非法操作
5a6191b96b refactor(api): extract workflow statistic query service (#41271) 2026-08-27 02:41:02 +00:00
yyh
ce31cdc585 refactor(web): migrate metadata inputs (#41339) 2026-08-27 02:40:08 +00:00
非法操作
32981687dd refactor: remove unused workflow run export endpoint (#41335) 2026-08-27 02:38:27 +00:00
非法操作
58d71bf9c9 fix(web): align model provider access permissions (#41329) 2026-08-27 02:27:57 +00:00
-LAN-
82520c144f fix(api): migrate legacy model types during upgrade (#41326) 2026-08-27 02:00:33 +00:00
Pranav Agarwal
0d05eae517 fix(api): enforce RBAC permission on agent composer GET endpoint (#41324) (#41325) 2026-08-26 20:09:25 +00:00
yyh
c8e29d9a7d fix(web): preserve link semantics in button-styled navigation (#41312) 2026-08-26 10:50:06 +00:00
Xin Zhang
638dfd77a4 fix: update secret environment variable description (#41309) 2026-08-26 10:08:30 +00:00
wangxiaolei
0047522b0d feat: add command cli to migration rbac scope to automatic_include_workspace_members (#41304) 2026-08-26 09:10:22 +00:00
Joel
ac23430aca fix: improve login and signup accessibility (#41301) 2026-08-26 08:16:15 +00:00
yyh
06482af260 test(e2e): stabilize Agent access toggles (#41282) 2026-08-26 07:56:28 +00:00
Byron.wang
30e6069851 refactor(api): thin OAuth controllers and extract application services (#40692) 2026-08-26 07:33:37 +00:00
github-actions[bot]
021d5ceae7 chore(i18n): sync translations with en-US (#41291)
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
2026-08-26 07:31:34 +00:00
Wu Tianwei
73dd8739ef feat: optimize resource access config logic (#41164)
Co-authored-by: fatelei <fatelei@gmail.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-26 07:18:57 +00:00
林玮 (Jade Lin)
f5aaa50a30 fix(auth): normalize Gmail registration emails (#41249) 2026-08-26 07:14:27 +00:00
林玮 (Jade Lin)
8c9f248520 fix(api): attribute Skill Builder credit usage (#41290) 2026-08-26 07:02:45 +00:00
Taranum Wasu
6e0e32848e fix(human-input): align backend timeout handle with frontend DSL (#40746)
Co-authored-by: Taranum01 <50813317+Taranum01@users.noreply.github.com>
Co-authored-by: QuantumGhost <obelisk.reg+git@gmail.com>
2026-08-26 06:47:14 +00:00
非法操作
6ba29b3f0c chore(web): remove retired forum entry (#41289) 2026-08-26 06:47:13 +00:00
lei_lei
119e6af2a9 fix(api): honor DELETE JSON body in model_validate (#41288) 2026-08-26 06:38:13 +00:00
非法操作
c563528a2d refactor(api): standardize compliance downloads (#41057) 2026-08-26 06:32:13 +00:00
非法操作
c4ace15afd refactor(api): extract console app site command boundary (#41216) 2026-08-26 06:31:06 +00:00
ccl125
d5a8ace1c4 fix(rag-pipeline): mark credential-free datasources as authorized (#39772)
Co-authored-by: ccl125 <ccl125@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: FFXN <31929997+FFXN@users.noreply.github.com>
2026-08-26 05:44:10 +00:00
heyszt
86f8b847e9 fix(api): clean multimodal attachments in batch deletion (#41256) 2026-08-26 05:10:28 +00:00
Stephen Zhou
1c6f0a0388 fix(api): restore Service API OpenAPI semantics (#41274) 2026-08-26 05:05:36 +00:00
wangxiaolei
c937fcb21a feat: go to anything check enable skill (#41281) 2026-08-26 04:46:10 +00:00
yyh
0a1ce09dfb refactor(web): migrate external knowledge input (#41278) 2026-08-26 04:44:52 +00:00
yyh
b9ac4d3cb1 refactor(web): migrate dataset settings input (#41277) 2026-08-26 04:44:51 +00:00
yyh
e4cd2c72ad refactor(web): migrate document metadata input (#41276) 2026-08-26 04:44:50 +00:00
Joel
dfe396fb64 fix: separate WebApp analytics from console page tracking (#41251) 2026-08-26 03:02:38 +00:00
Pranav Agarwal
6b5952425d fix(api): enforce RBAC permission on agent app detail GET endpoint (#41264) (#41265) 2026-08-26 02:51:13 +00:00
samzong
1299d99b2d feat(cli): add a compact command map for agent discovery (#41226)
Signed-off-by: samzong <samzong.lu@gmail.com>
2026-08-26 01:13:07 +00:00
yyh
36dfc5abd3 fix(web): upgrade Next.js to 16.3.3 (#41262) 2026-08-26 00:32:30 +00:00
yyh
c7520d7c71 refactor(ci): trim redundant autofix work (#41259) 2026-08-25 13:10:06 +00:00
yyh
798a238e63 fix(web): align goto anything autocomplete behavior (#41258) 2026-08-25 12:39:07 +00:00
yyh
db5121828e fix(agent-v2): refine access card interactions (#41254) 2026-08-25 12:25:49 +00:00
yyh
ed184a6632 fix(web): restore AI credits icon (#41257) 2026-08-25 12:22:49 +00:00
Stephen Zhou
92016aa139 fix(api): align Service API OpenAPI contract (#41248)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-25 10:54:14 +00:00
Yunlu Wen
09a855dcef chore: bump version to 1.17.0 (#41247)
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-25 10:52:21 +00:00
wangxiaolei
a6fe278662 feat: hide add library skill in agent ui (#41250)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-25 10:26:06 +00:00
林玮 (Jade Lin)
960018253b feat(api): track credit usage contexts (#41181)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-25 10:21:32 +00:00
yyh
8abff1b0b1 refactor(web): migrate dataset rename form (#41233) 2026-08-25 09:41:37 +00:00
yyh
eb7a1829fe refactor(web): migrate pipeline DSL import form (#41232) 2026-08-25 09:41:36 +00:00
yyh
9ce92d8605 fix(ui): add tabs panel focus treatment (#41231) 2026-08-25 09:41:36 +00:00
wangxiaolei
ddcdbb2d14 feat: add skill enable feature switch (#41246) 2026-08-25 08:42:15 +00:00
Joel
18d3990ae6 fix: show a not-allowed cursor for the prompt editor in build mode (#41243) 2026-08-25 07:43:32 +00:00
zxhlyh
03e4bc50a2 fix(skills): align Japanese Skills page title (#41242) 2026-08-25 07:42:23 +00:00
Joel
370efc493c fix: prevent sidebar footer actions from triggering hover preview (#41230) 2026-08-25 06:53:52 +00:00
Rafli Surya Wijaya
cf236aed8a fix(api): enforce APP_EDIT RBAC permission on MCP server refresh endpoint (#41235) 2026-08-25 06:38:13 +00:00
Asuka Minato
48315be2b1 test: migrate RAG variable controller sessions and ORM models to SQLite (#40609)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-25 06:20:48 +00:00
Asuka Minato
a9035a3264 test: migrate step-by-step tour sessions to SQLite (#40636) 2026-08-25 06:20:13 +00:00
Asuka Minato
39ce9f68fc test(vdb): use real ORM models in provider tests (#40687) 2026-08-25 06:19:59 +00:00
Asuka Minato
ed9d3801ba test: move pure integration cases to unit tests (#40705)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-25 06:19:48 +00:00
Asuka Minato
f3bb73b671 test: centralize app and account config overrides (#40860) 2026-08-25 06:19:35 +00:00
wangxiaolei
bc845ea748 fix: fix skill display name rename conflict (#41229) 2026-08-25 06:13:47 +00:00
非法操作
1afac21690 feat(api): support New Agent Beta for inline Workflow agents (#41215) 2026-08-25 05:39:41 +00:00
samzong
dd2e691ea8 fix(cli): declare write effect for import and context-switch commands (#41225)
Signed-off-by: samzong <samzong.lu@gmail.com>
2026-08-25 05:32:55 +00:00
非法操作
f360a7bf94 fix: allow OAuth trigger builder verification without credentials (#39199)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-25 05:32:27 +00:00
Xiyuan Chen
caf7e90ca5 test(cli): tsconfig gap (#41224) 2026-08-25 05:11:44 +00:00
Alexey Shabalin
1e501cd75b fix(web): stop digits rendering in the emoji font (#41201)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-25 05:04:23 +00:00
盐粒 Yanli
45cb385d77 fix(docker): harden agent compose configuration (#41065) 2026-08-25 04:41:51 +00:00
Yunlu Wen
679514d40a perf(agent): exponential backoff in polling to prevent forking storm (#41222) 2026-08-25 04:36:46 +00:00
Yunlu Wen
9643dcacce perf(agent): polling interval tuning (#41221) 2026-08-25 03:50:22 +00:00
Joel
fcb380044c fix: enforce read-only agent resources in build mode (#41220) 2026-08-25 03:37:02 +00:00
向阳
d4ed92cb0a perf(api): batch recommended app catalog lookups (#41218) 2026-08-25 03:23:52 +00:00
Joel
12f259ecae fix: address Agent UX feedback (#41219) 2026-08-25 03:14:24 +00:00
Aarush Karak
d9ca69d34f fix(types): replace any[] with ThoughtItem[] for agent_thoughts (#41141)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-25 02:08:51 +00:00
Taranum Wasu
ebb0f12cd0 fix(model): re-sign bare/backticked tool file URLs in answer (#40799)
Co-authored-by: Taranum01 <50813317+Taranum01@users.noreply.github.com>
Co-authored-by: Taranum01 <taranumwasu@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Crazywoola <100913391+crazywoola@users.noreply.github.com>
2026-08-25 02:04:21 +00:00
zxhlyh
667d66c4dc fix(skills): align management UI accessibility and localization (#41180)
Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
2026-08-25 01:53:19 +00:00
非法操作
ef92cb7c65 refactor(api): complete account education boundary (#41153)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-25 01:48:12 +00:00
dependabot[bot]
c9ea15a968 chore(deps): bump boto3 from 1.43.71 to 1.43.76 in /api in the storage group (#41126)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-25 10:00:23 +08:00
Jingyi
b56d30b366 fix(web): refresh model provider version after update (#41212) 2026-08-25 01:12:01 +00:00
yyh
8d6128957f fix(web): restore model selector popup spacing (#41190) 2026-08-24 15:05:22 +00:00
Joel
e25ca611d8 fix: failed e2e test in agent caused by changed copywriting (#41187) 2026-08-24 13:16:37 +00:00
Joel
44aec257bf fix: avoid copy-sensitive agent file toast assertion (#41179) 2026-08-24 10:33:25 +00:00
Joel
2be3c3d69e fix: refine agent configuration copy (#41177) 2026-08-24 09:58:06 +00:00
yyh
09b199b280 fix: keep pagination skeletons in app grid (#41175) 2026-08-24 09:35:54 +00:00
github-actions[bot]
b9764c4779 chore(i18n): sync translations with en-US (#41173)
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
2026-08-24 09:08:26 +00:00
Harsh Kashyap
ff3cf5681f fix(api): attach exc_info=True to 11 logger.debug/info('...: %s', str(e)) sites — sibling of #41066 (DEBUG/INFO level) (#41077)
Co-authored-by: Harsh Kashyap <harsh23kashyap@gmail.com>
Co-authored-by: Asuka Minato <i@asukaminato.eu.org>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-24 09:08:08 +00:00
Asuka Minato
cfae2515fd test: remove obsolete integration coverage (#40704) 2026-08-24 09:06:29 +00:00
yyh
b5982927de fix: align main navigation card grids (#41167) 2026-08-24 09:04:30 +00:00
Xiyuan Chen
28a4859218 fix(api): respect configured model params in prompt generator (#41165) 2026-08-24 09:02:34 +00:00
QuantumGhost
4f8a4c20fd ci: add HITL IM test environment deployment (#41171) 2026-08-24 08:54:27 +00:00
Crazywoola
21d540f760 feat(web): enhance Go to Anything navigation and discovery (#41160) 2026-08-24 08:48:53 +00:00
Joel
fef28097cc fix: preserve agent task editor focus when inserting commands (#41166) 2026-08-24 08:33:29 +00:00
yyh
3de20e0ba8 fix: keep home intro without banner (#41155) 2026-08-24 08:30:55 +00:00
yyh
703f6d1780 fix(web): align agent v2 monitoring translations (#41161) 2026-08-24 08:21:41 +00:00
-LAN-
2e1620c1ac chore(api): enforce backend layer boundaries (#41159) 2026-08-24 08:17:11 +00:00
zyssyz123
4847447635 fix(agent): allow saving model-less inline Agent drafts (#41147) 2026-08-24 07:57:14 +00:00
Joel
7ce751ffe8 chore: show full agent save time on hover (#41148)
Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
2026-08-24 07:53:31 +00:00
Joel
7cb9aa2d3b fix: align duplicate agent name behavior with agent forms (#41156) 2026-08-24 07:48:33 +00:00
yyh
3ab8476d2d fix(web): align agent v2 monitoring copy (#41150) 2026-08-24 07:36:18 +00:00
yyh
643e2d66bf chore(deps): upgrade pnpm workspace dependencies (#41138) 2026-08-24 07:07:47 +00:00
Joel
693e1b0fc5 fix: show checklist errors for inline agents without models (#41146) 2026-08-24 06:57:34 +00:00
林玮 (Jade Lin)
70a513fc62 fix(api): scope hosted credits by tenant plan (#41131)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-24 06:35:42 +00:00
FFXN
bec4ef6ac7 fix: fix upload for plugin (#41133)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-24 05:39:27 +00:00
wangxiaolei
0024a845f7 feat: support agent skill (#39675)
Signed-off-by: kenwoodjw <blackxin55+@gmail.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: zxhlyh <jasonapring2015@outlook.com>
Co-authored-by: 起岚 <155608604+xiaoyaoqilan@users.noreply.github.com>
Co-authored-by: Parman Mohammadalizadeh <prmma23@gmail.com>
Co-authored-by: Escape0707 <tothesong@gmail.com>
Co-authored-by: Xin Zhang <zhangxin@dify.ai>
Co-authored-by: iridescentWen <66297467+iridescentWen@users.noreply.github.com>
Co-authored-by: Bond Zhu <37842169+MRZHUH@users.noreply.github.com>
Co-authored-by: KVOJJJin <jzongcode@gmail.com>
Co-authored-by: Joel <iamjoel007@gmail.com>
Co-authored-by: 非法操作 <hjlarry@163.com>
Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
Co-authored-by: Asuka Minato <i@asukaminato.eu.org>
Co-authored-by: Chester <superdiao6@gmail.com>
Co-authored-by: WH-2099 <wh2099@pm.me>
Co-authored-by: Jony <619963502@qq.com>
Co-authored-by: Jony <13896935+zyz619963502zyz@users.noreply.github.com>
Co-authored-by: Harsh Kashyap <harsh.kashyap2001@gmail.com>
Co-authored-by: Harsh Kashyap <Harsh23Kashyap@users.noreply.github.com>
Co-authored-by: kenwoodjw <blackxin55+@gmail.com>
Co-authored-by: csurong <csurong1@gmail.com>
Co-authored-by: caosurong <surong.cao@thinkingdata.cn>
Co-authored-by: Taranum Wasu <81034301+Taranum01@users.noreply.github.com>
Co-authored-by: Taranum01 <50813317+Taranum01@users.noreply.github.com>
Co-authored-by: Pranav Agarwal <agarwalpranav0711@gmail.com>
Co-authored-by: Stephen Zhou <hi@hyoban.cc>
Co-authored-by: zl86790 <marshal_li_b@163.com>
Co-authored-by: QuantumGhost <obelisk.reg+git@gmail.com>
Co-authored-by: yunlu.wen <yunlu.wen@dify.ai>
Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
2026-08-24 05:29:14 +00:00
Crazywoola
0ab88ef36a chore: Replace star image with new asset link (#41136) 2026-08-24 04:33:24 +00:00
yyh
7b3d97cb42 refactor(web): migrate pipeline publishing input form (#41129) 2026-08-24 04:05:39 +00:00
yyh
429edf4d82 refactor(web): migrate pipeline template input form (#41128) 2026-08-24 04:05:38 +00:00
yyh
5a9b6cb239 refactor(web): migrate duplicate app input form (#41127) 2026-08-24 04:05:37 +00:00
Asuka Minato
bda6bf3fee test: migrate trigger and webhook sessions and ORM models to SQLite (#40594) 2026-08-24 04:01:02 +00:00
Joel
24287bcb0c fix: stabilize the agent tool picker placement (#41132) 2026-08-24 03:38:57 +00:00
AsperforMias
3f7e6cdcb4 fix(tts): propagate and validate actual audio MIME (#41043)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: WH-2099 <wh2099@pm.me>
2026-08-24 03:38:09 +00:00
Benjamin
ea6c15b68e fix: fall back to the batch API when the global plugin manifest is empty (#41107)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 03:33:23 +00:00
dependabot[bot]
77998e41e4 chore(deps): bump gunicorn from 26.0.0 to 26.1.0 in /api in the flask group (#41118)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-24 03:28:14 +00:00
酒诗
aed1672366 refactor: pass session to workflow comment account accessors (#41117)
Co-authored-by: geneachina <geneachina@gmail.com>
2026-08-24 03:20:32 +00:00
dependabot[bot]
11c922b5d4 chore(deps): bump the github-actions-dependencies group with 4 updates (#41120)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-24 03:17:12 +00:00
XIIRUAN
ccd0f4b15d refactor(web): use shared session factory for JWT decoding (#41007) 2026-08-24 03:16:44 +00:00
lei_lei
ab34f9ae09 fix(workflow): honor stop between non-streaming nodes (#41090)
Co-authored-by: Crazywoola <100913391+crazywoola@users.noreply.github.com>
Co-authored-by: crazywoola <427733928@qq.com>
2026-08-24 02:51:20 +00:00
ump45nose
9385e583ff fix(agent): avoid empty Bedrock schema fields (#40443)
Co-authored-by: Crazywoola <100913391+crazywoola@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-24 02:08:11 +00:00
非法操作
5018f8aa8a refactor(api): standardize session factory wiring (#41085) 2026-08-24 01:57:17 +00:00
非法操作
ed45016475 refactor(api): standardize console billing portal errors (#41055)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-24 01:55:48 +00:00
陈志谦
9d6c846a49 docs: fix dead anchors in localized READMEs and stale dify-agent link (#41101) 2026-08-24 01:53:59 +00:00
yyh
8bdf702f73 fix(agent-v2): prevent workflow refresh render loop (#41105) 2026-08-23 08:56:02 +00:00
yyh
c62947f1f1 refactor(dify-ui): rename radio family entrypoint (#41104) 2026-08-23 08:08:29 +00:00
Pranav Agarwal
24f5e2ac69 fix(api): enforce admin and RBAC permissions on default model and provider models GET endpoints (#41099) (#41100) 2026-08-23 07:33:57 +00:00
yyh
e18310e52e refactor(dify-ui): simplify overlay content APIs (#41098) 2026-08-22 23:54:08 +00:00
Pranav Agarwal
07119e3f00 fix(api): enforce admin and RBAC permissions on data source integrates GET endpoint (#41079) (#41080) 2026-08-21 17:57:23 +00:00
yyh
a9b8c84e9b refactor(dify-ui): simplify popover content API (#41069) 2026-08-21 13:11:40 +00:00
盐粒 Yanli
35a4533889 refactor(agent): simplify Agent v2 output contract (#41062)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-21 11:55:25 +00:00
Blackoutta
3a8fbcbd02 feat(trace): add provider-neutral unified tracing (#39451)
Co-authored-by: EvoX <evox@evomap.ai>
2026-08-21 11:28:18 +00:00
mesrop2008
23150c2319 fix(api): attach exc_info=True to logger.warning sites that drop the traceback (#41068) 2026-08-21 11:20:42 +00:00
Xiyuan Chen
d6147456e3 feat: Enterprise Home Snapshot — runtime endpoints and dify-agent adapter (#40996) 2026-08-21 10:39:36 +00:00
gegemeimingzi
7d5c68c2e1 fix(web): prevent signin page content from overflowing on mobile (#40921)
Co-authored-by: gegemeimingzi <gegemeimingzi@users.noreply.github.com>
2026-08-21 10:36:31 +00:00
Rafli Surya Wijaya
385e8662bb fix(vdb): add document_id keyword mapping and fix VectorType in elasticsearch-ja adapter (#40400)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-21 10:35:54 +00:00
yyh
6cb96adfbe refactor(dify-ui): compose dialog close controls (#41064) 2026-08-21 10:21:43 +00:00
Yunlu Wen
373f33fd3b fix: add missing metrics back and enhance typing (#40935)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-21 09:46:45 +00:00
yyh
faca558bf5 fix(web): prevent Safari clipping tour recovery prompt (#41060) 2026-08-21 09:19:38 +00:00
Byron.wang
b38d907ede refactor(api): finish account controller application boundary (#40440) 2026-08-21 08:46:06 +00:00
Carson Yang
0c3d08f355 docs: add Sealos deployment option (#41026) 2026-08-21 08:15:35 +00:00
Byron.wang
a52adef203 refactor(api): extract change email state machine (#40439) 2026-08-21 08:13:23 +00:00
Byron.wang
3b05b5e553 refactor(api): move account lifecycle into application services (#40438) 2026-08-21 08:05:43 +00:00
Asuka Minato
92978f6d9f test: migrate console dataset segment sessions and ORM models to SQLite (#40515)
Co-authored-by: Byron.wang <byron@dify.ai>
2026-08-21 06:50:14 +00:00
Asuka Minato
6fe87aaca5 test: migrate residual app generator ORM models to SQLite (#40580)
Co-authored-by: Byron.wang <byron@dify.ai>
2026-08-21 06:49:58 +00:00
Asuka Minato
37a927bf63 test: migrate console agent skill ORM models to SQLite (#40570)
Co-authored-by: Byron.wang <byron@dify.ai>
2026-08-21 06:49:44 +00:00
yyh
44e89d8844 refactor(web): migrate external API input fields (#41052) 2026-08-21 06:38:21 +00:00
yyh
7b1339a156 refactor(web): migrate subscription confirmation input (#41051) 2026-08-21 06:38:21 +00:00
yyh
2ff3f7b533 refactor(web): migrate human input timeout field (#41050) 2026-08-21 06:38:20 +00:00
potoior
34fdac2113 fix: merge system messages and place them first to comply with Qwen/v… (#39136) 2026-08-21 06:24:20 +00:00
Asuka Minato
7d635d9f7e test: migrate auth and access controller ORM models to SQLite (#40572)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-21 06:12:29 +00:00
Asuka Minato
0ce41bfea1 test: migrate console app sessions and ORM models to SQLite (#40559) 2026-08-21 06:12:08 +00:00
Asuka Minato
92b93c9d37 test: migrate remaining controller sessions and ORM models to SQLite (#40538)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-21 06:11:44 +00:00
Asuka Minato
4692741aa0 test: migrate Agent App session store to SQLite ORM (#40638) 2026-08-21 06:10:31 +00:00
Asuka Minato
4ca0a10088 test: migrate vector space admission sessions and ORM models to SQLite (#40640) 2026-08-21 06:10:13 +00:00
Asuka Minato
6ce0976265 test: add tmp_path type (#40724)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-21 06:09:39 +00:00
Asuka Minato
5827ce2adf test: migrate annotation sessions and ORM models to SQLite (#40504) 2026-08-21 06:09:26 +00:00
Byron.wang
1d79b87307 refactor(api): move account access behind application services (#40437) 2026-08-21 05:56:30 +00:00
zl86790
9d8dacd0c8 fix(api): prevent dropped workflow_started events in Redis Streams (#40964)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: QuantumGhost <obelisk.reg+git@gmail.com>
2026-08-21 03:46:50 +00:00
yyh
720e1fab9b refactor(dify-ui): expose slider anatomy (#41045) 2026-08-21 03:15:45 +00:00
yyh
ca6f4e11f9 docs(dify-ui): establish documentation hierarchy (#41044) 2026-08-21 02:29:41 +00:00
WH-2099
a5e284e6b1 fix(plugin): protect endpoint listings (#40897) 2026-08-21 02:17:58 +00:00
Stephen Zhou
3d08b2f89a fix(web): route enterprise documentation links (#40957) 2026-08-21 02:13:26 +00:00
Pranav Agarwal
43e59d3bc5 fix(api): enforce edit and RBAC permissions on datasource credential …fix(api): enforce edit and RBAC permissions on datasource credential GET endpoint (#41040) (#41041) 2026-08-21 02:11:46 +00:00
WH-2099
edc805c453 fix(api): enforce app-scoped access on indirect resources (#40893) 2026-08-21 00:52:39 +00:00
Ingram Z
0ca99312c1 fix(agent): align Binding file upload timeouts (#41027) 2026-08-20 18:59:44 +00:00
wangxiaolei
785ca4b915 fix: when rbac enabled is true, not check_dataset_permission (#41022) 2026-08-20 14:45:40 +00:00
dependabot[bot]
c7b5a455f5 chore(deps): bump google-cloud-aiplatform from 1.160.0 to 1.164.0 in /api in the google group across 1 directory (#39249)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-20 13:48:44 +00:00
dependabot[bot]
0c698744ab chore(deps): bump the storage group across 1 directory with 2 updates (#40393)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-20 13:47:50 +00:00
hyhyf
e425e18fca fix: add MESSAGE_TRACE task on chat pipline error events (#39129)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-20 13:44:22 +00:00
yyh
f4e50f3c8a refactor(web): migrate empty dataset input (#41030) 2026-08-20 13:38:53 +00:00
yyh
aba3f9c1d6 refactor(web): migrate document rename input (#41029) 2026-08-20 13:38:52 +00:00
yyh
979c8cc34b refactor(web): migrate conversation rename input (#41028) 2026-08-20 13:38:51 +00:00
Asuka Minato
502418f707 test: centralize typed runtime config overrides (#40857)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-20 13:30:04 +00:00
蓝破碎半圆/破碎蓝调
ccfb47d2c5 feat: support ODT document extraction (#39973)
Co-authored-by: Crazywoola <100913391+crazywoola@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Asuka Minato <i@asukaminato.eu.org>
2026-08-20 13:23:03 +00:00
非法操作
1bb9183af9 refactor(api): replace legacy recommended app retrieval stack (#40395) 2026-08-20 13:13:43 +00:00
非法操作
de7e43a7ef refactor(api): decouple recommended app runtime admission (#40257) 2026-08-20 13:13:43 +00:00
非法操作
b09691e5d2 refactor(api): isolate trial app usage writes (#40208) 2026-08-20 13:13:42 +00:00
GGbond
6f70ca8d26 refactor(api): decouple console tag management (#40843)
Co-authored-by: Byron Wang <byron@dify.ai>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-20 12:31:01 +00:00
Fasih Ur Rahman
a7a30b20af fix(api): add missing admin and RBAC permission decorators to model credentials GET endpoints (#40962) 2026-08-20 12:15:13 +00:00
盐粒 Yanli
cbd78c0073 fix(agent): clean legacy Agent Soul files (#41024) 2026-08-20 10:34:11 +00:00
盐粒 Yanli
97a3039a2d refactor(dify-agent): use Workspace as shell temp space (#41023) 2026-08-20 10:16:05 +00:00
盐粒 Yanli
005edb7d47 fix(dify-agent): add reliable shellctl stdio mode (#39997) 2026-08-20 10:10:00 +00:00
盐粒 Yanli
b034368b3b fix(dify-agent): adjust local sandbox home paths (#41021) 2026-08-20 10:00:01 +00:00
Pranav Agarwal
43b6d8e32e fix(api): enforce admin and RBAC permissions on tool OAuth custom client GET endpoint (#40944) (#40945) 2026-08-20 09:10:02 +00:00
FFXN
248df5dd25 fix(snippet): support snippet history version export (#41012)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-20 08:52:45 +00:00
非法操作
f97fc01c2f refactor(api): extract recommended app query service (#40207) 2026-08-20 08:45:47 +00:00
林玮 (Jade Lin)
a6ace29e1a fix(api): handle suspended email domains (#41004)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-20 08:04:05 +00:00
盐粒 Yanli
013b328555 fix(agent): complete ownership-aware deletion lifecycle (#40888)
Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
2026-08-20 07:48:02 +00:00
chelsealong
d7b1531431 fix(snippets): implement delete for published snippet workflow versions (#41003)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-20 07:36:17 +00:00
yyh
63acefa6d0 fix(billing): remove misleading tax assurance (#41009) 2026-08-20 07:33:20 +00:00
Stephen Zhou
e2f6418fe4 chore: inline custom ESLint rules (#41008) 2026-08-20 07:32:13 +00:00
yyh
2daa69c92e fix(web): clarify agent deletion consequences (#41002) 2026-08-20 06:45:55 +00:00
yyh
72b6a4e6ed refactor: consolidate frontend browser test infrastructure (#40997) 2026-08-20 06:13:30 +00:00
yyh
b16a24f084 refactor(web): migrate install account fields (#40992) 2026-08-20 05:54:30 +00:00
Asuka Minato
6e890524db test: migrate snippet service ORM models to SQLite (#40567) 2026-08-20 05:12:30 +00:00
Asuka Minato
e27eb51f8a test: migrate media and execution service sessions and ORM models to SQLite (#40552) 2026-08-20 05:11:46 +00:00
Asuka Minato
2155adff5a test: migrate Explore controller sessions and ORM models to SQLite (#40537) 2026-08-20 05:10:49 +00:00
Asuka Minato
c2c1876484 test: migrate document service sessions and ORM models to SQLite (#40536) 2026-08-20 05:10:13 +00:00
非法操作
48f338e649 refactor(api): extract web app runtime bootstrap (#40949) 2026-08-20 05:05:31 +00:00
Byron.wang
b4e13ec83e refactor(api): add account profile application service (#40436)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-20 05:03:08 +00:00
yyh
11f830a17b ci(web): run browser tests on GitHub Ubuntu (#40995) 2026-08-20 04:24:32 +00:00
yyh
5550ec8ebf fix(web): redirect after deleting an agent (#40994) 2026-08-20 04:09:50 +00:00
yyh
ea59256349 refactor(web): migrate signup password fields (#40991) 2026-08-20 03:29:14 +00:00
yyh
0f1536585e refactor(web): migrate signup email field (#40990) 2026-08-20 03:29:13 +00:00
林玮 (Jade Lin)
602a646dbd fix(api): enforce dataset document ownership (#40989) 2026-08-20 03:24:45 +00:00
Amogh Bhat Nagri
54ffbc7f0f fix(logstore): normalize workflow timestamps to naive UTC (#40947)
Co-authored-by: wangxiaolei <fatelei@gmail.com>
2026-08-20 02:58:07 +00:00
WH-2099
ae20d64304 fix(ci): run Playwright E2E on GitHub Ubuntu (#40986) 2026-08-20 02:48:27 +00:00
非法操作
ee997d00fa refactor(api): reuse web app access queries for permissions (#40984) 2026-08-20 02:27:49 +00:00
yyh
98c2ffeec7 fix(ui): align toast swipe direction with viewport (#40980) 2026-08-19 13:16:12 +00:00
yyh
8e1c259a66 fix(web): prevent workflow errors after app deletion (#40977) 2026-08-19 12:24:40 +00:00
盐粒 Yanli
ea3fd4c093 perf(dify-agent): parallelize Agent Stub config pulls (#40973) 2026-08-19 10:35:24 +00:00
盐粒 Yanli
930f4e6c26 fix(dify-agent): persist interrupted run history (#40972) 2026-08-19 10:35:13 +00:00
非法操作
356e3a8ab6 refactor(api): snapshot explore banner feature flag (#40555) 2026-08-19 10:34:37 +00:00
非法操作
532489babd refactor(api): extract web app access queries (#40482) 2026-08-19 10:34:36 +00:00
yyh
6fa9c14490 fix(ui): stabilize toast stack interactions (#40970) 2026-08-19 10:13:43 +00:00
zyssyz123
d0149c3f94 fix(agent): resolve suggested questions from runtime config (#40963) 2026-08-19 07:54:38 +00:00
非法操作
2f6e782215 refactor(api): reuse app definition queries for service API site (#40795) 2026-08-19 07:23:47 +00:00
zyssyz123
414f211cde fix(auth): harden email code login verification (#40960) 2026-08-19 06:57:47 +00:00
Pranav Agarwal
f1b48a93a9 fix(api): enforce edit and RBAC permissions on model provider credential GET endpoints (#40899) (#40900) 2026-08-19 06:48:15 +00:00
盐粒 Yanli
8874f3c80b refactor(agent): remove Agent Drive (#40887)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-19 06:34:36 +00:00
yyh
297fdc7cb8 refactor(web): migrate HTTP timeout inputs (#40953) 2026-08-19 06:30:37 +00:00
yyh
73b15fc562 refactor(web): compose reset password fields (#40952) 2026-08-19 06:30:37 +00:00
yyh
90a6b8c998 refactor(web): simplify debounced filter state (#40951) 2026-08-19 06:30:36 +00:00
Riskey
8d18931125 fix: refine access point copy and remove undeploy state warning (#40886) 2026-08-19 04:11:44 +00:00
Nguyễn Phương
7444f96a1d refactor: clean away unnecessary-type-conversion (bool/str no-op wrappers) (#40822) 2026-08-19 03:48:45 +00:00
Wu Tianwei
8a33a9adb5 fix(web): remove only-me resource access option (#40956) 2026-08-19 02:50:07 +00:00
yyh
b78a3462c9 chore(web): align browser support targets (#40938) 2026-08-18 14:21:18 +00:00
zyssyz123
c38fb16efa fix(agent): retain usage for incomplete runs (#40937) 2026-08-18 13:11:22 +00:00
Asuka Minato
2400c6c59d test: migrate dataset service sessions and ORM models to SQLite (#40534) 2026-08-18 12:35:57 +00:00
yyh
324ddb361d fix(web): gate system features requests by connection (#40939) 2026-08-18 12:34:34 +00:00
Asuka Minato
4f81005662 test: migrate app runtime sessions and ORM models to SQLite (#40590) 2026-08-18 12:27:32 +00:00
Asuka Minato
f2dfa462e1 test: migrate agent runtime sessions and ORM models to SQLite (#40587) 2026-08-18 12:26:58 +00:00
Asuka Minato
14bc28ffbe test: migrate residual controller sessions and ORM models to SQLite (#40579) 2026-08-18 12:26:33 +00:00
Asuka Minato
5afce305e7 test: migrate residual service and task ORM models to SQLite (#40576) 2026-08-18 12:26:01 +00:00
Asuka Minato
beecf5730a test: migrate telemetry and core entity ORM models to SQLite (#40574) 2026-08-18 12:25:42 +00:00
Asuka Minato
eeda983b17 test: migrate service boundary sessions and ORM models to SQLite (#40533)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-18 12:23:33 +00:00
Asuka Minato
e2e3521874 test: migrate residual model sessions and ORM models to SQLite (#40531) 2026-08-18 12:23:02 +00:00
Asuka Minato
303ce70ac4 test: migrate app model sessions and ORM models to SQLite (#40530) 2026-08-18 12:22:33 +00:00
Asuka Minato
5fde1d096e test: eliminate remaining whole config mocks (#40855) 2026-08-18 12:01:49 +00:00
Asuka Minato
3bcd97b643 test: scope plugin and datasource config overrides (#40854) 2026-08-18 12:01:29 +00:00
Asuka Minato
20fdbcf36f test: centralize enterprise config overrides (#40853) 2026-08-18 12:01:01 +00:00
Asuka Minato
c7f4422333 test: keep integration config overrides typed (#40850) 2026-08-18 12:00:32 +00:00
Asuka Minato
da6ca23b50 test: use typed config overrides in service coverage (#40848) 2026-08-18 11:59:58 +00:00
yyh
b064a13aa4 refactor(web): remove legacy embedded API docs (#40929) 2026-08-18 09:53:55 +00:00
yyh
45e2d81be4 fix(ci): align Oxlint suppression formatting (#40934) 2026-08-18 09:41:48 +00:00
yyh
fe41e80f33 refactor(web): remove legacy tag component (#40928) 2026-08-18 07:58:47 +00:00
yyh
a2ac8ad106 refactor(web): migrate clearable search inputs (#40924) 2026-08-18 07:55:08 +00:00
yyh
bd4cfd5a7a refactor(web): migrate retry units to number field (#40923) 2026-08-18 07:55:07 +00:00
chenshiyang
0e975f6305 refactor(models): dep-inject Session on remaining @property accessors (#40797)
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-18 07:23:09 +00:00
dependabot[bot]
c94846ee2a chore(deps): bump sqlparse from 0.5.4 to 0.6.0 in /api (#40904)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-18 06:50:31 +00:00
yyh
9ce463fc24 refactor(web): compose search prefixes with input group (#40922) 2026-08-18 06:04:37 +00:00
zyssyz123
5a0a12cb44 fix: preserve Agent tool-generated file outputs (#40917) 2026-08-18 05:59:43 +00:00
Byron.wang
ba61ab4f9f refactor(api): extract account activation application service (#40421)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-18 05:27:40 +00:00
Byron.wang
891627b210 refactor(api): decouple data source API key auth flow (#40452)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-18 04:30:17 +00:00
蓝破碎半圆/破碎蓝调
ba5e7d76fd fix: accept legacy plugin daemon list responses (#38265) 2026-08-18 04:11:49 +00:00
yyh
809a6cff1e refactor(web): standardize label search inputs (#40914) 2026-08-18 04:05:26 +00:00
yyh
32c11fd06e refactor(web): standardize dataset search inputs (#40913) 2026-08-18 04:05:25 +00:00
yyh
04d2d9ff19 refactor(web): standardize app log search inputs (#40912) 2026-08-18 04:05:25 +00:00
yyh
05499b9011 test(dify-ui): stabilize dropdown menu story (#40916) 2026-08-18 04:05:24 +00:00
Harsh Kashyap
ca32e87683 fix(api): bound connect phase to 5.0s in two api/core/ outbound timeouts (#40807)
Co-authored-by: Harsh Kashyap <Harsh23Kashyap@users.noreply.github.com>
2026-08-18 03:38:59 +00:00
盐粒 Yanli
122368f5e0 chore(dify-agent): disable Landlock for E2B templates (#40892) 2026-08-18 03:30:00 +00:00
盐粒 Yanli
c267e73ca6 fix(dify-agent): use E2B traffic access header (#40891) 2026-08-18 03:29:50 +00:00
盐粒 Yanli
c649b84bf6 fix(dify-agent): isolate cancellation intent observer (#40896) 2026-08-18 03:29:42 +00:00
yyh
09f8f43d20 fix(ci): use default Ubuntu mirror for Playwright (#40909) 2026-08-18 02:55:17 +00:00
mesrop2008
50d6c19ef4 fix(api): clear stale cancellation signals when resuming a paused workflow (#40905) 2026-08-18 02:27:43 +00:00
yyh
6d89557355 feat(dify-ui): add input group composition (#40890) 2026-08-18 02:14:39 +00:00
Amogh Bhat Nagri
30c304c6a7 fix(api): repair two malformed logger format strings (#40901) 2026-08-18 02:10:59 +00:00
yyh
76a91eb433 refactor(dify-ui): expose autocomplete popup anatomy (#40895) 2026-08-18 02:06:03 +00:00
Chengxiao
394b43376a fix: suggest deepseek-v4-flash for Agent mode (#40852) 2026-08-18 01:57:21 +00:00
Asuka Minato
02f0e8cffa test: isolate config inputs from process environment (#40847) 2026-08-17 13:09:17 +00:00
Asuka Minato
3f0a9c5060 test: migrate RAG indexing sessions and ORM models to SQLite (#40513) 2026-08-17 12:13:02 +00:00
Asuka Minato
ce1aed8df5 test: migrate RAG pipeline sessions and ORM models to SQLite (#40511) 2026-08-17 12:12:46 +00:00
Asuka Minato
c3d090fe4e test: migrate Service API dataset metadata sessions and ORM models to SQLite (#40518) 2026-08-17 12:12:06 +00:00
Asuka Minato
d92cf5d198 test: migrate Service API dataset document sessions and ORM models to SQLite (#40519) 2026-08-17 12:11:53 +00:00
Asuka Minato
ccf4d25321 test: migrate console workflow controller sessions and ORM models to SQLite (#40527) 2026-08-17 12:11:34 +00:00
Asuka Minato
4e02075f8d test: migrate console app MCP sessions and ORM models to SQLite (#40526) 2026-08-17 12:11:12 +00:00
Asuka Minato
0f358f5bb3 test: migrate console conversation sessions and ORM models to SQLite (#40528) 2026-08-17 12:10:57 +00:00
Asuka Minato
a575ae5ef2 test: migrate controller auth wrapper sessions and ORM models to SQLite (#40529) 2026-08-17 12:10:44 +00:00
盐粒 Yanli
2aaac4dadb feat(dify-agent): enforce signed upload size limits (#40883) 2026-08-17 11:59:42 +00:00
盐粒 Yanli
bec3890689 fix(dify-agent): enforce short-lived Agent Stub authorization (#40884) 2026-08-17 11:48:12 +00:00
非法操作
e3ab88f6de feat: dispatch New Agent Beta eligibility checks (#40725)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-17 10:33:50 +00:00
盐粒 Yanli
a679ee5644 fix(dify-agent): preserve snapshots for failed and cancelled runs (#40876) 2026-08-17 10:11:22 +00:00
盐粒 Yanli
96809473fc feat(dify-agent): add context-aware history compaction (#40872) 2026-08-17 09:36:21 +00:00
林玮 (Jade Lin)
5ef8becd25 feat: create accounts with client IP (#40875) 2026-08-17 09:29:57 +00:00
盐粒 Yanli
4249a0d052 fix(dify-agent): require E2B traffic authentication (#40871) 2026-08-17 08:35:53 +00:00
zyssyz123
64587eae43 fix(workflow): preserve historical Agent node compatibility (#40859) 2026-08-17 07:31:38 +00:00
yyh
4ce681d42f test(e2e): align agent model selector locators (#40862) 2026-08-17 06:48:00 +00:00
yyh
59c6a470bb fix(web): update agent model request limit copy (#40863) 2026-08-17 06:37:23 +00:00
无能的迪拜巧克力
b02072baee fix(web): let multimodal guidance height fit content (#40846) 2026-08-17 06:10:06 +00:00
Bond Zhu
f6a472d948 feat(ci): sync E2B template on release tag push (#40858) 2026-08-17 06:06:46 +00:00
Weike Zhang
45be4620fe refactor(controllers/web): dep-inject login and forgot-password payloads (#36659) (#40856) 2026-08-17 05:58:40 +00:00
dependabot[bot]
08993dd622 chore(deps): bump the github-actions-dependencies group with 2 updates (#40834)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-17 02:50:41 +00:00
YungLe
219596c4df feat(plugin-auth): visibility picker for OAuth credentials (#39840)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Wu Tianwei <30284043+WTW0313@users.noreply.github.com>
Co-authored-by: twwu <twwu@dify.ai>
2026-08-17 02:41:26 +00:00
yyh
facb60abfe fix(web): align combobox interaction semantics (#40826) 2026-08-17 02:13:08 +00:00
zy
141cbf9832 fix(api): support audio/x-m4a for ASR (#40776)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-16 02:47:31 +00:00
Asuka Minato
8fb5dd8587 test: migrate agent controller sessions and ORM models to SQLite (#40600)
Co-authored-by: Byron Wang <byron@dify.ai>
2026-08-15 15:15:28 +00:00
Asuka Minato
1651bcc774 test: migrate residual controller sessions and ORM models to SQLite (#40606)
Co-authored-by: Byron Wang <byron@dify.ai>
2026-08-15 15:15:11 +00:00
mesrop2008
c2e68335d4 docs: fix pipeline_generator docstrings to reference pipeline instead of app_model (#40813) 2026-08-15 12:09:16 +00:00
Asuka Minato
177edaa1c6 test: migrate annotation security sessions and ORM models to SQLite (#40604) 2026-08-15 09:54:29 +00:00
Asuka Minato
edb32fba92 test: migrate RAG processor residuals to SQLite ORM models (#40608) 2026-08-15 09:54:09 +00:00
Asuka Minato
959cacdc00 test: migrate agent surface sessions and ORM models to SQLite (#40602) 2026-08-15 09:53:48 +00:00
Asuka Minato
582c73bc3b test: migrate residual user ORM stand-ins to real models (#40625) 2026-08-15 09:52:59 +00:00
Asuka Minato
6eca353804 test: migrate file controller ORM models to real entities (#40632) 2026-08-15 09:52:38 +00:00
Harsh Kashyap
d43685bc79 fix(extension): chain original exception in APIBasedExtensionRequestor per PEP 3134 (#40810)
Co-authored-by: Harsh Kashyap <Harsh23Kashyap@users.noreply.github.com>
2026-08-15 08:48:28 +00:00
Valor
56ebccf14d fix: narrow bare except in storage exists() to ClientError (#40420)
Co-authored-by: Asuka Minato <i@asukaminato.eu.org>
2026-08-15 07:12:04 +00:00
chenshiyang
d31a7d47bf refactor(controllers/web): dep-inject payloads with @model_validate (#40796)
Co-authored-by: chenshiyang.10 <chenshiyang.10@jd.com>
2026-08-15 06:55:06 +00:00
Dream
8031ea6d73 fix: replace bare except with except Exception in core agent, storage and vector backends (#40801) 2026-08-15 00:56:09 +00:00
zyssyz123
dfac3e524e fix: reclaim conversation resources on deletion (#40792)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-14 14:30:04 +00:00
WH-2099
fc7b51634d fix(api): protect agent sandbox reads (#40794) 2026-08-14 13:51:41 +00:00
WH-2099
96bfcf20cd fix(api): protect workspace credential mutations (#40790) 2026-08-14 12:03:54 +00:00
Mahbub Souad
557fbec45f refactor: add Mapped type annotations to model fields (#40373) (#40380) 2026-08-14 12:03:17 +00:00
AlexMultiAgent
eaa9d877f1 test(api): make session decorator path assertion platform-agnostic (#39895)
Co-authored-by: -LAN- <laipz8200@outlook.com>
2026-08-14 11:52:40 +00:00
chelsealong
b537fed907 fix(api): point SSRF-blocked error message at the correct dify issue (#40605) 2026-08-14 11:46:50 +00:00
酒诗
b6319c819c chore: dep inject for model in dataset document actions (#40787)
Co-authored-by: geneachina <geneachina@gmail.com>
2026-08-14 11:08:21 +00:00
WH-2099
b6694d462f fix(api): protect custom OAuth client deletion (#40786) 2026-08-14 10:59:49 +00:00
L1nSn0w
ea6770c7a1 feat(oauth): drive silent authorization from oauth_provider_apps.auto_authorize (#40783)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-14 10:29:39 +00:00
Joel
b0c5172e10 fix: show accurate copy for agent run limit errors (#40784) 2026-08-14 10:07:36 +00:00
WH-2099
62a544a146 fix(api): enforce RAG draft variable access boundaries (#40745) 2026-08-14 10:07:22 +00:00
非法操作
eec092f93d refactor(api): reuse app definition queries for service API info (#40476) 2026-08-14 09:38:35 +00:00
非法操作
e0fd3b264a refactor(api): reuse app definition queries for app parameters (#40465) 2026-08-14 09:38:34 +00:00
非法操作
17c8ff6a33 refactor(api): reuse app definition queries in web and service APIs (#40463) 2026-08-14 09:38:33 +00:00
非法操作
c425e4cdd5 refactor(api): extract installed app definition queries (#40462) 2026-08-14 09:38:32 +00:00
yyh
de9b456e82 fix(ci): align staged checks with Vite+ (#40774) 2026-08-14 09:09:33 +00:00
Joel
62d06a3c73 fix: preserve successful last run status after page restore (#40775) 2026-08-14 08:59:18 +00:00
zyssyz123
09f20b7a14 fix(agent): return conflict for duplicate creation (#40771)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-14 08:57:13 +00:00
Asuka Minato
0a1e52598f test: migrate controller identity ORM models to SQLite (#40626) 2026-08-14 08:54:48 +00:00
Asuka Minato
640bf56859 test: migrate workflow tool users to SQLite ORM models (#40628) 2026-08-14 08:54:31 +00:00
Asuka Minato
a958c2cadb test: migrate RAG residual entities to real ORM models (#40629) 2026-08-14 08:53:56 +00:00
Asuka Minato
f058e36084 test: migrate account tenant ORM stand-ins to SQLite (#40627) 2026-08-14 08:53:32 +00:00
Asuka Minato
9f364339cc test: migrate residual namespace ORM entities to real models (#40633) 2026-08-14 08:52:53 +00:00
盐粒 Yanli
3acc9470d4 feat(dify-agent): expand and enforce agent run limits (#40641) 2026-08-14 08:27:19 +00:00
yyh
9ddbc23b16 fix(dify-ui): refine segmented control focus feedback (#40769) 2026-08-14 08:17:14 +00:00
Myshkin451
c903e93e8b fix: preserve file preview content type (#37211)
Co-authored-by: FFXN <31929997+FFXN@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-14 07:45:21 +00:00
盐粒 Yanli
0b36a0bbc0 fix(dify-agent): clarify shell working spaces (#40623)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-14 07:39:32 +00:00
林玮 (Jade Lin)
4e44ade07f fix: handle long text URLs in webscraper (#40757) 2026-08-14 07:34:53 +00:00
Joel
35132d6892 chore: reopen the education application flow (#40760)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-14 07:16:21 +00:00
dependabot[bot]
6edc8ba147 chore(deps): bump pydantic-ai-slim from 1.102.0 to 1.106.0 in /dify-agent (#40736)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-14 06:26:00 +00:00
yyh
12b3b62a7f chore: update workspace dependencies (#40764) 2026-08-14 06:17:11 +00:00
Crazywoola
58653f2cdb feat(workflow-generator): prefer installed tools (#40611) 2026-08-14 05:38:37 +00:00
Asuka Minato
ef176f130b test: migrate workflow event ORM models to real entities (#40634) 2026-08-14 05:35:10 +00:00
Asuka Minato
c36161a73f test: migrate OpenAPI and tool-file ORM entities (#40637) 2026-08-14 05:34:56 +00:00
Asuka Minato
4b189777c4 test: migrate web controller identity ORM models to real entities (#40639) 2026-08-14 05:34:43 +00:00
Asuka Minato
d08dc6162c test: migrate trace workflow run ORM model to real entity (#40642) 2026-08-14 05:34:29 +00:00
Asuka Minato
b5e05516f4 test: migrate annotation controller ORM models to real entities (#40643) 2026-08-14 05:34:16 +00:00
Asuka Minato
9f048cd89b test: migrate load balancing account ORM model to real entity (#40644) 2026-08-14 05:34:00 +00:00
Asuka Minato
78dfce3b63 test: migrate expired log workflow ORM models to real entities (#40645) 2026-08-14 05:33:46 +00:00
Asuka Minato
97d34ae6be test: migrate agent drive end-user ORM models to real entities (#40654) 2026-08-14 05:33:29 +00:00
Asuka Minato
ea0ee680dc test: migrate app service accounts and commit failures to real ORM (#40655) 2026-08-14 05:33:16 +00:00
yyh
9acdcbe2f8 fix(web): skip lifecycle scripts in Docker install (#40763) 2026-08-14 05:12:14 +00:00
yyh
0f63a05d04 chore: upgrade Vite+ to 0.2.9 (#40762) 2026-08-14 04:42:28 +00:00
WH-2099
3cd23d4ef8 fix(agent): authenticate agent control plane (#40737) 2026-08-14 04:32:09 +00:00
Pranav Agarwal
e2852524be fix(api): enforce edit and RBAC permissions on dataset API key GET endpoint (#40740) (#40743) 2026-08-14 04:27:37 +00:00
yyh
f8e05ebfc0 docs(web): consolidate maintainer guidance (#40758) 2026-08-14 03:40:05 +00:00
Joel
0ac005eb98 fix: add semantic document titles across pages (#40396) 2026-08-14 03:29:16 +00:00
林玮 (Jade Lin)
755c154b1f refactor: resolve completion model via manager (#40756) 2026-08-14 02:52:42 +00:00
Jingyi
e3b3165e9a feat(web): embed marketplace in integration categories (#40744) 2026-08-14 01:55:51 +00:00
Xiyuan Chen
bf044cf19c chore(deps): bump wandb to 0.28.2 (go-git, grpc, x/text, Go stdlib CVEs) (#40753) 2026-08-14 01:36:14 +00:00
yyh
1cf8db8395 refactor(web): clarify model selector trigger ownership (#40732)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-14 01:03:50 +00:00
WH-2099
c1bde25bcc fix(api): remove unsafe Bedrock test endpoint (#40742) 2026-08-13 19:47:13 +00:00
Harsh Kashyap
8238684334 fix(api): chain original exception in 13 except blocks per PEP 3134 (#40738)
Co-authored-by: Harsh Kashyap <Harsh23Kashyap@users.noreply.github.com>
2026-08-13 17:50:05 +00:00
zyssyz123
c9c7fb9962 fix(agent): meter internal LLM calls through API (#40613)
Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
2026-08-13 12:15:44 +00:00
林玮 (Jade Lin)
b9248690b0 refactor: generalize hosted model quota lifecycle (#40722)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-13 08:10:02 +00:00
yyh
36dfc6c216 refactor(ui): enforce single-choice segmented controls (#40726) 2026-08-13 08:09:10 +00:00
yyh
7a6f380f2c fix(dify-ui): refine pagination navigation semantics (#40723) 2026-08-13 07:54:31 +00:00
Joel
84e348c52b fix: prevent cross-tab chat conversation switching (#40709) 2026-08-13 07:26:38 +00:00
盐粒 Yanli
79b8d7a797 fix(agent): normalize plugin provider identities (#40619)
Co-authored-by: Joel <iamjoel007@gmail.com>
2026-08-13 07:22:41 +00:00
yyh
fb30dd2d58 refactor(web): migrate app card icon controls (#40652) 2026-08-13 07:04:17 +00:00
yyh
a0ca3d2e81 refactor(web): remove legacy action button references (#40651) 2026-08-13 07:04:16 +00:00
yyh
204a906de8 refactor(web): migrate help menu icon trigger (#40650) 2026-08-13 07:04:15 +00:00
yyh
146f402a8c refactor(web): migrate workflow icon commands (#40649) 2026-08-13 06:44:03 +00:00
yyh
d6f32a0267 refactor(web): migrate plugin icon commands (#40648) 2026-08-13 06:44:02 +00:00
yyh
288766171d refactor(web): migrate dataset icon commands (#40647) 2026-08-13 06:44:01 +00:00
yyh
7ab368f4a4 refactor(web): migrate app icon commands (#40646) 2026-08-13 06:44:00 +00:00
yyh
d0e2723e45 refactor(web): migrate semantic icon controls (#40624) 2026-08-13 06:43:59 +00:00
Joel
c085142e66 chore: remove scope selection from the agent environment editor (#40701) 2026-08-13 06:24:51 +00:00
林玮 (Jade Lin)
c647cfd6a3 refactor: resolve summary models through manager (#40696) 2026-08-13 06:22:22 +00:00
yyh
29a4897e73 fix(ci): prevent false failures from superseded runs (#40699) 2026-08-13 06:18:22 +00:00
盐粒 Yanli
8df220c2b3 fix(agent): propagate resource collection failures (#40697) 2026-08-13 06:16:12 +00:00
zyssyz123
6e80f42f38 fix(api): decouple response listeners from execution lifecycle (#39813) 2026-08-13 05:50:43 +00:00
Asuka Minato
211344d0b0 test: migrate conversation lifecycle sessions and ORM models to SQLite (#40656) 2026-08-13 05:20:10 +00:00
Asuka Minato
6b5c04e7d3 test: migrate workflow node trace ORM models to real entities (#40657) 2026-08-13 05:19:52 +00:00
Asuka Minato
6ea89dc7cb test: migrate workflow tool-file ORM model to real entity (#40658) 2026-08-13 05:19:34 +00:00
Asuka Minato
ff46c3d7d7 test: migrate reranker upload-file sessions and ORM models to SQLite (#40659) 2026-08-13 05:19:19 +00:00
Asuka Minato
2f969afaf2 test: migrate app runner transaction sessions and ORM models to SQLite (#40660) 2026-08-13 05:19:00 +00:00
Asuka Minato
fbd38753fa test: migrate residual controller ORM identities to real models (#40661) 2026-08-13 05:18:44 +00:00
Asuka Minato
2d1fb61885 test: migrate RAG dataset ORM contracts to real models (#40662) 2026-08-13 05:18:25 +00:00
Asuka Minato
7e3381e8ad test: migrate OpenTelemetry ORM identities to real models (#40663) 2026-08-13 05:17:53 +00:00
Joel
190780e125 fix(e2e): skip hidden Agent knowledge E2E scenarios (#40691) 2026-08-13 05:03:15 +00:00
yyh
1f96da5e6d fix(ci): always report required style checks (#40684) 2026-08-13 04:05:45 +00:00
Joel
a8d5679a1c fix: update Agent advanced settings copy (#40682) 2026-08-13 03:25:43 +00:00
Xiyuan Chen
5bacb68115 fix(ops): keep the path of self-hosted LangSmith and Weave endpoints (#40584) 2026-08-13 03:18:22 +00:00
Asuka Minato
af2fac75db test: migrate workflow variable ORM model to real entity (#40664) 2026-08-13 03:05:31 +00:00
Asuka Minato
616736e0f1 test: migrate residual session factories to shared SQLite (#40665) 2026-08-13 03:04:59 +00:00
Asuka Minato
94323c0838 test: migrate residual dataset and archive ORM models (#40668) 2026-08-13 03:04:17 +00:00
Asuka Minato
223998bd48 test: migrate residual ORM model stand-ins to real mappings (#40666) 2026-08-13 03:03:46 +00:00
Joel
b3d770a69b fix: hide knowledge retrieval from Agent V2 configuration (#40679) 2026-08-13 03:03:12 +00:00
Asuka Minato
9fb51b7e67 test: migrate API workflow pause ORM models to real entities (#40669) 2026-08-13 03:03:10 +00:00
yyh
67366dd35c feat(ui): expose base toggle composition (#40622) 2026-08-13 02:29:37 +00:00
yyh
71b31e17b0 refactor(web): migrate domain icon commands (#40621) 2026-08-13 02:29:36 +00:00
yyh
312bc4912d refactor(web): migrate shared icon commands (#40620) 2026-08-13 02:29:36 +00:00
yyh
3925b5fa1b refactor(ui): adopt icon button in close controls (#40617) 2026-08-13 02:29:35 +00:00
yyh
d4d30148bd feat(ui): add icon button primitive (#40616) 2026-08-13 02:29:34 +00:00
林玮 (Jade Lin)
12e6838403 fix: meter hosted LLM invocations (#40589) 2026-08-12 12:33:21 +00:00
WH-2099
489772908b fix: enforce API key list permissions (#40516) 2026-08-12 11:44:27 +00:00
Benjamin
6a37e1538a fix(rbac): grant member policies when a dataset is opened to the work… (#39735)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-12 09:02:03 +00:00
wangxiaolei
eeaaf11a51 fix: fix create dataset with document miss rbac operation (#40599)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-12 08:57:43 +00:00
Wu Tianwei
6899c7720f refactor(web): remove deprecated deployments pages (#40593) 2026-08-12 08:49:51 +00:00
Byron.wang
51a007e84e refactor(api): extract init validation into layered application service (#40046) 2026-08-12 08:42:09 +00:00
yyh
6d185b6f40 test(web): remove brittle publisher lock test (#40592) 2026-08-12 07:55:46 +00:00
github-actions[bot]
7358c0f735 chore(i18n): sync translations with en-US (#40573)
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
2026-08-12 07:49:39 +00:00
yyh
01460f681e fix(web): render workspace plan badge during SSR (#40581)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-12 07:45:39 +00:00
Crazywoola
750fce7e52 fix(web): restore app deletion autofill and knowledge scope label (#40583) 2026-08-12 07:31:59 +00:00
Asuka Minato
216d528f1b test: migrate agent app sandbox sessions and ORM models to SQLite (#40568) 2026-08-12 06:30:17 +00:00
Xin Zhang
0ee89c1302 fix: restrict app deploy to explicit enterprise permission (#40564) 2026-08-12 06:25:05 +00:00
WH-2099
af382be837 fix(api): bind remaining RAG resources to owners (#40503) 2026-08-12 06:05:16 +00:00
chelsealong
d813edb945 fix(agent-v2): stop dropping non-vision attachments from agent chat (#40179)
Co-authored-by: Crazywoola <100913391+crazywoola@users.noreply.github.com>
2026-08-12 05:57:21 +00:00
无能的迪拜巧克力
9041251da5 feat(web): add multimodal retrieval guidance for Knowledge embedding models (#40566) 2026-08-12 05:54:33 +00:00
Joel
9e04e4f5c2 chore: add Docker configuration for the Turnstile site key (#40569) 2026-08-12 05:54:21 +00:00
yyh
28ba7033fa refactor(web): remove profile bootstrap atom layer (#40474) 2026-08-12 04:05:57 +00:00
Wu Tianwei
fbaf23dc8d fix(web): improve app deployment v2 accessibility (#40550) 2026-08-12 03:43:35 +00:00
github-actions[bot]
9cc1f68364 chore(i18n): sync translations with en-US (#40546)
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
2026-08-12 03:25:34 +00:00
zyssyz123
059c9ce0b6 feat: add trunstile (#40494)
Co-authored-by: Joel <iamjoel007@gmail.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-12 03:08:19 +00:00
yyh
668fb4c14a refactor(web): sync zendesk from profile query (#40473) 2026-08-12 02:57:27 +00:00
yyh
4c06bcf000 refactor(web): sync amplitude from profile query (#40472) 2026-08-12 02:15:24 +00:00
Wu Tianwei
7aba539e82 feat: app deployment v2 (#39829)
Co-authored-by: zhangx1n <zhangxin@dify.ai>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-12 01:55:36 +00:00
WH-2099
ef8544b173 fix(api): bind dataset operations to owners (#40149) 2026-08-11 16:37:14 +00:00
yyh
bee269afe8 refactor(web): align education autocomplete async behavior (#40500) 2026-08-11 14:12:50 +00:00
yyh
324b0f97ff refactor(web): read plugin profile from query cache (#40471) 2026-08-11 11:39:26 +00:00
yyh
7352944dec refactor(web): read account profile from query cache (#40470) 2026-08-11 11:17:29 +00:00
yyh
78c7fb9c5c refactor(web): move education verification to dedicated routes (#40493)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-11 09:56:11 +00:00
Joel
8598af2a17 fix: improve agent working directory tab labels and tooltips (#40496) 2026-08-11 09:36:33 +00:00
yyh
df07a0a1de refactor(web): read workflow profile from query cache (#40469) 2026-08-11 09:03:56 +00:00
Asuka Minato
a64a24b39c test: migrate snippet and vector sessions to SQLite (#40089)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Byron Wang <byron@dify.ai>
2026-08-11 08:51:07 +00:00
yyh
cd0e88c680 refactor(web): read dataset profile from query cache (#40468) 2026-08-11 08:30:49 +00:00
Asuka Minato
08008f6305 test: migrate controller sessions to SQLite (#40083)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-11 08:29:40 +00:00
Valor
e3812cf72b fix: add zh_Hans labels for builtin Audio provider and its tools (#40408) 2026-08-11 08:27:59 +00:00
yyh
4175d062f4 fix(web): make legacy Home redirect permanent (#40492) 2026-08-11 08:27:57 +00:00
Yunlu Wen
84f9b6530e chore: bump cryptography, pypdf, h2 for CVE fixes (#40409)
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-11 08:14:55 +00:00
yyh
3d02a12eb6 refactor(web): read app profile from query cache (#40467) 2026-08-11 08:09:58 +00:00
Byron.wang
c1e94f8ee7 refactor(api): consolidate deployment edition handling (#40142)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-11 07:39:01 +00:00
yyh
7fffd51535 fix(web): preserve workflow canvas after history updates (#40489) 2026-08-11 07:36:21 +00:00
Joel
a68e0bbc6f fix: show a persistent toast for agent run timeouts (#40486) 2026-08-11 07:27:52 +00:00
Asuka Minato
dd3cf53044 test: migrate retention and task sessions to SQLite (#40090)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-11 07:05:36 +00:00
Asuka Minato
500e37e2fd test: migrate core RAG sessions to SQLite (#40085)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-11 07:05:26 +00:00
Joel
44c5f1c011 fix: split sandbox files into saved and temporary tabs (#40478) 2026-08-11 06:46:01 +00:00
Asuka Minato
7162450e83 test: migrate app service sessions to SQLite (#40088)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-11 06:43:15 +00:00
Asuka Minato
3f62f3cd05 test: migrate dataset indexing task sessions to SQLite (#40091) 2026-08-11 06:31:33 +00:00
Asuka Minato
15483f1592 test: use sqlite sessions in rag pipeline coverage (#40093) 2026-08-11 06:19:08 +00:00
wangxiaolei
4c7b870062 fix: _multiple_retrieve_thread not fail fast (#40466) 2026-08-11 05:40:23 +00:00
yyh
48451f5adf fix(web): keep agent ref updates out of render (#40429) 2026-08-11 03:57:58 +00:00
Kecheng Wang
f785af3cec fix(docker): use dynamic DNS resolution for all nginx upstreams (#39155)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-11 00:48:59 +00:00
Tushar Motwani
aa5e8a5eff chore: suppress pyrefly necessary conversions (#40444) 2026-08-10 16:41:34 +00:00
yyh
6a9efa8ffd fix(web): keep workflow ref updates out of render (#40428) 2026-08-10 14:38:04 +00:00
林玮 (Jade Lin)
4eb9a24997 refactor(workflow): align standalone node execution layers (#40447) 2026-08-10 12:37:34 +00:00
yyh
b206e691ca fix(web): keep shared ref updates out of render (#40427) 2026-08-10 11:33:11 +00:00
yyh
3f354c2b06 docs(web): clarify ref mutation ownership (#40426) 2026-08-10 11:04:18 +00:00
github-actions[bot]
8ae9d0ad8e chore(i18n): sync translations with en-US (#40435)
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
2026-08-10 11:00:10 +00:00
Joel
0f583cfe75 fix: widen agent orchestration chat on large displays (#40433) 2026-08-10 09:57:47 +00:00
zyqzyq
df250423d4 feat: add tool plugin param type date and date-picker (#36163)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: hjlarry <hjlarry@163.com>
2026-08-10 09:31:38 +00:00
Asuka Minato
b8934b743c test: migrate core app sessions to SQLite (#40084)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-10 09:01:02 +00:00
Byron.wang
976d061f9b refactor(api): merge ping and version endpoints into system (#40058)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-10 08:50:40 +00:00
Asuka Minato
96655436f4 test: migrate RAG index sessions to SQLite (#40080)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-10 08:43:18 +00:00
非法操作
648806bc9c refactor(api): extract explore banner query service (#40053) 2026-08-10 08:07:54 +00:00
yyh
64ebfe2235 fix(web): name the webapp password visibility action (#40225) 2026-08-10 07:12:24 +00:00
yyh
ca4d7ff1f2 fix(web): make suggested questions native buttons (#40200)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-10 06:47:19 +00:00
yyh
2917d1d51c refactor(web): migrate webapp password fields to dify ui (#40223) 2026-08-10 06:44:28 +00:00
yyh
c79b9821fa fix(web): name endpoint card actions (#40260) 2026-08-10 06:44:10 +00:00
yyh
6422ef2b57 fix(web): use button for workflow debug close (#40274)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-10 06:43:23 +00:00
yyh
509ea9afc4 fix(web): name secret key delete action (#40297) 2026-08-10 06:43:02 +00:00
yyh
1828cc6a10 fix(web): name MCP header delete actions (#40300) 2026-08-10 06:42:45 +00:00
yyh
8d5ff67d05 fix(web): name external API card actions (#40304) 2026-08-10 06:42:36 +00:00
yyh
ec63a26511 fix(web): expose chat variable tips state (#40334) 2026-08-10 06:42:03 +00:00
yyh
c2b3b89445 docs(web): add Next.js agent rules (#40398) 2026-08-10 06:39:37 +00:00
Joel
5967bd8e08 chore: tighten education verification and pause discount access (#40402)
Co-authored-by: Yansong Zhang <916125788@qq.com>
2026-08-10 06:33:03 +00:00
非法操作
7e7548cd18 fix(web): allow unlimited text input in trial apps (#40403) 2026-08-10 06:18:38 +00:00
dependabot[bot]
1ba3aa718e chore(deps): bump pymdown-extensions from 11.0 to 11.0.1 in /dify-agent (#40183)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 06:16:06 +00:00
dependabot[bot]
c7b1660650 chore(deps): bump gitpython from 3.1.57 to 3.1.58 in /api (#40184)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 06:14:40 +00:00
yyh
f5e1f1590f fix(web): use buttons for version filters (#40357)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-10 04:41:57 +00:00
yyh
09d0cca5b9 fix(web): make tool category filters keyboard accessible (#40243) 2026-08-10 04:18:04 +00:00
yyh
d8736be194 fix(web): name MCP header fields (#40299) 2026-08-10 03:57:24 +00:00
Pranav Agarwal
7f15f506f8 fix(api): end_date filter in feedback export excludes the entire end date (#40114) 2026-08-10 03:27:56 +00:00
chelsealong
6aa3fa5193 fix: catch ValueError instead of bare except in account CLI commands (#40356) 2026-08-10 03:18:33 +00:00
dependabot[bot]
c849be5e52 chore(deps): bump the github-actions-dependencies group with 2 updates (#40391)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 03:17:53 +00:00
yyh
b3b3088a17 fix(web): name external API panel close (#40309) 2026-08-10 03:13:36 +00:00
yyh
72fad39913 fix(web): name external API modal close (#40313) 2026-08-10 03:13:35 +00:00
yyh
e12563a4b4 fix(web): name plugin item actions (#40261) 2026-08-10 03:13:33 +00:00
yyh
e8afed13cc fix(web): name plugin detail close action (#40264) 2026-08-10 03:13:33 +00:00
yyh
7a72bb3571 fix(web): name OAuth redirect copy action (#40303) 2026-08-10 03:13:33 +00:00
yyh
08f30717ad fix(web): make verification back actions keyboard accessible (#40196) 2026-08-10 03:13:31 +00:00
yyh
2bdfbb9e61 fix(web): name generated result copy action (#40259) 2026-08-10 03:13:31 +00:00
yyh
06e757a9e9 fix(web): name the snippet info menu trigger (#40251) 2026-08-10 03:13:31 +00:00
yyh
7b84d4daca fix(web): use primary headings on password reset pages (#40193) 2026-08-10 03:13:31 +00:00
yyh
5e0d705a7f fix(web): name the plugin debug trigger (#40252) 2026-08-10 03:13:31 +00:00
yyh
30ca836e03 fix(web): make the citation toggle a button (#40204) 2026-08-10 03:12:25 +00:00
Asuka Minato
b391dc56a0 chore: example to rm db.session (#40370) 2026-08-10 02:58:52 +00:00
yyh
606fac6e1c fix(web): use button for publisher access (#40361)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-10 02:56:21 +00:00
yyh
ed36ee5133 refactor(web): rely on preview dialog containment (#40363)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-10 02:56:20 +00:00
yyh
c35242731f fix(web): use button for provider tool item (#40362) 2026-08-10 02:56:20 +00:00
yyh
d2d07d0345 fix(web): use buttons for plugin type switch (#40353)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-10 02:56:19 +00:00
yyh
8b908d6150 fix(web): use buttons for pricing categories (#40360)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-10 02:56:18 +00:00
yyh
1017a76b4c fix(web): name assigner add operation (#40337) 2026-08-10 02:56:18 +00:00
yyh
9c5d76c299 refactor(web): rely on QR panel containment (#40352)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-10 02:56:18 +00:00
yyh
83987b8eec fix(web): name prompt generator action (#40328) 2026-08-10 02:56:16 +00:00
yyh
cbd71699de fix(web): expose SVG preview toggle state (#40332) 2026-08-10 02:56:16 +00:00
yyh
5d58a25e52 fix(web): name human input preview close (#40321) 2026-08-10 02:56:16 +00:00
yyh
764d9b5fbe fix(web): name external retrieval close action (#40317) 2026-08-10 02:56:16 +00:00
yyh
5ffea6d30e fix(web): name code generator action (#40324) 2026-08-10 02:56:16 +00:00
yyh
2796210e18 fix(web): name agent log navigation menu (#40286) 2026-08-10 02:56:14 +00:00
yyh
1b2c71ac75 fix(web): name variable inspect close actions (#40289) 2026-08-10 02:56:14 +00:00
yyh
cc4bf22d07 fix(web): expose workflow parallel toggle state (#40282) 2026-08-10 02:56:14 +00:00
yyh
7295d9306f fix(web): name image previewer actions (#40283) 2026-08-10 02:56:14 +00:00
yyh
2a66b49bc7 fix(web): name human input delete action (#40293) 2026-08-10 02:56:14 +00:00
yyh
c944a25585 fix(web): expose debug toolbar semantics (#40258) 2026-08-10 02:56:12 +00:00
yyh
2067836851 fix(web): name saved item actions (#40256) 2026-08-10 02:56:12 +00:00
yyh
6f95a071b5 fix(web): name snippet stop action (#40278) 2026-08-10 02:56:11 +00:00
yyh
a543fd3656 fix(web): name workflow version history action (#40276) 2026-08-10 02:56:11 +00:00
yyh
d94c4415af fix(web): name annotation reply actions (#40270) 2026-08-10 02:56:11 +00:00
yyh
abbed23c64 fix(web): make dataset sidebar menu items buttons (#40248) 2026-08-10 02:56:09 +00:00
yyh
5de4e5b3c0 fix(web): name dataset configuration actions (#40254) 2026-08-10 02:56:09 +00:00
yyh
1e17a55e79 fix(web): name annotation configuration action (#40255) 2026-08-10 02:56:09 +00:00
yyh
465dab2eed refactor(web): keep copy id events on the button (#40247) 2026-08-10 02:56:09 +00:00
yyh
532e0a77cc fix(web): name conversation menu triggers (#40253) 2026-08-10 02:56:09 +00:00
yyh
47835e6b25 fix(web): expose the voice recording timer (#40205) 2026-08-10 02:56:07 +00:00
yyh
11c537dc1e fix(web): restore webapp email code form submission (#40227) 2026-08-10 02:56:07 +00:00
yyh
e4420227b5 fix(web): make the scroll-to-node action a button (#40214) 2026-08-10 02:56:07 +00:00
yyh
f9e44fe86e fix(web): restore the signup email focus order (#40230) 2026-08-10 02:56:07 +00:00
yyh
b256e211dc fix(web): make the member selector keyboard accessible (#40209) 2026-08-10 02:56:07 +00:00
yyh
2a34c7a714 fix(web): make the human input expander a button (#40202)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-10 02:55:30 +00:00
yyh
04132b51f0 fix(web): use button for chat variable panel close (#40333)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-10 02:53:49 +00:00
yyh
908f6ada4e fix(web): restore webapp password form submission (#40222) 2026-08-10 02:53:43 +00:00
yyh
e7da213f93 fix(web): name workflow debug actions (#40273) 2026-08-10 02:53:37 +00:00
yyh
e7f789f185 fix(web): hide citation measurement items from assistive tech (#40203) 2026-08-10 02:34:14 +00:00
yyh
f8d381e6c5 fix(web): name chat settings triggers (#40341) 2026-08-10 02:33:11 +00:00
yyh
c29425c0fc fix(web): name chat history controls (#40344) 2026-08-10 02:33:02 +00:00
yyh
612f9ee669 fix(web): use button for tool detail toggle (#40349)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-10 02:32:52 +00:00
Souravrajvi0
81a38df814 feat(api): cache remote recommended app template fetches (#40176) 2026-08-10 02:30:15 +00:00
yyh
e9eb130731 fix(web): use a button for unauthorized logout (#40198) 2026-08-10 02:29:46 +00:00
yyh
4edaecc04d fix(web): use a button for the webapp fallback action (#40197) 2026-08-10 02:29:10 +00:00
yyh
fc8d0a0187 fix(web): use a primary heading on the install page (#40194) 2026-08-10 02:26:36 +00:00
yyh
96960499ef fix(web): use primary headings on auth pages (#40192) 2026-08-10 02:26:10 +00:00
yyh
c2687c16b3 refactor(web): unify infinite scroll sentinels (#40188) 2026-08-10 02:22:07 +00:00
Asuka Minato
883944d289 test: Type test (#40371)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-10 02:13:17 +00:00
yyh
a7156a0702 fix(web): remove workflow output title tab stop (#40377) 2026-08-10 01:52:33 +00:00
yyh
dee9d27af8 fix(web): associate app deletion confirmation label (#40375) 2026-08-10 01:52:09 +00:00
yyh
e06f0ee315 fix(web): hide credential icons from assistive tech (#40376) 2026-08-10 01:51:42 +00:00
chelsealong
7522ae14b2 fix(agent): preserve plugin-declared model parameters through Agent Soul (#40163)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-09 08:48:01 +00:00
Likalikali
e09eee8fd1 refactor: replace manual model_validate with @model_validate in datasets controllers (#40236)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-09 08:25:27 +00:00
Likalikali
b692ddd80c refactor: replace manual model_validate with @model_validate in workspace remaining controllers (#40239)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-09 08:23:51 +00:00
Likalikali
5ebb389d26 refactor: replace manual model_validate with @model_validate in rag_pipeline controllers (#40237) 2026-08-09 08:22:50 +00:00
Likalikali
fff6f7cf2f refactor: replace manual model_validate with @model_validate in app workflow controllers (#40235) 2026-08-09 08:20:10 +00:00
Likalikali
516fd12b8d refactor: replace manual model_validate with @model_validate in app core controllers (#40234)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-09 08:18:02 +00:00
Likalikali
925ca49f21 refactor: replace manual model_validate with @model_validate in explore/snippets controllers (#40241) 2026-08-09 07:07:08 +00:00
Likalikali
a1577fc48c refactor: replace manual model_validate with @model_validate in auth/billing/tag controllers (#40240) 2026-08-09 06:14:07 +00:00
Likalikali
acda0341ed refactor: replace manual model_validate with @model_validate in workspace plugin/tool controllers (#40238) 2026-08-09 06:13:24 +00:00
Likalikali
98378cfe03 refactor: replace manual model_validate with @model_validate in agent controllers (#40233) 2026-08-09 06:11:33 +00:00
非法操作
3f89a3c742 fix(workflow): fall back when default socket is unavailable (#40191) 2026-08-09 04:13:41 +00:00
medimedi
e036075e22 chore: Remove redundant dataset context string conversions (#40189) 2026-08-08 18:26:52 +00:00
Asuka Minato
5a84cde198 test: move RAG pipeline workflow coverage to unit tests (#38937) 2026-08-08 12:00:32 +00:00
Byron.wang
4e18ab0ad4 refactor(api): decouple setup and spec endpoints (#40104) 2026-08-08 11:52:15 +00:00
chelsealong
2a742486c5 fix(agent-v2): accept composer UI ids on manual metadata filter conditions (#40171)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-08 06:55:27 +00:00
Likalikali
d362bdbb4e refactor: replace manual model_validate with @model_validate decorator in app controllers (#40170) 2026-08-08 05:47:11 +00:00
Likalikali
60d6be5b13 chore: dep inject for model in explore workflow run (#40158) 2026-08-08 02:50:27 +00:00
Likalikali
cc1b55aaf7 chore: dep inject for model in explore apis (#40160)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-08 02:23:17 +00:00
yyh
d1fa17032e revert(web): use suspense boundary in home page (#40167) 2026-08-07 18:50:33 +00:00
盐粒 Yanli
916d7e1c96 refactor(dify-agent): download Binding files through Agent Stub (#40143)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-07 14:56:52 +00:00
Likalikali
c094117ca2 chore: dep inject for model in agent app sandbox upload (#40153) 2026-08-07 13:28:31 +00:00
Likalikali
c6b1311aa3 chore: dep inject for model in workspace snippets, load balancing, and endpoint (#40161) 2026-08-07 13:22:02 +00:00
Likalikali
515c3d0c62 chore: dep inject for model in onboarding step by step tour (#40155) 2026-08-07 12:41:22 +00:00
Likalikali
fe94ddaaeb chore: dep inject for model in workflow run archive download (#40157) 2026-08-07 12:40:44 +00:00
Likalikali
3e8c0fdcef chore: dep inject for model in website crawl api (#40156) 2026-08-07 12:40:12 +00:00
Likalikali
055462fe6e chore: dep inject for model in tags, mcp server, and data source auth (#40159) 2026-08-07 12:38:29 +00:00
Likalikali
06e229e8b2 chore: dep inject for model in api based extension (#40154) 2026-08-07 12:37:50 +00:00
Likalikali
fa498ad7a2 chore: dep inject for model in oauth server (#40147) 2026-08-07 11:16:11 +00:00
Likalikali
a279be91a8 chore: dep inject for model in datasets document and web human input … (#40151) 2026-08-07 11:15:43 +00:00
盐粒 Yanli
12300f3833 feat(dify-agent): propagate run limit error types (#40116)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-07 10:37:22 +00:00
Joel
b439b6a800 feat: support accessibility checks in CI (#40137) 2026-08-07 10:28:44 +00:00
github-actions[bot]
7a7d8fe19e chore(i18n): sync translations with en-US (#40150)
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
2026-08-07 10:10:33 +00:00
Joel
2635d1b3df fix: improve readability of DSL import warnings (#40148) 2026-08-07 10:01:09 +00:00
yyh
a952487789 chore(web): remove unreachable explore sidebar (#40136) 2026-08-07 09:29:44 +00:00
WH-2099
c9e6db5ef2 fix(api): scope temporary capabilities to owners (#39863) 2026-08-07 09:21:13 +00:00
Likalikali
b31e66107c chore: dep inject for model in notification dismiss (#40146) 2026-08-07 09:02:49 +00:00
Joel
42d6589ce2 fix: show inline agent build draft change details (#40140) 2026-08-07 07:28:41 +00:00
yyh
f00d0329d4 perf(web): prefetch app links on intent (#40133)
Co-authored-by: 非法操作 <hjlarry@163.com>
2026-08-07 07:16:38 +00:00
yyh
af9d2d00a3 chore(web): add dedicated home loading boundary (#40135) 2026-08-07 07:16:25 +00:00
非法操作
ae8cb996c7 chore: use multi-arch plugin daemon image tag (#40139) 2026-08-07 07:01:06 +00:00
盐粒 Yanli
adb89a8926 refactor(dify-agent): make config pulls direct and remove gRPC (#40044) 2026-08-07 06:54:07 +00:00
非法操作
3a4920c595 chore: bump plugin daemon image (#40134) 2026-08-07 06:22:33 +00:00
yyh
276c3b6e02 refactor(web): localize education status query (#40132)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-07 05:29:31 +00:00
Mubelotix
7ff5c85796 docs: Fixes Star History chart (#40115) 2026-08-07 05:23:22 +00:00
yyh
b8330df96e refactor(web): simplify billing portal link (#40131) 2026-08-07 04:26:18 +00:00
yyh
7422052759 fix(web): scope hidden outlines to focus-visible (#40130) 2026-08-07 04:00:19 +00:00
Xiyuan Chen
ab0e131e87 refactor(api): move license expiry notice flag onto license detail (#40128)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-07 03:53:35 +00:00
Asuka Minato
1375dc3864 test: migrate console app sessions to SQLite (#40081)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-07 03:46:27 +00:00
Asuka Minato
6530f2bcdb test: migrate document indexing task sessions to SQLite (#40092)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-07 03:45:56 +00:00
Asuka Minato
7039217c99 test: use sqlite sessions at generation boundaries (#40095) 2026-08-07 03:45:27 +00:00
yyh
924d787e41 fix(web): enforce frame ancestors on protected routes (#40124)
Signed-off-by: yyh <yuanyouhuilyz@gmail.com>
2026-08-07 03:11:30 +00:00
非法操作
baba36d47d chore: improve current workspace summary (#40121)
Co-authored-by: Jingyi-Dify <jingyi.qi@dify.ai>
2026-08-07 03:08:55 +00:00
Xiyuan Chen
4b2c5ac4ae feat: make the console license expiry badge optional (#39972)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-07 02:28:58 +00:00
yyh
73197e4354 refactor(web): modernize Studio app list data flow (#40109) 2026-08-07 02:23:38 +00:00
Jingyi
5dfd83e9ab feat: optimize integrations initial loading (#40118)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-07 02:06:25 +00:00
yyh
6f2e4d72d3 test(e2e): align duplicate Agent publish state (#40108) 2026-08-07 01:56:05 +00:00
Byron.wang
b76a14d71d refactor(api): decouple console queries through application services (#40031) 2026-08-07 00:42:55 +00:00
Yunlu Wen
1983e842ca feat: support azure keyvault (#39933)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: -LAN- <laipz8200@outlook.com>
2026-08-07 00:42:13 +00:00
zyssyz123
90d6046345 fix: gate Agent access until first publish (#40105)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
2026-08-06 12:36:24 +00:00
盐粒 Yanli
05c7386013 fix(dify-agent): end SSE streams on terminal events (#40042) 2026-08-06 10:53:10 +00:00
盐粒 Yanli
4d0bc32dd3 fix(dify-agent): align agent and shell execution limits (#40043)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-06 10:53:03 +00:00
yyh
d6336c5d49 revert(web): remove redundant slash picker intent tracking (#40103) 2026-08-06 09:20:46 +00:00
yyh
7073baa737 fix(ci): switch Playwright jobs to Azure Ubuntu mirror (#40100) 2026-08-06 09:01:37 +00:00
Asuka Minato
78129cf6c3 test: use SQLite sessions in datasource files (#39048) 2026-08-06 08:28:27 +00:00
Asuka Minato
1a69435fff test: use sqlite3 session in test_external_dataset_service (#38696)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-06 08:27:37 +00:00
yyh
33b238343b chore: remove obsolete development docs (#40098) 2026-08-06 08:21:17 +00:00
github-actions[bot]
4b8a2c7e6c chore(i18n): sync translations with en-US (#40096)
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
2026-08-06 08:14:10 +00:00
Joel
06d8301a90 fix: report unavailable agent tools in publish and workflow checks (#40077) 2026-08-06 07:44:22 +00:00
yyh
dc309ced59 chore(web): remove obsolete PWA assets (#40082) 2026-08-06 07:41:01 +00:00
Elliot Bai
cf88aef710 feat: support TiDB Vector full-text and hybrid search (#38112)
Co-authored-by: Crazywoola <100913391+crazywoola@users.noreply.github.com>
Co-authored-by: bkidy <bkidyy.macmini@gmail.com>
2026-08-06 07:08:42 +00:00
BoneNI
0277b9eb30 feat: Add Lao (lo-LA) language support #39489 (#39474)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: crazywoola <427733928@qq.com>
2026-08-06 07:00:37 +00:00
Eldar Dadashov
8fbbfbc243 fix(web): register audio listeners on real media events (#37841)
Co-authored-by: crazywoola <427733928@qq.com>
2026-08-06 06:57:58 +00:00
wangxiaolei
5bceac05eb fix: get role and list role need filter billing permission key (#38218)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-06 06:37:52 +00:00
yyh
febcc4e054 chore: format GitHub metadata with Oxfmt (#40073) 2026-08-06 06:37:06 +00:00
Souravrajvi0
36c990a0cf fix(web): only open slash variable picker when / is typed (#39755) (#39761) 2026-08-06 06:36:30 +00:00
yyh
658d5e0dcf fix(e2e): align marketplace plugin download URL (#40075) 2026-08-06 06:32:16 +00:00
yyh
cfef48c408 chore: upgrade workspace dependencies (#40069) 2026-08-06 05:56:30 +00:00
Liu Ziming
1973a2e96f feat(trace-aliyun): GenAI spans for LLM TTFT, agent ReAct, tools, and failed LLM nodes (#39339)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-06 05:51:28 +00:00
Asuka Minato
b105f21763 test: use SQLite sessions in core repositories (#39061)
Co-authored-by: Byron Wang <byron@dify.ai>
2026-08-06 05:50:40 +00:00
Wu Tianwei
e5a07e97a4 fix(web): improve markdown form rendering (#40070) 2026-08-06 05:49:24 +00:00
Asuka Minato
046df1260a test: use SQLite sessions in controllers console app (#39096)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-06 05:25:01 +00:00
Asuka Minato
9e95e1302e test: use SQLite sessions in commands (#39082) 2026-08-06 05:14:38 +00:00
Asuka Minato
59cbba3b37 test: use SQLite sessions in controllers console auth (#39060) 2026-08-06 05:12:35 +00:00
Asuka Minato
20b31de791 test: use SQLite sessions in core entities (#39056)
Co-authored-by: Byron Wang <byron@dify.ai>
2026-08-06 05:10:04 +00:00
yyh
5e036e5489 refactor(system-features): derive nullable SSO protocol (#40063) 2026-08-06 04:51:32 +00:00
Asuka Minato
e6ede05fe9 test: use SQLite sessions in clean dataset (#39051) 2026-08-06 04:49:10 +00:00
Asuka Minato
7edd05100a test: move webhook service coverage to unit tests (#38945)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-06 04:48:27 +00:00
Asuka Minato
46024b6ad8 test: use SQLite sessions in core app apps (#39083)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-06 04:38:15 +00:00
Asuka Minato
123f128ccc test: use real ORM models in app and API tests (#40020) 2026-08-06 04:36:58 +00:00
Joel
6474059eb1 fix: hide log detail actions for legacy app logs (#40057) 2026-08-06 04:18:23 +00:00
Asuka Minato
479a5613a8 test: use real ORM models in dataset service tests (#40018) 2026-08-06 04:14:12 +00:00
Joel
d51900974f fix: offset legacy app error toasts below model controls (#40040)
Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
2026-08-06 04:14:12 +00:00
Asuka Minato
f08cc41546 test: use SQLite sessions in services core (#39058) 2026-08-06 04:07:01 +00:00
Asuka Minato
2443df2e42 test: use real ORM models in workflow repository tests (#40019) 2026-08-06 04:06:04 +00:00
Asuka Minato
2e65ab9d1e test: use SQLite sessions in core tools (#39108) 2026-08-06 03:57:33 +00:00
Aiden
6add64a44d fix(api): allow account avatars across workspaces (#40055)
Co-authored-by: aiden <zhouyuchi@kurogames.com>
2026-08-06 03:33:23 +00:00
非法操作
8170a2a5f3 chore: more upload file size for paid user (#39967)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-06 03:23:16 +00:00
pineapple880066
70051950ab fix: preserve UTF-8 byte size for text uploads (#40034) 2026-08-06 02:25:29 +00:00
csurong
f7881bb635 fix: make document retry batches consistent (#39978)
Co-authored-by: caosurong <surong.cao@thinkingdata.cn>
2026-08-06 02:01:14 +00:00
Escape0707
b6b3e747f3 refactor(api): extract workspace member listing into layered service (#39974)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-06 01:08:39 +00:00
Jingyi
18f740402f fix(web): redirect legacy plugin fallbacks (#40051)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-05 23:27:08 +00:00
Jingyi
15a5317bd3 fix(web): refresh model provider plugins after updates (#40002) 2026-08-05 23:26:18 +00:00
盐粒 Yanli
1369a2cdfc fix(dify-agent): wait for E2B shellctl readiness (#39996) 2026-08-05 11:03:06 +00:00
Asuka Minato
ac0c909d11 test: use real ORM models in RAG indexing tests (#40017) 2026-08-05 10:03:23 +00:00
林玮 (Jade Lin)
945503523b fix(web): improve debug plugin copy accessibility (#40035) 2026-08-05 10:00:37 +00:00
Asuka Minato
fe7e2dc62f test: use sqlite3 session in test_agent_config_service (#38764) 2026-08-05 08:43:40 +00:00
Asuka Minato
3bb21a9a88 test: use sqlite3 session in test_credit_pool_service (#38694) 2026-08-05 08:43:27 +00:00
yyh
dc09384b1d refactor(web): derive system feature enums from schemas (#40030) 2026-08-05 08:32:54 +00:00
yyh
890e5aa294 refactor(web): align query client ownership (#40024) 2026-08-05 07:02:09 +00:00
yyh
0bf3416431 fix(web): remove misleading ARIA states (#40015) 2026-08-05 06:52:41 +00:00
yyh
685e291e65 refactor(web): remove duplicate dataset title update (#40023) 2026-08-05 06:18:09 +00:00
yyh
c15dd6d994 refactor(web): simplify tag selector trigger (#40014) 2026-08-05 05:23:53 +00:00
Joel
72b30ff313 chore: add copy action to workflow log errors (#40011) 2026-08-05 05:15:59 +00:00
yyh
7dd7b3dfa8 fix(ci): make web workflows reproducible (#40010) 2026-08-05 04:08:12 +00:00
yyh
d033124552 fix(ci): harden Playwright browser installs (#40009) 2026-08-05 03:57:08 +00:00
yyh
2fd8f98f2d chore(deps): upgrade Base UI to 1.7.0 (#40006) 2026-08-05 03:55:46 +00:00
Asuka Minato
7d6d173b01 test: use SQLite in Arize Phoenix traces (#38984) 2026-08-05 03:45:06 +00:00
yyh
2dc6b08044 fix(web): preserve feedback state on submission failure (#40004) 2026-08-05 02:55:50 +00:00
Byron.wang
896e5e20c0 refactor(api): extract workspace list into layered application service (#39822)
Co-authored-by: WH-2099 <wh2099@pm.me>
2026-08-05 02:36:16 +00:00
yyh
143bc121da fix(e2e): configure sandbox-reachable API URL (#40005) 2026-08-05 02:28:16 +00:00
zyssyz123
4213e6b150 fix(agent): expose feedback in agent logs (#39994)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-04 14:11:13 +00:00
盐粒 Yanli
b462cb041d feat(agent): separate CLI file URL audiences (#39952)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-04 13:14:02 +00:00
nightcityblade
9d81f0da10 chore(api): remove unreachable match suppressions (#39949)
Co-authored-by: nightcityblade <nightcityblade@gmail.com>
2026-08-04 11:56:37 +00:00
Asuka Minato
482ec5e712 test: use sqlite3 session in test_qa_index_processor (#38765) 2026-08-04 10:53:55 +00:00
Asuka Minato
36a4c98732 test: use sqlite3 session in test_if_else (#38753) 2026-08-04 10:53:42 +00:00
yyh
dec1cb3798 fix(ui): align button spacing with design (#39990) 2026-08-04 10:37:16 +00:00
林玮 (Jade Lin)
3ada29bbe0 fix(api): surface system quota exhaustion without fallback (#39986) 2026-08-04 08:49:25 +00:00
非法操作
8f817644e9 fix(workflow): avoid app context dependency in parallel iteration (#39983) 2026-08-04 07:47:49 +00:00
Joel
0271ca6e5f fix: align build and preview chat layouts (#39980) 2026-08-04 07:07:48 +00:00
-LAN-
aab31292d8 feat(workflow): support LLM environment variables (#39125)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-04 06:17:13 +00:00
-LAN-
545bdecff2 chore(docker): move optional settings to service envs (#39970) 2026-08-04 05:28:05 +00:00
yyh
7d92097526 fix(dify-ui): improve select and status dot accessibility (#39971) 2026-08-04 05:14:02 +00:00
Xiyuan Chen
edcd3fc2e3 fix(api): allow external knowledge base creation under enterprise RBAC (#39930) 2026-08-04 04:50:43 +00:00
yyh
be413650ba chore(web): upgrade Next.js to 16.3 (#39962) 2026-08-04 04:46:44 +00:00
-LAN-
2d2cc7cab1 refactor(workflow): move AgentNode events out of graphon (#39845) 2026-08-04 03:54:40 +00:00
dependabot[bot]
2838957004 chore(deps): bump the vdb group with 9 updates (#39911)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: -LAN- <laipz8200@outlook.com>
2026-08-04 03:40:41 +00:00
Yufeng He
f6852205d2 fix(vdb): bound the TiDB Cloud API timeouts (#39953)
Signed-off-by: Yufeng He <40085740+he-yufeng@users.noreply.github.com>
Co-authored-by: -LAN- <laipz8200@outlook.com>
2026-08-04 03:17:05 +00:00
dependabot[bot]
9802329b91 chore(deps): bump aiohttp from 3.14.1 to 3.14.3 in /api (#39959)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: -LAN- <laipz8200@outlook.com>
2026-08-04 03:14:55 +00:00
盐粒 Yanli
dc5192ba11 fix(dify-agent): make run cancellation route-independent (#39942)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-04 03:11:22 +00:00
盐粒 Yanli
21dbc6c60c fix(dify-agent): keep tmux server alive without sessions (#39943) 2026-08-04 03:09:11 +00:00
dependabot[bot]
a1769d0b3d chore(deps): bump cryptography from 49.0.0 to 50.0.0 in /dify-agent (#39958)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: -LAN- <laipz8200@outlook.com>
2026-08-04 03:02:14 +00:00
林玮 (Jade Lin)
be0e2c03e4 feat(api): isolate credentials from local packages (#39957) 2026-08-04 02:50:04 +00:00
Xiyuan Chen
1b7a132afa fix(api): validate installation scope for cached marketplace packages (#39935) 2026-08-04 02:22:45 +00:00
Xiyuan Chen
f2d0001424 fix(api): bump OpenTelemetry to stop duplicate Flask context detach (#39921) 2026-08-04 02:17:53 +00:00
yyh
9ea21e4fd1 perf(web): streaming ssr for home page (#39922) 2026-08-04 02:16:08 +00:00
yyh
5456d4d56e fix(web): improve main navigation responsiveness and tour focus (#39940)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-03 19:05:49 +00:00
Asuka Minato
b4f360127d test: use SQLite sessions in core app apps (#39079) 2026-08-03 15:45:14 +00:00
Asuka Minato
f15a514878 test: use SQLite sessions in core test_provider_manager.py (#39071)
Co-authored-by: Byron Wang <byron@dify.ai>
2026-08-03 15:44:54 +00:00
Asuka Minato
ca1cec6011 test: use SQLite sessions in controllers console explore (#39064) 2026-08-03 15:44:43 +00:00
Asuka Minato
0a05328eb2 test: use SQLite sessions in controllers service api (#39059) 2026-08-03 15:44:25 +00:00
Asuka Minato
6e9a3f8654 test: use SQLite sessions in rag pipeline dsl (#39053) 2026-08-03 15:43:43 +00:00
Asuka Minato
730794426a test: use SQLite sessions in web controller fixtures (#39052) 2026-08-03 15:41:56 +00:00
yyh
a77236e564 fix(web): remove Web Apps loading skeleton (#39939) 2026-08-03 13:41:29 +00:00
yyh
984045190c fix(web): improve home accessibility (#39938) 2026-08-03 13:41:15 +00:00
Ingram Z
612ad161bc fix(dify-agent): atomically finalize run terminals (#39929)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-03 12:02:09 +00:00
mengnanjiugaipeifense
e2bc8f2c17 fix: keep colons in HTTP node form body values on migration (#38861)
Co-authored-by: xiaweiwei67-stack <293320877+xiaweiwei67-stack@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-03 08:39:04 +00:00
wangxiaolei
dc8dd09450 feat: pass image file to llm (#39848)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-03 06:04:32 +00:00
Asuka Minato
982c0667e1 chore: bump pyrefly version (#39876)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-03 05:59:01 +00:00
Ingram Z
66a69c30f5 fix(dify-agent): stabilize E2B config materialization (#39873) 2026-08-03 05:38:05 +00:00
Harsh Kashyap
a5f5acbe0c fix(api): stop echoing the raw api_key in the 403 error message (#39888) (#39902)
Co-authored-by: Harsh Kashyap <Harsh23Kashyap@users.noreply.github.com>
2026-08-03 03:18:06 +00:00
wangxiaolei
2f52ac94fe chore: keep dify-agent env same with dify (#39918) 2026-08-03 03:17:14 +00:00
Wu Tianwei
5d151ec214 fix(web): clarify member permission exception copy (#39917) 2026-08-03 02:51:51 +00:00
Hand Sonic
bb68a05f9e chore: pass session explicitly in ApiModeration (#39885) 2026-08-03 02:33:18 +00:00
dependabot[bot]
61583e3f0f chore(deps): bump the github-actions-dependencies group with 2 updates (#39909)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 02:32:24 +00:00
-LAN-
351577bdb0 feat(workflow): support human input in loop and iteration (#39243)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-03 02:24:18 +00:00
Harsh Kashyap
8dbac96621 fix(vdb-oceanbase): reject trailing newlines in metadata-key and document-id validators (#39884) (#39901)
Co-authored-by: Harsh Kashyap <Harsh23Kashyap@users.noreply.github.com>
2026-08-03 02:17:13 +00:00
Hassan Rady
26b4798e88 perf(dataset): fix N+1 database insert bottleneck in Notion sync (#39899) 2026-08-03 00:57:22 +00:00
yyh
802fe70423 test(web): remove Base UI component mocks (#39877) 2026-08-02 09:51:45 +00:00
Harsh Kashyap
02a9c51a3e fix(api): bound JinaReader and adaptive-crawl HTTP timeouts (#39859) (#39860)
Co-authored-by: Harsh Kashyap <Harsh23Kashyap@users.noreply.github.com>
2026-08-02 02:49:17 +00:00
Taranum Wasu
83b3a8fd88 fix(api): make SSRF-blocked error message actionable (#39867)
Co-authored-by: Taranum01 <50813317+Taranum01@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-02 02:48:44 +00:00
csurong
8a2cf65ec5 fix(matrixone): apply score threshold to vector search (#39784)
Co-authored-by: caosurong <surong.cao@thinkingdata.cn>
2026-08-02 02:43:56 +00:00
kenwoodjw
a42d486bc0 fix(api): prevent cookies from shadowing admin API keys (#39872)
Signed-off-by: kenwoodjw <blackxin55+@gmail.com>
2026-08-02 02:43:29 +00:00
yyh
b6824334cf refactor(web): align Base UI state consumers (#39864)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-01 13:09:30 +00:00
Harsh Kashyap
eec0e2e44e fix(api): bound billing service HTTP timeouts (#39874) (#39875)
Co-authored-by: Harsh Kashyap <Harsh23Kashyap@users.noreply.github.com>
2026-08-01 10:46:13 +00:00
Jony
f6832fddee chore(api): fix typos in config description and comment (#39870)
Co-authored-by: Jony <13896935+zyz619963502zyz@users.noreply.github.com>
2026-08-01 07:41:28 +00:00
WH-2099
e7380865d8 fix(api): scope segment batch deletes (#38217) 2026-08-01 01:39:40 +00:00
yyh
c4d9919d30 fix(web): align secondary sidebar help trigger (#39862) 2026-07-31 20:33:27 +00:00
Chester
4557f127ff fix(auth): add bounded timeout to WaterCrawl credential validation (#39824) 2026-07-31 13:52:02 +00:00
Chester
97e9d8be5a fix(rag): add bounded timeout to Notion extractor requests (#39833) 2026-07-31 13:41:44 +00:00
Chester
074811106d fix(rag): add bounded timeout to Firecrawl extractor requests (#39831) 2026-07-31 13:41:19 +00:00
Asuka Minato
33518407c9 test: use SQLite sessions in services workflow (#39087) 2026-07-31 12:54:41 +00:00
Asuka Minato
f6bbb94112 test: use SQLite sessions in core workflow (#39086) 2026-07-31 12:54:30 +00:00
Asuka Minato
917207414b test: use SQLite sessions in core callback_handler (#39081) 2026-07-31 12:54:20 +00:00
Asuka Minato
753583c06c test: use SQLite sessions in core repositories (#39078) 2026-07-31 12:54:10 +00:00
Asuka Minato
8c4c1dc656 test: use SQLite sessions in core llm_generator (#39070) 2026-07-31 12:54:00 +00:00
Asuka Minato
bab3db7f77 test: use SQLite sessions in core tools (#39068) 2026-07-31 12:53:50 +00:00
Asuka Minato
9ee7750411 test: use SQLite sessions in core ops (#39062)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-31 12:53:32 +00:00
Asuka Minato
5800338911 test: use SQLite sessions in core rag (#39055) 2026-07-31 12:52:42 +00:00
Asuka Minato
5e71fdde0f test: use SQLite sessions in services agent (#39054) 2026-07-31 12:52:11 +00:00
yyh
7e30aba12a refactor(ui): simplify scroll area API (#39857) 2026-07-31 12:43:11 +00:00
yyh
c62ab071eb fix(web): hide prompt log action in agent v2 logs (#39858) 2026-07-31 12:40:44 +00:00
非法操作
b4d93b02fd fix(web): skip auth validation for local file datasource (#39856) 2026-07-31 09:55:48 +00:00
Joel
37bf80dcf6 feat: prioritize configured tools in the agent prompt picker (#39850) 2026-07-31 08:50:54 +00:00
KVOJJJin
f9966c2ee4 fix(workflow): remap snippet references (#39843) 2026-07-31 06:57:10 +00:00
Bond Zhu
c562f78d4f fix(api): silence opentelemetry.context error reports to Sentry on cloud (#39841) 2026-07-31 05:32:02 +00:00
iridescentWen
0d8c02ca62 docs: fix typos in api comments and prompt example (#39838) 2026-07-31 05:30:53 +00:00
Xin Zhang
4b415e7d6b fix: refresh mcp server code by app id (#39828)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-31 04:57:02 +00:00
Escape0707
676dff04c8 test: exercise credential visibility with SQLite (#39827) 2026-07-31 03:20:21 +00:00
Parman Mohammadalizadeh
908dc703ec chore(api): consolidate chained .where() calls into single calls (#39819) 2026-07-30 16:59:50 +00:00
起岚
bea2f78e09 docs: remove trailing whitespace in docker/README.md (#39808) 2026-07-30 16:45:37 +00:00
yyh
5e6154fdd1 refactor(web): align Base UI composition contracts (#39820) 2026-07-30 13:37:04 +00:00
wangxiaolei
69a16d8319 feat: change api/v1/plugins/download to api/v1/plugins/download-url (#39811) 2026-07-30 10:23:29 +00:00
yyh
563cf2602f refactor(dify-ui): govern public component APIs (#39806)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-30 10:12:34 +00:00
Evan
3aa937def4 test: use caplog for telemetry error logging (#39722) 2026-07-30 09:32:56 +00:00
Escape0707
f057a7d32f test: use SQLite sessions in app DSL service tests (#39803) 2026-07-30 09:31:12 +00:00
林玮 (Jade Lin)
8cca3959ae feat: make skill package upload size limit configurable (#39799) 2026-07-30 08:42:24 +00:00
yyh
48bb46a72b fix(ui): align select trigger focus ring (#39804) 2026-07-30 08:40:20 +00:00
yyh
6a52069872 refactor(web): narrow app list context (#39802) 2026-07-30 08:24:22 +00:00
yyh
72afcc1326 refactor(web): remove stale header maximize state (#39801) 2026-07-30 08:20:41 +00:00
yyh
e834fa212d refactor(web): remove dead dataset operator context state (#39800) 2026-07-30 08:20:31 +00:00
Joel
b32c900761 feat: add upload size guidance and validation for agent files and skills (#39798) 2026-07-30 07:57:53 +00:00
Jingyi
e8b17345c3 fix(web): isolate MCP card action overlays (#39797) 2026-07-30 07:51:20 +00:00
yyh
95166806ae refactor(web): remove configuration mitt context (#39796) 2026-07-30 07:07:43 +00:00
yyh
e4947811a5 refactor(web): localize retrieval method query (#39795) 2026-07-30 07:07:32 +00:00
yyh
0bb1b4d6d2 refactor(web): internalize trigger limit modal state (#39794) 2026-07-30 07:07:23 +00:00
yyh
01ff1b5128 refactor(web): remove app log drawer context (#39792) 2026-07-30 06:11:33 +00:00
yyh
71ae1d5511 refactor(web): localize dataset external API state (#39791) 2026-07-30 06:11:23 +00:00
yyh
3d01e8389a fix(chat): derive themes per chat root (#39790) 2026-07-30 06:11:13 +00:00
yyh
44a3ea7c0c refactor(web): localize model load balancing modal state (#39789) 2026-07-30 06:10:57 +00:00
Rafli Surya Wijaya
1fd9ab14f9 fix(workflow): provide default values for AgentNodeData fields (#39743) (#39754)
Co-authored-by: -LAN- <laipz8200@outlook.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-30 05:23:48 +00:00
Asuka Minato
0aefcfa373 test: use SQLite sessions in tasks (#39076) 2026-07-30 05:18:19 +00:00
Asuka Minato
09d5aa47bb test: use sqlite3 session in test_workflow_node_execution_truncation (#38734) 2026-07-30 04:47:38 +00:00
Asuka Minato
b852252076 test: use sqlite3 session in test_trial (#38732) 2026-07-30 04:47:18 +00:00
Asuka Minato
814fee5550 test: use sqlite3 session in test_factory (#38731) 2026-07-30 04:39:16 +00:00
Asuka Minato
754c380e2d test: use sqlite3 session in test_billing (#38722) 2026-07-30 04:39:04 +00:00
Asuka Minato
9f17e1ca95 test: move RAG pipeline import coverage to unit tests (#38938) 2026-07-30 04:32:23 +00:00
Asuka Minato
61a5b4d205 test: use SQLite sessions in core tools (#39094) 2026-07-30 04:23:36 +00:00
Asuka Minato
7b33622cdd test: use SQLite in Langfuse traces (#38985) 2026-07-30 04:14:18 +00:00
Asuka Minato
942a16b2a5 test: use SQLite in Opik traces (#38987) 2026-07-30 04:13:58 +00:00
Joel
97a13b6c36 fix: open inline agent editor from checklist warnings (#39781) 2026-07-30 03:22:07 +00:00
李政达
7fd2f4f4e8 fix(api): prevent HITL pause from aborting workflow resume (#39485)
Co-authored-by: 李政达 <1242427577@qq.com>
Co-authored-by: QuantumGhost <obelisk.reg+git@gmail.com>
2026-07-30 03:21:28 +00:00
Asuka Minato
1593b7cc60 test: use SQLite sessions in core app apps (#39102)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-30 03:18:31 +00:00
Asuka Minato
3f1036e55a test: use SQLite sessions in core app apps (#39101) 2026-07-30 03:18:09 +00:00
Asuka Minato
7c9a0ce93b test: use SQLite sessions in controllers console app (#39097)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-30 03:17:48 +00:00
Asuka Minato
9e8733413a test: use SQLite sessions in controllers console app (#39095)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-30 03:07:43 +00:00
Asuka Minato
3453fdce44 test: use SQLite sessions in core rag (#39092)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-30 03:04:18 +00:00
Asuka Minato
6804dd474d test: use SQLite sessions in services workflow (#39091)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-30 03:03:47 +00:00
Asuka Minato
edd6a6e77f test: use SQLite sessions in core repositories (#39073) 2026-07-30 02:53:50 +00:00
Asuka Minato
19b0a8ce08 test: use SQLite sessions in core repositories (#39067) 2026-07-30 02:53:38 +00:00
Asuka Minato
e12e86a308 test: use sqlite3 session in test_completion_completion_app_generator (#38723) 2026-07-30 02:45:54 +00:00
Asuka Minato
b855d71adb test: use SQLite sessions in rag pipeline transform (#39050) 2026-07-30 02:43:48 +00:00
Asuka Minato
87aa982185 test: use SQLite sessions in services data_migration (#39065) 2026-07-30 02:41:42 +00:00
Asuka Minato
bea82fb57f test: use SQLite sessions in services tools (#39063) 2026-07-30 02:39:55 +00:00
yyh
a21d2b1201 fix(web): constrain slash picker triggers (#39768) 2026-07-30 02:23:52 +00:00
Souravrajvi0
fdaa073d53 fix(api): delete custom models stored with legacy model_type values (#39708)
Co-authored-by: Crazywoola <100913391+crazywoola@users.noreply.github.com>
2026-07-30 01:12:26 +00:00
Jony
89ceba027e fix: allow an empty Agent tools selection (#39695) 2026-07-30 01:06:32 +00:00
Checo
832f42a996 fix(socketio): omit socket_timeout from RedisManager pub/sub options (#39587)
Signed-off-by: sergioperezcheco <checo520@outlook.com>
2026-07-30 00:50:21 +00:00
zyssyz123
72c20daa61 fix(plugin): preserve credentials during local replacement (#39764)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-29 12:39:06 +00:00
yyh
81fd1da3ff fix: refactor account about dialog ownership (#39765) 2026-07-29 12:33:26 +00:00
csurong
fc2f1f4f75 fix(matrixone): generate ids for every document (#39734)
Co-authored-by: caosurong <surong.cao@thinkingdata.cn>
2026-07-29 12:31:11 +00:00
wangxiaolei
080a1d42f2 fix: fix hardcode /home/dify (#39767) 2026-07-29 12:27:38 +00:00
Stephen Zhou
0441d27cac chore: canonicalize Tailwind classes (#39762) 2026-07-29 11:58:14 +00:00
Escape0707
10621b5a9e test: migrate account service tests to shared SQLite (#39758) 2026-07-29 11:43:32 +00:00
非法操作
c1fdd6fb78 chore: paginate installed apps (#39739)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
2026-07-29 09:51:34 +00:00
Joel
fd804dfcc0 fix(web): show API errors when agent publishing fails (#39756) 2026-07-29 09:37:18 +00:00
Asuka Minato
155e4fbdc5 test: use SQLite in Tencent traces (#38988) 2026-07-29 09:25:26 +00:00
David Park
20b9278ca3 fix(docker): mount shared storage volume in api_websocket (#39424) 2026-07-29 09:00:37 +00:00
Asuka Minato
2844948aa0 test: use SQLite sessions in core app (#39100)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-29 08:14:06 +00:00
Asuka Minato
62791579ab test: move service dataset controller coverage to unit tests (#38941)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Byron Wang <byron@dify.ai>
2026-07-29 07:57:35 +00:00
yyh
dbabddf1ab fix(web): force render dialog backdrop and use dialog description in education verify modal (#39749) 2026-07-29 07:43:21 +00:00
yyh
3ad925a66a refactor(web): clarify education state ownership (#39748) 2026-07-29 07:25:54 +00:00
Joel
54aced9e20 fix: display workflow run errors in the result panel (#39746) 2026-07-29 07:24:48 +00:00
非法操作
0d6b2fc40c fix: avoid returning unused vectors in TiDB on Qdrant search (#39744) 2026-07-29 06:51:18 +00:00
林玮 (Jade Lin)
14a938c5c5 fix: handle unconfigured LLM workflow streams (#39741) 2026-07-29 06:07:24 +00:00
yyh
d4eab4ae88 refactor(web): consolidate settings state in URL (#39740) 2026-07-29 06:00:55 +00:00
Asuka Minato
8629b91517 test: use SQLite sessions in libs (#39089) 2026-07-29 05:53:33 +00:00
Asuka Minato
0290c8d525 test: use SQLite sessions in core rag (#39106) 2026-07-29 05:52:45 +00:00
Asuka Minato
c5b0772ab0 test: use SQLite sessions in core tools (#39107)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-29 05:52:33 +00:00
Asuka Minato
8e74d7d715 test: use sqlite3 session in test_session (#38772) 2026-07-29 05:51:02 +00:00
Asuka Minato
103c864b35 test: use sqlite3 session in test_sqlalchemy_workflow_execution_repository (#38761) 2026-07-29 05:50:43 +00:00
Asuka Minato
133e974dff test: use sqlite3 session in test_metadata_bug_complete (#38721) 2026-07-29 05:50:26 +00:00
Asuka Minato
958d8a7997 test: use sqlite3 session in test_human_input_timeout_tasks (#38703) 2026-07-29 05:49:56 +00:00
Asuka Minato
b6bfae7e3c test: use sqlite3 session in test_workflow_pause_events (#38688) 2026-07-29 05:49:15 +00:00
yyh
8946d7fbf4 refactor(web): remove workflow node useBoolean usage (#39729) 2026-07-29 03:07:30 +00:00
非法操作
e604fad630 fix(web): gate plugin auth permission hint (#39721) 2026-07-29 02:07:57 +00:00
Xiyuan Chen
f07cc3dfb4 chore(deps): bump wandb 0.28.0 -> 0.28.1 for CVE fix attempt (#39718) 2026-07-29 02:01:54 +00:00
盐粒 Yanli
6506aaae83 chore: add E2B sync and tini supervision (#39705) 2026-07-29 02:01:25 +00:00
盐粒 Yanli
f6683c2c6b feat(agent): make home snapshots optional and use backend defaults (#39702)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-29 02:01:12 +00:00
Xiyuan Chen
7eba562f7d chore(deps): bump starlette, soupsieve, cryptography for CVE fixes (#39716) 2026-07-29 01:47:29 +00:00
yyh
fd412a82e9 refactor(e2e): unify seeded runtime orchestration (#39700) 2026-07-28 15:05:20 +00:00
Escape0707
1419c7c6db test: share unbound unit test sessions (#39690) 2026-07-28 14:12:08 +00:00
Escape0707
7083a953e1 test: enforce strict typing in migrated unit tests (#39689) 2026-07-28 14:04:56 +00:00
yyh
93e7d50845 test(e2e): align Agent tool credential states (#39698) 2026-07-28 13:41:23 +00:00
盐粒 Yanli
a048f35099 refactor: introduce agent working environment architecture (#39480)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-28 13:16:05 +00:00
Yunlu Wen
22cef67804 chore(deps): bump gitpython from 3.1.54 to 3.1.57 in /api (#39684) 2026-07-28 10:27:16 +00:00
Joel
3bc8c69def feat: label agent conversation reset action on hover (#39691) 2026-07-28 10:06:46 +00:00
yyh
798e5ed7a7 refactor(web): derive workspace billing from current workspace (#39674)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-28 09:32:03 +00:00
Escape0707
eef709e475 ci: enforce strict checks for unit tests (#39682) 2026-07-28 09:10:02 +00:00
Escape0707
04158ac8ea ci: replace custom noqa markers with guard ignores (#39679) 2026-07-28 08:52:12 +00:00
Joel
ae0b66311d feat: add missing plugin installation to agent DSL imports (#39680) 2026-07-28 08:23:42 +00:00
dependabot[bot]
b97abe5328 chore: bump nltk from 3.9.4 to 3.10.0 in /api (#39503)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: yunlu.wen <yunlu.wen@dify.ai>
2026-07-28 08:19:15 +00:00
Jyong
d94314627f ci: wait for KnowledgeFS before deployment (#39677) 2026-07-28 07:12:29 +00:00
Shakti
7ec6a57ddf fix: populate completion_params from model schema defaults in Agent node (#39590) 2026-07-28 07:06:49 +00:00
Joel
35b539e35b fix: improve unconfigured agent guidance (#39676) 2026-07-28 07:02:49 +00:00
Asuka Minato
3b040e6bed test: use sqlite3 session in test_web_login (#38725)
Co-authored-by: Byron.wang <byron@dify.ai>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-28 06:37:45 +00:00
Asuka Minato
9300be03f0 test: use sqlite3 session in test_agent_app_feature_service (#38724) 2026-07-28 06:32:07 +00:00
github-actions[bot]
137d4f3f60 chore(i18n): sync translations with en-US (#39671)
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
2026-07-28 06:11:36 +00:00
Asuka Minato
e723b348cf test: use SQLite sessions in core app apps (#39103)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-28 05:54:17 +00:00
Harsh Kashyap
59fb603ec6 fix: reject trailing newlines in alphanumeric() validator (#39666) (#39667)
Co-authored-by: Harsh Kashyap <Harsh23Kashyap@users.noreply.github.com>
2026-07-28 05:49:19 +00:00
Asuka Minato
63f072ebfb test: use SQLite sessions in core rag (#39105)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-28 05:47:22 +00:00
Asuka Minato
0913d04d33 test: use SQLite sessions in services retention (#39074)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-28 05:47:01 +00:00
Asuka Minato
80ff108fc0 test: use SQLite in Aliyun trace utilities (#38983) 2026-07-28 05:40:27 +00:00
Asuka Minato
ea58129ebe test: move workflow app service coverage to unit tests (#38946) 2026-07-28 05:34:59 +00:00
-LAN-
698869460c chore(docker): remove redundant feature preview env (#39035) 2026-07-28 05:34:35 +00:00
Asuka Minato
f3f2f63110 test: use SQLite in LangSmith traces (#38986) 2026-07-28 05:26:52 +00:00
Asuka Minato
b100cdc382 test: use SQLite sessions in core app (#39099)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-28 05:22:47 +00:00
Asuka Minato
9e90b32991 test: use SQLite sessions in core datasource (#39104)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-28 05:22:18 +00:00
非法操作
b2d54cb2e9 chore: improve archived logs hint in logs list page (#39659) 2026-07-28 05:15:35 +00:00
yyh
1e5e47b889 fix: validate plugin installation scope (#39669) 2026-07-28 04:13:20 +00:00
Asuka Minato
dd28b0d165 test: move OAuth server service coverage to unit tests (#38931)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Byron.wang <byron@dify.ai>
2026-07-28 04:09:32 +00:00
Joel
49e74e2f58 fix: prevent the model selector footer from covering options (#39668) 2026-07-28 04:02:28 +00:00
Joel
e6e5d761c2 fix: prevent Safari from clipping the settings close button (#39664)
Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
2026-07-28 04:01:12 +00:00
Asuka Minato
e1ce808567 test: move data source controller coverage to unit tests (#38924) 2026-07-28 03:51:22 +00:00
Asuka Minato
3c7ad816d9 test: use SQLite sessions in commands (#39080) 2026-07-28 03:29:02 +00:00
Asuka Minato
f44dd343da test: use sqlite3 session in test_plugin_service (#38727) 2026-07-28 03:27:58 +00:00
Asuka Minato
2d9b2d50f3 test: use sqlite3 session in test_wraps (#38770) 2026-07-28 03:27:22 +00:00
Asuka Minato
003e0f9614 test: move message cleanup coverage to unit tests (#38932) 2026-07-28 03:26:43 +00:00
Asuka Minato
da0979b373 test: use SQLite sessions in services core (#39090)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Byron.wang <byron@dify.ai>
2026-07-28 03:20:27 +00:00
Asuka Minato
81fb57639e test: use SQLite sessions in controllers service api (#39098)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Byron.wang <byron@dify.ai>
2026-07-28 03:19:17 +00:00
Asuka Minato
1e61078e93 test: use SQLite sessions in services core (#39088) 2026-07-28 03:18:32 +00:00
Escape0707
b597bb1b17 test: separate human input unit and database paths (#39655) 2026-07-28 03:18:01 +00:00
Asuka Minato
65ead05dfc test: use SQLite sessions in services plugin (#39084)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Byron.wang <byron@dify.ai>
2026-07-28 03:16:19 +00:00
wangxiaolei
6f8ed69ee1 fix: fix mcp output_schema is optional (#39453)
Co-authored-by: yunlu.wen <yunlu.wen@dify.ai>
2026-07-28 02:31:18 +00:00
Yunlu Wen
59b879d2df chore: bump version to 1.16.1 (#39653)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-28 01:09:25 +00:00
6645 changed files with 337818 additions and 238765 deletions

View File

@@ -7,12 +7,14 @@ description: Use when writing, changing, or reviewing Cucumber and Playwright te
`e2e/AGENTS.md` owns the suite architecture, lifecycle, commands, tags, generated-client boundaries, fixtures, and cleanup contracts. Read the nearest feature-scoped `AGENTS.md` when one exists. This skill adds no parallel package policy.
Cucumber owns scenario and hook execution and reporting. Playwright provides browser automation, contexts, pages, locators, actions, assertions, request, and tracing APIs; protocol exceptions remain with the package-defined owner. Their timeout domains remain separate, and importing from `@playwright/test` does not make Playwright Test runner configuration, fixtures, or retries applicable to this suite.
## Topic Routing
Read only the bundled reference required by the change:
- Locator, assertion, isolation, or waiting decisions: [`references/playwright-best-practices.md`][playwright]
- Scenario wording, step granularity, expressions, or tag design: [`references/cucumber-best-practices.md`][cucumber]
- Scenario wording, step granularity, expressions, World state, hook visibility, or tag design: [`references/cucumber-best-practices.md`][cucumber]
Check current official Playwright or Cucumber documentation before introducing a framework pattern that local code and references do not already establish.
@@ -23,7 +25,7 @@ Check current official Playwright or Cucumber documentation before introducing a
3. Read the target scenario, matching step definitions, and lifecycle files only when session or shared state matters.
4. Reuse an existing step when wording and behavior match; add one coherent scenario or step when they do not.
5. Keep browser actions and assertions at the public user boundary; keep setup, seed, polling, and cleanup at their package-defined owners.
6. Run the narrowest tagged scenario and package checks documented in `e2e/AGENTS.md`; broaden only for shared hooks, tags, or support changes.
6. For changes, run the narrowest tagged scenario and package checks documented in `e2e/AGENTS.md`; broaden only for shared hooks, tags, or support changes.
For review requests, lead with reproducible correctness failures, flake sources, or demonstrated architecture drift. Report the behavior verified and any external-runtime, browser, or environment gap.

View File

@@ -4,15 +4,18 @@ Use this reference when writing or reviewing Gherkin scenarios, step definitions
Official sources:
- https://cucumber.io/docs/guides/10-minute-tutorial
- https://cucumber.io/docs/cucumber/step-definitions
- https://cucumber.io/docs/bdd/better-gherkin
- https://cucumber.io/docs/gherkin/reference
- https://cucumber.io/docs/gherkin/step-organization
- https://cucumber.io/docs/cucumber/state
- https://cucumber.io/docs/cucumber/cucumber-expressions
- https://github.com/cucumber/cucumber-js/blob/main/docs/support_files/world.md
## What Matters Most
### 1. Treat scenarios as executable specifications
Cucumber scenarios should describe examples of behavior, not test implementation recipes.
Cucumber scenarios should usually describe behavior declaratively, not reproduce an interaction script.
Apply it like this:
@@ -20,11 +23,15 @@ Apply it like this:
- avoid UI-internal wording such as selector details, DOM structure, or component names
- keep language concrete enough that the scenario reads like living documentation
Procedural detail is appropriate when the interaction mechanism is the behavior under test, such as keyboard navigation, focus movement, or a required multi-actor sequence.
### 2. Keep scenarios focused
A scenario should usually prove one workflow or business outcome. If a scenario wanders across several unrelated behaviors, split it.
A scenario should prove one business rule or coherent outcome. Cucumber's three-to-five-step recommendation is a review heuristic, not a hard limit: when a scenario is longer, check for multiple outcomes, incidental setup, or UI procedure that can move behind a domain step.
Keep each scenario centered on one coherent outcome. Avoid hidden dependencies on another scenario's side effects, and keep unavoidable setup outside the behavior narrative unless the precondition matters to the specification.
Use `Given` for initial context, `When` for the event, and `Then` for the expected outcome. Restarting those phases is a prompt to review the narrative, not an automatic failure. Avoid hidden dependencies on another scenario's side effects.
Use `Rule` when several examples illustrate one named business rule. Use a short `Background` only for shared context the reader needs to understand; do not hide fixture preparation, runtime readiness, or long setup there.
### 3. Reuse steps, but only when behavior really matches
@@ -45,6 +52,8 @@ Write a new step when:
Do not optimize for a low step count by making vague steps. Optimize for a small set of truthful, domain-owned steps.
Step definitions share one global matching namespace regardless of their directory. Organize them by domain capability and avoid feature-coupled glue or expressions broad enough to overlap unrelated behavior.
### 4. Prefer Cucumber Expressions
Use Cucumber Expressions for parameters unless regex is clearly necessary.
@@ -62,18 +71,24 @@ Use regex for a bounded natural-language alternative only when it keeps Gherkin
### 5. Keep step definitions thin and meaningful
Step definitions are glue between Gherkin and automation, not a second abstraction language.
Step definitions are glue between Gherkin and automation, not a second abstraction language. A step should express one coherent domain action or outcome; it may call several implementation helpers when that keeps UI mechanics out of the specification.
Keep each step to one user-visible action or assertion. In JavaScript and TypeScript, use `async function` when the step reads Cucumber World state because Cucumber binds `this`; do not leak state across scenarios through module globals.
Cucumber creates a new World for each scenario. Keep scenario state there rather than in module globals. Cucumber.js supports a `world` proxy for arrow functions, but this suite consistently uses typed `async function (this: DifyWorld, ...)` so ownership and TypeScript discovery remain explicit.
Hooks are invisible to feature readers. Keep them for low-level browser lifecycle, cleanup, and diagnostics; express business-relevant context in Gherkin.
### 6. Use tags intentionally
Tags should communicate selection or execution intent, not become ad hoc metadata. A tag does not change runtime behavior unless configuration or hooks implement it.
Tags may communicate stable capability grouping, selection, fixture dependency, or conditional-hook intent. A tag changes runtime behavior only when a runner, seed profile, or hook owns that meaning.
## Review Questions
- Does the scenario read like a real example of product behavior?
- Does it prove one outcome, or combine several independent phases?
- Are the steps behavior-oriented instead of implementation-oriented?
- Is procedural wording necessary to the behavior being tested?
- Is a reused step still truthful in this feature?
- Could a new expression overlap an existing step in the global namespace?
- Would `Rule` clarify the business rule, or would `Background` hide important setup?
- Is a new tag documenting real behavior, or inventing semantics that the suite does not implement?
- Would a new reader understand the outcome without opening the step-definition file?

View File

@@ -6,8 +6,12 @@ Official sources:
- https://playwright.dev/docs/best-practices
- https://playwright.dev/docs/locators
- https://playwright.dev/docs/actionability
- https://playwright.dev/docs/test-assertions
- https://playwright.dev/docs/test-timeouts
- https://playwright.dev/docs/browser-contexts
- https://playwright.dev/docs/events
- https://playwright.dev/docs/trace-viewer
## What Matters Most
@@ -21,28 +25,22 @@ Apply it like this:
- keep scenario state in the runner's scenario-owned context rather than module globals
- model special authentication or session setup through explicit per-scenario fixtures rather than shared mutable state
### 2. Prefer user-facing locators
### 2. Select locators by user contract
Playwright recommends built-in locators that reflect what users perceive on the page.
Prefer built-in locators that match how the target is exposed to users:
Preferred order:
- interactive controls: role and accessible name
- form controls: associated label; use placeholder when it is the relevant stable contract, especially when no label exists
- non-interactive content: visible text or the relevant text alternative
- elements without a meaningful user-facing contract: an intentional test id
1. `getByRole`
2. `getByLabel`
3. `getByPlaceholder`
4. `getByText`
5. `getByTestId` when an explicit test contract is the most stable option
This is a semantic choice, not a fixed ranking. Do not add incorrect roles or accessible names solely to satisfy a locator. When the product element should have user-facing semantics, fix that contract instead.
Avoid raw CSS/XPath selectors unless no stable user-facing contract exists and adding one is not practical.
Also remember:
Locators are strict for single-element actions. Scope to a stable region or use `filter({ has, hasText })` to make the intended target unique. Treat `.first()`, `.last()`, or `.nth()` as a review signal: the positional choice should be intentional and stable, not merely silence ambiguity.
- repeated content usually needs scoping to a stable container
- exact text matching is often too brittle when role/name or label already exists
- `getByTestId` is acceptable when semantics are weak but the contract is intentional
- when a real UI region, card, status, or icon lacks an accessible name, prefer adding that semantic contract in product code before falling back to `getByTestId`
### 3. Use web-first assertions
### 3. Use web-first assertions with the right timeout owner
Playwright assertions auto-wait and retry. Prefer them over manual state inspection.
@@ -64,6 +62,8 @@ If a condition genuinely needs custom retry logic, use Playwright's polling/asse
Use `expect.poll` for non-DOM truth such as API state, backend eventual consistency, generated resources, or captured browser events. For DOM state, use locator assertions so Playwright can apply actionability and web-first retry semantics.
Cucumber step and hook timeouts, Playwright locator/action timeouts, and Playwright assertion timeouts are separate budgets. `browserContext.setDefaultTimeout()` does not change the default five-second assertion timeout. Put an explicit longer assertion timeout only on the readiness owner that needs it; do not raise an outer timeout to mask a shorter inner failure.
### 4. Let actions wait for actionability
Locator actions already wait for the element to be actionable. Do not preface every click/fill with extra timing logic unless the action needs a specific visible/ready assertion for clarity.
@@ -77,15 +77,20 @@ Bad pattern:
- stack arbitrary waits before every action
- wait on unstable implementation details instead of the visible state the user cares about
- use `force: true` to bypass a real hit-target, overlay, or disabled-state failure
When synchronizing on a one-shot popup, download, request, or response, create the wait before triggering the action, then await the event. A scenario-owned listener may instead capture events for a later assertion. Do not use `networkidle` as an application-readiness assertion; wait for the user-visible state or owned backend contract.
### 5. Match debugging to the active harness
Playwright supports traces, screenshots, page snapshots, and browser logs. Configure artifact capture at the runner boundary instead of adding parallel diagnostics to individual scenarios.
Playwright supports traces, screenshots, page snapshots, and browser logs. Configure artifact capture in Cucumber hooks instead of adding parallel diagnostics to individual scenarios. If tracing is introduced, use `browserContext.tracing`; Playwright Test options such as `trace: 'on-first-retry'`, projects, workers, fixtures, reporters, and retries do not configure this harness.
## Review Questions
- Would this locator survive DOM refactors that do not change user-visible behavior?
- Is a positional locator expressing product order, or hiding an ambiguous match?
- Is this assertion using Playwright's retrying semantics?
- Is any explicit wait masking a real readiness problem?
- Does an explicit timeout belong to the condition that is actually slow?
- Was an event wait registered before the action that emits it?
- Does this code preserve per-scenario isolation?
- Is a new abstraction really needed, or does it bypass the runner's scenario-owned context and lifecycle?

View File

@@ -27,7 +27,7 @@ Read only the packs matched by the diff:
- Stable Dify runtime invariants in the named paths: [`references/dify-invariants.md`][dify-invariants]
- General TypeScript or styling quality not owned above: [`references/code-quality.md`][code-quality]
Read `packages/dify-ui/README.md`, `packages/dify-ui/AGENTS.md`, `web/docs/overlay.md`, or `web/docs/test.md` only when the reviewed code falls under that contract. Check current official documentation when local code and bundled references do not settle a framework, browser, or accessibility behavior.
Read `packages/dify-ui/README.md`, `packages/dify-ui/AGENTS.md`, `packages/dify-ui/docs/overlays.md`, or `web/docs/test.md` only when the reviewed code falls under that contract. Check current official documentation when local code and bundled references do not settle a framework, browser, or accessibility behavior.
## Severity And Output

View File

@@ -61,7 +61,7 @@ Flag effects that:
- Transform props/state for rendering.
- Copy one state value into another representing the same concept.
- Handle user actions that belong in event handlers.
- Reset state from props when a keyed reset, stable ID, or render-time derivation would work.
- Reset local state from props or visibility when derivation, a stable semantic identity, or the intended mounted owner already expresses the lifecycle.
- Fetch data that belongs in framework APIs or TanStack Query.
If an effect remains, it must synchronize with a named external system: browser API, subscription, timer, analytics-on-visibility, non-React widget, or imperative DOM integration.
@@ -71,11 +71,24 @@ If an effect remains, it must synchronize with a named external system: browser
Flag:
- Storing derived booleans, disabled flags, default tabs, or loading labels that can be calculated from current query/feature state.
- Per-session state held by a longer-lived visibility coordinator and cleared through an open-state Effect or a generated key when the primitive's mounted-content lifecycle already matches the intended state lifetime.
- A DOM field mirrored into competing prop, default, and React state sources when editing does not require those sources to synchronize.
- Local state used to fake server data or generated contract fields.
- UI state persisted to localStorage when it is live app state.
- Feature-local mock shells wired to unrelated existing APIs before the real API is confirmed.
Prefer render-time derivation. Keep true local state for user choices, transient input, controlled popups, and feature UI state that has no server source.
Review state lifetime before its storage mechanism. For a hidden surface, distinguish the
visibility coordinator from mounted content. State private to one mounted session belongs in that
content owner; promote it only when the draft must survive that content owner's unmount or another
owner coordinates it. A stable semantic identity key may create a new snapshot when the represented
identity changes; a generated key is not a routine reset command.
Prefer render-time derivation. Keep true local state for user choices, transient input, controlled
popups, and feature UI state that has no server source. Submit-only DOM fields may remain
uncontrolled; use local controlled state when React must own the current value to drive rendering
or coordination. Observing change events or tracking a derived fact such as dirty state does not
require mirroring the field value. Do not flag controlled state by itself without a concrete
competing-source, stale-state, or ownership defect.
## Navigation

View File

@@ -1,141 +1,29 @@
# Dify UI Rules
# Dify UI Review Routing
Use these rules whenever a review touches `packages/dify-ui/` or code consuming `@langgenius/dify-ui/*`.
Use this reference when a review touches `packages/dify-ui/` or consumes
`@langgenius/dify-ui/*`. It routes to owner documentation; it does not redefine package
contracts.
Before finalizing findings for those files, read the current local docs that apply:
Read `packages/dify-ui/AGENTS.md` and the primitive implementation first, then only the matching
owner:
- `packages/dify-ui/README.md`
- `packages/dify-ui/AGENTS.md`
- `web/docs/overlay.md` for floating UI
- `packages/dify-ui/src/<primitive>/index.tsx` for the primitive being changed or consumed
| Review area | Canonical owner |
| ------------------------------------------ | ------------------------------------------------------------------- |
| Package boundary and document routing | `packages/dify-ui/AGENTS.md` |
| Imports, exports, public types, and anatomy | `packages/dify-ui/docs/authoring.md` |
| Button or icon-only actions | `packages/dify-ui/src/button/README.md`, `packages/dify-ui/src/icon-button/README.md` |
| Compound inputs | `packages/dify-ui/src/input-group/README.md` |
| Forms and field semantics | `packages/dify-ui/docs/forms.md` |
| Selection and typed values | `packages/dify-ui/docs/selection.md` |
| Portals, layers, and floating surfaces | `packages/dify-ui/docs/overlays.md` |
| Tailwind and radius tokens | `packages/dify-ui/docs/styling.md` |
| Package tests and Storybook | `packages/dify-ui/docs/testing.md` |
## Package Boundary
For consumer code under `web/`, also read `web/AGENTS.md` for application-owned reuse policy and
`packages/dify-ui/README.md` for the available public subpaths.
Flag in `packages/dify-ui`:
- Imports from `web/`.
- Dependencies on Next.js, i18n, ky, Jotai, Zustand, TanStack Query, oRPC, or business APIs.
- Business-specific component behavior that belongs in `web/`.
- Multiple unrelated primitives in one component folder.
`packages/dify-ui` is a primitive layer: Base UI headless components + `cva` + `cn` + Dify design tokens.
## Imports And Exports
Flag:
- Consumer imports from `@langgenius/dify-ui` without a subpath.
- Missing `package.json#exports` entry for a new primitive.
- Internal package imports using workspace subpaths instead of relative paths.
- Exported props using internal-only types that consumers cannot import from the component subpath.
- Canonical primitive boundaries or their associated public types using a redundant `Root` suffix when no higher-level convenience component exists in the same subpath.
Consumers use subpath exports such as `@langgenius/dify-ui/button`.
Canonical boundaries use the primitive name and matching public types (`Select` / `SelectProps`). Keep `Root` only to distinguish a low-level anatomy root from a higher-level convenience component (`CheckboxRoot` / `Checkbox`); implementation aliases should still show their Base UI source (`BaseSelect.Root.Props`).
## Props And State
Flag:
- Flattened props where related values need a discriminated union, such as `value` / `defaultValue`, `multiple` / `value`, or `clearable` / `onChange`.
- React state used only to mirror Base UI state for class names.
- JavaScript conditional class logic for visual states that the Dify UI/Base UI primitive already exposes through `data-*` attributes or CSS variables.
- Controlled props added when uncontrolled DOM state or CSS variables would be enough.
- Thin wrappers that rename Base UI parts without adding semantics.
- Generic Base UI selection primitives wrapped without preserving their value generics, such as `Select.Root<Value, Multiple>`, `RadioGroup<Value>`, or `Radio.Root<Value>`.
- Shared select/radio option components that type selected values as `string` while callers pass enums, unions, booleans, numbers, objects, or nullable placeholder values.
Prefer Base UI/Dify UI data attributes and CSS variables for visual state: `data-open`, `data-checked`, `data-disabled`, `data-highlighted`, `data-popup-open`, `group-data-*`, `peer-data-*`, `has-[:focus-visible]`, and primitive CSS variables such as anchor width or transform origin. Use JS conditional classes for product/business state that the primitive does not expose.
For non-string `Select` and `RadioGroup` values, prefer explicit domain generics at the root and at child value carriers. JSX children do not inherit the parent generic, so `RadioGroup<PromptMode>` should compose with `Radio<PromptMode>`, `RadioItem<PromptMode>`, or option values from a typed collection. For `Select`, prefer the Base UI `items` collection pattern for typed value-to-label rendering, and flag string coercion helpers used only to recover display labels.
## Forms
Flag:
- Form-like UI using unrelated `Input` and `Button` pieces without a submit boundary.
- Text-like fields not composed through `Field`, `FieldLabel`, and `FieldControl` when using Dify UI form semantics.
- Select fields using `FieldLabel` instead of `SelectLabel`.
- Slider fields using a generic label instead of `SliderLabel`.
- Checkbox/radio groups missing `Fieldset` and `FieldsetLegend`.
- Field errors or descriptions rendered without `FieldDescription` / `FieldError` relationships.
`Form` is the submit boundary. Dify UI form primitives are not a form state-management framework; business validation and schema-driven behavior belong in `web/`.
## Overlay Contract
Flag:
- Legacy web overlay imports in new or modified code.
- Manual portals around Dify UI overlay primitives.
- Call-site `z-*` overrides on overlays.
- Missing root `isolation: isolate` assumptions when debugging overlay stacking.
- Repeated backdrop, z-index, or portal chrome at call sites.
- Tooltip used for infotips, long text, or interactive content.
All Dify UI body-portalled overlays use `z-50`. Toast uses `z-60`. DOM order handles stacking between overlays.
## Primitive Selection
Flag:
- `Tabs` used for simple mode/filter/view selection where `SegmentedControl` is the semantic primitive.
- `SegmentedControl` used where `tablist` / `tabpanel` semantics are required.
- `Select` used for searchable or free-form input.
- `Combobox` used for unrestricted search text where no selected option is remembered.
- `Autocomplete` used for closed-list selection.
- Tooltip or PreviewCard used for content that must be reachable on touch or by screen readers.
Use:
- `Autocomplete` for free-form text with optional suggestions.
- `Combobox` for searchable selected values from a collection.
- `Select` for closed, scannable option sets.
- `Popover` for infotips, help text, rich content, or interactions.
## Bad Usage Patterns To Flag
Flag:
- Manually recreating UI behavior or chrome already owned by `@langgenius/dify-ui/*` or `web/app/components/base/*`, such as buttons, inputs, toggle groups, popovers, dropdown menus, alert dialogs, switches, avatars, scroll areas, toasts, borders, focus states, disabled states, segmented controls, or existing feature components.
- Styling a raw Base UI primitive directly in `web/` when a Dify UI primitive exists.
- Wrapping a Dify UI primitive in a feature component that hides its label, error, disabled, or focus contract.
- Replacing a semantic primitive with a generic `div` plus classes to match a screenshot.
- Using `Tooltip` because it is visually convenient when the content is actually help text or needs touch access.
- Adding a `z-*` override to make a child popup appear over a parent dialog.
- Adding a new app-level wrapper around Dialog, Drawer, Popover, Select, or Combobox that repeats portal/backdrop/positioner logic.
- Using dify-ui `Input` as a drop-in replacement for legacy inputs that include search, clear, copy, unit, localized placeholder, or number normalization behavior.
- Building a form row from loose text and controls instead of the matching Field/Form primitives.
- Adding component state only to style `data-open`, `data-checked`, `data-disabled`, or highlighted states that Base UI already exposes.
- Passing booleans down only so children can toggle classes already expressible with primitive `data-*` selectors.
## Tokens, Radius, And Styling
Flag:
- `radius-*` class names.
- Custom Tailwind `borderRadius` extension for Figma radius values.
- Generic colors where semantic Dify tokens exist.
- Hardcoded design values where Dify tokens, component variants, or documented Figma radius mappings exist.
- `!` important modifiers used to fight primitive styles instead of fixing the variant, selector, or component composition.
- Manual class strings that duplicate primitive variants.
- `min-w-(--anchor-width)` on picker popups when it defeats viewport clamping.
Use the Figma radius mapping from `packages/dify-ui/README.md`; for example `--radius/sm` maps to `rounded-md`, and `--radius/md` maps to `rounded-lg`.
Use `!` only for a tightly scoped compatibility override after confirming the primitive API, data attributes, and selector structure cannot express the state.
## Focus Details
Flag focus rings attached to the wrong element. For example, Base UI `Slider.Thumb` focuses an internal `input[type=range]`, so the visible thumb wrapper needs `has-[:focus-visible]` rather than direct wrapper `focus-visible`.
## Custom SVG Icons
Flag:
- New generated React icon components or JSON files under `web/app/components/base/icons/src/...` for custom SVG icons.
- Custom SVG icons consumed outside the Tailwind `i-custom-*` icon class pipeline.
- Generated `packages/iconify-collections/custom-*/icons.json` diffs where unrelated existing icons lost or changed intrinsic `width` or `height`.
New custom SVG icons belong in `packages/iconify-collections/assets/...`. Regenerate with `pnpm --filter @dify/iconify-collections generate`, validate with `pnpm --filter @dify/iconify-collections check:dimensions`, and consume the generated icon with Tailwind `i-custom-*` classes.
Treat the implementation, public types, tests, and stories as evidence for the documented
contract. If they disagree, identify the actual owner before reporting a finding. Read current
official Base UI documentation and installed type declarations for upstream-derived behavior.
Report only a reproducible contract violation or observable defect, not a preference inferred from
this routing file.

View File

@@ -9,6 +9,7 @@ Flag missing coverage when a change alters a reachable contract such as:
- User interaction, navigation, form submission, validation, or permissions.
- Query or mutation behavior, URL state, persistence, or one-shot signals.
- Loading, error, empty, and recovery states that users can encounter.
- A hidden surface whose close-and-reopen behavior changes whether in-progress state resets or persists.
- Accessibility-critical labels, keyboard flow, focus, disabled state, or overlay behavior.
- A regression-prone business rule or bug fix that can be reproduced through a public boundary.

View File

@@ -13,4 +13,4 @@ description: Use when writing or changing Vitest or React Testing Library tests
4. Run the focused spec before the affected suite and relevant static checks.
5. Report the behavior verified and any remaining browser, visual, or end-to-end risk.
Recommend deleting low-value tests as readily as adding missing behavior coverage. Use `web/docs/test.md` for policy and Web commands; use the `packages/dify-ui/README.md` Development section for Dify UI commands.
Recommend deleting low-value tests as readily as adding missing behavior coverage. Use `web/docs/test.md` for policy and Web commands; use `packages/dify-ui/docs/testing.md` for Dify UI commands.

View File

@@ -9,10 +9,11 @@ Use this skill to route component architecture decisions to its bundled referenc
## First Decisions
| Question | Default | Promote only when |
| Question | Default | Choose differently when |
| --- | --- | --- |
| Where should code live? | In the product workflow, route, or feature owner. | Several verticals need the same stable contract. |
| Who owns state and handlers? | The lowest visual owner that consumes them. | A parent coordinates one workflow or consistent snapshot. |
| Who owns state and handlers? | The lowest owner that consumes them and whose lifetime matches the state. | Another owner coordinates the value or it must survive the local owner's unmount. |
| Should React control a value? | Leave submit-only DOM fields uncontrolled. | The workflow must own the current value to drive rendering or coordination. |
| Should state enter Jotai? | Keep component and form state local. | Siblings need one source of truth or scoped workflow persistence. |
| Who owns URL state? | Next.js route APIs and `nuqs`. | Atoms require a read-only route-identity bridge. |
| Who owns remote state? | TanStack Query at the lowest consumer. | Atom state drives the query or shared derivations consume it. |
@@ -24,15 +25,15 @@ Use this skill to route component architecture decisions to its bundled referenc
- Component moves, module boundaries, props, types, or owner placement: read [`references/ownership.md`][ownership].
- Jotai, form drafts, route identity, URL state, or persistence: read [`references/state.md`][state].
- Generated contracts, nullable API data, Query, mutations, SSR, auth, or workspace state: read [`references/data.md`][data].
- Hotkeys, focus, dialogs, menus, popovers, or other secondary surfaces: read [`references/interactions.md`][interactions] and the overlay guide it references when applicable.
- Hotkeys, focus, dialogs, menus, popovers, or other secondary surfaces: read [`references/interactions.md`][interactions] and the overlay guide it references when applicable. Also read [`references/state.md`][state] when the surface owns a draft or other local session state.
- Effects, navigation, memoization, preloading, or render cost: read [`references/runtime.md`][runtime].
## Workflow
1. Identify the behavior owner and the public contract being changed.
1. Identify the behavior owner, the required state lifetime, and the public contract being changed.
2. Read the nearby implementation, tests, and only the routed skill references.
3. Implement one coherent vertical slice. Do not expand into equivalent patterns elsewhere unless the current contract cannot be completed without them.
4. Verify observable behavior at the narrowest sufficient boundary, then run the checks documented by the owning package: `web/docs/test.md` or `web/docs/lint.md` for Web, and the `packages/dify-ui/README.md` Development section for Dify UI.
4. Verify observable behavior at the narrowest sufficient boundary, then run the checks documented by the owning package: `web/docs/test.md` or `web/docs/lint.md` for Web, and `packages/dify-ui/docs/testing.md` for Dify UI.
[data]: references/data.md
[interactions]: references/interactions.md

View File

@@ -1,6 +1,6 @@
# Component Interactions And Overlays
Read this document when a change involves application hotkeys, focus, dialogs, menus, popovers, or other secondary surfaces. Overlay primitive selection and layering are owned by the [overlay guide].
Read this document when a change involves application hotkeys, focus, dialogs, menus, popovers, or other secondary surfaces. Overlay primitive selection and layering are owned by the [overlay contract].
## Focus And Semantics
@@ -20,12 +20,13 @@ Read this document when a change involves application hotkeys, focus, dialogs, m
## Secondary Surfaces
- Follow `web/docs/overlay.md` for primitive choice. Dify UI primitives are the default, with package-approved Web wrappers such as `Infotip` where the overlay guide allows them.
- Follow the [overlay contract] for primitive choice and shared mechanics. The nearest consumer `AGENTS.md` owns application-specific composite reuse policy.
- Separate behavior ownership from placement ownership: the action may own trigger, open state, and menu content while the caller owns slots, offsets, and alignment.
- Keep menu and dialog surfaces as siblings when a menu command opens a dialog. Mount the dialog outside popup content.
- Mount controlled overlays unconditionally unless unmounting is required for performance or reset semantics. Prefer keyed or owner-local reset over conditional wrappers.
- Put query and mutation work inside dialog or alert-dialog content when it should mount only after opening.
- Prefer uncontrolled roots when the primitive can own open state. Use controlled state only for business coordination, analytics, cleanup, or explicit reset behavior.
- Do not add manual portals or call-site z-index escalation. Fix ownership and stacking structure at the shared boundary.
- Keep overlay open-state ownership separate from content-session ownership. A controlled root does not require controlled fields or root-owned drafts.
- Match transient state to the primitive's content mount lifecycle. State below an unmounting content boundary gets a fresh instance after unmount; intentionally kept-mounted content needs an explicit persistence or reset policy.
- Keep a controlled overlay root at its coordination owner so the primitive can complete exit transitions, focus restoration, and detached-handle behavior. Do not conditionally remove the root to reset content state, and use keys only for stable semantic identity.
- Place query subscriptions and mutation observers at the owner whose lifetime matches when they should run. Mounted-session work may belong inside content; work that must start or stop exactly with `open` needs an explicit open-state condition.
- Prefer primitive-owned open state unless another owner must observe or coordinate it. Analytics callbacks and local cleanup alone do not require a controlled root.
[overlay guide]: ../../../../web/docs/overlay.md
[overlay contract]: ../../../../packages/dify-ui/docs/overlays.md

View File

@@ -12,8 +12,8 @@ Read this document when adding, moving, splitting, or refactoring React componen
## Component Ownership
- Put state, data access, loading, empty, error, and handlers in the lowest visual owner that uses them.
- Keep coordination in a parent only when it needs one consistent snapshot or coordinates submission, shared selection, batch behavior, navigation, or cross-section loading and errors.
- Put state, data access, loading, empty, error, and handlers in the lowest owner that uses them and whose mounted lifetime matches the required persistence.
- Keep coordination in a parent only when it needs one consistent snapshot, the value must intentionally survive the local owner's unmount, or the parent coordinates submission, shared selection, batch behavior, navigation, or cross-section loading and errors.
- Repeated TanStack Query calls in siblings are acceptable when each sibling independently consumes the data; the cache already deduplicates requests.
- Pass stable domain identity across boundaries. Do not pass raw server data together with separately derived flags for the same concept.
- One pass-through prop layer is acceptable. Repeated forwarding means ownership should move closer to the consumer or into feature-scoped shared state.
@@ -23,7 +23,8 @@ Read this document when adding, moving, splitting, or refactoring React componen
## Boundaries
- State-heavy wizards, drawers, modals, and secondary workflows can form a small vertical surface with an entrypoint, optional feature-local state, and shallow owners matching real visual regions.
- The entrypoint owns route integration, provider wiring, close behavior, and mounting. Composition owners handle workflow branches; the closest visual owner handles section branches.
- The entrypoint owns route integration, provider wiring, placement, and open-state coordination. A content or session owner keeps state scoped to that mounted surface.
- Judge hook lifetime by the component that declares the hook and the primitive's mount contract, not only by where its rendered controls appear in JSX.
- Separate hidden dialogs, dropdowns, and popovers into small local owners when their content obscures the parent flow.
- Keep cohesive forms, menu bodies, and one-off helpers local unless they have their own state, reuse, or semantic boundary.
- Avoid wrapper components and wrapper DOM that only rename props, pass children through, or hide the real primitive. A wrapper must own behavior, validation, state, accessibility, layout, or library integration.

View File

@@ -4,9 +4,10 @@ Read this document when a change introduces Effects, navigation side effects, me
## Effects
- Keep render pure: do not read or write `ref.current` during render except for predictable null-guarded lazy initialization. Update interaction-owned refs in event handlers, synchronize external-system refs after commit, and use state or derivation for rendered values.
- Use Effects only to synchronize with a named external system such as a browser API, subscription, timer, analytics integration, non-React widget, or imperative DOM API.
- Do not use Effects to transform render state, handle user actions, copy query data, reset state from props, or fetch data owned by framework APIs or TanStack Query.
- Initialize query-backed forms with keyed remounts or surface-entry hydration instead of copying data through Effects.
- Initialize query-backed form sessions after their defaults are available instead of copying data through Effects. Use a stable semantic identity key when the represented identity changes; use the intended surface lifecycle for per-session reset.
## Navigation

View File

@@ -9,10 +9,12 @@ Read this document when a change involves Jotai, form drafts, route identity, sh
- Keep server and cache state in TanStack Query. Use existing feature stores for complex, high-frequency interaction state such as workflow canvas drag, resize, and runtime panels.
- Use feature-owned storage only for low-frequency client preferences, dismissed notices, and UI defaults. Live application state does not belong in local storage.
## Forms
## Forms And Sessions
- Prefer uncontrolled Dify UI form and field controls when values are only read at submit time. Initialize query-backed defaults with `defaultValue` and keyed remounts.
- Promote form values to atoms only when another owner reacts to in-progress values, the draft must survive scoped unmounting, or several workflow steps edit the same draft.
- Keep form state in the narrowest owner whose lifetime matches the draft. A draft scoped to one mounted surface belongs to that content or session owner; a draft that must survive its current owner's unmount belongs to an explicit longer-lived feature owner.
- Prefer uncontrolled fields when values are only read at submit time. Use local controlled state only when React must own the current value to drive dependent UI or linked fields; track derived facts such as dirty state without mirroring the field value. Controlledness does not decide whether a draft is local or persisted.
- For query-backed defaults, establish the form session after the required defaults are available. `defaultValue` initializes the current mount; a stable semantic identity key may create a fresh snapshot when the represented identity changes. Do not use a generated key as a routine reset command.
- Promote drafts beyond the session only when another owner reacts to in-progress values, several workflow steps share one draft, or the draft must intentionally survive unmounting. Start with the lowest shared React owner; use feature-scoped atoms only when their coordination or persistence contract is needed.
- Keep validation, source priority, fallback behavior, dirty checks, and payload assembly in the workflow that owns submission.
## Route And URL State

View File

@@ -12,7 +12,7 @@
"features": {
"ghcr.io/devcontainers/features/node:1": {
"nodeGypDependencies": true,
"version": "lts"
"version": "24.20.0"
},
"ghcr.io/devcontainers-extra/features/npm-package:1": {
"package": "typescript",
@@ -46,4 +46,4 @@
// Configure tool-specific properties.
// "customizations": {},
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
}
}

View File

@@ -37,3 +37,7 @@ indent_size = 2
[package.json]
indent_style = space
indent_size = 2
# Oxlint writes its generated suppression baseline without a final newline.
[oxlint-suppressions.json]
insert_final_newline = false

View File

@@ -1,13 +0,0 @@
have_fun: false
memory_config:
disabled: false
code_review:
disable: true
comment_severity_threshold: MEDIUM
max_review_comments: -1
pull_request_opened:
help: false
summary: false
code_review: false
include_drafts: false
ignore_patterns: []

7
.github/CODEOWNERS vendored
View File

@@ -28,6 +28,7 @@
# E2E
/e2e/ @lyzno1
/.github/workflows/web-e2e.yml @lyzno1
# Backend (default owner, more specific rules below will override)
/api/ @QuantumGhost
@@ -245,7 +246,7 @@
# Frontend - Billing and Education
/web/app/components/billing/ @iamjoel @zxhlyh
/web/app/education-apply/ @iamjoel @zxhlyh
/web/app/education/ @iamjoel @zxhlyh
# Frontend - Workspace
/web/app/components/header/account-dropdown/workplace-selector/ @iamjoel @zxhlyh
@@ -267,5 +268,9 @@
/web/app/auth/refresh/route.ts @iamjoel @lyzno1
/web/service/server.ts @iamjoel @lyzno1
# Frontend - Browser Mode Tests
/web/app/**/*.browser.spec.ts @lyzno1
/web/app/**/*.browser.spec.tsx @lyzno1
# Docker
/docker/* @laipz8200

View File

@@ -1,17 +1,17 @@
title: "General Discussion"
title: 'General Discussion'
body:
- type: checkboxes
attributes:
label: Self Checks
description: "To make sure we get to you in time, please check the following :)"
description: 'To make sure we get to you in time, please check the following :)'
options:
- label: I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones.
required: true
- label: I confirm that I am using English to submit this report (我已阅读并同意 [Language Policy](https://github.com/langgenius/dify/issues/1542)).
required: true
- label: "[FOR CHINESE USERS] 请务必使用英文提交 Issue,否则会被关闭。谢谢!:)"
- label: '[FOR CHINESE USERS] 请务必使用英文提交 Issue,否则会被关闭。谢谢!:)'
required: true
- label: "Please do not modify this template :) and fill in all the required fields."
- label: 'Please do not modify this template :) and fill in all the required fields.'
required: true
- type: textarea
attributes:

View File

@@ -1,17 +1,17 @@
title: "Help"
title: 'Help'
body:
- type: checkboxes
attributes:
label: Self Checks
description: "To make sure we get to you in time, please check the following :)"
description: 'To make sure we get to you in time, please check the following :)'
options:
- label: I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones.
required: true
- label: I confirm that I am using English to submit this report (我已阅读并同意 [Language Policy](https://github.com/langgenius/dify/issues/1542)).
required: true
- label: "[FOR CHINESE USERS] 请务必使用英文提交 Issue,否则会被关闭。谢谢!:)"
- label: '[FOR CHINESE USERS] 请务必使用英文提交 Issue,否则会被关闭。谢谢!:)'
required: true
- label: "Please do not modify this template :) and fill in all the required fields."
- label: 'Please do not modify this template :) and fill in all the required fields.'
required: true
- type: textarea
attributes:

View File

@@ -3,15 +3,15 @@ body:
- type: checkboxes
attributes:
label: Self Checks
description: "To make sure we get to you in time, please check the following :)"
description: 'To make sure we get to you in time, please check the following :)'
options:
- label: I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones.
required: true
- label: I confirm that I am using English to submit this report (我已阅读并同意 [Language Policy](https://github.com/langgenius/dify/issues/1542)).
required: true
- label: "[FOR CHINESE USERS] 请务必使用英文提交 Issue,否则会被关闭。谢谢!:)"
- label: '[FOR CHINESE USERS] 请务必使用英文提交 Issue,否则会被关闭。谢谢!:)'
required: true
- label: "Please do not modify this template :) and fill in all the required fields."
- label: 'Please do not modify this template :) and fill in all the required fields.'
required: true
- type: textarea
attributes:

View File

@@ -1,4 +1,4 @@
name: "🕷️ Bug report"
name: '🕷️ Bug report'
description: Report errors or unexpected behavior
labels:
- bug
@@ -6,7 +6,7 @@ body:
- type: checkboxes
attributes:
label: Self Checks
description: "To make sure we get to you in time, please check the following :)"
description: 'To make sure we get to you in time, please check the following :)'
options:
- label: I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542).
required: true
@@ -18,7 +18,7 @@ body:
required: true
- label: 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)
required: true
- label: "Please do not modify this template :) and fill in all the required fields."
- label: 'Please do not modify this template :) and fill in all the required fields.'
required: true
- type: input

View File

@@ -1,13 +1,13 @@
blank_issues_enabled: false
contact_links:
- name: "\U0001F510 Security Vulnerabilities"
url: "https://github.com/langgenius/dify/security/advisories/new"
url: 'https://github.com/langgenius/dify/security/advisories/new'
about: Report security vulnerabilities through GitHub Security Advisories to ensure responsible disclosure. 💡 Please do not report security vulnerabilities in public issues.
- name: "\U0001F4A1 Model Providers & Plugins"
url: "https://github.com/langgenius/dify-official-plugins/issues/new/choose"
url: 'https://github.com/langgenius/dify-official-plugins/issues/new/choose'
about: Report issues with official plugins or model providers, you will need to provide the plugin version and other relevant details.
- name: "\U0001F4AC Documentation Issues"
url: "https://github.com/langgenius/dify-docs/issues/new"
url: 'https://github.com/langgenius/dify-docs/issues/new'
about: Report issues with the documentation, such as typos, outdated information, or missing content. Please provide the specific section and details of the issue.
- name: "\U0001F4E7 Discussions"
url: https://github.com/langgenius/dify/discussions/categories/general

View File

@@ -1,4 +1,4 @@
name: "⭐ Feature or enhancement request"
name: '⭐ Feature or enhancement request'
description: Propose something new.
labels:
- enhancement
@@ -6,7 +6,7 @@ body:
- type: checkboxes
attributes:
label: Self Checks
description: "To make sure we get to you in time, please check the following :)"
description: 'To make sure we get to you in time, please check the following :)'
options:
- label: I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542).
required: true
@@ -14,7 +14,7 @@ body:
required: true
- label: I confirm that I am using English to submit this report, otherwise it will be closed.
required: true
- label: "Please do not modify this template :) and fill in all the required fields."
- label: 'Please do not modify this template :) and fill in all the required fields.'
required: true
- type: textarea
attributes:

View File

@@ -1,11 +1,11 @@
name: "✨ Refactor or Chore"
name: '✨ Refactor or Chore'
description: Refactor existing code or perform maintenance chores to improve readability and reliability.
title: "[Refactor/Chore] "
title: '[Refactor/Chore] '
body:
- type: checkboxes
attributes:
label: Self Checks
description: "To make sure we get to you in time, please check the following :)"
description: 'To make sure we get to you in time, please check the following :)'
options:
- label: I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542).
required: true
@@ -17,26 +17,26 @@ body:
required: true
- label: 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)
required: true
- label: "Please do not modify this template :) and fill in all the required fields."
- label: 'Please do not modify this template :) and fill in all the required fields.'
required: true
- type: textarea
id: description
attributes:
label: Description
placeholder: "Describe the refactor or chore you are proposing."
placeholder: 'Describe the refactor or chore you are proposing.'
validations:
required: true
- type: textarea
id: motivation
attributes:
label: Motivation
placeholder: "Explain why this refactor or chore is necessary."
placeholder: 'Explain why this refactor or chore is necessary.'
validations:
required: false
- type: textarea
id: additional-context
attributes:
label: Additional Context
placeholder: "Add any other context or screenshots about the request here."
placeholder: 'Add any other context or screenshots about the request here.'
validations:
required: false

View File

@@ -5,12 +5,12 @@ runs:
using: composite
steps:
- name: Setup pnpm
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
with:
run_install: false
- name: Setup Vite+
uses: voidzero-dev/setup-vp@ca1c46663915d6c1042ae23bd39ab85718bfb0fa # v1.10.0
uses: voidzero-dev/setup-vp@1b32467adbe183473499fd9d5d372c3ed9641754 # v1.18.0
with:
node-version-file: .nvmrc
node-version-file: package.json
cache: true
run-install: true

328
.github/dependabot.yml vendored
View File

@@ -1,223 +1,223 @@
version: 2
updates:
- package-ecosystem: "uv"
directory: "/api"
- package-ecosystem: 'uv'
directory: '/api'
open-pull-requests-limit: 10
schedule:
interval: "weekly"
interval: 'weekly'
groups:
flask:
patterns:
- "flask"
- "flask-*"
- "werkzeug"
- "gunicorn"
- 'flask'
- 'flask-*'
- 'werkzeug'
- 'gunicorn'
google:
patterns:
- "google-*"
- "googleapis-*"
- 'google-*'
- 'googleapis-*'
opentelemetry:
patterns:
- "opentelemetry-*"
- 'opentelemetry-*'
pydantic:
patterns:
- "pydantic"
- "pydantic-*"
- 'pydantic'
- 'pydantic-*'
llm:
patterns:
- "langfuse"
- "langsmith"
- "litellm"
- "mlflow*"
- "opik"
- "weave*"
- "arize*"
- "tiktoken"
- "transformers"
- 'langfuse'
- 'langsmith'
- 'litellm'
- 'mlflow*'
- 'opik'
- 'weave*'
- 'arize*'
- 'tiktoken'
- 'transformers'
database:
patterns:
- "sqlalchemy"
- "psycopg2*"
- "psycogreen"
- "redis*"
- "alembic*"
- 'sqlalchemy'
- 'psycopg2*'
- 'psycogreen'
- 'redis*'
- 'alembic*'
storage:
patterns:
- "boto3*"
- "botocore*"
- "azure-*"
- "bce-*"
- "cos-python-*"
- "esdk-obs-*"
- "google-cloud-storage"
- "opendal"
- "oss2"
- "supabase*"
- "tos*"
- 'boto3*'
- 'botocore*'
- 'azure-*'
- 'bce-*'
- 'cos-python-*'
- 'esdk-obs-*'
- 'google-cloud-storage'
- 'opendal'
- 'oss2'
- 'supabase*'
- 'tos*'
vdb:
patterns:
- "alibabacloud*"
- "chromadb"
- "clickhouse-*"
- "clickzetta-*"
- "couchbase"
- "elasticsearch"
- "opensearch-py"
- "oracledb"
- "pgvect*"
- "pymilvus"
- "pymochow"
- "pyobvector"
- "qdrant-client"
- "intersystems-*"
- "tablestore"
- "tcvectordb"
- "tidb-vector"
- "upstash-*"
- "volcengine-*"
- "weaviate-*"
- "xinference-*"
- "mo-vector"
- "mysql-connector-*"
- 'alibabacloud*'
- 'chromadb'
- 'clickhouse-*'
- 'clickzetta-*'
- 'couchbase'
- 'elasticsearch'
- 'opensearch-py'
- 'oracledb'
- 'pgvect*'
- 'pymilvus'
- 'pymochow'
- 'pyobvector'
- 'qdrant-client'
- 'intersystems-*'
- 'tablestore'
- 'tcvectordb'
- 'tidb-vector'
- 'upstash-*'
- 'volcengine-*'
- 'weaviate-*'
- 'xinference-*'
- 'mo-vector'
- 'mysql-connector-*'
dev:
patterns:
- "coverage"
- "dotenv-linter"
- "faker"
- "lxml-stubs"
- "basedpyright"
- "ruff"
- "pytest*"
- "types-*"
- "boto3-stubs"
- "hypothesis"
- "pandas-stubs"
- "scipy-stubs"
- "import-linter"
- "celery-types"
- "mypy*"
- "pyrefly"
- 'coverage'
- 'dotenv-linter'
- 'faker'
- 'lxml-stubs'
- 'basedpyright'
- 'ruff'
- 'pytest*'
- 'types-*'
- 'boto3-stubs'
- 'hypothesis'
- 'pandas-stubs'
- 'scipy-stubs'
- 'import-linter'
- 'celery-types'
- 'mypy*'
- 'pyrefly'
python-packages:
patterns:
- "*"
- package-ecosystem: "github-actions"
directory: "/"
- '*'
- package-ecosystem: 'github-actions'
directory: '/'
open-pull-requests-limit: 5
schedule:
interval: "weekly"
interval: 'weekly'
groups:
github-actions-dependencies:
patterns:
- "*"
- package-ecosystem: "uv"
directory: "/api"
target-branch: "lts/1.13.x"
- '*'
- package-ecosystem: 'uv'
directory: '/api'
target-branch: 'lts/1.13.x'
open-pull-requests-limit: 10
schedule:
interval: "weekly"
interval: 'weekly'
groups:
flask:
patterns:
- "flask"
- "flask-*"
- "werkzeug"
- "gunicorn"
- 'flask'
- 'flask-*'
- 'werkzeug'
- 'gunicorn'
google:
patterns:
- "google-*"
- "googleapis-*"
- 'google-*'
- 'googleapis-*'
opentelemetry:
patterns:
- "opentelemetry-*"
- 'opentelemetry-*'
pydantic:
patterns:
- "pydantic"
- "pydantic-*"
- 'pydantic'
- 'pydantic-*'
llm:
patterns:
- "langfuse"
- "langsmith"
- "litellm"
- "mlflow*"
- "opik"
- "weave*"
- "arize*"
- "tiktoken"
- "transformers"
- 'langfuse'
- 'langsmith'
- 'litellm'
- 'mlflow*'
- 'opik'
- 'weave*'
- 'arize*'
- 'tiktoken'
- 'transformers'
database:
patterns:
- "sqlalchemy"
- "psycopg2*"
- "psycogreen"
- "redis*"
- "alembic*"
- 'sqlalchemy'
- 'psycopg2*'
- 'psycogreen'
- 'redis*'
- 'alembic*'
storage:
patterns:
- "boto3*"
- "botocore*"
- "azure-*"
- "bce-*"
- "cos-python-*"
- "esdk-obs-*"
- "google-cloud-storage"
- "opendal"
- "oss2"
- "supabase*"
- "tos*"
- 'boto3*'
- 'botocore*'
- 'azure-*'
- 'bce-*'
- 'cos-python-*'
- 'esdk-obs-*'
- 'google-cloud-storage'
- 'opendal'
- 'oss2'
- 'supabase*'
- 'tos*'
vdb:
patterns:
- "alibabacloud*"
- "chromadb"
- "clickhouse-*"
- "clickzetta-*"
- "couchbase"
- "elasticsearch"
- "opensearch-py"
- "oracledb"
- "pgvect*"
- "pymilvus"
- "pymochow"
- "pyobvector"
- "qdrant-client"
- "intersystems-*"
- "tablestore"
- "tcvectordb"
- "tidb-vector"
- "upstash-*"
- "volcengine-*"
- "weaviate-*"
- "xinference-*"
- "mo-vector"
- "mysql-connector-*"
- 'alibabacloud*'
- 'chromadb'
- 'clickhouse-*'
- 'clickzetta-*'
- 'couchbase'
- 'elasticsearch'
- 'opensearch-py'
- 'oracledb'
- 'pgvect*'
- 'pymilvus'
- 'pymochow'
- 'pyobvector'
- 'qdrant-client'
- 'intersystems-*'
- 'tablestore'
- 'tcvectordb'
- 'tidb-vector'
- 'upstash-*'
- 'volcengine-*'
- 'weaviate-*'
- 'xinference-*'
- 'mo-vector'
- 'mysql-connector-*'
dev:
patterns:
- "coverage"
- "dotenv-linter"
- "faker"
- "lxml-stubs"
- "basedpyright"
- "ruff"
- "pytest*"
- "types-*"
- "boto3-stubs"
- "hypothesis"
- "pandas-stubs"
- "scipy-stubs"
- "import-linter"
- "celery-types"
- "mypy*"
- "pyrefly"
- 'coverage'
- 'dotenv-linter'
- 'faker'
- 'lxml-stubs'
- 'basedpyright'
- 'ruff'
- 'pytest*'
- 'types-*'
- 'boto3-stubs'
- 'hypothesis'
- 'pandas-stubs'
- 'scipy-stubs'
- 'import-linter'
- 'celery-types'
- 'mypy*'
- 'pyrefly'
python-packages:
patterns:
- "*"
- package-ecosystem: "github-actions"
directory: "/"
target-branch: "lts/1.13.x"
- '*'
- package-ecosystem: 'github-actions'
directory: '/'
target-branch: 'lts/1.13.x'
open-pull-requests-limit: 5
schedule:
interval: "weekly"
interval: 'weekly'
groups:
github-actions-dependencies:
patterns:
- "*"
- '*'

1
.github/labeler.yml vendored
View File

@@ -6,7 +6,6 @@ web:
- 'package.json'
- 'pnpm-lock.yaml'
- 'pnpm-workspace.yaml'
- '.nvmrc'
e2e:
- changed-files:

View File

@@ -1 +1 @@
failure-threshold: "error"
failure-threshold: 'error'

View File

@@ -1,10 +1,11 @@
---
extends: default
rules:
brackets:
max-spaces-inside: 1
comments:
min-spaces-from-content: 1
comments-indentation: disable
document-start: disable
line-length: disable

View File

@@ -1,22 +1,22 @@
{
"Verbose": false,
"Debug": false,
"IgnoreDefaults": false,
"SpacesAfterTabs": false,
"NoColor": false,
"Exclude": [
"^web/public/vs/",
"^web/public/pdf.worker.min.mjs$",
"web/app/components/base/icons/src/vender/"
],
"AllowedContentTypes": [],
"PassedFiles": [],
"Disable": {
"EndOfLine": false,
"Indentation": false,
"IndentSize": true,
"InsertFinalNewline": false,
"TrimTrailingWhitespace": false,
"MaxLineLength": false
}
"Verbose": false,
"Debug": false,
"IgnoreDefaults": false,
"SpacesAfterTabs": false,
"NoColor": false,
"Exclude": [
"^web/public/vs/",
"^web/public/pdf.worker.min.mjs$",
"web/app/components/base/icons/src/vender/"
],
"AllowedContentTypes": [],
"PassedFiles": [],
"Disable": {
"EndOfLine": false,
"Indentation": false,
"IndentSize": true,
"InsertFinalNewline": false,
"TrimTrailingWhitespace": false,
"MaxLineLength": false
}
}

View File

@@ -12,8 +12,8 @@
## Screenshots
| Before | After |
|--------|-------|
| ... | ... |
| ------ | ----- |
| ... | ... |
## Checklist
@@ -21,4 +21,4 @@
- [ ] I understand that this PR may be closed in case there was no previous discussion or issues. (This doesn't apply to typos!)
- [ ] I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
- [ ] I've updated the documentation accordingly.
- [ ] I ran `make lint && make type-check` (backend) and `cd web && pnpm exec vp staged` (frontend) to appease the lint gods
- [ ] I ran `make lint && make type-check` (backend) and `vp staged` (frontend) to appease the lint gods

View File

@@ -8,31 +8,31 @@ const headSha = process.env.HEAD_SHA || ''
const files = (process.env.CHANGED_FILES || '').split(/\s+/).filter(Boolean)
const outputPath = process.env.I18N_CHANGES_OUTPUT_PATH || '/tmp/i18n-changes.json'
const englishPath = fileStem => path.join(repoRoot, 'web', 'i18n', 'en-US', `${fileStem}.json`)
const englishPath = (fileStem) => path.join(repoRoot, 'web', 'i18n', 'en-US', `${fileStem}.json`)
const readCurrentJson = (fileStem) => {
const filePath = englishPath(fileStem)
if (!fs.existsSync(filePath))
return null
if (!fs.existsSync(filePath)) return null
return JSON.parse(fs.readFileSync(filePath, 'utf8'))
}
const readBaseJson = (fileStem) => {
if (!baseSha)
return null
if (!baseSha) return null
try {
const relativePath = `web/i18n/en-US/${fileStem}.json`
const content = execFileSync('git', ['show', `${baseSha}:${relativePath}`], { encoding: 'utf8' })
const content = execFileSync('git', ['show', `${baseSha}:${relativePath}`], {
encoding: 'utf8',
})
return JSON.parse(content)
}
catch {
} catch {
return null
}
}
const compareJson = (beforeValue, afterValue) => JSON.stringify(beforeValue) === JSON.stringify(afterValue)
const compareJson = (beforeValue, afterValue) =>
JSON.stringify(beforeValue) === JSON.stringify(afterValue)
const changes = {}
@@ -59,8 +59,7 @@ for (const fileStem of files) {
}
for (const key of Object.keys(beforeJson)) {
if (!(key in afterJson))
deleted.push(key)
if (!(key in afterJson)) deleted.push(key)
}
changes[fileStem] = {
@@ -78,5 +77,5 @@ fs.writeFileSync(
headSha,
files,
changes,
})
}),
)

101
.github/workflows/accessibility-e2e.yml vendored Normal file
View File

@@ -0,0 +1,101 @@
name: Manual WCAG Accessibility Audit
run-name: WCAG ${{ inputs.level }} · ${{ inputs.page }}
on:
workflow_dispatch:
inputs:
page:
description: Page to scan
required: true
default: home
type: choice
options:
- home
- sign-in
- studio
- agents
- knowledge
- integrations
- all
level:
description: WCAG level to scan
required: true
default: aa
type: choice
options:
- aa
- a
permissions:
contents: read
concurrency:
group: accessibility-e2e-${{ github.ref }}-${{ inputs.page }}-${{ inputs.level }}
cancel-in-progress: true
jobs:
accessibility:
name: WCAG Level ${{ inputs.level == 'a' && 'A' || 'AA' }} · ${{ inputs.page }}
runs-on: ubuntu-24.04
timeout-minutes: 120
defaults:
run:
shell: bash
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup web dependencies
uses: ./.github/actions/setup-web
- name: Setup UV and Python
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
enable-cache: true
python-version: '3.12'
cache-dependency-glob: |
api/uv.lock
- name: Install API dependencies
run: uv sync --project api --dev
- name: Install Chromium for accessibility E2E
timeout-minutes: 15
working-directory: ./e2e
run: vp run e2e:install:ci:chromium
- name: Run automated WCAG Level ${{ inputs.level == 'a' && 'A' || 'AA' }} checks
working-directory: ./e2e
env:
E2E_ADMIN_EMAIL: e2e-admin@example.com
E2E_ADMIN_NAME: E2E Admin
E2E_ADMIN_PASSWORD: E2eAdmin12345
E2E_FORCE_WEB_BUILD: '1'
E2E_INIT_PASSWORD: E2eInit12345
WCAG_PAGE: ${{ inputs.page }}
run: |
if [[ "$WCAG_PAGE" == "all" ]]; then
vp run e2e:accessibility:${{ inputs.level }}
else
pnpm exec tsx ./scripts/run-cucumber.ts --full -- --tags "@axe and @wcag-${{ inputs.level }} and @wcag-page-$WCAG_PAGE"
fi
- name: Upload accessibility Cucumber report
if: ${{ !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: cucumber-report-accessibility-${{ inputs.level }}-${{ inputs.page }}
path: e2e/cucumber-report
retention-days: 7
- name: Upload accessibility E2E logs
if: ${{ !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: e2e-logs-accessibility-${{ inputs.level }}-${{ inputs.page }}
path: e2e/.logs/*.log
include-hidden-files: true
retention-days: 7

View File

@@ -25,7 +25,7 @@ jobs:
strategy:
matrix:
python-version:
- "3.12"
- '3.12'
steps:
- name: Checkout code
@@ -35,7 +35,7 @@ jobs:
persist-credentials: false
- name: Setup UV and Python
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
enable-cache: true
python-version: ${{ matrix.python-version }}
@@ -84,7 +84,7 @@ jobs:
strategy:
matrix:
python-version:
- "3.12"
- '3.12'
steps:
- name: Checkout code
@@ -94,7 +94,7 @@ jobs:
persist-credentials: false
- name: Setup UV and Python
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
enable-cache: true
python-version: ${{ matrix.python-version }}
@@ -145,10 +145,10 @@ jobs:
persist-credentials: false
- name: Setup UV and Python
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
enable-cache: true
python-version: "3.12"
python-version: '3.12'
cache-dependency-glob: api/uv.lock
- name: Install dependencies

View File

@@ -1,12 +1,10 @@
name: autofix.ci
on:
pull_request:
branches: ["main"]
branches: ['main']
merge_group:
branches: ["main"]
branches: ['main']
types: [checks_requested]
push:
branches: ["main"]
permissions:
contents: read
@@ -32,29 +30,6 @@ jobs:
docker/.env.example
docker/docker-compose-template.yaml
docker/docker-compose.yaml
- name: Check web inputs
if: github.event_name != 'merge_group'
id: web-changes
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
with:
files: |
web/**
cli/**
e2e/**
packages/**
sdks/nodejs-client/**
package.json
pnpm-lock.yaml
pnpm-workspace.yaml
.nvmrc
vite.config.ts
lint.config.ts
eslint.config.mjs
oxlint-suppressions.json
eslint-suppressions.json
.vscode/**
.github/workflows/autofix.yml
.github/workflows/style.yml
- name: Check api inputs
if: github.event_name != 'merge_group'
id: api-changes
@@ -83,13 +58,13 @@ jobs:
dify-agent/**/*.py
dify-agent/pyproject.toml
dify-agent/uv.lock
- if: github.event_name != 'merge_group'
- if: github.event_name != 'merge_group' && (steps.docker-compose-changes.outputs.any_changed == 'true' || steps.api-changes.outputs.any_changed == 'true' || steps.frontend-contract-changes.outputs.any_changed == 'true' || steps.dify-agent-changes.outputs.any_changed == 'true')
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.11"
python-version: '3.11'
- if: github.event_name != 'merge_group'
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
- if: github.event_name != 'merge_group' && (steps.api-changes.outputs.any_changed == 'true' || steps.frontend-contract-changes.outputs.any_changed == 'true' || steps.dify-agent-changes.outputs.any_changed == 'true')
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
- name: Generate Docker Compose
if: github.event_name != 'merge_group' && steps.docker-compose-changes.outputs.any_changed == 'true'
@@ -119,12 +94,6 @@ jobs:
# Format code
uv run ruff format .
- name: count migration progress
if: github.event_name != 'merge_group' && steps.api-changes.outputs.any_changed == 'true'
run: |
cd api
./cnt_base.sh
- name: ast-grep
if: github.event_name != 'merge_group' && steps.api-changes.outputs.any_changed == 'true'
run: |
@@ -156,7 +125,7 @@ jobs:
find . -name "*.py.bak" -type f -delete
- name: Setup web environment
if: github.event_name != 'merge_group'
if: github.event_name != 'merge_group' && steps.frontend-contract-changes.outputs.any_changed == 'true'
uses: ./.github/actions/setup-web
- name: Generate API docs
@@ -169,13 +138,5 @@ jobs:
if: github.event_name != 'merge_group' && steps.frontend-contract-changes.outputs.any_changed == 'true'
run: pnpm --dir packages/contracts gen-api-contract
- name: ESLint fallback autofix
if: github.event_name != 'merge_group' && steps.web-changes.outputs.any_changed == 'true'
run: pnpm lint:eslint:fix --quiet || true
- name: Vite+ static autofix
if: github.event_name != 'merge_group' && (steps.web-changes.outputs.any_changed == 'true' || steps.frontend-contract-changes.outputs.any_changed == 'true')
run: vp check --fix || true
- if: github.event_name != 'merge_group'
uses: autofix-ci/action@c5b2d67aa2274e7b5a18224e8171550871fc7e4a # v1.3.4

View File

@@ -3,13 +3,13 @@ name: Build and Push API & Web
on:
push:
branches:
- "main"
- "deploy/**"
- "build/**"
- "release/e-*"
- "hotfix/**"
- 'main'
- 'deploy/**'
- 'build/**'
- 'release/e-*'
- 'hotfix/**'
tags:
- "*"
- '*'
concurrency:
group: build-push-${{ github.head_ref || github.run_id }}
@@ -33,60 +33,60 @@ jobs:
strategy:
matrix:
include:
- service_name: "build-api-amd64"
image_name_env: "DIFY_API_IMAGE_NAME"
artifact_context: "api"
build_context: "{{defaultContext}}"
file: "api/Dockerfile"
- service_name: 'build-api-amd64'
image_name_env: 'DIFY_API_IMAGE_NAME'
artifact_context: 'api'
build_context: '{{defaultContext}}'
file: 'api/Dockerfile'
platform: linux/amd64
runs_on: depot-ubuntu-24.04-4
- service_name: "build-api-arm64"
image_name_env: "DIFY_API_IMAGE_NAME"
artifact_context: "api"
build_context: "{{defaultContext}}"
file: "api/Dockerfile"
- service_name: 'build-api-arm64'
image_name_env: 'DIFY_API_IMAGE_NAME'
artifact_context: 'api'
build_context: '{{defaultContext}}'
file: 'api/Dockerfile'
platform: linux/arm64
runs_on: depot-ubuntu-24.04-4
- service_name: "build-web-amd64"
image_name_env: "DIFY_WEB_IMAGE_NAME"
artifact_context: "web"
build_context: "{{defaultContext}}"
file: "web/Dockerfile"
- service_name: 'build-web-amd64'
image_name_env: 'DIFY_WEB_IMAGE_NAME'
artifact_context: 'web'
build_context: '{{defaultContext}}'
file: 'web/Dockerfile'
platform: linux/amd64
runs_on: depot-ubuntu-24.04-4
- service_name: "build-web-arm64"
image_name_env: "DIFY_WEB_IMAGE_NAME"
artifact_context: "web"
build_context: "{{defaultContext}}"
file: "web/Dockerfile"
- service_name: 'build-web-arm64'
image_name_env: 'DIFY_WEB_IMAGE_NAME'
artifact_context: 'web'
build_context: '{{defaultContext}}'
file: 'web/Dockerfile'
platform: linux/arm64
runs_on: depot-ubuntu-24.04-4
- service_name: "build-agent-amd64"
image_name_env: "DIFY_AGENT_IMAGE_NAME"
artifact_context: "agent"
build_context: "{{defaultContext}}"
file: "dify-agent/Dockerfile"
- service_name: 'build-agent-amd64'
image_name_env: 'DIFY_AGENT_IMAGE_NAME'
artifact_context: 'agent'
build_context: '{{defaultContext}}'
file: 'dify-agent/Dockerfile'
platform: linux/amd64
runs_on: depot-ubuntu-24.04-4
- service_name: "build-agent-arm64"
image_name_env: "DIFY_AGENT_IMAGE_NAME"
artifact_context: "agent"
build_context: "{{defaultContext}}"
file: "dify-agent/Dockerfile"
- service_name: 'build-agent-arm64'
image_name_env: 'DIFY_AGENT_IMAGE_NAME'
artifact_context: 'agent'
build_context: '{{defaultContext}}'
file: 'dify-agent/Dockerfile'
platform: linux/arm64
runs_on: depot-ubuntu-24.04-4
- service_name: "build-agent-local-sandbox-amd64"
image_name_env: "DIFY_AGENT_LOCAL_SANDBOX_IMAGE_NAME"
artifact_context: "local-sandbox"
build_context: "{{defaultContext}}:dify-agent-runtime"
file: "docker/Dockerfile"
- service_name: 'build-agent-local-sandbox-amd64'
image_name_env: 'DIFY_AGENT_LOCAL_SANDBOX_IMAGE_NAME'
artifact_context: 'local-sandbox'
build_context: '{{defaultContext}}:dify-agent-runtime'
file: 'docker/Dockerfile'
platform: linux/amd64
runs_on: depot-ubuntu-24.04-4
- service_name: "build-agent-local-sandbox-arm64"
image_name_env: "DIFY_AGENT_LOCAL_SANDBOX_IMAGE_NAME"
artifact_context: "local-sandbox"
build_context: "{{defaultContext}}:dify-agent-runtime"
file: "docker/Dockerfile"
- service_name: 'build-agent-local-sandbox-arm64'
image_name_env: 'DIFY_AGENT_LOCAL_SANDBOX_IMAGE_NAME'
artifact_context: 'local-sandbox'
build_context: '{{defaultContext}}:dify-agent-runtime'
file: 'docker/Dockerfile'
platform: linux/arm64
runs_on: depot-ubuntu-24.04-4
@@ -97,13 +97,13 @@ jobs:
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Login to Docker Hub
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
username: ${{ env.DOCKERHUB_USER }}
password: ${{ env.DOCKERHUB_TOKEN }}
- name: Set up Depot CLI
uses: depot/setup-action@15c09a5f77a0840ad4bce955686522a257853461 # v1.7.1
uses: depot/setup-action@91bc8495a33ebfc504ffc89e5674379ccf23c29c # v1.7.2
- name: Extract metadata for Docker
id: meta
@@ -146,21 +146,21 @@ jobs:
strategy:
matrix:
include:
- service_name: "validate-api-amd64"
build_context: "{{defaultContext}}"
file: "api/Dockerfile"
- service_name: "validate-web-amd64"
build_context: "{{defaultContext}}"
file: "web/Dockerfile"
- service_name: "validate-agent-amd64"
build_context: "{{defaultContext}}"
file: "dify-agent/Dockerfile"
- service_name: "validate-agent-local-sandbox-amd64"
build_context: "{{defaultContext}}:dify-agent-runtime"
file: "docker/Dockerfile"
- service_name: 'validate-api-amd64'
build_context: '{{defaultContext}}'
file: 'api/Dockerfile'
- service_name: 'validate-web-amd64'
build_context: '{{defaultContext}}'
file: 'web/Dockerfile'
- service_name: 'validate-agent-amd64'
build_context: '{{defaultContext}}'
file: 'dify-agent/Dockerfile'
- service_name: 'validate-agent-local-sandbox-amd64'
build_context: '{{defaultContext}}:dify-agent-runtime'
file: 'docker/Dockerfile'
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
- name: Validate Docker image
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
@@ -178,18 +178,18 @@ jobs:
strategy:
matrix:
include:
- service_name: "merge-api-images"
image_name_env: "DIFY_API_IMAGE_NAME"
context: "api"
- service_name: "merge-web-images"
image_name_env: "DIFY_WEB_IMAGE_NAME"
context: "web"
- service_name: "merge-agent-images"
image_name_env: "DIFY_AGENT_IMAGE_NAME"
context: "agent"
- service_name: "merge-agent-local-sandbox-images"
image_name_env: "DIFY_AGENT_LOCAL_SANDBOX_IMAGE_NAME"
context: "local-sandbox"
- service_name: 'merge-api-images'
image_name_env: 'DIFY_API_IMAGE_NAME'
context: 'api'
- service_name: 'merge-web-images'
image_name_env: 'DIFY_WEB_IMAGE_NAME'
context: 'web'
- service_name: 'merge-agent-images'
image_name_env: 'DIFY_AGENT_IMAGE_NAME'
context: 'agent'
- service_name: 'merge-agent-local-sandbox-images'
image_name_env: 'DIFY_AGENT_LOCAL_SANDBOX_IMAGE_NAME'
context: 'local-sandbox'
steps:
- name: Download digests
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
@@ -199,7 +199,7 @@ jobs:
merge-multiple: true
- name: Login to Docker Hub
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
username: ${{ env.DOCKERHUB_USER }}
password: ${{ env.DOCKERHUB_TOKEN }}
@@ -229,3 +229,32 @@ jobs:
IMAGE_VERSION: ${{ steps.meta.outputs.version }}
run: |
docker buildx imagetools inspect "$IMAGE_NAME:$IMAGE_VERSION"
sync-e2b-template:
needs: create-manifest
runs-on: ubuntu-24.04
if: github.repository == 'langgenius/dify' && startsWith(github.ref, 'refs/tags/')
strategy:
matrix:
include:
- project: dev
api_key_secret: E2B_API_KEY_DEV
- project: prod
api_key_secret: E2B_API_KEY_PROD
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
- name: Login to Docker Hub
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
username: ${{ env.DOCKERHUB_USER }}
password: ${{ env.DOCKERHUB_TOKEN }}
- name: Sync E2B Template (${{ matrix.project }})
env:
E2B_API_KEY: ${{ secrets[matrix.api_key_secret] }}
run: ./dify-agent-runtime/docker/sync-e2b-template.sh

View File

@@ -4,19 +4,19 @@ on:
workflow_dispatch:
inputs:
cli_ref:
description: "Git ref (default: current branch)"
description: 'Git ref (default: current branch)'
type: string
required: false
edition:
description: "Dify edition"
description: 'Dify edition'
type: choice
required: false
default: ee
options: [ee, ce]
test_scope:
description: "smoke = [P0] only / full = all cases"
description: 'smoke = [P0] only / full = all cases'
type: choice
required: false
default: full
@@ -24,23 +24,23 @@ on:
# ── Suite on/off ────────────────────────────────────────────────────────
suite_framework_output_error:
description: "framework + output + error-handling suites"
description: 'framework + output + error-handling suites'
type: boolean
default: true
suite_discovery:
description: "discovery suite (get app / describe app)"
description: 'discovery suite (get app / describe app)'
type: boolean
default: true
suite_run:
description: "run suite (basic / streaming / conversation / file / hitl)"
description: 'run suite (basic / streaming / conversation / file / hitl)'
type: boolean
default: true
suite_auth:
description: "auth suite (login / status / whoami / use / devices / logout)"
description: 'auth suite (login / status / whoami / use / devices / logout)'
type: boolean
default: true
suite_agent:
description: "agent suite"
description: 'agent suite'
type: boolean
default: true
@@ -51,32 +51,31 @@ permissions:
# Each job reads DIFY_E2E_TOKEN + app IDs from the provision job outputs,
# so global-setup skips minting and finds existing apps in < 10 s.
env:
DIFY_E2E_NO_KEYRING: "1" # Linux CI has no keychain; skip probe
VITEST_RETRY: "2" # Retry flaky staging responses
DIFY_E2E_NO_KEYRING: '1' # Linux CI has no keychain; skip probe
VITEST_RETRY: '2' # Retry flaky staging responses
jobs:
# ════════════════════════════════════════════════════════════════════════════
# 0. PROVISION — mint token + import DSL fixtures (runs once, outputs IDs)
# ════════════════════════════════════════════════════════════════════════════
# ════════════════════════════════════════════════════════════════════════════
# 0. PROVISION — mint token + import DSL fixtures (runs once, outputs IDs)
# ════════════════════════════════════════════════════════════════════════════
provision:
name: "Provision: mint token + DSL apps"
name: 'Provision: mint token + DSL apps'
runs-on: ubuntu-latest
timeout-minutes: 10
outputs:
token: ${{ steps.out.outputs.DIFY_E2E_TOKEN }}
workspace_id: ${{ steps.out.outputs.DIFY_E2E_WORKSPACE_ID }}
workspace_name: ${{ steps.out.outputs.DIFY_E2E_WORKSPACE_NAME }}
ws2_id: ${{ steps.out.outputs.DIFY_E2E_WS2_ID }}
chat_app_id: ${{ steps.out.outputs.DIFY_E2E_CHAT_APP_ID }}
workflow_app_id: ${{ steps.out.outputs.DIFY_E2E_WORKFLOW_APP_ID }}
file_app_id: ${{ steps.out.outputs.DIFY_E2E_FILE_APP_ID }}
file_chat_app_id: ${{ steps.out.outputs.DIFY_E2E_FILE_CHAT_APP_ID }}
hitl_app_id: ${{ steps.out.outputs.DIFY_E2E_HITL_APP_ID }}
hitl_external_app_id: ${{ steps.out.outputs.DIFY_E2E_HITL_EXTERNAL_APP_ID }}
hitl_single_action_app_id: ${{ steps.out.outputs.DIFY_E2E_HITL_SINGLE_ACTION_APP_ID }}
hitl_multi_node_app_id: ${{ steps.out.outputs.DIFY_E2E_HITL_MULTI_NODE_APP_ID }}
ws2_app_id: ${{ steps.out.outputs.DIFY_E2E_WS2_APP_ID }}
token: ${{ steps.out.outputs.DIFY_E2E_TOKEN }}
workspace_id: ${{ steps.out.outputs.DIFY_E2E_WORKSPACE_ID }}
workspace_name: ${{ steps.out.outputs.DIFY_E2E_WORKSPACE_NAME }}
ws2_id: ${{ steps.out.outputs.DIFY_E2E_WS2_ID }}
chat_app_id: ${{ steps.out.outputs.DIFY_E2E_CHAT_APP_ID }}
workflow_app_id: ${{ steps.out.outputs.DIFY_E2E_WORKFLOW_APP_ID }}
file_app_id: ${{ steps.out.outputs.DIFY_E2E_FILE_APP_ID }}
file_chat_app_id: ${{ steps.out.outputs.DIFY_E2E_FILE_CHAT_APP_ID }}
hitl_app_id: ${{ steps.out.outputs.DIFY_E2E_HITL_APP_ID }}
hitl_external_app_id: ${{ steps.out.outputs.DIFY_E2E_HITL_EXTERNAL_APP_ID }}
hitl_single_action_app_id: ${{ steps.out.outputs.DIFY_E2E_HITL_SINGLE_ACTION_APP_ID }}
hitl_multi_node_app_id: ${{ steps.out.outputs.DIFY_E2E_HITL_MULTI_NODE_APP_ID }}
ws2_app_id: ${{ steps.out.outputs.DIFY_E2E_WS2_APP_ID }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
@@ -88,7 +87,7 @@ jobs:
with:
bun-version: latest
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
with:
package_json_field: packageManager
run_install: false
@@ -101,19 +100,19 @@ jobs:
id: out
working-directory: cli
env:
DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }}
DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }}
DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }}
DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }}
DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }}
DIFY_E2E_TOKEN: ${{ secrets.DIFY_E2E_TOKEN }}
DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }}
DIFY_E2E_TOKEN: ${{ secrets.DIFY_E2E_TOKEN }}
DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }}
run: bun scripts/e2e-provision.ts
# ════════════════════════════════════════════════════════════════════════════
# 1-B. framework + output + error-handling (parallel with run/discovery)
# ════════════════════════════════════════════════════════════════════════════
# ════════════════════════════════════════════════════════════════════════════
# 1-B. framework + output + error-handling (parallel with run/discovery)
# ════════════════════════════════════════════════════════════════════════════
suite-framework-output-error:
name: "Suite: framework + output + error-handling"
if: ${{ inputs.suite_framework_output_error != 'false' }}
name: 'Suite: framework + output + error-handling'
if: ${{ inputs.suite_framework_output_error }}
needs: provision
runs-on: ubuntu-latest
timeout-minutes: 20
@@ -130,24 +129,27 @@ jobs:
- uses: ./.github/actions/setup-web
- uses: oven-sh/setup-bun@v2
with: { bun-version: latest }
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
with: { package_json_field: packageManager, run_install: false }
with:
bun-version: latest
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
with:
package_json_field: packageManager
run_install: false
- run: pnpm install --frozen-lockfile
- run: pnpm tree:gen
- name: Run framework + output + error-handling
env:
DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }}
DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }}
DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }}
DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }}
DIFY_E2E_TOKEN: ${{ needs.provision.outputs.token }}
DIFY_E2E_WORKSPACE_ID: ${{ needs.provision.outputs.workspace_id }}
DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }}
DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }}
DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }}
DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }}
DIFY_E2E_TOKEN: ${{ needs.provision.outputs.token }}
DIFY_E2E_WORKSPACE_ID: ${{ needs.provision.outputs.workspace_id }}
DIFY_E2E_WORKSPACE_NAME: ${{ needs.provision.outputs.workspace_name }}
DIFY_E2E_CHAT_APP_ID: ${{ needs.provision.outputs.chat_app_id }}
DIFY_E2E_CHAT_APP_ID: ${{ needs.provision.outputs.chat_app_id }}
DIFY_E2E_WORKFLOW_APP_ID: ${{ needs.provision.outputs.workflow_app_id }}
DIFY_E2E_INCLUDE: "test/e2e/suites/framework/**/*.e2e.ts,test/e2e/suites/output/**/*.e2e.ts,test/e2e/suites/error-handling/**/*.e2e.ts"
DIFY_E2E_INCLUDE: 'test/e2e/suites/framework/**/*.e2e.ts,test/e2e/suites/output/**/*.e2e.ts,test/e2e/suites/error-handling/**/*.e2e.ts'
run: |
if [ "${{ inputs.test_scope }}" = "smoke" ]; then
pnpm test:e2e -- -t "\[P0\]"
@@ -155,12 +157,12 @@ jobs:
pnpm test:e2e
fi
# ════════════════════════════════════════════════════════════════════════════
# 1-C. Discovery (parallel)
# ════════════════════════════════════════════════════════════════════════════
# ════════════════════════════════════════════════════════════════════════════
# 1-C. Discovery (parallel)
# ════════════════════════════════════════════════════════════════════════════
suite-discovery:
name: "Suite: discovery"
if: ${{ inputs.suite_discovery != 'false' }}
name: 'Suite: discovery'
if: ${{ inputs.suite_discovery }}
needs: provision
runs-on: ubuntu-latest
timeout-minutes: 20
@@ -177,25 +179,28 @@ jobs:
- uses: ./.github/actions/setup-web
- uses: oven-sh/setup-bun@v2
with: { bun-version: latest }
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
with: { package_json_field: packageManager, run_install: false }
with:
bun-version: latest
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
with:
package_json_field: packageManager
run_install: false
- run: pnpm install --frozen-lockfile
- run: pnpm tree:gen
- name: Run discovery suite
env:
DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }}
DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }}
DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }}
DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }}
DIFY_E2E_TOKEN: ${{ needs.provision.outputs.token }}
DIFY_E2E_WORKSPACE_ID: ${{ needs.provision.outputs.workspace_id }}
DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }}
DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }}
DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }}
DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }}
DIFY_E2E_TOKEN: ${{ needs.provision.outputs.token }}
DIFY_E2E_WORKSPACE_ID: ${{ needs.provision.outputs.workspace_id }}
DIFY_E2E_WORKSPACE_NAME: ${{ needs.provision.outputs.workspace_name }}
DIFY_E2E_WS2_ID: ${{ needs.provision.outputs.ws2_id }}
DIFY_E2E_CHAT_APP_ID: ${{ needs.provision.outputs.chat_app_id }}
DIFY_E2E_WS2_ID: ${{ needs.provision.outputs.ws2_id }}
DIFY_E2E_CHAT_APP_ID: ${{ needs.provision.outputs.chat_app_id }}
DIFY_E2E_WORKFLOW_APP_ID: ${{ needs.provision.outputs.workflow_app_id }}
DIFY_E2E_INCLUDE: "test/e2e/suites/discovery/**/*.e2e.ts"
DIFY_E2E_INCLUDE: 'test/e2e/suites/discovery/**/*.e2e.ts'
run: |
if [ "${{ inputs.test_scope }}" = "smoke" ]; then
pnpm test:e2e -- -t "\[P0\]"
@@ -203,12 +208,12 @@ jobs:
pnpm test:e2e
fi
# ════════════════════════════════════════════════════════════════════════════
# 1-D. Run suite — 5 files in matrix (parallel)
# ════════════════════════════════════════════════════════════════════════════
# ════════════════════════════════════════════════════════════════════════════
# 1-D. Run suite — 5 files in matrix (parallel)
# ════════════════════════════════════════════════════════════════════════════
suite-run:
name: "Suite: run / ${{ matrix.name }}"
if: ${{ inputs.suite_run != 'false' }}
name: 'Suite: run / ${{ matrix.name }}'
if: ${{ inputs.suite_run }}
needs: provision
runs-on: ubuntu-latest
timeout-minutes: 20
@@ -240,31 +245,34 @@ jobs:
- uses: ./.github/actions/setup-web
- uses: oven-sh/setup-bun@v2
with: { bun-version: latest }
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
with: { package_json_field: packageManager, run_install: false }
with:
bun-version: latest
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
with:
package_json_field: packageManager
run_install: false
- run: pnpm install --frozen-lockfile
- run: pnpm tree:gen
- name: "Run run/${{ matrix.name }}"
- name: 'Run run/${{ matrix.name }}'
env:
DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }}
DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }}
DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }}
DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }}
DIFY_E2E_SSO_TOKEN: ${{ secrets.DIFY_E2E_SSO_TOKEN }}
DIFY_E2E_TOKEN: ${{ needs.provision.outputs.token }}
DIFY_E2E_WORKSPACE_ID: ${{ needs.provision.outputs.workspace_id }}
DIFY_E2E_WORKSPACE_NAME: ${{ needs.provision.outputs.workspace_name }}
DIFY_E2E_CHAT_APP_ID: ${{ needs.provision.outputs.chat_app_id }}
DIFY_E2E_WORKFLOW_APP_ID: ${{ needs.provision.outputs.workflow_app_id }}
DIFY_E2E_FILE_APP_ID: ${{ needs.provision.outputs.file_app_id }}
DIFY_E2E_FILE_CHAT_APP_ID: ${{ needs.provision.outputs.file_chat_app_id }}
DIFY_E2E_HITL_APP_ID: ${{ needs.provision.outputs.hitl_app_id }}
DIFY_E2E_HITL_EXTERNAL_APP_ID: ${{ needs.provision.outputs.hitl_external_app_id }}
DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }}
DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }}
DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }}
DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }}
DIFY_E2E_SSO_TOKEN: ${{ secrets.DIFY_E2E_SSO_TOKEN }}
DIFY_E2E_TOKEN: ${{ needs.provision.outputs.token }}
DIFY_E2E_WORKSPACE_ID: ${{ needs.provision.outputs.workspace_id }}
DIFY_E2E_WORKSPACE_NAME: ${{ needs.provision.outputs.workspace_name }}
DIFY_E2E_CHAT_APP_ID: ${{ needs.provision.outputs.chat_app_id }}
DIFY_E2E_WORKFLOW_APP_ID: ${{ needs.provision.outputs.workflow_app_id }}
DIFY_E2E_FILE_APP_ID: ${{ needs.provision.outputs.file_app_id }}
DIFY_E2E_FILE_CHAT_APP_ID: ${{ needs.provision.outputs.file_chat_app_id }}
DIFY_E2E_HITL_APP_ID: ${{ needs.provision.outputs.hitl_app_id }}
DIFY_E2E_HITL_EXTERNAL_APP_ID: ${{ needs.provision.outputs.hitl_external_app_id }}
DIFY_E2E_HITL_SINGLE_ACTION_APP_ID: ${{ needs.provision.outputs.hitl_single_action_app_id }}
DIFY_E2E_HITL_MULTI_NODE_APP_ID: ${{ needs.provision.outputs.hitl_multi_node_app_id }}
DIFY_E2E_INCLUDE: "test/e2e/suites/run/${{ matrix.file }}"
DIFY_E2E_HITL_MULTI_NODE_APP_ID: ${{ needs.provision.outputs.hitl_multi_node_app_id }}
DIFY_E2E_INCLUDE: 'test/e2e/suites/run/${{ matrix.file }}'
run: |
if [ "${{ inputs.test_scope }}" = "smoke" ]; then
pnpm test:e2e -- -t "\[P0\]"
@@ -280,12 +288,12 @@ jobs:
path: cli/test-results/
retention-days: 3
# ════════════════════════════════════════════════════════════════════════════
# 1-E. auth/login + status + whoami (parallel, read-only, safe)
# ════════════════════════════════════════════════════════════════════════════
# ════════════════════════════════════════════════════════════════════════════
# 1-E. auth/login + status + whoami (parallel, read-only, safe)
# ════════════════════════════════════════════════════════════════════════════
suite-auth-safe:
name: "Suite: auth (login / status / whoami)"
if: ${{ inputs.suite_auth != 'false' }}
name: 'Suite: auth (login / status / whoami)'
if: ${{ inputs.suite_auth }}
needs: provision
runs-on: ubuntu-latest
timeout-minutes: 15
@@ -302,23 +310,26 @@ jobs:
- uses: ./.github/actions/setup-web
- uses: oven-sh/setup-bun@v2
with: { bun-version: latest }
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
with: { package_json_field: packageManager, run_install: false }
with:
bun-version: latest
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
with:
package_json_field: packageManager
run_install: false
- run: pnpm install --frozen-lockfile
- run: pnpm tree:gen
- name: Run auth/login + status + whoami
env:
DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }}
DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }}
DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }}
DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }}
DIFY_E2E_TOKEN: ${{ needs.provision.outputs.token }}
DIFY_E2E_WORKSPACE_ID: ${{ needs.provision.outputs.workspace_id }}
DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }}
DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }}
DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }}
DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }}
DIFY_E2E_TOKEN: ${{ needs.provision.outputs.token }}
DIFY_E2E_WORKSPACE_ID: ${{ needs.provision.outputs.workspace_id }}
DIFY_E2E_WORKSPACE_NAME: ${{ needs.provision.outputs.workspace_name }}
DIFY_E2E_WS2_ID: ${{ needs.provision.outputs.ws2_id }}
DIFY_E2E_INCLUDE: "test/e2e/suites/auth/login.e2e.ts,test/e2e/suites/auth/status.e2e.ts,test/e2e/suites/auth/whoami.e2e.ts"
DIFY_E2E_WS2_ID: ${{ needs.provision.outputs.ws2_id }}
DIFY_E2E_INCLUDE: 'test/e2e/suites/auth/login.e2e.ts,test/e2e/suites/auth/status.e2e.ts,test/e2e/suites/auth/whoami.e2e.ts'
run: |
if [ "${{ inputs.test_scope }}" = "smoke" ]; then
pnpm test:e2e -- -t "\[P0\]"
@@ -326,15 +337,15 @@ jobs:
pnpm test:e2e
fi
# ════════════════════════════════════════════════════════════════════════════
# 2. DESTRUCTIVE — auth/use + devices + logout + agent (serial, runs LAST)
# Must wait for ALL parallel suites to finish to avoid token revocation
# invalidating other in-flight requests.
# ════════════════════════════════════════════════════════════════════════════
# ════════════════════════════════════════════════════════════════════════════
# 2. DESTRUCTIVE — auth/use + devices + logout + agent (serial, runs LAST)
# Must wait for ALL parallel suites to finish to avoid token revocation
# invalidating other in-flight requests.
# ════════════════════════════════════════════════════════════════════════════
suite-last:
name: "Suite: auth-use + devices + logout + agent (last, serial)"
name: 'Suite: auth-use + devices + logout + agent (last, serial)'
# Runs when auth is selected; also runs after all parallel jobs finish
if: ${{ inputs.suite_auth != 'false' || inputs.suite_agent != 'false' }}
if: ${{ inputs.suite_auth || inputs.suite_agent }}
needs:
- provision
- suite-framework-output-error
@@ -358,28 +369,31 @@ jobs:
- uses: ./.github/actions/setup-web
- uses: oven-sh/setup-bun@v2
with: { bun-version: latest }
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
with: { package_json_field: packageManager, run_install: false }
with:
bun-version: latest
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
with:
package_json_field: packageManager
run_install: false
- run: pnpm install --frozen-lockfile
- run: pnpm tree:gen
- name: Run use / devices / logout / agent (serial)
env:
DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }}
DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }}
DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }}
DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }}
DIFY_E2E_TOKEN: ${{ needs.provision.outputs.token }}
DIFY_E2E_WORKSPACE_ID: ${{ needs.provision.outputs.workspace_id }}
DIFY_E2E_WORKSPACE_NAME: ${{ needs.provision.outputs.workspace_name }}
DIFY_E2E_WS2_ID: ${{ needs.provision.outputs.ws2_id }}
DIFY_E2E_CHAT_APP_ID: ${{ needs.provision.outputs.chat_app_id }}
DIFY_E2E_WORKFLOW_APP_ID: ${{ needs.provision.outputs.workflow_app_id }}
DIFY_E2E_HITL_APP_ID: ${{ needs.provision.outputs.hitl_app_id }}
DIFY_E2E_HITL_EXTERNAL_APP_ID: ${{ needs.provision.outputs.hitl_external_app_id }}
DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }}
DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }}
DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }}
DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }}
DIFY_E2E_TOKEN: ${{ needs.provision.outputs.token }}
DIFY_E2E_WORKSPACE_ID: ${{ needs.provision.outputs.workspace_id }}
DIFY_E2E_WORKSPACE_NAME: ${{ needs.provision.outputs.workspace_name }}
DIFY_E2E_WS2_ID: ${{ needs.provision.outputs.ws2_id }}
DIFY_E2E_CHAT_APP_ID: ${{ needs.provision.outputs.chat_app_id }}
DIFY_E2E_WORKFLOW_APP_ID: ${{ needs.provision.outputs.workflow_app_id }}
DIFY_E2E_HITL_APP_ID: ${{ needs.provision.outputs.hitl_app_id }}
DIFY_E2E_HITL_EXTERNAL_APP_ID: ${{ needs.provision.outputs.hitl_external_app_id }}
DIFY_E2E_HITL_SINGLE_ACTION_APP_ID: ${{ needs.provision.outputs.hitl_single_action_app_id }}
DIFY_E2E_HITL_MULTI_NODE_APP_ID: ${{ needs.provision.outputs.hitl_multi_node_app_id }}
DIFY_E2E_HITL_MULTI_NODE_APP_ID: ${{ needs.provision.outputs.hitl_multi_node_app_id }}
run: |
# Collect files in safe order: use → devices → logout (revokes last) → agent
FILES=()

View File

@@ -36,7 +36,7 @@ jobs:
uses: ./.github/actions/setup-web
- name: Setup Bun
uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.2
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version-file: cli/.bun-version

View File

@@ -7,12 +7,22 @@ on:
description: Dify release tag to attach difyctl assets to (blank = latest stable)
required: false
type: string
dry_run:
description: Build and checksum only — skip asset upload and stale-asset prune
required: false
type: boolean
default: false
workflow_call:
inputs:
release_tag:
description: Dify release tag to attach difyctl assets to (blank = latest stable)
required: false
type: string
dry_run:
description: Build and checksum only — skip asset upload and stale-asset prune
required: false
type: boolean
default: false
release:
types: [released]
@@ -39,11 +49,8 @@ jobs:
with:
persist-credentials: false
- name: Export manifest to env
run: node scripts/release-naming.mjs github-env >> "$GITHUB_ENV"
- name: Validate manifest
run: scripts/release-validate-manifest.sh
run: node scripts/release-naming.mjs validate
- name: Resolve target Dify release
id: resolve
@@ -75,15 +82,6 @@ jobs:
DIFY_TAG: ${{ steps.resolve.outputs.dify_tag }}
run: node scripts/release-naming.mjs compat-check "$DIFY_TAG"
- name: Reject duplicate difyctl version
env:
GH_TOKEN: ${{ github.token }}
run: |
if gh api "repos/${GITHUB_REPOSITORY}/git/ref/tags/${difyctlTag}" >/dev/null 2>&1; then
echo "::error::difyctl ${version} already released (tag ${difyctlTag} exists); bump cli/package.json version"
exit 1
fi
release:
name: build + attach standalone binaries (all targets)
needs: validate
@@ -114,12 +112,13 @@ jobs:
run: node scripts/release-naming.mjs github-env >> "$GITHUB_ENV"
- name: Setup Bun
uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.2
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version-file: cli/.bun-version
- name: Compile standalone binaries (all targets)
run: |
CLI_VERSION="$version" \
DIFYCTL_COMMIT="$(git rev-parse HEAD)" \
DIFYCTL_BUILD_DATE="$(git log -1 --format=%cI HEAD)" \
pnpm build:bin
@@ -128,6 +127,7 @@ jobs:
run: scripts/release-write-checksums.sh
- name: Attach difyctl assets to Dify release
if: ${{ !inputs.dry_run }}
env:
GH_TOKEN: ${{ github.token }}
run: |
@@ -135,6 +135,7 @@ jobs:
--repo "$GITHUB_REPOSITORY" --clobber
- name: Prune stale difyctl assets
if: ${{ !inputs.dry_run }}
env:
GH_TOKEN: ${{ github.token }}
run: |
@@ -149,18 +150,3 @@ jobs:
--repo "$GITHUB_REPOSITORY" --yes
fi
done
- name: Create provenance tag
env:
GH_TOKEN: ${{ github.token }}
run: |
ref="refs/tags/${difyctlTag}"
sha="$(git rev-parse HEAD)"
status="$(gh api -X POST "repos/${GITHUB_REPOSITORY}/git/refs" \
-f ref="$ref" -f sha="$sha" --silent --include 2>/dev/null \
| awk 'NR==1 {print $2; exit}' || true)"
case "$status" in
201) echo "::notice::created ${ref}" ;;
422) echo "::notice::tag ${ref} already exists; skipping (immutable)" ;;
*) echo "::error::provenance tag ${ref} not created (HTTP ${status:-unknown})"; exit 1 ;;
esac

View File

@@ -4,11 +4,11 @@ on:
workflow_dispatch:
inputs:
dify_version:
description: "Dify image tag to test against (e.g. 1.7.0)"
description: 'Dify image tag to test against (e.g. 1.7.0)'
type: string
required: true
cli_ref:
description: "Git ref to build the cli from (default: current branch)"
description: 'Git ref to build the cli from (default: current branch)'
type: string
required: false

View File

@@ -44,7 +44,7 @@ jobs:
- name: Validate release manifest
if: matrix.os == 'depot-ubuntu-24.04'
run: scripts/release-validate-manifest.sh
run: node scripts/release-naming.mjs validate
- name: CI pipeline (tree, coverage, build)
run: pnpm run ci

View File

@@ -19,10 +19,10 @@ jobs:
persist-credentials: false
- name: Setup UV and Python
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
enable-cache: true
python-version: "3.12"
python-version: '3.12'
cache-dependency-glob: api/uv.lock
- name: Install dependencies
@@ -40,7 +40,7 @@ jobs:
cp envs/middleware.env.example middleware.env
- name: Set up Middlewares
uses: hoverkraft-tech/compose-action@11beaa1c2dae4e8ed7b1665aa074723b6cecb0e4 # v3.0.0
uses: hoverkraft-tech/compose-action@ee6af68587292d72db67743171809c19787df4c9 # v3.1.0
with:
compose-file: |
docker/docker-compose.middleware.yaml
@@ -69,10 +69,10 @@ jobs:
persist-credentials: false
- name: Setup UV and Python
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
enable-cache: true
python-version: "3.12"
python-version: '3.12'
cache-dependency-glob: api/uv.lock
- name: Install dependencies
@@ -94,7 +94,7 @@ jobs:
sed -i 's/DB_USERNAME=postgres/DB_USERNAME=mysql/' middleware.env
- name: Set up Middlewares
uses: hoverkraft-tech/compose-action@11beaa1c2dae4e8ed7b1665aa074723b6cecb0e4 # v3.0.0
uses: hoverkraft-tech/compose-action@ee6af68587292d72db67743171809c19787df4c9 # v3.1.0
with:
compose-file: |
docker/docker-compose.middleware.yaml

View File

@@ -5,9 +5,9 @@ permissions:
on:
workflow_run:
workflows: ["Build and Push API & Web"]
workflows: ['Build and Push API & Web']
branches:
- "deploy/agent"
- 'deploy/agent'
types:
- completed

View File

@@ -2,9 +2,9 @@ name: Deploy Dev
on:
workflow_run:
workflows: ["Build and Push API & Web"]
workflows: ['Build and Push API & Web']
branches:
- "deploy/dev"
- 'deploy/dev'
types:
- completed

View File

@@ -5,9 +5,9 @@ permissions:
on:
workflow_run:
workflows: ["Build and Push API & Web"]
workflows: ['Build and Push API & Web']
branches:
- "deploy/enterprise"
- 'deploy/enterprise'
types:
- completed

View File

@@ -0,0 +1,25 @@
name: Deploy HITL IM Dev
on:
workflow_run:
workflows: ['Build and Push API & Web']
branches:
- 'build/feat/hitl-im-dev'
types:
- completed
jobs:
deploy:
runs-on: depot-ubuntu-24.04
if: |
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.head_branch == 'build/feat/hitl-im-dev'
steps:
- name: Deploy to server
uses: appleboy/ssh-action@0ff4204d59e8e51228ff73bce53f80d53301dee2 # v1.2.5
with:
host: ${{ secrets.HITL_SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
${{ vars.SSH_SCRIPT || secrets.SSH_SCRIPT }}

View File

@@ -1,13 +1,14 @@
name: Deploy Knowledge
permissions:
actions: read
contents: read
on:
workflow_run:
workflows: ["Build and Push API & Web"]
workflows: ['Build and Push API & Web']
branches:
- "deploy/konwledge"
- 'deploy/konwledge'
types:
- completed
@@ -18,6 +19,48 @@ jobs:
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.head_branch == 'deploy/konwledge'
steps:
- name: Wait for KnowledgeFS CI
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
timeout-minutes: 35
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const workflowId = "knowledge-fs-ci.yml";
const headBranch = context.payload.workflow_run.head_branch;
const headSha = context.payload.workflow_run.head_sha;
const deadline = Date.now() + 30 * 60 * 1000;
const pollIntervalMs = 15 * 1000;
while (Date.now() < deadline) {
const { data } = await github.rest.actions.listWorkflowRuns({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: workflowId,
branch: headBranch,
event: "push",
head_sha: headSha,
per_page: 10,
});
const run = data.workflow_runs[0];
if (!run) {
core.info(`Waiting for ${workflowId} to start for ${headSha}.`);
} else if (run.status !== "completed") {
core.info(`Waiting for ${run.html_url}; current status is ${run.status}.`);
} else if (run.conclusion !== "success") {
throw new Error(
`${workflowId} did not succeed for ${headSha}: ${run.conclusion} (${run.html_url})`,
);
} else {
core.info(`KnowledgeFS CI succeeded for ${headSha}: ${run.html_url}`);
return;
}
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
}
throw new Error(`Timed out waiting for ${workflowId} to succeed for ${headSha}.`);
- name: Deploy to server
uses: appleboy/ssh-action@0ff4204d59e8e51228ff73bce53f80d53301dee2 # v1.2.5
with:

View File

@@ -5,9 +5,9 @@ permissions:
on:
workflow_run:
workflows: ["Build and Push API & Web"]
workflows: ['Build and Push API & Web']
branches:
- "deploy/saas"
- 'deploy/saas'
types:
- completed

47
.github/workflows/dify-agent-tests.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
name: Dify Agent Tests
on:
workflow_call:
permissions:
contents: read
concurrency:
group: dify-agent-tests-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
dify-agent-unit:
name: Dify Agent Unit Tests
runs-on: depot-ubuntu-24.04
defaults:
run:
shell: bash
working-directory: dify-agent
strategy:
matrix:
python-version:
- '3.12'
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Setup UV and Python
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
enable-cache: true
python-version: ${{ matrix.python-version }}
cache-dependency-glob: dify-agent/uv.lock
- name: Check UV lockfile
run: uv lock --check
- name: Install dependencies
run: uv sync --extra server --dev
- name: Run unit tests
run: uv run pytest

View File

@@ -3,7 +3,7 @@ name: Build docker image
on:
pull_request:
branches:
- "main"
- 'main'
paths:
- api/Dockerfile
- api/Dockerfile.dockerignore
@@ -33,39 +33,39 @@ jobs:
strategy:
matrix:
include:
- service_name: "api-amd64"
- service_name: 'api-amd64'
platform: linux/amd64
runs_on: depot-ubuntu-24.04-4
context: "{{defaultContext}}"
file: "api/Dockerfile"
- service_name: "api-arm64"
context: '{{defaultContext}}'
file: 'api/Dockerfile'
- service_name: 'api-arm64'
platform: linux/arm64
runs_on: depot-ubuntu-24.04-4
context: "{{defaultContext}}"
file: "api/Dockerfile"
- service_name: "web-amd64"
context: '{{defaultContext}}'
file: 'api/Dockerfile'
- service_name: 'web-amd64'
platform: linux/amd64
runs_on: depot-ubuntu-24.04-4
context: "{{defaultContext}}"
file: "web/Dockerfile"
- service_name: "web-arm64"
context: '{{defaultContext}}'
file: 'web/Dockerfile'
- service_name: 'web-arm64'
platform: linux/arm64
runs_on: depot-ubuntu-24.04-4
context: "{{defaultContext}}"
file: "web/Dockerfile"
- service_name: "local-sandbox-amd64"
context: '{{defaultContext}}'
file: 'web/Dockerfile'
- service_name: 'local-sandbox-amd64'
platform: linux/amd64
runs_on: depot-ubuntu-24.04-4
context: "{{defaultContext}}:dify-agent-runtime"
file: "docker/Dockerfile"
- service_name: "local-sandbox-arm64"
context: '{{defaultContext}}:dify-agent-runtime'
file: 'docker/Dockerfile'
- service_name: 'local-sandbox-arm64'
platform: linux/arm64
runs_on: depot-ubuntu-24.04-4
context: "{{defaultContext}}:dify-agent-runtime"
file: "docker/Dockerfile"
context: '{{defaultContext}}:dify-agent-runtime'
file: 'docker/Dockerfile'
steps:
- name: Set up Depot CLI
uses: depot/setup-action@15c09a5f77a0840ad4bce955686522a257853461 # v1.7.1
uses: depot/setup-action@91bc8495a33ebfc504ffc89e5674379ccf23c29c # v1.7.2
- name: Build Docker Image
uses: depot/build-push-action@98e78adca7817480b8185f474a400b451d74e287 # v1.18.0
@@ -85,18 +85,18 @@ jobs:
strategy:
matrix:
include:
- service_name: "api-amd64"
context: "{{defaultContext}}"
file: "api/Dockerfile"
- service_name: "web-amd64"
context: "{{defaultContext}}"
file: "web/Dockerfile"
- service_name: "local-sandbox-amd64"
context: "{{defaultContext}}:dify-agent-runtime"
file: "docker/Dockerfile"
- service_name: 'api-amd64'
context: '{{defaultContext}}'
file: 'api/Dockerfile'
- service_name: 'web-amd64'
context: '{{defaultContext}}'
file: 'web/Dockerfile'
- service_name: 'local-sandbox-amd64'
context: '{{defaultContext}}:dify-agent-runtime'
file: 'docker/Dockerfile'
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
- name: Build Docker Image
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0

View File

@@ -1,4 +1,4 @@
name: "Pull Request Labeler"
name: 'Pull Request Labeler'
on:
pull_request_target:

View File

@@ -2,9 +2,9 @@ name: Main CI Pipeline
on:
pull_request:
branches: ["main"]
branches: ['main']
merge_group:
branches: ["main"]
branches: ['main']
types: [checks_requested]
permissions:
@@ -15,8 +15,10 @@ permissions:
statuses: write
concurrency:
group: main-ci-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
# Pull request deduplication is owned by skip-duplicate-actions so pre_job can
# publish should_skip before required status finalizers run.
group: main-ci-${{ github.event.merge_group.head_sha || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'merge_group' }}
jobs:
pre_job:
@@ -46,9 +48,10 @@ jobs:
vdb-changed: ${{ steps.changes.outputs.vdb }}
migration-changed: ${{ steps.changes.outputs.migration }}
sandbox-runtime-changed: ${{ steps.changes.outputs.sandbox-runtime }}
dify-agent-changed: ${{ steps.changes.outputs.dify-agent }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2
- uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3
id: changes
with:
filters: |
@@ -79,7 +82,6 @@ jobs:
- 'pnpm-workspace.yaml'
- 'lint.config.ts'
- '.npmrc'
- '.nvmrc'
- '.github/workflows/cli-tests.yml'
- '.github/actions/setup-web/**'
web:
@@ -88,7 +90,7 @@ jobs:
- 'package.json'
- 'pnpm-lock.yaml'
- 'pnpm-workspace.yaml'
- '.nvmrc'
- '.github/workflows/main-ci.yml'
- '.github/workflows/web-tests.yml'
- '.github/actions/setup-web/**'
e2e:
@@ -101,7 +103,6 @@ jobs:
- 'package.json'
- 'pnpm-lock.yaml'
- 'pnpm-workspace.yaml'
- '.nvmrc'
- 'docker/docker-compose.middleware.yaml'
- 'docker/envs/middleware.env.example'
- '.github/workflows/web-e2e.yml'
@@ -135,6 +136,9 @@ jobs:
sandbox-runtime:
- 'dify-agent-runtime/**'
- '.github/workflows/sandbox-runtime-tests.yml'
dify-agent:
- 'dify-agent/**'
- '.github/workflows/dify-agent-tests.yml'
migration:
- 'api/migrations/**'
- 'api/.env.example'
@@ -393,10 +397,10 @@ jobs:
style-check:
name: Style Check
needs: pre_job
if: needs.pre_job.outputs.should_skip != 'true'
uses: ./.github/workflows/style.yml
with:
base-rev: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha }}
skip-checks: ${{ needs.pre_job.outputs.should_skip == 'true' }}
vdb-tests-run:
name: Run VDB Tests
@@ -575,3 +579,63 @@ jobs:
echo "Sandbox runtime tests were not required, but the skip job finished with result: $SKIP_RESULT" >&2
exit 1
dify-agent-tests-run:
name: Run Dify Agent Tests
needs:
- pre_job
- check-changes
if: needs.pre_job.outputs.should_skip != 'true' && needs.check-changes.outputs.dify-agent-changed == 'true'
uses: ./.github/workflows/dify-agent-tests.yml
secrets: inherit
dify-agent-tests-skip:
name: Skip Dify Agent Tests
needs:
- pre_job
- check-changes
if: needs.pre_job.outputs.should_skip != 'true' && needs.check-changes.outputs.dify-agent-changed != 'true'
runs-on: depot-ubuntu-24.04
steps:
- name: Report skipped dify agent tests
run: echo "No dify-agent-related changes detected; skipping dify agent tests."
dify-agent-tests:
name: Dify Agent Tests
if: ${{ always() }}
needs:
- pre_job
- check-changes
- dify-agent-tests-run
- dify-agent-tests-skip
runs-on: depot-ubuntu-24.04
steps:
- name: Finalize Dify Agent Tests status
env:
SHOULD_SKIP_WORKFLOW: ${{ needs.pre_job.outputs.should_skip }}
TESTS_CHANGED: ${{ needs.check-changes.outputs.dify-agent-changed }}
RUN_RESULT: ${{ needs.dify-agent-tests-run.result }}
SKIP_RESULT: ${{ needs.dify-agent-tests-skip.result }}
run: |
if [[ "$SHOULD_SKIP_WORKFLOW" == 'true' ]]; then
echo "Dify agent tests were skipped because this workflow run duplicated a successful or newer run."
exit 0
fi
if [[ "$TESTS_CHANGED" == 'true' ]]; then
if [[ "$RUN_RESULT" == 'success' ]]; then
echo "Dify agent tests ran successfully."
exit 0
fi
echo "Dify agent tests were required but finished with result: $RUN_RESULT" >&2
exit 1
fi
if [[ "$SKIP_RESULT" == 'success' ]]; then
echo "Dify agent tests were skipped because no dify-agent-related files changed."
exit 0
fi
echo "Dify agent tests were not required, but the skip job finished with result: $SKIP_RESULT" >&2
exit 1

View File

@@ -2,7 +2,7 @@ name: Post-Merge Checks
on:
push:
branches: ["main"]
branches: ['main']
permissions:
contents: read
@@ -19,7 +19,7 @@ jobs:
external-e2e-changed: ${{ steps.changes.outputs.external_e2e }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2
- uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3
id: changes
with:
filters: |
@@ -39,7 +39,6 @@ jobs:
- 'e2e/tsx-register.js'
- 'package.json'
- 'pnpm-lock.yaml'
- '.nvmrc'
- '.github/workflows/post-merge.yml'
- '.github/workflows/web-e2e.yml'
- '.github/actions/setup-web/**'

View File

@@ -22,7 +22,7 @@ jobs:
fetch-depth: 0
- name: Setup Python & UV
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
enable-cache: true

View File

@@ -24,7 +24,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup Python & UV
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
enable-cache: true

View File

@@ -22,7 +22,7 @@ jobs:
fetch-depth: 0
- name: Setup Python & UV
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
enable-cache: true

View File

@@ -57,7 +57,7 @@ jobs:
cache-dependency-path: dify-agent-runtime/go.sum
- name: Run golangci-lint
uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v6.5.0
uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9.3.0
with:
working-directory: dify-agent-runtime
version: latest

View File

@@ -8,7 +8,7 @@ on:
- reopened
- synchronize
merge_group:
branches: ["main"]
branches: ['main']
types: [checks_requested]
jobs:

View File

@@ -11,20 +11,19 @@ on:
jobs:
stale:
runs-on: depot-ubuntu-24.04
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@1e223db275d687790206a7acac4d1a11bd6fe629 # v10.4.0
- uses: actions/stale@4391f3da665fdf50b6810c1a66712fb9ba21aa93 # v11.0.0
with:
days-before-issue-stale: 15
days-before-issue-close: 3
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: "Closed due to inactivity. If you have any questions, you can reopen it."
stale-pr-message: "Closed due to inactivity. If you have any questions, you can reopen it."
stale-issue-message: 'Closed due to inactivity. If you have any questions, you can reopen it.'
stale-pr-message: 'Closed due to inactivity. If you have any questions, you can reopen it.'
stale-issue-label: 'no-issue-activity'
stale-pr-label: 'no-pr-activity'
any-of-labels: '🌚 invalid,🙋‍♂️ question,wont-fix,no-issue-activity,no-pr-activity,💪 enhancement,🤔 cant-reproduce,🙏 help wanted'

View File

@@ -6,10 +6,11 @@ on:
base-rev:
required: true
type: string
concurrency:
group: style-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
skip-checks:
description: Create the required check runs without repeating previously successful work.
required: false
type: boolean
default: false
permissions:
checks: write
@@ -19,6 +20,7 @@ permissions:
jobs:
python-style:
name: Python Style
if: ${{ !inputs.skip-checks }}
runs-on: depot-ubuntu-24.04
steps:
@@ -45,10 +47,10 @@ jobs:
- name: Setup UV and Python
if: steps.changed-files.outputs.any_changed == 'true'
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
enable-cache: false
python-version: "3.12"
python-version: '3.12'
cache-dependency-glob: api/uv.lock
- name: Install dependencies
@@ -83,6 +85,7 @@ jobs:
web-style:
name: Web Style
if: ${{ !inputs.skip-checks }}
runs-on: depot-ubuntu-24.04
defaults:
run:
@@ -109,7 +112,8 @@ jobs:
package.json
pnpm-lock.yaml
pnpm-workspace.yaml
.nvmrc
knip.config.ts
scripts/check-web-production-unused-after-knip-fix.mjs
.github/workflows/style.yml
.github/actions/setup-web/**
@@ -125,18 +129,22 @@ jobs:
- name: Web dead code check
if: steps.changed-files.outputs.any_changed == 'true'
working-directory: .
run: vp run knip
- name: Web dead code check production
if: steps.changed-files.outputs.any_changed == 'true'
working-directory: .
run: vp run knip:production
- name: Web production unused declarations check
if: steps.changed-files.outputs.any_changed == 'true'
working-directory: .
run: vp run knip:production-unused-check
ts-common-style:
name: TS Common
if: ${{ !inputs.skip-checks }}
runs-on: depot-ubuntu-24.04-4
permissions:
checks: write
@@ -161,16 +169,15 @@ jobs:
package.json
pnpm-lock.yaml
pnpm-workspace.yaml
.nvmrc
vite.config.ts
lint.config.ts
eslint.config.mjs
knip.config.ts
scripts/check-web-production-unused-after-knip-fix.mjs
oxlint-suppressions.json
eslint-suppressions.json
.vscode/**
.github/workflows/autofix.yml
.github/workflows/style.yml
.github/actions/setup-web/**
.github/**
- name: Setup web environment
if: steps.changed-files.outputs.any_changed == 'true'
@@ -182,6 +189,7 @@ jobs:
superlinter:
name: SuperLinter
if: ${{ !inputs.skip-checks }}
runs-on: depot-ubuntu-24.04
steps:
@@ -202,6 +210,7 @@ jobs:
**Dockerfile
dev/**
.editorconfig
.vite-hooks/**
- name: Super-linter
uses: super-linter/super-linter/slim@4ce20838b8ab83717e78138c5b3a1407148e0918 # v8.7.0
@@ -210,10 +219,11 @@ jobs:
BASH_SEVERITY: warning
DEFAULT_BRANCH: origin/main
EDITORCONFIG_FILE_NAME: editorconfig-checker.json
FILTER_REGEX_INCLUDE: pnpm-lock.yaml
ENABLE_GITHUB_PULL_REQUEST_SUMMARY_COMMENT: false
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
IGNORE_GENERATED_FILES: true
IGNORE_GITIGNORED_FILES: true
VALIDATE_ALL_CODEBASE: false
VALIDATE_BASH: true
VALIDATE_BASH_EXEC: true
# FIXME: temporarily disabled until api-docker.yaml's run script is fixed for shellcheck

View File

@@ -31,7 +31,7 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
node-version-file: package.json
cache: ''
cache-dependency-path: 'pnpm-lock.yaml'

View File

@@ -8,15 +8,19 @@ on:
workflow_dispatch:
inputs:
files:
description: 'Specific files to translate (space-separated, e.g., "app common"). Required for full mode; leave empty in incremental mode to use en-US files changed since HEAD~1.'
description: 'Specific files to translate (space-separated, e.g., "app common").
Required for full mode; leave empty in incremental mode to use en-US
files changed since HEAD~1.'
required: false
type: string
languages:
description: 'Specific languages to translate (space-separated, e.g., "zh-Hans ja-JP"). Leave empty for all supported target languages except en-US.'
description: 'Specific languages to translate (space-separated, e.g., "zh-Hans
ja-JP"). Leave empty for all supported target languages except en-US.'
required: false
type: string
mode:
description: 'Sync mode: incremental (compare with previous en-US revision) or full (sync all keys in scope)'
description: 'Sync mode: incremental (compare with previous en-US revision) or
full (sync all keys in scope)'
required: false
default: incremental
type: choice
@@ -158,7 +162,7 @@ jobs:
- name: Run Claude Code for Translation Sync
if: steps.context.outputs.CHANGED_FILES != ''
uses: anthropics/claude-code-action@be7b93b1907a4abad570368f3c74b6fe3807510b # v1.0.183
uses: anthropics/claude-code-action@833fb0f8c9f6686b33d963a8bae0a94f4936ab2a # v1.0.211
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -20,7 +20,7 @@ jobs:
strategy:
matrix:
python-version:
- "3.12"
- '3.12'
steps:
- name: Checkout code
@@ -29,14 +29,14 @@ jobs:
persist-credentials: false
- name: Free Disk Space
uses: endersonmenezes/free-disk-space@7901478139cff6e9d44df5972fd8ab8fcade4db1 # v3.2.2
uses: endersonmenezes/free-disk-space@2a22f8c59cae9cddae7194b33e6b92d023b2b4b8 # v4.0.0
with:
remove_dotnet: true
remove_haskell: true
remove_tool_cache: true
- name: Setup UV and Python
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
enable-cache: true
python-version: ${{ matrix.python-version }}
@@ -48,16 +48,16 @@ jobs:
- name: Install dependencies
run: uv sync --project api --dev
# - name: Set up Vector Store (TiDB)
# uses: hoverkraft-tech/compose-action@v2.0.2
# with:
# compose-file: docker/tidb/docker-compose.yaml
# services: |
# tidb
# tiflash
# - name: Set up Vector Store (TiDB)
# uses: hoverkraft-tech/compose-action@v2.0.2
# with:
# compose-file: docker/tidb/docker-compose.yaml
# services: |
# tidb
# tiflash
# - name: Check VDB Ready (TiDB)
# run: uv run --project api python api/providers/vdb/tidb-vector/tests/integration_tests/check_tiflash_ready.py
# - name: Check VDB Ready (TiDB)
# run: uv run --project api python api/providers/vdb/tidb-vector/tests/integration_tests/check_tiflash_ready.py
- name: Test Vector Stores
run: |

View File

@@ -17,7 +17,7 @@ jobs:
strategy:
matrix:
python-version:
- "3.12"
- '3.12'
steps:
- name: Checkout code
@@ -26,14 +26,14 @@ jobs:
persist-credentials: false
- name: Free Disk Space
uses: endersonmenezes/free-disk-space@7901478139cff6e9d44df5972fd8ab8fcade4db1 # v3.2.2
uses: endersonmenezes/free-disk-space@2a22f8c59cae9cddae7194b33e6b92d023b2b4b8 # v4.0.0
with:
remove_dotnet: true
remove_haskell: true
remove_tool_cache: true
- name: Setup UV and Python
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
enable-cache: true
python-version: ${{ matrix.python-version }}
@@ -45,16 +45,16 @@ jobs:
- name: Install dependencies
run: uv sync --project api --dev
# - name: Set up Vector Store (TiDB)
# uses: hoverkraft-tech/compose-action@v2.0.2
# with:
# compose-file: docker/tidb/docker-compose.yaml
# services: |
# tidb
# tiflash
# - name: Set up Vector Store (TiDB)
# uses: hoverkraft-tech/compose-action@v2.0.2
# with:
# compose-file: docker/tidb/docker-compose.yaml
# services: |
# tidb
# tiflash
# - name: Check VDB Ready (TiDB)
# run: uv run --project api python api/providers/vdb/tidb-vector/tests/integration_tests/check_tiflash_ready.py
# - name: Check VDB Ready (TiDB)
# run: uv run --project api python api/providers/vdb/tidb-vector/tests/integration_tests/check_tiflash_ready.py
- name: Test Vector Stores
run: |

View File

@@ -11,18 +11,64 @@ on:
permissions:
contents: read
concurrency:
group: web-e2e-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
name: Web Full-Stack E2E
core-build:
name: Prepare Core E2E Web Build
if: ${{ !inputs.run-external-runtime }}
runs-on: depot-ubuntu-24.04-4
timeout-minutes: 120
defaults:
run:
shell: bash
timeout-minutes: 30
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup web dependencies
uses: ./.github/actions/setup-web
- name: Run E2E support unit tests
working-directory: ./e2e
run: vp run test:unit
- name: Build production Web app
working-directory: ./e2e
env:
E2E_FORCE_WEB_BUILD: '1'
run: vp run e2e:web:build
- name: Package Web build
run: >-
tar -cf e2e-web-build.tar -C web
.next/BUILD_ID
.next/e2e-web-build.sha256
.next/standalone
.next/static
- name: Upload Web build
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: core-e2e-web-build
path: e2e-web-build.tar
if-no-files-found: error
overwrite: true
retention-days: 7
chromium-full:
name: Chromium Full (${{ matrix.shard }}/3)
if: ${{ !inputs.run-external-runtime }}
needs: core-build
runs-on: ubuntu-24.04
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3]
env:
E2E_ADMIN_EMAIL: e2e-admin@example.com
E2E_ADMIN_NAME: E2E Admin
E2E_ADMIN_PASSWORD: E2eAdmin12345
E2E_INIT_PASSWORD: E2eInit12345
steps:
- name: Checkout code
@@ -34,10 +80,143 @@ jobs:
uses: ./.github/actions/setup-web
- name: Setup UV and Python
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
enable-cache: true
python-version: "3.12"
python-version: '3.12'
cache-dependency-glob: api/uv.lock
- name: Install API dependencies
run: uv sync --project api --dev
- name: Download Web build
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: core-e2e-web-build
- name: Extract Web build
run: tar -xf e2e-web-build.tar -C web
- name: Install Chromium
timeout-minutes: 15
working-directory: ./e2e
run: vp run e2e:install:ci:chromium
- name: Run Chromium full shard
working-directory: ./e2e
run: vp run e2e:full -- --shard ${{ matrix.shard }}/3
- name: Upload Cucumber report
if: ${{ !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: cucumber-report-chromium-${{ matrix.shard }}
path: e2e/cucumber-report
if-no-files-found: ignore
overwrite: true
retention-days: 7
- name: Upload E2E logs
if: ${{ !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: e2e-logs-chromium-${{ matrix.shard }}
path: e2e/.logs/*.log
if-no-files-found: ignore
include-hidden-files: true
overwrite: true
retention-days: 7
webkit-smoke:
name: WebKit Browser Smoke
if: ${{ !inputs.run-external-runtime }}
needs: core-build
runs-on: ubuntu-24.04
timeout-minutes: 30
env:
E2E_ADMIN_EMAIL: e2e-admin@example.com
E2E_ADMIN_NAME: E2E Admin
E2E_ADMIN_PASSWORD: E2eAdmin12345
E2E_BROWSER: webkit
E2E_INIT_PASSWORD: E2eInit12345
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup web dependencies
uses: ./.github/actions/setup-web
- name: Setup UV and Python
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
enable-cache: true
python-version: '3.12'
cache-dependency-glob: api/uv.lock
- name: Install API dependencies
run: uv sync --project api --dev
- name: Download Web build
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: core-e2e-web-build
- name: Extract Web build
run: tar -xf e2e-web-build.tar -C web
- name: Install WebKit
timeout-minutes: 15
working-directory: ./e2e
run: vp run e2e:install:ci:webkit
- name: Run WebKit browser smoke
working-directory: ./e2e
run: vp run e2e:full -- --tags '@browser-smoke'
- name: Upload Cucumber report
if: ${{ !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: cucumber-report-webkit
path: e2e/cucumber-report
if-no-files-found: ignore
overwrite: true
retention-days: 7
- name: Upload E2E logs
if: ${{ !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: e2e-logs-webkit
path: e2e/.logs/*.log
if-no-files-found: ignore
include-hidden-files: true
overwrite: true
retention-days: 7
external-runtime:
name: Web Full-Stack E2E
if: ${{ inputs.run-external-runtime }}
runs-on: ubuntu-24.04
timeout-minutes: 120
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup web dependencies
uses: ./.github/actions/setup-web
- name: Setup UV and Python
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
enable-cache: true
python-version: '3.12'
cache-dependency-glob: |
api/uv.lock
dify-agent/uv.lock
@@ -45,74 +224,12 @@ jobs:
- name: Install API dependencies
run: uv sync --project api --dev
- name: Run E2E support unit tests
if: ${{ !inputs.run-external-runtime }}
- name: Install Chromium
timeout-minutes: 15
working-directory: ./e2e
run: vp run test:unit
- name: Install Playwright browser
working-directory: ./e2e
run: vp run e2e:install
- name: Run isolated source-api and built-web Cucumber E2E tests
if: ${{ !inputs.run-external-runtime }}
working-directory: ./e2e
env:
E2E_ADMIN_EMAIL: e2e-admin@example.com
E2E_ADMIN_NAME: E2E Admin
E2E_ADMIN_PASSWORD: E2eAdmin12345
E2E_FORCE_WEB_BUILD: "1"
E2E_INIT_PASSWORD: E2eInit12345
run: vp run e2e:full
- name: Preserve Chromium E2E report and logs
if: ${{ !cancelled() && !inputs.run-external-runtime }}
run: |
if [[ -d e2e/cucumber-report ]]; then
mv e2e/cucumber-report e2e/cucumber-report-non-external
fi
if [[ -d e2e/.logs ]]; then
mv e2e/.logs e2e/.logs-non-external
fi
- name: Run WebKit keyboard and browser smoke tests
if: ${{ !inputs.run-external-runtime }}
working-directory: ./e2e
env:
E2E_ADMIN_EMAIL: e2e-admin@example.com
E2E_ADMIN_NAME: E2E Admin
E2E_ADMIN_PASSWORD: E2eAdmin12345
E2E_BROWSER: webkit
E2E_INIT_PASSWORD: E2eInit12345
run: |
teardown_webkit_smoke() {
local run_status=$?
trap - EXIT
if ! vp run e2e:middleware:down; then
echo "::error title=E2E teardown failed::WebKit smoke middleware did not shut down cleanly."
if [[ "$run_status" -eq 0 ]]; then
run_status=1
fi
fi
exit "$run_status"
}
trap teardown_webkit_smoke EXIT
vp run e2e:middleware:up
vp run e2e -- --tags '@browser-smoke'
- name: Preserve WebKit E2E report and logs
if: ${{ !cancelled() && !inputs.run-external-runtime }}
run: |
if [[ -d e2e/cucumber-report ]]; then
mv e2e/cucumber-report e2e/cucumber-report-webkit
fi
if [[ -d e2e/.logs ]]; then
mv e2e/.logs e2e/.logs-webkit
fi
run: vp run e2e:install:ci:chromium
- name: Run prepared and external runtime E2E tests
if: ${{ inputs.run-external-runtime }}
working-directory: ./e2e
env:
E2E_ADMIN_EMAIL: e2e-admin@example.com
@@ -121,7 +238,7 @@ jobs:
E2E_AGENT_DECISION_MODEL_NAME: ${{ vars.E2E_AGENT_DECISION_MODEL_NAME || 'gpt-5.5' }}
E2E_AGENT_DECISION_MODEL_PROVIDER: ${{ vars.E2E_AGENT_DECISION_MODEL_PROVIDER || 'openai' }}
E2E_AGENT_DECISION_MODEL_TYPE: ${{ vars.E2E_AGENT_DECISION_MODEL_TYPE || 'llm' }}
E2E_FORCE_WEB_BUILD: "1"
E2E_FORCE_WEB_BUILD: '1'
E2E_INIT_PASSWORD: E2eInit12345
E2E_MARKETPLACE_API_URL: ${{ vars.E2E_MARKETPLACE_API_URL }}
E2E_MARKETPLACE_PLUGIN_IDS: ${{ vars.E2E_MARKETPLACE_PLUGIN_IDS }}
@@ -138,21 +255,6 @@ jobs:
exit 1
fi
teardown_external_runtime() {
local run_status=$?
trap - EXIT
if ! vp run e2e:middleware:down; then
echo "::error title=E2E teardown failed::External runtime middleware did not shut down cleanly."
if [[ "$run_status" -eq 0 ]]; then
run_status=1
fi
fi
exit "$run_status"
}
trap teardown_external_runtime EXIT
vp run e2e:middleware:up
vp run e2e:post-merge:prepare
vp run e2e:post-merge
- name: Upload Cucumber report
@@ -160,10 +262,8 @@ jobs:
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: cucumber-report
path: |
e2e/cucumber-report
e2e/cucumber-report-non-external
e2e/cucumber-report-webkit
path: e2e/cucumber-report
overwrite: true
retention-days: 7
- name: Upload E2E logs
@@ -171,18 +271,17 @@ jobs:
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: e2e-logs
path: |
e2e/.logs/*.log
e2e/.logs-non-external/*.log
e2e/.logs-webkit/*.log
path: e2e/.logs/*.log
include-hidden-files: true
overwrite: true
retention-days: 7
- name: Upload E2E seed report
if: ${{ !cancelled() && inputs.run-external-runtime }}
if: ${{ !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: e2e-seed-report
path: e2e/seed-report
if-no-files-found: ignore
overwrite: true
retention-days: 7

View File

@@ -9,10 +9,6 @@ on:
permissions:
contents: read
concurrency:
group: web-tests-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
name: Web Tests (${{ matrix.shardIndex }}/${{ matrix.shardTotal }})
@@ -37,7 +33,7 @@ jobs:
uses: ./.github/actions/setup-web
- name: Run tests
run: vp test run --reporter=blob --reporter=minimal --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} --coverage
run: vp test run --project unit --reporter=blob --reporter=minimal --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} --coverage
- name: Upload blob report
if: ${{ !cancelled() }}
@@ -48,6 +44,41 @@ jobs:
include-hidden-files: true
retention-days: 1
browser-test:
name: Web Browser Tests
runs-on: ubuntu-24.04
timeout-minutes: 20
defaults:
run:
shell: bash
working-directory: ./web
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup web environment
uses: ./.github/actions/setup-web
- name: Install Chromium for Browser Mode
timeout-minutes: 15
run: vp exec playwright install --with-deps --only-shell chromium
- name: Run browser tests
run: vp test run --project browser --silent=passed-only
- name: Upload browser failure artifacts
if: ${{ failure() && !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: browser-test-failures
path: web/.vitest-browser/
if-no-files-found: ignore
include-hidden-files: true
retention-days: 7
merge-reports:
name: Merge Test Reports
if: ${{ !cancelled() }}
@@ -90,7 +121,8 @@ jobs:
dify-ui-test:
name: dify-ui Tests
runs-on: depot-ubuntu-24.04-4
runs-on: ubuntu-24.04
timeout-minutes: 20
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
defaults:
@@ -108,11 +140,22 @@ jobs:
uses: ./.github/actions/setup-web
- name: Install Chromium for Browser Mode
run: vp exec playwright install --with-deps chromium
timeout-minutes: 15
run: vp exec playwright install --with-deps --only-shell chromium
- name: Run dify-ui tests
run: vp test run --project unit --coverage --silent=passed-only
- name: Upload dify-ui test failure artifacts
if: ${{ failure() && !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: dify-ui-test-failures
path: packages/dify-ui/.vitest-browser/
if-no-files-found: ignore
include-hidden-files: true
retention-days: 7
- name: Report coverage
if: ${{ env.CODECOV_TOKEN != '' }}
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
@@ -124,7 +167,8 @@ jobs:
dify-ui-storybook-test:
name: dify-ui Storybook Tests
runs-on: depot-ubuntu-24.04-4
runs-on: ubuntu-24.04
timeout-minutes: 20
defaults:
run:
shell: bash
@@ -140,7 +184,18 @@ jobs:
uses: ./.github/actions/setup-web
- name: Install Chromium for Browser Mode
run: vp exec playwright install --with-deps chromium
timeout-minutes: 15
run: vp exec playwright install --with-deps --only-shell chromium
- name: Run dify-ui Storybook tests
run: vp run test:storybook
- name: Upload dify-ui Storybook test failure artifacts
if: ${{ failure() && !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: dify-ui-storybook-test-failures
path: packages/dify-ui/.vitest-browser/
if-no-files-found: ignore
include-hidden-files: true
retention-days: 7

4
.gitignore vendored
View File

@@ -140,6 +140,9 @@ dmypy.json
pyrightconfig.json
!api/pyrightconfig.json
# import-linter
.import_linter_cache/
# Pyre type checker
.pyre/
.idea/'
@@ -260,6 +263,7 @@ scripts/stress-test/reports/
.qoder/*
.context/
# Vitest local reports
web/.vitest-browser/
web/.vitest-reports/
# dify-agent-runtime

1
.nvmrc
View File

@@ -1 +0,0 @@
22

View File

@@ -5,7 +5,6 @@ files=$(git diff --cached --name-only)
# check if api or web directory is modified
api_modified=false
web_modified=false
skip_web_checks=false
git_path() {
@@ -29,10 +28,6 @@ do
# set api_modified flag to true
api_modified=true
;;
web/*)
# set web_modified flag to true
web_modified=true
;;
esac
done

View File

@@ -4,7 +4,6 @@
"tailwindCSS.experimental.configFile": "web/app/styles/globals.css",
// Format
"[javascript]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
"[javascriptreact]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
"[typescript]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
@@ -25,9 +24,9 @@
"[handlebars]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
"editor.formatOnSave": true,
"editor.formatOnSaveMode": "file",
"oxc.fmt.configPath": "./vite.config.ts",
"oxc.disableNestedConfig": true,
"oxc.fmt.disableNestedConfig": true,
// Lint fix
"eslint.useFlatConfig": true,
"eslint.validate": ["json", "jsonc", "markdown", "yaml", "toml"],
"editor.codeActionsOnSave": {

View File

@@ -6,3 +6,10 @@ Dify is an open-source platform for building LLM applications, agentic workflows
- Run backend commands through `uv run --project api <command>`.
- Backend integration tests are CI-only and are not expected to run locally.
- Keep `docker/.env.example` limited to variables required for a default Docker Compose deployment to start. Put optional and provider-specific settings in the matching `docker/envs/*.env.example` file; `docker/.env` overrides those service-specific env files.
## Frontend Workflow
- For truncated text disclosure and native `title` decisions, follow [Truncated Text Disclosure].
[Truncated Text Disclosure]: web/docs/truncated-text-disclosure.md

View File

@@ -129,92 +129,43 @@ All of Dify's offerings come with corresponding APIs, so you could effortlessly
Star Dify on GitHub and be instantly notified of new releases.
![star-us](https://github.com/langgenius/dify/assets/13230914/b823edc1-6388-4e25-ad45-2f6b187adbb4)
<img width="1344" height="720" alt="star" src="https://github.com/user-attachments/assets/dcd086d1-af0f-471b-ae52-1ad2fa040595" />
## Advanced Setup
### Custom configurations
If you need to customize the configuration, edit `docker/.env`. The essential startup defaults live in [`docker/.env.example`](docker/.env.example), and optional advanced variables are split under `docker/envs/` by theme. After making any changes, re-run `docker compose up -d` from the `docker` directory. You can find the full list of available environment variables [here](https://docs.dify.ai/getting-started/install-self-hosted/environments).
### Metrics Monitoring with Grafana
Import the dashboard to Grafana, using Dify's PostgreSQL database as data source, to monitor metrics in granularity of apps, tenants, messages, and more.
- [Grafana Dashboard by @bowenliang123](https://github.com/bowenliang123/dify-grafana-dashboard)
### Deployment with Kubernetes
If you'd like to configure a highly available setup, there are community-contributed [Helm Charts](https://helm.sh/) and YAML files which allow Dify to be deployed on Kubernetes.
- [Helm Chart by @LeoQuote](https://github.com/douban/charts/tree/master/charts/dify)
- [Helm Chart by @BorisPolonsky](https://github.com/BorisPolonsky/dify-helm)
- [Helm Chart by @magicsong](https://github.com/magicsong/ai-charts)
- [YAML file by @Winson-030](https://github.com/Winson-030/dify-kubernetes)
- [YAML file by @wyy-holding](https://github.com/wyy-holding/dify-k8s)
- [🚀 NEW! YAML files (Supports Dify v1.6.0) by @Zhoneym](https://github.com/Zhoneym/DifyAI-Kubernetes)
#### Using Terraform for Deployment
Deploy Dify to Cloud Platform with a single click using [terraform](https://www.terraform.io/)
##### Azure Global
- [Azure Terraform by @nikawang](https://github.com/nikawang/dify-azure-terraform)
##### Google Cloud
- [Google Cloud Terraform by @sotazum](https://github.com/DeNA/dify-google-cloud-terraform)
#### Using AWS CDK for Deployment
Deploy Dify to AWS with [CDK](https://aws.amazon.com/cdk/)
##### AWS
- [AWS CDK by @KevinZhao (EKS based)](https://github.com/aws-samples/solution-for-deploying-dify-on-aws)
- [AWS CDK by @tmokmss (ECS based)](https://github.com/aws-samples/dify-self-hosted-on-aws)
#### Using Alibaba Cloud Computing Nest
Quickly deploy Dify to Alibaba cloud with [Alibaba Cloud Computing Nest](https://computenest.console.aliyun.com/service/instance/create/default?type=user&ServiceName=Dify%E7%A4%BE%E5%8C%BA%E7%89%88)
#### Using Alibaba Cloud Data Management
One-Click deploy Dify to Alibaba Cloud with [Alibaba Cloud Data Management](https://www.alibabacloud.com/help/en/dms/dify-in-invitational-preview/)
#### Deploy to AKS with Azure Devops Pipeline
One-Click deploy Dify to AKS with [Azure Devops Pipeline Helm Chart by @LeoZhang](https://github.com/Ruiruiz30/Dify-helm-chart-AKS)
For custom configuration, observability, and deployment options, see [Advanced Setup](docs/ADVANCED_SETUP.md).
## Contributing
For those who'd like to contribute code, see our [Contribution Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md).
At the same time, please consider supporting Dify by sharing it on social media and at events and conferences.
Dify welcomes contributions of all kinds:
> We are looking for contributors to help translate Dify into languages other than Mandarin or English. If you are interested in helping, please see the [i18n README](https://github.com/langgenius/dify/blob/main/web/i18n-config/README.md) for more information, and leave us a comment in the `global-users` channel of our [Discord Community Server](https://discord.gg/8Tpq4AcN9c).
- **Code**: Read the [Contribution Guide](CONTRIBUTING.md), then browse [good first issues](https://github.com/langgenius/dify/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22).
- **Ideas and feedback**: Start or join a [GitHub Discussion](https://github.com/langgenius/dify/discussions).
- **Translations**: Follow the [internationalization guide](web/i18n-config/README.md) to add or update a locale.
- **Community**: Share the apps you build, help other users, and spread the word about Dify.
### Contributors
<a href="https://github.com/langgenius/dify/graphs/contributors">
<img alt="Dify contributors" src="https://contrib.rocks/image?repo=langgenius/dify" />
</a>
## Community & contact
- [GitHub Discussion](https://github.com/langgenius/dify/discussions). Best for: sharing feedback and asking questions.
- [GitHub Issues](https://github.com/langgenius/dify/issues). Best for: bugs you encounter using Dify.AI, and feature proposals. See our [Contribution Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md).
- [Discord](https://discord.gg/FngNHpbcY7). Best for: sharing your applications and hanging out with the community.
- [X(Twitter)](https://twitter.com/dify_ai). Best for: sharing your applications and hanging out with the community.
Choose the channel that best fits your question:
**Contributors**
<a href="https://github.com/langgenius/dify/graphs/contributors">
<img src="https://contrib.rocks/image?repo=langgenius/dify" />
</a>
- [GitHub Discussions](https://github.com/langgenius/dify/discussions): Get help, share feedback, and propose ideas.
- [GitHub Issues](https://github.com/langgenius/dify/issues): Report reproducible bugs and track engineering work. Read the [Contribution Guide](CONTRIBUTING.md) before opening one.
- [Discord](https://discord.gg/FngNHpbcY7): Chat in real time, share your apps, and connect with other Dify users.
- [X](https://x.com/dify_ai): Follow Dify for release news and project updates.
## Star History
<!-- GitHub token name: star-history -->
<a href="https://www.star-history.com/?repos=langgenius%2Fdify&type=date&legend=top-left">
<a href="https://star-history.dera.page/#langgenius/dify&type=date&legend=top-left">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=langgenius/dify&type=date&theme=dark&legend=top-left&sealed_token=p-SWD-UXZEDc5a2d0EMfgMmyCwVyRlSof0Qox68v7k4PvQPKRlCx0jDIlNztw7mbA6DEn96R50DojO9pCi5LQUlDBAoIhRswt8-GuC8K3rZQ3naJUXbuHqR_oItIW2F0NNM-7npevzw5SXp7L5mwixgqJncAvAGzuGq5zmhQfiDRSW_Jd6y8TQCZMJbt" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=langgenius/dify&type=date&legend=top-left&sealed_token=p-SWD-UXZEDc5a2d0EMfgMmyCwVyRlSof0Qox68v7k4PvQPKRlCx0jDIlNztw7mbA6DEn96R50DojO9pCi5LQUlDBAoIhRswt8-GuC8K3rZQ3naJUXbuHqR_oItIW2F0NNM-7npevzw5SXp7L5mwixgqJncAvAGzuGq5zmhQfiDRSW_Jd6y8TQCZMJbt" />
<img alt="Star History Chart" src="https://api.star-history.com/chart?repos=langgenius/dify&type=date&legend=top-left&sealed_token=p-SWD-UXZEDc5a2d0EMfgMmyCwVyRlSof0Qox68v7k4PvQPKRlCx0jDIlNztw7mbA6DEn96R50DojO9pCi5LQUlDBAoIhRswt8-GuC8K3rZQ3naJUXbuHqR_oItIW2F0NNM-7npevzw5SXp7L5mwixgqJncAvAGzuGq5zmhQfiDRSW_Jd6y8TQCZMJbt" />
<source media="(prefers-color-scheme: dark)" srcset="https://star-history.dera.page/svg?repos=langgenius/dify&type=date&theme=dark&legend=top-left" />
<source media="(prefers-color-scheme: light)" srcset="https://star-history.dera.page/svg?repos=langgenius/dify&type=date&legend=top-left" />
<img alt="Star History Chart" src="https://star-history.dera.page/svg?repos=langgenius/dify&type=date&legend=top-left" />
</picture>
</a>

View File

@@ -39,6 +39,9 @@ ENABLE_COLLABORATION_MODE=true
# Learn app feature toggle
ENABLE_LEARN_APP=true
# Show the license expiry countdown badge in the console (enterprise only)
ENABLE_LICENSE_EXPIRY_NOTICE=true
# Access token expiration time in minutes
ACCESS_TOKEN_EXPIRE_MINUTES=60
@@ -95,9 +98,11 @@ REDIS_KEEPALIVE=true
CELERY_BROKER_URL=redis://:difyai123456@localhost:${REDIS_PORT}/1
CELERY_BACKEND=redis
# Ops trace retry configuration
OPS_TRACE_RETRYABLE_DISPATCH_MAX_RETRIES=60
# Ops trace configuration
OPS_TRACE_UNIFIED_ENABLED=false
OPS_TRACE_RETRYABLE_DISPATCH_MAX_RETRIES=780
OPS_TRACE_RETRYABLE_DISPATCH_DELAY_SECONDS=5
OPS_TRACE_PARENT_CONTEXT_TTL_SECONDS=3900
# Database configuration
DB_TYPE=postgresql
@@ -117,6 +122,19 @@ SQLALCHEMY_POOL_RESET_ON_RETURN=rollback
# storage type: opendal, s3, aliyun-oss, azure-blob, baidu-obs, google-storage, huawei-obs, oci-storage, tencent-cos, volcengine-tos, supabase
STORAGE_TYPE=opendal
# Key provider configuration, used to encrypt/decrypt tenant credentials (LLM/tool provider secrets)
# key provider type: local, azure-keyvault
KEY_PROVIDER_TYPE=local
# Azure Key Vault configuration, required when KEY_PROVIDER_TYPE=azure-keyvault
# authentication uses DefaultAzureCredential (managed identity, environment variables, or Azure CLI login)
AZURE_KEYVAULT_VAULT_URL=https://<your-vault-name>.vault.azure.net
AZURE_KEYVAULT_KEY_SIZE=2048
# optional: auto-rotate each tenant's key every N days. Leave empty to manage rotation manually.
# rotation is safe because old key versions are never given an expiry and stay usable forever --
# do NOT set a rotation policy on this key in the Azure portal that expires old versions.
AZURE_KEYVAULT_ROTATION_INTERVAL_DAYS=
# Apache OpenDAL storage configuration, refer to https://github.com/apache/opendal
OPENDAL_SCHEME=fs
OPENDAL_FS_ROOT=storage
@@ -204,6 +222,7 @@ SUPABASE_URL=your-server-url
# CORS configuration
WEB_API_CORS_ALLOW_ORIGINS=http://localhost:3000,*
CONSOLE_CORS_ALLOW_ORIGINS=http://localhost:3000,*
WEBSOCKET_MAX_HTTP_BUFFER_SIZE=10485760
# When the frontend and backend run on different subdomains, set COOKIE_DOMAIN to the site’s top-level domain (e.g., `example.com`). Leading dots are optional.
COOKIE_DOMAIN=
@@ -326,6 +345,7 @@ TIDB_VECTOR_PORT=4000
TIDB_VECTOR_USER=xxx.root
TIDB_VECTOR_PASSWORD=xxxxxx
TIDB_VECTOR_DATABASE=dify
TIDB_VECTOR_ENABLE_FULLTEXT_SEARCH=false
# Tidb on qdrant configuration
TIDB_ON_QDRANT_URL=http://127.0.0.1
@@ -333,6 +353,7 @@ TIDB_ON_QDRANT_API_KEY=dify
TIDB_ON_QDRANT_CLIENT_TIMEOUT=20
TIDB_ON_QDRANT_GRPC_ENABLED=false
TIDB_ON_QDRANT_GRPC_PORT=6334
TIDB_ON_QDRANT_ESTIMATED_STORAGE_LIMITS_MB=sandbox:60,professional:6400,team:25600
TIDB_PUBLIC_KEY=dify
TIDB_PRIVATE_KEY=dify
TIDB_API_URL=http://127.0.0.1
@@ -432,10 +453,12 @@ OPENGAUSS_MAX_CONNECTION=5
# Upload configuration
UPLOAD_FILE_SIZE_LIMIT=15
KNOWLEDGE_UPLOAD_FILE_SIZE_LIMIT_FOR_PAID_PLAN=15
UPLOAD_FILE_BATCH_LIMIT=5
UPLOAD_IMAGE_FILE_SIZE_LIMIT=10
UPLOAD_VIDEO_FILE_SIZE_LIMIT=100
UPLOAD_AUDIO_FILE_SIZE_LIMIT=50
UPLOAD_SKILL_FILE_SIZE_LIMIT=50
# Comma-separated list of file extensions blocked from upload for security reasons.
# Extensions should be lowercase without dots (e.g., exe,bat,sh,dll).
@@ -468,6 +491,13 @@ SENDGRID_API_KEY=
# Sentry configuration
SENTRY_DSN=
# Cloudflare Turnstile server-side verification for Dify Cloud sign-in
TURNSTILE_SECRET_KEY=
# Comma-separated parent or exact hostnames, for example: dify.ai,staging.dify.dev
TURNSTILE_ALLOWED_HOSTNAMES=
# Enable only after the compatible web client has been fully deployed.
TURNSTILE_EMAIL_CODE_VERIFY_REQUIRED=false
# DEBUG
DEBUG=false
ENABLE_REQUEST_LOGGING=False
@@ -558,7 +588,7 @@ INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH=4000
# Workflow runtime configuration
WORKFLOW_MAX_EXECUTION_STEPS=500
WORKFLOW_MAX_EXECUTION_TIME=1200
WORKFLOW_MAX_EXECUTION_TIME=3600
WORKFLOW_CALL_MAX_DEPTH=5
MAX_VARIABLE_SIZE=204800
# Maximum concurrent node-builder LLM calls per workflow generation request
@@ -569,8 +599,8 @@ WORKFLOW_GENERATOR_NODE_BUILDER_MAX_WORKERS=6
GRAPH_ENGINE_MIN_WORKERS=3
# Maximum number of workers per GraphEngine instance (default: 10)
GRAPH_ENGINE_MAX_WORKERS=10
# Queue depth threshold that triggers worker scale up (default: 3)
GRAPH_ENGINE_SCALE_UP_THRESHOLD=3
# Pending task threshold that triggers worker scale up (default: 0)
GRAPH_ENGINE_SCALE_UP_THRESHOLD=0
# Seconds of idle time before scaling down workers (default: 5.0)
GRAPH_ENGINE_SCALE_DOWN_IDLE_TIME=5.0
@@ -603,7 +633,7 @@ WORKFLOW_LOG_CLEANUP_BATCH_SIZE=100
WORKFLOW_LOG_CLEANUP_SPECIFIC_WORKFLOW_IDS=
# App configuration
APP_MAX_EXECUTION_TIME=1200
APP_MAX_EXECUTION_TIME=3600
APP_DEFAULT_ACTIVE_REQUESTS=0
APP_MAX_ACTIVE_REQUESTS=0
@@ -678,11 +708,12 @@ INNER_API_KEY_FOR_PLUGIN=QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y
# Dify Agent backend
AGENT_BACKEND_BASE_URL=http://localhost:5050
# Bearer token sent to the Agent backend /runs API. Must match DIFY_AGENT_API_TOKEN on the server side.
# Bearer token sent to the Agent backend control-plane API. Must match DIFY_AGENT_API_TOKEN on the server side.
AGENT_BACKEND_API_TOKEN=dify-agent-run-token-for-dev-only
AGENT_BACKEND_STREAM_READ_TIMEOUT_SECONDS=30
AGENT_BACKEND_STREAM_MAX_RECONNECTS=3
AGENT_BACKEND_RUN_TIMEOUT_SECONDS=1200
# Client deadline for converting a Binding file to a ToolFile through the Agent backend.
AGENT_BACKEND_BINDING_FILE_DOWNLOAD_TIMEOUT_SECONDS=240
# KnowledgeFS (Dataset 2.0)
KNOWLEDGE_FS_ENABLED=false
@@ -709,6 +740,8 @@ RESET_PASSWORD_TOKEN_EXPIRY_MINUTES=5
EMAIL_REGISTER_TOKEN_EXPIRY_MINUTES=5
CHANGE_EMAIL_TOKEN_EXPIRY_MINUTES=5
OWNER_TRANSFER_TOKEN_EXPIRY_MINUTES=5
EMAIL_CODE_LOGIN_TOKEN_EXPIRY_MINUTES=5
EMAIL_CODE_LOGIN_MAX_ATTEMPTS=5
CREATE_TIDB_SERVICE_JOB_ENABLED=false
@@ -805,6 +838,12 @@ ENABLE_HUMAN_INPUT_TIMEOUT_TASK=true
# Human input timeout check interval in minutes
HUMAN_INPUT_TIMEOUT_TASK_INTERVAL=1
# Whether to recover soft-deleted conversation cleanup jobs periodically
ENABLE_CONVERSATION_CLEANUP_TASK=true
# Recovery interval in minutes and maximum conversations dispatched per sweep
CONVERSATION_CLEANUP_TASK_INTERVAL=5
CONVERSATION_CLEANUP_BATCH_SIZE=100
# Nacos remote settings source HTTP timeouts (seconds).
# Bound how long requests to the Nacos endpoint wait before failing, so a slow or
# unresponsive Nacos server cannot stall API startup or token refresh.
@@ -812,3 +851,6 @@ HUMAN_INPUT_TIMEOUT_TASK_INTERVAL=1
DIFY_ENV_NACOS_REQUEST_TIMEOUT=10.0
# Connect timeout for Nacos requests (default: 3.0)
DIFY_ENV_NACOS_CONNECT_TIMEOUT=3.0
# skill entry
ENABLE_SKILL=true

View File

@@ -8,7 +8,502 @@ root_packages =
extensions
factories
libs
machinery
models
repositories
tasks
services
include_external_packages = True
[importlinter:contract:backend-layers]
name = Backend modules follow the transport, application, domain, and shared-library layers
type = layers
layers =
controllers
services
core
libs
# Migration baseline: keep every exception exact. The default unmatched-import
# error makes this list shrink whenever a legacy dependency is removed.
unmatched_ignore_imports_alerting = error
ignore_imports =
core.app.app_config.easy_ui_based_app.dataset.manager -> services.dataset_service
core.app.apps.advanced_chat.app_generator -> controllers.console.app.workflow
core.app.apps.advanced_chat.app_generator -> services.conversation_service
core.app.apps.advanced_chat.app_generator -> services.errors.conversation
core.app.apps.advanced_chat.app_generator -> services.workflow_draft_variable_service
core.app.apps.advanced_chat.app_runner -> services.conversation_variable_updater
core.app.apps.agent_app.app_generator -> services.agent.composer_service
core.app.apps.agent_app.app_generator -> services.agent.workspace_service
core.app.apps.agent_app.app_generator -> services.conversation_service
core.app.apps.agent_app.runtime_request_builder -> services.agent.prompt_mentions
core.app.apps.agent_app.session_store -> services.agent.workspace_service
core.app.apps.agent_chat.app_generator -> services.conversation_service
core.app.apps.base_app_generator -> services.workflow_draft_variable_service
core.app.apps.chat.app_generator -> services.conversation_service
core.app.apps.common.workflow_response_converter -> services.variable_truncator
core.app.apps.completion.app_generator -> services.errors.app
core.app.apps.completion.app_generator -> services.errors.message
core.app.apps.message_based_app_generator -> services.errors.app_model_config
core.app.apps.message_based_app_generator -> services.errors.conversation
core.app.apps.message_based_app_generator -> services.errors.message
core.app.apps.pipeline.pipeline_generator -> services
core.app.apps.pipeline.pipeline_generator -> services.dataset_service
core.app.apps.pipeline.pipeline_generator -> services.datasource_provider_service
core.app.apps.pipeline.pipeline_generator -> services.feature_service
core.app.apps.pipeline.pipeline_generator -> services.workflow_draft_variable_service
core.app.apps.pipeline.pipeline_runner -> services.dataset_ref_service
core.app.apps.workflow.app_generator -> controllers.console.app.workflow
core.app.apps.workflow.app_generator -> services.snippet_generate_service
core.app.apps.workflow.app_generator -> services.workflow_draft_variable_service
core.app.apps.workflow_app_runner -> tasks.mail_human_input_delivery_task
core.app.features.annotation_reply.annotation_reply -> services.annotation_service
core.app.features.annotation_reply.annotation_reply -> services.dataset_service
core.app.llm.quota -> services.credit_pool_service
core.app.task_pipeline.message_cycle_manager -> services.account_service
core.app.task_pipeline.message_cycle_manager -> services.annotation_service
core.app.workflow.layers.persistence -> services.workflow.inspector_events
core.datasource.datasource_manager -> services.datasource_provider_service
core.helper.credential_utils -> services.enterprise.plugin_manager_service
core.helper.credential_utils -> services.system_feature_service
core.indexing_runner -> services.vector_space_admission_service
core.mcp.auth_client -> services
core.provider_manager -> services.credential_permission_service
core.provider_manager -> services.credit_pool_service
core.provider_manager -> services.feature_service
core.rag.datasource.retrieval_service -> services.external_knowledge_service
core.rag.index_processor.index_processor -> services.vector_space_admission_service
core.rag.index_processor.index_processor_base -> services.file_service
core.rag.index_processor.processor.paragraph_index_processor -> services.account_service
core.rag.index_processor.processor.paragraph_index_processor -> services.summary_index_service
core.rag.index_processor.processor.parent_child_index_processor -> services.account_service
core.rag.index_processor.processor.parent_child_index_processor -> services.summary_index_service
core.rag.index_processor.processor.qa_index_processor -> services.summary_index_service
core.rag.retrieval.dataset_retrieval -> services.external_knowledge_service
core.rag.retrieval.dataset_retrieval -> services.feature_service
core.rag.summary_index.summary_index -> services.summary_index_service
core.rag.summary_index.summary_index -> tasks.generate_summary_index_task
core.repositories.sqlalchemy_workflow_node_execution_repository -> services.file_service
core.repositories.sqlalchemy_workflow_node_execution_repository -> services.variable_truncator
core.tools.tool_manager -> services
core.workflow.node_runtime -> services
core.workflow.nodes.agent.message_transformer -> services
core.workflow.nodes.agent_v2.agent_node -> services.agent.prompt_mentions
core.workflow.nodes.agent_v2.agent_node -> services.agent.workspace_service
core.workflow.nodes.agent_v2.dify_tools_builder -> services
core.workflow.nodes.agent_v2.runtime_feature_manifest -> services.agent.knowledge_datasets
core.workflow.nodes.agent_v2.runtime_request_builder -> services.agent.prompt_mentions
core.workflow.nodes.agent_v2.runtime_request_builder -> services.skill_management_service
core.workflow.nodes.agent_v2.session_store -> services.agent.workspace_service
core.workflow.nodes.agent_v2.validators -> services.agent.knowledge_datasets
core.workflow.nodes.agent_v2.workspace_retirement_layer -> tasks.collect_agent_resources_task
libs.device_flow_security -> controllers.openapi._models
libs.device_flow_security -> services.entities.feature_entities
libs.device_flow_security -> services.system_feature_service
libs.email_i18n -> services.entities.feature_entities
libs.email_i18n -> services.system_feature_service
libs.external_api -> core
libs.external_api -> core.errors.error
libs.external_api -> extensions.ext_logging
libs.flask_utils -> models
libs.helper -> core.app.features.rate_limiting.rate_limit
libs.helper -> models
libs.helper -> models.model
libs.json_in_md_parser -> core.llm_generator.output_parser.errors
libs.login -> extensions.ext_login
libs.login -> models
libs.login -> models.model
libs.oauth -> core.helper.http_client_pooling
libs.oauth_bearer -> models
libs.rsa -> extensions.ext_storage
libs.workspace_permission -> services.enterprise.enterprise_service
services.account_service -> controllers
services.account_service -> controllers.console.error
services.app_generate_service -> controllers.console.app.workflow
[importlinter:contract:no-direct-rsa-imports]
# Note: `libs` itself is deliberately excluded from source_modules -- import-linter's
# `forbidden` contract cannot check a package against its own descendant (libs.rsa lives
# inside libs). Sibling modules under libs/ importing libs.rsa are not covered by this
# contract; the realistic risk this guards against is application/service code reaching
# past the key provider abstraction, which is fully covered below.
name = Only the key provider abstraction may import libs.rsa directly
type = forbidden
source_modules =
core
constants
context
configs
controllers
extensions
factories
models
tasks
services
forbidden_modules =
libs.rsa
allow_indirect_imports = True
[importlinter:contract:machinery-framework-boundary]
name = API machinery is framework neutral
type = forbidden
source_modules =
machinery
forbidden_modules =
controllers
extensions
flask
models
sqlalchemy
werkzeug
[importlinter:contract:workspace-query-service-boundary]
name = Workspace query application service is framework and persistence neutral
type = forbidden
source_modules =
services.workspace_query_service
forbidden_modules =
controllers
extensions
flask
models
repositories
sqlalchemy
werkzeug
[importlinter:contract:init-validation-service-boundary]
name = Initialization validation application service is framework and persistence neutral
type = forbidden
source_modules =
services.init_validation_service
forbidden_modules =
controllers
extensions
flask
models
repositories
sqlalchemy
werkzeug
[importlinter:contract:explore-banner-query-service-boundary]
name = Explore banner query application service is framework and persistence neutral
type = forbidden
source_modules =
services.explore_banner_query_service
forbidden_modules =
controllers
extensions
flask
models
repositories
sqlalchemy
werkzeug
[importlinter:contract:account-application-boundary]
name = Account application services and contracts are framework and persistence neutral
type = forbidden
source_modules =
services.account_avatar_service
services.account_change_email_ports
services.account_change_email_service
services.account_email_registration_service
services.account_deletion_service
services.account_deletion_feedback_service
services.account_education_service
services.account_errors
services.account_initialization_service
services.account_integration_service
services.account_password_service
services.account_ports
services.account_profile_service
services.entities.account_entities
forbidden_modules =
configs
controllers
extensions
flask
models
repositories
sqlalchemy
werkzeug
[importlinter:contract:app-definition-query-service-boundary]
name = App definition query application service is framework and persistence neutral
type = forbidden
source_modules =
services.app_definition_query_service
forbidden_modules =
controllers
extensions
flask
models
repositories
sqlalchemy
werkzeug
[importlinter:contract:app-site-service-boundary]
name = App site application service is framework and persistence neutral
type = forbidden
source_modules =
services.app_site_service
forbidden_modules =
configs
controllers
extensions
flask
models
repositories
sqlalchemy
werkzeug
[importlinter:contract:webapp-access-query-service-boundary]
name = Web app access query application service is framework and persistence neutral
type = forbidden
source_modules =
services.webapp_access_query_service
forbidden_modules =
configs
controllers
extensions
flask
models
repositories
services.enterprise
services.feature_service
sqlalchemy
werkzeug
[importlinter:contract:web-app-runtime-query-service-boundary]
name = Web app runtime query application service does not directly depend on configuration, feature implementation, transport, or ORM modules
type = forbidden
source_modules =
services.web_app_runtime_query_service
forbidden_modules =
configs
controllers
extensions
flask
models
repositories
services.feature_service
services.feature_service_gateway
sqlalchemy
werkzeug
allow_indirect_imports = True
[importlinter:contract:feature-query-service-boundary]
name = Feature query application service is framework and persistence neutral
type = forbidden
source_modules =
services.feature_query_service
forbidden_modules =
controllers
extensions
flask
models
repositories
sqlalchemy
werkzeug
[importlinter:contract:data-source-oauth-service-boundary]
name = Data source OAuth application service is framework and persistence neutral
type = forbidden
source_modules =
services.data_source_oauth_service
forbidden_modules =
configs
controllers
extensions
flask
httpx
libs
models
repositories
sqlalchemy
werkzeug
[importlinter:contract:oauth-server-application-service-boundary]
name = OAuth server application service is framework and persistence neutral
type = forbidden
source_modules =
services.oauth_server_service
forbidden_modules =
configs
controllers
extensions
flask
httpx
libs
models
repositories
sqlalchemy
werkzeug
[importlinter:contract:workspace-member-query-service-boundary]
name = Workspace member query application service is framework and persistence neutral
type = forbidden
source_modules =
services.workspace_member_query_service
forbidden_modules =
configs
controllers
extensions
flask
models
repositories
services.enterprise
services.workspace_member_role_resolver
sqlalchemy
werkzeug
[importlinter:contract:setup-service-boundary]
name = Setup application service is framework and persistence neutral
type = forbidden
source_modules =
services.setup_service
forbidden_modules =
configs
controllers
extensions
flask
models
repositories
sqlalchemy
werkzeug
[importlinter:contract:schema-definition-service-boundary]
name = Schema definition application service is framework and persistence neutral
type = forbidden
source_modules =
services.schema_definition_service
forbidden_modules =
configs
controllers
extensions
flask
models
repositories
sqlalchemy
werkzeug
[importlinter:contract:inner-mail-service-boundary]
name = Inner mail application service is framework and implementation neutral
type = forbidden
source_modules =
services.inner_mail_service
forbidden_modules =
configs
controllers
extensions
flask
models
repositories
sqlalchemy
tasks
werkzeug
[importlinter:contract:web-passport-service-boundary]
name = Web passport application service is framework and persistence neutral
type = forbidden
source_modules =
services.web_passport_service
forbidden_modules =
configs
controllers
extensions
flask
models
repositories
sqlalchemy
werkzeug
[importlinter:contract:account-activation-service-boundary]
name = Account activation application service is framework and persistence neutral
type = forbidden
source_modules =
services.account_activation_service
services.entities.account_activation_entities
forbidden_modules =
configs
controllers
extensions
flask
models
repositories
sqlalchemy
werkzeug
[importlinter:contract:tag-application-service-boundary]
name = Tag application service is framework and persistence neutral
type = forbidden
source_modules =
services.tag_application_service
forbidden_modules =
configs
controllers
extensions
flask
models
repositories
sqlalchemy
werkzeug
[importlinter:contract:recommended-app-query-service-boundary]
name = Recommended app query application service is framework and persistence neutral
type = forbidden
source_modules =
services.recommended_app_query_service
forbidden_modules =
configs
controllers
extensions
flask
models
repositories
services.feature_service
services.recommended_app_catalog_gateway
sqlalchemy
werkzeug
[importlinter:contract:recommended-app-catalog-gateway-boundary]
name = Recommended app catalog gateway does not depend on Flask
type = forbidden
source_modules =
services.recommended_app_catalog_gateway
forbidden_modules =
flask
[importlinter:contract:billing-application-boundary]
name = Billing application services and ports are framework and infrastructure neutral
type = forbidden
source_modules =
services.billing_portal_service
services.compliance_download_service
services.partner_tenant_binding_service
forbidden_modules =
configs
controllers
extensions
flask
models
repositories
services.billing_service
sqlalchemy
werkzeug
[importlinter:contract:workflow-run-archive-application-boundary]
name = Workflow run archive application service and task domain are framework and persistence neutral
type = forbidden
source_modules =
services.retention.workflow_run.archive_download_task
services.retention.workflow_run.archive_log_service
forbidden_modules =
configs
controllers
extensions
flask
models
repositories
sqlalchemy
tasks
werkzeug

View File

@@ -33,7 +33,6 @@ RUN uv sync --frozen --no-dev --no-editable
FROM base AS production
ENV FLASK_APP=app.py
ENV EDITION=SELF_HOSTED
ENV DEPLOY_ENV=PRODUCTION
ENV CONSOLE_API_URL=http://127.0.0.1:5001
ENV CONSOLE_WEB_URL=http://127.0.0.1:3000
@@ -54,15 +53,14 @@ WORKDIR /app/api
# Create non-root user
ARG dify_uid=1001
ARG NODE_MAJOR=22
ARG NODE_PACKAGE_VERSION=22.21.0-1nodesource1
ARG NODE_PACKAGE_VERSION=24.20.0-1nodesource1
ARG NODESOURCE_KEY_FPR=6F71F525282841EEDAF851B42F59B5F99B1BE0B4
RUN groupadd -r -g ${dify_uid} dify && \
useradd -r -u ${dify_uid} -g ${dify_uid} -s /bin/bash dify && \
chown -R dify:dify /app
RUN \
apt-get update \
RUN NODE_MAJOR="${NODE_PACKAGE_VERSION%%.*}" \
&& apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
curl \
@@ -99,9 +97,9 @@ ENV VIRTUAL_ENV=/app/api/.venv
COPY --from=packages --chown=dify:dify ${VIRTUAL_ENV} ${VIRTUAL_ENV}
ENV PATH="${VIRTUAL_ENV}/bin:${PATH}"
# Download nltk data
RUN mkdir -p /usr/local/share/nltk_data \
&& NLTK_DATA=/usr/local/share/nltk_data python -c "import nltk; nltk.download('punkt'); nltk.download('averaged_perceptron_tagger'); nltk.download('stopwords')" \
&& NLTK_DATA=/usr/local/share/nltk_data python -m nltk.downloader punkt_tab averaged_perceptron_tagger_eng stopwords \
&& NLTK_DATA=/usr/local/share/nltk_data python -c "import nltk; nltk.data.find('tokenizers/punkt_tab'); nltk.data.find('taggers/averaged_perceptron_tagger_eng'); nltk.data.find('corpora/stopwords')" \
&& chmod -R 755 /usr/local/share/nltk_data
ENV TIKTOKEN_CACHE_DIR=/app/api/.tiktoken_cache

View File

@@ -14,9 +14,10 @@ from contexts.wrapper import RecyclableContextVar
from controllers.console.error import UnauthorizedAndForceLogout
from core.logging.context import init_request_context
from dify_app import DifyApp
from enums import DeploymentEdition
from extensions.ext_socketio import sio
from services.enterprise.enterprise_service import EnterpriseService
from services.feature_service import LicenseStatus
from services.entities.feature_entities import LicenseStatus
logger = logging.getLogger(__name__)
@@ -112,7 +113,7 @@ def create_flask_app_with_configs() -> DifyApp:
init_request_context()
RecyclableContextVar.increment_thread_recycles()
if dify_config.ENTERPRISE_ENABLED:
if dify_config.DEPLOYMENT_EDITION == DeploymentEdition.ENTERPRISE:
surface = _match_license_gated_surface(request.path)
if surface is not None:
try:
@@ -172,6 +173,7 @@ def initialize_extensions(app: DifyApp):
from context.flask_app_context import init_flask_context
from extensions import (
ext_app_metrics,
ext_application_services,
ext_blueprints,
ext_celery,
ext_code_based_extension,
@@ -183,6 +185,7 @@ def initialize_extensions(app: DifyApp):
ext_forward_refs,
ext_hosting_provider,
ext_import_modules,
ext_key_provider,
ext_logging,
ext_login,
ext_logstore,
@@ -218,6 +221,7 @@ def initialize_extensions(app: DifyApp):
ext_migrate,
ext_redis,
ext_storage,
ext_key_provider, # Initialize after storage, since RSAKeyProvider reads private keys from it
ext_set_secretkey,
ext_logstore, # Initialize logstore after storage, before celery
ext_celery,
@@ -233,6 +237,7 @@ def initialize_extensions(app: DifyApp):
ext_enterprise_telemetry,
ext_request_logging,
ext_session_factory,
ext_application_services,
ext_oauth_bearer,
]
for ext in extensions:

View File

@@ -5,8 +5,6 @@ API adapters: request building from Dify product concepts, a thin client wrapper
event adaptation for future workflow integration, and deterministic fakes.
"""
from dify_agent.protocol import RuntimeLayerSpec, extract_runtime_layer_specs
from clients.agent_backend.client import AgentBackendRunClient, DifyAgentBackendRunClient
from clients.agent_backend.errors import (
AgentBackendError,
@@ -47,11 +45,6 @@ from clients.agent_backend.request_builder import (
AgentBackendWorkflowNodeRunInput,
redact_for_agent_backend_log,
)
from clients.agent_backend.session_cleanup import (
AgentBackendSessionCleanupPayload,
AgentBackendSessionCleanupResult,
cleanup_agent_backend_session,
)
__all__ = [
"AGENT_SOUL_PROMPT_LAYER_ID",
@@ -80,8 +73,6 @@ __all__ = [
"AgentBackendRunRequestBuilder",
"AgentBackendRunStartedInternalEvent",
"AgentBackendRunSucceededInternalEvent",
"AgentBackendSessionCleanupPayload",
"AgentBackendSessionCleanupResult",
"AgentBackendStreamError",
"AgentBackendStreamInternalEvent",
"AgentBackendTransportError",
@@ -90,9 +81,6 @@ __all__ = [
"DifyAgentBackendRunClient",
"FakeAgentBackendRunClient",
"FakeAgentBackendScenario",
"RuntimeLayerSpec",
"cleanup_agent_backend_session",
"create_agent_backend_run_client",
"extract_runtime_layer_specs",
"redact_for_agent_backend_log",
]

View File

@@ -23,6 +23,7 @@ from dify_agent.protocol import (
CancelRunResponse,
CreateRunRequest,
CreateRunResponse,
RunCancelledEvent,
RunEvent,
RunStatusResponse,
)
@@ -45,6 +46,15 @@ class AgentBackendRunClient(Protocol):
def cancel_run(self, run_id: str, request: CancelRunRequest | None = None) -> CancelRunResponse:
"""Request explicit cancellation for one Agent backend run."""
def cancel_run_and_wait(
self,
run_id: str,
request: CancelRunRequest | None = None,
*,
after: str | None = None,
) -> RunCancelledEvent:
"""Request cancellation and wait for runner cleanup to finish."""
def stream_events(
self,
run_id: str,
@@ -67,6 +77,15 @@ class _DifyAgentSyncClient(Protocol):
def cancel_run_sync(self, run_id: str, request: CancelRunRequest | None = None) -> CancelRunResponse:
"""Cancel one run synchronously."""
def cancel_run_and_wait_sync(
self,
run_id: str,
request: CancelRunRequest | None = None,
*,
after: str | None = None,
) -> RunCancelledEvent:
"""Cancel one run and wait for its terminal event synchronously."""
def stream_events_sync(
self,
run_id: str,
@@ -92,11 +111,9 @@ class DifyAgentBackendRunClient:
client: _DifyAgentSyncClient,
*,
stream_max_reconnects: int = 3,
stream_timeout_seconds: float = 1200,
) -> None:
self.client = client
self._stream_max_reconnects = stream_max_reconnects
self._stream_timeout_seconds = stream_timeout_seconds
def create_run(self, request: CreateRunRequest) -> CreateRunResponse:
"""Create one run through ``POST /runs`` and normalize client exceptions."""
@@ -112,6 +129,19 @@ class DifyAgentBackendRunClient:
except Exception as exc:
raise _normalize_dify_agent_error(exc) from exc
def cancel_run_and_wait(
self,
run_id: str,
request: CancelRunRequest | None = None,
*,
after: str | None = None,
) -> RunCancelledEvent:
"""Cancel one run, then wait for the cleanup-complete terminal event."""
try:
return self.client.cancel_run_and_wait_sync(run_id, request=request, after=after)
except Exception as exc:
raise _normalize_dify_agent_error(exc) from exc
def stream_events(
self,
run_id: str,
@@ -125,7 +155,6 @@ class DifyAgentBackendRunClient:
run_id,
after=after,
max_reconnects=self._stream_max_reconnects,
timeout_seconds=self._stream_timeout_seconds,
should_stop=should_stop,
)
except Exception as exc:

View File

@@ -8,8 +8,39 @@ classes.
from __future__ import annotations
from http import HTTPStatus
from typing import Any
from dify_agent.client import DifyAgentHTTPError
from dify_agent.protocol import RunFailureType
def backend_reported_failure(exc: DifyAgentHTTPError) -> bool:
"""Whether the backend itself reported the failure.
``DifyAgentValidationError`` is a ``DifyAgentHTTPError`` that the client also
raises when a *successful* response fails DTO validation. Those carry a 2xx
status and a Pydantic error list, not a backend-authored error envelope.
"""
return exc.status_code >= HTTPStatus.BAD_REQUEST
def backend_error_detail(
exc: DifyAgentHTTPError,
*,
default_code: str = "agent_backend_error",
) -> tuple[str, str]:
"""Split an Agent backend HTTP error into the code and message the backend itself sent."""
detail = exc.detail
if isinstance(detail, dict):
code = detail.get("code")
message = detail.get("message")
return (
code if isinstance(code, str) and code else default_code,
message if isinstance(message, str) and message else str(exc),
)
return default_code, str(detail)
class AgentBackendError(Exception):
"""Base error for API-side Agent backend integration failures."""
@@ -54,6 +85,7 @@ class AgentBackendRunFailedError(AgentBackendError):
run_id: str
detail: Any
error_type: RunFailureType | None
reason: str | None
source_event_id: str | None
@@ -63,11 +95,13 @@ class AgentBackendRunFailedError(AgentBackendError):
detail: Any,
*,
message: str | None = None,
error_type: RunFailureType | None = None,
reason: str | None = None,
source_event_id: str | None = None,
) -> None:
self.run_id = run_id
self.detail = detail
self.error_type = error_type
self.reason = reason
self.source_event_id = source_event_id
display_message = message or f"Agent backend run failed: {run_id}"

View File

@@ -22,6 +22,7 @@ from dify_agent.protocol import (
RunCancelledEvent,
RunEvent,
RunFailedEvent,
RunFailureType,
RunStartedEvent,
RunSucceededEvent,
)
@@ -96,7 +97,10 @@ class AgentBackendRunFailedInternalEvent(AgentBackendInternalEventBase):
type: Literal[AgentBackendInternalEventType.RUN_FAILED] = AgentBackendInternalEventType.RUN_FAILED
error: str
error_type: RunFailureType | None = None
reason: str | None = None
session_snapshot: CompositorSessionSnapshot | None = None
usage: dict[str, JsonValue] | None = None
class AgentBackendRunCancelledInternalEvent(AgentBackendInternalEventBase):
@@ -105,6 +109,8 @@ class AgentBackendRunCancelledInternalEvent(AgentBackendInternalEventBase):
type: Literal[AgentBackendInternalEventType.RUN_CANCELLED] = AgentBackendInternalEventType.RUN_CANCELLED
reason: str | None = None
message: str | None = None
session_snapshot: CompositorSessionSnapshot | None = None
usage: dict[str, JsonValue] | None = None
type AgentBackendInternalEvent = Annotated[
@@ -180,7 +186,10 @@ class AgentBackendRunEventAdapter:
run_id=event.run_id,
source_event_id=event.id,
error=event.data.error,
error_type=event.data.error_type,
reason=event.data.reason,
session_snapshot=event.data.session_snapshot,
usage=_agent_run_usage(event.data.usage),
)
]
case RunCancelledEvent():
@@ -190,6 +199,8 @@ class AgentBackendRunEventAdapter:
source_event_id=event.id,
reason=event.data.reason,
message=event.data.message,
session_snapshot=event.data.session_snapshot,
usage=_agent_run_usage(event.data.usage),
)
]
raise TypeError(f"unsupported agent backend run event: {type(event).__name__}")

View File

@@ -8,6 +8,25 @@ from clients.agent_backend.client import AgentBackendRunClient, DifyAgentBackend
from clients.agent_backend.fake_client import FakeAgentBackendRunClient, FakeAgentBackendScenario
def create_agent_backend_client(
*,
base_url: str,
api_token: str | None = None,
stream_timeout: float = 30,
timeout: float = 30.0,
binding_file_download_timeout: float = 240,
) -> Client:
api_token = api_token.strip() if api_token else None
headers = {"Authorization": f"Bearer {api_token}"} if api_token else None
return Client(
base_url=base_url,
stream_timeout=stream_timeout,
timeout=timeout,
binding_file_download_timeout=binding_file_download_timeout,
headers=headers,
)
def create_agent_backend_run_client(
*,
base_url: str | None = None,
@@ -16,18 +35,17 @@ def create_agent_backend_run_client(
fake_scenario: str | FakeAgentBackendScenario = FakeAgentBackendScenario.SUCCESS,
stream_read_timeout_seconds: float = 30,
stream_max_reconnects: int = 3,
stream_run_timeout_seconds: float = 1200,
) -> AgentBackendRunClient:
"""Create the API-side run client without hiding the ``dify-agent`` protocol."""
if use_fake:
return FakeAgentBackendRunClient(scenario=FakeAgentBackendScenario(fake_scenario))
if base_url is None:
raise ValueError("base_url is required when creating a real Agent backend client")
headers: dict[str, str] = {}
if api_token:
headers["Authorization"] = f"Bearer {api_token}"
return DifyAgentBackendRunClient(
Client(base_url=base_url, stream_timeout=stream_read_timeout_seconds, headers=headers),
create_agent_backend_client(
base_url=base_url,
api_token=api_token,
stream_timeout=stream_read_timeout_seconds,
),
stream_max_reconnects=stream_max_reconnects,
stream_timeout_seconds=stream_run_timeout_seconds,
)

View File

@@ -18,6 +18,8 @@ from dify_agent.protocol import (
CreateRunRequest,
CreateRunResponse,
DeferredToolCallPayload,
RunCancelledEvent,
RunCancelledEventData,
RunEvent,
RunFailedEvent,
RunFailedEventData,
@@ -69,6 +71,28 @@ class FakeAgentBackendRunClient:
del request
return CancelRunResponse(run_id=run_id, status="cancelled")
def cancel_run_and_wait(
self,
run_id: str,
request: CancelRunRequest | None = None,
*,
after: str | None = None,
) -> RunCancelledEvent:
"""Return a deterministic cleanup-complete cancellation event."""
del after
request = request or CancelRunRequest()
_ = self.cancel_run(run_id, request)
return RunCancelledEvent(
id="cancel-0",
run_id=run_id,
created_at=_FIXED_TIME,
data=RunCancelledEventData(
reason=request.reason,
message=request.message,
session_snapshot=CompositorSessionSnapshot(layers=[]),
),
)
def stream_events(
self,
run_id: str,
@@ -133,7 +157,11 @@ class FakeAgentBackendRunClient:
id="2-0",
run_id=run_id,
created_at=_FIXED_TIME,
data=RunFailedEventData(error="fake failure", reason="unit_test"),
data=RunFailedEventData(
error="fake failure",
reason="unit_test",
session_snapshot=CompositorSessionSnapshot(layers=[]),
),
),
)
case FakeAgentBackendScenario.PAUSED:

View File

@@ -16,7 +16,6 @@ from collections.abc import Mapping
from typing import ClassVar, Literal
from agenton.compositor import CompositorSessionSnapshot
from agenton.compositor.schemas import LayerSessionSnapshot
from agenton.layers import ExitIntent
from agenton_collections.layers.plain import PLAIN_PROMPT_LAYER_TYPE_ID, PromptLayerConfig
from agenton_collections.layers.pydantic_ai import PYDANTIC_AI_HISTORY_LAYER_TYPE_ID
@@ -26,17 +25,16 @@ from dify_agent.layers.dify_core_tools import DIFY_CORE_TOOLS_LAYER_TYPE_ID, Dif
from dify_agent.layers.dify_plugin import (
DIFY_PLUGIN_LLM_LAYER_TYPE_ID,
DIFY_PLUGIN_TOOLS_LAYER_TYPE_ID,
DifyPluginCredentialValue,
DifyPluginLLMLayerConfig,
DifyPluginToolsLayerConfig,
)
from dify_agent.layers.drive import DIFY_DRIVE_LAYER_TYPE_ID, DifyDriveLayerConfig
from dify_agent.layers.execution_context import (
DIFY_EXECUTION_CONTEXT_LAYER_TYPE_ID,
DifyExecutionContextLayerConfig,
)
from dify_agent.layers.knowledge import DIFY_KNOWLEDGE_BASE_LAYER_TYPE_ID, DifyKnowledgeBaseLayerConfig
from dify_agent.layers.output import DIFY_OUTPUT_LAYER_TYPE_ID, DifyOutputLayerConfig
from dify_agent.layers.runtime import DIFY_RUNTIME_LAYER_TYPE_ID, DifyRuntimeLayerConfig
from dify_agent.layers.shell import DIFY_SHELL_LAYER_TYPE_ID, DifyShellLayerConfig
from dify_agent.protocol import (
DIFY_AGENT_HISTORY_LAYER_ID,
@@ -47,7 +45,6 @@ from dify_agent.protocol import (
LayerExitSignals,
RunComposition,
RunLayerSpec,
RuntimeLayerSpec,
)
from pydantic import BaseModel, ConfigDict, Field, JsonValue, field_validator
@@ -56,8 +53,8 @@ WORKFLOW_NODE_JOB_PROMPT_LAYER_ID = "workflow_node_job_prompt"
WORKFLOW_USER_PROMPT_LAYER_ID = "workflow_user_prompt"
AGENT_APP_USER_PROMPT_LAYER_ID = "agent_app_user_prompt"
DIFY_EXECUTION_CONTEXT_LAYER_ID = "execution_context"
DIFY_RUNTIME_LAYER_ID = "runtime"
DIFY_CONFIG_LAYER_ID = "config"
DIFY_DRIVE_LAYER_ID = "drive"
DIFY_PLUGIN_TOOLS_LAYER_ID = "tools"
DIFY_CORE_TOOLS_LAYER_ID = "core_tools"
DIFY_KNOWLEDGE_BASE_LAYER_ID = "knowledge"
@@ -66,45 +63,17 @@ DIFY_SHELL_LAYER_ID = "shell"
type AgentConfigVersionKind = Literal["snapshot", "draft", "build_draft"]
def _filter_snapshot_to_specs(
snapshot: CompositorSessionSnapshot,
specs: list[RuntimeLayerSpec],
) -> CompositorSessionSnapshot:
"""Keep only snapshot layers whose names appear in the cleanup spec list.
The agenton compositor rejects a snapshot whose layer-name sequence does
not match the active composition exactly. Cleanup-replay drops plugin
layers, so we must drop the matching snapshot entries here.
"""
kept_names = {spec.name for spec in specs}
filtered_layers: list[LayerSessionSnapshot] = [layer for layer in snapshot.layers if layer.name in kept_names]
if len(filtered_layers) == len(snapshot.layers):
return snapshot
return CompositorSessionSnapshot(schema_version=snapshot.schema_version, layers=filtered_layers)
def _shell_layer_deps() -> dict[str, str]:
return {"execution_context": DIFY_EXECUTION_CONTEXT_LAYER_ID}
def _drive_layer_deps() -> dict[str, str]:
return {"shell": DIFY_SHELL_LAYER_ID}
return {
"execution_context": DIFY_EXECUTION_CONTEXT_LAYER_ID,
"runtime": DIFY_RUNTIME_LAYER_ID,
}
def _config_layer_deps() -> dict[str, str]:
return {"shell": DIFY_SHELL_LAYER_ID}
def _shell_config_with_drive_ref(
shell_config: DifyShellLayerConfig | None,
drive_config: DifyDriveLayerConfig | None,
) -> DifyShellLayerConfig:
config = shell_config or DifyShellLayerConfig()
if drive_config is None:
return config
return config.model_copy(update={"agent_stub_drive_ref": drive_config.drive_ref})
def _markdown_backtick_fence(text: str) -> str:
"""Choose a fence that will not terminate inside the prompt body."""
longest_backtick_run = max((len(match.group(0)) for match in re.finditer(r"`+", text)), default=0)
@@ -164,8 +133,8 @@ class AgentBackendModelConfig(BaseModel):
plugin_id: str
model_provider: str
model: str
credentials: dict[str, DifyPluginCredentialValue] = Field(default_factory=dict)
model_settings: dict[str, JsonValue] = Field(default_factory=dict)
context_window_tokens: int | None = Field(default=None, gt=0)
model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid")
@@ -173,8 +142,12 @@ class AgentBackendModelConfig(BaseModel):
# ``DifyPluginLLMLayerConfig.model_settings`` is pydantic_ai's ``ModelSettings``
# TypedDict (closed: unknown keys are rejected, explicit ``None`` values fail the
# per-field type checks). Agent Soul model settings carry a wider, nullable shape
# (``stop`` / ``response_format`` plus null-padded fields), so the layer config
# only receives the keys the runtime contract accepts.
# (``stop`` / ``response_format`` plus null-padded fields, plus arbitrary
# plugin-declared parameters such as Qwen's ``enable_thinking``), so the layer
# config only receives the keys the runtime contract accepts directly; anything
# else is forwarded through ``extra_body``, the TypedDict's own escape hatch for
# provider-specific parameters (see
# ``dify_agent.adapters.llm.model._map_model_settings_to_parameters``).
_AGENT_MODEL_SETTINGS_PASSTHROUGH_KEYS = (
"temperature",
"top_p",
@@ -182,6 +155,7 @@ _AGENT_MODEL_SETTINGS_PASSTHROUGH_KEYS = (
"frequency_penalty",
"max_tokens",
)
_AGENT_MODEL_SETTINGS_KNOWN_KEYS = frozenset({*_AGENT_MODEL_SETTINGS_PASSTHROUGH_KEYS, "stop", "response_format"})
def _agent_model_settings(settings: Mapping[str, JsonValue]) -> dict[str, JsonValue] | None:
@@ -191,6 +165,15 @@ def _agent_model_settings(settings: Mapping[str, JsonValue]) -> dict[str, JsonVa
stop = settings.get("stop")
if isinstance(stop, list) and stop:
sanitized["stop_sequences"] = stop
extra_body: dict[str, JsonValue] = {
key: value
for key, value in settings.items()
if key not in _AGENT_MODEL_SETTINGS_KNOWN_KEYS and value is not None
}
if extra_body:
sanitized["extra_body"] = extra_body
return sanitized or None
@@ -214,6 +197,7 @@ class AgentBackendWorkflowNodeRunInput(BaseModel):
model: AgentBackendModelConfig
execution_context: DifyExecutionContextLayerConfig
backend_binding_ref: str = Field(min_length=1)
workflow_node_job_prompt: str
user_prompt: str
agent_soul_prompt: str | None = None
@@ -224,15 +208,12 @@ class AgentBackendWorkflowNodeRunInput(BaseModel):
core_tools: DifyCoreToolsLayerConfig | None = None
knowledge: DifyKnowledgeBaseLayerConfig | None = None
config_layer_config: DifyConfigLayerConfig | None = None
# Drive Skills & Files declaration (dify.drive) — an index the agent pulls
# through the back proxy, never inline content.
drive_config: DifyDriveLayerConfig | None = None
# Human-in-the-loop ask_human deferred tool (dify.ask_human). Present only when
# the Agent Soul configures human involvement; a deferred call ends the run and
# the workflow pauses via the existing HITL form mechanism (ENG-635).
ask_human_config: DifyAskHumanLayerConfig | None = None
# Inject the sandboxed shell layer (dify.shell). Requires the agent backend
# to be wired with a shellctl entrypoint; see configs AGENT_SHELL_ENABLED.
# Inject the sandboxed shell graph. Requires a deployment-selected runtime
# backend plus the product-resolved persistent Binding.
include_shell: bool = False
shell_config: DifyShellLayerConfig | None = None
session_snapshot: CompositorSessionSnapshot | None = None
@@ -240,7 +221,6 @@ class AgentBackendWorkflowNodeRunInput(BaseModel):
# (ENG-638). Keyed by the original deferred tool_call_id.
deferred_tool_results: DeferredToolResultsPayload | None = None
include_history: bool = True
suspend_on_exit: bool = True
metadata: dict[str, JsonValue] = Field(default_factory=dict)
model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid", arbitrary_types_allowed=True)
@@ -264,6 +244,7 @@ class AgentBackendAgentAppRunInput(BaseModel):
model: AgentBackendModelConfig
execution_context: DifyExecutionContextLayerConfig
backend_binding_ref: str = Field(min_length=1)
user_prompt: str
agent_soul_prompt: str | None = None
agent_config_version_kind: AgentConfigVersionKind = "snapshot"
@@ -273,14 +254,11 @@ class AgentBackendAgentAppRunInput(BaseModel):
core_tools: DifyCoreToolsLayerConfig | None = None
knowledge: DifyKnowledgeBaseLayerConfig | None = None
config_layer_config: DifyConfigLayerConfig | None = None
# Drive Skills & Files declaration (dify.drive) — an index the agent pulls
# through the back proxy, never inline content.
drive_config: DifyDriveLayerConfig | None = None
# Human-in-the-loop ask_human deferred tool (dify.ask_human). Present only when
# the Agent Soul configures human involvement (ENG-635).
ask_human_config: DifyAskHumanLayerConfig | None = None
# Inject the sandboxed shell layer (dify.shell). Requires the agent backend
# to be wired with a shellctl entrypoint; see configs AGENT_SHELL_ENABLED.
# Inject the sandboxed shell graph. Requires a deployment-selected runtime
# backend plus the product-resolved persistent Binding.
include_shell: bool = False
shell_config: DifyShellLayerConfig | None = None
session_snapshot: CompositorSessionSnapshot | None = None
@@ -288,7 +266,6 @@ class AgentBackendAgentAppRunInput(BaseModel):
# (ENG-638). Keyed by the original deferred tool_call_id.
deferred_tool_results: DeferredToolResultsPayload | None = None
include_history: bool = True
suspend_on_exit: bool = True
metadata: dict[str, JsonValue] = Field(default_factory=dict)
model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid", arbitrary_types_allowed=True)
@@ -308,7 +285,7 @@ class AgentBackendRunRequestBuilder:
"""Build an Agent App conversation-turn run request.
Layer graph: optional Agent Soul system prompt → user prompt →
execution context → optional shell / config / drive / history
execution context → optional shell / config / history
(multi-turn) → LLM → optional plugin-direct tools / core-routed tools /
knowledge search / ask_human / structured output. Mirrors the
workflow-node layer ordering minus the workflow-job / previous-node
@@ -346,20 +323,25 @@ class AgentBackendRunRequestBuilder:
]
)
include_shell = (
run_input.include_shell or run_input.config_layer_config is not None or run_input.drive_config is not None
)
include_shell = run_input.include_shell or run_input.config_layer_config is not None
if include_shell:
# Sandboxed bash workspace (dify.shell). It enters before config/drive
# so eager pulls materialize content in the same filesystem used by
# model commands.
layers.append(
RunLayerSpec(
name=DIFY_RUNTIME_LAYER_ID,
type=DIFY_RUNTIME_LAYER_TYPE_ID,
metadata=run_input.metadata,
config=DifyRuntimeLayerConfig(backend_binding_ref=run_input.backend_binding_ref),
)
)
# Sandboxed bash workspace (dify.shell). It enters before config so
# eager pulls materialize content in the same filesystem used by model commands.
layers.append(
RunLayerSpec(
name=DIFY_SHELL_LAYER_ID,
type=DIFY_SHELL_LAYER_TYPE_ID,
deps=_shell_layer_deps(),
metadata=run_input.metadata,
config=_shell_config_with_drive_ref(run_input.shell_config, run_input.drive_config),
config=run_input.shell_config or DifyShellLayerConfig(),
)
)
@@ -374,19 +356,6 @@ class AgentBackendRunRequestBuilder:
)
)
if run_input.drive_config is not None:
# Drive Skills & Files declaration (dify.drive): the catalog plus
# prompt-mentioned entries eagerly pulled through the shell layer.
layers.append(
RunLayerSpec(
name=DIFY_DRIVE_LAYER_ID,
type=DIFY_DRIVE_LAYER_TYPE_ID,
deps=_drive_layer_deps(),
metadata=run_input.metadata,
config=run_input.drive_config,
)
)
if run_input.include_history:
layers.append(
RunLayerSpec(
@@ -406,8 +375,8 @@ class AgentBackendRunRequestBuilder:
plugin_id=run_input.model.plugin_id,
model_provider=run_input.model.model_provider,
model=run_input.model.model,
credentials=run_input.model.credentials,
model_settings=_agent_model_settings(run_input.model.model_settings),
context_window_tokens=run_input.model.context_window_tokens,
),
)
)
@@ -481,60 +450,14 @@ class AgentBackendRunRequestBuilder:
metadata=run_input.metadata,
session_snapshot=run_input.session_snapshot,
deferred_tool_results=run_input.deferred_tool_results,
on_exit=LayerExitSignals(
default=ExitIntent.SUSPEND if run_input.suspend_on_exit else ExitIntent.DELETE,
),
)
def build_cleanup_request(
self,
*,
session_snapshot: CompositorSessionSnapshot,
runtime_layer_specs: list[RuntimeLayerSpec],
idempotency_key: str | None = None,
metadata: dict[str, JsonValue] | None = None,
) -> CreateRunRequest:
"""Build a lifecycle-only cleanup request that replays the prior layers.
The agenton compositor enforces that the session snapshot's layer names
match the active composition in order, so cleanup must replay the same
non-plugin layer graph that produced the snapshot. Plugin layers
(``dify.plugin.llm``, ``dify.plugin.tools``) are excluded from both the
composition and the snapshot before submission because their configs
may carry credentials or runtime-only declarations that are not
persisted between runs.
"""
if not runtime_layer_specs:
raise ValueError(
"build_cleanup_request requires runtime_layer_specs; an empty "
"composition would fail the agent backend's snapshot validation."
)
request_metadata = dict(metadata or {})
request_metadata["agent_backend_lifecycle"] = "session_cleanup"
layers = [
RunLayerSpec(
name=spec.name,
type=spec.type,
deps=dict(spec.deps),
metadata=dict(spec.metadata),
config=spec.config,
)
for spec in runtime_layer_specs
]
filtered_snapshot = _filter_snapshot_to_specs(session_snapshot, runtime_layer_specs)
return CreateRunRequest(
composition=RunComposition(layers=layers),
idempotency_key=idempotency_key,
metadata=request_metadata,
session_snapshot=filtered_snapshot,
on_exit=LayerExitSignals(default=ExitIntent.DELETE),
on_exit=LayerExitSignals(default=ExitIntent.SUSPEND),
)
def build_for_workflow_node(self, run_input: AgentBackendWorkflowNodeRunInput) -> CreateRunRequest:
"""Build a workflow Agent Node run request without defining another wire schema.
Layer graph mirrors the workflow surface: prompts → execution context →
optional shell / config / drive / history → LLM → optional
optional shell / config / history → LLM → optional
plugin-direct tools / core-routed tools / knowledge search /
ask_human / structured output.
"""
@@ -576,20 +499,25 @@ class AgentBackendRunRequestBuilder:
]
)
include_shell = (
run_input.include_shell or run_input.config_layer_config is not None or run_input.drive_config is not None
)
include_shell = run_input.include_shell or run_input.config_layer_config is not None
if include_shell:
# Sandboxed bash workspace (dify.shell). It enters before drive so
# drive can materialize mentioned targets with `dify-agent drive pull`
# in the same shell-visible filesystem used by model commands.
layers.append(
RunLayerSpec(
name=DIFY_RUNTIME_LAYER_ID,
type=DIFY_RUNTIME_LAYER_TYPE_ID,
metadata=run_input.metadata,
config=DifyRuntimeLayerConfig(backend_binding_ref=run_input.backend_binding_ref),
)
)
# Sandboxed bash workspace (dify.shell). It enters before config so
# eager pulls materialize content in the same filesystem used by model commands.
layers.append(
RunLayerSpec(
name=DIFY_SHELL_LAYER_ID,
type=DIFY_SHELL_LAYER_TYPE_ID,
deps=_shell_layer_deps(),
metadata=run_input.metadata,
config=_shell_config_with_drive_ref(run_input.shell_config, run_input.drive_config),
config=run_input.shell_config or DifyShellLayerConfig(),
)
)
@@ -604,19 +532,6 @@ class AgentBackendRunRequestBuilder:
)
)
if run_input.drive_config is not None:
# Drive Skills & Files declaration (dify.drive): the catalog plus
# prompt-mentioned entries eagerly pulled through the shell layer.
layers.append(
RunLayerSpec(
name=DIFY_DRIVE_LAYER_ID,
type=DIFY_DRIVE_LAYER_TYPE_ID,
deps=_drive_layer_deps(),
metadata=run_input.metadata,
config=run_input.drive_config,
)
)
if run_input.include_history:
layers.append(
RunLayerSpec(
@@ -637,8 +552,8 @@ class AgentBackendRunRequestBuilder:
plugin_id=run_input.model.plugin_id,
model_provider=run_input.model.model_provider,
model=run_input.model.model,
credentials=run_input.model.credentials,
model_settings=_agent_model_settings(run_input.model.model_settings),
context_window_tokens=run_input.model.context_window_tokens,
),
),
]
@@ -713,9 +628,7 @@ class AgentBackendRunRequestBuilder:
metadata=run_input.metadata,
session_snapshot=run_input.session_snapshot,
deferred_tool_results=run_input.deferred_tool_results,
on_exit=LayerExitSignals(
default=ExitIntent.SUSPEND if run_input.suspend_on_exit else ExitIntent.DELETE,
),
on_exit=LayerExitSignals(default=ExitIntent.SUSPEND),
)

View File

@@ -1,100 +0,0 @@
"""Shared API-side helper for Agent backend lifecycle-only session cleanup.
Product code owns local row retirement and background-task dispatch. This module
only adapts persisted cleanup inputs into the public ``dify-agent`` run
protocol, performs the synchronous ``create_run + wait_run`` loop used by Celery
workers, and reports whether the backend cleanup succeeded, was skipped, or
failed.
"""
from __future__ import annotations
from dataclasses import dataclass
from typing import ClassVar, Literal
from agenton.compositor import CompositorSessionSnapshot
from dify_agent.protocol import RuntimeLayerSpec
from pydantic import BaseModel, ConfigDict, Field, JsonValue
from clients.agent_backend.client import AgentBackendRunClient
from clients.agent_backend.errors import AgentBackendError
from clients.agent_backend.request_builder import AgentBackendRunRequestBuilder
class AgentBackendSessionCleanupPayload(BaseModel):
"""Serialized cleanup inputs preserved across API and Celery boundaries."""
session_snapshot: CompositorSessionSnapshot | None = None
runtime_layer_specs: list[RuntimeLayerSpec] = Field(default_factory=list)
idempotency_key: str | None = None
metadata: dict[str, JsonValue] = Field(default_factory=dict)
timeout_seconds: float = 30.0
model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid")
@dataclass(frozen=True, slots=True)
class AgentBackendSessionCleanupResult:
"""Terminal outcome of one backend cleanup attempt."""
status: Literal["succeeded", "skipped", "failed"]
reason: str | None = None
cleanup_run_id: str | None = None
@classmethod
def succeeded(cls, cleanup_run_id: str) -> AgentBackendSessionCleanupResult:
return cls(status="succeeded", cleanup_run_id=cleanup_run_id)
@classmethod
def skipped(cls, reason: str) -> AgentBackendSessionCleanupResult:
return cls(status="skipped", reason=reason)
@classmethod
def failed(cls, reason: str, cleanup_run_id: str | None = None) -> AgentBackendSessionCleanupResult:
return cls(status="failed", reason=reason, cleanup_run_id=cleanup_run_id)
def cleanup_agent_backend_session(
*,
payload: AgentBackendSessionCleanupPayload,
client: AgentBackendRunClient | None,
request_builder: AgentBackendRunRequestBuilder | None = None,
) -> AgentBackendSessionCleanupResult:
"""Run lifecycle-only cleanup against the Agent backend and report status."""
if client is None:
return AgentBackendSessionCleanupResult.skipped("no_agent_backend_client")
if payload.session_snapshot is None:
return AgentBackendSessionCleanupResult.skipped("missing_session_snapshot")
if not payload.runtime_layer_specs:
return AgentBackendSessionCleanupResult.skipped("missing_runtime_layer_specs")
builder = request_builder or AgentBackendRunRequestBuilder()
request = builder.build_cleanup_request(
session_snapshot=payload.session_snapshot,
runtime_layer_specs=payload.runtime_layer_specs,
idempotency_key=payload.idempotency_key,
metadata=payload.metadata,
)
try:
response = client.create_run(request)
except AgentBackendError as exc:
return AgentBackendSessionCleanupResult.failed(str(exc))
try:
status_response = client.wait_run(response.run_id, timeout_seconds=payload.timeout_seconds)
except AgentBackendError as exc:
return AgentBackendSessionCleanupResult.failed(str(exc), cleanup_run_id=response.run_id)
if status_response.status != "succeeded":
reason = status_response.error or f"cleanup run ended with status {status_response.status}"
return AgentBackendSessionCleanupResult.failed(reason, cleanup_run_id=response.run_id)
return AgentBackendSessionCleanupResult.succeeded(response.run_id)
__all__ = [
"AgentBackendSessionCleanupPayload",
"AgentBackendSessionCleanupResult",
"cleanup_agent_backend_session",
]

View File

@@ -22,7 +22,12 @@ from .plugin import (
setup_system_trigger_oauth_client,
transform_datasource_credentials,
)
from .rbac import migrate_dataset_permissions_to_rbac, migrate_member_roles_to_rbac
from .rbac import (
migrate_dataset_permissions_to_rbac,
migrate_member_roles_to_rbac,
migrate_only_me_resource_whitelist_scopes_to_automatic_include,
migrate_resource_whitelist_scopes_to_automatic_include,
)
from .retention import (
archive_workflow_runs,
archive_workflow_runs_plan,
@@ -81,7 +86,9 @@ __all__ = [
"migrate_dataset_permissions_to_rbac",
"migrate_knowledge_vector_database",
"migrate_member_roles_to_rbac",
"migrate_only_me_resource_whitelist_scopes_to_automatic_include",
"migrate_oss",
"migrate_resource_whitelist_scopes_to_automatic_include",
"migration_data_wizard",
"old_metadata_migration",
"remove_orphaned_files_on_storage",

View File

@@ -8,6 +8,7 @@ from constants.languages import languages
from extensions.ext_database import db
from libs.helper import email as email_validate
from libs.password import hash_password, password_pattern, valid_password
from services.account_email import normalize_email
from services.account_service import AccountService, RegisterService, TenantService
@@ -20,7 +21,7 @@ def reset_password(email, new_password, password_confirm):
Reset password of owner account
Only available in SELF_HOSTED mode
"""
if str(new_password).strip() != str(password_confirm).strip():
if new_password.strip() != password_confirm.strip():
click.echo(click.style("Passwords do not match.", fg="red"))
return
normalized_email = email.strip().lower()
@@ -33,7 +34,7 @@ def reset_password(email, new_password, password_confirm):
try:
valid_password(new_password)
except:
except ValueError:
click.echo(click.style(f"Invalid password. Must match {password_pattern}", fg="red"))
return
@@ -62,7 +63,7 @@ def reset_email(email, new_email, email_confirm):
Replace account email
:return:
"""
if str(new_email).strip() != str(email_confirm).strip():
if new_email.strip() != email_confirm.strip():
click.echo(click.style("New emails do not match.", fg="red"))
return
normalized_new_email = new_email.strip().lower()
@@ -75,13 +76,14 @@ def reset_email(email, new_email, email_confirm):
try:
email_validate(normalized_new_email)
except:
except ValueError:
click.echo(click.style(f"Invalid email: {new_email}", fg="red"))
return
with Session(db.engine) as session:
account = session.merge(account)
account.email = normalized_new_email
account.normalized_email = normalize_email(normalized_new_email)
session.commit()
click.echo(click.style("Email updated successfully.", fg="green"))

View File

@@ -7,7 +7,11 @@ from typing import cast
import click
from commands.rbac import migrate_dataset_permissions_to_rbac
from commands.rbac import (
migrate_dataset_permissions_to_rbac,
migrate_only_me_resource_whitelist_scopes_to_automatic_include,
migrate_resource_whitelist_scopes_to_automatic_include, # noqa: F401
)
from extensions.ext_database import db
from graphon.model_runtime.entities.model_entities import ModelType
from services.legacy_model_type_migration import (
@@ -179,3 +183,4 @@ def legacy_model_types(
data_migrate.add_command(legacy_model_types)
data_migrate.add_command(migrate_dataset_permissions_to_rbac)
data_migrate.add_command(migrate_only_me_resource_whitelist_scopes_to_automatic_include)

View File

@@ -11,10 +11,11 @@ from sqlalchemy.orm import Session
from configs import dify_config
from core.db.session_factory import session_factory
from core.rbac import RBACResourceWhitelistScope
from models import Dataset, DatasetPermission, DatasetPermissionEnum, TenantAccountJoin, TenantAccountRole
from models import App, Dataset, DatasetPermission, DatasetPermissionEnum, TenantAccountJoin, TenantAccountRole
from services.enterprise.rbac_service import ListOption, RBACService, ReplaceMemberBindings, ReplaceUserAccessPolicies
_RBAC_DEFAULT_ACCESS_POLICY_ID = "default"
_RBAC_RESOURCE_ACCESS_POLICY_BATCH_SIZE = 500
_LEGACY_ROLE_TO_BUILTIN_TAG = {
TenantAccountRole.OWNER.value: "owner",
@@ -310,6 +311,499 @@ def _emit_dataset_permission_migration_event(payload: dict[str, object]) -> None
click.echo(json.dumps(payload, sort_keys=True))
def _emit_resource_whitelist_scope_migration_event(payload: dict[str, object]) -> None:
click.echo(json.dumps(payload, sort_keys=True))
def _normalize_rbac_whitelist_scope(scope: object) -> RBACResourceWhitelistScope | None:
if scope is None:
return None
try:
return RBACResourceWhitelistScope(str(scope))
except ValueError as exc:
raise ValueError(f"Unsupported RBAC whitelist scope: {scope}") from exc
def _owner_account_id(tenant_id: str, *, session: Session) -> str:
account_id = session.scalar(
select(TenantAccountJoin.account_id)
.where(TenantAccountJoin.tenant_id == tenant_id, TenantAccountJoin.role == TenantAccountRole.OWNER)
.order_by(TenantAccountJoin.id.asc())
.limit(1)
)
if not account_id:
raise ValueError(f"Workspace owner not found for tenant={tenant_id}")
return str(account_id)
def _workspace_member_account_id_batches(tenant_id: str, batch_size: int) -> Iterator[list[str]]:
last_join_id: str | None = None
while True:
with session_factory.create_session() as session:
stmt = (
select(TenantAccountJoin.id, TenantAccountJoin.account_id)
.where(TenantAccountJoin.tenant_id == tenant_id)
.order_by(TenantAccountJoin.id.asc())
.limit(batch_size)
)
if last_join_id:
stmt = stmt.where(TenantAccountJoin.id > last_join_id)
rows = list(session.execute(stmt).all())
if not rows:
return
yield [str(row.account_id) for row in rows]
last_join_id = str(rows[-1].id)
def _replace_resource_whitelist(
resource_type: str,
*,
tenant_id: str,
operator_account_id: str,
resource_id: str,
automatic_include_workspace_members: bool,
) -> None:
payload = ReplaceMemberBindings(automatic_include_workspace_members=automatic_include_workspace_members)
if resource_type == "app":
RBACService.AppAccess.replace_whitelist(
tenant_id=tenant_id,
account_id=operator_account_id,
app_id=resource_id,
payload=payload,
)
return
RBACService.DatasetAccess.replace_whitelist(
tenant_id=tenant_id,
account_id=operator_account_id,
dataset_id=resource_id,
payload=payload,
)
def _replace_resource_default_access_policies(
resource_type: str,
*,
tenant_id: str,
operator_account_id: str,
resource_id: str,
account_ids: list[str],
) -> None:
if not account_ids:
return
payload = ReplaceUserAccessPolicies(
access_policy_ids=[_RBAC_DEFAULT_ACCESS_POLICY_ID],
account_ids=account_ids,
)
if resource_type == "app":
RBACService.AppAccess.replace_user_access_policies(
tenant_id=tenant_id,
account_id=operator_account_id,
app_id=resource_id,
target_account_id=None,
payload=payload,
)
return
RBACService.DatasetAccess.replace_user_access_policies(
tenant_id=tenant_id,
account_id=operator_account_id,
dataset_id=resource_id,
target_account_id=None,
payload=payload,
)
def _resource_legacy_whitelist_config(
resource_type: str,
*,
tenant_id: str,
operator_account_id: str,
resource_id: str,
):
if resource_type == "app":
return RBACService.AppAccess.legacy_whitelist_config(
tenant_id=tenant_id,
account_id=operator_account_id,
app_id=resource_id,
)
return RBACService.DatasetAccess.legacy_whitelist_config(
tenant_id=tenant_id,
account_id=operator_account_id,
dataset_id=resource_id,
)
def _iter_rbac_resource_rows(
resource_type: str,
*,
tenant_id: str | None,
resource_id: str | None,
batch_size: int,
) -> Iterator[tuple[str, str, str, str | None]]:
model = App if resource_type == "app" else Dataset
last_resource_id: str | None = None
while True:
with session_factory.create_session() as session:
stmt = select(model.id, model.tenant_id, model.maintainer).order_by(model.id.asc()).limit(batch_size)
if tenant_id:
stmt = stmt.where(model.tenant_id == tenant_id)
if resource_id:
stmt = stmt.where(model.id == resource_id)
if last_resource_id:
stmt = stmt.where(model.id > last_resource_id)
rows = list(session.execute(stmt).all())
if not rows:
return
for row in rows:
yield resource_type, str(row.tenant_id), str(row.id), str(row.maintainer) if row.maintainer else None
last_resource_id = str(rows[-1].id)
if resource_id:
return
def _iter_selected_rbac_resource_rows(
resource_type: str,
*,
tenant_id: str | None,
resource_id: str | None,
batch_size: int,
) -> Iterator[tuple[str, str, str, str | None]]:
if resource_type in {"app", "all"}:
yield from _iter_rbac_resource_rows(
"app",
tenant_id=tenant_id,
resource_id=resource_id if resource_type == "app" else None,
batch_size=batch_size,
)
if resource_type in {"dataset", "all"}:
yield from _iter_rbac_resource_rows(
"dataset",
tenant_id=tenant_id,
resource_id=resource_id if resource_type == "dataset" else None,
batch_size=batch_size,
)
@click.command(
"rbac-migrate-resource-whitelist-scopes",
help=(
"Migrate RBAC app/dataset whitelist scope values to automatic_include_workspace_members. "
"Old scope all becomes true; specific and only_me become false."
),
)
@click.option("--tenant-id", help="Only migrate resources in a single workspace.")
@click.option(
"--resource-type",
type=click.Choice(["app", "dataset", "all"]),
default="all",
show_default=True,
help="Resource type to migrate.",
)
@click.option("--resource-id", help="Only migrate a single resource. Requires --resource-type app or dataset.")
@click.option("--batch-size", default=500, show_default=True, type=click.IntRange(min=1))
@click.option(
"--member-batch-size",
default=_RBAC_RESOURCE_ACCESS_POLICY_BATCH_SIZE,
show_default=True,
type=click.IntRange(min=1),
help="Workspace members written per default-policy call when migrating old scope all.",
)
@click.option(
"--dry-run/--apply",
default=True,
show_default=True,
help="Preview the migration without writing RBAC bindings. Use --apply to write changes.",
)
def migrate_resource_whitelist_scopes_to_automatic_include(
tenant_id: str | None,
resource_type: str,
resource_id: str | None,
batch_size: int,
member_batch_size: int,
dry_run: bool,
) -> None:
"""Backfill RBAC app/dataset automatic workspace-member inclusion from old RBAC scope."""
if resource_id and resource_type == "all":
raise click.BadParameter("--resource-id requires --resource-type app or dataset", param_hint="--resource-id")
click.echo(click.style("Starting RBAC resource whitelist scope migration.", fg="green"))
scanned_count = 0
migrated_count = 0
member_policy_batch_count = 0
owner_account_ids_by_tenant_id: dict[str, str] = {}
for (
current_resource_type,
workspace_id,
current_resource_id,
maintainer_account_id,
) in _iter_selected_rbac_resource_rows(
resource_type,
tenant_id=tenant_id,
resource_id=resource_id,
batch_size=batch_size,
):
scanned_count += 1
with session_factory.create_session() as session:
operator_account_id = maintainer_account_id or owner_account_ids_by_tenant_id.get(workspace_id)
if not operator_account_id:
operator_account_id = _owner_account_id(workspace_id, session=session)
owner_account_ids_by_tenant_id[workspace_id] = operator_account_id
legacy_config = _resource_legacy_whitelist_config(
current_resource_type,
tenant_id=workspace_id,
operator_account_id=operator_account_id,
resource_id=current_resource_id,
)
scope = _normalize_rbac_whitelist_scope(legacy_config.rbac_whitelist_scope)
if scope is None:
_emit_resource_whitelist_scope_migration_event(
{
"event": "resource_whitelist_scope_migration_skipped",
"reason": "missing_legacy_scope",
"dry_run": dry_run,
"tenant_id": workspace_id,
"resource_type": current_resource_type,
"resource_id": current_resource_id,
}
)
continue
automatic_include_workspace_members = scope is RBACResourceWhitelistScope.ALL
if scope is RBACResourceWhitelistScope.SPECIFIC:
member_account_ids = sorted(set(legacy_config.account_ids))
member_source = "legacy_specific_members"
elif scope is RBACResourceWhitelistScope.ONLY_ME:
member_account_ids = [maintainer_account_id] if maintainer_account_id else []
member_source = "resource_maintainer"
else:
member_account_ids = []
member_source = "workspace_members"
_emit_resource_whitelist_scope_migration_event(
{
"event": "resource_whitelist_scope_migration_proposed_change",
"dry_run": dry_run,
"tenant_id": workspace_id,
"operator_account_id": operator_account_id,
"resource_type": current_resource_type,
"resource_id": current_resource_id,
"before": {
"rbac_whitelist_scope": scope.value,
"legacy_account_ids": sorted(set(legacy_config.account_ids)),
},
"after": {
"automatic_include_workspace_members": automatic_include_workspace_members,
"default_policy_member_source": member_source,
"default_policy_account_ids": member_account_ids,
},
}
)
if dry_run:
continue
_replace_resource_whitelist(
current_resource_type,
tenant_id=workspace_id,
operator_account_id=operator_account_id,
resource_id=current_resource_id,
automatic_include_workspace_members=automatic_include_workspace_members,
)
migrated_count += 1
if scope is RBACResourceWhitelistScope.ALL:
for batch in _workspace_member_account_id_batches(workspace_id, member_batch_size):
_replace_resource_default_access_policies(
current_resource_type,
tenant_id=workspace_id,
operator_account_id=operator_account_id,
resource_id=current_resource_id,
account_ids=batch,
)
member_policy_batch_count += 1
else:
_replace_resource_default_access_policies(
current_resource_type,
tenant_id=workspace_id,
operator_account_id=operator_account_id,
resource_id=current_resource_id,
account_ids=member_account_ids,
)
if member_account_ids:
member_policy_batch_count += 1
if scanned_count == 0:
click.echo(click.style("No RBAC resources found for migration.", fg="yellow"))
return
if dry_run:
click.echo(
click.style(
f"Dry run completed. Scanned {scanned_count} RBAC resources. No RBAC bindings were written.",
fg="yellow",
)
)
else:
click.echo(
click.style(
"RBAC resource whitelist scope migration completed. "
f"Scanned {scanned_count} resources, migrated {migrated_count}, "
f"wrote {member_policy_batch_count} default-policy batches.",
fg="green",
)
)
@click.command(
"rbac-migrate-resource-whitelist-scopes",
help=(
"Migrate RBAC app/dataset whitelist configs whose old scope is only_me to "
"automatic_include_workspace_members=true and sync workspace members into the whitelist."
),
)
@click.option("--tenant-id", help="Only migrate resources in a single workspace.")
@click.option(
"--resource-type",
type=click.Choice(["app", "dataset", "all"]),
default="all",
show_default=True,
help="Resource type to migrate.",
)
@click.option("--resource-id", help="Only migrate a single resource. Requires --resource-type app or dataset.")
@click.option("--batch-size", default=500, show_default=True, type=click.IntRange(min=1))
@click.option(
"--member-batch-size",
default=_RBAC_RESOURCE_ACCESS_POLICY_BATCH_SIZE,
show_default=True,
type=click.IntRange(min=1),
help="Workspace members written per default-policy call.",
)
@click.option(
"--dry-run/--apply",
default=True,
show_default=True,
help="Preview the migration without writing RBAC bindings. Use --apply to write changes.",
)
def migrate_only_me_resource_whitelist_scopes_to_automatic_include(
tenant_id: str | None,
resource_type: str,
resource_id: str | None,
batch_size: int,
member_batch_size: int,
dry_run: bool,
) -> None:
"""Backfill automatic workspace-member inclusion for old RBAC only_me resource scopes."""
if resource_id and resource_type == "all":
raise click.BadParameter("--resource-id requires --resource-type app or dataset", param_hint="--resource-id")
click.echo(click.style("Starting RBAC only_me resource whitelist scope migration.", fg="green"))
scanned_count = 0
only_me_count = 0
migrated_count = 0
member_policy_batch_count = 0
owner_account_ids_by_tenant_id: dict[str, str] = {}
for (
current_resource_type,
workspace_id,
current_resource_id,
maintainer_account_id,
) in _iter_selected_rbac_resource_rows(
resource_type,
tenant_id=tenant_id,
resource_id=resource_id,
batch_size=batch_size,
):
scanned_count += 1
with session_factory.create_session() as session:
operator_account_id = maintainer_account_id or owner_account_ids_by_tenant_id.get(workspace_id)
if not operator_account_id:
operator_account_id = _owner_account_id(workspace_id, session=session)
owner_account_ids_by_tenant_id[workspace_id] = operator_account_id
legacy_config = _resource_legacy_whitelist_config(
current_resource_type,
tenant_id=workspace_id,
operator_account_id=operator_account_id,
resource_id=current_resource_id,
)
scope = _normalize_rbac_whitelist_scope(legacy_config.rbac_whitelist_scope)
if scope is not RBACResourceWhitelistScope.ONLY_ME:
continue
only_me_count += 1
_emit_resource_whitelist_scope_migration_event(
{
"event": "only_me_resource_whitelist_scope_migration_proposed_change",
"dry_run": dry_run,
"tenant_id": workspace_id,
"operator_account_id": operator_account_id,
"resource_type": current_resource_type,
"resource_id": current_resource_id,
"before": {
"rbac_whitelist_scope": scope.value,
"legacy_account_ids": sorted(set(legacy_config.account_ids)),
},
"after": {
"automatic_include_workspace_members": True,
"default_policy_member_source": "workspace_members",
},
}
)
if dry_run:
continue
_replace_resource_whitelist(
current_resource_type,
tenant_id=workspace_id,
operator_account_id=operator_account_id,
resource_id=current_resource_id,
automatic_include_workspace_members=True,
)
migrated_count += 1
for batch in _workspace_member_account_id_batches(workspace_id, member_batch_size):
_replace_resource_default_access_policies(
current_resource_type,
tenant_id=workspace_id,
operator_account_id=operator_account_id,
resource_id=current_resource_id,
account_ids=batch,
)
member_policy_batch_count += 1
if scanned_count == 0:
click.echo(click.style("No RBAC resources found for migration.", fg="yellow"))
return
if dry_run:
click.echo(
click.style(
f"Dry run completed. Scanned {scanned_count} RBAC resources, found {only_me_count} only_me resources. "
"No RBAC bindings were written.",
fg="yellow",
)
)
else:
click.echo(
click.style(
"RBAC only_me resource whitelist scope migration completed. "
f"Scanned {scanned_count} resources, migrated {migrated_count}, "
f"wrote {member_policy_batch_count} default-policy batches.",
fg="green",
)
)
@click.command(
"rbac-migrate-dataset-permissions",
help=(
@@ -399,7 +893,9 @@ def migrate_dataset_permissions_to_rbac(
)
scanned_count += 1
replace_whitelist_payload = ReplaceMemberBindings(scope=scope)
replace_whitelist_payload = ReplaceMemberBindings(
automatic_include_workspace_members=scope is RBACResourceWhitelistScope.ALL
)
if dry_run:
_emit_dataset_permission_migration_event(
{

View File

@@ -10,6 +10,8 @@ import click
import sqlalchemy as sa
from sqlalchemy.orm import Session, sessionmaker
from configs import dify_config
from enums import CloudPlan, DeploymentEdition
from extensions.ext_database import db
from libs.datetime_utils import naive_utc_now
from services.clear_free_plan_tenant_expired_logs import ClearFreePlanTenantExpiredLogs
@@ -126,14 +128,12 @@ def _get_archive_candidate_tenant_ids_by_prefix(
def _filter_paid_workflow_archive_tenant_ids(tenant_ids: list[str]) -> tuple[list[str], list[str]]:
from configs import dify_config
from enums.cloud_plan import CloudPlan
from services.billing_service import BillingService
tenant_ids = sorted(set(tenant_ids))
if not tenant_ids:
return [], []
if not dify_config.BILLING_ENABLED:
if dify_config.DEPLOYMENT_EDITION != DeploymentEdition.CLOUD:
return tenant_ids, []
plans = BillingService.get_plan_bulk_with_cache(tenant_ids)
@@ -1462,7 +1462,7 @@ def cleanup_orphaned_draft_variables(
"--graceful-period",
default=21,
show_default=True,
help="Graceful period in days after subscription expiration, will be ignored when billing is disabled.",
help="Graceful period in days after subscription expiration; ignored outside the Cloud edition.",
)
@click.option("--dry-run", is_flag=True, default=False, help="Show messages logs would be cleaned without deleting")
def clean_expired_messages(
@@ -1514,8 +1514,8 @@ def clean_expired_messages(
if from_days_ago <= before_days:
raise click.UsageError("--from-days-ago must be greater than --before-days.")
# Create policy based on billing configuration
# NOTE: graceful_period will be ignored when billing is disabled.
# Create the policy for the configured deployment edition.
# NOTE: graceful_period is ignored outside the Cloud edition.
policy = create_message_clean_policy(graceful_period_days=graceful_period)
if from_days_ago is not None and before_days is not None:

View File

@@ -6,12 +6,12 @@ from sqlalchemy import delete, select, update
from sqlalchemy.orm import sessionmaker
from configs import dify_config
from enums.deployment_edition import DeploymentEdition
from enums import DeploymentEdition
from events.app_event import app_was_created
from extensions.ext_database import db
from extensions.ext_redis import redis_client
from libs.db_migration_lock import DbMigrationAutoRenewLock
from libs.rsa import generate_key_pair
from libs.key_providers import generate_key_pair
from models import Tenant
from models.model import App, AppMode, Conversation
from models.provider import Provider, ProviderModel

View File

@@ -5,7 +5,6 @@ from typing import Any, override
from pydantic.fields import FieldInfo
from pydantic_settings import BaseSettings, PydanticBaseSettingsSource, SettingsConfigDict, TomlConfigSettingsSource
from enums.deployment_edition import DeploymentEdition
from libs.file_utils import search_file_upwards
from .deploy import DeploymentConfig
@@ -117,11 +116,3 @@ class DifyConfig(
),
),
)
@property
def DEPLOYMENT_EDITION(self) -> DeploymentEdition:
if self.EDITION == "CLOUD":
return DeploymentEdition.CLOUD
if self.ENTERPRISE_ENABLED:
return DeploymentEdition.ENTERPRISE
return DeploymentEdition.COMMUNITY

View File

@@ -1,8 +1,8 @@
from typing import Literal
from pydantic import Field
from pydantic_settings import BaseSettings
from enums import DeploymentEdition
class DeploymentConfig(BaseSettings):
"""
@@ -25,9 +25,14 @@ class DeploymentConfig(BaseSettings):
default=False,
)
EDITION: Literal["SELF_HOSTED", "CLOUD"] = Field(
description="Deployment edition of the application (e.g., 'SELF_HOSTED', 'CLOUD')",
default="SELF_HOSTED",
DEPLOYMENT_EDITION: DeploymentEdition = Field(
description="Product edition of the application.",
default=DeploymentEdition.COMMUNITY,
)
INIT_PASSWORD: str = Field(
description="Password required before initializing a self-hosted deployment",
default="",
)
DEPLOY_ENV: str = Field(

View File

@@ -8,12 +8,6 @@ class EnterpriseFeatureConfig(BaseSettings):
**Before using, please contact business@dify.ai by email to inquire about licensing matters.**
"""
ENTERPRISE_ENABLED: bool = Field(
description="Enable or disable enterprise-level features."
"Before using, please contact business@dify.ai by email to inquire about licensing matters.",
default=False,
)
WEBAPP_PUBLIC_ACCESS_ENABLED: bool = Field(
description="Whether admins are allowed to set a webapp's access mode to public (anyone with the link, "
"no auth). Disable in security-sensitive on-prem deployments.",
@@ -25,6 +19,12 @@ class EnterpriseFeatureConfig(BaseSettings):
default=False,
)
ENABLE_LICENSE_EXPIRY_NOTICE: bool = Field(
description="Show the license expiry countdown badge in the console when the license is expiring. "
"Disable to hide the badge; license status and all enforcement remain unaffected.",
default=True,
)
ENTERPRISE_REQUEST_TIMEOUT: int = Field(
ge=1, description="Maximum timeout in seconds for enterprise requests", default=5
)
@@ -53,7 +53,7 @@ class EnterpriseTelemetryConfig(BaseSettings):
"""
ENTERPRISE_TELEMETRY_ENABLED: bool = Field(
description="Enable enterprise telemetry collection (also requires ENTERPRISE_ENABLED=true).",
description="Enable enterprise telemetry collection for enterprise deployments.",
default=False,
)
@@ -83,11 +83,6 @@ class EnterpriseTelemetryConfig(BaseSettings):
default=False,
)
ENTERPRISE_SERVICE_NAME: str = Field(
description="Service name for OTEL resource.",
default="dify",
)
ENTERPRISE_OTEL_SAMPLING_RATE: float = Field(
description="Sampling rate for enterprise traces (0.0 to 1.0, default 1.0 = 100%).",
default=1.0,

View File

@@ -1,8 +1,10 @@
from configs.extra.agent_backend_config import AgentBackendConfig
from configs.extra.archive_config import ArchiveStorageConfig
from configs.extra.knowledge_fs_config import KnowledgeFSConfig
from configs.extra.logstore_config import LogStoreConfig
from configs.extra.notion_config import NotionConfig
from configs.extra.sentry_config import SentryConfig
from configs.extra.turnstile_config import TurnstileConfig
class ExtraServiceConfig(
@@ -10,7 +12,9 @@ class ExtraServiceConfig(
AgentBackendConfig,
ArchiveStorageConfig,
KnowledgeFSConfig,
LogStoreConfig,
NotionConfig,
SentryConfig,
TurnstileConfig,
):
pass

View File

@@ -13,7 +13,7 @@ class AgentBackendConfig(BaseSettings):
)
AGENT_BACKEND_API_TOKEN: str | None = Field(
description="Bearer token for authenticating with the Agent backend /runs API.",
description="Bearer token for authenticating with the Agent backend control-plane API.",
default=None,
)
@@ -37,16 +37,23 @@ class AgentBackendConfig(BaseSettings):
default=3,
)
AGENT_BACKEND_RUN_TIMEOUT_SECONDS: PositiveFloat = Field(
description="Total deadline for one Agent backend run event stream.",
default=1200,
AGENT_BACKEND_HOME_SNAPSHOT_TIMEOUT_SECONDS: PositiveFloat = Field(
description=(
"Client timeout for Agent backend calls that may carry a Home Snapshot transfer: "
"snapshot capture and delete, and Execution Binding creation that restores one. "
),
default=45.0,
)
AGENT_BACKEND_BINDING_FILE_DOWNLOAD_TIMEOUT_SECONDS: PositiveFloat = Field(
description="Client timeout for converting a Binding file to a ToolFile through the Agent backend.",
default=240,
)
AGENT_SHELL_ENABLED: bool = Field(
description=(
"Inject the dify.shell layer (sandboxed bash workspace) into Agent runs. "
"Requires the agent backend to be wired with a shellctl entrypoint before "
"shell-using Agent runs are executed."
"Inject the Home, Workspace, Sandbox, and Shell runtime layers into Agent runs. "
"Requires Dify Agent to have a deployment-selected runtime backend."
),
default=True,
)

View File

@@ -0,0 +1,11 @@
from pydantic_settings import BaseSettings
class LogStoreConfig(BaseSettings):
"""Migration controls for repositories backed by Aliyun LogStore."""
LOGSTORE_DUAL_WRITE_ENABLED: bool = False
# Keep workflow graphs in LogStore by default. Deployments may disable this
# while migrating large graph payloads to another persistence owner.
LOGSTORE_ENABLE_PUT_GRAPH_FIELD: bool = True

View File

@@ -0,0 +1,41 @@
from pydantic import Field, SecretStr, field_validator
from pydantic_settings import BaseSettings
class TurnstileConfig(BaseSettings):
"""Server-side Cloudflare Turnstile settings for Cloud sign-in."""
TURNSTILE_SECRET_KEY: SecretStr | None = Field(
default=None,
description="Secret key used to validate Cloudflare Turnstile tokens.",
)
TURNSTILE_ALLOWED_HOSTNAMES: str = Field(
default="",
description="Comma-separated parent or exact hostnames accepted from Turnstile.",
)
TURNSTILE_EMAIL_CODE_VERIFY_REQUIRED: bool = Field(
default=False,
description=(
"Require a separate Turnstile challenge when verifying email login codes on Dify Cloud. "
"Enable after the compatible web client has been deployed."
),
)
@field_validator("TURNSTILE_SECRET_KEY", mode="before")
@classmethod
def normalize_secret_key(cls, value: object) -> object:
if isinstance(value, SecretStr):
normalized = value.get_secret_value().strip()
return SecretStr(normalized) if normalized else None
if isinstance(value, str):
normalized = value.strip()
return normalized or None
return value
@property
def TURNSTILE_ALLOWED_HOSTNAME_SET(self) -> frozenset[str]:
return frozenset(
hostname.strip().lower().strip(".")
for hostname in self.TURNSTILE_ALLOWED_HOSTNAMES.split(",")
if hostname.strip().strip(".")
)

View File

@@ -12,6 +12,7 @@ from pydantic import (
PositiveInt,
computed_field,
field_validator,
model_validator,
)
from pydantic_settings import BaseSettings
@@ -83,7 +84,7 @@ class AppExecutionConfig(BaseSettings):
APP_MAX_EXECUTION_TIME: PositiveInt = Field(
description="Maximum allowed execution time for the application in seconds",
default=1200,
default=3600,
)
APP_DEFAULT_ACTIVE_REQUESTS: NonNegativeInt = Field(
description="Default number of concurrent active requests per app (0 for unlimited)",
@@ -450,6 +451,11 @@ class FileUploadConfig(BaseSettings):
default=15,
)
KNOWLEDGE_UPLOAD_FILE_SIZE_LIMIT_FOR_PAID_PLAN: NonNegativeInt = Field(
description="Maximum allowed file size for knowledge uploads on paid cloud plans in megabytes",
default=15,
)
UPLOAD_FILE_BATCH_LIMIT: NonNegativeInt = Field(
description="Maximum number of files allowed in a single upload batch",
default=5,
@@ -470,6 +476,11 @@ class FileUploadConfig(BaseSettings):
default=50,
)
UPLOAD_SKILL_FILE_SIZE_LIMIT: NonNegativeInt = Field(
description="Maximum allowed Skill package size for uploads in megabytes",
default=50,
)
BATCH_UPLOAD_LIMIT: NonNegativeInt = Field(
description="Maximum number of files allowed in a batch upload operation",
default=20,
@@ -582,6 +593,16 @@ class HttpConfig(BaseSettings):
def CONSOLE_CORS_ALLOW_ORIGINS(self) -> list[str]:
return self.inner_CONSOLE_CORS_ALLOW_ORIGINS.split(",")
WEBSOCKET_MAX_HTTP_BUFFER_SIZE: PositiveInt = Field(
description=(
"Maximum Socket.IO / Engine.IO HTTP buffer size in bytes. "
"Large workflow collaboration payloads (sync_request graph snapshots) "
"exceed the Engine.IO default of 1 MiB and get rejected, which "
"disconnects the editor WebSocket. Default is 10 MiB."
),
default=10 * 1024 * 1024,
)
inner_WEB_API_CORS_ALLOW_ORIGINS: str = Field(
description="",
validation_alias=AliasChoices("WEB_API_CORS_ALLOW_ORIGINS"),
@@ -800,17 +821,6 @@ class ModelLoadBalanceConfig(BaseSettings):
)
class BillingConfig(BaseSettings):
"""
Configuration for platform billing features
"""
BILLING_ENABLED: bool = Field(
description="Enable or disable billing functionality",
default=False,
)
class UpdateConfig(BaseSettings):
"""
Configuration for application update checks
@@ -865,7 +875,7 @@ class WorkflowVariableTruncationConfig(BaseSettings):
)
WORKFLOW_VARIABLE_TRUNCATION_STRING_LENGTH: PositiveInt = Field(
100000,
description="maximum length for string to trigger tuncation, measure in number of characters",
description="maximum length for string to trigger truncation, measure in number of characters",
)
WORKFLOW_VARIABLE_TRUNCATION_ARRAY_LENGTH: PositiveInt = Field(
1000,
@@ -890,7 +900,7 @@ class WorkflowConfig(BaseSettings):
WORKFLOW_MAX_EXECUTION_TIME: PositiveInt = Field(
description="Maximum execution time in seconds for a single workflow",
default=1200,
default=3600,
)
WORKFLOW_CALL_MAX_DEPTH: PositiveInt = Field(
@@ -919,9 +929,9 @@ class WorkflowConfig(BaseSettings):
default=10,
)
GRAPH_ENGINE_SCALE_UP_THRESHOLD: PositiveInt = Field(
description="Queue depth threshold that triggers worker scale up",
default=3,
GRAPH_ENGINE_SCALE_UP_THRESHOLD: NonNegativeInt = Field(
description="Pending task threshold that triggers worker scale up",
default=0,
)
GRAPH_ENGINE_SCALE_DOWN_IDLE_TIME: float = Field(
@@ -1291,6 +1301,13 @@ class DataSetConfig(BaseSettings):
)
class SkillConfig(BaseSettings):
ENABLE_SKILL: bool = Field(
description="Enable or disable Skill feature entry points",
default=True,
)
class WorkspaceConfig(BaseSettings):
"""
Configuration for workspace management
@@ -1325,10 +1342,28 @@ class MultiModalTransferConfig(BaseSettings):
)
class NewAgentBetaConfig(BaseSettings):
NEW_AGENT_BETA_ACTIVITY_START_AT: datetime | None = Field(
description="New Agent Beta Publish window start in RFC3339 UTC (inclusive)",
default=None,
)
NEW_AGENT_BETA_ACTIVITY_END_AT: datetime | None = Field(
description="New Agent Beta Publish window end in RFC3339 UTC (exclusive)",
default=None,
)
class OpsTraceConfig(BaseSettings):
OPS_TRACE_UNIFIED_ENABLED: bool = Field(
description="Enable unified ops tracing for providers registered in the unified registry.",
default=False,
)
# Include scheduling and export grace after the parent workflow's maximum execution time.
# Recommended: max_retries >= ceil((WORKFLOW_MAX_EXECUTION_TIME + grace_seconds) / delay_seconds).
OPS_TRACE_RETRYABLE_DISPATCH_MAX_RETRIES: PositiveInt = Field(
description="Maximum retry attempts for transient ops trace provider dispatch failures.",
default=60,
default=780,
)
OPS_TRACE_RETRYABLE_DISPATCH_DELAY_SECONDS: PositiveInt = Field(
@@ -1336,6 +1371,20 @@ class OpsTraceConfig(BaseSettings):
default=5,
)
OPS_TRACE_PARENT_CONTEXT_TTL_SECONDS: PositiveInt = Field(
description="Retention in seconds for unified tracing parent contexts.",
default=3900,
)
@model_validator(mode="after")
def validate_parent_context_retention(self) -> "OpsTraceConfig":
if not self.OPS_TRACE_UNIFIED_ENABLED:
return self
retry_window = self.OPS_TRACE_RETRYABLE_DISPATCH_MAX_RETRIES * self.OPS_TRACE_RETRYABLE_DISPATCH_DELAY_SECONDS
if retry_window > self.OPS_TRACE_PARENT_CONTEXT_TTL_SECONDS:
raise ValueError("OPS_TRACE_PARENT_CONTEXT_TTL_SECONDS must cover the retry window")
return self
class CeleryBeatConfig(BaseSettings):
CELERY_BEAT_SCHEDULER_TIME: int = Field(
@@ -1345,6 +1394,18 @@ class CeleryBeatConfig(BaseSettings):
class CeleryScheduleTasksConfig(BaseSettings):
ENABLE_CONVERSATION_CLEANUP_TASK: bool = Field(
description="Enable periodic recovery of soft-deleted conversation cleanup",
default=True,
)
CONVERSATION_CLEANUP_TASK_INTERVAL: PositiveInt = Field(
description="Soft-deleted conversation cleanup recovery interval in minutes",
default=5,
)
CONVERSATION_CLEANUP_BATCH_SIZE: PositiveInt = Field(
description="Maximum soft-deleted conversations dispatched per cleanup sweep",
default=100,
)
ENABLE_CLEAN_EMBEDDING_CACHE_TASK: bool = Field(
description="Enable clean embedding cache task",
default=False,
@@ -1527,6 +1588,10 @@ class LoginConfig(BaseSettings):
description="expiry time in minutes for email code login token",
default=5,
)
EMAIL_CODE_LOGIN_MAX_ATTEMPTS: PositiveInt = Field(
description="maximum number of verification attempts for an email code login challenge",
default=5,
)
ALLOW_REGISTER: bool = Field(
description="whether to enable register",
default=False,
@@ -1611,7 +1676,6 @@ class FeatureConfig(
# place the configs in alphabet order
AppExecutionConfig,
AuthConfig, # Changed from OAuthConfig to AuthConfig
BillingConfig,
CodeExecutionSandboxConfig,
CreatorsPlatformConfig,
TriggerConfig,
@@ -1631,12 +1695,14 @@ class FeatureConfig(
ModelLoadBalanceConfig,
ModerationConfig,
MultiModalTransferConfig,
NewAgentBetaConfig,
OpsTraceConfig,
PositionConfig,
RagEtlConfig,
RepositoryConfig,
SandboxExpiredRecordsCleanConfig,
SecurityConfig,
SkillConfig,
TenantIsolatedTaskQueueConfig,
ToolConfig,
UpdateConfig,

View File

@@ -451,6 +451,12 @@ class HostedFetchAppTemplateConfig(BaseSettings):
default="https://tmpl.dify.ai",
)
HOSTED_FETCH_APP_TEMPLATES_CACHE_TTL: int = Field(
description="TTL in seconds for caching remote app template HTTP responses. 0 disables caching.",
default=600,
ge=0,
)
class HostedFetchPipelineTemplateConfig(BaseSettings):
"""

View File

@@ -7,6 +7,7 @@ from pydantic_settings import BaseSettings
from .cache.redis_config import RedisConfig
from .cache.redis_pubsub_config import RedisPubSubConfig
from .key_provider.azure_keyvault_config import AzureKeyVaultConfig
from .storage.aliyun_oss_storage_config import AliyunOSSStorageConfig
from .storage.amazon_s3_storage_config import S3StorageConfig
from .storage.azure_blob_storage_config import AzureBlobStorageConfig
@@ -83,6 +84,22 @@ class StorageConfig(BaseSettings):
)
_VALID_KEY_PROVIDER_TYPE = Literal[
"local",
"azure-keyvault",
]
class KeyProviderConfig(BaseSettings):
KEY_PROVIDER_TYPE: _VALID_KEY_PROVIDER_TYPE = Field(
description="Key provider used to encrypt/decrypt tenant credentials (LLM/tool provider secrets)."
" Options: 'local' (per-tenant RSA key pair, private key kept in the STORAGE_TYPE backend),"
" 'azure-keyvault' (per-tenant RSA key kept in Azure Key Vault, private key never leaves the vault)."
" Default is 'local'.",
default=cast(_VALID_KEY_PROVIDER_TYPE, "local"),
)
class VectorStoreConfig(BaseSettings):
VECTOR_STORE: str | None = Field(
description="Type of vector store to use for efficient similarity search."
@@ -318,22 +335,6 @@ class CeleryConfig(DatabaseConfig):
return self.CELERY_BROKER_URL.startswith("rediss://") if self.CELERY_BROKER_URL else False
class InternalTestConfig(BaseSettings):
"""
Configuration settings for Internal Test
"""
AWS_SECRET_ACCESS_KEY: str | None = Field(
description="Internal test AWS secret access key",
default=None,
)
AWS_ACCESS_KEY_ID: str | None = Field(
description="Internal test AWS access key ID",
default=None,
)
class DatasetQueueMonitorConfig(BaseSettings):
"""
Configuration settings for Dataset Queue Monitor
@@ -359,6 +360,9 @@ class MiddlewareConfig(
KeywordStoreConfig,
RedisConfig,
RedisPubSubConfig,
# configs of the tenant credential encryption key provider
KeyProviderConfig,
AzureKeyVaultConfig,
# configs of storage and storage providers
StorageConfig,
AliyunOSSStorageConfig,
@@ -396,7 +400,6 @@ class MiddlewareConfig(
WeaviateConfig,
ElasticsearchConfig,
CouchbaseConfig,
InternalTestConfig,
VikingDBConfig,
UpstashConfig,
TidbOnQdrantConfig,

Some files were not shown because too many files have changed in this diff Show More