Compare commits

..
Author SHA1 Message Date
-LAN- fae6d4f2dd chore: add default value for FILES_URL
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-04 21:30:12 +08:00
twwu 495324b85b Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-09-04 20:52:02 +08:00
twwu 65df8f6c57 refactor(DocumentList): Optimize dataset configuration handling and improve data source type checks 2025-09-04 20:51:56 +08:00
jyong d4ee915058 Merge branch 'feat/queue-based-graph-engine' into feat/rag-2 2025-09-04 20:51:48 +08:00
-LAN- 81e9d6f63a fix: correct type checking for None values in code node output validation
- Fixed isinstance() checks to properly handle None values by checking None separately
- Fixed typo in STRING type validation where 'output_name' was hardcoded as string instead of variable
- Updated error message format to be consistent and more informative
- Updated test assertion to match new error message format
2025-09-04 20:39:37 +08:00
twwu 637afe1ab0 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-09-04 20:36:38 +08:00
twwu df70e28481 chore(docker): Update Docker images to version 2.0.0-beta.1 for API, worker, web, and plugin daemon services 2025-09-04 20:36:23 +08:00
jyong b9394d542c Merge branch 'feat/queue-based-graph-engine' into feat/rag-2
# Conflicts:
#	api/core/app/apps/advanced_chat/generate_task_pipeline.py
#	api/pyproject.toml
#	api/uv.lock
#	docker/docker-compose-template.yaml
#	docker/docker-compose.yaml
#	web/package.json
2025-09-04 20:30:08 +08:00
twwu 1fda319ecb chore(docker): Update Docker images to version 2.0.0-beta1 for API, worker, web, and plugin daemon services 2025-09-04 20:24:17 +08:00
-LAN- 9c2943183e test: fix code node
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-04 20:17:28 +08:00
twwu 814cbee28e chore: Update GitHub Actions workflow to include 'feat/rag-2' path for build triggers 2025-09-04 20:11:16 +08:00
twwu 443e1fad32 chore: Bump version to 2.0.0-beta1 2025-09-04 20:06:15 +08:00
-LAN- f6a2a09815 test: fix code node
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-04 20:04:29 +08:00
jyong e21c133e1d change migration 2025-09-04 19:38:51 +08:00
-LAN- e229510e73 perf: eliminate lock contention in worker pool by removing callbacks
Remove worker idle/active callbacks that caused severe lock contention.
Instead, use sampling-based monitoring where worker states are queried
on-demand during scaling decisions. This eliminates the performance
bottleneck caused by workers acquiring locks 10+ times per second.

Changes:
- Remove callback parameters from Worker class
- Add properties to expose worker idle state directly
- Update WorkerPool to query worker states without callbacks
- Maintain scaling functionality with better performance
2025-09-04 19:37:31 +08:00
-LAN- 36048d1526 feat(graph_engine): allow to scale down without lock
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-04 19:32:07 +08:00
-LAN- aff7ca12b8 fix(code_node): type checking bypass
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-04 19:25:08 +08:00
twwu 8506288180 fix(firecrawl): map markdown content to content field in crawl results 2025-09-04 19:24:54 +08:00
-LAN- ad9eed2551 fix: disable scale for perfermance
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-04 19:11:22 +08:00
twwu ef64729771 refactor(notion-page-preview): update fetchNotionPagePreview to include pageType parameter for improved API request 2025-09-04 19:02:35 +08:00
jyong 771ea54a0b change migration 2025-09-04 18:37:58 +08:00
jyong 35ec0d25e8 change migration 2025-09-04 18:06:45 +08:00
-LAN- 07109846e0 Merge remote-tracking branch 'origin/main' into feat/queue-based-graph-engine 2025-09-04 17:48:08 +08:00
-LAN- 2aeaefccec test: fix test 2025-09-04 17:47:36 +08:00
-LAN- 4d63bd2083 refactor(graph_engine): rename SimpleWorkerPool to WorkerPool 2025-09-04 17:47:13 +08:00
jyong 952fb16b91 change migration 2025-09-04 17:37:21 +08:00
jyong e9f11b4706 change migration 2025-09-04 17:29:09 +08:00
jyong 41b5596441 fix file name 2025-09-04 17:11:13 +08:00
twwu 55b936003f refactor(context-menu): conditionally render export option based on pipeline ID 2025-09-04 16:47:21 +08:00
WTW0313 a6b0071ca0 feat: add datasource category handling in marketplace list condition 2025-09-04 16:05:29 +08:00
-LAN- 226f14a20f feat(graph_engine): implement scale down worker
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-04 15:35:20 +08:00
twwu ebeb17ec96 refactor(form-input-item): enhance type switch logic to include select input handling 2025-09-04 15:34:21 +08:00
twwu 313069a63e refactor(workflow): improve loading state rendering and enhance control prompt editor re-rendering logic 2025-09-04 15:27:55 +08:00
jyong 64fc0c9073 Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-09-04 14:52:34 +08:00
jyong 94f2956e3a fix file name 2025-09-04 14:52:23 +08:00
zxhlyh 1bf04b7b74 fix: export workflow image 2025-09-04 14:43:14 +08:00
jyong 1e5f6c1475 fix file name 2025-09-04 14:07:58 +08:00
Novice 9f3c996be2 fix(pipeline-publish): publish not update dataset 2025-09-04 14:07:42 +08:00
twwu 0bcdd0db99 fix(field): add z-index to sticky header for improved layering in workflow nodes 2025-09-04 13:18:14 +08:00
twwu 5ecf382180 refactor(chunk-preview): improve key assignment for ChunkContainer components and enhance localFileList handling in Preparation component 2025-09-04 13:03:49 +08:00
autofix-ci[bot]andGitHub 2b28aed4e2 [autofix.ci] apply automated fixes 2025-09-04 04:50:21 +00:00
-LAN- 938a845852 Merge remote-tracking branch 'origin/main' into feat/queue-based-graph-engine 2025-09-04 12:48:58 +08:00
twwu 04d01c8409 refactor(icons): remove unused Globe01 icon and related files 2025-09-04 12:37:01 +08:00
jyong 7efe215d2b fix file name 2025-09-04 12:28:52 +08:00
-LAN- ead8568bfc fix: some errors reported by basedpyright
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-04 11:58:54 +08:00
Novice 25e3f4da04 fix(pipeline-tracing-log): datasource icon error 2025-09-04 11:44:10 +08:00
Novice 68f4d4b97c fix(rag-pipeline-dsl): dsl import session error 2025-09-04 11:03:45 +08:00
twwu c40dfe7060 fix(pipeline): correct API endpoint for stopping workflow runs 2025-09-04 10:39:23 +08:00
jyong 647af6fc69 fix file name 2025-09-04 10:36:44 +08:00
twwu 5114569017 refactor(document-picker): enhance chunking mode handling and improve parent mode label logic 2025-09-04 09:59:55 +08:00
-LAN- ed22d04ea0 test: remove outdated test case 2025-09-04 02:42:36 +08:00
-LAN- 04bbf540d9 chore: code format
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-04 02:33:53 +08:00
-LAN- 657c27ec75 feat(graph_engine): make runtime state read-only in layer
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-04 02:30:40 +08:00
-LAN- 16e9cd5ac5 feat(graph_runtime_state): prevent to set variable pool after initialized. 2025-09-04 02:20:19 +08:00
-LAN- 61c79b0013 test: correct imported name 2025-09-04 02:15:46 +08:00
-LAN- 8332472944 refactor(graph_engine): rename Layer to GraphEngineLayer
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-04 02:11:31 +08:00
-LAN- fe3f03e50a feat: add property-based access control to GraphRuntimeState
- Replace direct field access with private attributes and property decorators
- Implement deep copy protection for mutable objects (dict, LLMUsage)
- Add helper methods: set_output(), get_output(), update_outputs()
- Add increment_node_run_steps() and add_tokens() convenience methods
- Update loop_node and event_handlers to use new accessor methods
- Add comprehensive unit tests for immutability and validation
- Ensure backward compatibility with existing property access patterns
2025-09-04 02:08:58 +08:00
-LAN- 9c96b23d55 Merge remote-tracking branch 'origin/main' into feat/queue-based-graph-engine 2025-09-04 00:27:08 +08:00
twwu f811855f79 fix(workflow): ensure variable updates only occur for matching selectors in updateNodeVars 2025-09-03 23:28:32 +08:00
twwu c7510d3f54 refactor(panel): simplify outputSchema mapping for improved readability 2025-09-03 23:06:12 +08:00
jyong e3092837e4 fix file name 2025-09-03 21:26:28 +08:00
twwu 46731dc8a1 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-09-03 20:33:01 +08:00
twwu 1214942eb7 refactor(datasets): rename 'markdown' to 'content' for consistency across components 2025-09-03 20:32:48 +08:00
jyong dd89c9aa21 fix preview and recommend plugins 2025-09-03 19:51:07 +08:00
jyong 5ab3cd7213 fix preview and recommend plugins 2025-09-03 19:42:20 +08:00
jyong 49d268d4a3 fix preview and recommend plugins 2025-09-03 19:20:14 +08:00
Novice aa670c8982 fix(datasource): add datasource icon in tracing panel 2025-09-03 18:23:23 +08:00
Joel c8d60f372d fix: in pipeline not show the node config right 2025-09-03 18:21:51 +08:00
twwu c4f0691454 refactor(workflow): update fetchInspectVars calls to accept empty parameters 2025-09-03 18:15:14 +08:00
jyong 451948d49c Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-09-03 18:10:14 +08:00
jyong fd3b55cc16 fix preview and recommend plugins 2025-09-03 18:09:56 +08:00
QuantumGhost 0212f0de9f fix(api): fix workflow execution 2025-09-03 17:11:43 +08:00
twwu 9eb1c15906 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-09-03 16:51:57 +08:00
twwu 110211d966 refactor(uploader): replace YAML icon with pipeline icon and update label text 2025-09-03 16:51:49 +08:00
Joel 08d6fcfd52 fix: large data markdown ui problems 2025-09-03 16:48:41 +08:00
twwu d755b2885e refactor(workflow): enhance handleExportDSL function and clean up code structure 2025-09-03 16:22:59 +08:00
twwu b4c98daa8d refactor(workflow): update RAG tool suggestions and improve filtering logic 2025-09-03 16:05:55 +08:00
jyong 58e598dac8 Merge branch 'main' into feat/rag-2 2025-09-03 15:01:41 +08:00
jyong d4aed3df5c Merge branch 'feat/queue-based-graph-engine' into feat/rag-2
# Conflicts:
#	api/core/memory/token_buffer_memory.py
#	api/core/rag/extractor/notion_extractor.py
#	api/core/repositories/sqlalchemy_workflow_node_execution_repository.py
#	api/core/variables/variables.py
#	api/core/workflow/graph/graph.py
#	api/core/workflow/graph_engine/entities/event.py
#	api/services/dataset_service.py
#	web/app/components/app-sidebar/index.tsx
#	web/app/components/base/tag-management/selector.tsx
#	web/app/components/base/toast/index.tsx
#	web/app/components/datasets/create/website/index.tsx
#	web/app/components/datasets/create/website/jina-reader/base/options-wrap.tsx
#	web/app/components/workflow/header/version-history-button.tsx
#	web/app/components/workflow/hooks/use-inspect-vars-crud-common.ts
#	web/app/components/workflow/hooks/use-workflow-interactions.ts
#	web/app/components/workflow/panel/version-history-panel/index.tsx
#	web/service/base.ts
2025-09-03 15:01:06 +08:00
Joel c422d732d2 fix: tool bool input can choose file 2025-09-03 14:41:29 +08:00
Joel df0fe49fcc fix: one step run schema type file not support 2025-09-03 14:28:13 +08:00
zxhlyh 97875d2b55 plugin dependencies select all 2025-09-03 14:27:29 +08:00
-LAN- 8c97937cae Merge remote-tracking branch 'origin/main' into feat/queue-based-graph-engine 2025-09-03 13:53:43 +08:00
twwu 9a79d8941e Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-09-03 12:59:34 +08:00
twwu 9d3772f7d6 feat(workflow): add DisplayContent component for improved variable inspection and integrate schema type handling 2025-09-03 12:59:22 +08:00
QuantumGhost d2e341367e fix(api): fix relations of WorkflowNodeExecutionModel not preloaded
`WorkflowNodeExecutionModel.offload_data` should be preloaded to
provide info about the offloading information of execution record.

The `RagPipelineService.get_node_last_run` does not utilize
`DifyAPISQLAlchemyWorkflowNodeExecutionRepository` so the loading
logics is not changed.

In the commit we migrate to calling
`DifyAPISQLAlchemyWorkflowNodeExecutionRepository` to avoid such issue.
2025-09-03 12:30:20 +08:00
QuantumGhost e761f38d26 fix(api): adjust gevent patching 2025-09-03 12:29:39 +08:00
QuantumGhost e2ff7fac77 fix(api): fix variable truncation related field not returned. 2025-09-03 12:29:38 +08:00
jyong 617dc247f5 fix preview and recommend plugins 2025-09-03 12:15:03 +08:00
-LAN- f6acff4cce chore: remove unused variables
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-03 12:12:27 +08:00
-LAN- 3fa48cb5cf chore: remove ty-check from Python style check.
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-03 12:05:41 +08:00
-LAN- b81745aed8 Merge remote-tracking branch 'origin/main' into feat/queue-based-graph-engine 2025-09-03 11:56:05 +08:00
jyong e1b6da21f4 fix preview and recommend plugins 2025-09-03 11:35:41 +08:00
Joel b10d7d5b22 fix: datasource file can not be chosen 2025-09-03 11:31:53 +08:00
-LAN- 8c41d95d03 Merge remote-tracking branch 'origin/main' into feat/queue-based-graph-engine 2025-09-03 11:06:42 +08:00
Joel 885c7d26e5 feat: handle choose select 2025-09-03 11:05:15 +08:00
Novice 7896eeec5b fix: correct run history tracing sequence 2025-09-03 10:56:23 +08:00
Novice 38e24922e1 Merge branch 'feat/tool-rag-tag' into feat/rag-2 2025-09-03 10:27:02 +08:00
Novice d2787dc925 feat: tools add rag tag 2025-09-03 10:25:08 +08:00
twwu 706969d812 fix(workflow): enhance variable inspection by integrating schema type handling and refactoring logic 2025-09-03 10:17:38 +08:00
-LAN- 9d004a0971 test: fix test
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-03 02:11:37 +08:00
autofix-ci[bot]andGitHub 02fcd08c08 [autofix.ci] apply automated fixes 2025-09-02 17:34:07 +00:00
-LAN- 77a9a73d0d Merge remote-tracking branch 'origin/main' into feat/queue-based-graph-engine 2025-09-03 01:33:17 +08:00
jyong 7623dc14bb fix preview and recommend plugins 2025-09-02 20:12:45 +08:00
twwu 1ad46d0962 fix(pipeline): add handling for RAG pipeline variables in workflow state 2025-09-02 20:11:38 +08:00
twwu 5e854238b0 fix(workflow): improve formatting and add checkbox type to input variable type mapping 2025-09-02 19:57:18 +08:00
jyong 343f1a375f fix preview and recommend plugins 2025-09-02 19:41:29 +08:00
twwu fc4bc08796 feat(workflow): enhance RAG recommended plugins structure and update related components 2025-09-02 19:11:03 +08:00
Joel 60da4c9048 feat: set var inspect schema type 2025-09-02 18:44:49 +08:00
twwu 32a009654f feat(input-field): add isEditMode prop to InputFieldForm and update handling of variable changes 2025-09-02 18:19:40 +08:00
twwu 1522fd50df Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-09-02 17:25:54 +08:00
twwu 00b5772012 feat(portal): add customContainer prop to PortalToFollowElem for flexible rendering 2025-09-02 17:25:47 +08:00
jyong 8467494706 fix preview and recommend plugins 2025-09-02 17:02:25 +08:00
jyong a8cd1e2483 Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-09-02 16:44:33 +08:00
jyong 7ace7e65e1 fix preview and recommend plugins 2025-09-02 16:44:18 +08:00
twwu 273dae6738 fix(header): update boolean form type to checkbox and improve JSX formatting in form input component 2025-09-02 16:26:41 +08:00
-LAN- 1770b93e5b chore(graph_engine): Add a TODO commment in _update_response_outputs in event_handlers
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-02 15:20:03 +08:00
-LAN- d8ff4aa9ba feat(graph_engine): Handle NodeRunAgentLogEvent
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-02 15:02:07 +08:00
-LAN- 9f8f21bf87 chore: remove backup files
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-02 15:01:58 +08:00
jyong dfb967773b Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-09-02 11:56:13 +08:00
jyong 56fc9088dd add recommended rag plugin endpoint 2025-09-02 11:56:05 +08:00
-LAN- 0b0dc63f29 Merge remote-tracking branch 'origin/main' into feat/queue-based-graph-engine 2025-09-02 11:52:25 +08:00
twwu bf09c3eb10 feat(rag): integrate RAG recommended plugins into workflow component 2025-09-02 10:43:57 +08:00
twwu e5e52ab4b9 refactor(value-content): improve JSX formatting for readability in variable inspect component 2025-09-02 10:19:01 +08:00
jyong 826b9d5b21 add recommended rag plugin endpoint 2025-09-01 20:41:14 +08:00
jyong 633de2cb47 add recommended rag plugin endpoint 2025-09-01 20:12:27 +08:00
jyong d94e03c72b add recommended rag plugin endpoint 2025-09-01 19:38:28 +08:00
QuantumGhost 89ec13ec67 fix(api): fix ToolNode._extract_variable_selector_to_variable_mapping
The original selector syntax does not match our current implementation
for injecting user inputs into VariablePool.
2025-09-01 18:11:33 +08:00
jyong 1103130f81 add recommended rag plugin endpoint 2025-09-01 18:03:35 +08:00
jyong 493dae239f add recommended rag plugin endpoint 2025-09-01 17:08:37 +08:00
QuantumGhost eb7b21c7f1 Merge remote-tracking branch 'upstream/feat/rag-2' into feat/rag-2 2025-09-01 17:06:53 +08:00
QuantumGhost ad5a2c77c1 Merge remote-tracking branch 'upstream/feat/big-var-value-show-fe' into feat/rag-2 2025-09-01 17:06:23 +08:00
QuantumGhost acbf27eb65 chore(api): adjust migration order and date 2025-09-01 15:20:57 +08:00
QuantumGhost e2ae89e08d fix(tests): fix broken tests and linter issues 2025-09-01 14:55:35 +08:00
jyong 1676207776 add recommended rag plugin endpoint 2025-09-01 14:50:02 +08:00
jyong 8c780df8fd Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-09-01 14:46:08 +08:00
jyong 7920714f49 add recommended rag plugin endpoint 2025-09-01 14:45:56 +08:00
-LAN- 8433cf4437 refactor(graph_engine): Merge event_collector and event_emitter into event_manager
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-01 13:15:58 +08:00
-LAN- bb5d52539c refactor(graph_engine): Merge branch_handler into edge_processor
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-01 12:53:06 +08:00
-LAN- 88622f70fb refactor(graph_engine): Move setup methods into __init__
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-01 12:08:03 +08:00
twwu a41af6f322 refactor: update file upload and download handling for pipeline format 2025-09-01 11:13:11 +08:00
zxhlyh ce3eb0fcbb fix: rag pipeline template 2025-09-01 10:23:08 +08:00
-LAN- 0fdb1b2bc9 refactor(graph_engine): Correct private attributes and private methods naming
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-01 04:37:23 +08:00
-LAN- a5cb9d2b73 refactor(graph_engine): inline output_registry into response_coordinator
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-01 03:59:53 +08:00
-LAN- 64c1234724 refactor(graph_engine): Merge worker management into one WorkerPool
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-01 03:23:47 +08:00
-LAN- 202fdfcb81 refactor(graph_engine): Remove backward compatibility code
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-01 02:41:16 +08:00
-LAN- e2f4c9ba8d refactor(graph_engine): Merge state managers into unified_state_manager
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-09-01 02:08:08 +08:00
-LAN- 546d75d84d Merge remote-tracking branch 'origin/main' into feat/queue-based-graph-engine 2025-09-01 00:29:28 +08:00
QuantumGhost 63c035d8a2 chore(api): migrate import for db 2025-08-31 16:46:25 +08:00
QuantumGhost e9e7d4f3cd Merge branch 'feat/rag-2' into feat/workflow-draft-var-optimize 2025-08-31 15:17:23 +08:00
QuantumGhost c72d847ac7 feat(api): support array[boolean] truncation 2025-08-31 14:32:53 +08:00
QuantumGhost 982fd9170c WIP: test(api): tests for truncation logic 2025-08-31 13:45:16 +08:00
QuantumGhost 91fac9b720 WIP: feat(api): draft var cleanup task 2025-08-31 13:45:16 +08:00
QuantumGhost a527bd42b5 chore(api): optimize file url signing 2025-08-31 13:45:16 +08:00
QuantumGhost 621b75b343 feat(api): implement truncation for SSE events 2025-08-31 13:45:15 +08:00
QuantumGhost 6b9d2e98b9 feat(api): Implement truncation for WorkflowNodeExecution 2025-08-31 13:44:39 +08:00
QuantumGhost 2fd337e610 feat(api): add WorkflowNodeExecutionOffload model 2025-08-31 13:44:39 +08:00
QuantumGhost a7aa17e361 chore(api): remove orphan files in draft var cleanup script 2025-08-31 13:44:38 +08:00
QuantumGhost 13eb9f7d7d feat(api): implement truncation for draft var 2025-08-31 13:44:38 +08:00
QuantumGhost d7db58cabd feat(api): implement VariableTruncator 2025-08-31 13:44:38 +08:00
QuantumGhost 0cf8a80bdd chore(api): Introduce variable truncation configuration 2025-08-31 13:44:38 +08:00
QuantumGhost a10586c8ea fixup! feat(api): Add migration for WorkflowDraftVariableFile 2025-08-31 13:44:38 +08:00
QuantumGhost 40faa9ce16 refactor(api): Inject db dependency to FileService 2025-08-31 13:44:38 +08:00
QuantumGhost 58dfae60f0 feat(api): Add migration for WorkflowDraftVariableFile 2025-08-31 13:44:38 +08:00
QuantumGhost de08b2310c feat(api): Introduce WorkflowDraftVariableFile model
This model is used to track offloaded variables values for
`WorkflowDraftVariable`.
2025-08-31 13:44:38 +08:00
QuantumGhost e9c6038192 docs(api): update docs for UploadFile 2025-08-31 13:44:38 +08:00
-LAN- a8fe4ea802 Merge remote-tracking branch 'origin/main' into feat/queue-based-graph-engine 2025-08-30 16:36:10 +08:00
-LAN- 82193580de chore: improve typing
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-08-30 16:35:57 +08:00
-LAN- 1fd27cf3ad Merge remote-tracking branch 'origin/main' into feat/queue-based-graph-engine 2025-08-30 00:13:45 +08:00
twwu 1e9bfd8872 feat(chunk-card-list): implement ChunkCard and QAItem components, refactor ChunkCardList to utilize new structure and types 2025-08-29 23:28:43 +08:00
-LAN- 11d32ca87d test: fix web test
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-08-29 23:20:28 +08:00
-LAN- 5415d0c6d1 Merge remote-tracking branch 'origin/main' into feat/queue-based-graph-engine 2025-08-29 23:17:30 +08:00
-LAN- d8af8ae4e6 fix: update workflow service tests for new graph engine
- Update method calls from _handle_node_run_result to _handle_single_step_result
- Add required fields (id, node_id, node_type, start_at) to graph events
- Use proper NodeType enum values instead of strings
- Fix imports to use correct modules (Node instead of BaseNode)
- Ensure event generators return proper generator objects

These tests were failing because the internal implementation changed
with the new graph engine architecture.
2025-08-29 23:04:33 +08:00
-LAN- 04e5d4692f Merge remote-tracking branch 'origin/main' into feat/queue-based-graph-engine 2025-08-29 22:34:47 +08:00
-LAN- 3aa48efd0a test(test_workflow_service): Use new engine's method.
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-08-29 22:06:10 +08:00
jyong c2afb84884 fix chunk format 2025-08-29 17:10:18 +08:00
-LAN- 8eb78c04b2 chore(token_buffer_memory): code format
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-08-29 17:02:51 +08:00
-LAN- 22ee318cf8 Merge remote-tracking branch 'origin/main' into feat/queue-based-graph-engine 2025-08-29 17:01:42 +08:00
jyong 3c0adfb48a fix chunk format 2025-08-29 16:27:22 +08:00
twwu b3dbf9fe94 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-08-29 16:20:54 +08:00
twwu a597ae1a8a feat(block-selector): add RAG tool suggestions component and integrate with existing tools 2025-08-29 16:20:43 +08:00
-LAN- f2bc4f5d87 fix: resolve type error in node_factory by using type guard for node_type_str 2025-08-29 16:16:58 +08:00
-LAN- d7d456349d Merge remote-tracking branch 'origin/main' into feat/queue-based-graph-engine 2025-08-29 16:14:04 +08:00
jyong 65215135e5 Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-08-29 14:49:05 +08:00
jyong 5cf795f2b8 fix preview run 2025-08-29 14:48:51 +08:00
twwu 1c8190f142 feat(search-box): enhance marketplace search box with new triggers and conditional rendering 2025-08-29 14:45:04 +08:00
-LAN- dce4d0ff80 Merge remote-tracking branch 'origin/main' into feat/queue-based-graph-engine 2025-08-29 13:22:13 +08:00
-LAN- 3dee8064ba feat: enhance typing 2025-08-29 13:17:02 +08:00
jyong d0dd728e6c Merge branch 'main' into feat/rag-2
# Conflicts:
#	api/core/app/entities/queue_entities.py
#	api/core/workflow/graph_engine/entities/event.py
2025-08-29 11:29:51 +08:00
jyong 0bb3407385 fix preview run 2025-08-29 11:25:08 +08:00
kurokoboandGitHub 05c21883f9 fix(pipeline): make kb node deletable (#24731) 2025-08-29 09:19:09 +08:00
jyong 5b4335c4b5 fix preview run 2025-08-28 22:02:22 +08:00
jyong 39080eed10 fix preview run 2025-08-28 22:01:49 +08:00
jyong 1db04aa729 Merge branch 'feat/queue-based-graph-engine' into feat/rag-2 2025-08-28 18:12:49 +08:00
jyong 64772fb413 fix preview run 2025-08-28 18:12:27 +08:00
twwu 1022e67fb6 fix: adjust padding in search box component for improved layout 2025-08-28 18:02:19 +08:00
twwu a67589d5db feat: add title property to DataSourceDefaultValue type in block-selector 2025-08-28 17:25:26 +08:00
-LAN- bfbb36756a feat(graph_engine): Add NodeExecutionType.ROOT and auto mark skipped in Graph.init
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-08-28 16:41:51 +08:00
twwu 9448d49305 feat: add 'rag' tag to plugin constants and translations in multiple languages 2025-08-28 16:21:53 +08:00
twwu 169a8edc28 refactor: update import statement style in IfElseNode component 2025-08-28 15:47:39 +08:00
-LAN- d7e0c5f759 chore: use 'XXX | None' instead of Optional[XXX] in graph.py 2025-08-28 15:45:22 +08:00
twwu 9c93a49605 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-08-28 15:40:11 +08:00
twwu f6ed1c5643 fix: update chunk structure tip messages in English and Chinese translations for clarity 2025-08-28 15:40:02 +08:00
jyong 334bc8f1a2 Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-08-28 15:39:36 +08:00
jyong a9f7ee029e fix preview run 2025-08-28 15:39:22 +08:00
-LAN- c396788128 chore(graph_engine): add final mark to classes
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-08-28 15:38:35 +08:00
twwu edd41a30eb feat: add AddChunks icon and related components for knowledge base chunk structure 2025-08-28 15:31:30 +08:00
Joel 580201ed2c merge main 2025-08-28 14:57:30 +08:00
Joel e955a603c6 fix: can choose file in add in variable aggregator 2025-08-28 14:19:07 +08:00
Joel 740f1c5f2c fix: tools value not update caused data outdated 2025-08-28 14:06:28 +08:00
twwu 9a13cb5bdf refactor: remove unused state management in usePipelineRun hook 2025-08-28 13:58:03 +08:00
twwu 048feb4165 refactor: update local file and online drive state management in create-from-pipeline components 2025-08-28 13:47:20 +08:00
twwu 843b14ccc6 refactor: Refactor online drive breadcrumbs navigation 2025-08-28 10:56:51 +08:00
-LAN- e3a7b1f691 fix: type hints
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-08-28 05:24:18 +08:00
-LAN- 8aab7f49c3 chore(graph_engine): Use XXX | None instead of Optional[XXX] 2025-08-28 05:09:33 +08:00
autofix-ci[bot]andGitHub 1e12c1cbf2 [autofix.ci] apply automated fixes 2025-08-27 21:00:36 +00:00
-LAN- affedd6ce4 chore(graph_engine): Use XXX | None instead of Optional[XXX] 2025-08-28 04:59:49 +08:00
-LAN- ef21097774 refactor(graph_engine): Remove unnecessary check from SkipPropagator
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-08-28 04:45:26 +08:00
-LAN- 1d377fe994 refactor(graph_engine): Use _ to mark unused variable in BranchHandler
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-08-28 04:44:45 +08:00
-LAN- c82697f267 refactor(graph_engine): Remove node_id from SkipPropagator.skip_branch_paths
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-08-28 04:43:56 +08:00
-LAN- 98b25c0bbc refactor(graph_engine): Convert attrs to private in error_handler
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-08-28 04:42:37 +08:00
-LAN- 1cd0792606 chore(graph_events): Improve type hints
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-08-28 04:41:48 +08:00
-LAN- 7cbf4093f4 chore(graph_engine): Use TYPE | None instead of Optional
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-08-28 04:30:50 +08:00
-LAN- 8129ca7c05 chore(graph_engine): Move error_strategy.py to protocols/
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-08-28 04:29:32 +08:00
-LAN- 65617f000d feat(event_collector): Update to use ReadWriteLock 2025-08-28 03:26:42 +08:00
-LAN- 635eff2e25 test(graph_engine): remove outdated tests
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-08-28 02:53:19 +08:00
-LAN- 55085a9ca2 chore(graph_engine): add type hint for event_queue
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-08-28 02:38:56 +08:00
-LAN- 9dc1e9724e Merge remote-tracking branch 'origin/main' into feat/queue-based-graph-engine 2025-08-28 02:26:40 +08:00
jyong 4403a26f37 merge new graph engine 2025-08-27 20:44:14 +08:00
jyong 88abaa840c merge new graph engine 2025-08-27 18:33:38 +08:00
Joel 4e2c3bfb05 fix: not obj type struct schema render error 2025-08-27 18:32:04 +08:00
Joel a644153e9f feat: just use chunk type in knowledge base 2025-08-27 18:16:46 +08:00
twwu 0316eb6064 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-08-27 18:09:55 +08:00
twwu 6a56649be2 feat(web): add support for Tool block type in BlockIcon component 2025-08-27 18:09:48 +08:00
Joel 8a585607c1 fix: tool schem not right 2025-08-27 18:07:33 +08:00
-LAN- c3f66e2901 Merge remote-tracking branch 'origin/main' into feat/queue-based-graph-engine 2025-08-27 18:05:35 +08:00
jyong 90d72f5ddf merge new graph engine 2025-08-27 17:46:46 +08:00
jyong 6c8212d509 Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-08-27 17:46:05 +08:00
Joel 19d3ba42e5 chore: schema type change 2025-08-27 17:40:05 +08:00
twwu ee144452e2 Merge branch 'main' into feat/rag-2 2025-08-27 17:28:21 +08:00
twwu 367b2d0320 refactor(web): streamline data source before run form and enhance run handling logic 2025-08-27 16:56:33 +08:00
Joel bd294ffe0d feat: file schem file replace 2025-08-27 16:07:31 +08:00
jyong 392514fa13 Merge branch 'feat/queue-based-graph-engine' into feat/rag-2
# Conflicts:
#	api/commands.py
#	api/core/app/apps/common/workflow_response_converter.py
#	api/core/llm_generator/llm_generator.py
#	api/core/plugin/entities/plugin.py
#	api/core/plugin/impl/tool.py
#	api/core/rag/index_processor/index_processor_base.py
#	api/core/workflow/entities/workflow_execution.py
#	api/core/workflow/entities/workflow_node_execution.py
#	api/core/workflow/enums.py
#	api/core/workflow/graph_engine/entities/graph.py
#	api/core/workflow/graph_engine/graph_engine.py
#	api/core/workflow/nodes/enums.py
#	api/services/dataset_service.py
2025-08-27 16:05:59 +08:00
autofix-ci[bot]andGitHub 86e7cb713c [autofix.ci] apply automated fixes 2025-08-27 07:38:26 +00:00
-LAN- 0f29244459 fix: test
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-08-27 15:37:37 +08:00
autofix-ci[bot]and-LAN- 48cbf4c78f [autofix.ci] apply automated fixes 2025-08-27 15:33:30 +08:00
-LAN- 8c35663220 feat: queue-based graph engine
Signed-off-by: -LAN- <laipz8200@outlook.com>
2025-08-27 15:33:28 +08:00
Joel 4cb286c765 feat: handle file schem show 2025-08-27 14:46:44 +08:00
zxhlyh ff33d42c55 rag pipeline initial template 2025-08-27 14:39:39 +08:00
twwu e1a2755e3b fix(web): add spinning animation to loader icon in variable inspect trigger for better UX 2025-08-27 13:55:43 +08:00
twwu b1f348fb31 refactor(web): reorganize imports in document index component for improved clarity 2025-08-27 13:48:04 +08:00
twwu 5f0bae0ae5 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-08-27 13:46:10 +08:00
twwu 57c242fff3 Update dataset pipeline header text and translations for improved clarity 2025-08-27 13:46:03 +08:00
kurokoboandGitHub 1814b99c79 fix(web): correct title color in option card in dark mode (#24579) 2025-08-27 11:27:25 +08:00
Joel f24f573731 feat: show struct schema in output 2025-08-27 11:18:22 +08:00
twwu da48e54778 Merge branch 'main' into feat/rag-2 2025-08-27 11:16:27 +08:00
Joel 2db699522c feat: compare schema type 2025-08-27 10:48:38 +08:00
jyong 5c15fe7b01 fix pipeline export 2025-08-26 18:52:24 +08:00
jyong da9b38f642 pipeline name 2025-08-26 18:26:25 +08:00
jyong 918958743f Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-08-26 17:18:49 +08:00
jyong 51c3f1b2e2 add pipeline async run 2025-08-26 17:18:43 +08:00
twwu bdcd9ad9cb refactor(workflow): update output schema handling in tool and data source nodes for improved integration with plugin info 2025-08-26 16:48:18 +08:00
Harry 1f5fd13359 refactor(plugin_migration): improve code readability by formatting the install function signature 2025-08-26 16:03:59 +08:00
Harry 61f2f8fd31 refactor(schemas): update titles in JSON schemas for consistency and clarity 2025-08-26 16:03:59 +08:00
jyong 60fb242f27 Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-08-26 15:52:01 +08:00
jyong 85f0d31fab add pipeline async run 2025-08-26 15:51:49 +08:00
Harry a282b6cea4 refactor(tests): remove unused TestPerformance class from schema resolver tests 2025-08-26 15:47:34 +08:00
Harry 46019ea927 refactor(resolver): enhance schema reference resolution with improved error handling and caching 2025-08-26 15:47:34 +08:00
Harry 7e20273bce refactor(resolver): implement BFS approach for resolving references in Dify schemas 2025-08-26 15:47:34 +08:00
jyong 1d2d0ff49f add pipeline async run 2025-08-26 15:32:39 +08:00
jyong c77bdd1fb3 add pipeline async run 2025-08-26 15:20:40 +08:00
Harry 0f3ca1d8f4 fix: ruff 2025-08-26 12:51:40 +08:00
Harry d1be9544fb fix: restful to restx 2025-08-26 12:51:40 +08:00
jyong 1692a7bd1b Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-08-26 12:06:43 +08:00
jyong c3c4ef3a8e add pipeline async run 2025-08-26 12:06:34 +08:00
Harry c911ac8c01 refactor(console): add spec controller import and enhance tool output schema resolution 2025-08-26 11:07:12 +08:00
twwu 1bc77204b1 fix(use-initial): handle potential undefined nodeData by providing a fallback object 2025-08-26 10:23:13 +08:00
jyong 1ad7b0e852 add pipeline async run 2025-08-25 18:26:05 +08:00
twwu e0e3224413 refactor(option-card): enhance styling and accessibility by updating class names and adding title attribute 2025-08-25 17:46:27 +08:00
jyong f418164648 add pipeline async run 2025-08-25 17:33:49 +08:00
jyong 4fc498bd48 fix 2025-08-25 16:55:08 +08:00
twwu 14d8788dac refactor: remove unused DataSourceType import and simplify iconType handling in DatasetDetailLayout 2025-08-25 16:43:52 +08:00
jyong 101d6504fb fix 2025-08-25 16:14:22 +08:00
twwu d440577913 refactor(operations): remove document download functionality and associated UI elements 2025-08-25 15:32:48 +08:00
twwu 85fd97e090 Merge branch 'main' into feat/rag-2 2025-08-25 15:30:18 +08:00
twwu 412e4b04f3 fix(use-settings-display): correct translation key for keyword search in settings display 2025-08-25 15:20:59 +08:00
jyong cc1f0d4d8d fix 2025-08-25 13:55:42 +08:00
Joel 1b9c817dba feat: add process data truncate 2025-08-25 11:26:57 +08:00
zxhlyh b7ed2cade1 initial template 2025-08-22 18:12:24 +08:00
twwu 8c44151e6f Merge branch 'main' into feat/rag-2 2025-08-22 17:40:34 +08:00
twwu 570b644a7e refactor(header, option-card): improve layout and responsiveness by adjusting flex properties and adding title attributes 2025-08-22 16:49:28 +08:00
twwu 5824a2d71c refactor(use-tool-icon): make data parameter optional and update usage in variable inspect components 2025-08-22 16:02:14 +08:00
twwu 83cc3b4710 refactor(credential-selector): enhance layout with overflow handling for better UI responsiveness 2025-08-22 14:49:24 +08:00
Joel 0ca7c29c47 feat: preiew show the large data 2025-08-22 11:35:54 +08:00
jyong 2f6c51927e Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-08-22 11:34:13 +08:00
jyong 6b7ea9885c support name generate 2025-08-22 11:34:01 +08:00
Joel 68ba41e57e chore: fix trunate change proplem 2025-08-22 11:08:54 +08:00
twwu 8ff4f34773 refactor(create-pipeline): remove unused CreateForm and CreateModal components, streamline dataset creation process 2025-08-22 10:49:23 +08:00
jyong 4545f509a5 support name generate 2025-08-21 19:15:16 +08:00
twwu af74019d6e refactor(knowledge-base): update title from 'Question-Answer' to 'Q&A' for improved clarity 2025-08-21 18:13:44 +08:00
twwu d3b6631df8 refactor(retrieval-method): replace all instances of invertedIndex with keyword_search in components and translations 2025-08-21 17:31:25 +08:00
twwu 5699adf69c refactor(result-preview): update chunk handling to use GeneralChunkPreview type and extract content 2025-08-21 17:07:20 +08:00
twwu 42935997aa refactor(retrieval-method): update retrieval method from invertedIndex to keywordSearch across components 2025-08-21 16:29:23 +08:00
Joel f82f06bdd0 feat: support filter file vars 2025-08-21 16:11:32 +08:00
zxhlyh c5ee6e09d4 fix: output schema file type 2025-08-21 15:12:53 +08:00
twwu 60fafc524c feat(data-source): add LOCAL_FILE_OUTPUT to constants and integrate into panel for local file handling 2025-08-21 14:17:25 +08:00
twwu cecef01bf7 feat(rag-pipeline): enhance result preview with chunk formatting and add configuration for preview chunk limit 2025-08-21 11:04:33 +08:00
twwu dfd33b3d84 Merge branch 'main' into feat/rag-2 2025-08-21 09:43:51 +08:00
twwu 3e27e97364 feat(publish): improve success and error notifications for knowledge pipeline publishing with localized messages and enhanced user guidance 2025-08-20 18:41:09 +08:00
twwu 9d3198f808 refactor(data-source, before-run-form): enhance data handling and user interface for data source selection, integrating new components and improving state management 2025-08-20 18:21:59 +08:00
twwu 449755ada4 refactor(test-run, preparation): restructure test run components, enhance data handling, and improve user experience with new loading states and error handling 2025-08-20 16:40:56 +08:00
twwu 8ab3f1212b refactor(billing, chunk-preview): update link target and improve file property handling in document preview 2025-08-20 10:23:33 +08:00
twwu be045a68ee refactor(credential-icon, create-from-pipeline, test-run): improve component structure and enhance data handling for online drive files 2025-08-19 15:24:14 +08:00
Joel d4370a8ca5 chore: alert ui 2025-08-19 15:07:53 +08:00
twwu 95f60d89ab refactor(datasets): reorganize document components and enhance operations with download functionality 2025-08-19 15:07:52 +08:00
twwu a1666fe058 Merge branch 'main' into feat/rag-2 2025-08-19 14:59:06 +08:00
twwu ed4bd56146 refactor(create-card, template-card): add TODO comments for direct pipeline dataset creation and improve code organization 2025-08-19 14:41:32 +08:00
Joel 64897bc6fe chore: hide mock data 2025-08-19 14:21:53 +08:00
Joel 559d014b29 chore: use api return truncate 2025-08-19 14:18:41 +08:00
twwu ad523ef4ad feat(publish): enhance success notification for pipeline template publishing with additional information and links 2025-08-19 14:15:49 +08:00
Joel 3c4b374038 feat: run result data too long export 2025-08-19 14:04:00 +08:00
twwu d9cdce3f7a fix(i18n): refine Simplified Chinese translations for dataset and pipeline terminology 2025-08-19 13:10:51 +08:00
twwu 865e3ee85b fix(billing): adjust padding and margin for pricing plan item components 2025-08-19 10:43:49 +08:00
twwu 07887fb24f fix(i18n): update Simplified Chinese translations for "知识管道" to "知识流水线" 2025-08-19 10:24:52 +08:00
Harry fcdbe3b84a fix: plugin service import 2025-08-19 10:06:27 +08:00
twwu 38c51b1011 fix(i18n): highlight "プレミアム" in Japanese billing translations 2025-08-18 21:04:57 +08:00
twwu 469ed5a311 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-08-18 21:00:13 +08:00
twwu 56273a2dcf fix(i18n): update Japanese and Simplified Chinese translations for billing terms 2025-08-18 20:59:49 +08:00
Harry 6ce013ac52 fix: OAuth client parameter retrieval by verifying plugin status 2025-08-18 20:41:22 +08:00
twwu fb6fe4a32b fix(billing): adjust z-index for noise effects in pricing plans and self-hosted plan items 2025-08-18 20:40:45 +08:00
yessenia ae183b348c feat: variable preview 2025-08-18 18:16:48 +08:00
Joel b4e76af4a7 feat: string type too long hide 2025-08-18 18:15:10 +08:00
twwu 4a5c883988 feat(pipeline): implement footer component for dataset creation and enhance UI with new styles 2025-08-18 16:58:43 +08:00
Joel 2391e582f2 feat: debug show big data 2025-08-18 16:57:41 +08:00
twwu cd760633cb feat(billing): add noise effects to pricing plans and update rendering logic 2025-08-18 14:31:09 +08:00
twwu ece1330567 feat(billing): add Enterprise plan component and update plan rendering logic 2025-08-18 11:25:48 +08:00
twwu 386614951f Merge branch 'main' into feat/rag-2 2025-08-18 11:16:18 +08:00
twwu a2892773f2 fix: dark mode color 2025-08-17 15:25:10 +08:00
twwu e80645bfa1 feat: enhance billing plan components with new SVG assets and update styles for premium and enterprise plans 2025-08-15 22:17:32 +08:00
twwu c7d5ec1520 feat: add new pricing assets and update billing plan components to utilize them 2025-08-15 18:39:59 +08:00
twwu 8cf98ba0ce feat: add knowledge pipeline publishing feature and update billing context; refactor popup component for conditional rendering 2025-08-15 18:06:15 +08:00
twwu fb10706c20 feat: refactor billing plans components to improve structure and add self-hosted plan item button; update pricing layout and translations 2025-08-15 16:29:45 +08:00
jyong fb7dc4e0e1 fix file 2025-08-15 14:55:37 +08:00
twwu d558f98aa6 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-08-15 14:17:46 +08:00
twwu 89c7f71199 feat: add Footer component and integrate it into Pricing layout; refactor Header styles and update Plans component structure 2025-08-15 14:16:35 +08:00
autofix-ci[bot]andGitHub ff76adc88a [autofix.ci] apply automated fixes 2025-08-15 04:17:51 +00:00
Yunlu Wen cfc555d05d feat: add knowledge pipeline creation feature 2025-08-15 12:15:37 +08:00
twwu 153d5e8f03 refactor: Change plan-item directory 2025-08-15 11:14:38 +08:00
twwu ac456c1a95 feat: refactor billing plans components and add new PlanItem structure with tooltip support 2025-08-15 11:08:36 +08:00
jyong 8e88765261 fix file 2025-08-14 18:17:44 +08:00
jyong 5a2618d002 fix file 2025-08-14 18:07:52 +08:00
jyong 69a821db02 fix file 2025-08-14 18:01:29 +08:00
twwu 46224724a2 feat: add Cloud and SelfHosted components with updated PlanSwitcher integration 2025-08-14 15:54:07 +08:00
twwu 8a5bcd11f2 fix: add missing newline at end of JSON files for icon components 2025-08-14 15:21:53 +08:00
jyong a8fbf123e4 Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-08-14 15:12:29 +08:00
jyong 8b8d257f78 fix file 2025-08-14 15:12:09 +08:00
twwu 02720c9b95 Merge branch 'main' into feat/rag-2 2025-08-14 15:03:48 +08:00
twwu d8a9645e83 feat: Implement billing plan selection UI with plan switcher and range options 2025-08-14 15:01:38 +08:00
jyong 72ea3b4d01 fix variable_pool 2025-08-13 17:38:14 +08:00
jyong 3797416fe0 fix online drive 2025-08-13 15:45:33 +08:00
jyong f74706a4a5 fix online drive 2025-08-13 15:28:18 +08:00
twwu 463ca7043d fix: sync doc styling change 2025-08-13 15:13:03 +08:00
twwu 5a6818c817 Merge branch 'main' into feat/rag-2 2025-08-13 15:05:57 +08:00
twwu acde411629 fix: Update breadcrumb styles in Online Drive component for improved visual consistency 2025-08-13 14:28:55 +08:00
twwu 4d34891ac0 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-08-13 11:34:27 +08:00
twwu cf46fba753 feat: Enhance Online Drive component with bucket handling and breadcrumb navigation 2025-08-13 11:34:22 +08:00
jyong fcdbfbda4f add credential id 2025-08-12 17:56:28 +08:00
twwu 71d8a0c0b6 refactor: Refactor FileIcon component to use useMemo for file type determination and rename loading state variable for clarity 2025-08-12 16:55:00 +08:00
jyong ae3addb922 add credential id 2025-08-12 15:43:11 +08:00
jyong bd1d7f8652 add credential id 2025-08-12 15:38:26 +08:00
jyong a0006ce968 add credential id 2025-08-12 14:45:45 +08:00
jyong 2b7243dbc7 add credential id 2025-08-12 11:13:47 +08:00
jyong 22b3933cc3 Merge branch 'main' into feat/rag-2
# Conflicts:
#	api/core/workflow/entities/variable_pool.py
2025-08-12 11:13:04 +08:00
jyong 1bc506603a add credential id 2025-08-12 11:10:21 +08:00
zxhlyh 54b935f609 fix 2025-08-12 10:49:49 +08:00
Harry cf4a526e7f refactor: replace db.session with session in DatasourceProviderService for consistency 2025-08-11 20:35:46 +08:00
Harry 543f80ad5d refactor: replace get_real_credential_by_id with get_datasource_credentials in multiple services for consistency 2025-08-11 20:04:04 +08:00
twwu 7f328328fb Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-08-11 18:37:22 +08:00
twwu 9893b8110d refactor: rename selectedFileKeys to selectedFileIds and update related logic in online drive components 2025-08-11 18:37:15 +08:00
jyong 087a4fbd14 add credential id 2025-08-11 18:26:41 +08:00
Harry ada0875ac4 fix: update default value for expires_at in DatasourceProvider model 2025-08-11 11:40:51 +08:00
Harry 6b07e0e8d6 feat: add expiration for OAuth credentials in datasource provider 2025-08-11 11:25:50 +08:00
twwu fc779d00df Merge branch 'main' into feat/rag-2 2025-08-11 11:15:58 +08:00
zxhlyh 58aca75ee0 fix: json schema 2025-08-08 17:38:01 +08:00
zxhlyh 8464ec46e6 fix: json schema 2025-08-08 17:38:01 +08:00
twwu ac7953a32c feat: add credential_id handling in CreateFormPipeline and OnlineDrive components 2025-08-08 14:48:58 +08:00
twwu b21d991fdb feat(rag): pass credentialId to online document preview and wire to data source store 2025-08-08 14:26:38 +08:00
jyong df5a4e5c08 Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-08-08 14:18:45 +08:00
jyong d07ce809be add credential id 2025-08-08 14:18:30 +08:00
twwu ec3cb126a0 feat: add clear data functions for online documents, website crawl, and online drive; integrate credential change handling 2025-08-08 13:49:08 +08:00
twwu 184c3c88b7 refactor: Refactor online document and online drive components to handle credential changes 2025-08-08 13:43:01 +08:00
zxhlyh 097a6fc1e0 fix: variable 2025-08-07 17:22:29 +08:00
zxhlyh d5f82d0d5f fix: json schema 2025-08-07 16:36:59 +08:00
twwu 1b3860d012 Merge branch 'main' into feat/rag-2 2025-08-07 16:27:20 +08:00
twwu 5729d38776 feat: add CredentialIcon component and integrate it into credential selector for improved avatar display 2025-08-07 15:34:15 +08:00
zxhlyh 9e882122ca fix: json schema 2025-08-07 15:28:42 +08:00
jyong e6f1bc165c add tool file preview 2025-08-07 14:35:04 +08:00
jyong 842ced218e Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-08-07 11:13:10 +08:00
jyong ca8f80ee33 notion fix 2025-08-07 11:13:02 +08:00
twwu 646b798e9c Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-08-07 10:10:32 +08:00
twwu e0753359f8 fix: adjust Toast component positioning to top-right corner 2025-08-07 10:10:27 +08:00
Harry 1d79c21ae3 feat: implement structured output wrapping for pipeline items 2025-08-06 17:41:07 +08:00
twwu 5b433aa2d1 feat: add useFloatingRight hook and integrate it into InputFieldEditorPanel and PreviewPanel for dynamic positioning 2025-08-06 16:59:22 +08:00
jyong 218e778099 Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-08-06 15:39:27 +08:00
jyong 1567b615dc notion fix 2025-08-06 15:39:22 +08:00
Harry 29da2e5c19 feat: enhance output schema descriptions and remove unused constants 2025-08-06 15:12:57 +08:00
Harry facbe02cf7 feat: datasource output schema 2025-08-06 15:12:57 +08:00
Harry 2a1e1a8042 feat: datasource output schema 2025-08-06 15:12:57 +08:00
jyong 13f38045d4 Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-08-06 15:11:45 +08:00
jyong 94a0fb6dc1 notion fix 2025-08-06 15:11:37 +08:00
twwu c5a3bf9b9e refactor: simplify Markdown rendering in ChunkContent component 2025-08-06 14:32:28 +08:00
twwu 95982d37a6 refactor: remove unused DataSourceOauthBinding import from dataset_service and document_indexing_sync_task 2025-08-06 14:25:39 +08:00
twwu 40f3524cfe Merge branch 'main' into feat/rag-2 2025-08-06 14:23:51 +08:00
twwu da68cf48c4 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-08-06 11:40:35 +08:00
twwu 8717a789b3 feat: dynamically import panel components to improve performance 2025-08-06 11:40:30 +08:00
jyong 05e96e56e5 notion fix 2025-08-06 11:13:20 +08:00
twwu 6954926df9 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-08-06 10:33:50 +08:00
twwu ec6fabb222 feat: introduce useInputFieldPanel hook to manage input field panel state and refactor related components 2025-08-06 10:32:57 +08:00
zxhlyh 6cae1a2872 fix: rag variable 2025-08-05 18:26:07 +08:00
jyong 2f163bad8f transform document 2025-08-05 18:16:24 +08:00
zxhlyh 6faa4b107b fix: rag variable 2025-08-05 16:31:14 +08:00
twwu 8ab5c47737 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-08-05 14:20:41 +08:00
twwu 0a397ac477 feat: Refactor document context and update chunking mode handling across components 2025-08-05 14:19:28 +08:00
zxhlyh 09b5cacbad fix: rag variable 2025-08-05 13:02:51 +08:00
zxhlyh 522210bad6 fix: rag variable 2025-08-05 11:39:17 +08:00
zxhlyh 0975f5bdc2 merge main 2025-08-05 10:31:12 +08:00
zxhlyh 201e4cd64d merge main 2025-08-05 10:30:53 +08:00
twwu 1e5317d3f0 feat: Enhance InputFieldPanel to manage preview and edit states more effectively 2025-08-01 16:35:27 +08:00
twwu 44d569a7c1 feat: Implement input field management panel 2025-08-01 16:27:53 +08:00
twwu ec501cf664 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-08-01 14:43:00 +08:00
twwu cd9bfe0df3 feat: Update website crawl provider to use jinaReader and synchronize selection changes 2025-08-01 14:42:54 +08:00
jyong d36501203f Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-08-01 14:11:18 +08:00
jyong f3f3a99e5b transform document 2025-08-01 14:11:11 +08:00
twwu 19a93c6554 feat: Enhance Notion integration by adding credential_id to NotionInfo and updating related functions 2025-08-01 14:04:01 +08:00
jyong 383ee368e6 Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-08-01 13:59:19 +08:00
jyong 79f30daf03 transform document 2025-08-01 13:59:11 +08:00
twwu e7e531dc06 feat: Refactor WebsiteCrawl component to improve header configuration and remove unused memoization 2025-08-01 11:50:50 +08:00
zxhlyh d8ac78056e fix: open input field modal from var picker 2025-08-01 11:28:30 +08:00
twwu f75a3ef212 feat: Enhance InputFieldDialog and PreviewPanel with improved styling for better layout 2025-07-31 20:24:18 +08:00
twwu c9ab0fb8f6 feat: Update InputFieldDialog styling to allow for flexible growth 2025-07-31 20:18:20 +08:00
twwu 2dc71f059c feat: Update FooterTip component and enhance InputFieldDialog layout 2025-07-31 18:38:04 +08:00
twwu 18af3dfe5d Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-07-31 16:29:00 +08:00
twwu 0b871abe59 feat: Add credential handling to Notion page selector and related components 2025-07-31 16:28:53 +08:00
jyong 82819af55c transform document 2025-07-31 15:59:30 +08:00
jyong 9915364740 Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-07-31 15:21:18 +08:00
jyong 97136ca8f0 transform document 2025-07-31 15:21:06 +08:00
twwu 195bf6621a Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-07-31 15:19:11 +08:00
twwu 8711a57d92 feat: Enhance NotionPageSelector and NotionPageSelectorModal with loading states and credential handling 2025-07-31 15:19:03 +08:00
jyong 8e96b9ed77 transform document 2025-07-31 11:51:40 +08:00
Joel 5a21da00c5 chore: knowledge base single run 2025-07-31 11:20:46 +08:00
jyong a7a4c8228e Merge branch 'main' into feat/rag-2
# Conflicts:
#	web/app/components/workflow/hooks/use-workflow.ts
2025-07-31 10:30:28 +08:00
twwu 1b6a925b34 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-07-30 17:42:10 +08:00
twwu 41363459b5 feat: Update Header component button styling and remove redundant onClick from icon 2025-07-30 17:41:55 +08:00
Harry deceaa38f0 feat: datasource oauth default credentials 2025-07-30 16:36:27 +08:00
Harry f7ec255b3e feat: oauth 2025-07-30 15:55:16 +08:00
Harry 4dab128900 feat: oauth 2025-07-30 15:52:59 +08:00
zxhlyh 76b4288b34 datasource change authed page 2025-07-30 15:23:04 +08:00
twwu a1c38a2740 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-07-30 15:19:16 +08:00
twwu f8d7d07c13 feat: Introduce CredentialSelector component and remove WorkspaceSelector 2025-07-30 15:19:10 +08:00
Joel 69738794bc feat: support custom before run form 2025-07-30 14:43:29 +08:00
jyong f37109ef39 transform document 2025-07-30 14:34:38 +08:00
Harry 875aea1c22 feat: datasource reauthentication 2025-07-30 13:39:04 +08:00
Joel c70a7e832e chore: data source add single run button 2025-07-29 18:31:35 +08:00
jyong ecba9e44ff transform document 2025-07-29 18:17:56 +08:00
jyong a7d4675831 transform document 2025-07-29 18:12:35 +08:00
jyong 21df72a57a transform document 2025-07-29 17:56:28 +08:00
Joel 240f6890f1 fix: some lint 2025-07-29 16:29:59 +08:00
Joel 27f65150d7 fix: run tool cause page crash because of feature context 2025-07-29 16:19:14 +08:00
jyong e2df3f182d transform document 2025-07-29 16:01:06 +08:00
zxhlyh a996c1d90c merge main 2025-07-29 15:45:01 +08:00
zxhlyh e19a07c2e6 merge main 2025-07-29 15:44:23 +08:00
Joel 2c6f88ef82 chore: reload vars 2025-07-29 15:24:26 +08:00
jyong 786d121fdf Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-07-29 15:23:22 +08:00
jyong 9cfb531e3b transform document 2025-07-29 15:23:11 +08:00
twwu 1c813239c9 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-07-29 14:52:25 +08:00
twwu fbf3abddf2 feat: Add tooltip for configuration button in header and update translations 2025-07-29 14:52:17 +08:00
jyong e89398f415 add old auth transform 2025-07-29 14:13:50 +08:00
twwu cc911f46f2 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-07-29 13:46:23 +08:00
twwu c2cbdcd3bf feat: Enhance dataset info and card components with memoization for improved performance 2025-07-29 13:46:17 +08:00
jyong 46db1acf98 Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-07-29 11:18:14 +08:00
jyong 6d00ffa509 add old auth transform 2025-07-29 11:18:06 +08:00
zxhlyh 446301a443 fix: search method 2025-07-29 11:10:16 +08:00
jyong 657e813c7f add old auth transform 2025-07-28 19:29:36 +08:00
jyong 829e6f0d1a add old auth transform 2025-07-28 19:29:07 +08:00
twwu b0cd4daf54 feat: Add credential seletor for online docuemnts and online drive 2025-07-28 16:55:40 +08:00
zxhlyh fc3250678c fix: module not found 2025-07-28 16:36:40 +08:00
zxhlyh a95cf6f8b0 merge main 2025-07-28 16:00:38 +08:00
zxhlyh acae51c309 initial nodes 2025-07-28 15:38:48 +08:00
zxhlyh 347cd6befc publish toast 2025-07-28 14:29:05 +08:00
jyong 50fed69c0c r2 transform 2025-07-28 14:00:18 +08:00
jyong 9dbc887da5 Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-07-25 17:43:23 +08:00
jyong 38e6391be4 r2 transform 2025-07-25 17:43:15 +08:00
twwu e1861f5f9c fix: add dataset reset functionality and improve warning message consistency 2025-07-25 17:30:19 +08:00
jyong f887bbedab r2 transform 2025-07-25 17:06:29 +08:00
jyong f4dd22b9cb r2 transform 2025-07-25 15:17:03 +08:00
jyong 7f6759e0ac r2 transform 2025-07-25 14:41:39 +08:00
jyong b01c66acbc Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-07-25 14:10:20 +08:00
jyong ed1bec9344 r2 transform 2025-07-25 14:10:12 +08:00
zxhlyh 4fdcd74f52 fix: publish 2025-07-25 12:00:00 +08:00
jyong bb609ee3ca Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-07-24 17:43:38 +08:00
jyong 1938991162 r2 transform 2025-07-24 17:43:26 +08:00
twwu bae2af0c85 Merge branch main into feat/rag-2 2025-07-24 17:40:04 +08:00
jyong 3b0be18d47 r2 transform 2025-07-24 17:08:39 +08:00
zxhlyh 0417e2f4d9 fix: auth provider 2025-07-24 16:58:25 +08:00
zxhlyh 16603952a0 datasource template 2025-07-23 18:20:32 +08:00
jyong 5401299e6e Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-07-23 17:02:12 +08:00
jyong 98ef4ffb4d r2 transform 2025-07-23 17:02:01 +08:00
zxhlyh 761d717656 fix 2025-07-23 16:59:47 +08:00
zxhlyh 44a8b4120b pipeline template 2025-07-23 15:34:32 +08:00
zxhlyh 53cdee1e2f pipeline template 2025-07-23 10:46:45 +08:00
zxhlyh d76e37b018 add datasource empty node 2025-07-22 16:48:24 +08:00
zxhlyh 3b8d96f45c merge main 2025-07-22 13:52:24 +08:00
zxhlyh 10657b6bd3 datasource auth 2025-07-22 10:39:19 +08:00
Harry e5c7fd5b14 feat: enforce maximum length for authorization name in datasource authentication 2025-07-21 19:31:58 +08:00
Harry 12661ce0ca feat: improve authorization name validation and enhance credential encryption handling 2025-07-21 19:28:00 +08:00
Harry 34072371a1 feat: refactor OAuth client retrieval in datasource authentication 2025-07-21 18:55:21 +08:00
Harry 666868fa35 feat: remove unused import for CredentialsValidateFailedError in datasource provider service 2025-07-21 18:53:36 +08:00
Harry ba7f0b3004 feat: enhance datasource authentication by improving credential handling and updating API parameters 2025-07-21 18:51:55 +08:00
zxhlyh 386d320650 rename auth name 2025-07-21 17:59:13 +08:00
zxhlyh 4d36e784b7 merge main 2025-07-21 17:45:26 +08:00
zxhlyh caa2de3344 datasource oauth 2025-07-21 17:41:19 +08:00
Harry 039a053027 feat: standardize credential type string for API key in datasource provider service 2025-07-21 17:40:50 +08:00
Harry 7141181732 feat: remove unnecessary blank line in datasource authentication setup 2025-07-21 17:00:10 +08:00
Harry 17da96bdd8 feat: refactor datasource authentication APIs for improved credential management 2025-07-21 16:43:50 +08:00
Harry 57b48f51b5 feat: convert credential form schemas to lists for consistency 2025-07-21 15:51:24 +08:00
Harry af94602d37 feat: add APIs for setting default datasource provider and updating provider name 2025-07-21 15:49:39 +08:00
jyong 9c96f1db6c r2 transform 2025-07-21 14:51:40 +08:00
Harry 51d7a9b6be feat: mask hidden values in tenant OAuth client retrieval 2025-07-21 14:35:46 +08:00
Harry 529eca70bc feat: enhance datasource credential and OAuth schema serialization 2025-07-21 14:31:26 +08:00
Harry ef8d941633 feat: simplify OAuth encrypter retrieval and remove unnecessary validation 2025-07-21 13:48:05 +08:00
Harry e97f03c130 feat: add custom OAuth client setup and enhance datasource provider model with avatar_url 2025-07-21 12:36:02 +08:00
Harry 7364d051d2 feat: refactor provider name generation to use incremental naming & enforce unique constraints 2025-07-18 21:34:59 +08:00
Harry 23a5ff410e feat: add avatar_url to datasource providers and update OAuth handling 2025-07-18 19:47:59 +08:00
jyong 34a6ed74b6 r2 transform 2025-07-18 19:22:31 +08:00
jyong dc359c6442 r2 transform 2025-07-18 19:04:46 +08:00
Harry dd59cea085 migrations 2025-07-18 14:58:10 +08:00
Harry ab775bce26 feat: remove BuiltinDatasourceProvider class and related credential handling 2025-07-18 14:47:08 +08:00
Harry 82b531e949 feat: remove tenant_plugin_auto_upgrade_strategies table and adjust datasource_oauth_params 2025-07-18 14:44:01 +08:00
Harry f325662141 feat: refactor DatasourceNode and KnowledgeIndexNode to use _node_data attribute 2025-07-18 14:25:11 +08:00
twwu 32fe8313b4 feat: import and extend dayjs relativeTime plugin in multiple components 2025-07-18 14:15:07 +08:00
Harry 6ca5bc1063 feat: add datasource OAuth client setup command and refactor related models 2025-07-18 14:11:15 +08:00
twwu f153319a77 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-07-18 14:05:55 +08:00
twwu 0e428afe43 feat: convert VersionHistoryPanel to dynamic import for improved performance 2025-07-18 14:05:34 +08:00
Joel f336245a45 fix: tool node text overflow 2025-07-18 14:05:08 +08:00
twwu 5b2c99e183 Merge branch 'main' into feat/rag-2 2025-07-18 14:03:48 +08:00
twwu 399866e0ac fix: add 'no-spinner' class to InputNumber component for better styling 2025-07-18 13:42:05 +08:00
Harry 633bfc25e0 feat: update provider parameter naming and refactor related logic in datasource_auth.py 2025-07-18 13:13:20 +08:00
Harry 0ac5c0bf3e feat: refactor OAuth provider handling and improve provider name generation 2025-07-18 12:47:32 +08:00
twwu 9f2a9ad271 fix: update keyboard shortcut and clean up component structure in various files 2025-07-17 18:22:03 +08:00
twwu 59f68cd63b fix: ensure default values are handled correctly in InputNumber and related components 2025-07-17 18:15:52 +08:00
Harry 3388e83920 Merge remote-tracking branch 'origin/main' into feat/rag-2
# Conflicts:
#	.github/workflows/build-push.yml
#	web/app/components/workflow/nodes/_base/components/workflow-panel/index.tsx
2025-07-17 17:56:56 +08:00
zxhlyh e0e0a7661d merge main 2025-07-17 16:49:59 +08:00
zxhlyh de47b56ca4 merge main 2025-07-17 16:49:22 +08:00
zxhlyh 01566035e3 merge main 2025-07-17 16:48:43 +08:00
jyong cc96b7f507 r2 transform 2025-07-17 16:45:30 +08:00
jyong ad7650e724 r2 transform 2025-07-17 16:36:40 +08:00
zxhlyh f79a90fb21 fix agent default 2025-07-17 16:07:58 +08:00
jyong d0c78d079b r2 transform 2025-07-17 15:32:58 +08:00
jyong cc06ce60fd Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-07-17 15:22:51 +08:00
jyong 761ea0eedb r2 transform 2025-07-17 15:22:39 +08:00
zxhlyh c706793847 fix: file upload config 2025-07-17 13:48:23 +08:00
zxhlyh 2c52561060 datasource oauth 2025-07-17 11:18:08 +08:00
jyong a39d7e1f85 r2 transform 2025-07-16 19:26:33 +08:00
jyong aaa5b0e295 r2 transform 2025-07-16 18:05:40 +08:00
jyong 3bdb40f37b Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-07-16 14:25:30 +08:00
jyong c660c98b04 r2 transform 2025-07-16 14:25:16 +08:00
twwu e7f31a66be fix: correct notification type for successful dataset conversion 2025-07-16 14:12:33 +08:00
jyong 675ff9bd7d r2 transform 2025-07-16 12:00:26 +08:00
jyong 6363ecef97 r2 transform 2025-07-16 11:49:59 +08:00
twwu 5c0d19e36d fix: improve handleVariableNameBlur logic to prevent setting label when it already exists 2025-07-16 10:33:59 +08:00
twwu e0753ebfd1 fix: update dataset conversion endpoint path for correct API integration 2025-07-16 10:08:46 +08:00
twwu b8e9b97f07 feat: implement dataset conversion to pipeline with success and error notifications 2025-07-16 09:53:11 +08:00
jyong 384073f025 r2 transform 2025-07-16 02:02:08 +08:00
jyong 2012ea3213 r2 transform 2025-07-16 01:50:37 +08:00
jyong 1ad73ccdc8 r2 2025-07-15 17:54:53 +08:00
jyong 96484731a2 r2 2025-07-15 16:13:45 +08:00
jyong 537e535d9a r2 2025-07-15 15:33:40 +08:00
jyong 3a3b60bab5 r2 2025-07-15 15:00:38 +08:00
jyong 63111e8050 r2 2025-07-14 18:17:34 +08:00
twwu 405139c377 fix: add isRunning prop to ProcessDocuments and related components for better processing state management 2025-07-14 17:45:19 +08:00
jyong a919e3e135 r2 2025-07-14 17:33:08 +08:00
twwu 3e5772c50c fix: enhance layout and tooltip handling in Actions component 2025-07-14 16:36:51 +08:00
twwu cb8fab7364 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-07-14 16:26:03 +08:00
twwu 60f3832c65 fix: refactor OptionCard and StepTwo components for improved structure and readability 2025-07-14 16:25:56 +08:00
Joel cf89d06023 fix: single run url error in pipeline 2025-07-14 16:15:52 +08:00
jyong 4b9a5a66c1 r2 2025-07-14 16:14:27 +08:00
Joel e095de05c5 feat: pipeline run 2025-07-14 16:04:43 +08:00
Joel 82f4b35d52 chore: use flow type instead of whole url 2025-07-14 15:30:04 +08:00
Joel 7a9faf909e feat: workflow use common last run 2025-07-14 15:10:35 +08:00
jyong 928751a856 r2 2025-07-14 14:11:58 +08:00
twwu d77d86f53b fix: remove unused showWorkflowEmpty prop from Tools component for cleaner code 2025-07-14 14:11:05 +08:00
twwu 2a5bab10b8 fix: pass dataSources prop to PortalToFollowElem for improved functionality 2025-07-14 13:48:45 +08:00
twwu 6313f819cf fix: add block enumeration and tool icon handling for enhanced workflow functionality 2025-07-14 11:44:13 +08:00
twwu 682b65034c Merge branch 'main' into feat/rag-2 2025-07-14 11:17:42 +08:00
twwu adbad0ad33 fix: enhance bucket list initiation check for improved accuracy 2025-07-14 10:06:55 +08:00
jyong ed77877db1 Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-07-11 18:46:29 +08:00
jyong 9c4356e9a1 r2 2025-07-11 18:46:22 +08:00
twwu 0fdb1fedb0 feat: add PluginDependency component to RagPipelineChildren and WorkflowChildren for enhanced functionality 2025-07-11 18:38:18 +08:00
twwu 23a6fe3259 fix: adjust default selection of crawl results based on pipeline status 2025-07-11 18:02:23 +08:00
twwu 90d0f12ee9 refactor: update file extension handling in ChunkPreview component to use dynamic extension retrieval 2025-07-11 16:53:03 +08:00
twwu 50e16f8362 refactor: optimize state selection in data source components using useShallow for improved performance 2025-07-11 16:41:01 +08:00
twwu 9dbb06fccc fix: Fix node panel positioning issue when chat log modal is open 2025-07-11 15:58:26 +08:00
jyong 3b70f8ac08 r2 2025-07-11 15:25:58 +08:00
twwu 58a3471a5f refactor: update variable utility functions to include isRagVariableVar for enhanced variable validation 2025-07-11 13:51:23 +08:00
twwu 3e187ba6aa refactor: update BlockIcon component to handle Tool and DataSource types for conditional rendering 2025-07-10 16:56:59 +08:00
twwu f677f2f71b refactor: update useEffect dependency to include currentPage.page_id for proper content fetching 2025-07-10 16:27:56 +08:00
twwu de6867f875 refactor: update CrawledResult and WebsiteCrawl components to handle showPreview prop and adjust previewIndex logic 2025-07-10 15:43:36 +08:00
twwu c39746181d refactor: update data source store usage in LocalFile and WebsiteCrawl components 2025-07-10 15:24:58 +08:00
twwu 15cd9e0b12 refactor: rename selectedFileList to selectedFileKeys across components and update related logic 2025-07-10 15:14:23 +08:00
twwu e66c2badda refactor: update error handling to use DataSourceNodeErrorResponse in OnlineDocuments and WebsiteCrawl components 2025-07-10 13:55:24 +08:00
twwu 6030ae9d0f refactor: integrate currentNodeIdRef into data source store and update related components 2025-07-10 12:02:54 +08:00
twwu 42fd40500a refactor: remove isTruncated state and update related logic to use mutable refs 2025-07-10 10:39:01 +08:00
twwu 611bc728d0 fix: update hover background color for disabled and active NavLink states 2025-07-10 10:21:45 +08:00
twwu e2a141b3bb Merge branch 'main' into feat/rag-2 2025-07-10 10:14:12 +08:00
jyong 8b97551f1a r2 2025-07-09 18:50:13 +08:00
twwu 966e6e03fc style: Update component attributes to use single quotes and adjust z-index in ContentDialog 2025-07-09 18:34:21 +08:00
twwu 775983b04b Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-07-09 18:21:01 +08:00
twwu a2e0bc26c6 feat: Add conversion functionality to Knowledge Pipeline with UI and translations 2025-07-09 18:20:52 +08:00
jyong bd33b9ffec r2 2025-07-09 17:34:42 +08:00
jyong b538eee5dd r2 2025-07-09 17:28:52 +08:00
twwu 7c6bdb9ec9 feat: Enhance operations with pause and resume functionality 2025-07-09 16:05:42 +08:00
twwu 258c965bd0 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-07-09 15:55:31 +08:00
twwu 9e44f2b805 Merge branch 'main' into feat/rag-2 2025-07-09 15:54:57 +08:00
jyong 9dcba51225 r2 2025-07-09 15:48:08 +08:00
twwu e7d394f160 feat: Add DatasetSidebarDropdown component and integrate ExtraInfo for dataset details 2025-07-09 15:13:02 +08:00
twwu dfe3c2caa1 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-07-09 14:45:03 +08:00
twwu 4ea4d227c6 refactor: Remove unused file support types logic from CreateFormPipeline component 2025-07-09 14:44:56 +08:00
jyong b5e4ce6c68 r2 2025-07-09 14:27:49 +08:00
twwu 4a8061d14c fix: Integrate dataset list reset functionality in dropdown and step two components 2025-07-09 13:54:49 +08:00
twwu 59c3305dcc feat: Enhance dataset dropdown functionality with export and delete options 2025-07-09 13:42:24 +08:00
twwu 8fc15c83d0 feat: Refactor dataset info components and add export pipeline functionality 2025-07-09 10:45:50 +08:00
twwu a0942399cd Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-07-08 20:04:26 +08:00
twwu 1c85dada53 feat: Implement sidebar toggle functionality with keyboard shortcuts and improve translations 2025-07-08 20:04:15 +08:00
jyong bc1a517a97 r2 2025-07-08 17:16:10 +08:00
twwu b3431ab0c4 feat: Refactor online drive components to improve file retrieval and selection logic 2025-07-08 16:46:59 +08:00
twwu 073a0974a4 fix: Update breadcrumb click handling to close dropdown and adjust prefix slicing logic 2025-07-08 15:40:16 +08:00
twwu e911a4e719 fix: Update button styles and improve file size validation in breadcrumb and item components 2025-07-08 15:28:22 +08:00
twwu 5e2b60664f fix: Improve item selection logic and reset selected file list on folder open 2025-07-08 14:26:55 +08:00
twwu b36f36d242 feat: Enhance CreateFormPipeline with file selection and validation for online documents and drives 2025-07-08 14:14:50 +08:00
jyong 6332fe795e Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-07-08 14:05:45 +08:00
jyong db886ae3fb r2 2025-07-08 14:04:44 +08:00
twwu 467cd2c4c1 fix: Update onlineDrive file check to use selectedFileList for better validation 2025-07-07 16:34:43 +08:00
twwu d3ca50626d feat: Integrate useOnlineDrive hook and enhance datasource handling in CreateFormPipeline 2025-07-07 16:30:15 +08:00
twwu 13f168ed1c refactor: Refactor Online Drive components to improve state management and add truncation support 2025-07-07 15:51:59 +08:00
twwu 83c8219942 feat: Enhance file item component with support for disabled state and file type validation 2025-07-07 14:36:09 +08:00
twwu a30b92d6b1 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-07-04 19:15:52 +08:00
twwu 1bd664e655 feat: Implement Dropdown and Menu components for breadcrumb navigation in Online Drive 2025-07-04 19:15:37 +08:00
jyong 1fb59adba9 r2 2025-07-04 19:09:40 +08:00
jyong 1b3888a13e Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-07-04 18:49:50 +08:00
jyong 9c6eb95700 r2 2025-07-04 18:49:37 +08:00
twwu 1ff608dfa9 Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2 2025-07-04 18:24:59 +08:00
twwu 933ad0649c feat: Add subItems mapping to Panel component for enhanced item details 2025-07-04 18:24:52 +08:00
jyong a8b676ade0 r2 2025-07-04 18:05:58 +08:00
twwu 0d9991ec88 feat: Add ONLINE_DRIVE_OUTPUT and integrate into DataSource components for online drive support 2025-07-04 18:04:47 +08:00
twwu e67a19b26b refactor: Enhance Bucket and Breadcrumbs components; improve event handling and add button for bucket name 2025-07-04 17:55:30 +08:00
twwu d44af3ec46 refactor: Restructure breadcrumbs component; introduce Bucket and BreadcrumbItem components for improved navigation 2025-07-04 16:44:21 +08:00
twwu 9ce0c69687 refactor: Update event handling in Checkbox and Radio components; optimize Online Drive file filtering 2025-07-04 15:30:08 +08:00
twwu 2ecbcd6a7f refactor: Add loading state and bucket handling to Online Drive components 2025-07-04 15:14:19 +08:00
twwu d3b17ea567 fix: Update key property for onlineDrive datasource handling in TestRunPanel 2025-07-04 14:11:23 +08:00
twwu a4f7d373b5 refactor: Replace useDataSourceStore with useDataSourceStoreWithSelector for improved state selection across components 2025-07-04 14:03:04 +08:00
twwu 334f0c905a feat: Enhance Online Drive file handling with selection and folder opening functionality 2025-07-04 13:42:36 +08:00
jyong 44c2efcfe4 r2 2025-07-03 18:56:42 +08:00
twwu f2960989c1 refactor: Refactor data source components 2025-07-03 18:34:54 +08:00
jyong 816b49483a Merge remote-tracking branch 'origin/feat/rag-2' into feat/rag-2 2025-07-03 15:15:14 +08:00
jyong 798d0880d6 r2 2025-07-03 15:15:01 +08:00
twwu cf4f652105 fix: Enhance data source handling by adding error response type and updating local file and online document slices 2025-07-03 14:58:58 +08:00
jyong 76c418c0b7 r2 2025-07-03 14:03:06 +08:00
jyong 7c5893db91 Merge branch 'feat/r2' into deploy/rag-dev
# Conflicts:
#	web/app/components/workflow-app/components/workflow-main.tsx
#	web/app/components/workflow/constants.ts
#	web/app/components/workflow/header/run-and-history.tsx
#	web/app/components/workflow/hooks-store/store.ts
#	web/app/components/workflow/hooks/use-nodes-interactions.ts
#	web/app/components/workflow/hooks/use-workflow-interactions.ts
#	web/app/components/workflow/hooks/use-workflow.ts
#	web/app/components/workflow/nodes/_base/components/panel-operator/panel-operator-popup.tsx
#	web/app/components/workflow/nodes/_base/components/variable/var-reference-picker.tsx
#	web/app/components/workflow/nodes/code/use-config.ts
#	web/app/components/workflow/nodes/llm/default.ts
#	web/app/components/workflow/panel/index.tsx
#	web/app/components/workflow/panel/version-history-panel/index.tsx
#	web/app/components/workflow/store/workflow/index.ts
#	web/app/components/workflow/types.ts
#	web/config/index.ts
#	web/types/workflow.ts
2025-07-03 11:40:54 +08:00
twwu 2dd1f41ad3 feat: Implement data source store with slices for local files, online documents, website crawls, and online drives 2025-07-03 10:31:29 +08:00
twwu ddde576b4a refactor: Update notification messages in CreateFromDSLModal and CreateFromScratchModal for dataset creation 2025-07-03 10:17:55 +08:00
jyong 38d895ab5f r2 2025-07-02 18:46:36 +08:00
jyong a6ff9b224b r2 2025-07-02 18:20:41 +08:00
jyong 832bef053f Merge branch 'main' into feat/r2
# Conflicts:
#	docker/docker-compose.middleware.yaml
#	web/app/components/workflow-app/components/workflow-main.tsx
#	web/app/components/workflow-app/hooks/index.ts
#	web/app/components/workflow/hooks-store/store.ts
#	web/app/components/workflow/hooks/index.ts
#	web/app/components/workflow/nodes/_base/components/variable/var-reference-picker.tsx
2025-07-02 18:20:05 +08:00
jyong 81b07dc3be r2 2025-07-02 18:15:23 +08:00
zxhlyh a52bf6211a merge main 2025-07-02 18:07:09 +08:00
twwu d7b0ccd6f7 feat: Add name field to data source credentials update function in usePipeline service 2025-07-02 15:08:20 +08:00
twwu 68d59ee8b3 refactor: Refactor useOnlineDocument hook 2025-07-02 14:56:29 +08:00
jyong e23d7e39ec Merge branch 'feat/datasource' into feat/r2
# Conflicts:
#	api/services/rag_pipeline/rag_pipeline.py
#	web/app/components/workflow/constants.ts
#	web/app/components/workflow/header/run-and-history.tsx
#	web/app/components/workflow/hooks/use-nodes-interactions.ts
#	web/app/components/workflow/hooks/use-workflow-interactions.ts
#	web/app/components/workflow/hooks/use-workflow.ts
#	web/app/components/workflow/index.tsx
#	web/app/components/workflow/nodes/_base/components/panel-operator/panel-operator-popup.tsx
#	web/app/components/workflow/nodes/_base/panel.tsx
#	web/app/components/workflow/nodes/code/use-config.ts
#	web/app/components/workflow/nodes/llm/default.ts
#	web/app/components/workflow/panel/index.tsx
#	web/app/components/workflow/panel/version-history-panel/index.tsx
#	web/app/components/workflow/store/workflow/index.ts
#	web/app/components/workflow/types.ts
#	web/config/index.ts
#	web/types/workflow.ts
2025-07-02 14:01:59 +08:00
twwu 0284e7556e refactor: Refactor useDatasourceIcon hook and enhance dataset node rendering with AppIcon component 2025-07-02 13:48:11 +08:00
jyong 9f14b5db9a r2 2025-07-02 11:55:21 +08:00
jyong 39d3f58082 r2 2025-07-02 11:33:00 +08:00
twwu 5d7a533ada fix: Improve layout by adding overflow handling in CreateFromPipeline and List components 2025-07-01 17:46:41 +08:00
twwu 0db7967e5f refactor: Add useOnlineDrive hook and integrate it into CreateFormPipeline and TestRunPanel components 2025-07-01 16:54:44 +08:00
twwu a81dc49ad2 feat: Refactor OnlineDocuments and PageSelector components to enhance state management and integrate new Actions component 2025-07-01 16:32:21 +08:00
jyong f33b6c0c73 add online drive 2025-07-01 16:08:54 +08:00
jyong a4eddd7dc2 r2 2025-07-01 15:16:33 +08:00
jyong c993a05da7 Merge remote-tracking branch 'origin/feat/r2' into feat/r2 2025-07-01 14:23:58 +08:00
jyong f44f0fa34c r2 2025-07-01 14:23:46 +08:00
twwu 2d0d448667 feat: Update selection handling to support multiple choice in OnlineDocuments and PageSelector components 2025-07-01 14:14:28 +08:00
Dongyu Li bfcf09b684 feat(datasource): fix datasource icon 2025-07-01 14:04:09 +08:00
Dongyu Li cdbba1400c feat(datasource): update fetch_datasource_provider 2025-07-01 11:57:06 +08:00
twwu 55d7d7ef76 fix: Update default value handling for number input in useInitialData hook 2025-07-01 11:24:30 +08:00
twwu 7b473bb5c9 feat: Integrate OnlineDrive component into CreateFormPipeline and update related components 2025-06-30 18:31:52 +08:00
twwu ff511c6f31 refactor: Remove unused variables and simplify next button logic in TestRunPanel 2025-06-30 17:54:33 +08:00
twwu 310102bebd feat: Add SearchMenu icon and integrate it into the file list component with empty state handling 2025-06-30 17:31:27 +08:00
zxhlyh 1f5c32525f datasource page 2025-06-30 16:16:54 +08:00
jyong 618ad4c291 r2 2025-06-30 15:36:20 +08:00
twwu ada632f9f5 feat: Enhance input field handling by adding allVariableNames prop and localizing error messages 2025-06-30 15:28:55 +08:00
twwu 4c82c9d029 feat: Add Online Drive file management components and enhance file icon handling 2025-06-30 14:19:14 +08:00
zxhlyh 42655a3b1f fix: checklist 2025-06-30 14:11:26 +08:00
Harry 1449ed86c4 feat: rename online driver to online drive and update related classes and methods :) 2025-06-27 20:11:28 +08:00
zxhlyh 94674e99ab datasource page add marketplace 2025-06-27 16:44:23 +08:00
Harry eee72101f4 feat(online_driver): add online driver plugin, support browsing and downloading 2025-06-27 16:41:39 +08:00
twwu 93eabef58a refactor: Refactor OnlineDocuments component and remove OnlineDocumentSelector 2025-06-27 16:29:30 +08:00
twwu 5248fcca56 feat: implement support for single and multiple choice in crawled result items 2025-06-27 15:56:38 +08:00
twwu 264b95e572 feat: separate input fields into datasource and global categories in RAG pipeline 2025-06-27 15:23:04 +08:00
zxhlyh 8f2ad89027 datasource page 2025-06-27 15:01:33 +08:00
twwu 18b1a9cb2e Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-06-26 15:28:19 +08:00
zxhlyh 25fef5d757 merge main 2025-06-26 15:21:24 +08:00
twwu 2a25ca2b2c feat: enhance online drive connection UI and add localization for connection status in dataset pipeline 2025-06-26 14:24:50 +08:00
twwu 3a9c79b09a feat: refactor data source handling and integrate OnlineDrive component in TestRunPanel 2025-06-26 13:46:12 +08:00
twwu 025b55ef3b feat: update tooltip text for test run mode in English and Chinese translations for clarity 2025-06-26 10:17:48 +08:00
twwu cf7574bd10 feat: add FooterTips component and integrate it into TestRunPanel; extend DatasourceType enum with onlineDrive 2025-06-26 10:16:37 +08:00
jyong efccbe4039 r2 2025-06-25 17:32:26 +08:00
twwu c7cec120a6 feat: update variable validation regex for consistency in ExternalDataToolModal and schema 2025-06-25 17:07:31 +08:00
twwu 7d7fd18e65 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-06-25 16:16:41 +08:00
twwu c6ae9628af feat: refactor input variable handling and configurations in pipeline processing components 2025-06-25 16:15:59 +08:00
Joel 4631575c12 feat: can support choose current node var 2025-06-25 16:06:08 +08:00
zxhlyh a4f4fea0a5 fix: note node delete 2025-06-25 16:01:45 +08:00
jyong 540096a8d8 Merge branch 'main' into feat/r2
# Conflicts:
#	api/core/plugin/impl/oauth.py
#	api/core/workflow/entities/variable_pool.py
#	api/models/workflow.py
#	api/services/dataset_service.py
2025-06-25 14:35:23 +08:00
jyong 7b7cdad1d8 r2 2025-06-25 13:28:08 +08:00
twwu 261b7cabc8 feat: enhance OnlineDocumentPreview with datasourceNodeId and implement preview functionality 2025-06-25 11:36:56 +08:00
twwu ccd346d1da feat: add handling for RAG pipeline variables in node interactions 2025-06-25 10:40:48 +08:00
twwu a866cbc6d7 feat: implement usePipeline hook for managing pipeline variables and refactor input field handling 2025-06-25 10:11:26 +08:00
Dongyu Li 6aba39a2dd feat(datasource): add datasource content preview api 2025-06-24 17:43:25 +08:00
zxhlyh 8f4a0d4a22 variable picker 2025-06-24 17:27:06 +08:00
Dongyu Li 49bb15fae1 feat(datasource): add datasource content preview api 2025-06-24 17:14:31 +08:00
Dongyu Li e165f4a102 feat(datasource): add datasource content preview api 2025-06-24 17:14:16 +08:00
twwu 1c51bef3cb fix: standardize capitalization in translation keys and remove unused group property in FieldListContainer 2025-06-24 14:25:58 +08:00
zxhlyh c31754e6cd fix: create pipeline from customized 2025-06-24 11:12:39 +08:00
jyong 83cc484c24 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-23 17:12:26 +08:00
jyong 1ff9c07a92 fix notion dataset rule not found 2025-06-23 17:12:08 +08:00
twwu b25b284d7f Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-23 16:41:13 +08:00
twwu 2414dbb5f8 feat: clear selected IDs on document deletion action in DocumentList component 2025-06-23 16:38:19 +08:00
twwu 916a8c76e7 fix: rename currentDocuments to currentDocument for consistency in online documents handling 2025-06-23 16:31:09 +08:00
Dongyu Li 9783832223 Merge branch 'feat/datasource' into deploy/rag-dev 2025-06-23 16:12:03 +08:00
Dongyu Li b77081a19e feat(datasource): update datasource icon 2025-06-23 15:57:37 +08:00
twwu 896906ae77 feat: refactor layout structure in PipelineSettings component for improved responsiveness 2025-06-23 15:57:02 +08:00
twwu 2365a3a5fc Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-23 15:39:00 +08:00
twwu dd792210f6 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-06-23 15:38:34 +08:00
twwu 6ba4a4c165 feat: enhance website crawl functionality with state management and result handling 2025-06-23 15:38:24 +08:00
Dongyu Li 0a6dbf6ee2 Merge remote-tracking branch 'origin/deploy/rag-dev' into deploy/rag-dev 2025-06-23 15:21:15 +08:00
Dongyu Li ca0979dd43 feat(datasource): update fetch_datasource_provider 2025-06-23 15:18:15 +08:00
zxhlyh 0762e5ae50 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-23 15:03:32 +08:00
zxhlyh 48f53f3b9b workflow dependency 2025-06-23 15:02:57 +08:00
twwu af64f29e87 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-23 13:59:39 +08:00
twwu b9f59e3a75 Merge branch 'main' into feat/rag-pipeline 2025-06-23 13:59:05 +08:00
Dongyu Li b12a8eeb90 feat(datasource): change datasource result type to event-stream 2025-06-20 10:09:47 +08:00
twwu e551cf65c9 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-19 15:58:51 +08:00
twwu 3899211c41 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-06-19 15:58:01 +08:00
twwu 335e1e3602 feat: enhance pipeline settings with execution log and processing capabilities 2025-06-19 15:57:49 +08:00
jyong 725fc72c6f Merge branch 'feat/r2' into deploy/rag-dev 2025-06-19 15:31:03 +08:00
jyong b618f3bd9e r2 2025-06-19 15:30:46 +08:00
zxhlyh 95ba55af4d fix: import dsl sync rag variables 2025-06-19 15:04:26 +08:00
jyong f4e1ea9011 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-19 14:30:05 +08:00
jyong 3d0e288e85 r2 2025-06-19 14:29:39 +08:00
jyong 9620d6bcd8 Merge branch 'feat/r2' into deploy/rag-dev
# Conflicts:
#	web/i18n/zh-Hans/app.ts
2025-06-19 13:32:49 +08:00
jyong f7fbded8b9 Merge branch 'main' into feat/r2 2025-06-19 13:32:07 +08:00
Dongyu Li 0c5706b3f6 Merge remote-tracking branch 'origin/deploy/rag-dev' into deploy/rag-dev 2025-06-19 11:10:43 +08:00
Dongyu Li 82d0a70cb4 feat(datasource): change datasource result type to event-stream 2025-06-19 11:10:24 +08:00
twwu 55516c4e57 fix: add type checks for workspace roles in DatasetsLayout component 2025-06-19 10:56:03 +08:00
jyong cc2cd85ff5 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-19 10:46:15 +08:00
jyong 6ec742539a r2 2025-06-19 10:45:59 +08:00
jyong 09e0a54070 r2 2025-06-19 10:38:10 +08:00
twwu 5d25199f42 refactor: update layout for creation title and content in StepThree component 2025-06-19 09:36:04 +08:00
twwu 387826674c Merge branch 'main' into feat/rag-pipeline 2025-06-19 09:34:09 +08:00
twwu 02ae479636 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-18 18:04:23 +08:00
twwu a103324f25 refactor: enhance UI components with new icons and improved styling in billing and dataset processes 2025-06-18 18:03:43 +08:00
jyong 643efc5d85 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-18 17:11:52 +08:00
Dongyu Li 43e5798e13 feat(datasource): change datasource result type to event-stream 2025-06-18 16:27:10 +08:00
Dongyu Li 8aca70cd50 Merge remote-tracking branch 'origin/deploy/rag-dev' into deploy/rag-dev 2025-06-18 16:05:08 +08:00
Dongyu Li 2cf980026e feat(datasource): change datasource result type to event-stream 2025-06-18 16:04:47 +08:00
Dongyu Li 224111081b feat(datasource): change datasource result type to event-stream 2025-06-18 16:04:40 +08:00
twwu 4dc6cad588 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-18 15:08:05 +08:00
twwu f85e6a0dea feat: implement SSE for data source node processing and completion events, replacing previous run methods 2025-06-18 15:06:50 +08:00
twwu 4b3a54633f refactor: streamline dataset detail fetching and improve dataset list handling across components 2025-06-18 15:05:21 +08:00
jyong 6f67a34349 r2 qa index 2025-06-18 14:37:18 +08:00
zxhlyh e51d308312 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-18 13:47:36 +08:00
zxhlyh 379c92bd82 Merge branch 'main' into feat/rag-pipeline 2025-06-18 13:47:06 +08:00
jyong fa9f0ebfb1 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-18 11:06:37 +08:00
jyong ac917bb56d r2 2025-06-18 11:05:52 +08:00
jyong f7a4e5d1a6 Merge branch 'main' into feat/r2 2025-06-18 10:57:44 +08:00
jyong 515d34bbfb Merge branch 'feat/r2' into deploy/rag-dev 2025-06-17 19:07:38 +08:00
jyong 66de2e1f0a Merge remote-tracking branch 'origin/feat/r2' into feat/r2
# Conflicts:
#	api/core/workflow/graph_engine/entities/event.py
#	api/services/rag_pipeline/rag_pipeline.py
2025-06-17 19:07:15 +08:00
jyong 7f7ea92a45 r2 2025-06-17 19:06:17 +08:00
Dongyu Li a014345688 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-17 18:29:24 +08:00
Dongyu Li cf66d111ba feat(datasource): change datasource result type to event-stream 2025-06-17 18:29:02 +08:00
Dongyu Li 2d01b1a808 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-17 18:24:52 +08:00
Dongyu Li 739ebf2117 feat(datasource): change datasource result type to event-stream 2025-06-17 18:24:09 +08:00
twwu 176b844cd5 refactor: consolidate DialogWrapper component usage and improve prop handling across input fields 2025-06-17 18:20:30 +08:00
jyong 8fc6684ab1 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-17 18:12:36 +08:00
jyong 7c41f71248 r2 2025-06-17 18:11:38 +08:00
zxhlyh 2c2bfb4f54 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-17 17:45:50 +08:00
zxhlyh 3164f90327 merge main 2025-06-17 17:44:08 +08:00
twwu 90ac52482c test: add unit tests for ActionButton component with various states and sizes 2025-06-17 16:48:52 +08:00
twwu 879ac940dd Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-17 16:30:37 +08:00
twwu 796797d12b feat: centralize variable type mapping by introducing VAR_TYPE_MAP in pipeline model 2025-06-17 16:28:50 +08:00
twwu 7ac0f0c08c feat: enhance processing components by adding runDisabled state and fetching indicators 2025-06-17 16:13:49 +08:00
twwu 5cc6a2bf33 refactor: update toast notification handling and improve context usage in DocumentDetail 2025-06-17 14:41:06 +08:00
jyong 2db0b19044 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-17 14:05:15 +08:00
jyong 1d2ee9020c r2 2025-06-17 14:04:55 +08:00
Dongyu Li f2538bf381 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-17 13:56:00 +08:00
Dongyu Li f37e28a368 feat(datasource): Comment out the datasource_file_manager. 2025-06-17 13:54:25 +08:00
Dongyu Li c5976f5a09 feat(datasource): change datasource result type to event-stream 2025-06-17 13:51:41 +08:00
twwu 64a9181ee4 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-17 11:30:38 +08:00
twwu 33cd32382f feat: add indexing status batch and process rule hooks; refactor Notion page preview types 2025-06-17 11:29:56 +08:00
twwu 9456c59290 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-17 10:14:20 +08:00
twwu ce0bd421ae Merge branch 'main' into feat/rag-pipeline 2025-06-17 10:13:31 +08:00
twwu f9d04c6975 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-06-16 18:26:01 +08:00
twwu ecb07a5d0d feat: enhance field list functionality by adding chosen and selected properties to SortableItem 2025-06-16 18:25:30 +08:00
zxhlyh a165ba2059 merge main 2025-06-16 15:43:57 +08:00
zxhlyh 12fd2903d8 fix 2025-06-16 15:41:27 +08:00
twwu 0a2c569b3b fix: replace useGetDocLanguage with useDocLink for consistent documentation linking 2025-06-16 14:58:52 +08:00
twwu 9ab0d5fe60 Merge branch 'main' into feat/rag-pipeline 2025-06-16 14:25:58 +08:00
jyong 1d71fd5b56 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-16 14:09:04 +08:00
jyong b277acc298 Merge branch 'main' into feat/r2 2025-06-16 14:08:02 +08:00
jyong 8d47d8ce4f Merge remote-tracking branch 'origin/feat/r2' into feat/r2
# Conflicts:
#	api/core/datasource/website_crawl/website_crawl_plugin.py
#	api/services/rag_pipeline/rag_pipeline.py
2025-06-16 13:50:33 +08:00
jyong 41fef8a21f r2 2025-06-16 13:48:43 +08:00
zxhlyh b853a42e37 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-16 11:45:24 +08:00
zxhlyh 1633626d23 Merge branch 'main' into feat/rag-pipeline 2025-06-16 11:44:42 +08:00
zxhlyh 6c7a40c571 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-16 10:16:00 +08:00
zxhlyh abb2ed66e7 merge main 2025-06-16 10:15:24 +08:00
zxhlyh 5ae78f79b0 datasource dark theme 2025-06-16 10:00:14 +08:00
twwu e3b3a6d040 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-13 18:32:56 +08:00
twwu 6622ce6ad8 fix: update formData construction in convertToInputFieldFormData for improved handling of optional fields
fix: adjust z-index value in DialogWrapper for proper stacking context
2025-06-13 18:32:36 +08:00
Harry 5ccb8d9736 feat: online document 2025-06-13 18:22:15 +08:00
twwu 55906c8375 fix: remove unused billing plan logic from CreateFromDSLModal component 2025-06-13 18:01:01 +08:00
Harry 0908f310fc feat: webcrawl 2025-06-13 17:47:51 +08:00
twwu 58842898e1 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-06-13 16:42:27 +08:00
zxhlyh 1c17c8fa36 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-13 16:39:40 +08:00
zxhlyh 26aff400e4 node default configs 2025-06-13 16:38:54 +08:00
twwu 4b11d29ede fix: update VAR_TYPE_MAP and initialData handling in useConfigurations for improved variable processing 2025-06-13 15:57:16 +08:00
jyong b2b95412b9 r2 2025-06-13 15:04:22 +08:00
twwu 5c228bca4f feat: replace TypeIcon with AppIcon in SelectDataSet component for improved icon display 2025-06-13 15:02:31 +08:00
JyongandGitHub 7bd2509ad5 Update deploy-dev.yml 2025-06-13 14:50:38 +08:00
twwu 2a5d70d9e1 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-13 14:44:53 +08:00
twwu b0107f4128 fix: update z-index values for DialogWrapper components to ensure proper stacking context 2025-06-13 14:44:32 +08:00
Joel dc3c5362e4 Merge branch 'deploy/rag-dev' of https://github.com/langgenius/dify into deploy/rag-dev 2025-06-13 14:43:58 +08:00
Joel 1d106c3660 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-13 14:43:46 +08:00
zxhlyh fcb2fa04e7 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-13 14:43:38 +08:00
zxhlyh 55bff10f0d fix 2025-06-13 14:43:02 +08:00
Joel 45c9b77e82 fix: match var reg 2025-06-13 14:42:35 +08:00
twwu 767860e76b Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-13 11:44:22 +08:00
twwu 80f656f79a fix: adjust layout and visibility conditions in CreateFormPipeline and ChunkPreview components 2025-06-13 11:38:26 +08:00
Joel c891eb28fc fix: in prompt editor show vars error 2025-06-13 11:12:11 +08:00
twwu b9fa3f54e9 refactor: refactor component imports and enhance layout for better responsiveness in dataset previews 2025-06-13 10:54:31 +08:00
twwu 4d2f904d72 feat: enhance WorkflowPreview and TemplateCard components with additional styling and className prop 2025-06-13 10:14:45 +08:00
twwu 26b7911177 Merge branch 'main' into feat/rag-pipeline 2025-06-13 09:49:03 +08:00
twwu dd91edf70b Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-12 18:11:19 +08:00
twwu d994e6b6c7 feat: replace data source icons with AppIcon component in Item and DatasetItem 2025-06-12 18:11:00 +08:00
twwu aba48bde0b feat: update SettingsModal to integrate keyword number handling and refactor index method logic 2025-06-12 18:06:00 +08:00
twwu 3e5d9884cb test: add unit tests for AppIcon component with various rendering scenarios 2025-06-12 17:33:28 +08:00
twwu faadad62ff Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-12 17:01:41 +08:00
twwu 406d70e4a3 feat: integrate resetDatasetList hook into CreateOptions and TemplateCard components 2025-06-12 16:59:33 +08:00
zxhlyh f17f256b2b Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-12 16:25:04 +08:00
zxhlyh b367f48de6 add datasource category 2025-06-12 16:24:21 +08:00
JyongandGitHub dee7b6eb22 Update deploy-dev.yml 2025-06-12 16:19:12 +08:00
twwu 6f17200dec refactor: update dataset handling to use runtime_mode instead of pipeline_id 2025-06-12 15:57:07 +08:00
twwu d3dbfbe8b3 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-12 15:18:49 +08:00
twwu b1f250862f Merge branch 'main' into feat/rag-pipeline 2025-06-12 15:18:19 +08:00
twwu 141d6b1abf feat: implement document settings and pipeline settings components with localization support 2025-06-12 15:13:15 +08:00
zxhlyh a7eb534761 add datasource category 2025-06-12 15:05:36 +08:00
twwu 808f792f55 fix: update isPending condition and add indexing technique checks for segment detail and new segment modal 2025-06-12 11:11:03 +08:00
twwu 346d066128 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-11 18:12:17 +08:00
twwu 5c41922b8a fix: update file extension for downloaded DSL files and refine mutation keys for template operations 2025-06-11 18:11:38 +08:00
jyong 9c3e3b00d0 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-11 18:07:20 +08:00
jyong da3a3ce165 r2 2025-06-11 18:07:06 +08:00
jyong b525bc2b81 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-11 18:03:53 +08:00
jyong 14dc3e8642 r2 2025-06-11 18:03:21 +08:00
twwu e52c905aa5 refactor: improve layout-main component structure and readability 2025-06-11 17:46:50 +08:00
twwu 7b9a3c1084 fix: update translation keys for document availability messages in English and Chinese 2025-06-11 17:42:45 +08:00
jyong ce8ddae11e Merge remote-tracking branch 'origin/deploy/rag-dev' into deploy/rag-dev 2025-06-11 17:30:45 +08:00
jyong 4e8184bc56 Merge branch 'feat/r2' into deploy/rag-dev
# Conflicts:
#	api/models/dataset.py
2025-06-11 17:30:30 +08:00
jyong 9eb8597957 r2 2025-06-11 17:29:14 +08:00
twwu cde584046d Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-11 17:19:08 +08:00
twwu b7f9d7e94a Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-06-11 17:17:15 +08:00
zxhlyh 88817bf974 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-11 17:17:10 +08:00
twwu 92e6c52c0e refactor: update handleUseTemplate to use callback for dataset creation and improve error handling; change HTTP method for dependency check 2025-06-11 17:17:09 +08:00
jyong 309dfe8829 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-11 17:16:52 +08:00
jyong 1d8b390584 Merge branch 'main' into feat/r2
# Conflicts:
#	docker/docker-compose.middleware.yaml
2025-06-11 17:16:27 +08:00
zxhlyh 7dea7f77ac Merge branch 'main' into feat/rag-pipeline 2025-06-11 17:12:38 +08:00
zxhlyh 4d9b15e519 fix 2025-06-11 17:11:57 +08:00
jyong 45a708f17e Merge branch 'feat/r2' into deploy/rag-dev 2025-06-11 17:10:42 +08:00
jyong 5f08a9314c r2 2025-06-11 17:10:20 +08:00
twwu 5802b2b437 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-11 16:39:18 +08:00
twwu f995436eec feat: implement chunk structure card and related hooks for dataset creation; update translations and refactor pipeline template fetching 2025-06-11 16:38:42 +08:00
jyong 25f0c61e65 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-11 16:36:56 +08:00
jyong 66fa68fa18 r2 2025-06-11 16:36:36 +08:00
jyong 3e5781c6f1 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-11 14:03:50 +08:00
jyong a6f7560d2f r2 2025-06-11 14:03:32 +08:00
twwu 45c76c1d68 refactor: rename icon property to icon_info in UpdateTemplateInfoRequest and related components 2025-06-11 13:39:07 +08:00
jyong 14d5af468c Merge branch 'feat/r2' into deploy/rag-dev 2025-06-11 13:12:41 +08:00
jyong 874e1bc41d r2 2025-06-11 13:12:18 +08:00
zxhlyh d2ae695b3b Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-11 11:55:46 +08:00
zxhlyh 6ecdac6344 pipeline preview 2025-06-11 11:51:19 +08:00
twwu 3c2ce07f38 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-11 11:30:14 +08:00
twwu 5c58b11b22 refactor: standardize pipeline template properties and improve related components 2025-06-11 11:25:08 +08:00
jyong be92122f17 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-11 11:21:37 +08:00
jyong 2972a06f16 r2 2025-06-11 11:21:17 +08:00
twwu caa275fdbd refactor: remove unused websiteCrawlJobId state and related props from useWebsiteCrawl and CreateFormPipeline components; update loading and file preview components for consistent width 2025-06-11 10:50:03 +08:00
zxhlyh 5dbda7f4c5 merge main 2025-06-11 10:41:50 +08:00
zxhlyh 0564651f6f publish as customized pipeline 2025-06-11 10:40:49 +08:00
twwu eff8108f1c refactor: update dataset model and improve batch action component 2025-06-11 10:24:07 +08:00
jyong 127a77d807 r2 2025-06-10 19:22:08 +08:00
jyong 265842223c Merge branch 'feat/r2' into deploy/rag-dev 2025-06-10 18:20:44 +08:00
jyong 95a24156de r2 2025-06-10 18:20:32 +08:00
jyong 80ca5b3356 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-10 18:16:45 +08:00
jyong e934503fa0 r2 2025-06-10 18:16:30 +08:00
jyong 442bcd18c0 Merge remote-tracking branch 'origin/deploy/rag-dev' into deploy/rag-dev 2025-06-10 17:59:27 +08:00
jyong aeb1d1946c r2 2025-06-10 17:59:14 +08:00
zxhlyh 12f2913e08 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-10 17:40:08 +08:00
zxhlyh 0aeeee49f7 fix: draft sync 2025-06-10 17:39:20 +08:00
jyong eb7479b1ea Merge branch 'feat/r2' into deploy/rag-dev 2025-06-10 17:12:12 +08:00
jyong 80b219707e r2 2025-06-10 17:11:49 +08:00
twwu 65ac022245 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-06-10 16:06:58 +08:00
twwu 6e6090d5a9 test(SegmentedControl): add test cases 2025-06-10 16:06:42 +08:00
jyong 58b5daeef3 r2 2025-06-10 15:56:28 +08:00
zxhlyh 33fd1fa79d Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-10 15:40:52 +08:00
zxhlyh 978118f770 fix: datasource 2025-06-10 15:40:15 +08:00
zxhlyh a2610b22cc Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-10 15:20:19 +08:00
zxhlyh f4789d750d publish as pipeline 2025-06-10 15:19:47 +08:00
zxhlyh 176f9ea2f4 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-10 15:10:52 +08:00
zxhlyh 5e71f7c825 publish as pipeline 2025-06-10 15:10:13 +08:00
jyong 7624edd32d r2 2025-06-10 14:56:18 +08:00
jyong 7b79354849 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-10 14:54:27 +08:00
jyong a7ff2ab470 r2 2025-06-10 14:53:07 +08:00
twwu d3eedaf0ec feat(i18n): add new translation entries for local file, website crawl, and online document 2025-06-10 14:22:09 +08:00
jyong bcb0496bf4 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-10 14:13:32 +08:00
jyong 4d967544f3 r2 2025-06-10 14:13:10 +08:00
jyong c18ee4be50 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-10 11:45:19 +08:00
jyong 65873aa411 r2 2025-06-10 11:44:52 +08:00
jyong b95256d624 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-10 11:00:11 +08:00
jyong c0d3452494 r2 2025-06-10 10:59:44 +08:00
twwu c91456de1b fix(ChunkStructure): add disabled prop to OptionCard component 2025-06-10 10:43:40 +08:00
zxhlyh e1ce156433 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-10 10:16:49 +08:00
zxhlyh 9e19ed4e67 knowledge base node checklisst 2025-06-10 10:16:13 +08:00
jyong ba383b1b0d Merge branch 'feat/r2' into deploy/rag-dev 2025-06-10 10:00:48 +08:00
jyong ad3d9cf782 r2 2025-06-10 10:00:20 +08:00
twwu 69053332e4 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-10 09:47:36 +08:00
zxhlyh 5b4d04b348 Merge branch 'main' into feat/rag-pipeline 2025-06-10 09:38:06 +08:00
jyong 47664f8fd3 r2 2025-06-09 14:00:34 +08:00
twwu 8d8f21addd Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-06 18:52:57 +08:00
twwu 9b9640b3db refactor: remove job ID handling from website crawl components and update related hooks 2025-06-06 18:52:32 +08:00
jyong 83ba61203b Merge branch 'feat/r2' into deploy/rag-dev 2025-06-06 17:47:47 +08:00
jyong fcbd5febeb r2 2025-06-06 17:47:06 +08:00
twwu b8813e199f Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-06 17:27:14 +08:00
jyong 2322496552 Merge branch 'feat/r2' into deploy/rag-dev
# Conflicts:
#	docker/docker-compose.middleware.yaml
2025-06-06 17:15:24 +08:00
jyong 21a3509bef r2 2025-06-06 17:14:43 +08:00
twwu 3e2f12b065 refactor: update website crawl handling and improve parameter naming in pipeline processing 2025-06-06 17:00:34 +08:00
JyongandGitHub 55e20d189a Update deploy-dev.yml 2025-06-06 16:16:44 +08:00
jyong 1aa13bd20d r2 2025-06-06 16:05:49 +08:00
jyong cc2dd052df Merge remote-tracking branch 'origin/deploy/rag-dev' into deploy/rag-dev 2025-06-06 16:03:46 +08:00
jyong 4ffdf68a20 r2 2025-06-06 16:03:35 +08:00
twwu 547bd3cc1b refactor: rename cancel editor handler and improve variable name validation in field list 2025-06-06 15:54:55 +08:00
zxhlyh f3e9761c75 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-06 15:35:53 +08:00
twwu 83ca59e0f1 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-06-06 15:35:50 +08:00
twwu d725aa8791 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-06-06 15:35:31 +08:00
zxhlyh cc8ee0ff69 dsl 2025-06-06 15:35:19 +08:00
twwu 4a249c40b1 feat: enhance input field configurations with blur listeners and update translations for display name 2025-06-06 15:35:19 +08:00
jyong 04e4a1e3aa Merge branch 'feat/r2' into deploy/rag-dev 2025-06-06 15:20:06 +08:00
jyong d2d5fc62ae r2 2025-06-06 15:19:53 +08:00
jyong 52460f6929 Merge remote-tracking branch 'origin/deploy/rag-dev' into deploy/rag-dev 2025-06-06 15:06:59 +08:00
jyong 06dfc32e0f Merge branch 'feat/r2' into deploy/rag-dev
# Conflicts:
#	docker/docker-compose.middleware.yaml
2025-06-06 15:06:47 +08:00
jyong 0ca38d8215 r2 2025-06-06 15:06:26 +08:00
zxhlyh 3da6becad3 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-06 15:02:00 +08:00
zxhlyh f9d0a7bdc8 Merge branch 'main' into feat/rag-pipeline 2025-06-06 15:01:27 +08:00
zxhlyh e961722597 dsl 2025-06-06 15:00:37 +08:00
zxhlyh 2ddd2616ec confirm publish 2025-06-06 14:24:02 +08:00
twwuandzxhlyh a82a9fb9d4 fix: update condition for handling datasource selection in DataSourceOptions 2025-06-06 14:24:02 +08:00
jyong 3fce6f2581 Merge branch 'feat/r2' into deploy/rag-dev
# Conflicts:
#	api/services/rag_pipeline/rag_pipeline.py
2025-06-06 14:23:05 +08:00
zxhlyh 3db864561e confirm publish 2025-06-06 14:22:15 +08:00
jyong d2750f1a02 r2 2025-06-06 14:22:00 +08:00
jyong 30a50c5cc8 Merge remote-tracking branch 'origin/deploy/rag-dev' into deploy/rag-dev 2025-06-06 12:08:20 +08:00
jyong 0ff746ebf6 r2 2025-06-06 12:08:09 +08:00
twwu 5193fa2118 fix: update condition for handling datasource selection in DataSourceOptions 2025-06-06 11:43:00 +08:00
zxhlyh 9a0dc82e6a Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-06 10:55:43 +08:00
zxhlyh 8e4165defe datasource 2025-06-06 10:55:13 +08:00
twwu d917bc8ed0 Merge branch 'deploy/rag-dev' of https://github.com/langgenius/dify into deploy/rag-dev 2025-06-06 10:53:23 +08:00
twwu ef7bd262c5 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-06 10:52:53 +08:00
jyong d3e29ffa74 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-06 10:40:57 +08:00
jyong 70432952fd r2 2025-06-06 10:40:06 +08:00
twwu cf2ef93ad5 Merge branch 'main' into feat/rag-pipeline 2025-06-06 10:10:53 +08:00
twwu cbf0864edc refactor: refactor online documents handling and update related components 2025-06-06 10:08:19 +08:00
twwu bce2bdd0de Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-06-05 18:28:58 +08:00
twwu 82e7c8a2f9 refactor: update datasource handling and improve documentation properties in pipeline components 2025-06-05 18:28:48 +08:00
Joel 2acdb0a4ea fix: var type error in cal var type in data source type 2025-06-05 17:40:49 +08:00
twwu 350ea6be6e fix: correct spacing and formatting in variable utility functions 2025-06-05 17:32:03 +08:00
zxhlyh 4664174ef3 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-05 16:51:55 +08:00
zxhlyh f0413f359a datasource 2025-06-05 16:51:19 +08:00
jyong 53b32c8b22 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-05 16:44:02 +08:00
jyong b8ef1d9585 r2 2025-06-05 16:43:47 +08:00
Joel 90ca98ff3a fix: in node show rag var 2025-06-05 16:41:04 +08:00
Joel d4a1d045f8 fix: to new var format 2025-06-05 16:36:41 +08:00
twwu 91fefa0e37 refactor: improve layout and event handling in Header and FieldItem components 2025-06-05 15:44:18 +08:00
jyong 067ec17539 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-05 15:29:37 +08:00
jyong c084b57933 r2 2025-06-05 15:28:44 +08:00
zxhlyh 876be7e6e9 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-05 15:07:59 +08:00
zxhlyh 468bfdfed9 datasource 2025-06-05 15:07:29 +08:00
jyong 82d817f612 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-05 14:56:19 +08:00
jyong 9e84a5321d r2 2025-06-05 14:55:09 +08:00
jyong d77e27ac05 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-05 14:10:07 +08:00
jyong 8a86a2c817 r2 2025-06-05 14:09:50 +08:00
twwu fdc4c36b77 refactor: replace useStore with useDatasetDetailContextWithSelector for pipeline ID retrieval 2025-06-05 14:05:27 +08:00
jyong 52c118f5b8 Merge remote-tracking branch 'origin/deploy/rag-dev' into deploy/rag-dev 2025-06-05 11:46:19 +08:00
jyong 5d7c7023c3 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-05 11:46:07 +08:00
jyong 3e0a10b7ed r2 2025-06-05 11:45:53 +08:00
twwu 84f5272f72 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-05 11:40:47 +08:00
twwu 6286f368f1 refactor: replace ImagePlus icon with RiImageCircleAiLine and improve tab button styling 2025-06-05 11:21:17 +08:00
jyong cb2ca0b533 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-05 11:12:32 +08:00
jyong 5fe5da7c1d r2 2025-06-05 11:12:06 +08:00
twwu c83370f701 refactor: simplify workflow draft synchronization in InputFieldDialog 2025-06-05 11:07:28 +08:00
twwu 7506867fb9 Merge branch 'main' into feat/rag-pipeline 2025-06-05 10:29:18 +08:00
twwu 842136959b feat: update data source handling and improve processing parameters integration 2025-06-05 10:24:25 +08:00
twwu 4c2cc98ebc Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-06-04 18:37:25 +08:00
twwu 44b9f49ab1 feat: enhance field item interaction and add preprocessing parameters hooks 2025-06-04 18:37:19 +08:00
zxhlyh f7f7952951 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-04 18:10:03 +08:00
zxhlyh a7fa5044e3 datasource 2025-06-04 18:09:31 +08:00
jyong eb84134706 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-04 17:39:46 +08:00
jyong fbca9010f3 r2 2025-06-04 17:39:31 +08:00
Joel 0bf0c7dbe8 feat: var type to inner 2025-06-04 17:34:22 +08:00
jyong e071bd63e6 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-04 17:29:55 +08:00
jyong 8a147a00e8 r2 2025-06-04 17:29:39 +08:00
twwu c9a4c66b07 fix: update input type from 'number-input' to 'number' for consistency 2025-06-04 16:58:08 +08:00
jyong edec654b68 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-04 16:51:52 +08:00
jyong a82ab1d152 r2 2025-06-04 16:51:23 +08:00
twwu 9934eac15c refactor: refactor data source handling and add form for document processing 2025-06-04 16:50:27 +08:00
Joel c155afac29 chore: rename rag var spell errro 2025-06-04 16:43:24 +08:00
Joel 7080c9f279 fix: show rag vars names 2025-06-04 16:29:36 +08:00
jyong e41699cbc8 Merge branch 'feat/r2' into deploy/rag-dev 2025-06-04 16:23:34 +08:00
jyong 133193e7d0 r2 2025-06-04 16:23:12 +08:00
zxhlyh 9d6371e0a3 Merge branch 'feat/rag-pipeline' into deploy/rag-dev 2025-06-04 15:48:58 +08:00
zxhlyh dfe091789c datasource 2025-06-04 15:48:29 +08:00
zxhlyh 4c9bf78363 knowledge base node checklist 2025-06-04 15:18:03 +08:00
JyongandGitHub b95ecaf8a3 Update build-push.yml 2025-06-04 15:17:39 +08:00
jyong 7a0e8108ae Merge branch 'feat/r2' into deploy/rag-dev 2025-06-04 15:16:47 +08:00
twwu 3afd5e73c9 feat: enhance input field dialog with preview functionality and global inputs 2025-06-04 15:16:02 +08:00
jyong c09c8c6e5b r2 2025-06-04 15:12:05 +08:00
Joel cab491795a chore: some special to some fns 2025-06-04 14:54:11 +08:00
twwu e290ddc3e5 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-06-04 14:50:16 +08:00
twwu db154e33b7 Merge branch 'main' into feat/rag-pipeline 2025-06-04 14:48:10 +08:00
zxhlyh 32f9004b5f merge feat/rag-pipeline 2025-06-04 11:43:38 +08:00
zxhlyh 225402280e datasource auth 2025-06-04 11:39:31 +08:00
jyong abcca11479 r2 2025-06-03 19:10:40 +08:00
jyong 9cdd2cbb27 r2 2025-06-03 19:02:57 +08:00
jyong 309fffd1e4 Merge branch 'main' into feat/r2
# Conflicts:
#	api/core/repositories/sqlalchemy_workflow_node_execution_repository.py
#	api/core/workflow/entities/node_entities.py
#	api/core/workflow/enums.py
2025-06-03 18:56:49 +08:00
twwu 0a9f50e85f Merge branch 'main' into feat/rag-pipeline 2025-06-03 18:44:53 +08:00
twwu ed1d71f4d0 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-06-03 18:33:07 +08:00
twwu 7039ec33b9 refactor: update retrieval search method from invertedIndex to keywordSearch 2025-06-03 18:33:01 +08:00
Joel 025dc7c781 feat: can show rag vars 2025-06-03 18:32:52 +08:00
jyong 4130c50643 r2 2025-06-03 18:32:39 +08:00
jyong 7b7f8ef51d r2 2025-06-03 18:12:24 +08:00
twwu bad451d5ec Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-06-03 17:42:53 +08:00
twwu 87c15062e6 feat: enhance document processing with embedding and rule detail components 2025-06-03 17:42:40 +08:00
jyong 573cd15e77 r2 2025-06-03 16:52:21 +08:00
jyong ab1730bbaa r2 2025-06-03 16:51:21 +08:00
zxhlyh 163bae3aaf input rag variable 2025-06-03 16:07:58 +08:00
jyong 270edd43ab r2 2025-06-03 15:53:17 +08:00
jyong b8f3b23b1a r2 2025-06-03 15:51:31 +08:00
zxhlyh b9c6496fea datasource default value & publish sync draft 2025-06-03 14:42:17 +08:00
jyong 0486aa3445 r2 2025-06-03 13:30:51 +08:00
twwu 5fb771218c fix: update types and improve data handling in pipeline components 2025-06-03 10:14:48 +08:00
jyong 3fb02a7933 r2 2025-05-30 17:28:09 +08:00
twwu 898495b5c4 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-05-30 15:54:46 +08:00
twwu 08624878cf fix: update ChunkStructureEnum values for consistency with model naming 2025-05-30 15:53:32 +08:00
zxhlyh 6fe473f0fa knowledge base node 2025-05-30 15:45:58 +08:00
jyong 11cf23e5fc Merge remote-tracking branch 'origin/feat/r2' into feat/r2 2025-05-30 15:42:56 +08:00
jyong 631768ea1d r2 2025-05-30 15:42:36 +08:00
JyongandGitHub e1d658b482 Update build-push.yml 2025-05-30 15:26:51 +08:00
twwu 1274aaed5d fix: add dataset mutation context to Popup component 2025-05-30 15:17:19 +08:00
twwu 9be036e0ca Merge branch 'main' into feat/rag-pipeline 2025-05-30 15:10:16 +08:00
JyongandGitHub 7284569c5f Update build-push.yml 2025-05-30 01:02:33 +08:00
jyong 976b465e76 r2 2025-05-30 00:55:06 +08:00
jyong 804e55824d r2 2025-05-30 00:37:36 +08:00
jyong 69529fb16d r2 2025-05-30 00:37:27 +08:00
jyong cb5cfb2dae r2 2025-05-30 00:03:43 +08:00
jyong a826879cf7 Merge branch 'main' into feat/r2 2025-05-29 23:04:38 +08:00
jyong e7c48c0b69 r2 2025-05-29 23:04:04 +08:00
zxhlyh 558a280fc8 datasource type 2025-05-29 18:21:29 +08:00
twwu 2158c03231 fix: update button disabled state to reflect publishedAt status in Popup component 2025-05-29 17:53:08 +08:00
twwu a61f1f8eb0 refactor: replace anchor tag with Link component for navigation in Actions 2025-05-29 17:42:00 +08:00
twwu 9f724c19db refactor: refactor navigation components to use Link for improved routing 2025-05-29 17:33:04 +08:00
twwu 4ae936b263 refactor: refactor navigation handling in dataset components to use button elements 2025-05-29 15:48:54 +08:00
twwu 80875a109a feat: add logic to handle navigation based on pipeline status in DatasetCard 2025-05-29 15:22:29 +08:00
zxhlyh 121e54f3e3 plugins page 2025-05-29 15:18:27 +08:00
zxhlyh 1c2c4b62f8 run & tracing 2025-05-29 14:31:35 +08:00
twwu 9176790adf feat: enhance dataset detail layout with button disable logic based on pipeline status 2025-05-29 14:06:12 +08:00
zxhlyh 6ff6525d1d test run 2025-05-29 11:30:42 +08:00
zxhlyh 71ce505631 data source panel 2025-05-29 11:03:22 +08:00
twwu 11dfe3713f refactor: enhance document upload flow with step indicators and file preview handling 2025-05-29 10:18:11 +08:00
jyong a025db137d Merge branch 'main' into feat/r2 2025-05-29 09:54:28 +08:00
jyong 797d044714 r2 2025-05-29 09:53:42 +08:00
zxhlyh c4169f8aa0 Merge branch 'main' into feat/rag-pipeline 2025-05-29 09:39:36 +08:00
twwu 3005419573 feat: implement document upload steps and enhance test run panel with new hooks and components 2025-05-28 18:34:26 +08:00
jyong 7f59ffe7af r2 2025-05-28 17:56:04 +08:00
twwu cc7ad5ac97 feat: add input field variables change sync 2025-05-28 16:38:49 +08:00
zxhlyh 769b5e185a workflow init config staletime 2025-05-28 15:36:10 +08:00
twwu 9e763c9e87 feat: enhance file uploader and test run panel with batch upload limits and tooltips 2025-05-28 14:51:10 +08:00
zxhlyh b9214ca76b knowledge base default data 2025-05-28 13:57:24 +08:00
twwu 29d2f2339b refactor: enhance document preview functionality and refactor form handling 2025-05-28 13:44:37 +08:00
zxhlyh 5ac1e3584d Merge branch 'main' into feat/rag-pipeline 2025-05-28 11:01:56 +08:00
twwu dd0cf6fadc refactor: streamline data source type handling and improve FieldList props 2025-05-28 10:07:12 +08:00
zxhlyh b320ebe2ba datasource variables 2025-05-27 18:44:29 +08:00
twwu 377093b776 fix: conditionally render FieldListContainer based on inputFields length 2025-05-27 18:19:10 +08:00
twwu 70119a054a fix: add is_preview flag to datasource submission and improve dataset card rendering logic 2025-05-27 17:54:39 +08:00
zxhlyh 69d1e3ec7d input field in datasource 2025-05-27 17:42:30 +08:00
twwu 365157c37d refactor: enhance action button logic to include workflow running state 2025-05-27 15:43:10 +08:00
zxhlyh 4bc0a1bd37 knowledge base node init 2025-05-27 15:28:35 +08:00
twwu d6640f2adf refactor: streamline input field data conversion and enhance datasource component 2025-05-27 15:25:35 +08:00
twwu 987f845e79 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-05-27 14:42:12 +08:00
zxhlyh 84daf49047 node meta data 2025-05-27 14:40:56 +08:00
twwu 31e183ef0d refactor: enhance datasource handling by adding fileExtensions support 2025-05-27 14:39:52 +08:00
twwu 754a1d1197 refactor: add DatasourceIcon component and update related hooks and options 2025-05-27 14:17:55 +08:00
twwu 049a6de4b3 refactor: update data source handling and replace icon implementation 2025-05-27 13:52:43 +08:00
zxhlyh 6bd28cadc4 datasource icon 2025-05-27 13:42:13 +08:00
zxhlyh 3b9a0b1d25 datasource icon 2025-05-27 11:27:25 +08:00
twwu db963a638c Merge branch 'main' into feat/rag-pipeline 2025-05-27 11:03:49 +08:00
twwu dcb4c9e84a refactor: refactor datasource type handling 2025-05-27 11:01:38 +08:00
jyong 5fc2bc58a9 r2 2025-05-27 00:01:23 +08:00
twwu d333645e09 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-05-26 17:48:59 +08:00
twwu 2812c774c6 fix(i18n): Update economy index method description to include keyword count 2025-05-26 17:48:54 +08:00
zxhlyh e2f3f0ae4c datasource 2025-05-26 17:47:03 +08:00
Yeuoly 83ca7f8deb feat: add datasource support to PluginDeclaration and PluginCategory 2025-05-26 17:32:25 +08:00
zxhlyh e6c6fa8ed8 tool icon 2025-05-26 17:28:16 +08:00
jyong 678d6ffe2b r2 2025-05-26 17:00:16 +08:00
zxhlyh cef77a3717 datasource icon 2025-05-26 16:41:50 +08:00
zxhlyh 28726b6cf3 block selector 2025-05-26 16:33:08 +08:00
jyong ef0e41de07 r2 2025-05-26 16:02:11 +08:00
zxhlyh dc2b63b832 Merge branch 'main' into feat/rag-pipeline 2025-05-26 15:58:15 +08:00
zxhlyh 0478fc9649 datasource node variable 2025-05-26 15:57:34 +08:00
jyong 1b07e612d2 r2 2025-05-26 15:49:37 +08:00
jyong 38cce3f62a r2 2025-05-26 14:52:09 +08:00
jyong 35be8721b9 Merge branch 'main' into feat/r2 2025-05-26 14:50:33 +08:00
jyong 665ffbdc10 r2 2025-05-26 14:49:59 +08:00
zxhlyh b5f88c77a3 datasource list 2025-05-26 14:13:59 +08:00
twwu 324c0d7b4c refactor: improve layout and styling in TestRunPanel and FilePreview components 2025-05-26 14:06:04 +08:00
twwu 13e3f17493 refactor: standardize terminology by renaming 'data-source' to 'datasource' across components and translations 2025-05-26 10:50:39 +08:00
twwu 841bd35ebb Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-05-26 09:49:15 +08:00
twwu ccefd41606 refactor: rename InputType to InputTypeEnum and update related usages for consistency 2025-05-26 09:48:17 +08:00
jyong ec1c4efca9 r2 2025-05-25 23:09:01 +08:00
jyong 0f10852b6b Merge remote-tracking branch 'origin/feat/r2' into feat/r2 2025-05-23 19:30:59 +08:00
jyong 6d547447d3 r2 2025-05-23 19:30:48 +08:00
Yeuoly 6123f1ab21 refactor: reorganize imports and fix datasource endpoint URL 2025-05-23 19:22:50 +08:00
zxhlyh e7370766bd datasource 2025-05-23 18:19:28 +08:00
twwu db4958be05 fix: fix modal handling in InputFieldEditor 2025-05-23 17:52:00 +08:00
Yeuoly a15bf8e8fe remove output schema 2025-05-23 17:35:26 +08:00
jyong 70d2c78176 r2 2025-05-23 17:13:09 +08:00
jyong 42fcda3dc8 r2 2025-05-23 17:11:56 +08:00
twwu ac049d938e Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-05-23 16:57:46 +08:00
twwu 3af61f4b5d refactor: update input type mappings and enums for consistency across components 2025-05-23 16:57:27 +08:00
zxhlyh e19adbbbc5 datasource 2025-05-23 16:27:49 +08:00
jyong 64d997fdb0 r2 2025-05-23 15:55:41 +08:00
Yeuoly a49942b949 fix: rename first_step_parameters 2025-05-23 15:12:31 +08:00
Yeuoly 4460d96e58 feat: add oauth schema 2025-05-23 15:11:40 +08:00
Yeuoly a7d5f2f53b apply ruff 2025-05-23 15:10:56 +08:00
twwu c9bf99a1e2 refactor: update input variable types and initial data handling in pipeline components 2025-05-23 15:10:20 +08:00
Yeuoly 4300ebc8aa fix: remove provide type 2025-05-23 15:10:16 +08:00
zxhlyh 720ce79901 checklist & datasource icon 2025-05-23 14:26:06 +08:00
twwu 693107a6c8 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-05-23 13:54:59 +08:00
twwu 583db24ee7 refactor: update CustomActions type to use structured props across form components 2025-05-23 13:54:49 +08:00
zxhlyh 7d92574e02 datasource panel 2025-05-23 11:51:17 +08:00
twwu 5aaa06c8b0 refactor: integrate routing for document creation in Popup component 2025-05-23 11:19:57 +08:00
twwu 52b773770b refactor: update datasource handling in InputFieldDialog and Datasource components 2025-05-23 11:07:48 +08:00
zxhlyh 23adc7d8a8 datasource 2025-05-23 10:47:31 +08:00
twwu e3708bfa85 refactor: enhance ChunkPreview with form handling and preview functionality 2025-05-23 10:29:59 +08:00
twwu 7d65e9980c Merge branch 'main' into feat/rag-pipeline 2025-05-23 09:35:08 +08:00
jyong b93d26ee9f Merge remote-tracking branch 'origin/feat/r2' into feat/r2
# Conflicts:
#	api/core/datasource/entities/datasource_entities.py
2025-05-23 00:06:51 +08:00
jyong b82b26bba5 r2 2025-05-23 00:05:57 +08:00
twwu 21c24977d8 refactor: enhance document processing UI and functionality with new components and translations 2025-05-22 23:05:58 +08:00
zxhlyh fe435c23c3 i18n 2025-05-22 17:44:07 +08:00
twwu ead1209f98 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-05-22 17:41:18 +08:00
twwu 3994bb1771 refactor: refactor document processing components and update translations 2025-05-22 17:39:39 +08:00
zxhlyh 327690e4a7 merge main 2025-05-22 16:45:13 +08:00
zxhlyh c2a7e0e986 version panel 2025-05-22 16:43:30 +08:00
twwu faf6b9ea03 refactor: refactor preview components 2025-05-22 14:49:40 +08:00
Yeuoly 3bfc602561 refactor: update datasource entity structure and parameter handling
- Renamed and split parameters in DatasourceEntity into first_step_parameters and second_step_parameters.
- Updated validation methods for new parameter structure.
- Adjusted datasource_node to reference first_step_parameters.
- Cleaned up unused imports and improved type hints in workflow.py.
2025-05-21 20:36:26 +08:00
Yeuoly 5fa2aca2c8 feat: add oauth schema to datasource 2025-05-21 20:29:59 +08:00
twwu 69a60101fe Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-05-21 16:37:08 +08:00
twwu b18519b824 refactor: add create-from-pipeline page and associated components for document processing 2025-05-21 16:37:02 +08:00
zxhlyh 0d01025254 parallel check 2025-05-21 16:34:41 +08:00
zxhlyh eef1542cb3 use available nodes 2025-05-21 15:51:05 +08:00
twwu 9aef4b6d6b refactor: Notion component and add NotionPageSelector for improved page selection 2025-05-21 14:02:37 +08:00
zxhlyh 7dba83754f Merge branch 'main' into feat/rag-pipeline 2025-05-21 13:42:28 +08:00
zxhlyh e2585bc778 Merge branch 'main' into feat/rag-pipeline 2025-05-21 11:27:50 +08:00
twwu cc6e2558ef Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-05-21 10:53:29 +08:00
twwu 20343facad refactor: website data source components and hooks 2025-05-21 10:53:18 +08:00
zxhlyh eff123a11c checklist 2025-05-20 16:52:45 +08:00
jyong 9bafd3a226 r2 2025-05-20 15:41:10 +08:00
jyong 82be119fec Merge branch 'main' into feat/r2 2025-05-20 15:18:52 +08:00
jyong a64df507f6 r2 2025-05-20 15:18:33 +08:00
twwu cf73faf174 feat: add FileUploaderField and TextAreaField components; enhance BaseField to support file inputs 2025-05-20 15:09:30 +08:00
jyong ba52bf27c1 r2 2025-05-20 14:57:26 +08:00
zxhlyh 55f4177b01 merge main 2025-05-20 14:03:54 +08:00
twwu 14a9052d60 refactor: update variable naming for consistency and improve data source handling in pipeline components 2025-05-20 11:42:22 +08:00
twwu 314a2f9be8 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-05-19 18:21:29 +08:00
twwu 8eee344fbb fix: correct hover state logic and refactor environment variable handling in FieldItem and usePipelineInit 2025-05-19 18:21:17 +08:00
zxhlyh 0e0a266142 merge main 2025-05-19 18:11:45 +08:00
zxhlyh 7bce35913d i18n 2025-05-19 18:09:12 +08:00
twwu 7898dbd5bf Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-05-19 16:26:24 +08:00
twwu bd1073ff1a refactor: update input variable types to use PipelineInputVarType and simplify form data handling 2025-05-19 16:26:13 +08:00
zxhlyh 1bbd572593 option card 2025-05-19 15:59:04 +08:00
zxhlyh 5199297f61 run and history 2025-05-19 14:23:40 +08:00
Yeuoly c5a2f43ceb refactor: replace BuiltinToolManageService with RagPipelineManageService for datasource management and remove unused datasource engine and related code 2025-05-16 18:42:07 +08:00
twwu 8d4ced227e fix: update click handler logic in OptionCard 2025-05-16 17:54:41 +08:00
zxhlyh f481075f8f pipeline sync draft 2025-05-16 17:48:01 +08:00
zxhlyh 836cf6453e pipeline sync draft 2025-05-16 17:48:01 +08:00
jyong 8bea88c8cc r2 2025-05-16 17:22:17 +08:00
twwu 4b7274f9a5 fix: update link in Form component and correct endpoint for related apps query 2025-05-16 16:49:43 +08:00
twwu 7de5585da6 refactor: replace SWR with custom hooks for dataset detail and related apps; update context usage in components 2025-05-16 16:32:25 +08:00
twwu 87dc80f6fa fix: add cursor pointer and hover effect to MemberItem; adjust padding in PermissionItem 2025-05-16 15:52:28 +08:00
twwu a008c04331 refactor: standardize naming for load more handlers and navigation items across components 2025-05-16 15:43:28 +08:00
twwu 56b66b8a57 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-05-16 15:15:00 +08:00
twwu 35a7add4e9 refactor: refactor pipeline-related components and services to use template terminology 2025-05-16 15:14:50 +08:00
zxhlyh f1fe143962 add i18n 2025-05-16 14:53:39 +08:00
jyong 9e72afee3c r2 2025-05-16 14:00:35 +08:00
jyong 613b94a6e6 r2 2025-05-16 13:45:47 +08:00
jyong 7b0d38f7d3 r2 2025-05-16 12:02:35 +08:00
jyong 4ff971c8a3 r2 2025-05-16 11:26:56 +08:00
twwu 019ef74bf2 refactor: replace Container with List, update DatasetCard z-index, and implement useDatasetList for data fetching 2025-05-16 10:50:31 +08:00
zxhlyh 2670557258 merge main 2025-05-16 10:09:24 +08:00
jyong 93ac6d37e9 r2 2025-05-15 16:44:55 +08:00
jyong e710a8402c r2 2025-05-15 16:07:17 +08:00
jyong 360f8a3375 Merge branch 'main' into feat/r2 2025-05-15 15:15:23 +08:00
jyong 818eb46a8b r2 2025-05-15 15:14:52 +08:00
zxhlyh f5c297708b Merge branch 'main' into feat/rag-pipeline 2025-05-15 14:52:54 +08:00
zxhlyh bf8324f7f7 tag filter 2025-05-15 14:52:00 +08:00
zxhlyh b730d153ea Merge branch 'main' into feat/rag-pipeline 2025-05-15 10:27:47 +08:00
zxhlyh 11977596c9 merge main 2025-05-15 10:14:40 +08:00
twwu 612dca8b7d feat: add WorkflowPreview component to Details and define graph structure in PipelineTemplateByIdResponse 2025-05-14 18:20:29 +08:00
zxhlyh 53018289d4 workflow preview 2025-05-14 18:02:58 +08:00
twwu 958ff44707 refactor: simplify import DSL confirmation request structure 2025-05-14 16:27:59 +08:00
twwu d910770b3c feat: add dataset_id to DSL import responses and update routing logic in CreateFromDSLModal 2025-05-14 16:00:17 +08:00
twwu 5a8f10520f feat: refactor template card actions and details to standardize prop names; add create modal for dataset creation 2025-05-14 15:53:17 +08:00
twwu df928772c0 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-05-14 14:49:10 +08:00
twwu b713218cab feat: add DSL modal header and tab components; enhance pipeline import functionality 2025-05-14 14:49:01 +08:00
zxhlyh 9ea2123e7f component add readonly 2025-05-14 11:14:49 +08:00
twwu de0cb06f8c feat: implement create dataset pipeline forms and modals 2025-05-14 10:48:54 +08:00
twwu cfb6d59513 Merge branch 'main' into feat/rag-pipeline 2025-05-13 18:38:26 +08:00
twwu 4c30d1c1eb feat: Enhance InputFieldDialog and workflow hooks to handle ragPipelineVariables 2025-05-13 16:33:38 +08:00
twwu 5bb02c79cc Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-05-13 16:18:07 +08:00
twwu 0a891e5392 feat: Update retrieval method configuration to use new OptionCard component and improve layout 2025-05-13 16:17:59 +08:00
zxhlyh f6978ce6b1 fix: pipeline init 2025-05-13 16:02:36 +08:00
twwu 4d68aadc1c Refactor: Replace IndexMethodRadio with IndexMethod component, add keyword number functionality, and update related translations 2025-05-13 15:35:21 +08:00
twwu cef6463847 feat: Enhance dataset settings with chunk structure and icon selection 2025-05-13 11:07:31 +08:00
zxhlyh 39b8331f81 merge main 2025-05-09 18:20:56 +08:00
twwu 212d4c5899 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-05-09 16:35:14 +08:00
twwu 97ec855df4 feat: enhance input field management with internationalization support and improved state handling 2025-05-09 16:35:09 +08:00
zxhlyh d83b9b70e3 fix: import 2025-05-09 16:25:34 +08:00
zxhlyh b51c18c2cf pipeline init 2025-05-09 15:53:31 +08:00
twwu 7e31da7882 refactor: update data source handling and improve internationalization support in test run panel 2025-05-09 12:56:57 +08:00
twwu d9ed61287d Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-05-08 18:29:58 +08:00
twwu 6024dbe98d refactor: simplify type definitions in form components and update related configurations 2025-05-08 18:29:49 +08:00
zxhlyh 13ce6317f1 pipeline header 2025-05-08 18:27:44 +08:00
twwu 0099f2296d Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-05-08 16:26:37 +08:00
twwu 2d93bc6725 refactor: update DatasetInfo component layout and styling for better responsiveness 2025-05-08 16:26:30 +08:00
zxhlyh cb52f9ecc5 pipeline header 2025-05-08 15:32:19 +08:00
twwu 1fbeb3a21a refactor: enhance dataset components with new icons and improve layout structure 2025-05-08 13:48:14 +08:00
twwu 38f1a42ce8 refactor: remove unused icon components and update imports in dataset components 2025-05-08 11:15:27 +08:00
twwu 3d11af2dd6 refactor: update imports for knowledge and pipeline components 2025-05-08 10:44:26 +08:00
twwu d1fd5db7f8 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-05-08 09:52:53 +08:00
twwu c240cf3bb1 refactor: dataset creation to support pipeline datasets, update related types and hooks 2025-05-08 09:42:02 +08:00
zxhlyh bbbcd68258 portal element 2025-05-07 18:14:26 +08:00
twwu 7ce9710229 feat: add pipeline template details and import functionality, enhance dataset pipeline management 2025-05-07 18:09:38 +08:00
zxhlyh 3f7f21ce70 show test run panel 2025-05-07 17:31:06 +08:00
zxhlyh fa8ab4ea04 rag pipeline 2025-05-07 16:30:24 +08:00
jyong 3f1363503b r2 2025-05-07 16:19:09 +08:00
zxhlyh 3f52f491d7 feat: knowledge base node 2025-05-07 15:08:37 +08:00
twwu e86a3fc672 feat: Enhance dataset pipeline creation and management with new export and delete functionalities, improved internationalization, and refactor for better clarity 2025-05-07 14:29:01 +08:00
twwu 6f77f67427 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-05-07 11:30:20 +08:00
twwu 4025cd0b46 feat: Refactor dataset pipeline creation components and add internationalization support 2025-05-07 11:30:13 +08:00
zxhlyh 3bbb22750c merge main 2025-05-06 18:28:44 +08:00
zxhlyh d196872059 merge main 2025-05-06 17:31:48 +08:00
zxhlyh a478d95950 feat: knowledge base node 2025-05-06 17:25:18 +08:00
twwu 12c060b795 feat: enhance dataset icon handling by making icon background and URL optional 2025-05-06 16:58:37 +08:00
twwu c480c3d881 feat: enhance dataset detail layout with new icon structure and additional document count display 2025-05-06 16:37:21 +08:00
jyong a998022c12 r2 2025-05-06 16:18:34 +08:00
jyong a25cc4e8af r2 2025-05-06 13:56:13 +08:00
twwu b4bccf5fef feat: Add External Knowledge Base and Pipeline icons, update DatasetCard component 2025-05-06 11:58:53 +08:00
twwu 14ad34af71 feat: enhance dataset creation UI with new pipeline list and edit functionality 2025-05-03 17:16:00 +08:00
twwu 7ed398267f Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-05-03 13:43:43 +08:00
twwu fc9556e057 feat: add dataset creation components and functionality 2025-05-03 13:43:37 +08:00
zxhlyh acf6872a50 fix: variable selector 2025-04-30 16:55:00 +08:00
twwu e689f21a60 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-04-30 14:16:25 +08:00
twwu a7f9259e27 feat: new Dataset list 2025-04-30 14:16:13 +08:00
zxhlyh a46b4e3616 Merge branch 'main' into feat/rag-pipeline 2025-04-29 16:27:49 +08:00
zxhlyh e7e12c1d2e fix: node selector 2025-04-29 16:26:53 +08:00
zxhlyh 66176c4d71 fix: node default 2025-04-29 16:14:20 +08:00
twwu 2613a380b6 fix: Correct link path for creating datasets and optimize Link component with memoization 2025-04-29 15:47:29 +08:00
twwu 9392ce259f feat: Refactor dataset components and update translations for new dataset creation options 2025-04-29 15:44:32 +08:00
twwu d1287f08b4 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-04-29 10:44:37 +08:00
twwu 7ee8472a5f feat: Add SegmentedControl component with styling and option handling 2025-04-29 10:44:03 +08:00
zxhlyh cdb615deeb knowledge base node 2025-04-28 18:37:18 +08:00
zxhlyh abbba1d004 knowledge base node 2025-04-28 18:37:17 +08:00
jyong 3c386c63a6 Merge remote-tracking branch 'origin/feat/r2' into feat/r2 2025-04-28 16:19:29 +08:00
jyong 49d1846e63 r2 2025-04-28 16:19:12 +08:00
twwu 53f2882077 feat: Implement document processing component with configuration and action handling 2025-04-28 15:55:24 +08:00
twwu 8f07e088f5 feat: Add JinaReader and WaterCrawl components with configurations and schema handling 2025-04-28 14:33:01 +08:00
twwu f71b0eccb2 Refactor: dataset creation components and implement Firecrawl functionality 2025-04-28 13:33:16 +08:00
twwu 5b89d36ea1 feat: Update Zod schema generation for file types and upload methods to use new constants 2025-04-27 20:44:05 +08:00
twwu 7c3af74b0d feat: Update useConfigurations and useHiddenConfigurations to use InputVarType constants for type values 2025-04-27 20:34:25 +08:00
twwu d1d83f8a2a feat: Enhance form components with hidden fields and popup properties for improved configuration 2025-04-27 20:17:50 +08:00
twwu 839fe12087 feat: Update OptionsField to use correct Options type and enhance Zod schema generation for options and select input types 2025-04-27 18:45:22 +08:00
twwu fd8ee9f53e Refactor input field form components and schema 2025-04-27 15:29:11 +08:00
Yeuoly c2d02f8f4d Merge branch 'main' into feat/r2 2025-04-27 14:31:19 +08:00
twwu 8367ae85de feat: Replace BaseVarType with BaseFieldType for consistent field type usage across components 2025-04-27 10:16:16 +08:00
twwu d1f0e6e5c2 feat: Implement Zod schema generation for form validation and update form component usage 2025-04-27 09:56:48 +08:00
twwu 7deb44f864 feat: Add additional field components to form hook for enhanced functionality 2025-04-26 22:43:51 +08:00
twwu d12e9b81e3 feat: Introduce new form field components and enhance existing ones with label options 2025-04-26 21:50:21 +08:00
twwu b1fbaaed95 refactor: Simplify type checks for form field rendering and correct comment grammar 2025-04-25 18:39:05 +08:00
twwu 3f8b0b937c Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-04-25 18:13:57 +08:00
twwu 734c62998f feat: Implement dynamic form field rendering and replace SubmitButton with Actions component 2025-04-25 18:13:52 +08:00
zxhlyh 4792ca1813 knowledge base node 2025-04-25 17:24:47 +08:00
jyong d4007ae073 r2 2025-04-25 15:49:36 +08:00
jyong 389f15f8e3 r2 2025-04-25 14:56:22 +08:00
jyong 9437145218 r2 2025-04-25 13:42:57 +08:00
zxhlyh 076924bbd6 rag pipeline main 2025-04-25 11:32:17 +08:00
zxhlyh 97cf6b2d65 refactor workflow 2025-04-25 11:04:14 +08:00
twwu f317ef2fe2 feat: Refactor NotionConnector integration and add Header component for improved UI in NotionPageSelector 2025-04-24 21:26:54 +08:00
zxhlyh f7de55364f chore: refactor workflow 2025-04-24 16:29:58 +08:00
twwu de30e9278c feat: Refactor Notion and LocalFile components to remove unused VectorSpaceFull prop and improve step indicator logic 2025-04-24 15:47:22 +08:00
jyong b9ab1555fb r2 2025-04-24 15:42:30 +08:00
twwu 44b9ce0951 feat: Implement Notion connector and related components for data source selection in the RAG pipeline 2025-04-24 15:32:04 +08:00
twwu d768094376 feat: Refactor file upload configuration and validation logic 2025-04-24 13:46:50 +08:00
twwu 93f83086c1 feat: add CustomSelectField component and integrate with input field form 2025-04-23 22:16:19 +08:00
zxhlyh 8d9c252811 block selector & data source node 2025-04-22 16:46:33 +08:00
jyong c7f4b41920 r2 2025-04-22 16:08:58 +08:00
twwu efb27eb443 feat: enhance FieldList component with sorting and dynamic input field management 2025-04-22 12:56:22 +08:00
twwu 5b8c43052e feat: implement input field dialog and related components for rag pipeline 2025-04-22 11:29:03 +08:00
twwu e04ae927b6 Merge branch 'main' into feat/rag-pipeline 2025-04-22 10:14:28 +08:00
twwu ac68d62d1c Merge branch 'main' into feat/rag-pipeline 2025-04-21 18:07:15 +08:00
zxhlyh caa17b8fe9 rag pipeline store 2025-04-21 17:52:34 +08:00
twwu cd1562ee24 Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline 2025-04-21 16:58:28 +08:00
twwu 47af1a9c42 feat: add InputField component and integrate into RagPipeline panel 2025-04-21 16:58:22 +08:00
zxhlyh 0cd6a427af add publisher 2025-04-21 14:41:41 +08:00
twwu 51165408ed feat: implement input field form with file upload settings and validation 2025-04-21 09:53:35 +08:00
zxhlyh a2dc38f90a feat: add rag pipeline store slice 2025-04-18 15:51:40 +08:00
zxhlyh a36436b585 feat: add rag pipeline store slice 2025-04-18 15:46:54 +08:00
zxhlyh 2d87823fc6 init rag pipeline 2025-04-18 14:56:34 +08:00
zxhlyh d238da9826 Merge branch 'main' into feat/rag-pipeline 2025-04-18 14:00:58 +08:00
twwu 6eef5990c9 feat: enhance form components with additional props for validation and tooltips; add OptionsField component 2025-04-18 11:32:23 +08:00
jyong 5c4bf2a9e4 r2 2025-04-17 15:07:23 +08:00
twwu 0345eb4659 feat: add new form components including CheckboxField, NumberInputField, SelectField, TextField, and SubmitButton with updated input sizes 2025-04-17 13:33:33 +08:00
twwu 71f78e0d33 feat: replace existing page content with DemoForm component for improved layout 2025-04-16 14:16:56 +08:00
twwu 942648e9e9 feat: implement form components including CheckboxField, SelectField, TextField, and SubmitButton with validation 2025-04-16 14:16:32 +08:00
twwu d841581679 feat: add IndeterminateIcon component and update Checkbox to support indeterminate state
refactor: remove mixed state handling and update related styles
fix: update useCallback dependencies for better performance
2025-04-15 17:30:18 +08:00
jyong 9f8e05d9f0 r2 2025-04-14 18:17:17 +08:00
jyong 3340775052 r2 2025-04-14 11:10:44 +08:00
jyong 9987774471 r2 2025-04-10 18:00:22 +08:00
14421 changed files with 463820 additions and 2137684 deletions
@@ -1,40 +0,0 @@
---
name: backend-code-review
description: Use only when the user explicitly requests a review or audit of backend code under `api/`. Supports pending-change, file-focused, and pasted-diff reviews. Do not use for implementation-only requests, diagnosis without review intent, frontend code, or backend code outside `api/`.
---
# Backend Code Review
Review the requested scope for concrete, reproducible defects. The nearest `AGENTS.md` owns package facts and commands; this skill owns the review workflow and routes to its bundled rule packs.
## Evidence First
1. Establish the requested review scope and inspect the relevant diff or files.
2. Read the changed lines, their behavior owner, nearby tests, and local docstrings or comments that define contracts.
3. Trace callers, persistence boundaries, authorization, generated schemas, or external I/O only when they decide correctness.
4. Report only findings tied to an observable failure, violated contract, security boundary, data integrity risk, or demonstrated maintenance problem.
## Rule Routing
Read only the packs matched by the diff:
- Models or migrations: [`references/db-schema-rule.md`][db-schema]
- Controller, service, core/domain, library, or model dependency direction: [`references/architecture-rule.md`][architecture]
- Table access outside an established repository boundary: [`references/repositories-rule.md`][repositories]
- SQLAlchemy sessions, queries, transactions, CRUD, concurrency, or raw SQL: [`references/sqlalchemy-rule.md`][sqlalchemy]
When no pack applies, review correctness, security, behavior changes, and test evidence directly. Check current official documentation only when local code and contracts do not settle framework or library behavior.
## Severity And Output
- **P0**: security or privacy exposure, data loss, or a production-wide outage.
- **P1**: user-visible regression, broken authorization or tenant isolation, invalid public contract, or failed primary workflow.
- **P2**: concrete correctness, performance, maintainability, or test defect likely to cause incorrect behavior.
- **P3**: minor actionable cleanup; omit unless the user requested a thorough audit.
Lead with findings ordered by severity. Include a tight file and line reference, the failing contract or reproduction path, impact, and a concrete fix direction. If there are no findings, say `No issues found.` and state any material verification gap. Do not add praise sections, speculative risks, or an unsolicited offer to implement fixes.
[architecture]: references/architecture-rule.md
[db-schema]: references/db-schema-rule.md
[repositories]: references/repositories-rule.md
[sqlalchemy]: references/sqlalchemy-rule.md
@@ -1,88 +0,0 @@
# Rule Catalog — Architecture
## Scope
- Covers: controller/service/core-domain/libs/model layering, dependency direction, responsibility placement, observability-friendly flow.
## Rules
### Keep business logic out of controllers
- Category: maintainability
- Description: Controllers should parse input, call services, and return serialized responses. Business decisions inside controllers make behavior hard to reuse and test.
- Suggested fix: Move domain/business logic into the service or core/domain layer. Keep controller handlers thin and orchestration-focused.
- Example:
- Bad:
```python
@bp.post("/apps/<app_id>/publish")
def publish_app(app_id: str):
payload = request.get_json() or {}
if payload.get("force") and current_user.role != "admin":
raise ValueError("only admin can force publish")
app = App.query.get(app_id)
app.status = "published"
db.session.commit()
return {"result": "ok"}
```
- Good:
```python
@bp.post("/apps/<app_id>/publish")
def publish_app(app_id: str):
payload = PublishRequest.model_validate(request.get_json() or {})
app_service.publish_app(app_id=app_id, force=payload.force, actor_id=current_user.id)
return {"result": "ok"}
```
### Preserve layer dependency direction
- Category: best practices
- Description: Controllers may depend on services, and services may depend on core/domain abstractions. Reversing this direction (for example, core importing controller/web modules) creates cycles and leaks transport concerns into domain code.
- Suggested fix: Extract shared contracts into core/domain or service-level modules and make upper layers depend on lower, not the reverse.
- Example:
- Bad:
```python
# core/policy/publish_policy.py
from controllers.console.app import request_context
def can_publish() -> bool:
return request_context.current_user.is_admin
```
- Good:
```python
# core/policy/publish_policy.py
def can_publish(role: str) -> bool:
return role == "admin"
# service layer adapts web/user context to domain input
allowed = can_publish(role=current_user.role)
```
### Keep libs business-agnostic
- Category: maintainability
- Description: Modules under `api/libs/` should remain reusable, business-agnostic building blocks. They must not encode product/domain-specific rules, workflow orchestration, or business decisions.
- Suggested fix:
- If business logic appears in `api/libs/`, extract it into the appropriate `services/` or `core/` module and keep `libs` focused on generic, cross-cutting helpers.
- Keep `libs` dependencies clean: avoid importing service/controller/domain-specific modules into `api/libs/`.
- Example:
- Bad:
```python
# api/libs/conversation_filter.py
from services.conversation_service import ConversationService
def should_archive_conversation(conversation, tenant_id: str) -> bool:
# Domain policy and service dependency are leaking into libs.
service = ConversationService()
if service.has_paid_plan(tenant_id):
return conversation.idle_days > 90
return conversation.idle_days > 30
```
- Good:
```python
# api/libs/datetime_utils.py (business-agnostic helper)
def older_than_days(idle_days: int, threshold_days: int) -> bool:
return idle_days > threshold_days
# services/conversation_service.py (business logic stays in service/core)
from libs.datetime_utils import older_than_days
def should_archive_conversation(conversation, tenant_id: str) -> bool:
threshold_days = 90 if has_paid_plan(tenant_id) else 30
return older_than_days(conversation.idle_days, threshold_days)
```
@@ -1,152 +0,0 @@
# Rule Catalog — DB Schema Design
## Scope
- Covers: model/base inheritance, schema boundaries in model properties, tenant-aware schema design, index redundancy checks, dialect portability in models, and cross-database compatibility in migrations.
- Does NOT cover: session lifecycle, transaction boundaries, and query execution patterns (handled by `sqlalchemy-rule.md`).
## Rules
### Do not query other tables inside `@property`
- Category: [maintainability, performance]
- Description: A model `@property` must not open sessions or query other tables. This hides dependencies across models, tightly couples schema objects to data access, and can cause N+1 query explosions when iterating collections.
- Suggested fix:
- Keep model properties pure and local to already-loaded fields.
- Move cross-table data fetching to service/repository methods.
- For list/batch reads, fetch required related data explicitly (join/preload/bulk query) before rendering derived values.
- Example:
- Bad:
```python
class Conversation(TypeBase):
__tablename__ = "conversations"
@property
def app_name(self) -> str:
with Session(db.engine, expire_on_commit=False) as session:
app = session.execute(select(App).where(App.id == self.app_id)).scalar_one()
return app.name
```
- Good:
```python
class Conversation(TypeBase):
__tablename__ = "conversations"
@property
def display_title(self) -> str:
return self.name or "Untitled"
# Service/repository layer performs explicit batch fetch for related App rows.
```
### Prefer including `tenant_id` in model definitions
- Category: maintainability
- Description: In multi-tenant domains, include `tenant_id` in schema definitions whenever the entity belongs to tenant-owned data. This improves data isolation safety and keeps future partitioning/sharding strategies practical as data volume grows.
- Suggested fix:
- Add a `tenant_id` column and ensure related unique/index constraints include tenant dimension when applicable.
- Propagate `tenant_id` through service/repository contracts to keep access paths tenant-aware.
- Exception: if a table is explicitly designed as non-tenant-scoped global metadata, document that design decision clearly.
- Example:
- Bad:
```python
from sqlalchemy.orm import Mapped
class Dataset(TypeBase):
__tablename__ = "datasets"
id: Mapped[str] = mapped_column(StringUUID, primary_key=True)
name: Mapped[str] = mapped_column(sa.String(255), nullable=False)
```
- Good:
```python
from sqlalchemy.orm import Mapped
class Dataset(TypeBase):
__tablename__ = "datasets"
id: Mapped[str] = mapped_column(StringUUID, primary_key=True)
tenant_id: Mapped[str] = mapped_column(StringUUID, nullable=False, index=True)
name: Mapped[str] = mapped_column(sa.String(255), nullable=False)
```
### Detect and avoid duplicate/redundant indexes
- Category: performance
- Description: Review index definitions for leftmost-prefix redundancy. For example, index `(a, b, c)` can safely cover most lookups for `(a, b)`. Keeping both may increase write overhead and can mislead the optimizer into suboptimal execution plans.
- Suggested fix:
- Before adding an index, compare against existing composite indexes by leftmost-prefix rules.
- Drop or avoid creating redundant prefixes unless there is a proven query-pattern need.
- Apply the same review standard in both model `__table_args__` and migration index DDL.
- Example:
- Bad:
```python
__table_args__ = (
sa.Index("idx_msg_tenant_app", "tenant_id", "app_id"),
sa.Index("idx_msg_tenant_app_created", "tenant_id", "app_id", "created_at"),
)
```
- Good:
```python
__table_args__ = (
# Keep the wider index unless profiling proves a dedicated short index is needed.
sa.Index("idx_msg_tenant_app_created", "tenant_id", "app_id", "created_at"),
)
```
### Avoid PostgreSQL-only dialect usage in models; wrap in `models.types`
- Category: maintainability
- Description: Model/schema definitions should avoid PostgreSQL-only constructs directly in business models. When database-specific behavior is required, encapsulate it in `api/models/types.py` using both PostgreSQL and MySQL dialect implementations, then consume that abstraction from model code.
- Suggested fix:
- Do not directly place dialect-only types/operators in model columns when a portable wrapper can be used.
- Add or extend wrappers in `models.types` (for example, `AdjustedJSON`, `LongText`, `BinaryData`) to normalize behavior across PostgreSQL and MySQL.
- Example:
- Bad:
```python
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import Mapped
class ToolConfig(TypeBase):
__tablename__ = "tool_configs"
config: Mapped[dict] = mapped_column(JSONB, nullable=False)
```
- Good:
```python
from sqlalchemy.orm import Mapped
from models.types import AdjustedJSON
class ToolConfig(TypeBase):
__tablename__ = "tool_configs"
config: Mapped[dict] = mapped_column(AdjustedJSON(), nullable=False)
```
### Guard migration incompatibilities with dialect checks and shared types
- Category: maintainability
- Description: Migration scripts under `api/migrations/versions/` must account for PostgreSQL/MySQL incompatibilities explicitly. For dialect-sensitive DDL or defaults, branch on the active dialect (for example, `conn.dialect.name == "postgresql"`), and prefer reusable compatibility abstractions from `models.types` where applicable.
- Suggested fix:
- In migration upgrades/downgrades, bind connection and branch by dialect for incompatible SQL fragments.
- Reuse `models.types` wrappers in column definitions when that keeps behavior aligned with runtime models.
- Avoid one-dialect-only migration logic unless there is a documented, deliberate compatibility exception.
- Example:
- Bad:
```python
with op.batch_alter_table("dataset_keyword_tables") as batch_op:
batch_op.add_column(
sa.Column(
"data_source_type",
sa.String(255),
server_default=sa.text("'database'::character varying"),
nullable=False,
)
)
```
- Good:
```python
def _is_pg(conn) -> bool:
return conn.dialect.name == "postgresql"
conn = op.get_bind()
default_expr = sa.text("'database'::character varying") if _is_pg(conn) else sa.text("'database'")
with op.batch_alter_table("dataset_keyword_tables") as batch_op:
batch_op.add_column(
sa.Column("data_source_type", sa.String(255), server_default=default_expr, nullable=False)
)
```
@@ -1,60 +0,0 @@
# Rule Catalog - Repositories Abstraction
## Scope
- Covers: when to reuse existing repository abstractions, when to introduce new repositories, and how to preserve dependency direction between service/core and infrastructure implementations.
- Does NOT cover: SQLAlchemy session lifecycle and query-shape specifics (handled by `sqlalchemy-rule.md`), and table schema/migration design (handled by `db-schema-rule.md`).
## Rules
### Introduce repositories abstraction
- Category: maintainability
- Description: If a table/model already has a repository abstraction, all reads/writes/queries for that table should use the existing repository. If no repository exists, introduce one only when complexity justifies it, such as large/high-volume tables, repeated complex query logic, or likely storage-strategy variation.
- Suggested fix:
- First check `api/repositories`, `api/core/repositories`, and `api/extensions/*/repositories/` to verify whether the table/model already has a repository abstraction. If it exists, route all operations through it and add missing repository methods instead of bypassing it with ad-hoc SQLAlchemy access.
- If no repository exists, add one only when complexity warrants it (for example, repeated complex queries, large data domains, or multiple storage strategies), while preserving dependency direction (service/core depends on abstraction; infra provides implementation).
- Example:
- Bad:
```python
# Existing repository is ignored and service uses ad-hoc table queries.
class AppService:
def archive_app(self, app_id: str, tenant_id: str) -> None:
app = self.session.execute(
select(App).where(App.id == app_id, App.tenant_id == tenant_id)
).scalar_one()
app.archived = True
self.session.commit()
```
- Good:
```python
# Case A: Existing repository must be reused for all table operations.
class AppService:
def archive_app(self, app_id: str, tenant_id: str) -> None:
app = self.app_repo.get_by_id(app_id=app_id, tenant_id=tenant_id)
app.archived = True
self.app_repo.save(app)
# If the query is missing, extend the existing abstraction.
active_apps = self.app_repo.list_active_for_tenant(tenant_id=tenant_id)
```
- Bad:
```python
# No repository exists, but large-domain query logic is scattered in service code.
class ConversationService:
def list_recent_for_app(self, app_id: str, tenant_id: str, limit: int) -> list[Conversation]:
...
# many filters/joins/pagination variants duplicated across services
```
- Good:
```python
# Case B: Introduce repository for large/complex domains or storage variation.
class ConversationRepository(Protocol):
def list_recent_for_app(self, app_id: str, tenant_id: str, limit: int) -> list[Conversation]: ...
class SqlAlchemyConversationRepository:
def list_recent_for_app(self, app_id: str, tenant_id: str, limit: int) -> list[Conversation]:
...
class ConversationService:
def __init__(self, conversation_repo: ConversationRepository):
self.conversation_repo = conversation_repo
```
@@ -1,135 +0,0 @@
# Rule Catalog — SQLAlchemy Patterns
## Scope
- Covers: SQLAlchemy session and transaction lifecycle, query construction, tenant scoping, raw SQL boundaries, and write-path concurrency safeguards.
- Does NOT cover: table/model schema and migration design details (handled by `db-schema-rule.md`).
## Rules
### Use Session context manager with explicit transaction control behavior
- Category: best practices
- Description: Session and transaction lifecycle must be explicit and bounded on write paths. Missing commits can silently drop intended updates, while ad-hoc or long-lived transactions increase contention, lock duration, and deadlock risk.
- Suggested fix:
- Use **explicit `session.commit()`** after completing a related write unit.
- Or use **`session.begin()` context manager** for automatic commit/rollback on a scoped block.
- Keep transaction windows short: avoid network I/O, heavy computation, or unrelated work inside the transaction.
- Example:
- Bad:
```python
# Missing commit: write may never be persisted.
with Session(db.engine, expire_on_commit=False) as session:
run = session.get(WorkflowRun, run_id)
run.status = "cancelled"
# Long transaction: external I/O inside a DB transaction.
with Session(db.engine, expire_on_commit=False) as session, session.begin():
run = session.get(WorkflowRun, run_id)
run.status = "cancelled"
call_external_api()
```
- Good:
```python
# Option 1: explicit commit.
with Session(db.engine, expire_on_commit=False) as session:
run = session.get(WorkflowRun, run_id)
run.status = "cancelled"
session.commit()
# Option 2: scoped transaction with automatic commit/rollback.
with Session(db.engine, expire_on_commit=False) as session, session.begin():
run = session.get(WorkflowRun, run_id)
run.status = "cancelled"
# Keep non-DB work outside transaction scope.
call_external_api()
```
### Enforce tenant_id scoping on shared-resource queries
- Category: security
- Description: Reads and writes against shared tables must be scoped by `tenant_id` to prevent cross-tenant data leakage or corruption.
- Suggested fix: Add `tenant_id` predicate to all tenant-owned entity queries and propagate tenant context through service/repository interfaces.
- Example:
- Bad:
```python
stmt = select(Workflow).where(Workflow.id == workflow_id)
workflow = session.execute(stmt).scalar_one_or_none()
```
- Good:
```python
stmt = select(Workflow).where(
Workflow.id == workflow_id,
Workflow.tenant_id == tenant_id,
)
workflow = session.execute(stmt).scalar_one_or_none()
```
### Prefer SQLAlchemy expressions over raw SQL by default
- Category: maintainability
- Description: Raw SQL should be exceptional. ORM/Core expressions are easier to evolve, safer to compose, and more consistent with the codebase.
- Suggested fix: Rewrite straightforward raw SQL into SQLAlchemy `select/update/delete` expressions; keep raw SQL only when required by clear technical constraints.
- Example:
- Bad:
```python
row = session.execute(
text("SELECT * FROM workflows WHERE id = :id AND tenant_id = :tenant_id"),
{"id": workflow_id, "tenant_id": tenant_id},
).first()
```
- Good:
```python
stmt = select(Workflow).where(
Workflow.id == workflow_id,
Workflow.tenant_id == tenant_id,
)
row = session.execute(stmt).scalar_one_or_none()
```
### Protect write paths with concurrency safeguards
- Category: quality
- Description: Multi-writer paths without explicit concurrency control can silently overwrite data. Choose the safeguard based on contention level, lock scope, and throughput cost instead of defaulting to one strategy.
- Suggested fix:
- **Optimistic locking**: Use when contention is usually low and retries are acceptable. Add a version (or updated_at) guard in `WHERE` and treat `rowcount == 0` as a conflict.
- **Redis distributed lock**: Use when the critical section spans multiple steps/processes (or includes non-DB side effects) and you need cross-worker mutual exclusion.
- **SELECT ... FOR UPDATE**: Use when contention is high on the same rows and strict in-transaction serialization is required. Keep transactions short to reduce lock wait/deadlock risk.
- In all cases, scope by `tenant_id` and verify affected row counts for conditional writes.
- Example:
- Bad:
```python
# No tenant scope, no conflict detection, and no lock on a contested write path.
session.execute(update(WorkflowRun).where(WorkflowRun.id == run_id).values(status="cancelled"))
session.commit() # silently overwrites concurrent updates
```
- Good:
```python
# 1) Optimistic lock (low contention, retry on conflict)
result = session.execute(
update(WorkflowRun)
.where(
WorkflowRun.id == run_id,
WorkflowRun.tenant_id == tenant_id,
WorkflowRun.version == expected_version,
)
.values(status="cancelled", version=WorkflowRun.version + 1)
)
if result.rowcount == 0:
raise WorkflowStateConflictError("stale version, retry")
# 2) Redis distributed lock (cross-worker critical section)
lock_name = f"workflow_run_lock:{tenant_id}:{run_id}"
with redis_client.lock(lock_name, timeout=20):
session.execute(
update(WorkflowRun)
.where(WorkflowRun.id == run_id, WorkflowRun.tenant_id == tenant_id)
.values(status="cancelled")
)
session.commit()
# 3) Pessimistic lock with SELECT ... FOR UPDATE (high contention)
run = session.execute(
select(WorkflowRun)
.where(WorkflowRun.id == run_id, WorkflowRun.tenant_id == tenant_id)
.with_for_update()
).scalar_one()
run.status = "cancelled"
session.commit()
```
@@ -1,31 +0,0 @@
---
name: e2e-cucumber-playwright
description: Use when writing, changing, or reviewing Cucumber and Playwright tests under `e2e/`, including feature files, step definitions, support code, scenario tags, locators, and assertions. Do not use for Vitest, React Testing Library, backend tests, or generic browser automation outside the E2E suite.
---
# E2E Cucumber And Playwright
`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.
## 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]
Check current official Playwright or Cucumber documentation before introducing a framework pattern that local code and references do not already establish.
## Workflow
1. Add E2E coverage only for a critical user journey with a cross-boundary outcome that cheaper owner-level tests do not already prove.
2. Identify the user-visible behavior and its feature owner. Start from real product defaults and actor roles; setup may establish preconditions but must not manufacture the opposite state to make the scenario meaningful.
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.
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.
[cucumber]: references/cucumber-best-practices.md
[playwright]: references/playwright-best-practices.md
@@ -1,4 +0,0 @@
interface:
display_name: "E2E Cucumber + Playwright"
short_description: "Write and review Dify E2E scenarios."
default_prompt: "Use $e2e-cucumber-playwright to write or review a Dify E2E scenario under e2e/."
@@ -1,79 +0,0 @@
# Cucumber Best Practices
Use this reference when writing or reviewing Gherkin scenarios, step definitions, parameter expressions, and step reuse.
Official sources:
- https://cucumber.io/docs/guides/10-minute-tutorial
- https://cucumber.io/docs/cucumber/step-definitions
- https://cucumber.io/docs/cucumber/cucumber-expressions
## What Matters Most
### 1. Treat scenarios as executable specifications
Cucumber scenarios should describe examples of behavior, not test implementation recipes.
Apply it like this:
- write what the user does and what should happen
- avoid UI-internal wording such as selector details, DOM structure, or component names
- keep language concrete enough that the scenario reads like living documentation
### 2. Keep scenarios focused
A scenario should usually prove one workflow or business outcome. If a scenario wanders across several unrelated behaviors, split it.
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.
### 3. Reuse steps, but only when behavior really matches
Good reuse reduces duplication. Bad reuse hides meaning.
Prefer reuse when:
- the user action is genuinely the same
- the expected outcome is genuinely the same
- the wording stays natural across features
- the parameter is a real product domain value such as a named surface, mode, resource, or status
Write a new step when:
- the behavior is materially different
- reusing the old wording would make the scenario misleading
- a supposedly generic step would become an implementation-detail wrapper
Do not optimize for a low step count by making vague steps. Optimize for a small set of truthful, domain-owned steps.
### 4. Prefer Cucumber Expressions
Use Cucumber Expressions for parameters unless regex is clearly necessary.
Common examples:
- `{string}` for labels, names, and visible text
- `{int}` for counts
- `{float}` for decimal values
- `{word}` only when the value is truly a single token
Keep expressions readable. If a step needs complicated parsing logic, first ask whether the scenario wording should be simpler.
Use regex for a bounded natural-language alternative only when it keeps Gherkin readable, for example `/(Web app|Backend service API)/`. Avoid broad regexes that accept unowned language.
### 5. Keep step definitions thin and meaningful
Step definitions are glue between Gherkin and automation, not a second abstraction language.
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.
### 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.
## Review Questions
- Does the scenario read like a real example of product behavior?
- Are the steps behavior-oriented instead of implementation-oriented?
- Is a reused step still truthful in this feature?
- 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?
@@ -1,91 +0,0 @@
# Playwright Best Practices
Use this reference when writing or reviewing locator, assertion, isolation, or synchronization logic.
Official sources:
- https://playwright.dev/docs/best-practices
- https://playwright.dev/docs/locators
- https://playwright.dev/docs/test-assertions
- https://playwright.dev/docs/browser-contexts
## What Matters Most
### 1. Keep scenarios isolated
Playwright's model is built around clean browser contexts so one test does not leak into another.
Apply it like this:
- do not depend on another scenario having run first
- 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
Playwright recommends built-in locators that reflect what users perceive on the page.
Preferred order:
1. `getByRole`
2. `getByLabel`
3. `getByPlaceholder`
4. `getByText`
5. `getByTestId` when an explicit test contract is the most stable option
Avoid raw CSS/XPath selectors unless no stable user-facing contract exists and adding one is not practical.
Also remember:
- 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
Playwright assertions auto-wait and retry. Prefer them over manual state inspection.
Prefer:
- `await expect(page).toHaveURL(...)`
- `await expect(locator).toBeVisible()`
- `await expect(locator).toBeHidden()`
- `await expect(locator).toBeEnabled()`
- `await expect(locator).toHaveText(...)`
Avoid:
- `expect(await locator.isVisible()).toBe(true)`
- custom polling loops for DOM state
- `waitForTimeout` as synchronization
If a condition genuinely needs custom retry logic, use Playwright's polling/assertion tools deliberately and keep that choice local and explicit.
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.
### 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.
Good pattern:
- assert a meaningful visible state when that is part of the behavior
- then click/fill/select via locator APIs
Bad pattern:
- stack arbitrary waits before every action
- wait on unstable implementation details instead of the visible state the user cares about
### 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.
## Review Questions
- Would this locator survive DOM refactors that do not change user-visible behavior?
- Is this assertion using Playwright's retrying semantics?
- Is any explicit wait masking a real readiness problem?
- 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?
@@ -1,48 +0,0 @@
---
name: frontend-code-review
description: Use only when the user explicitly requests a review or audit of frontend code under `web/` or `packages/dify-ui/`. Supports pending-change, file-focused, and pasted-diff reviews. Do not use for implementation-only requests, diagnosis without review intent, or backend-only code.
---
# Frontend Code Review
Review the requested scope for concrete, reproducible regressions. This skill owns the review phase and routes directly to its bundled rule packs. For a combined review-and-fix request, establish findings before applying implementation or testing guidance.
## Evidence First
1. Establish the review scope from the requested files or current diff.
2. Read the changed lines, their behavior owner, and the nearest scoped `AGENTS.md`.
3. Trace public consumers, generated contracts, primitive APIs, or runtime configuration only when they decide correctness.
4. Report only findings tied to an observable failure, violated contract, security boundary, or demonstrated maintenance risk.
## Rule Routing
Read only the packs matched by the diff:
- DOM semantics, focus, keyboard, forms, disabled state, or visible interaction: [`references/accessibility-ui.md`][accessibility]
- Dify UI imports, Base UI wrappers, overlays, tokens, or primitive contracts: [`references/dify-ui.md`][dify-ui]
- Component ownership, props, state, Effects, navigation, or module boundaries: [`references/component-architecture.md`][component-architecture]
- Generated clients, Query, mutations, auth, SSR, URL state, or persistence: [`references/data-query-contracts.md`][data-query]
- Test files or a concrete missing-regression-test finding: [`references/testing.md`][testing]
- Bundle, waterfall, rendering, or subscription cost supported by evidence: [`references/performance.md`][performance]
- 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.
## Severity And Output
- **P0**: security or privacy leak, data loss, production crash, or inaccessible critical workflow.
- **P1**: user-visible regression, invalid API or authorization contract, hydration failure, or broken primary interaction.
- **P2**: concrete maintainability, performance, test, or accessibility defect likely to cause incorrect behavior.
- **P3**: minor actionable cleanup; omit unless the user requested a thorough audit.
Lead with findings ordered by severity. Include a tight file and line reference, the failing contract or reproduction path, impact, and a concrete fix direction. If there are no findings, say `No issues found.` and state any material verification gap. Do not add praise sections, speculative risks, or an unsolicited offer to implement fixes.
[accessibility]: references/accessibility-ui.md
[code-quality]: references/code-quality.md
[component-architecture]: references/component-architecture.md
[data-query]: references/data-query-contracts.md
[dify-invariants]: references/dify-invariants.md
[dify-ui]: references/dify-ui.md
[performance]: references/performance.md
[testing]: references/testing.md
@@ -1,109 +0,0 @@
# Accessibility And UI Rules
Accessibility findings are first-class review findings. Treat broken keyboard access, missing accessible names, focus loss, and unreachable popup content as correctness bugs, not polish.
Before finalizing UI or accessibility findings, fetch the latest Web Interface Guidelines as a required baseline:
```text
https://raw.githubusercontent.com/vercel-labs/web-interface-guidelines/main/command.md
```
Do not treat that document as the complete accessibility rule set. Combine it with:
- `packages/dify-ui/README.md`, `packages/dify-ui/AGENTS.md`, and the relevant primitive implementation when code uses `@langgenius/dify-ui/*`.
- Base UI docs and local `.d.ts` contracts when primitive semantics, focus target, labels, or popup reachability are unclear.
- MDN or relevant WAI-ARIA/browser standards when behavior, compatibility, or deprecation status matters.
- The current feature's product semantics, because an accessible primitive can still be used in an inaccessible workflow.
## Semantic HTML
Flag:
- Clickable `div` or `span` used for actions.
- Router navigation implemented with button or `onClick` when a `Link` / `<a>` is the real semantic element.
- Icon-only buttons without `aria-label` or `aria-labelledby`.
- Decorative icons missing `aria-hidden="true"`.
- Images without `alt`; use `alt=""` only when truly decorative.
- Heading levels that skip hierarchy in page-level content.
Prefer semantic HTML before ARIA.
## Keyboard And Focus
Flag:
- Interactive elements without visible `focus-visible` treatment.
- `outline-none` / `outline-hidden` without an equivalent focus-visible ring or state.
- Custom interactive elements missing keyboard handling.
- Focus trapped, lost, or sent to the wrong surface after dialog/popover/menu close.
- Focus ring applied to the wrong DOM node. Verify the actual focus target, especially with Base UI controls such as Slider.
Use `focus-visible` for keyboard focus. Use `focus-within` or `has-[:focus-visible]` when the visual wrapper is not the focused element.
## Forms
Flag:
- Inputs, selects, switches, checkboxes, radios, comboboxes, or sliders without a label relationship.
- Missing stable `name` on form fields that submit or validate.
- Incorrect input `type`, `inputMode`, `autoComplete`, or `spellCheck` for email, token, URL, number, search, code, or username fields.
- Labels that are not clickable.
- Submit buttons disabled before a request starts, preventing normal submit behavior.
- Non-submit buttons inside forms missing `type="button"`.
- Errors not associated with fields or not reachable by screen readers.
- Error recovery that does not focus or expose the first invalid field.
- `onPaste` blocking paste.
- Placeholder text used as the only label.
- Password managers accidentally triggered on non-auth fields because autocomplete is missing or wrong.
Prefer visible labels. If visible surrounding text already labels the control, use a visually hidden label or a precise `aria-label`.
## Disabled, Loading, And Async States
Flag:
- Loading state without `aria-busy`, `role="status"`, or another accessible update path when it changes user interaction.
- Spinner or decorative loading icon exposed to screen readers.
- Disabled controls that hide the reason users cannot proceed.
- `aria-disabled` used without manually blocking click, Space, and Enter.
- Toasts, inline validation, or async status changes that are not announced when users need the update to continue.
- Icon-only loading/error affordances without text or accessible status where the state matters.
Use native `disabled` when the control must not be interactive. Use `aria-disabled` only when the element must remain focusable and the code handles all blocked interactions.
For repeated shared disabled reasons, prefer a visible group message or badge plus native disabled controls. Use per-control popover/info only when the reason is item-specific.
## Overlays And Popup Reachability
Flag:
- Tooltip used for long, structured, interactive, or unique information.
- Tooltip content required to understand or complete a flow.
- PreviewCard content that touch or screen-reader users cannot reach through the trigger's click destination.
- Popover/dialog/menu triggers without accessible names.
- Popup content without title/description where the primitive requires them.
Use Popover for explanatory content, rich help, and infotips. Use Tooltip only as a short visual label for a trigger that already has an accessible name.
## Long Content And Layout
Flag:
- Text in flex/grid children without `min-w-0` when it can overflow.
- Names, labels, file names, model names, workspace names, or user content lacking `truncate`, `line-clamp`, or `break-words`.
- Right-side icons, badges, checks, or actions that shrink before the text area.
- Empty arrays or empty strings rendering broken layout instead of an empty state.
- Button, tab, badge, chip, menu item, or card text that can overlap sibling controls at common viewport widths.
The usual Dify layout chain is: container has width constraints, text region uses `min-w-0 flex-1 truncate`, adornments use `shrink-0`.
## Motion, Images, And Copy
Flag:
- `transition-all`.
- Animations that do not respect reduced motion.
- Layout-affecting animation where transform/opacity would work.
- Images without dimensions.
- Loading copy using `...` instead of `…`.
- Hardcoded dates, times, numbers, or currency formats instead of `Intl.*`.
@@ -1,68 +0,0 @@
# Code Quality Rules
## Scope Control
Flag changes that expand beyond the requested feature or review scope:
- Repo-wide cleanup mixed into a targeted fix.
- Compatibility exports, aliases, shims, or wrapper layers added without an explicit migration requirement.
- Shared abstractions created before there is stable cross-feature reuse.
- Business components moved into generic shared locations without a clear ownership boundary.
## TypeScript
Flag:
- `any` or broad `Record<string, any>` where generated/API types or local domain types exist.
- Re-declared API shapes instead of importing generated or returned types.
- Weak route/query param typing that leaks `string | string[] | undefined` deep into components.
- Runtime wrappers added only to satisfy TypeScript when a narrower type boundary would preserve the existing runtime shape.
Prefer:
- Explicit domain names that match the API contract.
- Type narrowing at route/API boundaries.
- Small conversion helpers colocated with the component that needs them.
## Styling
Flag:
- New CSS modules or ad hoc CSS when Tailwind utilities and Dify tokens cover the need.
- Component-level plain `.css` files or component CSS imported through `globals.css`; use scoped `*.module.css` only when Tailwind and component variants cannot express the style.
- Generic color utilities where Dify semantic tokens exist.
- Hardcoded magic class values for colors, spacing, radius, shadow, z-index, or typography when Dify tokens, component variants, or documented radius mappings exist.
- `!` important modifiers or important CSS overrides without a narrow, documented reason.
- Manual string concatenation, template strings, array `.join(' ')`, or custom ternaries for conditional or multi-line classes.
- JS conditional class branches for primitive visual states already exposed by Dify UI/Base UI `data-*` selectors.
- Incoming `className` placed before default classes in `cn(...)`, preventing call-site overrides.
- Arbitrary z-index or one-off layering fixes on overlays.
Use:
- `cn(...)` from the local package or utility already used by the file.
- Dify semantic tokens and Tailwind v4 utilities.
- Existing component variants before one-off class forks.
- Primitive selectors such as `data-disabled:*`, `data-checked:*`, `data-highlighted:*`, `group-data-*`, `peer-data-*`, and `has-[:focus-visible]` before adding React state or boolean props solely for styling.
- Component-level variants, semantic tokens, and normal cascade/order before `!` overrides. Use `!` only for a contained compatibility override that cannot be expressed through the component API or local selector structure.
## Imports
Flag:
- Barrel imports from `@langgenius/dify-ui`; consumers must use subpath exports.
- New overlay imports from legacy `@/app/components/base/modal`, `dialog`, or `drawer`.
- Cross-feature imports that bypass explicit top-level public files.
- Direct imports from generated/internal implementation files when a feature contract already exposes the intended surface.
## Copy And i18n
Flag:
- User-facing hardcoded strings in `web/`.
- Added or renamed i18n keys that are not present in every supported locale file for the touched namespace.
- Translation namespace drift, especially using unrelated module namespaces for local feature copy.
- Generic button labels like `Continue` where the action is specific.
- Error messages that state only the failure and not the next step.
Use feature-local translation keys by default. Alias only when crossing namespaces. `pnpm i18n:check --file <name>` should pass for any touched translation namespace.
@@ -1,88 +0,0 @@
# Component Architecture Rules
Use these rules for React component structure, ownership, state, props, effects, and module organization.
## Ownership
Flag:
- State, query, mutation, or handlers hoisted above the lowest component that actually uses them.
- Parent components owning row/item actions that do not coordinate a workflow.
- Prop drilling through multiple pass-through layers.
- A page/tab-level section component becoming the data owner without needing a shared snapshot or shared loading/error/empty UI.
- Feature code promoted to shared only because it appears once or might be reused later.
Accept repeated TanStack Query calls in siblings when each component independently consumes the data. Cache deduplication is not a reason to hoist by itself.
## Component Boundaries
Flag:
- React component files over 300 lines when the file mixes multiple responsibilities that can be split into focused colocated components, hooks, or utilities.
- Shallow wrappers that only rename props or hide the real primitive.
- Extra DOM wrappers that do not provide layout, semantics, accessibility, state ownership, or library integration.
- Dialog/dropdown/popover hidden surfaces that obscure the parent flow when they should be extracted into a small local component.
- Business forms, menu bodies, or one-off helpers moved away from their owner without reuse or semantic value.
Prefer colocated components split by actual data and state needs.
## Bad Component Design Patterns
Flag:
- Refactors of existing navigation, sidebar, dropdown, webapp list, or app-switching UI that do not preserve behavior-sensitive interactions such as expand/collapse arrows, hover persistence, pin/delete controls, routing, keyboard/focus handling, or open-state ownership.
- Components that mix data fetching, mutation side effects, popup state, form validation, layout, and row rendering without a clear owner.
- Generic components with many boolean props that encode one feature's workflow.
- A shared component that imports feature-specific copy, routes, or API contracts.
- A feature component that accepts pre-rendered fragments only to avoid placing ownership correctly.
- A child component that receives both raw server data and separately derived flags for the same concept.
- A wrapper that changes accessible semantics of the primitive it wraps.
- A component that exposes controlled props but still keeps a competing private state for the same value.
- A component that cannot render empty, loading, or missing optional API fields without caller-side preprocessing.
When existing components already own interaction logic, prefer reusing or extending them. If a refactor is necessary, preserve the old interaction contract and add or update focused tests for changed behavior.
## Props And Types
Flag:
- Declaration or export rewrites made only for stylistic uniformity, without changing an owned behavior or contract.
- Named `Props` types for trivial one-off props where inline typing is clearer.
- Props named by UI implementation instead of domain/API role.
- API data converted too early or under a generic name that breaks traceability.
- Callers duplicating fallback checks that the lowest rendering component already handles.
Do not flag `FC`, `React.FC`, function declarations, arrow functions, named exports, or default exports by syntax alone. Report them only when the chosen form causes a concrete type, lifecycle, export, framework, or enforced package-contract defect.
## Effects
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.
- 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.
## State Modeling
Flag:
- Storing derived booleans, disabled flags, default tabs, or loading labels that can be calculated from current query/feature state.
- 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.
## Navigation
Flag:
- Imperative router navigation for ordinary links.
- Button semantics used for navigation.
- Navigation state hidden in component state when URL state is required for shareable filters, tabs, or pagination.
Use `Link` for normal navigation. Use router APIs for mutation success, guarded redirects, command flows, or form submission side effects.
@@ -1,74 +0,0 @@
# Data, Query, And Contract Rules
Use these rules for generated contracts, TanStack Query, mutations, auth/SSR boundaries, URL state, and client persistence.
## Generated Contracts
Flag:
- New legacy service/helper wrappers around generated `queryOptions()` or `mutationOptions()`.
- Continuing to use deprecated contract operations when a ready generated contract exists.
- Assuming a generated file means an operation is ready without checking deprecated markers, schema shape, and the actual UI consumer.
- Re-declaring API DTOs in components.
- Adding compatibility layers instead of migrating the pointed line and deleting the old layer.
Backend Pydantic and OpenAPI schemas own API shape. Generated clients and schemas under `packages/contracts/generated/*` are authoritative at frontend boundaries and use the `{ params, query?, body? }` input shape.
## Queries
Flag:
- `enabled` used to hide missing required input instead of `input: skipToken`.
- Fake fallback IDs or placeholder inputs used to force a query to run.
- Query results copied into local state for rendering.
- Shared query behavior such as invalidation, stale defaults, or retry rules reimplemented at call sites.
- `prefetchQuery` treated as a hard gate or as returning data/errors to the caller.
Use `useQuery(consoleQuery.xxx.queryOptions(...))` or `useQuery(marketplaceQuery.xxx.queryOptions(...))` directly unless a feature hook performs real orchestration.
## Mutations
Flag:
- Deprecated `useInvalid` or `useReset`.
- `mutateAsync` used without a need for Promise semantics.
- Awaited mutations without `try/catch`.
- Components owning shared cache invalidation that belongs in query defaults.
- Optimistic updates that do not match current list/detail ownership.
Use generated `mutationOptions()` directly when possible. Put shared cache behavior in `createTanstackQueryUtils(...experimental_defaults...)`.
## SSR, Auth, And Route Boundaries
Flag:
- Request-time auth, setup, workspace role, or tenant decisions moved into static `next.config redirects()`.
- Dynamic role gates depending on `workspaces.current` implemented as static path redirects.
- Authorization logic depending on soft `prefetchQuery`.
- Removing a client fallback before server API unavailable behavior is defined.
- Global placeholder query contracts introduced to solve a route-local Suspense issue.
- Branding-sensitive UI reading placeholder defaults without checking pending/placeholder state.
Separate hard gates from soft prefetches. `fetchQuery` can be a server decision boundary; `prefetchQuery` is cache warmup.
## Workspace And Tenant
Flag:
- Treating workspace switch as ordinary CRUD invalidation when the current app flow performs server switch plus full reload.
- Query keys that omit workspace/tenant identity when the query truly varies by workspace and no full reload boundary applies.
- Mixing `workspace_id` and `tenant_id` without tracing the current backend/API contract.
Current Dify workspace switch should be reviewed as a tenant cache boundary first.
## URL State And Local Storage
Flag:
- Shareable filters, tabs, pagination, selected panels, or search state hidden only in component state.
- One-shot navigation signals modeled as subscribed persistent state.
- Live app state stored in localStorage.
- Direct `window.localStorage`, `globalThis.localStorage`, or raw storage calls in app code.
- High-frequency interaction state persisted on every change instead of on commit/settle.
Use URL state for shareable UI state, feature/Jotai/store state for live UI state, and `@/hooks/use-local-storage` only for low-frequency client-only preferences, dismissed notices, and UI defaults.
@@ -1,22 +0,0 @@
# Dify Invariants
Use these stable Dify-specific runtime rules in addition to the generic review packs.
This file is not a place for active feature notes. Do not add rules for one branch, one PR, or a short-lived product decision such as a specific agent-v2, plugin, model-provider, or onboarding task. Keep a rule here only when all of these are true:
- It is a stable Dify runtime invariant.
- Generic React, TypeScript, accessibility, dify-ui, query, or performance rules would not catch it.
- The failure mode is concrete enough to produce a file-line review finding.
- The rule is likely to remain valid across normal feature work.
## Workflow Nodes And RAG Pipe
Flag:
- Node components under `web/app/components/workflow/nodes/[nodeName]/node.tsx` importing workflow store hooks that are unavailable in RAG Pipe template rendering.
- Node UI relying on provider context that is not mounted in every rendering surface.
- Store reads in render where React Flow `useNodes` / `useEdges` provide the actual node/edge source.
Known failure mode: workflow node components can also render while creating a RAG Pipe from a template. In that context there may be no workflowStore provider, causing a blank screen.
Prefer React Flow hooks for node/edge UI consumption. Use store APIs only where the provider is guaranteed and the code path is workflow-only.
@@ -1,141 +0,0 @@
# Dify UI Rules
Use these rules whenever a review touches `packages/dify-ui/` or code consuming `@langgenius/dify-ui/*`.
Before finalizing findings for those files, read the current local docs that apply:
- `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
## Package Boundary
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.
@@ -1,78 +0,0 @@
# Performance Rules
Review performance only where there is realistic impact. Do not request `memo`, `useMemo`, `useCallback`, virtualization, or caching as style preferences.
## Async Waterfalls
Flag:
- Awaiting remote feature flags or fetches before checking cheap synchronous conditions.
- Sequential awaits for independent operations.
- API routes or server components starting requests late when they could start early.
- Nested per-item fetches running serially when each item can fetch in parallel.
- Suspense boundaries that force the whole page to wait when a lower boundary could stream or isolate loading.
Prefer `Promise.all` for independent work and branch-local awaits for conditionally needed data.
## Bundle Size
Flag:
- Barrel imports from heavy libraries or `@langgenius/dify-ui`.
- Dynamic paths that prevent static trace analysis.
- Heavy components loaded eagerly when hidden behind a dialog, tab, command, or feature activation.
- Analytics, logging, editor, visualization, or third-party SDK code loaded before it is needed.
- Feature-local optional modules imported at top level only for rare flows.
Use direct imports and `next/dynamic` where the user-visible path benefits.
## Server Rendering
Flag:
- Request-specific mutable state stored at module scope in SSR/RSC paths.
- Large duplicate data serialized across RSC/client boundaries.
- Static I/O repeated per request when it could be hoisted safely.
- Cross-request cache without a bounded invalidation strategy.
- Server actions lacking API-route-equivalent auth checks.
Use request-scoped deduplication such as `React.cache()` when repeated server reads in one request are the problem.
## Re-rendering
Flag:
- Effects or subscriptions reading broad state when a derived boolean or narrower selector is enough.
- Components defined inside components.
- Derived rendering state stored in state/effects.
- Non-primitive default props recreated for memoized children.
- Expensive work recalculated on every render where it affects real interaction cost.
- High-frequency transient values stored in state when refs or CSS variables would avoid render loops.
Do not flag simple primitive expressions wrapped or not wrapped in `useMemo`; prefer no memo for simple work.
Require stable object/array/function identity only when:
- The child is memoized and identity affects renders.
- The value is an effect/query dependency.
- A library API requires stable references.
- Profiling or local behavior shows avoidable re-rendering.
## DOM, Lists, And Rendering
Flag:
- Layout reads in render (`getBoundingClientRect`, `offset*`, `scrollTop`).
- Interleaved DOM reads/writes that can cause layout thrashing.
- Large lists rendering without virtualization, pagination, or `content-visibility`.
- SVG/animation code animating expensive properties when transform/opacity would work.
- `transition-all`.
- Long-running non-critical browser work performed immediately instead of idle/deferred scheduling.
## React Flow
For workflow React Flow components, keep this Dify-specific rule:
- UI consumption should use React Flow hooks such as `useNodes` / `useEdges`.
- Callback-only reads or mutations can use `useStoreApi`.
- Node components under `web/app/components/workflow/nodes/[nodeName]/node.tsx` must not depend on workflow stores that are absent in RAG Pipe template rendering.
@@ -1,36 +0,0 @@
# Testing Review Rules
`web/docs/test.md` is the canonical frontend testing policy. Use this file only to translate that policy into review findings.
## Request Missing Tests When Risk Justifies Them
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.
- 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.
Do not request tests for mechanical changes, pass-through wrappers, implementation details, or visual-only styling unless they affect behavior. Low coverage alone is not a finding.
## Flag Low-Value or Fragile Tests
Flag tests that:
- Assert internal state, refs, hook usage, effect dependencies, private DOM structure, or cosmetic classes.
- Exist only to render a component, exercise a prop, or cover generic invalid inputs without a product scenario.
- Mock away the behavior under review or use mocks that do not match the public contract.
- Add production `data-testid` attributes where semantic markup would work.
- Use fake timers without timer behavior, leave async work unawaited, or leak shared state.
- Duplicate a contract already protected at a more useful owner boundary.
## Review the Test Boundary
- Prefer semantic queries and accessible names.
- Prefer real feature components when integration semantics matter.
- Allow intentional child or provider mocks when setup would dominate the test and that boundary is covered independently.
- Do not accept semantically inaccurate mocks of Dify UI or legacy base primitives.
- Require a real-browser or visual verification plan when `happy-dom` cannot represent the risk.
Treat test quality, determinism, and regression value as the review criteria. Do not use test count or coverage percentage as a proxy for quality.
-16
View File
@@ -1,16 +0,0 @@
---
name: frontend-testing
description: Use when writing or changing Vitest or React Testing Library tests under `web/` or `packages/dify-ui/`, or when the user explicitly requests frontend test strategy, including evaluation of an existing strategy. Do not use for frontend code-review-only requests, general testability discussion, Python tests, or Cucumber/Playwright E2E.
---
# Frontend Testing
`web/docs/test.md` is the single policy owner. Read it before changing frontend tests; this skill adds no separate requirements.
1. Identify the observable contract and regression risk.
2. Choose the smallest boundary that includes the behavior owner.
3. Establish the failing case first when practical, then implement one coherent scenario.
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.
@@ -1,41 +0,0 @@
---
name: how-to-write-component
description: Use when implementing or refactoring React/TypeScript components and the task requires decisions about component ownership, feature boundaries, state, data flow, effects, or interaction ownership. Do not use for review-only requests, test-only work, copy-only edits, or styling-only changes.
---
# How To Write A Component
Use this skill to route component architecture decisions to its bundled references. Read only the references required by the current change.
## First Decisions
| Question | Default | Promote only 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. |
| 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. |
| Is a wrapper needed? | Use the primitive or direct code. | The wrapper owns behavior, validation, state, or semantics. |
| Is an Effect needed? | Derive during render or handle the user action. | A named external system must be synchronized. |
## Topic Routing
- 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.
- Effects, navigation, memoization, preloading, or render cost: read [`references/runtime.md`][runtime].
## Workflow
1. Identify the behavior owner 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.
[data]: references/data.md
[interactions]: references/interactions.md
[ownership]: references/ownership.md
[runtime]: references/runtime.md
[state]: references/state.md
@@ -1,42 +0,0 @@
# Component Data And Queries
Read this document when a component consumes generated contracts, nullable API values, TanStack Query, mutations, prefetching, authentication, or workspace state.
## Generated Contracts
- Treat generated contracts as authoritative at API, query, mutation, cache, and service boundaries. Enterprise APIs use `packages/contracts/generated/enterprise/*`.
- Backend Pydantic and OpenAPI schemas own API shape. Follow the generated `{ params, query?, body? }` input shape; when it is wrong, fix the backend schema and regenerate `packages/contracts/generated/*`.
- Do not hand-write DTO mirrors, widen generated fields or enums, edit generated output, or add a parallel frontend status layer unless it models product state absent from the API.
- Check deprecated markers, schema shape, and the actual consumer before assuming that a generated operation is ready to use.
- Normalize only at real boundaries such as user input, search, URL params, filenames, DOM IDs, or a required legacy adapter.
- Preserve `null`, `undefined`, and intentional empty strings until the final boundary. Do not use `value || undefined` when an empty string means clearing a field.
- Build required values in the branch that proves them. Avoid `filter(Boolean)`, truthiness filters, non-null assertions after filters, and placeholder values used only to satisfy types.
## Queries
- Use generated options directly with `useQuery(consoleQuery.xxx.queryOptions(...))`, `marketplaceQuery`, or the equivalent generated client.
- If query input comes from atom state, keep it in `atomWithQuery`; do not unwrap the atom in a component solely to call `useQuery`.
- For missing required input, branch the whole generated input with `skipToken`. Add `enabled` only for an independent execution condition; do not put `skipToken` inside a placeholder payload or coerce IDs to empty strings.
- Return generated `queryOptions()`, `infiniteOptions()`, or `mutationOptions()` directly from TanStack Query atoms. Pass supported options into the generated call instead of spreading into a parallel object.
- Share the exact options between prefetch and render when they represent the same request. Do not extract option helpers merely to reuse input construction.
- Avoid pass-through service hooks that only rename generated options. Keep feature hooks for actual orchestration or shared domain behavior.
## Mutations And Cache
- Use generated `mutationOptions()` directly for owner-local mutations.
- Put shared invalidation, retries, and cache behavior in `createTanstackQueryUtils(...experimental_defaults...)`. Local callbacks may own toast, close, and navigation effects but must not replace shared cache policy.
- Prefer `mutate(...)`. Use `mutateAsync(...)` only when Promise composition is required, and catch awaited failures.
- Preserve intentional empty values and current list/detail ownership when updating data. Do not add optimistic updates without a verified owner contract.
## Prefetch And Hidden Surfaces
- Prefetch expensive secondary content from the trigger or menu-open event when it benefits the visible path. Do not mount hidden subscribers solely to warm the cache.
- `prefetchQuery` is cache warmup, not an authorization or availability gate. Use a hard fetch boundary when the server must decide whether rendering may proceed.
## SSR, Authentication, And Workspace
- Static configuration owns path-invariant routing. Request-dependent authentication, setup, role, and tenant decisions belong to SSR or runtime decision boundaries.
- Distinguish soft SSR cache warming from authoritative decisions. Prefetched or placeholder data must not grant access or represent successful availability.
- Never reuse tenant-scoped state after switching workspaces. Discard it at the switch boundary or isolate it by workspace identity.
- Do not make product or authorization decisions from bootstrap defaults. Wait for authoritative data, or render an explicit loading or error state.
- Keep loading and Suspense behavior inside the feature that owns the request. Do not add fake global data merely to bypass that boundary.
@@ -1,31 +0,0 @@
# 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].
## Focus And Semantics
- Preserve a visible focus indicator on the final focusable element. Styled Dify UI controls usually provide it; headless anatomy parts and direct trigger exports may not.
- Native buttons, links, custom trigger renderers, clickable rows, icon controls, and menu-like items must retain their correct native semantics and accessible name.
- Do not hide an outline without an equivalent visible `focus-visible` treatment. Follow an existing Dify UI pattern rather than inventing a call-site style.
## Keyboard Commands
- Distinguish application commands from widget-local keyboard semantics. Use `@tanstack/react-hotkeys` for application commands; keep menu navigation, dialog Escape handling, editor behavior, and ARIA widget keys in their local primitive or owner.
- Use `useHotkey` or `useHotkeys` for registered commands. When an existing `onKeyDown` intentionally owns the command, use `matchesKeyboardEvent` rather than duplicating modifier parsing or adding another global listener.
- Keep registration and keycap or menu display derived from one canonical command. Distinguish registered commands, held keys, and display-only accelerators.
- Keep a single-owner command beside its component. Create a feature-local hotkey module only when several production files share it; tests alone do not justify extraction.
- Make availability and scope explicit with `enabled`, `ignoreInputs`, and `target`. Put a target ref on the actual behavior owner rather than creating wrapper DOM solely for hotkey scope.
- Preserve existing `preventDefault` and propagation behavior when migrating command APIs.
- Test observable command behavior, disabled and input scope, target scope, and the registration/display contract at the owning feature boundary.
## 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.
- 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.
[overlay guide]: ../../../../web/docs/overlay.md
@@ -1,39 +0,0 @@
# Component Ownership And Modules
Read this document when adding, moving, splitting, or refactoring React components or feature modules.
## Vertical Modules
- Organize code by product workflow, route, or behavior owner. Keep components, hooks, local types, atoms, query helpers, tests, and small utilities beside the code that changes with them.
- Name page and tab folders after the current route, tab, or user-visible surface. Do not preserve stale parent groupings that no longer own multiple surfaces.
- Split a growing page or tab by product or visual owners. Keep the feature root for its public entrypoint and genuinely cross-owner coordination.
- Import other features only through explicit public entrypoints. Avoid barrels that merely re-export secondary owners.
- Promote code outside a feature only when multiple verticals use the same stable contract. Possible future reuse is not sufficient.
## 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.
- 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.
- Do not replace prop drilling with one large view-model hook. Move each query, derived value, and handler to the concrete owner that consumes it.
- Keep source selection, defaults, validation, dirty checks, and payload shaping beside the workflow that owns submission.
## 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.
- 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.
- Loading states for page sections, cards, lists, tables, forms, and drawers should use skeletons scoped to the loaded content. Reserve spinners for small inline busy indicators.
## Components And Types
- Choose component declaration and export forms from the actual component contract, framework requirements, and enforced package rules. Existing style is context, not authority; do not rewrite unaffected code solely to normalize `FC`, `function`, arrow-function, named-export, or default-export forms.
- Type simple one-off props inline. Name a `Props` type when it is reused, exported, complex, or materially clearer.
- Use API-generated or API-returned types at component boundaries. Keep one-off UI refinements and conversions beside their owner.
- Preserve domain value types for selections. Do not widen enums, unions, booleans, numbers, objects, or nullable values to `string` before a real boundary requires it.
- Avoid generic `common.tsx` buckets and aliases that only rename another type. Name files, values, and public types after their domain role.
- Put fallback and invariant checks in the lowest component that already renders that state. Do not extract helpers whose only purpose is hiding missing display data.
@@ -1,23 +0,0 @@
# Component Effects, Navigation, And Runtime Cost
Read this document when a change introduces Effects, navigation side effects, memoization, preloading, or render-cost optimizations.
## Effects
- 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.
## Navigation
- Use `Link` for ordinary navigation.
- Use router APIs for command-flow side effects such as mutation success, guarded redirects, or form submission.
- Keep shareable navigation state in the URL rather than hidden component state.
## Runtime Cost
- Move changing state to the smallest consumer before considering memoization. Stable parent content can be lifted and passed as children.
- Avoid `memo`, `useMemo`, and `useCallback` unless identity or computation has a demonstrated consumer or measurable cost.
- Start independent remote work together and await it near the branch that consumes it. Avoid introducing request waterfalls.
- Load heavy optional surfaces on demand when they sit behind a dialog, tab, command, or feature activation.
- Use narrow selectors or field-level atoms for broad stores and subscriptions. Do not optimize simple primitive expressions merely for stylistic consistency.
@@ -1,38 +0,0 @@
# Component State And URL Ownership
Read this document when a change involves Jotai, form drafts, route identity, shared client state, or local persistence.
## Choose The Owner
- Keep synchronous state local when one component owns it: dialog and menu state, confirmations, field drafts, and local selections usually belong to the component or DOM.
- Use feature-scoped Jotai when siblings need one source of truth, values drive other atoms, or a scoped workflow must preserve state across hidden or unmounted steps.
- 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
- 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 validation, source priority, fallback behavior, dirty checks, and payload assembly in the workflow that owns submission.
## Route And URL State
- Treat `useParams`, route arguments, and `nuqs` as the owners of URL identity and updates.
- Hydrate a primitive atom at the route or surface boundary only when query atoms or shared derived atoms require route identity. Keep URL writes in route and query-state APIs.
- Within one route-owned feature, choose one route-identity source. Do not hydrate route identity into atoms while also threading the same ID through multiple component layers.
- Put shareable filters, tabs, pagination, and search state in the URL. Keep one-shot navigation signals and transient UI state out of persistent subscriptions.
## Jotai And Query
- A Jotai-backed feature may keep one feature-local state module ordered by dependency: types and constants, primitives, query atoms, query-data derivations, business facts, commands, mutations, submission orchestration, and provider exports.
- Use `atomWithQuery` or `atomWithMutation` for async work driven by atom state. Do not hand-roll loading, error, or in-flight state for atom-orchestrated work.
- Use field-specific derived atoms for query results. `jotai-tanstack-query` does not provide TanStack Query tracked properties, so reading a whole query atom subscribes to the entire observer result.
- Leave query and mutation atoms unscoped so they retain the shared QueryClient cache. Scope resettable primitives and hydration tuples; scope a derived atom only when all dependencies should be private to the surface.
- Use non-null lazy primitives for values always hydrated by a scope provider. Name derived atoms as business facts and write atoms as user or workflow commands.
- Keep independent dialog lifecycles separate. A scoped open-state atom is acceptable only when composed sibling surfaces would otherwise pass confusing lifecycle props through unrelated owners.
## Persistence
- Use feature-owned storage modules built on `createLocalStorageState`; callers should not scatter direct storage access or raw keys.
- Persist high-frequency interaction state only on commit or after updates settle.
- Do not add ad hoc global event listeners for shared state. Centralize subscriptions through the owning atom, store, or subscription hook.
-15
View File
@@ -1,15 +0,0 @@
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "npx -y block-no-verify@1.1.1"
}
]
}
]
}
}
+19
View File
@@ -0,0 +1,19 @@
{
"permissions": {
"allow": [],
"deny": []
},
"env": {
"__comment": "Environment variables for MCP servers. Override in .claude/settings.local.json with actual values.",
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
"enabledMcpjsonServers": [
"context7",
"sequential-thinking",
"github",
"fetch",
"playwright",
"ide"
],
"enableAllProjectMcpServers": true
}
-1
View File
@@ -1 +0,0 @@
../../.agents/skills/backend-code-review
-1
View File
@@ -1 +0,0 @@
../../.agents/skills/e2e-cucumber-playwright
-1
View File
@@ -1 +0,0 @@
../../.agents/skills/frontend-code-review
-1
View File
@@ -1 +0,0 @@
../../.agents/skills/frontend-testing
-1
View File
@@ -1 +0,0 @@
../../.agents/skills/how-to-write-component
-6
View File
@@ -1,6 +0,0 @@
[run]
omit =
api/conftest.py
api/tests/*
api/migrations/*
api/core/rag/datasource/vdb/*
+1 -1
View File
@@ -1,4 +1,4 @@
FROM mcr.microsoft.com/devcontainers/python:3.12-bookworm
FROM mcr.microsoft.com/devcontainers/python:3.12
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install libgmp-dev libmpfr-dev libmpc-dev
+8 -5
View File
@@ -6,15 +6,12 @@
"context": "..",
"dockerfile": "Dockerfile"
},
"mounts": [
"source=dify-dev-tmp,target=/tmp,type=volume"
],
"features": {
"ghcr.io/devcontainers/features/node:1": {
"nodeGypDependencies": true,
"version": "lts"
},
"ghcr.io/devcontainers-extra/features/npm-package:1": {
"ghcr.io/devcontainers-contrib/features/npm-package:1": {
"package": "typescript",
"version": "latest"
},
@@ -37,13 +34,19 @@
},
"postStartCommand": "./.devcontainer/post_start_command.sh",
"postCreateCommand": "./.devcontainer/post_create_command.sh"
// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "python --version",
// Configure tool-specific properties.
// "customizations": {},
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
}
// "remoteUser": "root"
}
+7 -8
View File
@@ -1,16 +1,15 @@
#!/bin/bash
WORKSPACE_ROOT=$(pwd)
export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
corepack enable
cd web && pnpm install
pipx install uv
echo "alias start-api=\"cd $WORKSPACE_ROOT/api && uv run python -m flask run --host 0.0.0.0 --port=5001 --debug\"" >> ~/.bashrc
echo "alias start-worker=\"cd $WORKSPACE_ROOT/api && uv run python -m celery -A app.celery worker -P threads -c 1 --loglevel INFO -Q dataset,dataset_summary,priority_dataset,priority_pipeline,pipeline,mail,ops_trace,app_deletion,plugin,workflow_storage,conversation,workflow,schedule_poller,schedule_executor,triggered_workflow_dispatcher,trigger_refresh_publisher,trigger_refresh_executor,retention\"" >> ~/.bashrc
echo "alias start-web=\"cd $WORKSPACE_ROOT/web && pnpm dev:inspect\"" >> ~/.bashrc
echo "alias start-web-prod=\"cd $WORKSPACE_ROOT/web && pnpm build && pnpm start\"" >> ~/.bashrc
echo "alias start-containers=\"cd $WORKSPACE_ROOT/docker && docker-compose -f docker-compose.middleware.yaml -p dify --env-file middleware.env up -d\"" >> ~/.bashrc
echo "alias stop-containers=\"cd $WORKSPACE_ROOT/docker && docker-compose -f docker-compose.middleware.yaml -p dify --env-file middleware.env down\"" >> ~/.bashrc
echo 'alias start-api="cd /workspaces/dify/api && uv run python -m flask run --host 0.0.0.0 --port=5001 --debug"' >> ~/.bashrc
echo 'alias start-worker="cd /workspaces/dify/api && uv run python -m celery -A app.celery worker -P gevent -c 1 --loglevel INFO -Q dataset,generation,mail,ops_trace,app_deletion,plugin,workflow_storage"' >> ~/.bashrc
echo 'alias start-web="cd /workspaces/dify/web && pnpm dev"' >> ~/.bashrc
echo 'alias start-web-prod="cd /workspaces/dify/web && pnpm build && pnpm start"' >> ~/.bashrc
echo 'alias start-containers="cd /workspaces/dify/docker && docker-compose -f docker-compose.middleware.yaml -p dify --env-file middleware.env up -d"' >> ~/.bashrc
echo 'alias stop-containers="cd /workspaces/dify/docker && docker-compose -f docker-compose.middleware.yaml -p dify --env-file middleware.env down"' >> ~/.bashrc
source /home/vscode/.bashrc
-15
View File
@@ -1,15 +0,0 @@
**/node_modules
**/.pnpm-store
**/dist
**/.next
**/.turbo
**/.cache
**/__pycache__
**/*.pyc
**/.mypy_cache
**/.ruff_cache
.git
.github
*.md
!web/README.md
!api/README.md
+1 -1
View File
@@ -29,7 +29,7 @@ trim_trailing_whitespace = false
# Matches multiple files with brace expansion notation
# Set default charset
[*.{js,jsx,ts,tsx,mjs}]
[*.{js,tsx}]
indent_style = space
indent_size = 2
-13
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: []
-4
View File
@@ -5,7 +5,3 @@
# them.
*.sh text eol=lf
# Codegen output must stay byte-identical across platforms so
# `pnpm tree:check` in CI does not trip on CRLF rewrites.
*.generated.ts text eol=lf
-271
View File
@@ -1,271 +0,0 @@
# CODEOWNERS
# This file defines code ownership for the Dify project.
# Each line is a file pattern followed by one or more owners.
# Owners can be @username, @org/team-name, or email addresses.
# For more information, see: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
* @crazywoola @laipz8200
# Lint bulk suppression baselines.
/oxlint-suppressions.json
# CODEOWNERS file
/.github/CODEOWNERS @laipz8200 @crazywoola
# Agents
/.agents/skills/ @hyoban
# Packages
/packages/ @lyzno1
/packages/contracts/ @crazywoola @laipz8200
# Docs
/docs/ @crazywoola
# CLI
/cli/ @GareArc
/.github/workflows/cli-tests.yml @GareArc
# E2E
/e2e/ @lyzno1
# Backend (default owner, more specific rules below will override)
/api/ @QuantumGhost
# Backend - Tests
/api/tests/ @laipz8200 @QuantumGhost
# Backend - RAG (Retrieval Augmented Generation)
/api/core/rag/ @JohnJyong
/api/services/rag_pipeline/ @JohnJyong
/api/services/dataset_service.py @JohnJyong
/api/services/knowledge_service.py @JohnJyong
/api/services/external_knowledge_service.py @JohnJyong
/api/services/hit_testing_service.py @JohnJyong
/api/services/metadata_service.py @JohnJyong
/api/services/vector_service.py @JohnJyong
/api/services/entities/knowledge_entities/ @JohnJyong
/api/services/entities/external_knowledge_entities/ @JohnJyong
/api/controllers/console/datasets/ @JohnJyong
/api/controllers/service_api/dataset/ @JohnJyong
/api/models/dataset.py @JohnJyong
/api/tasks/rag_pipeline/ @JohnJyong
/api/tasks/add_document_to_index_task.py @JohnJyong
/api/tasks/batch_clean_document_task.py @JohnJyong
/api/tasks/clean_document_task.py @JohnJyong
/api/tasks/clean_notion_document_task.py @JohnJyong
/api/tasks/document_indexing_task.py @JohnJyong
/api/tasks/document_indexing_sync_task.py @JohnJyong
/api/tasks/document_indexing_update_task.py @JohnJyong
/api/tasks/duplicate_document_indexing_task.py @JohnJyong
/api/tasks/recover_document_indexing_task.py @JohnJyong
/api/tasks/remove_document_from_index_task.py @JohnJyong
/api/tasks/retry_document_indexing_task.py @JohnJyong
/api/tasks/sync_website_document_indexing_task.py @JohnJyong
/api/tasks/batch_create_segment_to_index_task.py @JohnJyong
/api/tasks/create_segment_to_index_task.py @JohnJyong
/api/tasks/delete_segment_from_index_task.py @JohnJyong
/api/tasks/disable_segment_from_index_task.py @JohnJyong
/api/tasks/disable_segments_from_index_task.py @JohnJyong
/api/tasks/enable_segment_to_index_task.py @JohnJyong
/api/tasks/enable_segments_to_index_task.py @JohnJyong
/api/tasks/clean_dataset_task.py @JohnJyong
/api/tasks/deal_dataset_index_update_task.py @JohnJyong
/api/tasks/deal_dataset_vector_index_task.py @JohnJyong
# Backend - Plugins
/api/core/plugin/ @WH-2099
/api/services/plugin/ @WH-2099
/api/controllers/console/workspace/plugin.py @WH-2099
/api/controllers/inner_api/plugin/ @WH-2099
/api/tasks/process_tenant_plugin_autoupgrade_check_task.py @WH-2099
# Backend - Trigger/Schedule/Webhook
/api/controllers/trigger/ @CourTeous33
/api/controllers/console/app/workflow_trigger.py @CourTeous33
/api/controllers/console/workspace/trigger_providers.py @CourTeous33
/api/core/trigger/ @CourTeous33
/api/core/app/layers/trigger_post_layer.py @CourTeous33
/api/services/trigger/ @CourTeous33
/api/models/trigger.py @CourTeous33
/api/repositories/workflow_trigger_log_repository.py @CourTeous33
/api/repositories/sqlalchemy_workflow_trigger_log_repository.py @CourTeous33
/api/libs/schedule_utils.py @CourTeous33
/api/services/workflow/scheduler.py @CourTeous33
/api/schedule/trigger_provider_refresh_task.py @CourTeous33
/api/schedule/workflow_schedule_task.py @CourTeous33
/api/tasks/trigger_processing_tasks.py @CourTeous33
/api/tasks/trigger_subscription_refresh_tasks.py @CourTeous33
/api/tasks/workflow_schedule_tasks.py @CourTeous33
/api/tasks/workflow_cfs_scheduler/ @CourTeous33
/api/events/event_handlers/sync_plugin_trigger_when_app_created.py @CourTeous33
/api/events/event_handlers/update_app_triggers_when_app_published_workflow_updated.py @CourTeous33
/api/events/event_handlers/sync_workflow_schedule_when_app_published.py @CourTeous33
/api/events/event_handlers/sync_webhook_when_app_created.py @CourTeous33
# Backend - Async Workflow
/api/services/async_workflow_service.py @Mairuis
/api/tasks/async_workflow_tasks.py @Mairuis
# Backend - Billing
/api/services/billing_service.py @hj24 @zyssyz123
/api/controllers/console/billing/ @hj24 @zyssyz123
# Backend - Enterprise
/api/configs/enterprise/ @GareArc
/api/services/enterprise/ @GareArc
/api/services/feature_service.py @GareArc
/api/controllers/console/feature.py @GareArc
/api/controllers/web/feature.py @GareArc
# Backend - Database Migrations
/api/migrations/ @snakevash @laipz8200 @MRZHUH
# Backend - Vector DB Middleware
/api/configs/middleware/vdb/* @JohnJyong
# Frontend
/web/ @iamjoel
# Frontend - Platform and Features
/web/config/ @lyzno1
/web/env.ts @lyzno1
/web/features/ @lyzno1
/web/hooks/ @lyzno1
/web/scripts/gen-icons.mjs @lyzno1
# Frontend - Web Tests
/.github/workflows/web-tests.yml @iamjoel
# Frontend - App - Orchestration
/web/app/components/workflow/ @iamjoel @zxhlyh
/web/app/components/workflow-app/ @iamjoel @zxhlyh
/web/app/components/app/configuration/ @iamjoel @zxhlyh
/web/app/components/app/app-publisher/ @iamjoel @zxhlyh
# Frontend - WebApp - Chat
/web/app/components/base/chat/ @iamjoel @zxhlyh
# Frontend - WebApp - Completion
/web/app/components/share/text-generation/ @iamjoel @zxhlyh
# Frontend - App - List and Creation
/web/app/components/apps/ @JzoNgKVO @iamjoel
/web/app/components/app/create-app-dialog/ @JzoNgKVO @iamjoel
/web/app/components/app/create-app-modal/ @JzoNgKVO @iamjoel
/web/app/components/app/create-from-dsl-modal/ @JzoNgKVO @iamjoel
# Frontend - App - API Documentation
/web/app/components/develop/ @JzoNgKVO @iamjoel
/web/app/components/develop/template/*.mdx @JzoNgKVO @iamjoel @RiskeyL
# Frontend - App - Logs and Annotations
/web/app/components/app/workflow-log/ @JzoNgKVO @iamjoel
/web/app/components/app/log/ @JzoNgKVO @iamjoel
/web/app/components/app/log-annotation/ @JzoNgKVO @iamjoel
/web/app/components/app/annotation/ @JzoNgKVO @iamjoel
# Frontend - App - Monitoring
/web/app/(commonLayout)/app/(appDetailLayout)/\[appId\]/overview/ @JzoNgKVO @iamjoel
/web/app/components/app/overview/ @JzoNgKVO @iamjoel
# Frontend - App - Settings
/web/app/components/app-sidebar/ @JzoNgKVO @iamjoel
# Frontend - RAG - Hit Testing
/web/app/components/datasets/hit-testing/ @JzoNgKVO @iamjoel
# Frontend - RAG - List and Creation
/web/app/components/datasets/list/ @iamjoel @WTW0313
/web/app/components/datasets/create/ @iamjoel @WTW0313
/web/app/components/datasets/create-from-pipeline/ @iamjoel @WTW0313
/web/app/components/datasets/external-knowledge-base/ @iamjoel @WTW0313
# Frontend - RAG - Orchestration (general rule first, specific rules below override)
/web/app/components/rag-pipeline/ @iamjoel @WTW0313
/web/app/components/rag-pipeline/components/rag-pipeline-main.tsx @iamjoel @zxhlyh
/web/app/components/rag-pipeline/store/ @iamjoel @zxhlyh
# Frontend - RAG - Documents List
/web/app/components/datasets/documents/create-from-pipeline/ @iamjoel @WTW0313
# Frontend - RAG - Segments List
/web/app/components/datasets/documents/detail/ @iamjoel @WTW0313
# Frontend - RAG - Settings
/web/app/components/datasets/settings/ @iamjoel @WTW0313
# Frontend - Ecosystem - Plugins
/web/app/components/plugins/ @iamjoel @zhsama
# Frontend - Ecosystem - Tools
/web/app/components/tools/ @iamjoel @Yessenia-d
# Frontend - Ecosystem - MarketPlace
/web/app/components/plugins/marketplace/ @iamjoel @Yessenia-d
# Frontend - Login and Registration
/web/app/signin/ @iamjoel
/web/app/signup/ @iamjoel
/web/app/reset-password/ @iamjoel
/web/app/install/ @iamjoel
/web/app/init/ @iamjoel
/web/app/forgot-password/ @iamjoel
/web/app/account/ @iamjoel
# Frontend - Service Authentication
/web/service/base.ts @iamjoel
# Frontend - WebApp Authentication and Access Control
/web/app/(shareLayout)/components/ @iamjoel
/web/app/(shareLayout)/webapp-signin/ @iamjoel
/web/app/(shareLayout)/webapp-reset-password/ @iamjoel
/web/app/components/app/app-access-control/ @iamjoel
# Frontend - Explore Page
/web/app/components/explore/ @CodingOnStar @iamjoel
# Frontend - Personal Settings
/web/app/components/header/account-setting/ @CodingOnStar @iamjoel
/web/app/components/header/account-dropdown/ @CodingOnStar @iamjoel
# Frontend - Analytics
/web/app/components/base/ga/ @CodingOnStar @iamjoel
# Frontend - Base Components
/web/app/components/base/ @iamjoel @zxhlyh
# Frontend - Base Components Tests
/web/app/components/base/**/*.spec.tsx @hyoban @CodingOnStar
# Frontend - Utils and Hooks
/web/utils/time.ts @iamjoel @zxhlyh
/web/utils/format.ts @iamjoel @zxhlyh
/web/utils/clipboard.ts @iamjoel @zxhlyh
# Frontend - Billing and Education
/web/app/components/billing/ @iamjoel @zxhlyh
/web/app/education-apply/ @iamjoel @zxhlyh
# Frontend - Workspace
/web/app/components/header/account-dropdown/workplace-selector/ @iamjoel @zxhlyh
# Frontend - App Shell and Console Bootstrap
/web/app/layout.tsx @iamjoel @lyzno1
/web/app/error.tsx @iamjoel @lyzno1
/web/app/(commonLayout)/layout.tsx @iamjoel @lyzno1
/web/app/(commonLayout)/providers.tsx @iamjoel @lyzno1
/web/app/(commonLayout)/hydration-boundary.tsx @iamjoel @lyzno1
/web/app/(commonLayout)/profile-bootstrap-gate.tsx @iamjoel @lyzno1
/web/app/(commonLayout)/error.tsx @iamjoel @lyzno1
/web/app/account/(commonLayout)/layout.tsx @iamjoel @lyzno1
/web/app/components/main-nav/* @iamjoel @lyzno1
/web/app/components/main-nav/components/* @iamjoel @lyzno1
/web/context/query-client.tsx @iamjoel @lyzno1
/web/context/query-client-server.ts @iamjoel @lyzno1
/web/proxy.ts @iamjoel @lyzno1
/web/app/auth/refresh/route.ts @iamjoel @lyzno1
/web/service/server.ts @iamjoel @lyzno1
# Docker
/docker/* @laipz8200
-3
View File
@@ -1,8 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: "\U0001F510 Security Vulnerabilities"
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"
about: Report issues with official plugins or model providers, you will need to provide the plugin version and other relevant details.
+8 -6
View File
@@ -1,6 +1,8 @@
name: "✨ Refactor or Chore"
description: Refactor existing code or perform maintenance chores to improve readability and reliability.
title: "[Refactor/Chore] "
name: "✨ Refactor"
description: Refactor existing code for improved readability and maintainability.
title: "[Chore/Refactor] "
labels:
- refactor
body:
- type: checkboxes
attributes:
@@ -9,7 +11,7 @@ body:
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
- label: This is only for refactors or chores; if you would like to ask a question, please head to [Discussions](https://github.com/langgenius/dify/discussions/categories/general).
- label: This is only for refactoring, if you would like to ask a question, please head to [Discussions](https://github.com/langgenius/dify/discussions/categories/general).
required: true
- label: I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones.
required: true
@@ -23,14 +25,14 @@ body:
id: description
attributes:
label: Description
placeholder: "Describe the refactor or chore you are proposing."
placeholder: "Describe the refactor 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 is necessary."
validations:
required: false
- type: textarea
+13
View File
@@ -0,0 +1,13 @@
name: "👾 Tracker"
description: For inner usages, please do not use this template.
title: "[Tracker] "
labels:
- tracker
body:
- type: textarea
id: content
attributes:
label: Blockers
placeholder: "- [ ] ..."
validations:
required: true
-16
View File
@@ -1,16 +0,0 @@
name: Setup Web Environment
description: Set up Node.js, Vite+, pnpm, and web dependencies
runs:
using: composite
steps:
- name: Setup pnpm
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
with:
run_install: false
- name: Setup Vite+
uses: voidzero-dev/setup-vp@ca1c46663915d6c1042ae23bd39ab85718bfb0fa # v1.10.0
with:
node-version-file: .nvmrc
cache: true
run-install: true
-223
View File
@@ -1,223 +0,0 @@
version: 2
updates:
- package-ecosystem: "uv"
directory: "/api"
open-pull-requests-limit: 10
schedule:
interval: "weekly"
groups:
flask:
patterns:
- "flask"
- "flask-*"
- "werkzeug"
- "gunicorn"
google:
patterns:
- "google-*"
- "googleapis-*"
opentelemetry:
patterns:
- "opentelemetry-*"
pydantic:
patterns:
- "pydantic"
- "pydantic-*"
llm:
patterns:
- "langfuse"
- "langsmith"
- "litellm"
- "mlflow*"
- "opik"
- "weave*"
- "arize*"
- "tiktoken"
- "transformers"
database:
patterns:
- "sqlalchemy"
- "psycopg2*"
- "psycogreen"
- "redis*"
- "alembic*"
storage:
patterns:
- "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-*"
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"
python-packages:
patterns:
- "*"
- package-ecosystem: "github-actions"
directory: "/"
open-pull-requests-limit: 5
schedule:
interval: "weekly"
groups:
github-actions-dependencies:
patterns:
- "*"
- package-ecosystem: "uv"
directory: "/api"
target-branch: "lts/1.13.x"
open-pull-requests-limit: 10
schedule:
interval: "weekly"
groups:
flask:
patterns:
- "flask"
- "flask-*"
- "werkzeug"
- "gunicorn"
google:
patterns:
- "google-*"
- "googleapis-*"
opentelemetry:
patterns:
- "opentelemetry-*"
pydantic:
patterns:
- "pydantic"
- "pydantic-*"
llm:
patterns:
- "langfuse"
- "langsmith"
- "litellm"
- "mlflow*"
- "opik"
- "weave*"
- "arize*"
- "tiktoken"
- "transformers"
database:
patterns:
- "sqlalchemy"
- "psycopg2*"
- "psycogreen"
- "redis*"
- "alembic*"
storage:
patterns:
- "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-*"
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"
python-packages:
patterns:
- "*"
- package-ecosystem: "github-actions"
directory: "/"
target-branch: "lts/1.13.x"
open-pull-requests-limit: 5
schedule:
interval: "weekly"
groups:
github-actions-dependencies:
patterns:
- "*"
-15
View File
@@ -1,15 +0,0 @@
web:
- changed-files:
- any-glob-to-any-file:
- 'web/**'
- 'packages/**'
- 'package.json'
- 'pnpm-lock.yaml'
- 'pnpm-workspace.yaml'
- '.nvmrc'
e2e:
- changed-files:
- any-glob-to-any-file:
- 'e2e/**'
- '.github/workflows/web-e2e.yml'
+4 -5
View File
@@ -7,7 +7,6 @@
## Summary
<!-- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. -->
<!-- If this PR was created by an automated agent, add `From <Tool Name>` as the final line of the description. Example: `From Codex`. -->
## Screenshots
@@ -18,7 +17,7 @@
## Checklist
- [ ] This change requires a documentation update, included: [Dify Document](https://github.com/langgenius/dify-docs)
- [ ] 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
- [x] I understand that this PR may be closed in case there was no previous discussion or issues. (This doesn't apply to typos!)
- [x] I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
- [x] I've updated the documentation accordingly.
- [x] I ran `dev/reformat`(backend) and `cd web && npx lint-staged`(frontend) to appease the lint gods
@@ -1,73 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
BASE_SHA=${BASE_SHA:-}
HEAD_SHA=${HEAD_SHA:-}
MAIN_REF=${MAIN_REF:-origin/main}
REMEDIATION_HINT="Changes should be made from the main branch using git cherry-pick -x."
error() {
printf 'ERROR: %s\n' "$1" >&2
}
if [[ -z "$BASE_SHA" || -z "$HEAD_SHA" ]]; then
error "BASE_SHA and HEAD_SHA are required. $REMEDIATION_HINT"
exit 2
fi
if ! git rev-parse --verify "$BASE_SHA^{commit}" > /dev/null 2>&1; then
error "Base commit '$BASE_SHA' is not available in the local git checkout."
exit 2
fi
if ! git rev-parse --verify "$HEAD_SHA^{commit}" > /dev/null 2>&1; then
error "Head commit '$HEAD_SHA' is not available in the local git checkout."
exit 2
fi
if ! git rev-parse --verify "$MAIN_REF^{commit}" > /dev/null 2>&1; then
error "Main ref '$MAIN_REF' is not available in the local git checkout. $REMEDIATION_HINT"
exit 2
fi
failed=0
checked=0
while IFS= read -r commit_sha; do
[[ -n "$commit_sha" ]] || continue
checked=$((checked + 1))
subject=$(git log -1 --format=%s "$commit_sha")
source_sha=$(
git log -1 --format=%B "$commit_sha" \
| sed -nE 's/^\(cherry picked from commit ([0-9a-fA-F]{7,64})\)$/\1/p' \
| tail -n 1
)
if [[ -z "$source_sha" ]]; then
error "Commit $commit_sha ($subject) is missing cherry-pick provenance. $REMEDIATION_HINT If version differences prevent using git cherry-pick -x, manually add '(cherry picked from commit <sha>)' to the commit message."
failed=1
continue
fi
if ! git cat-file -e "$source_sha^{commit}" 2> /dev/null; then
error "Commit $commit_sha ($subject) references source $source_sha, but that commit is not available locally. $REMEDIATION_HINT"
failed=1
continue
fi
if ! git merge-base --is-ancestor "$source_sha" "$MAIN_REF"; then
error "Commit $commit_sha ($subject) references source $source_sha, but that source is not reachable from main ($MAIN_REF). $REMEDIATION_HINT"
failed=1
fi
done < <(git rev-list --reverse "$BASE_SHA..$HEAD_SHA")
if [[ "$failed" -ne 0 ]]; then
exit 1
fi
if [[ "$checked" -eq 0 ]]; then
echo "No PR commits to check."
else
echo "Verified $checked PR commit(s) include cherry-pick provenance from main."
fi
-82
View File
@@ -1,82 +0,0 @@
import { execFileSync } from 'node:child_process'
import fs from 'node:fs'
import path from 'node:path'
const repoRoot = process.cwd()
const baseSha = process.env.BASE_SHA || ''
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 readCurrentJson = (fileStem) => {
const filePath = englishPath(fileStem)
if (!fs.existsSync(filePath))
return null
return JSON.parse(fs.readFileSync(filePath, 'utf8'))
}
const readBaseJson = (fileStem) => {
if (!baseSha)
return null
try {
const relativePath = `web/i18n/en-US/${fileStem}.json`
const content = execFileSync('git', ['show', `${baseSha}:${relativePath}`], { encoding: 'utf8' })
return JSON.parse(content)
}
catch {
return null
}
}
const compareJson = (beforeValue, afterValue) => JSON.stringify(beforeValue) === JSON.stringify(afterValue)
const changes = {}
for (const fileStem of files) {
const currentJson = readCurrentJson(fileStem)
const beforeJson = readBaseJson(fileStem) || {}
const afterJson = currentJson || {}
const added = {}
const updated = {}
const deleted = []
for (const [key, value] of Object.entries(afterJson)) {
if (!(key in beforeJson)) {
added[key] = value
continue
}
if (!compareJson(beforeJson[key], value)) {
updated[key] = {
before: beforeJson[key],
after: value,
}
}
}
for (const key of Object.keys(beforeJson)) {
if (!(key in afterJson))
deleted.push(key)
}
changes[fileStem] = {
fileDeleted: currentJson === null,
added,
updated,
deleted,
}
}
fs.writeFileSync(
outputPath,
JSON.stringify({
baseSha,
headSha,
files,
changes,
})
)
+51 -157
View File
@@ -2,40 +2,32 @@ name: Run Pytest
on:
workflow_call:
secrets:
CODECOV_TOKEN:
required: false
permissions:
contents: read
concurrency:
group: api-tests-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
api-unit:
name: API Unit Tests
runs-on: depot-ubuntu-24.04
env:
COVERAGE_FILE: coverage-unit
test:
name: API Tests
runs-on: ubuntu-latest
defaults:
run:
shell: bash
strategy:
matrix:
python-version:
- "3.11"
- "3.12"
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- name: Setup UV and Python
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
python-version: ${{ matrix.python-version }}
@@ -47,155 +39,57 @@ jobs:
- name: Install dependencies
run: uv sync --project api --dev
- name: Run Unit Tests
- name: Run Unit tests
run: |
uv run --project api pytest \
-p no:benchmark \
--timeout "${PYTEST_TIMEOUT:-20}" \
-n auto \
api/tests/unit_tests \
api/providers/vdb/*/tests/unit_tests \
api/providers/trace/*/tests/unit_tests \
--ignore=api/tests/unit_tests/controllers
# Controller tests register Flask routes at import time, so keep them out of xdist.
uv run --project api pytest \
--timeout "${PYTEST_TIMEOUT:-20}" \
--cov-append \
api/tests/unit_tests/controllers
uv run --project api bash dev/pytest/pytest_unit_tests.sh
- name: Upload unit coverage data
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: api-coverage-unit
path: coverage-unit
retention-days: 1
api-integration:
name: API Integration Tests
runs-on: depot-ubuntu-24.04
env:
COVERAGE_FILE: coverage-integration
STORAGE_TYPE: opendal
OPENDAL_SCHEME: fs
OPENDAL_FS_ROOT: /tmp/dify-storage
defaults:
run:
shell: bash
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@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
enable-cache: true
python-version: ${{ matrix.python-version }}
cache-dependency-glob: api/uv.lock
- name: Check UV lockfile
run: uv lock --project api --check
- name: Install dependencies
run: uv sync --project api --dev
- name: Run Integration Tests
- name: Run pyrefly check
run: |
uv run --project api pytest \
-p no:benchmark \
--start-middleware \
-n auto \
--timeout "${PYTEST_TIMEOUT:-180}" \
api/tests/integration_tests/workflow \
api/tests/integration_tests/tools \
api/tests/test_containers_integration_tests
- name: Upload integration coverage data
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: api-coverage-integration
path: coverage-integration
retention-days: 1
api-coverage:
name: API Coverage
runs-on: depot-ubuntu-24.04
needs:
- api-unit
- api-integration
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
COVERAGE_FILE: .coverage
defaults:
run:
shell: bash
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@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
enable-cache: true
python-version: "3.12"
cache-dependency-glob: api/uv.lock
- name: Install dependencies
run: uv sync --project api --dev
- name: Download coverage data
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: coverage-data
pattern: api-coverage-*
merge-multiple: true
- name: Combine coverage
cd api
uv add --dev pyrefly
uv run pyrefly check || true
- name: Coverage Summary
run: |
set -euo pipefail
set -x
# Extract coverage percentage and create a summary
TOTAL_COVERAGE=$(python -c 'import json; print(json.load(open("coverage.json"))["totals"]["percent_covered_display"])')
echo "### API Coverage" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "Merged backend coverage report generated for Codecov project status." >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
# Create a detailed coverage summary
echo "### Test Coverage Summary :test_tube:" >> $GITHUB_STEP_SUMMARY
echo "Total Coverage: ${TOTAL_COVERAGE}%" >> $GITHUB_STEP_SUMMARY
uv run --project api coverage report --format=markdown >> $GITHUB_STEP_SUMMARY
unit_coverage="$(find coverage-data -type f -name coverage-unit -print -quit)"
integration_coverage="$(find coverage-data -type f -name coverage-integration -print -quit)"
: "${unit_coverage:?coverage-unit artifact not found}"
: "${integration_coverage:?coverage-integration artifact not found}"
- name: Run dify config tests
run: uv run --project api dev/pytest/pytest_config_tests.py
report_file="$(mktemp)"
uv run --project api coverage combine "$unit_coverage" "$integration_coverage"
uv run --project api coverage report --show-missing | tee "$report_file"
echo "Summary: \`$(tail -n 1 "$report_file")\`" >> "$GITHUB_STEP_SUMMARY"
{
echo ""
echo "<details><summary>Coverage report</summary>"
echo ""
echo '```'
cat "$report_file"
echo '```'
echo "</details>"
} >> "$GITHUB_STEP_SUMMARY"
uv run --project api coverage xml -o coverage.xml
- name: Set up dotenvs
run: |
cp docker/.env.example docker/.env
cp docker/middleware.env.example docker/middleware.env
- name: Report coverage
if: ${{ env.CODECOV_TOKEN != '' }}
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
- name: Expose Service Ports
run: sh .github/workflows/expose_service_ports.sh
- name: Set up Sandbox
uses: hoverkraft-tech/compose-action@v2.0.2
with:
files: ./coverage.xml
disable_search: true
flags: api
env:
CODECOV_TOKEN: ${{ env.CODECOV_TOKEN }}
compose-file: |
docker/docker-compose.middleware.yaml
services: |
db
redis
sandbox
ssrf_proxy
- name: setup test config
run: |
cp api/tests/integration_tests/.env.example api/tests/integration_tests/.env
- name: Run Workflow
run: uv run --project api bash dev/pytest/pytest_workflow.sh
- name: Run Tool
run: uv run --project api bash dev/pytest/pytest_tools.sh
- name: Run TestContainers
run: uv run --project api bash dev/pytest/pytest_testcontainers.sh
+12 -160
View File
@@ -2,180 +2,32 @@ name: autofix.ci
on:
pull_request:
branches: ["main"]
merge_group:
branches: ["main"]
types: [checks_requested]
push:
branches: ["main"]
permissions:
contents: read
jobs:
autofix:
if: github.repository == 'langgenius/dify'
runs-on: depot-ubuntu-24.04-4
runs-on: ubuntu-latest
steps:
- name: Complete merge group check
if: github.event_name == 'merge_group'
run: echo "autofix.ci updates pull request branches, not merge group refs."
- uses: actions/checkout@v4
- if: github.event_name != 'merge_group'
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Check Docker Compose inputs
if: github.event_name != 'merge_group'
id: docker-compose-changes
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
# Use uv to ensure we have the same ruff version in CI and locally.
- uses: astral-sh/setup-uv@v6
with:
files: |
docker/generate_docker_compose
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
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
with:
files: |
api/**
- name: Check frontend contract inputs
if: github.event_name != 'merge_group'
id: frontend-contract-changes
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
with:
files: |
api/**
packages/contracts/openapi-ts.api.config.ts
packages/contracts/package.json
packages/contracts/openapi/**
pnpm-lock.yaml
pnpm-workspace.yaml
- name: Check dify-agent inputs
if: github.event_name != 'merge_group'
id: dify-agent-changes
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
with:
files: |
dify-agent/**/*.py
dify-agent/pyproject.toml
dify-agent/uv.lock
- if: github.event_name != 'merge_group'
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.11"
- if: github.event_name != 'merge_group'
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
- name: Generate Docker Compose
if: github.event_name != 'merge_group' && steps.docker-compose-changes.outputs.any_changed == 'true'
run: |
cd docker
./generate_docker_compose
- if: github.event_name != 'merge_group' && steps.api-changes.outputs.any_changed == 'true'
run: |
python-version: "3.12"
- run: |
cd api
uv sync --dev
# fmt first to avoid line too long
uv run ruff format ..
# Fix lint errors
uv run ruff check --fix .
# Format code
uv run ruff format ..
- if: github.event_name != 'merge_group' && steps.dify-agent-changes.outputs.any_changed == 'true'
run: |
cd dify-agent
uv sync --dev
# fmt first to avoid line too long
uv run ruff format .
# Fix lint errors
uv run ruff check --fix .
uv run ruff check --fix-only .
# 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: |
# ast-grep exits 1 if no matches are found; allow idempotent runs.
uvx --from ast-grep-cli ast-grep --pattern 'db.session.query($WHATEVER).filter($HERE)' --rewrite 'db.session.query($WHATEVER).where($HERE)' -l py --update-all || true
uvx --from ast-grep-cli ast-grep --pattern 'session.query($WHATEVER).filter($HERE)' --rewrite 'session.query($WHATEVER).where($HERE)' -l py --update-all || true
uvx --from ast-grep-cli ast-grep -p '$A = db.Column($$$B)' -r '$A = mapped_column($$$B)' -l py --update-all || true
uvx --from ast-grep-cli ast-grep -p '$A : $T = db.Column($$$B)' -r '$A : $T = mapped_column($$$B)' -l py --update-all || true
# Convert Optional[T] to T | None (ignoring quoted types)
cat > /tmp/optional-rule.yml << 'EOF'
id: convert-optional-to-union
language: python
rule:
kind: generic_type
all:
- has:
kind: identifier
pattern: Optional
- has:
kind: type_parameter
has:
kind: type
pattern: $T
fix: $T | None
EOF
uvx --from ast-grep-cli ast-grep scan . --inline-rules "$(cat /tmp/optional-rule.yml)" --update-all
# Fix forward references that were incorrectly converted (Python doesn't support "Type" | None syntax)
find . -name "*.py" -type f -exec sed -i.bak -E 's/"([^"]+)" \| None/Optional["\1"]/g; s/'"'"'([^'"'"']+)'"'"' \| None/Optional['"'"'\1'"'"']/g' {} \;
find . -name "*.py.bak" -type f -delete
- name: Setup web environment
if: github.event_name != 'merge_group'
uses: ./.github/actions/setup-web
- name: Generate API docs
if: github.event_name != 'merge_group' && steps.api-changes.outputs.any_changed == 'true'
uvx --from ast-grep-cli sg --pattern 'db.session.query($WHATEVER).filter($HERE)' --rewrite 'db.session.query($WHATEVER).where($HERE)' -l py --update-all
uvx --from ast-grep-cli sg --pattern 'session.query($WHATEVER).filter($HERE)' --rewrite 'session.query($WHATEVER).where($HERE)' -l py --update-all
- name: mdformat
run: |
cd api
uv run dev/generate_swagger_markdown_docs.py --swagger-dir ../packages/contracts/openapi --markdown-dir openapi/markdown --keep-swagger-json
- name: Generate frontend contracts
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
uvx mdformat .
- uses: autofix-ci/action@635ffb0c9798bd160680f18fd73371e355b85f27
+26 -104
View File
@@ -4,10 +4,12 @@ on:
push:
branches:
- "main"
- "deploy/**"
- "deploy/dev"
- "deploy/enterprise"
- "build/**"
- "release/e-*"
- "hotfix/**"
- "deploy/rag-dev"
- "feat/rag-2"
tags:
- "*"
@@ -20,75 +22,30 @@ env:
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
DIFY_WEB_IMAGE_NAME: ${{ vars.DIFY_WEB_IMAGE_NAME || 'langgenius/dify-web' }}
DIFY_API_IMAGE_NAME: ${{ vars.DIFY_API_IMAGE_NAME || 'langgenius/dify-api' }}
DIFY_AGENT_IMAGE_NAME: ${{ vars.DIFY_AGENT_IMAGE_NAME || 'langgenius/dify-agent-backend' }}
DIFY_AGENT_LOCAL_SANDBOX_IMAGE_NAME: ${{ vars.DIFY_AGENT_LOCAL_SANDBOX_IMAGE_NAME || 'langgenius/dify-agent-local-sandbox' }}
jobs:
build:
runs-on: ${{ matrix.runs_on }}
runs-on: ${{ matrix.platform == 'linux/arm64' && 'arm64_runner' || 'ubuntu-latest' }}
if: github.repository == 'langgenius/dify'
permissions:
contents: read
id-token: write
strategy:
matrix:
include:
- service_name: "build-api-amd64"
image_name_env: "DIFY_API_IMAGE_NAME"
artifact_context: "api"
build_context: "{{defaultContext}}"
file: "api/Dockerfile"
context: "api"
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"
context: "api"
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"
context: "web"
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"
context: "web"
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"
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"
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"
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"
platform: linux/arm64
runs_on: depot-ubuntu-24.04-4
steps:
- name: Prepare
@@ -97,32 +54,34 @@ jobs:
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Login to Docker Hub
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
uses: docker/login-action@v3
with:
username: ${{ env.DOCKERHUB_USER }}
password: ${{ env.DOCKERHUB_TOKEN }}
- name: Set up Depot CLI
uses: depot/setup-action@15c09a5f77a0840ad4bce955686522a257853461 # v1.7.1
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Extract metadata for Docker
id: meta
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
uses: docker/metadata-action@v5
with:
images: ${{ env[matrix.image_name_env] }}
- name: Build Docker image
id: build
uses: depot/build-push-action@98e78adca7817480b8185f474a400b451d74e287 # v1.18.0
uses: docker/build-push-action@v6
with:
project: ${{ vars.DEPOT_PROJECT_ID }}
context: ${{ matrix.build_context }}
file: ${{ matrix.file }}
context: "{{defaultContext}}:${{ matrix.context }}"
platforms: ${{ matrix.platform }}
build-args: COMMIT_SHA=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }}
build-contexts: ${{ matrix.build_contexts }}
labels: ${{ steps.meta.outputs.labels }}
outputs: type=image,name=${{ env[matrix.image_name_env] }},push-by-digest=true,name-canonical=true,push=true
cache-from: type=gha,scope=${{ matrix.service_name }}
cache-to: type=gha,mode=max,scope=${{ matrix.service_name }}
- name: Export digest
env:
@@ -133,47 +92,16 @@ jobs:
touch "/tmp/digests/${sanitized_digest}"
- name: Upload digest
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@v4
with:
name: digests-${{ matrix.artifact_context }}-${{ env.PLATFORM_PAIR }}
name: digests-${{ matrix.context }}-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
fork-build-validate:
if: github.repository != 'langgenius/dify'
runs-on: ubuntu-24.04
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"
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Validate Docker image
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
push: false
context: ${{ matrix.build_context }}
file: ${{ matrix.file }}
build-contexts: ${{ matrix.build_contexts }}
platforms: linux/amd64
create-manifest:
needs: build
runs-on: depot-ubuntu-24.04
runs-on: ubuntu-latest
if: github.repository == 'langgenius/dify'
strategy:
matrix:
@@ -184,29 +112,23 @@ jobs:
- 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
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digests-${{ matrix.context }}-*
merge-multiple: true
- name: Login to Docker Hub
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
uses: docker/login-action@v3
with:
username: ${{ env.DOCKERHUB_USER }}
password: ${{ env.DOCKERHUB_TOKEN }}
- name: Extract metadata for Docker
id: meta
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
uses: docker/metadata-action@v5
with:
images: ${{ env[matrix.image_name_env] }}
tags: |
-415
View File
@@ -1,415 +0,0 @@
name: CLI E2E Tests
on:
workflow_dispatch:
inputs:
cli_ref:
description: "Git ref (default: current branch)"
type: string
required: false
edition:
description: "Dify edition"
type: choice
required: false
default: ee
options: [ee, ce]
test_scope:
description: "smoke = [P0] only / full = all cases"
type: choice
required: false
default: full
options: [smoke, full]
# ── Suite on/off ────────────────────────────────────────────────────────
suite_framework_output_error:
description: "framework + output + error-handling suites"
type: boolean
default: true
suite_discovery:
description: "discovery suite (get app / describe app)"
type: boolean
default: true
suite_run:
description: "run suite (basic / streaming / conversation / file / hitl)"
type: boolean
default: true
suite_auth:
description: "auth suite (login / status / whoami / use / devices / logout)"
type: boolean
default: true
suite_agent:
description: "agent suite"
type: boolean
default: true
permissions:
contents: read
# ── Shared env injected into every E2E job ───────────────────────────────────
# 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
jobs:
# ════════════════════════════════════════════════════════════════════════════
# 0. PROVISION — mint token + import DSL fixtures (runs once, outputs IDs)
# ════════════════════════════════════════════════════════════════════════════
provision:
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 }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
with:
ref: ${{ inputs.cli_ref || github.ref }}
persist-credentials: false
- 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
- name: Install CLI dependencies
working-directory: cli
run: pnpm install --frozen-lockfile
- name: Mint token & provision apps
id: out
working-directory: cli
env:
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' }}
run: bun scripts/e2e-provision.ts
# ════════════════════════════════════════════════════════════════════════════
# 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' }}
needs: provision
runs-on: ubuntu-latest
timeout-minutes: 20
defaults:
run:
working-directory: cli
shell: bash
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
with:
ref: ${{ inputs.cli_ref || github.ref }}
persist-credentials: false
- 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 }
- 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_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_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\]"
else
pnpm test:e2e
fi
# ════════════════════════════════════════════════════════════════════════════
# 1-C. Discovery (parallel)
# ════════════════════════════════════════════════════════════════════════════
suite-discovery:
name: "Suite: discovery"
if: ${{ inputs.suite_discovery != 'false' }}
needs: provision
runs-on: ubuntu-latest
timeout-minutes: 20
defaults:
run:
working-directory: cli
shell: bash
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
with:
ref: ${{ inputs.cli_ref || github.ref }}
persist-credentials: false
- 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 }
- 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_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_INCLUDE: "test/e2e/suites/discovery/**/*.e2e.ts"
run: |
if [ "${{ inputs.test_scope }}" = "smoke" ]; then
pnpm test:e2e -- -t "\[P0\]"
else
pnpm test:e2e
fi
# ════════════════════════════════════════════════════════════════════════════
# 1-D. Run suite — 5 files in matrix (parallel)
# ════════════════════════════════════════════════════════════════════════════
suite-run:
name: "Suite: run / ${{ matrix.name }}"
if: ${{ inputs.suite_run != 'false' }}
needs: provision
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
include:
- name: basic
file: run-app-basic.e2e.ts
- name: streaming
file: run-app-streaming.e2e.ts
- name: conversation
file: run-app-conversation.e2e.ts
- name: file
file: run-app-file.e2e.ts
- name: hitl
file: run-app-hitl.e2e.ts
defaults:
run:
working-directory: cli
shell: bash
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
with:
ref: ${{ inputs.cli_ref || github.ref }}
persist-credentials: false
- 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 }
- run: pnpm install --frozen-lockfile
- run: pnpm tree:gen
- 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_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 }}"
run: |
if [ "${{ inputs.test_scope }}" = "smoke" ]; then
pnpm test:e2e -- -t "\[P0\]"
else
pnpm test:e2e
fi
- name: Upload results on failure
if: failure()
uses: actions/upload-artifact@v7
with:
name: e2e-run-${{ matrix.name }}-${{ github.run_id }}
path: cli/test-results/
retention-days: 3
# ════════════════════════════════════════════════════════════════════════════
# 1-E. auth/login + status + whoami (parallel, read-only, safe)
# ════════════════════════════════════════════════════════════════════════════
suite-auth-safe:
name: "Suite: auth (login / status / whoami)"
if: ${{ inputs.suite_auth != 'false' }}
needs: provision
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
working-directory: cli
shell: bash
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
with:
ref: ${{ inputs.cli_ref || github.ref }}
persist-credentials: false
- 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 }
- 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_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"
run: |
if [ "${{ inputs.test_scope }}" = "smoke" ]; then
pnpm test:e2e -- -t "\[P0\]"
else
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.
# ════════════════════════════════════════════════════════════════════════════
suite-last:
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' }}
needs:
- provision
- suite-framework-output-error
- suite-discovery
- suite-run
- suite-auth-safe
# `needs` on a skipped job is treated as success — safe to proceed even if
# some suites were disabled via toggle.
runs-on: ubuntu-latest
timeout-minutes: 25
defaults:
run:
working-directory: cli
shell: bash
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
with:
ref: ${{ inputs.cli_ref || github.ref }}
persist-credentials: false
- 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 }
- 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_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 }}
run: |
# Collect files in safe order: use → devices → logout (revokes last) → agent
FILES=()
if [ "${{ inputs.suite_auth }}" = "true" ]; then
FILES+=(
test/e2e/suites/auth/use.e2e.ts
test/e2e/suites/auth/devices.e2e.ts
test/e2e/suites/auth/logout.e2e.ts
)
fi
if [ "${{ inputs.suite_agent }}" = "true" ]; then
while IFS= read -r f; do FILES+=("$f"); done \
< <(find test/e2e/suites/agent -name '*.e2e.ts' | sort)
fi
[ ${#FILES[@]} -eq 0 ] && { echo "Nothing to run."; exit 0; }
# Pass files via DIFY_E2E_INCLUDE (comma-separated) so vitest
# config's include list is overridden instead of ANDed.
INCLUDE=$(IFS=,; echo "${FILES[*]}")
if [ "${{ inputs.test_scope }}" = "smoke" ]; then
DIFY_E2E_INCLUDE="$INCLUDE" pnpm test:e2e -- -t "\[P0\]"
else
DIFY_E2E_INCLUDE="$INCLUDE" pnpm test:e2e
fi
- name: Upload results on failure
if: failure()
uses: actions/upload-artifact@v7
with:
name: e2e-last-${{ github.run_id }}
path: cli/test-results/
retention-days: 3
-74
View File
@@ -1,74 +0,0 @@
name: CLI Edge Publish
on:
push:
branches: [main]
paths:
- 'cli/**'
- 'packages/contracts/generated/api/openapi/**'
workflow_dispatch:
concurrency:
group: difyctl-edge-publish
cancel-in-progress: false
jobs:
publish:
name: build + publish edge to R2
runs-on: ${{ github.repository == 'langgenius/dify' && 'depot-ubuntu-24.04' || 'ubuntu-24.04' }}
if: vars.DIFYCTL_R2_BUCKET != ''
defaults:
run:
shell: bash
working-directory: ./cli
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
fetch-depth: 0
- name: Enable cross-arch native prebuilds
working-directory: ./
run: cat cli/scripts/cross-arch.pnpm.yaml >> pnpm-workspace.yaml
- name: Setup web environment
uses: ./.github/actions/setup-web
- name: Setup Bun
uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.2
with:
bun-version-file: cli/.bun-version
- name: Compute edge version
id: ver
run: echo "version=$(node scripts/release-naming.mjs edge-version "$(git rev-parse --short HEAD)")" >> "$GITHUB_OUTPUT"
- name: Compile standalone binaries (all targets, all-or-nothing)
run: |
CLI_VERSION="${{ steps.ver.outputs.version }}" \
DIFYCTL_CHANNEL=edge \
DIFYCTL_COMMIT="$(git rev-parse HEAD)" \
DIFYCTL_BUILD_DATE="$(git log -1 --format=%cI HEAD)" \
pnpm build:bin
- name: Generate sha256 checksums
run: CLI_VERSION="${{ steps.ver.outputs.version }}" scripts/release-write-checksums.sh
- name: Smoke the runner-arch binary
run: ./dist/bin/difyctl-v${{ steps.ver.outputs.version }}-linux-x64 version
- name: Publish to R2
env:
AWS_ACCESS_KEY_ID: ${{ secrets.DIFYCTL_R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.DIFYCTL_R2_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: auto
AWS_REQUEST_CHECKSUM_CALCULATION: WHEN_REQUIRED
AWS_RESPONSE_CHECKSUM_VALIDATION: WHEN_REQUIRED
DIFYCTL_R2_S3_ENDPOINT: ${{ vars.DIFYCTL_R2_S3_ENDPOINT }}
DIFYCTL_R2_BUCKET: ${{ vars.DIFYCTL_R2_BUCKET }}
DIFYCTL_R2_PUBLIC_BASE: ${{ vars.DIFYCTL_R2_PUBLIC_BASE }}
DIFYCTL_COMMIT: ${{ github.sha }}
run: |
DIFYCTL_BUILD_DATE="$(git log -1 --format=%cI HEAD)" \
scripts/release-r2-publish.sh edge "${{ steps.ver.outputs.version }}"
-166
View File
@@ -1,166 +0,0 @@
name: CLI Release
on:
workflow_dispatch:
inputs:
release_tag:
description: Dify release tag to attach difyctl assets to (blank = latest stable)
required: false
type: string
workflow_call:
inputs:
release_tag:
description: Dify release tag to attach difyctl assets to (blank = latest stable)
required: false
type: string
release:
types: [released]
concurrency:
group: difyctl-release
cancel-in-progress: false
jobs:
validate:
name: validate manifest + resolve target Dify release
runs-on: depot-ubuntu-24.04
if: github.repository == 'langgenius/dify'
permissions:
contents: read
defaults:
run:
shell: bash
working-directory: ./cli
outputs:
dify_tag: ${{ steps.resolve.outputs.dify_tag }}
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
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
- name: Resolve target Dify release
id: resolve
env:
GH_TOKEN: ${{ github.token }}
EVENT_TAG: ${{ github.event.release.tag_name }}
INPUT_TAG: ${{ inputs.release_tag }}
run: |
if [ -n "$EVENT_TAG" ]; then
tag="$EVENT_TAG"
elif [ -n "$INPUT_TAG" ]; then
tag="$INPUT_TAG"
else
tag="$(gh api "repos/${GITHUB_REPOSITORY}/releases/latest" --jq .tag_name)"
fi
if [ -z "$tag" ]; then
echo "::error::could not resolve a target Dify release tag"
exit 1
fi
if ! gh release view "$tag" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
echo "::error::target Dify release ${tag} not found"
exit 1
fi
echo "dify_tag=${tag}" >> "$GITHUB_OUTPUT"
echo "::notice::target Dify release ${tag}"
- name: Compatibility check
env:
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
runs-on: depot-ubuntu-24.04
permissions:
contents: write
defaults:
run:
shell: bash
working-directory: ./cli
env:
DIFY_TAG: ${{ needs.validate.outputs.dify_tag }}
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
fetch-depth: 1
- name: Enable cross-arch native prebuilds
working-directory: ./
run: cat cli/scripts/cross-arch.pnpm.yaml >> pnpm-workspace.yaml
- name: Setup web environment
uses: ./.github/actions/setup-web
- name: Export manifest to env
run: node scripts/release-naming.mjs github-env >> "$GITHUB_ENV"
- name: Setup Bun
uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.2
with:
bun-version-file: cli/.bun-version
- name: Compile standalone binaries (all targets)
run: |
DIFYCTL_COMMIT="$(git rev-parse HEAD)" \
DIFYCTL_BUILD_DATE="$(git log -1 --format=%cI HEAD)" \
pnpm build:bin
- name: Generate sha256 checksum file
run: scripts/release-write-checksums.sh
- name: Attach difyctl assets to Dify release
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release upload "$DIFY_TAG" dist/bin/${tagPrefix}* \
--repo "$GITHUB_REPOSITORY" --clobber
- name: Prune stale difyctl assets
env:
GH_TOKEN: ${{ github.token }}
run: |
new_set="$(cd dist/bin && ls ${tagPrefix}*)"
gh release view "$DIFY_TAG" --repo "$GITHUB_REPOSITORY" \
--json assets --jq '.assets[].name' \
| { grep -E "^${tagPrefix}" || true; } \
| while IFS= read -r name; do
if ! printf '%s\n' "$new_set" | grep -qxF -- "$name"; then
echo "::notice::pruning stale asset ${name}"
gh release delete-asset "$DIFY_TAG" "$name" \
--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
-60
View File
@@ -1,60 +0,0 @@
name: CLI Smoke (live dify)
on:
workflow_dispatch:
inputs:
dify_version:
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)"
type: string
required: false
permissions:
contents: read
jobs:
smoke:
runs-on: ubuntu-latest
timeout-minutes: 30
defaults:
run:
shell: bash
steps:
- name: Checkout cli ref
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ inputs.cli_ref || github.ref }}
persist-credentials: false
- name: Setup web environment
uses: ./.github/actions/setup-web
- name: Bring up dify
env:
DIFY_VERSION: ${{ inputs.dify_version }}
run: |
cd docker
cp .env.example .env
DIFY_API_IMAGE_TAG="$DIFY_VERSION" \
DIFY_WEB_IMAGE_TAG="$DIFY_VERSION" \
docker compose up -d api worker web db redis
for i in $(seq 1 60); do
if curl -fsS http://localhost:5001/health >/dev/null 2>&1; then
echo "dify api ready after ${i}s"
break
fi
sleep 1
done
- name: Run smoke against live dify
working-directory: ./cli
run: pnpm exec tsx scripts/run-smoke.ts --base-url http://localhost:5001
- name: Dump dify logs on failure
if: failure()
run: |
cd docker
docker compose logs api worker web --tail=200
-59
View File
@@ -1,59 +0,0 @@
name: CLI Tests
on:
workflow_call:
secrets:
CODECOV_TOKEN:
required: false
permissions:
contents: read
concurrency:
group: cli-tests-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
name: CLI Tests (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [depot-ubuntu-24.04, windows-latest, macos-latest]
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
defaults:
run:
shell: bash
working-directory: ./cli
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: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Validate release manifest
if: matrix.os == 'depot-ubuntu-24.04'
run: scripts/release-validate-manifest.sh
- name: CI pipeline (tree, coverage, build)
run: pnpm run ci
- name: Report coverage
if: ${{ env.CODECOV_TOKEN != '' && matrix.os == 'depot-ubuntu-24.04' }}
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
directory: cli/coverage
flags: cli
env:
CODECOV_TOKEN: ${{ env.CODECOV_TOKEN }}
+7 -86
View File
@@ -8,18 +8,18 @@ concurrency:
cancel-in-progress: true
jobs:
db-migration-test-postgres:
runs-on: depot-ubuntu-24.04
db-migration-test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- name: Setup UV and Python
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
python-version: "3.12"
@@ -37,15 +37,15 @@ jobs:
- name: Prepare middleware env
run: |
cd docker
cp envs/middleware.env.example middleware.env
cp middleware.env.example middleware.env
- name: Set up Middlewares
uses: hoverkraft-tech/compose-action@11beaa1c2dae4e8ed7b1665aa074723b6cecb0e4 # v3.0.0
uses: hoverkraft-tech/compose-action@v2.0.2
with:
compose-file: |
docker/docker-compose.middleware.yaml
services: |
db_postgres
db
redis
- name: Prepare configs
@@ -57,82 +57,3 @@ jobs:
env:
DEBUG: true
run: uv run --directory api flask upgrade-db
db-migration-test-mysql:
runs-on: depot-ubuntu-24.04
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@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
enable-cache: true
python-version: "3.12"
cache-dependency-glob: api/uv.lock
- name: Install dependencies
run: uv sync --project api
- name: Ensure Offline migration are supported
run: |
# upgrade
uv run --directory api flask db upgrade 'base:head' --sql
# downgrade
uv run --directory api flask db downgrade 'head:base' --sql
- name: Prepare middleware env for MySQL
run: |
cd docker
cp envs/middleware.env.example middleware.env
sed -i 's/DB_TYPE=postgresql/DB_TYPE=mysql/' middleware.env
sed -i 's/DB_HOST=db_postgres/DB_HOST=db_mysql/' middleware.env
sed -i 's/DB_PORT=5432/DB_PORT=3306/' middleware.env
sed -i 's/DB_USERNAME=postgres/DB_USERNAME=mysql/' middleware.env
- name: Set up Middlewares
uses: hoverkraft-tech/compose-action@11beaa1c2dae4e8ed7b1665aa074723b6cecb0e4 # v3.0.0
with:
compose-file: |
docker/docker-compose.middleware.yaml
services: |
db_mysql
redis
- name: Prepare configs for MySQL
run: |
cd api
cp .env.example .env
sed -i 's/DB_TYPE=postgresql/DB_TYPE=mysql/' .env
sed -i 's/DB_PORT=5432/DB_PORT=3306/' .env
sed -i 's/DB_USERNAME=postgres/DB_USERNAME=root/' .env
# hoverkraft-tech/compose-action@v2.6.0 only waits for `docker compose up -d`
# to return (container processes started); it does not wait on healthcheck
# status. mysql:8.0's first-time init takes 15-30s, so without an explicit
# wait the migration runs while InnoDB is still initialising and gets
# killed with "Lost connection during query". Poll a real SELECT until it
# succeeds.
- name: Wait for MySQL to accept queries
run: |
set +e
for i in $(seq 1 60); do
if docker run --rm --network host mysql:8.0 \
mysql -h 127.0.0.1 -P 3306 -uroot -pdifyai123456 \
-e 'SELECT 1' >/dev/null 2>&1; then
echo "MySQL ready after ${i}s"
exit 0
fi
sleep 1
done
echo "MySQL not ready after 60s; dumping container logs:"
docker compose -f docker/docker-compose.middleware.yaml --profile mysql logs --tail=200 db_mysql
exit 1
- name: Run DB Migration
env:
DEBUG: true
run: uv run --directory api flask upgrade-db
-28
View File
@@ -1,28 +0,0 @@
name: Deploy Agent
permissions:
contents: read
on:
workflow_run:
workflows: ["Build and Push API & Web"]
branches:
- "deploy/agent"
types:
- completed
jobs:
deploy:
runs-on: depot-ubuntu-24.04
if: |
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.head_branch == 'deploy/agent'
steps:
- name: Deploy to server
uses: appleboy/ssh-action@0ff4204d59e8e51228ff73bce53f80d53301dee2 # v1.2.5
with:
host: ${{ secrets.AGENT_SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
${{ vars.SSH_SCRIPT_AGENT || secrets.SSH_SCRIPT_AGENT }}
+5 -5
View File
@@ -4,21 +4,21 @@ on:
workflow_run:
workflows: ["Build and Push API & Web"]
branches:
- "deploy/dev"
- "deploy/rag-dev"
types:
- completed
jobs:
deploy:
runs-on: depot-ubuntu-24.04
runs-on: ubuntu-latest
if: |
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.head_branch == 'deploy/dev'
github.event.workflow_run.head_branch == 'deploy/rag-dev'
steps:
- name: Deploy to server
uses: appleboy/ssh-action@0ff4204d59e8e51228ff73bce53f80d53301dee2 # v1.2.5
uses: appleboy/ssh-action@v0.1.8
with:
host: ${{ secrets.SSH_HOST }}
host: ${{ secrets.RAG_SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
+9 -21
View File
@@ -13,29 +13,17 @@ on:
jobs:
deploy:
runs-on: depot-ubuntu-24.04
runs-on: ubuntu-latest
if: |
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.head_branch == 'deploy/enterprise'
steps:
- name: trigger deployments
env:
DEV_ENV_ADDRS: ${{ vars.DEV_ENV_ADDRS }}
DEPLOY_SECRET: ${{ secrets.DEPLOY_SECRET }}
run: |
IFS=',' read -ra ENDPOINTS <<< "${DEV_ENV_ADDRS:-}"
BODY='{"project":"dify-api","tag":"deploy-enterprise"}'
for ENDPOINT in "${ENDPOINTS[@]}"; do
ENDPOINT="$(echo "$ENDPOINT" | xargs)"
[ -z "$ENDPOINT" ] && continue
API_SIGNATURE=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$DEPLOY_SECRET" | awk '{print "sha256="$2}')
curl -sSf -X POST \
-H "Content-Type: application/json" \
-H "X-Hub-Signature-256: $API_SIGNATURE" \
-d "$BODY" \
"$ENDPOINT"
done
- name: Deploy to server
uses: appleboy/ssh-action@v0.1.8
with:
host: ${{ secrets.ENTERPRISE_SSH_HOST }}
username: ${{ secrets.ENTERPRISE_SSH_USER }}
password: ${{ secrets.ENTERPRISE_SSH_PASSWORD }}
script: |
${{ vars.ENTERPRISE_SSH_SCRIPT || secrets.ENTERPRISE_SSH_SCRIPT }}
-71
View File
@@ -1,71 +0,0 @@
name: Deploy Knowledge
permissions:
actions: read
contents: read
on:
workflow_run:
workflows: ["Build and Push API & Web"]
branches:
- "deploy/konwledge"
types:
- completed
jobs:
deploy:
runs-on: depot-ubuntu-24.04
if: |
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:
host: ${{ secrets.SSH_NEW_RAG_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
${{ vars.SSH_SCRIPT || secrets.SSH_SCRIPT }}
+28
View File
@@ -0,0 +1,28 @@
name: Deploy RAG Dev
permissions:
contents: read
on:
workflow_run:
workflows: ["Build and Push API & Web"]
branches:
- "deploy/rag-dev"
types:
- completed
jobs:
deploy:
runs-on: ubuntu-latest
if: |
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.head_branch == 'deploy/rag-dev'
steps:
- name: Deploy to server
uses: appleboy/ssh-action@v0.1.8
with:
host: ${{ secrets.RAG_SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
${{ vars.SSH_SCRIPT || secrets.SSH_SCRIPT }}
-28
View File
@@ -1,28 +0,0 @@
name: Deploy SaaS
permissions:
contents: read
on:
workflow_run:
workflows: ["Build and Push API & Web"]
branches:
- "deploy/saas"
types:
- completed
jobs:
deploy:
runs-on: depot-ubuntu-24.04
if: |
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.head_branch == 'deploy/saas'
steps:
- name: Deploy to server
uses: appleboy/ssh-action@0ff4204d59e8e51228ff73bce53f80d53301dee2 # v1.2.5
with:
host: ${{ secrets.SAAS_DEV_SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
${{ vars.SSH_SCRIPT_SAAS_DEV || secrets.SSH_SCRIPT_SAAS_DEV }}
+14 -74
View File
@@ -6,18 +6,7 @@ on:
- "main"
paths:
- api/Dockerfile
- api/Dockerfile.dockerignore
- api/pyproject.toml
- api/uv.lock
- dify-agent/pyproject.toml
- dify-agent/README.md
- dify-agent/src/**
- web/Dockerfile
- dify-agent-runtime/docker/Dockerfile
- dify-agent-runtime/go.mod
- dify-agent-runtime/go.sum
- dify-agent-runtime/cmd/**
- dify-agent-runtime/internal/**
concurrency:
group: docker-build-${{ github.head_ref || github.run_id }}
@@ -25,84 +14,35 @@ concurrency:
jobs:
build-docker:
if: github.event.pull_request.head.repo.full_name == github.repository
runs-on: ${{ matrix.runs_on }}
permissions:
contents: read
id-token: write
runs-on: ubuntu-latest
strategy:
matrix:
include:
- service_name: "api-amd64"
platform: linux/amd64
runs_on: depot-ubuntu-24.04-4
context: "{{defaultContext}}"
file: "api/Dockerfile"
context: "api"
- service_name: "api-arm64"
platform: linux/arm64
runs_on: depot-ubuntu-24.04-4
context: "{{defaultContext}}"
file: "api/Dockerfile"
context: "api"
- service_name: "web-amd64"
platform: linux/amd64
runs_on: depot-ubuntu-24.04-4
context: "{{defaultContext}}"
file: "web/Dockerfile"
context: "web"
- service_name: "web-arm64"
platform: linux/arm64
runs_on: depot-ubuntu-24.04-4
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"
platform: linux/arm64
runs_on: depot-ubuntu-24.04-4
context: "{{defaultContext}}:dify-agent-runtime"
file: "docker/Dockerfile"
context: "web"
steps:
- name: Set up Depot CLI
uses: depot/setup-action@15c09a5f77a0840ad4bce955686522a257853461 # v1.7.1
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Build Docker Image
uses: depot/build-push-action@98e78adca7817480b8185f474a400b451d74e287 # v1.18.0
with:
project: ${{ vars.DEPOT_PROJECT_ID }}
push: false
context: ${{ matrix.context }}
file: ${{ matrix.file }}
build-contexts: ${{ matrix.build_contexts }}
platforms: ${{ matrix.platform }}
build-docker-fork:
if: github.event.pull_request.head.repo.full_name != github.repository
runs-on: ubuntu-24.04
permissions:
contents: read
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"
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
uses: docker/setup-buildx-action@v3
- name: Build Docker Image
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
uses: docker/build-push-action@v6
with:
push: false
context: ${{ matrix.context }}
file: ${{ matrix.file }}
build-contexts: ${{ matrix.build_contexts }}
platforms: linux/amd64
context: "{{defaultContext}}:${{ matrix.context }}"
file: "${{ matrix.file }}"
platforms: ${{ matrix.platform }}
cache-from: type=gha
cache-to: type=gha,mode=max
+16
View File
@@ -0,0 +1,16 @@
#!/bin/bash
yq eval '.services.weaviate.ports += ["8080:8080"]' -i docker/docker-compose.yaml
yq eval '.services.qdrant.ports += ["6333:6333"]' -i docker/docker-compose.yaml
yq eval '.services.chroma.ports += ["8000:8000"]' -i docker/docker-compose.yaml
yq eval '.services["milvus-standalone"].ports += ["19530:19530"]' -i docker/docker-compose.yaml
yq eval '.services.pgvector.ports += ["5433:5432"]' -i docker/docker-compose.yaml
yq eval '.services["pgvecto-rs"].ports += ["5431:5432"]' -i docker/docker-compose.yaml
yq eval '.services["elasticsearch"].ports += ["9200:9200"]' -i docker/docker-compose.yaml
yq eval '.services.couchbase-server.ports += ["8091-8096:8091-8096"]' -i docker/docker-compose.yaml
yq eval '.services.couchbase-server.ports += ["11210:11210"]' -i docker/docker-compose.yaml
yq eval '.services.tidb.ports += ["4000:4000"]' -i docker/tidb/docker-compose.yaml
yq eval '.services.oceanbase.ports += ["2881:2881"]' -i docker/docker-compose.yaml
yq eval '.services.opengauss.ports += ["6600:6600"]' -i docker/docker-compose.yaml
echo "Ports exposed for sandbox, weaviate, tidb, qdrant, chroma, milvus, pgvector, pgvecto-rs, elasticsearch, couchbase, opengauss"
-49
View File
@@ -1,49 +0,0 @@
name: Hotfix Cherry-Pick Provenance
on:
pull_request:
branches:
- 'hotfix/**'
- 'lts/**'
types:
- opened
- edited
- reopened
- ready_for_review
- synchronize
permissions:
contents: read
concurrency:
group: hotfix-cherry-pick-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
jobs:
check-cherry-pick-provenance:
name: Require cherry-pick provenance
runs-on: depot-ubuntu-24.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- name: Fetch PR base, PR head, and main
env:
BASE_REF: ${{ github.base_ref }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
git fetch --no-tags --prune origin \
"+refs/heads/main:refs/remotes/origin/main" \
"+refs/heads/${BASE_REF}:refs/remotes/origin/${BASE_REF}" \
"+refs/pull/${PR_NUMBER}/head:refs/remotes/pull/${PR_NUMBER}/head"
- name: Load checker from main
run: git show origin/main:.github/scripts/check-hotfix-cherry-picks.sh > "$RUNNER_TEMP/check-hotfix-cherry-picks.sh"
- name: Check PR commits
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
MAIN_REF: origin/main
run: bash "$RUNNER_TEMP/check-hotfix-cherry-picks.sh"
-14
View File
@@ -1,14 +0,0 @@
name: "Pull Request Labeler"
on:
pull_request_target:
jobs:
labeler:
permissions:
contents: read
pull-requests: write
runs-on: depot-ubuntu-24.04
steps:
- uses: actions/labeler@bf12e9b00b37c5c0ca2b87b79b2daf7891dbda13 # v7.0.0
with:
sync-labels: true
+19 -518
View File
@@ -3,12 +3,10 @@ name: Main CI Pipeline
on:
pull_request:
branches: ["main"]
merge_group:
push:
branches: ["main"]
types: [checks_requested]
permissions:
actions: write
contents: write
pull-requests: write
checks: write
@@ -19,559 +17,62 @@ concurrency:
cancel-in-progress: true
jobs:
pre_job:
name: Skip Duplicate Checks
runs-on: depot-ubuntu-24.04
outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip || 'false' }}
steps:
- id: skip_check
continue-on-error: true
uses: fkirc/skip-duplicate-actions@b974a9395958c231af965b70070979a577efa578 # v5.3.2
with:
cancel_others: 'true'
concurrent_skipping: same_content_newer
# Check which paths were changed to determine which tests to run
check-changes:
name: Check Changed Files
needs: pre_job
if: needs.pre_job.outputs.should_skip != 'true'
runs-on: depot-ubuntu-24.04
runs-on: ubuntu-latest
outputs:
api-changed: ${{ steps.changes.outputs.api }}
cli-changed: ${{ steps.changes.outputs.cli }}
e2e-changed: ${{ steps.changes.outputs.e2e }}
web-changed: ${{ steps.changes.outputs.web }}
vdb-changed: ${{ steps.changes.outputs.vdb }}
migration-changed: ${{ steps.changes.outputs.migration }}
sandbox-runtime-changed: ${{ steps.changes.outputs.sandbox-runtime }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: changes
with:
filters: |
api:
- 'api/**'
- 'scripts/ast_grep_guard.py'
- 'scripts/check_no_new_getattr.py'
- 'scripts/check_no_new_controller_sqlalchemy.py'
- 'scripts/lint_controller_sqlalchemy.py'
- 'scripts/ast_grep_rules/no_new_getattr.yml'
- 'scripts/ast_grep_rules/no_new_controller_sqlalchemy.yml'
- '.github/workflows/style.yml'
- '.github/workflows/main-ci.yml'
- 'docker/**'
- '.github/workflows/api-tests.yml'
- 'docker/.env.example'
- 'docker/envs/middleware.env.example'
- 'docker/docker-compose.middleware.yaml'
- 'docker/docker-compose-template.yaml'
- 'docker/generate_docker_compose'
- 'docker/ssrf_proxy/**'
- 'docker/volumes/sandbox/conf/**'
cli:
- 'cli/**'
- 'packages/contracts/**'
- 'packages/tsconfig/**'
- 'package.json'
- 'pnpm-lock.yaml'
- 'pnpm-workspace.yaml'
- 'lint.config.ts'
- '.npmrc'
- '.nvmrc'
- '.github/workflows/cli-tests.yml'
- '.github/actions/setup-web/**'
web:
- 'web/**'
- 'packages/**'
- 'package.json'
- 'pnpm-lock.yaml'
- 'pnpm-workspace.yaml'
- '.nvmrc'
- '.github/workflows/web-tests.yml'
- '.github/actions/setup-web/**'
e2e:
- 'api/**'
- 'api/pyproject.toml'
- 'api/uv.lock'
- 'e2e/**'
- 'web/**'
- 'packages/**'
- 'package.json'
- 'pnpm-lock.yaml'
- 'pnpm-workspace.yaml'
- '.nvmrc'
- 'docker/docker-compose.middleware.yaml'
- 'docker/envs/middleware.env.example'
- '.github/workflows/web-e2e.yml'
- '.github/workflows/main-ci.yml'
- '.github/actions/setup-web/**'
vdb:
- 'api/core/rag/datasource/**'
- 'api/tests/integration_tests/vdb/**'
- 'api/conftest.py'
- 'api/tests/pytest_dify.py'
- 'api/providers/vdb/*/tests/**'
- 'docker/**'
- '.github/workflows/vdb-tests.yml'
- 'docker/.env.example'
- 'docker/envs/middleware.env.example'
- 'docker/docker-compose.pytest.ports.yaml'
- 'docker/docker-compose.yaml'
- 'docker/docker-compose-template.yaml'
- 'docker/generate_docker_compose'
- 'docker/certbot/**'
- 'docker/couchbase-server/**'
- 'docker/elasticsearch/**'
- 'docker/iris/**'
- 'docker/nginx/**'
- 'docker/pgvector/**'
- 'docker/ssrf_proxy/**'
- 'docker/startupscripts/**'
- 'docker/tidb/**'
- 'docker/volumes/**'
- 'api/uv.lock'
- 'api/pyproject.toml'
sandbox-runtime:
- 'dify-agent-runtime/**'
- '.github/workflows/sandbox-runtime-tests.yml'
migration:
- 'api/migrations/**'
- 'api/.env.example'
- '.github/workflows/db-migration-test.yml'
- 'docker/.env.example'
- 'docker/envs/middleware.env.example'
- 'docker/docker-compose.middleware.yaml'
- 'docker/docker-compose-template.yaml'
- 'docker/generate_docker_compose'
- 'docker/ssrf_proxy/**'
- 'docker/volumes/sandbox/conf/**'
# Run tests in parallel while always emitting stable required checks.
api-tests-run:
name: Run API Tests
needs:
- pre_job
- check-changes
if: needs.pre_job.outputs.should_skip != 'true' && needs.check-changes.outputs.api-changed == 'true'
uses: ./.github/workflows/api-tests.yml
secrets: inherit
api-tests-skip:
name: Skip API Tests
needs:
- pre_job
- check-changes
if: needs.pre_job.outputs.should_skip != 'true' && needs.check-changes.outputs.api-changed != 'true'
runs-on: depot-ubuntu-24.04
steps:
- name: Report skipped API tests
run: echo "No API-related changes detected; skipping API tests."
# Run tests in parallel
api-tests:
name: API Tests
if: ${{ always() }}
needs:
- pre_job
- check-changes
- api-tests-run
- api-tests-skip
runs-on: depot-ubuntu-24.04
steps:
- name: Finalize API Tests status
env:
SHOULD_SKIP_WORKFLOW: ${{ needs.pre_job.outputs.should_skip }}
TESTS_CHANGED: ${{ needs.check-changes.outputs.api-changed }}
RUN_RESULT: ${{ needs.api-tests-run.result }}
SKIP_RESULT: ${{ needs.api-tests-skip.result }}
run: |
if [[ "$SHOULD_SKIP_WORKFLOW" == 'true' ]]; then
echo "API 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 "API tests ran successfully."
exit 0
fi
echo "API tests were required but finished with result: $RUN_RESULT" >&2
exit 1
fi
if [[ "$SKIP_RESULT" == 'success' ]]; then
echo "API tests were skipped because no API-related files changed."
exit 0
fi
echo "API tests were not required, but the skip job finished with result: $SKIP_RESULT" >&2
exit 1
cli-tests-run:
name: Run CLI Tests
needs:
- pre_job
- check-changes
if: needs.pre_job.outputs.should_skip != 'true' && needs.check-changes.outputs.cli-changed == 'true'
uses: ./.github/workflows/cli-tests.yml
secrets: inherit
cli-tests-skip:
name: Skip CLI Tests
needs:
- pre_job
- check-changes
if: needs.pre_job.outputs.should_skip != 'true' && needs.check-changes.outputs.cli-changed != 'true'
runs-on: depot-ubuntu-24.04
steps:
- name: Report skipped CLI tests
run: echo "No CLI-related changes detected; skipping CLI tests."
cli-tests:
name: CLI Tests
if: ${{ always() }}
needs:
- pre_job
- check-changes
- cli-tests-run
- cli-tests-skip
runs-on: depot-ubuntu-24.04
steps:
- name: Finalize CLI Tests status
env:
SHOULD_SKIP_WORKFLOW: ${{ needs.pre_job.outputs.should_skip }}
TESTS_CHANGED: ${{ needs.check-changes.outputs.cli-changed }}
RUN_RESULT: ${{ needs.cli-tests-run.result }}
SKIP_RESULT: ${{ needs.cli-tests-skip.result }}
run: |
if [[ "$SHOULD_SKIP_WORKFLOW" == 'true' ]]; then
echo "CLI 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 "CLI tests ran successfully."
exit 0
fi
echo "CLI tests were required but finished with result: $RUN_RESULT" >&2
exit 1
fi
if [[ "$SKIP_RESULT" == 'success' ]]; then
echo "CLI tests were skipped because no CLI-related files changed."
exit 0
fi
echo "CLI tests were not required, but the skip job finished with result: $SKIP_RESULT" >&2
exit 1
web-tests-run:
name: Run Web Tests
needs:
- pre_job
- check-changes
if: needs.pre_job.outputs.should_skip != 'true' && needs.check-changes.outputs.web-changed == 'true'
uses: ./.github/workflows/web-tests.yml
secrets: inherit
web-tests-skip:
name: Skip Web Tests
needs:
- pre_job
- check-changes
if: needs.pre_job.outputs.should_skip != 'true' && needs.check-changes.outputs.web-changed != 'true'
runs-on: depot-ubuntu-24.04
steps:
- name: Report skipped web tests
run: echo "No web-related changes detected; skipping web tests."
needs: check-changes
if: needs.check-changes.outputs.api-changed == 'true'
uses: ./.github/workflows/api-tests.yml
web-tests:
name: Web Tests
if: ${{ always() }}
needs:
- pre_job
- check-changes
- web-tests-run
- web-tests-skip
runs-on: depot-ubuntu-24.04
steps:
- name: Finalize Web Tests status
env:
SHOULD_SKIP_WORKFLOW: ${{ needs.pre_job.outputs.should_skip }}
TESTS_CHANGED: ${{ needs.check-changes.outputs.web-changed }}
RUN_RESULT: ${{ needs.web-tests-run.result }}
SKIP_RESULT: ${{ needs.web-tests-skip.result }}
run: |
if [[ "$SHOULD_SKIP_WORKFLOW" == 'true' ]]; then
echo "Web 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 "Web tests ran successfully."
exit 0
fi
echo "Web tests were required but finished with result: $RUN_RESULT" >&2
exit 1
fi
if [[ "$SKIP_RESULT" == 'success' ]]; then
echo "Web tests were skipped because no web-related files changed."
exit 0
fi
echo "Web tests were not required, but the skip job finished with result: $SKIP_RESULT" >&2
exit 1
web-e2e-run:
name: Run Web Full-Stack E2E
needs:
- pre_job
- check-changes
if: needs.pre_job.outputs.should_skip != 'true' && needs.check-changes.outputs.e2e-changed == 'true'
uses: ./.github/workflows/web-e2e.yml
with:
run-external-runtime: false
secrets: inherit
web-e2e-skip:
name: Skip Web Full-Stack E2E
needs:
- pre_job
- check-changes
if: needs.pre_job.outputs.should_skip != 'true' && needs.check-changes.outputs.e2e-changed != 'true'
runs-on: depot-ubuntu-24.04
steps:
- name: Report skipped web full-stack e2e
run: echo "No E2E-related changes detected; skipping web full-stack E2E."
web-e2e:
name: Web Full-Stack E2E
if: ${{ always() }}
needs:
- pre_job
- check-changes
- web-e2e-run
- web-e2e-skip
runs-on: depot-ubuntu-24.04
steps:
- name: Finalize Web Full-Stack E2E status
env:
SHOULD_SKIP_WORKFLOW: ${{ needs.pre_job.outputs.should_skip }}
TESTS_CHANGED: ${{ needs.check-changes.outputs.e2e-changed }}
RUN_RESULT: ${{ needs.web-e2e-run.result }}
SKIP_RESULT: ${{ needs.web-e2e-skip.result }}
run: |
if [[ "$SHOULD_SKIP_WORKFLOW" == 'true' ]]; then
echo "Web full-stack E2E was 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 "Web full-stack E2E ran successfully."
exit 0
fi
echo "Web full-stack E2E was required but finished with result: $RUN_RESULT" >&2
exit 1
fi
if [[ "$SKIP_RESULT" == 'success' ]]; then
echo "Web full-stack E2E was skipped because no E2E-related files changed."
exit 0
fi
echo "Web full-stack E2E was not required, but the skip job finished with result: $SKIP_RESULT" >&2
exit 1
needs: check-changes
if: needs.check-changes.outputs.web-changed == 'true'
uses: ./.github/workflows/web-tests.yml
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 }}
vdb-tests-run:
name: Run VDB Tests
needs:
- pre_job
- check-changes
if: needs.pre_job.outputs.should_skip != 'true' && needs.check-changes.outputs.vdb-changed == 'true'
uses: ./.github/workflows/vdb-tests.yml
vdb-tests-skip:
name: Skip VDB Tests
needs:
- pre_job
- check-changes
if: needs.pre_job.outputs.should_skip != 'true' && needs.check-changes.outputs.vdb-changed != 'true'
runs-on: depot-ubuntu-24.04
steps:
- name: Report skipped VDB tests
run: echo "No VDB-related changes detected; skipping VDB tests."
vdb-tests:
name: VDB Tests
if: ${{ always() }}
needs:
- pre_job
- check-changes
- vdb-tests-run
- vdb-tests-skip
runs-on: depot-ubuntu-24.04
steps:
- name: Finalize VDB Tests status
env:
SHOULD_SKIP_WORKFLOW: ${{ needs.pre_job.outputs.should_skip }}
TESTS_CHANGED: ${{ needs.check-changes.outputs.vdb-changed }}
RUN_RESULT: ${{ needs.vdb-tests-run.result }}
SKIP_RESULT: ${{ needs.vdb-tests-skip.result }}
run: |
if [[ "$SHOULD_SKIP_WORKFLOW" == 'true' ]]; then
echo "VDB 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 "VDB tests ran successfully."
exit 0
fi
echo "VDB tests were required but finished with result: $RUN_RESULT" >&2
exit 1
fi
if [[ "$SKIP_RESULT" == 'success' ]]; then
echo "VDB tests were skipped because no VDB-related files changed."
exit 0
fi
echo "VDB tests were not required, but the skip job finished with result: $SKIP_RESULT" >&2
exit 1
db-migration-test-run:
name: Run DB Migration Test
needs:
- pre_job
- check-changes
if: needs.pre_job.outputs.should_skip != 'true' && needs.check-changes.outputs.migration-changed == 'true'
uses: ./.github/workflows/db-migration-test.yml
db-migration-test-skip:
name: Skip DB Migration Test
needs:
- pre_job
- check-changes
if: needs.pre_job.outputs.should_skip != 'true' && needs.check-changes.outputs.migration-changed != 'true'
runs-on: depot-ubuntu-24.04
steps:
- name: Report skipped DB migration tests
run: echo "No migration-related changes detected; skipping DB migration tests."
needs: check-changes
if: needs.check-changes.outputs.vdb-changed == 'true'
uses: ./.github/workflows/vdb-tests.yml
db-migration-test:
name: DB Migration Test
if: ${{ always() }}
needs:
- pre_job
- check-changes
- db-migration-test-run
- db-migration-test-skip
runs-on: depot-ubuntu-24.04
steps:
- name: Finalize DB Migration Test status
env:
SHOULD_SKIP_WORKFLOW: ${{ needs.pre_job.outputs.should_skip }}
TESTS_CHANGED: ${{ needs.check-changes.outputs.migration-changed }}
RUN_RESULT: ${{ needs.db-migration-test-run.result }}
SKIP_RESULT: ${{ needs.db-migration-test-skip.result }}
run: |
if [[ "$SHOULD_SKIP_WORKFLOW" == 'true' ]]; then
echo "DB migration 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 "DB migration tests ran successfully."
exit 0
fi
echo "DB migration tests were required but finished with result: $RUN_RESULT" >&2
exit 1
fi
if [[ "$SKIP_RESULT" == 'success' ]]; then
echo "DB migration tests were skipped because no migration-related files changed."
exit 0
fi
echo "DB migration tests were not required, but the skip job finished with result: $SKIP_RESULT" >&2
exit 1
sandbox-runtime-tests-run:
name: Run Sandbox Runtime Tests
needs:
- pre_job
- check-changes
if: needs.pre_job.outputs.should_skip != 'true' && needs.check-changes.outputs.sandbox-runtime-changed == 'true'
uses: ./.github/workflows/sandbox-runtime-tests.yml
secrets: inherit
sandbox-runtime-tests-skip:
name: Skip Sandbox Runtime Tests
needs:
- pre_job
- check-changes
if: needs.pre_job.outputs.should_skip != 'true' && needs.check-changes.outputs.sandbox-runtime-changed != 'true'
runs-on: depot-ubuntu-24.04
steps:
- name: Report skipped sandbox runtime tests
run: echo "No sandbox-runtime-related changes detected; skipping sandbox runtime tests."
sandbox-runtime-tests:
name: Sandbox Runtime Tests
if: ${{ always() }}
needs:
- pre_job
- check-changes
- sandbox-runtime-tests-run
- sandbox-runtime-tests-skip
runs-on: depot-ubuntu-24.04
steps:
- name: Finalize Sandbox Runtime Tests status
env:
SHOULD_SKIP_WORKFLOW: ${{ needs.pre_job.outputs.should_skip }}
TESTS_CHANGED: ${{ needs.check-changes.outputs.sandbox-runtime-changed }}
RUN_RESULT: ${{ needs.sandbox-runtime-tests-run.result }}
SKIP_RESULT: ${{ needs.sandbox-runtime-tests-skip.result }}
run: |
if [[ "$SHOULD_SKIP_WORKFLOW" == 'true' ]]; then
echo "Sandbox runtime 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 "Sandbox runtime tests ran successfully."
exit 0
fi
echo "Sandbox runtime tests were required but finished with result: $RUN_RESULT" >&2
exit 1
fi
if [[ "$SKIP_RESULT" == 'success' ]]; then
echo "Sandbox runtime tests were skipped because no sandbox-runtime-related files changed."
exit 0
fi
echo "Sandbox runtime tests were not required, but the skip job finished with result: $SKIP_RESULT" >&2
exit 1
needs: check-changes
if: needs.check-changes.outputs.migration-changed == 'true'
uses: ./.github/workflows/db-migration-test.yml
-94
View File
@@ -1,94 +0,0 @@
name: Post-Merge Checks
on:
push:
branches: ["main"]
permissions:
contents: read
concurrency:
group: post-merge-${{ github.sha }}
cancel-in-progress: false
jobs:
check-changes:
name: Check Changed Files
runs-on: depot-ubuntu-24.04
outputs:
external-e2e-changed: ${{ steps.changes.outputs.external_e2e }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2
id: changes
with:
filters: |
external_e2e:
- 'e2e/features/agent-v2/**'
- 'e2e/features/step-definitions/agent-v2/**'
- 'e2e/features/step-definitions/common/**'
- 'e2e/features/support/**'
- 'e2e/fixtures/auth.ts'
- 'e2e/fixtures/test-materials/**'
- 'e2e/scripts/**'
- 'e2e/support/**'
- 'e2e/cucumber.config.ts'
- 'e2e/package.json'
- 'e2e/test-env.ts'
- 'e2e/tsconfig.json'
- 'e2e/tsx-register.js'
- 'package.json'
- 'pnpm-lock.yaml'
- '.nvmrc'
- '.github/workflows/post-merge.yml'
- '.github/workflows/web-e2e.yml'
- '.github/actions/setup-web/**'
- 'docker/docker-compose.middleware.yaml'
- 'docker/envs/middleware.env.example'
- 'dify-agent/**'
- 'dify-agent-runtime/**'
- 'api/pyproject.toml'
- 'api/uv.lock'
- 'api/tests/integration_tests/.env.example'
- 'api/clients/agent_backend/**'
- 'api/core/app/apps/agent_app/**'
- 'api/core/workflow/nodes/agent_v2/**'
- 'api/controllers/console/agent/**'
- 'api/services/agent/**'
- 'api/core/plugin/**'
- 'api/services/plugin/**'
- 'api/core/tools/**'
- 'api/services/tools/**'
- 'packages/contracts/package.json'
- 'packages/contracts/generated/api/console/agent/**'
- 'packages/contracts/generated/api/console/apps/**'
- 'packages/contracts/generated/api/console/datasets/**'
- 'packages/contracts/generated/api/console/orpc.gen.ts'
- 'packages/contracts/generated/api/console/workspaces/**'
- 'packages/contracts/generated/api/service/**'
- 'web/features/agent-v2/**'
- 'web/app/(commonLayout)/agents/**'
- 'web/app/(commonLayout)/@detailSidebar/agents/**'
- 'web/app/(commonLayout)/roster/**'
- 'web/app/components/base/chat/chat/**'
- 'web/app/components/base/voice-input/**'
- 'web/app/components/workflow/nodes/agent-v2/**'
- 'web/i18n/en-US/agent-v-2.json'
- 'web/i18n/en-US/common.json'
- 'web/service/base.ts'
- 'web/service/client.ts'
- 'web/service/console-link.ts'
- 'web/service/console-openapi-url.ts'
- 'web/service/console-router-loader.ts'
- 'web/service/share.ts'
- 'web/package.json'
- 'pnpm-workspace.yaml'
external-e2e:
name: External Runtime E2E
needs: check-changes
if: needs.check-changes.outputs.external-e2e-changed == 'true'
uses: ./.github/workflows/web-e2e.yml
with:
run-external-runtime: true
secrets: inherit
-104
View File
@@ -1,104 +0,0 @@
name: Comment with Pyrefly Diff
on:
workflow_run:
workflows:
- Pyrefly Diff Check
types:
- completed
permissions: {}
jobs:
comment:
name: Comment PR with pyrefly diff
runs-on: depot-ubuntu-24.04
permissions:
actions: read
contents: read
issues: write
pull-requests: write
if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.pull_requests[0].head.repo.full_name != github.repository }}
steps:
- name: Download pyrefly diff artifact
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{ github.event.workflow_run.id }},
});
const match = artifacts.data.artifacts.find((artifact) =>
artifact.name === 'pyrefly_diff'
);
if (!match) {
throw new Error('pyrefly_diff artifact not found');
}
const download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: match.id,
archive_format: 'zip',
});
fs.writeFileSync('pyrefly_diff.zip', Buffer.from(download.data));
- name: Unzip artifact
run: unzip -o pyrefly_diff.zip
- name: Post comment
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
let diff = fs.readFileSync('pyrefly_diff.txt', { encoding: 'utf8' });
let prNumber = null;
try {
prNumber = parseInt(fs.readFileSync('pr_number.txt', { encoding: 'utf8' }), 10);
} catch (err) {
// Fallback to workflow_run payload if artifact is missing or incomplete.
const prs = context.payload.workflow_run.pull_requests || [];
if (prs.length > 0 && prs[0].number) {
prNumber = prs[0].number;
}
}
if (!prNumber) {
throw new Error('PR number not found in artifact or workflow_run payload');
}
const MAX_CHARS = 65000;
if (diff.length > MAX_CHARS) {
diff = diff.slice(0, MAX_CHARS);
diff = diff.slice(0, diff.lastIndexOf('\\n'));
diff += '\\n\\n... (truncated) ...';
}
if (diff.trim()) {
const body = '### Pyrefly Diff\n<details>\n<summary>base → PR</summary>\n\n```diff\n' + diff + '\n```\n</details>';
const marker = '### Pyrefly Diff';
const { data: comments } = await github.rest.issues.listComments({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
});
const existing = comments.find((comment) => comment.body.startsWith(marker));
if (existing) {
await github.rest.issues.updateComment({
comment_id: existing.id,
owner: context.repo.owner,
repo: context.repo.repo,
body,
});
} else {
await github.rest.issues.createComment({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
body,
});
}
}
-128
View File
@@ -1,128 +0,0 @@
name: Pyrefly Diff Check
on:
pull_request:
paths:
- 'api/**/*.py'
permissions:
contents: read
jobs:
pyrefly-diff:
runs-on: depot-ubuntu-24.04
permissions:
contents: read
issues: write
pull-requests: write
steps:
- name: Checkout PR branch
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- name: Setup Python & UV
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
enable-cache: true
- name: Install dependencies
run: uv sync --project api --dev
- name: Prepare diagnostics extractor
run: |
git show ${{ github.event.pull_request.head.sha }}:api/libs/pyrefly_diagnostics.py > /tmp/pyrefly_diagnostics.py
- name: Run pyrefly on PR branch
run: |
uv run --directory api --dev pyrefly check 2>&1 \
| uv run --directory api python /tmp/pyrefly_diagnostics.py > /tmp/pyrefly_pr.txt || true
- name: Checkout base branch
run: git checkout ${{ github.base_ref }}
- name: Run pyrefly on base branch
run: |
uv run --directory api --dev pyrefly check 2>&1 \
| uv run --directory api python /tmp/pyrefly_diagnostics.py > /tmp/pyrefly_base.txt || true
- name: Compute diff
run: |
diff -u /tmp/pyrefly_base.txt /tmp/pyrefly_pr.txt > pyrefly_diff.txt || true
- name: Check if line counts match
id: line_count_check
run: |
base_lines=$(wc -l < /tmp/pyrefly_base.txt)
pr_lines=$(wc -l < /tmp/pyrefly_pr.txt)
if [ "$base_lines" -eq "$pr_lines" ]; then
echo "same=true" >> $GITHUB_OUTPUT
else
echo "same=false" >> $GITHUB_OUTPUT
fi
- name: Save PR number
run: |
echo ${{ github.event.pull_request.number }} > pr_number.txt
- name: Upload pyrefly diff
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: pyrefly_diff
path: |
pyrefly_diff.txt
pr_number.txt
- name: Comment PR with pyrefly diff
if: ${{ github.event.pull_request.head.repo.full_name == github.repository && steps.line_count_check.outputs.same == 'false' }}
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
let diff = fs.readFileSync('pyrefly_diff.txt', { encoding: 'utf8' });
const prNumber = context.payload.pull_request.number;
const MAX_CHARS = 65000;
if (diff.length > MAX_CHARS) {
diff = diff.slice(0, MAX_CHARS);
diff = diff.slice(0, diff.lastIndexOf('\n'));
diff += '\n\n... (truncated) ...';
}
const body = diff.trim()
? [
'### Pyrefly Diff',
'<details>',
'<summary>base → PR</summary>',
'',
'```diff',
diff,
'```',
'</details>',
].join('\n')
: '### Pyrefly Diff\nNo changes detected.';
const marker = '### Pyrefly Diff';
const { data: comments } = await github.rest.issues.listComments({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
});
const existing = comments.find((comment) => comment.body.startsWith(marker));
if (existing) {
await github.rest.issues.updateComment({
comment_id: existing.id,
owner: context.repo.owner,
repo: context.repo.repo,
body,
});
} else {
await github.rest.issues.createComment({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
body,
});
}
@@ -1,118 +0,0 @@
name: Comment with Pyrefly Type Coverage
on:
workflow_run:
workflows:
- Pyrefly Type Coverage
types:
- completed
permissions: {}
jobs:
comment:
name: Comment PR with type coverage
runs-on: depot-ubuntu-24.04
permissions:
actions: read
contents: read
issues: write
pull-requests: write
if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.pull_requests[0].head.repo.full_name != github.repository }}
steps:
- name: Checkout default branch (trusted code)
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup Python & UV
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
enable-cache: true
- name: Install dependencies
run: uv sync --project api --dev
- name: Download type coverage artifact
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{ github.event.workflow_run.id }},
});
const match = artifacts.data.artifacts.find((artifact) =>
artifact.name === 'pyrefly_type_coverage'
);
if (!match) {
throw new Error('pyrefly_type_coverage artifact not found');
}
const download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: match.id,
archive_format: 'zip',
});
fs.writeFileSync('pyrefly_type_coverage.zip', Buffer.from(download.data));
- name: Unzip artifact
run: unzip -o pyrefly_type_coverage.zip
- name: Render coverage markdown from structured data
id: render
run: |
comment_body="$(uv run --directory api python libs/pyrefly_type_coverage.py \
--base "$GITHUB_WORKSPACE/base_report.json" \
< "$GITHUB_WORKSPACE/pr_report.json")"
{
echo "### Pyrefly Type Coverage"
echo ""
echo "$comment_body"
} > /tmp/type_coverage_comment.md
- name: Post comment
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
const body = fs.readFileSync('/tmp/type_coverage_comment.md', { encoding: 'utf8' });
let prNumber = null;
try {
prNumber = parseInt(fs.readFileSync('pr_number.txt', { encoding: 'utf8' }), 10);
} catch (err) {
const prs = context.payload.workflow_run.pull_requests || [];
if (prs.length > 0 && prs[0].number) {
prNumber = prs[0].number;
}
}
if (!prNumber) {
throw new Error('PR number not found in artifact or workflow_run payload');
}
// Update existing comment if one exists, otherwise create new
const { data: comments } = await github.rest.issues.listComments({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
});
const marker = '### Pyrefly Type Coverage';
const existing = comments.find(c => c.body.startsWith(marker));
if (existing) {
await github.rest.issues.updateComment({
comment_id: existing.id,
owner: context.repo.owner,
repo: context.repo.repo,
body,
});
} else {
await github.rest.issues.createComment({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
body,
});
}
-124
View File
@@ -1,124 +0,0 @@
name: Pyrefly Type Coverage
on:
pull_request:
paths:
- 'api/**/*.py'
permissions:
contents: read
jobs:
pyrefly-type-coverage:
runs-on: depot-ubuntu-24.04
permissions:
contents: read
issues: write
pull-requests: write
steps:
- name: Checkout PR branch
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- name: Setup Python & UV
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
enable-cache: true
- name: Install dependencies
run: uv sync --project api --dev
- name: Run pyrefly report on PR branch
run: |
uv run --directory api --dev pyrefly report 2>/dev/null > /tmp/pyrefly_report_pr.tmp && \
mv /tmp/pyrefly_report_pr.tmp /tmp/pyrefly_report_pr.json || \
echo '{}' > /tmp/pyrefly_report_pr.json
- name: Save helper script from base branch
run: |
git show ${{ github.event.pull_request.base.sha }}:api/libs/pyrefly_type_coverage.py > /tmp/pyrefly_type_coverage.py 2>/dev/null \
|| cp api/libs/pyrefly_type_coverage.py /tmp/pyrefly_type_coverage.py
- name: Checkout base branch
run: git checkout ${{ github.base_ref }}
- name: Run pyrefly report on base branch
run: |
uv run --directory api --dev pyrefly report 2>/dev/null > /tmp/pyrefly_report_base.tmp && \
mv /tmp/pyrefly_report_base.tmp /tmp/pyrefly_report_base.json || \
echo '{}' > /tmp/pyrefly_report_base.json
- name: Generate coverage comparison
id: coverage
run: |
comment_body="$(uv run --directory api python /tmp/pyrefly_type_coverage.py \
--base /tmp/pyrefly_report_base.json \
< /tmp/pyrefly_report_pr.json)"
{
echo "### Pyrefly Type Coverage"
echo ""
echo "$comment_body"
} | tee -a "$GITHUB_STEP_SUMMARY" > /tmp/type_coverage_comment.md
# Save structured data for the fork-PR comment workflow
cp /tmp/pyrefly_report_pr.json pr_report.json
cp /tmp/pyrefly_report_base.json base_report.json
# Keep fork-PR comments correct while the trusted workflow_run job is
# still using the default-branch renderer, which resolves --base from api/.
cp /tmp/pyrefly_report_base.json api/base_report.json
- name: Save PR number
run: |
echo ${{ github.event.pull_request.number }} > pr_number.txt
- name: Upload type coverage artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: pyrefly_type_coverage
path: |
pr_report.json
base_report.json
api/base_report.json
pr_number.txt
- name: Comment PR with type coverage
if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
const marker = '### Pyrefly Type Coverage';
let body;
try {
body = fs.readFileSync('/tmp/type_coverage_comment.md', { encoding: 'utf8' });
} catch {
body = `${marker}\n\n_Coverage report unavailable._`;
}
const prNumber = context.payload.pull_request.number;
// Update existing comment if one exists, otherwise create new
const { data: comments } = await github.rest.issues.listComments({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
});
const existing = comments.find(c => c.body.startsWith(marker));
if (existing) {
await github.rest.issues.updateComment({
comment_id: existing.id,
owner: context.repo.owner,
repo: context.repo.repo,
body,
});
} else {
await github.rest.issues.createComment({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
body,
});
}
@@ -1,98 +0,0 @@
name: Sandbox Runtime Tests
on:
workflow_call:
permissions:
contents: read
concurrency:
group: sandbox-runtime-tests-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
sandbox-runtime-unit:
name: Sandbox Runtime Unit Tests
runs-on: depot-ubuntu-24.04
defaults:
run:
shell: bash
working-directory: dify-agent-runtime
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: dify-agent-runtime/go.mod
cache-dependency-path: dify-agent-runtime/go.sum
- name: Run unit tests
run: go test -race -count=1 ./...
sandbox-runtime-lint:
name: Sandbox Runtime Lint
runs-on: depot-ubuntu-24.04
defaults:
run:
shell: bash
working-directory: dify-agent-runtime
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: dify-agent-runtime/go.mod
cache-dependency-path: dify-agent-runtime/go.sum
- name: Run golangci-lint
uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v6.5.0
with:
working-directory: dify-agent-runtime
version: latest
sandbox-runtime-integration:
name: Sandbox Runtime Integration Tests
runs-on: depot-ubuntu-24.04
defaults:
run:
shell: bash
working-directory: dify-agent-runtime
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: dify-agent-runtime/go.mod
cache-dependency-path: dify-agent-runtime/go.sum
- name: Build and start runtime
run: make integration-up
- name: Run integration tests
run: make integration-test
- name: Dump container logs on failure
if: failure()
run: make integration-logs || true
- name: Stop runtime container
if: always()
run: make integration-down
@@ -1,28 +0,0 @@
name: Semantic Pull Request
on:
pull_request:
types:
- opened
- edited
- reopened
- synchronize
merge_group:
branches: ["main"]
types: [checks_requested]
jobs:
lint:
name: Validate PR title
permissions:
pull-requests: read
runs-on: depot-ubuntu-24.04
steps:
- name: Complete merge group check
if: github.event_name == 'merge_group'
run: echo "Semantic PR title validation is handled on pull requests."
- name: Check title
if: github.event_name == 'pull_request'
uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+5 -5
View File
@@ -12,19 +12,19 @@ on:
jobs:
stale:
runs-on: depot-ubuntu-24.04
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@1e223db275d687790206a7acac4d1a11bd6fe629 # v10.4.0
- uses: actions/stale@v5
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: "Close due to it's no longer active, if you have any questions, you can reopen it."
stale-pr-message: "Close due to it's no longer active, 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'
any-of-labels: 'duplicate,question,invalid,wontfix,no-issue-activity,no-pr-activity,enhancement,cant-reproduce,help-wanted'
+49 -103
View File
@@ -2,10 +2,6 @@ name: Style check
on:
workflow_call:
inputs:
base-rev:
required: true
type: string
concurrency:
group: style-${{ github.head_ref || github.run_id }}
@@ -19,33 +15,25 @@ permissions:
jobs:
python-style:
name: Python Style
runs-on: depot-ubuntu-24.04
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@v4
with:
persist-credentials: false
fetch-depth: 0
- name: Check changed files
id: changed-files
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
uses: tj-actions/changed-files@v46
with:
files: |
api/**
scripts/ast_grep_guard.py
scripts/check_no_new_getattr.py
scripts/check_no_new_controller_sqlalchemy.py
scripts/lint_controller_sqlalchemy.py
scripts/ast_grep_rules/no_new_getattr.yml
scripts/ast_grep_rules/no_new_controller_sqlalchemy.yml
.github/workflows/style.yml
.github/workflows/main-ci.yml
- 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@v6
with:
enable-cache: false
python-version: "3.12"
@@ -55,27 +43,9 @@ jobs:
if: steps.changed-files.outputs.any_changed == 'true'
run: uv sync --project api --dev
- name: Run Import Linter
- name: Run Basedpyright Checks
if: steps.changed-files.outputs.any_changed == 'true'
run: uv run --directory api --dev lint-imports
- name: Run Response Contract Linter
if: steps.changed-files.outputs.any_changed == 'true'
run: uv run --project api --dev python api/dev/lint_response_contracts.py --fail-on-mismatch
- name: Run No New Getattr Guard
if: steps.changed-files.outputs.any_changed == 'true'
run: uv run --project api python scripts/check_no_new_getattr.py --base-rev "${{ inputs.base-rev }}"
- name: Run No New Controller SQLAlchemy Guard
if: steps.changed-files.outputs.any_changed == 'true'
run: uv run --project api python scripts/check_no_new_controller_sqlalchemy.py --base-rev "${{ inputs.base-rev }}"
- name: Run Type Checks
if: steps.changed-files.outputs.any_changed == 'true'
env:
PYREFLY_OUTPUT_FORMAT: github
run: make type-check-core
run: dev/basedpyright-check
- name: Dotenv check
if: steps.changed-files.outputs.any_changed == 'true'
@@ -83,117 +53,93 @@ jobs:
web-style:
name: Web Style
runs-on: depot-ubuntu-24.04
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./web
permissions:
checks: write
pull-requests: read
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Check changed files
id: changed-files
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
uses: tj-actions/changed-files@v46
with:
files: |
web/**
e2e/**
sdks/nodejs-client/**
packages/**
package.json
pnpm-lock.yaml
pnpm-workspace.yaml
.nvmrc
.github/workflows/style.yml
.github/actions/setup-web/**
files: web/**
- name: Setup web environment
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
package_json_file: web/package.json
run_install: false
- name: Setup NodeJS
uses: actions/setup-node@v4
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/actions/setup-web
with:
node-version: 22
cache: pnpm
cache-dependency-path: ./web/package.json
- name: Web tsslint
- name: Web dependencies
if: steps.changed-files.outputs.any_changed == 'true'
env:
NODE_OPTIONS: --max-old-space-size=4096
run: vp run lint:tss
working-directory: ./web
run: pnpm install --frozen-lockfile
- name: Web dead code check
- name: Web style check
if: steps.changed-files.outputs.any_changed == 'true'
run: vp run knip
working-directory: ./web
run: |
pnpm run lint
pnpm run eslint
- name: Web dead code check production
if: steps.changed-files.outputs.any_changed == 'true'
run: vp run knip:production
- name: Web production unused declarations check
if: steps.changed-files.outputs.any_changed == 'true'
run: vp run knip:production-unused-check
ts-common-style:
name: TS Common
runs-on: depot-ubuntu-24.04-4
permissions:
checks: write
pull-requests: read
docker-compose-template:
name: Docker Compose Template
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Check changed files
id: changed-files
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
uses: tj-actions/changed-files@v46
with:
files: |
web/**
cli/**
e2e/**
sdks/nodejs-client/**
packages/**
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
.github/actions/setup-web/**
docker/generate_docker_compose
docker/.env.example
docker/docker-compose-template.yaml
docker/docker-compose.yaml
- name: Setup web environment
- name: Generate Docker Compose
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/actions/setup-web
run: |
cd docker
./generate_docker_compose
- name: Static check
- name: Check for changes
if: steps.changed-files.outputs.any_changed == 'true'
run: pnpm -w check
run: git diff --exit-code
superlinter:
name: SuperLinter
runs-on: depot-ubuntu-24.04
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- name: Check changed files
id: changed-files
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
uses: tj-actions/changed-files@v46
with:
files: |
**.sh
@@ -204,7 +150,7 @@ jobs:
.editorconfig
- name: Super-linter
uses: super-linter/super-linter/slim@4ce20838b8ab83717e78138c5b3a1407148e0918 # v8.7.0
uses: super-linter/super-linter/slim@v8
if: steps.changed-files.outputs.any_changed == 'true'
env:
BASH_SEVERITY: warning
+9 -8
View File
@@ -6,9 +6,6 @@ on:
- main
paths:
- sdks/**
- package.json
- pnpm-lock.yaml
- pnpm-workspace.yaml
concurrency:
group: sdk-tests-${{ github.head_ref || github.run_id }}
@@ -17,21 +14,25 @@ concurrency:
jobs:
build:
name: unit test for Node.js SDK
runs-on: depot-ubuntu-24.04
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16, 18, 20, 22]
defaults:
run:
working-directory: sdks/nodejs-client
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Use Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: 22
node-version: ${{ matrix.node-version }}
cache: ''
cache-dependency-path: 'pnpm-lock.yaml'
@@ -0,0 +1,88 @@
name: Check i18n Files and Create PR
on:
push:
branches: [main]
paths:
- 'web/i18n/en-US/*.ts'
permissions:
contents: write
pull-requests: write
jobs:
check-and-update:
if: github.repository == 'langgenius/dify'
runs-on: ubuntu-latest
defaults:
run:
working-directory: web
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
token: ${{ secrets.GITHUB_TOKEN }}
- name: Check for file changes in i18n/en-US
id: check_files
run: |
recent_commit_sha=$(git rev-parse HEAD)
second_recent_commit_sha=$(git rev-parse HEAD~1)
changed_files=$(git diff --name-only $recent_commit_sha $second_recent_commit_sha -- 'i18n/en-US/*.ts')
echo "Changed files: $changed_files"
if [ -n "$changed_files" ]; then
echo "FILES_CHANGED=true" >> $GITHUB_ENV
file_args=""
for file in $changed_files; do
filename=$(basename "$file" .ts)
file_args="$file_args --file=$filename"
done
echo "FILE_ARGS=$file_args" >> $GITHUB_ENV
echo "File arguments: $file_args"
else
echo "FILES_CHANGED=false" >> $GITHUB_ENV
fi
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
package_json_file: web/package.json
run_install: false
- name: Set up Node.js
if: env.FILES_CHANGED == 'true'
uses: actions/setup-node@v4
with:
node-version: 'lts/*'
cache: pnpm
cache-dependency-path: ./web/package.json
- name: Install dependencies
if: env.FILES_CHANGED == 'true'
working-directory: ./web
run: pnpm install --frozen-lockfile
- name: Generate i18n translations
if: env.FILES_CHANGED == 'true'
working-directory: ./web
run: pnpm run auto-gen-i18n ${{ env.FILE_ARGS }}
- name: Generate i18n type definitions
if: env.FILES_CHANGED == 'true'
working-directory: ./web
run: pnpm run gen:i18n-types
- name: Create Pull Request
if: env.FILES_CHANGED == 'true'
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: Update i18n files and type definitions based on en-US changes
title: 'chore: translate i18n files and update type definitions'
body: |
This PR was automatically created to update i18n files and TypeScript type definitions based on changes in en-US locale.
**Changes included:**
- Updated translation files for all locales
- Regenerated TypeScript type definitions for type safety
branch: chore/automated-i18n-updates
-345
View File
@@ -1,345 +0,0 @@
name: Translate i18n Files with Claude Code
# Note: claude-code-action doesn't support push events directly.
# Push events are bridged by trigger-i18n-sync.yml via repository_dispatch.
on:
repository_dispatch:
types: [i18n-sync]
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.'
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.'
required: false
type: string
mode:
description: 'Sync mode: incremental (compare with previous en-US revision) or full (sync all keys in scope)'
required: false
default: incremental
type: choice
options:
- incremental
- full
permissions:
contents: write
pull-requests: write
concurrency:
group: translate-i18n-${{ github.event_name }}-${{ github.ref }}
cancel-in-progress: false
jobs:
translate:
if: github.repository == 'langgenius/dify'
runs-on: depot-ubuntu-24.04
timeout-minutes: 120
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Configure Git
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
- name: Setup web environment
uses: ./.github/actions/setup-web
- name: Prepare sync context
id: context
shell: bash
run: |
DEFAULT_TARGET_LANGS=$(awk "
/value: '/ {
value=\$2
gsub(/[',]/, \"\", value)
}
/supported: true/ && value != \"en-US\" {
printf \"%s \", value
}
" web/i18n-config/languages.ts | sed 's/[[:space:]]*$//')
generate_changes_json() {
node .github/scripts/generate-i18n-changes.mjs
}
if [ "${{ github.event_name }}" = "repository_dispatch" ]; then
BASE_SHA="${{ github.event.client_payload.base_sha }}"
HEAD_SHA="${{ github.event.client_payload.head_sha }}"
CHANGED_FILES="${{ github.event.client_payload.changed_files }}"
TARGET_LANGS="$DEFAULT_TARGET_LANGS"
SYNC_MODE="${{ github.event.client_payload.sync_mode || 'incremental' }}"
if [ -n "${{ github.event.client_payload.changes_base64 }}" ]; then
printf '%s' '${{ github.event.client_payload.changes_base64 }}' | base64 -d > /tmp/i18n-changes.json
CHANGES_AVAILABLE="true"
CHANGES_SOURCE="embedded"
elif [ -n "$BASE_SHA" ] && [ -n "$CHANGED_FILES" ]; then
export BASE_SHA HEAD_SHA CHANGED_FILES
generate_changes_json
CHANGES_AVAILABLE="true"
CHANGES_SOURCE="recomputed"
else
printf '%s' '{"baseSha":"","headSha":"","files":[],"changes":{}}' > /tmp/i18n-changes.json
CHANGES_AVAILABLE="false"
CHANGES_SOURCE="unavailable"
fi
else
BASE_SHA=""
HEAD_SHA=$(git rev-parse HEAD)
if [ -n "${{ github.event.inputs.languages }}" ]; then
TARGET_LANGS="${{ github.event.inputs.languages }}"
else
TARGET_LANGS="$DEFAULT_TARGET_LANGS"
fi
SYNC_MODE="${{ github.event.inputs.mode || 'incremental' }}"
if [ -n "${{ github.event.inputs.files }}" ]; then
CHANGED_FILES="${{ github.event.inputs.files }}"
elif [ "$SYNC_MODE" = "incremental" ]; then
BASE_SHA=$(git rev-parse HEAD~1 2>/dev/null || true)
if [ -n "$BASE_SHA" ]; then
CHANGED_FILES=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA" -- 'web/i18n/en-US/*.json' 2>/dev/null | sed -n 's@^.*/@@p' | sed 's/\.json$//' | tr '\n' ' ' | sed 's/[[:space:]]*$//')
else
CHANGED_FILES=$(find web/i18n/en-US -maxdepth 1 -type f -name '*.json' -print | sed -n 's@^.*/@@p' | sed 's/\.json$//' | sort | tr '\n' ' ' | sed 's/[[:space:]]*$//')
fi
elif [ "$SYNC_MODE" = "full" ]; then
echo "workflow_dispatch full mode requires the files input to stay within CI limits." >&2
exit 1
else
CHANGED_FILES=""
fi
if [ "$SYNC_MODE" = "incremental" ] && [ -n "$CHANGED_FILES" ]; then
export BASE_SHA HEAD_SHA CHANGED_FILES
generate_changes_json
CHANGES_AVAILABLE="true"
CHANGES_SOURCE="local"
else
printf '%s' '{"baseSha":"","headSha":"","files":[],"changes":{}}' > /tmp/i18n-changes.json
CHANGES_AVAILABLE="false"
CHANGES_SOURCE="unavailable"
fi
fi
FILE_ARGS=""
if [ -n "$CHANGED_FILES" ]; then
FILE_ARGS="--file $CHANGED_FILES"
fi
LANG_ARGS=""
if [ -n "$TARGET_LANGS" ]; then
LANG_ARGS="--lang $TARGET_LANGS"
fi
{
echo "DEFAULT_TARGET_LANGS=$DEFAULT_TARGET_LANGS"
echo "BASE_SHA=$BASE_SHA"
echo "HEAD_SHA=$HEAD_SHA"
echo "CHANGED_FILES=$CHANGED_FILES"
echo "TARGET_LANGS=$TARGET_LANGS"
echo "SYNC_MODE=$SYNC_MODE"
echo "CHANGES_AVAILABLE=$CHANGES_AVAILABLE"
echo "CHANGES_SOURCE=$CHANGES_SOURCE"
echo "FILE_ARGS=$FILE_ARGS"
echo "LANG_ARGS=$LANG_ARGS"
} >> "$GITHUB_OUTPUT"
echo "Files: ${CHANGED_FILES:-<none>}"
echo "Languages: ${TARGET_LANGS:-<none>}"
echo "Mode: $SYNC_MODE"
- name: Run Claude Code for Translation Sync
if: steps.context.outputs.CHANGED_FILES != ''
uses: anthropics/claude-code-action@be7b93b1907a4abad570368f3c74b6fe3807510b # v1.0.183
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
allowed_bots: 'github-actions[bot]'
show_full_output: ${{ github.event_name == 'workflow_dispatch' }}
prompt: |
You are the i18n sync agent for the Dify repository.
Your job is to keep translations synchronized with the English source files under `${{ github.workspace }}/web/i18n/en-US/`.
Use absolute paths at all times:
- Repo root: `${{ github.workspace }}`
- Web directory: `${{ github.workspace }}/web`
- Language config: `${{ github.workspace }}/web/i18n-config/languages.ts`
Inputs:
- Files in scope: `${{ steps.context.outputs.CHANGED_FILES }}`
- Target languages: `${{ steps.context.outputs.TARGET_LANGS }}`
- Sync mode: `${{ steps.context.outputs.SYNC_MODE }}`
- Base SHA: `${{ steps.context.outputs.BASE_SHA }}`
- Head SHA: `${{ steps.context.outputs.HEAD_SHA }}`
- Scoped file args: `${{ steps.context.outputs.FILE_ARGS }}`
- Scoped language args: `${{ steps.context.outputs.LANG_ARGS }}`
- Structured change set available: `${{ steps.context.outputs.CHANGES_AVAILABLE }}`
- Structured change set source: `${{ steps.context.outputs.CHANGES_SOURCE }}`
- Structured change set file: `/tmp/i18n-changes.json`
Tool rules:
- Use Read for repository files.
- Use Edit for JSON updates.
- Use Bash only for `vp`.
- Do not use Bash for `git`, `gh`, or branch management.
Required execution plan:
1. Resolve target languages.
- Use the provided `Target languages` value as the source of truth.
- If it is unexpectedly empty, read `${{ github.workspace }}/web/i18n-config/languages.ts` and use every language with `supported: true` except `en-US`.
2. Stay strictly in scope.
- Only process the files listed in `Files in scope`.
- Only process the resolved target languages, never `en-US`.
- Do not touch unrelated i18n files.
- Do not modify `${{ github.workspace }}/web/i18n/en-US/`.
3. Resolve source changes.
- If `Structured change set available` is `true`, read `/tmp/i18n-changes.json` and use it as the source of truth for file-level and key-level changes.
- For each file entry:
- `added` contains new English keys that need translations.
- `updated` contains stale keys whose English source changed; re-translate using the `after` value.
- `deleted` contains keys that should be removed from locale files.
- `fileDeleted: true` means the English file no longer exists; remove the matching locale file if present.
- Read the current English JSON file for any file that still exists so wording, placeholders, and surrounding terminology stay accurate.
- If `Structured change set available` is `false`, treat this as a scoped full sync and use the current English files plus scoped checks as the source of truth.
4. Run a scoped pre-check before editing:
- `vp run dify-web#i18n:check ${{ steps.context.outputs.FILE_ARGS }} ${{ steps.context.outputs.LANG_ARGS }}`
- Use this command as the source of truth for missing and extra keys inside the current scope.
5. Apply translations.
- For every target language and scoped file:
- If `fileDeleted` is `true`, remove the locale file if it exists and skip the rest of that file.
- If the locale file does not exist yet, create it with `Write` and then continue with `Edit` as needed.
- ADD missing keys.
- UPDATE stale translations when the English value changed.
- DELETE removed keys. Prefer `vp run dify-web#i18n:check ${{ steps.context.outputs.FILE_ARGS }} ${{ steps.context.outputs.LANG_ARGS }} --auto-remove` for extra keys so deletions stay in scope.
- Preserve placeholders exactly: `{{variable}}`, `${variable}`, HTML tags, component tags, and variable names.
- Match the existing terminology and register used by each locale.
- Prefer one Edit per file when stable, but prioritize correctness over batching.
6. Verify only the edited files.
- Run `vp fmt <repo-relative edited paths such as web/i18n/...>`
- Run `vp run dify-web#i18n:check ${{ steps.context.outputs.FILE_ARGS }} ${{ steps.context.outputs.LANG_ARGS }}`
- If verification fails, fix the remaining problems before continuing.
7. Stop after the scoped locale files are updated and verification passes.
- Do not create branches, commits, or pull requests.
claude_args: |
--max-turns 120
--allowedTools "Read,Write,Edit,Bash(vp *),Bash(vp:*),Glob,Grep"
- name: Prepare branch metadata
id: pr_meta
if: steps.context.outputs.CHANGED_FILES != ''
shell: bash
run: |
if [ -z "$(git -C "${{ github.workspace }}" status --porcelain -- web/i18n/)" ]; then
echo "has_changes=false" >> "$GITHUB_OUTPUT"
exit 0
fi
SCOPE_HASH=$(printf '%s|%s|%s' "${{ steps.context.outputs.CHANGED_FILES }}" "${{ steps.context.outputs.TARGET_LANGS }}" "${{ steps.context.outputs.SYNC_MODE }}" | sha256sum | cut -c1-8)
HEAD_SHORT=$(printf '%s' "${{ steps.context.outputs.HEAD_SHA }}" | cut -c1-12)
BRANCH_NAME="chore/i18n-sync-${HEAD_SHORT}-${SCOPE_HASH}"
{
echo "has_changes=true"
echo "branch_name=$BRANCH_NAME"
} >> "$GITHUB_OUTPUT"
- name: Commit translation changes
if: steps.pr_meta.outputs.has_changes == 'true'
shell: bash
run: |
git -C "${{ github.workspace }}" checkout -B "${{ steps.pr_meta.outputs.branch_name }}"
git -C "${{ github.workspace }}" add web/i18n/
git -C "${{ github.workspace }}" commit -m "chore(i18n): sync translations with en-US"
- name: Push translation branch
if: steps.pr_meta.outputs.has_changes == 'true'
shell: bash
run: |
if git -C "${{ github.workspace }}" ls-remote --exit-code --heads origin "${{ steps.pr_meta.outputs.branch_name }}" >/dev/null 2>&1; then
git -C "${{ github.workspace }}" push --force-with-lease origin "${{ steps.pr_meta.outputs.branch_name }}"
else
git -C "${{ github.workspace }}" push --set-upstream origin "${{ steps.pr_meta.outputs.branch_name }}"
fi
- name: Create or update translation PR
if: steps.pr_meta.outputs.has_changes == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH_NAME: ${{ steps.pr_meta.outputs.branch_name }}
FILES_IN_SCOPE: ${{ steps.context.outputs.CHANGED_FILES }}
TARGET_LANGS: ${{ steps.context.outputs.TARGET_LANGS }}
SYNC_MODE: ${{ steps.context.outputs.SYNC_MODE }}
CHANGES_SOURCE: ${{ steps.context.outputs.CHANGES_SOURCE }}
BASE_SHA: ${{ steps.context.outputs.BASE_SHA }}
HEAD_SHA: ${{ steps.context.outputs.HEAD_SHA }}
REPO_NAME: ${{ github.repository }}
shell: bash
run: |
PR_BODY_FILE=/tmp/i18n-pr-body.md
LANG_COUNT=$(printf '%s\n' "$TARGET_LANGS" | wc -w | tr -d ' ')
if [ "$LANG_COUNT" = "0" ]; then
LANG_COUNT="0"
fi
export LANG_COUNT
node <<'NODE' > "$PR_BODY_FILE"
const fs = require('node:fs')
const changesPath = '/tmp/i18n-changes.json'
const changes = fs.existsSync(changesPath)
? JSON.parse(fs.readFileSync(changesPath, 'utf8'))
: { changes: {} }
const filesInScope = (process.env.FILES_IN_SCOPE || '').split(/\s+/).filter(Boolean)
const lines = [
'## Summary',
'',
`- **Files synced**: \`${process.env.FILES_IN_SCOPE || '<none>'}\``,
`- **Languages updated**: ${process.env.TARGET_LANGS || '<none>'} (${process.env.LANG_COUNT} languages)`,
`- **Sync mode**: ${process.env.SYNC_MODE}${process.env.BASE_SHA ? ` (base: \`${process.env.BASE_SHA.slice(0, 10)}\`, head: \`${process.env.HEAD_SHA.slice(0, 10)}\`)` : ` (head: \`${process.env.HEAD_SHA.slice(0, 10)}\`)`}`,
'',
'### Key changes',
]
for (const fileName of filesInScope) {
const fileChange = changes.changes?.[fileName] || { added: {}, updated: {}, deleted: [], fileDeleted: false }
const addedKeys = Object.keys(fileChange.added || {})
const updatedKeys = Object.keys(fileChange.updated || {})
const deletedKeys = fileChange.deleted || []
lines.push(`- \`${fileName}\`: +${addedKeys.length} / ~${updatedKeys.length} / -${deletedKeys.length}${fileChange.fileDeleted ? ' (file deleted in en-US)' : ''}`)
}
lines.push(
'',
'## Verification',
'',
`- \`vp run dify-web#i18n:check --file ${process.env.FILES_IN_SCOPE} --lang ${process.env.TARGET_LANGS}\``,
`- \`vp fmt <repo-relative edited paths such as web/i18n/...>\``,
'',
'## Notes',
'',
'- This PR was generated from structured en-US key changes produced by `trigger-i18n-sync.yml`.',
`- Structured change source: ${process.env.CHANGES_SOURCE || 'unknown'}.`,
'- Branch name is deterministic for the head SHA and scope, so reruns update the same PR instead of opening duplicates.',
'',
'🤖 Generated with [Claude Code](https://claude.com/claude-code)'
)
process.stdout.write(lines.join('\n'))
NODE
EXISTING_PR_NUMBER=$(gh pr list --repo "$REPO_NAME" --head "$BRANCH_NAME" --state open --json number --jq '.[0].number')
if [ -n "$EXISTING_PR_NUMBER" ] && [ "$EXISTING_PR_NUMBER" != "null" ]; then
gh pr edit "$EXISTING_PR_NUMBER" --repo "$REPO_NAME" --title "chore(i18n): sync translations with en-US" --body-file "$PR_BODY_FILE"
else
gh pr create --repo "$REPO_NAME" --head "$BRANCH_NAME" --base main --title "chore(i18n): sync translations with en-US" --body-file "$PR_BODY_FILE"
fi
-90
View File
@@ -1,90 +0,0 @@
name: Trigger i18n Sync on Push
on:
push:
branches: [main]
paths:
- 'web/i18n/en-US/*.json'
permissions:
contents: write
concurrency:
group: trigger-i18n-sync-${{ github.ref }}
cancel-in-progress: true
jobs:
trigger:
if: github.repository == 'langgenius/dify'
runs-on: depot-ubuntu-24.04
timeout-minutes: 5
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- name: Detect changed files and build structured change set
id: detect
shell: bash
run: |
BASE_SHA="${{ github.event.before }}"
if [ -z "$BASE_SHA" ] || [ "$BASE_SHA" = "0000000000000000000000000000000000000000" ]; then
BASE_SHA=$(git rev-parse HEAD~1 2>/dev/null || true)
fi
HEAD_SHA="${{ github.sha }}"
if [ -n "$BASE_SHA" ]; then
CHANGED_FILES=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA" -- 'web/i18n/en-US/*.json' 2>/dev/null | sed -n 's@^.*/@@p' | sed 's/\.json$//' | tr '\n' ' ' | sed 's/[[:space:]]*$//')
else
CHANGED_FILES=$(find web/i18n/en-US -maxdepth 1 -type f -name '*.json' -print | sed -n 's@^.*/@@p' | sed 's/\.json$//' | sort | tr '\n' ' ' | sed 's/[[:space:]]*$//')
fi
export BASE_SHA HEAD_SHA CHANGED_FILES
node .github/scripts/generate-i18n-changes.mjs
if [ -n "$CHANGED_FILES" ]; then
echo "has_changes=true" >> "$GITHUB_OUTPUT"
else
echo "has_changes=false" >> "$GITHUB_OUTPUT"
fi
echo "base_sha=$BASE_SHA" >> "$GITHUB_OUTPUT"
echo "head_sha=$HEAD_SHA" >> "$GITHUB_OUTPUT"
echo "changed_files=$CHANGED_FILES" >> "$GITHUB_OUTPUT"
- name: Trigger i18n sync workflow
if: steps.detect.outputs.has_changes == 'true'
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
BASE_SHA: ${{ steps.detect.outputs.base_sha }}
HEAD_SHA: ${{ steps.detect.outputs.head_sha }}
CHANGED_FILES: ${{ steps.detect.outputs.changed_files }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs')
const changesJson = fs.readFileSync('/tmp/i18n-changes.json', 'utf8')
const changesBase64 = Buffer.from(changesJson).toString('base64')
const maxEmbeddedChangesChars = 48000
const changesEmbedded = changesBase64.length <= maxEmbeddedChangesChars
if (!changesEmbedded) {
console.log(`Structured change set too large to embed safely (${changesBase64.length} chars). Downstream workflow will regenerate it from git history.`)
}
await github.rest.repos.createDispatchEvent({
owner: context.repo.owner,
repo: context.repo.repo,
event_type: 'i18n-sync',
client_payload: {
changed_files: process.env.CHANGED_FILES,
changes_base64: changesEmbedded ? changesBase64 : '',
changes_embedded: changesEmbedded,
sync_mode: 'incremental',
base_sha: process.env.BASE_SHA,
head_sha: process.env.HEAD_SHA,
},
})
-68
View File
@@ -1,68 +0,0 @@
name: Run Full VDB Tests
on:
schedule:
- cron: '0 3 * * 1'
workflow_dispatch:
permissions:
contents: read
concurrency:
group: vdb-tests-full-${{ github.ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
name: Full VDB Tests
if: github.repository == 'langgenius/dify'
runs-on: depot-ubuntu-24.04
strategy:
matrix:
python-version:
- "3.12"
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Free Disk Space
uses: endersonmenezes/free-disk-space@7901478139cff6e9d44df5972fd8ab8fcade4db1 # v3.2.2
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
with:
enable-cache: true
python-version: ${{ matrix.python-version }}
cache-dependency-glob: api/uv.lock
- name: Check UV lockfile
run: uv lock --project api --check
- 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: 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: |
uv run --project api pytest \
--start-vdb \
--vdb-services "weaviate,qdrant,couchbase-server,etcd,minio,milvus-standalone,pgvecto-rs,pgvector,chroma,elasticsearch,oceanbase" \
--timeout "${PYTEST_TIMEOUT:-180}" \
api/providers/vdb/*/tests/integration_tests
+49 -26
View File
@@ -1,39 +1,37 @@
name: Run VDB Smoke Tests
name: Run VDB Tests
on:
workflow_call:
permissions:
contents: read
concurrency:
group: vdb-tests-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
name: VDB Smoke Tests
runs-on: depot-ubuntu-24.04
name: VDB Tests
runs-on: ubuntu-latest
strategy:
matrix:
python-version:
- "3.11"
- "3.12"
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Free Disk Space
uses: endersonmenezes/free-disk-space@7901478139cff6e9d44df5972fd8ab8fcade4db1 # v3.2.2
uses: endersonmenezes/free-disk-space@v2
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@v6
with:
enable-cache: true
python-version: ${{ matrix.python-version }}
@@ -45,23 +43,48 @@ 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 dotenvs
run: |
cp docker/.env.example docker/.env
cp docker/middleware.env.example docker/middleware.env
# - name: Check VDB Ready (TiDB)
# run: uv run --project api python api/providers/vdb/tidb-vector/tests/integration_tests/check_tiflash_ready.py
- name: Expose Service Ports
run: sh .github/workflows/expose_service_ports.sh
- 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 Stores (Weaviate, Qdrant, PGVector, Milvus, PgVecto-RS, Chroma, MyScale, ElasticSearch, Couchbase, OceanBase)
uses: hoverkraft-tech/compose-action@v2.0.2
with:
compose-file: |
docker/docker-compose.yaml
services: |
weaviate
qdrant
couchbase-server
etcd
minio
milvus-standalone
pgvecto-rs
pgvector
chroma
elasticsearch
oceanbase
- name: setup test config
run: |
echo $(pwd)
ls -lah .
cp api/tests/integration_tests/.env.example api/tests/integration_tests/.env
- name: Check VDB Ready (TiDB)
run: uv run --project api python api/tests/integration_tests/vdb/tidb_vector/check_tiflash_ready.py
- name: Test Vector Stores
run: |
uv run --project api pytest \
--start-vdb \
--timeout "${PYTEST_TIMEOUT:-180}" \
api/providers/vdb/vdb-chroma/tests/integration_tests \
api/providers/vdb/vdb-pgvector/tests/integration_tests \
api/providers/vdb/vdb-qdrant/tests/integration_tests \
api/providers/vdb/vdb-weaviate/tests/integration_tests
run: uv run --project api bash dev/pytest/pytest_vdb.sh
-189
View File
@@ -1,189 +0,0 @@
name: Web Full-Stack E2E
on:
workflow_call:
inputs:
run-external-runtime:
description: Run only the prepared and external runtime suite instead of the core suites.
required: true
type: boolean
permissions:
contents: read
concurrency:
group: web-e2e-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
name: Web Full-Stack E2E
runs-on: depot-ubuntu-24.04-4
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@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
enable-cache: true
python-version: "3.12"
cache-dependency-glob: |
api/uv.lock
dify-agent/uv.lock
- name: Install API dependencies
run: uv sync --project api --dev
- name: Run E2E support unit tests
if: ${{ !inputs.run-external-runtime }}
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
E2E_START_AGENT_BACKEND: "1"
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
- name: Run prepared and external runtime 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_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_INIT_PASSWORD: E2eInit12345
E2E_MARKETPLACE_API_URL: ${{ vars.E2E_MARKETPLACE_API_URL }}
E2E_MARKETPLACE_PLUGIN_IDS: ${{ vars.E2E_MARKETPLACE_PLUGIN_IDS }}
E2E_MODEL_PROVIDER_CREDENTIALS_JSON: ${{ secrets.E2E_MODEL_PROVIDER_CREDENTIALS_JSON }}
E2E_SPEECH_TO_TEXT_MODEL_NAME: ${{ vars.E2E_SPEECH_TO_TEXT_MODEL_NAME || 'gpt-4o-mini-transcribe' }}
E2E_SPEECH_TO_TEXT_MODEL_PROVIDER: ${{ vars.E2E_SPEECH_TO_TEXT_MODEL_PROVIDER || 'openai' }}
E2E_START_AGENT_BACKEND: ${{ vars.E2E_START_AGENT_BACKEND || '1' }}
E2E_STABLE_MODEL_NAME: ${{ vars.E2E_STABLE_MODEL_NAME || 'gpt-5-nano' }}
E2E_STABLE_MODEL_PROVIDER: ${{ vars.E2E_STABLE_MODEL_PROVIDER || 'openai' }}
E2E_STABLE_MODEL_TYPE: ${{ vars.E2E_STABLE_MODEL_TYPE || 'llm' }}
run: |
if [[ -z "${E2E_MODEL_PROVIDER_CREDENTIALS_JSON}" ]]; then
echo "E2E_MODEL_PROVIDER_CREDENTIALS_JSON is required for external runtime E2E." >&2
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
if: ${{ !cancelled() }}
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
retention-days: 7
- name: Upload E2E logs
if: ${{ !cancelled() }}
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
include-hidden-files: true
retention-days: 7
- name: Upload E2E seed report
if: ${{ !cancelled() && inputs.run-external-runtime }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: e2e-seed-report
path: e2e/seed-report
if-no-files-found: ignore
retention-days: 7
+35 -123
View File
@@ -2,12 +2,6 @@ name: Web Tests
on:
workflow_call:
secrets:
CODECOV_TOKEN:
required: false
permissions:
contents: read
concurrency:
group: web-tests-${{ github.head_ref || github.run_id }}
@@ -15,132 +9,50 @@ concurrency:
jobs:
test:
name: Web Tests (${{ matrix.shardIndex }}/${{ matrix.shardTotal }})
runs-on: depot-ubuntu-24.04-4
strategy:
fail-fast: false
matrix:
shardIndex: [1, 2, 3, 4]
shardTotal: [4]
name: Web Tests
runs-on: ubuntu-latest
defaults:
run:
shell: bash
working-directory: ./web
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Setup web environment
uses: ./.github/actions/setup-web
- name: Check changed files
id: changed-files
uses: tj-actions/changed-files@v46
with:
files: web/**
- name: Install pnpm
if: steps.changed-files.outputs.any_changed == 'true'
uses: pnpm/action-setup@v4
with:
package_json_file: web/package.json
run_install: false
- name: Setup Node.js
uses: actions/setup-node@v4
if: steps.changed-files.outputs.any_changed == 'true'
with:
node-version: 22
cache: pnpm
cache-dependency-path: ./web/package.json
- name: Install dependencies
if: steps.changed-files.outputs.any_changed == 'true'
working-directory: ./web
run: pnpm install --frozen-lockfile
- name: Check i18n types synchronization
if: steps.changed-files.outputs.any_changed == 'true'
working-directory: ./web
run: pnpm run check:i18n-types
- name: Run tests
run: vp test run --reporter=blob --reporter=minimal --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} --coverage
- name: Upload blob report
if: ${{ !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: blob-report-${{ matrix.shardIndex }}
path: web/.vitest-reports/*
include-hidden-files: true
retention-days: 1
merge-reports:
name: Merge Test Reports
if: ${{ !cancelled() }}
needs: [test]
runs-on: depot-ubuntu-24.04-4
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
defaults:
run:
shell: bash
if: steps.changed-files.outputs.any_changed == 'true'
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: Download blob reports
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: web/.vitest-reports
pattern: blob-report-*
merge-multiple: true
- name: Merge reports
run: vp test --merge-reports --coverage --silent=passed-only
- name: Report coverage
if: ${{ env.CODECOV_TOKEN != '' }}
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
directory: web/coverage
flags: web
env:
CODECOV_TOKEN: ${{ env.CODECOV_TOKEN }}
dify-ui-test:
name: dify-ui Tests
runs-on: depot-ubuntu-24.04-4
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
defaults:
run:
shell: bash
working-directory: ./packages/dify-ui
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
run: vp exec playwright install --with-deps chromium
- name: Run dify-ui tests
run: vp test run --project unit --coverage --silent=passed-only
- name: Report coverage
if: ${{ env.CODECOV_TOKEN != '' }}
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
directory: packages/dify-ui/coverage
flags: dify-ui
env:
CODECOV_TOKEN: ${{ env.CODECOV_TOKEN }}
dify-ui-storybook-test:
name: dify-ui Storybook Tests
runs-on: depot-ubuntu-24.04-4
defaults:
run:
shell: bash
working-directory: ./packages/dify-ui
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
run: vp exec playwright install --with-deps chromium
- name: Run dify-ui Storybook tests
run: vp run test:storybook
run: pnpm test
+3 -49
View File
@@ -6,9 +6,6 @@ __pycache__/
# C extensions
*.so
# *db files
*.db
# Distribution / packaging
.Python
build/
@@ -100,7 +97,6 @@ __pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat-schedule.db
celerybeat.pid
# SageMath parsed files
@@ -115,12 +111,6 @@ venv/
ENV/
env.bak/
venv.bak/
# cli/ has a src/env/ module (DIFY_* registry) — don't treat it as a venv
!/cli/src/env/
!/cli/src/commands/env/
# cli/scripts/lib/ holds TS build helpers (resolve-buildinfo etc.) — don't treat as Python lib/
!/cli/scripts/lib/
.conda/
# Spyder project settings
@@ -145,6 +135,7 @@ pyrightconfig.json
.idea/'
.DS_Store
web/.vscode/settings.json
# Intellij IDEA Files
.idea/*
@@ -191,17 +182,13 @@ docker/volumes/couchbase/*
docker/volumes/oceanbase/*
docker/volumes/plugin_daemon/*
docker/volumes/matrixone/*
docker/volumes/mysql/*
docker/volumes/seekdb/*
!docker/volumes/oceanbase/init.d
docker/volumes/iris/*
docker/nginx/conf.d/default.conf
docker/nginx/ssl/*
!docker/nginx/ssl/.gitkeep
docker/middleware.env
docker/docker-compose.override.yaml
docker/env-backup/*
sdks/python-client/build
sdks/python-client/dist
@@ -209,59 +196,26 @@ sdks/python-client/dify_client.egg-info
.vscode/*
!.vscode/launch.json.template
!.vscode/settings.example.json
!.vscode/README.md
api/.vscode
# vscode Code History Extension
.history
.eslintcache
.idea/
# pnpm
/.pnpm-store
node_modules
.vite-hooks/_
# plugin migrate
plugins.jsonl
# generated API OpenAPI specs
packages/contracts/openapi/
# mise
mise.toml
# Next.js build output
.next/
# AI Assistant
.roo/
/.claude/worktrees/
api/.env.backup
/clickzetta
# Benchmark
scripts/stress-test/setup/config/
scripts/stress-test/reports/
# mcp
.playwright-mcp/
.serena/
# vitest browser mode attachments (failure screenshots, traces, etc.)
.vitest-attachments/
**/__screenshots__/
# settings
*.local.json
*.local.md
*.local.toml
# Code Agent Folder
.qoder/*
.context/
# Vitest local reports
web/.vitest-reports/
# dify-agent-runtime
dify-agent-runtime/bin/
dify-agent-runtime/.integration-state
+34
View File
@@ -0,0 +1,34 @@
{
"mcpServers": {
"context7": {
"type": "http",
"url": "https://mcp.context7.com/mcp"
},
"sequential-thinking": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-sequential-thinking"],
"env": {}
},
"github": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PERSONAL_ACCESS_TOKEN}"
}
},
"fetch": {
"type": "stdio",
"command": "uvx",
"args": ["mcp-server-fetch"],
"env": {}
},
"playwright": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@playwright/mcp@latest"],
"env": {}
}
}
}
-1
View File
@@ -1 +0,0 @@
22
-64
View File
@@ -1,64 +0,0 @@
#!/bin/sh
# get the list of modified files
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() {
git rev-parse --git-path "$1"
}
if [ -f "$(git_path MERGE_HEAD)" ] || \
[ -f "$(git_path CHERRY_PICK_HEAD)" ] || \
[ -f "$(git_path REVERT_HEAD)" ] || \
[ -f "$(git_path SQUASH_MSG)" ] || \
[ -d "$(git_path rebase-merge)" ] || \
[ -d "$(git_path rebase-apply)" ]; then
skip_web_checks=true
fi
for file in $files
do
# Use POSIX compliant pattern matching
case "$file" in
api/*.py)
# set api_modified flag to true
api_modified=true
;;
web/*)
# set web_modified flag to true
web_modified=true
;;
esac
done
# run linters based on the modified modules
if $api_modified; then
echo "Running Ruff linter on api module"
# run Ruff linter auto-fixing
uv run --project api --dev ruff check --fix ./api
# run Ruff linter checks
uv run --project api --dev ruff check ./api || status=$?
status=${status:-0}
if [ $status -ne 0 ]; then
echo "Ruff linter on api module error, exit code: $status"
echo "Please run 'dev/reformat' to fix the fixable linting errors."
exit 1
fi
fi
if $skip_web_checks; then
echo "Git operation in progress, skipping web checks"
exit 0
fi
vp staged
+35 -7
View File
@@ -2,12 +2,22 @@
"version": "0.2.0",
"configurations": [
{
"name": "Python: API (gevent)",
"name": "Python: Flask API",
"type": "debugpy",
"request": "launch",
"module": "gevent.monkey",
"args": ["--module", "app"],
"gevent": true,
"module": "flask",
"env": {
"FLASK_APP": "app.py",
"FLASK_ENV": "development",
"GEVENT_SUPPORT": "True"
},
"args": [
"run",
"--host=0.0.0.0",
"--port=5001",
"--no-debugger",
"--no-reload"
],
"jinja": true,
"justMyCode": true,
"cwd": "${workspaceFolder}/api",
@@ -18,7 +28,9 @@
"type": "debugpy",
"request": "launch",
"module": "celery",
"env": {},
"env": {
"GEVENT_SUPPORT": "True"
},
"args": [
"-A",
"app.celery",
@@ -28,13 +40,29 @@
"-c",
"1",
"-Q",
"dataset,dataset_summary,priority_dataset,priority_pipeline,pipeline,mail,ops_trace,app_deletion,plugin,workflow_storage,conversation,workflow,schedule_poller,schedule_executor,triggered_workflow_dispatcher,trigger_refresh_executor,retention,workflow_based_app_execution",
"dataset,generation,mail,ops_trace",
"--loglevel",
"INFO"
],
"justMyCode": false,
"cwd": "${workspaceFolder}/api",
"python": "${workspaceFolder}/api/.venv/bin/python"
}
},
{
"name": "Next.js: debug full stack",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/web/node_modules/next/dist/bin/next",
"runtimeArgs": ["--inspect"],
"skipFiles": ["<node_internals>/**"],
"serverReadyAction": {
"action": "debugWithChrome",
"killOnServerStop": true,
"pattern": "- Local:.+(https?://.+)",
"uriFormat": "%s",
"webRoot": "${workspaceFolder}/web"
},
"cwd": "${workspaceFolder}/web"
}
]
}
-37
View File
@@ -1,37 +0,0 @@
{
"cucumber.features": ["e2e/features/**/*.feature"],
"cucumber.glue": ["e2e/features/**/*.ts"],
"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" },
"[typescriptreact]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
"[json]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
"[jsonc]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
"[markdown]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
"[mdx]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
"[yaml]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
"[toml]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
"[css]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
"[scss]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
"[less]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
"[html]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
"[vue]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
"[svelte]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
"[graphql]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
"[handlebars]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
"editor.formatOnSave": true,
"editor.formatOnSaveMode": "file",
"oxc.fmt.configPath": "./vite.config.ts",
// Lint fix
"eslint.useFlatConfig": true,
"eslint.validate": ["json", "jsonc", "markdown", "yaml", "toml"],
"editor.codeActionsOnSave": {
"source.fixAll.oxc": "explicit",
"source.fixAll.eslint": "explicit"
}
}
-8
View File
@@ -1,8 +0,0 @@
# AGENTS.md
Dify is an open-source platform for building LLM applications, agentic workflows, and RAG pipelines. This monorepo contains the backend API (`api/`), frontend application (`web/`), deployment assets (`docker/`), standalone agent backend (`dify-agent/`), CLI (`cli/`), and end-to-end suite (`e2e/`). Follow the nearest scoped `AGENTS.md` for the files being changed.
## Repository Gotchas
- Run backend commands through `uv run --project api <command>`.
- Backend integration tests are CI-only and are not expected to run locally.
Symlink
+1
View File
@@ -0,0 +1 @@
CLAUDE.md
-1
View File
@@ -1 +0,0 @@
AGENTS.md
+89
View File
@@ -0,0 +1,89 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
Dify is an open-source platform for developing LLM applications with an intuitive interface combining agentic AI workflows, RAG pipelines, agent capabilities, and model management.
The codebase consists of:
- **Backend API** (`/api`): Python Flask application with Domain-Driven Design architecture
- **Frontend Web** (`/web`): Next.js 15 application with TypeScript and React 19
- **Docker deployment** (`/docker`): Containerized deployment configurations
## Development Commands
### Backend (API)
All Python commands must be prefixed with `uv run --project api`:
```bash
# Start development servers
./dev/start-api # Start API server
./dev/start-worker # Start Celery worker
# Run tests
uv run --project api pytest # Run all tests
uv run --project api pytest tests/unit_tests/ # Unit tests only
uv run --project api pytest tests/integration_tests/ # Integration tests
# Code quality
./dev/reformat # Run all formatters and linters
uv run --project api ruff check --fix ./ # Fix linting issues
uv run --project api ruff format ./ # Format code
uv run --directory api basedpyright # Type checking
```
### Frontend (Web)
```bash
cd web
pnpm lint # Run ESLint
pnpm eslint-fix # Fix ESLint issues
pnpm test # Run Jest tests
```
## Testing Guidelines
### Backend Testing
- Use `pytest` for all backend tests
- Write tests first (TDD approach)
- Test structure: Arrange-Act-Assert
## Code Style Requirements
### Python
- Use type hints for all functions and class attributes
- No `Any` types unless absolutely necessary
- Implement special methods (`__repr__`, `__str__`) appropriately
### TypeScript/JavaScript
- Strict TypeScript configuration
- ESLint with Prettier integration
- Avoid `any` type
## Important Notes
- **Environment Variables**: Always use UV for Python commands: `uv run --project api <command>`
- **Comments**: Only write meaningful comments that explain "why", not "what"
- **File Creation**: Always prefer editing existing files over creating new ones
- **Documentation**: Don't create documentation files unless explicitly requested
- **Code Quality**: Always run `./dev/reformat` before committing backend changes
## Common Development Tasks
### Adding a New API Endpoint
1. Create controller in `/api/controllers/`
1. Add service logic in `/api/services/`
1. Update routes in controller's `__init__.py`
1. Write tests in `/api/tests/`
## Project-Specific Conventions
- All async tasks use Celery with Redis as broker
- **Internationalization**: Frontend supports multiple languages with English (`web/i18n/en-US/`) as the source. All user-facing text must use i18n keys, no hardcoded strings. Edit corresponding module files in `en-US/` directory for translations.
+1 -3
View File
@@ -66,7 +66,7 @@ How we prioritize:
1. Fork the repository
1. Before you draft a PR, please create an issue to discuss the changes you want to make
1. Create a new branch for your changes
1. Add or update tests when the change affects observable behavior or carries meaningful regression risk
1. Please add tests for your changes accordingly
1. Ensure your code passes the existing tests
1. Please link the issue in the PR description, `fixes #<issue_number>`
1. Get merged!
@@ -77,8 +77,6 @@ How we prioritize:
For setting up the frontend service, please refer to our comprehensive [guide](https://github.com/langgenius/dify/blob/main/web/README.md) in the `web/README.md` file. This document provides detailed instructions to help you set up the frontend environment properly.
**Testing**: Add focused tests when a change affects observable behavior or carries meaningful regression risk. See [web/docs/test.md](https://github.com/langgenius/dify/blob/main/web/docs/test.md) for the canonical frontend testing guidelines.
#### Backend
For setting up the backend service, kindly refer to our detailed [instructions](https://github.com/langgenius/dify/blob/main/api/README.md) in the `api/README.md` file. This document contains step-by-step guidance to help you get the backend up and running smoothly.
+97
View File
@@ -0,0 +1,97 @@
# 贡献指南
非常感谢你考虑为 Dify 做出贡献!作为一家资源有限的创业公司,我们希望打造最直观的 LLM 应用开发和管理工作流程。社区的每一份贡献对我们来说都弥足珍贵。
我们需要保持敏捷和快速迭代,同时也希望确保贡献者能获得尽可能流畅的参与体验。这份贡献指南旨在帮助你熟悉代码库和我们的工作方式,让你可以尽快进入有趣的开发环节。
本指南和 Dify 一样在不断完善中。如果有任何滞后于项目实际情况的地方,恳请谅解,我们也欢迎任何改进建议。
关于许可证,请花一分钟阅读我们简短的[许可和贡献者协议](./LICENSE)。同时也请遵循社区[行为准则](https://github.com/langgenius/.github/blob/main/CODE_OF_CONDUCT.md)。
## 开始之前
想寻找可以着手的任务?浏览我们的[新手友好议题](https://github.com/langgenius/dify/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22)并选择一个开始!
有酷炫的新模型运行时或工具要添加?在我们的[插件仓库](https://github.com/langgenius/dify-plugins)开启 PR,展示你的作品。
需要更新现有模型运行时、工具或修复 bug?前往我们的[官方插件仓库](https://github.com/langgenius/dify-official-plugins)大展身手!
加入我们,一起贡献,共同打造精彩项目!💡✨
请记得在 PR 描述中关联现有 issue 或创建新的 issue。
### Bug 报告
> [!IMPORTANT]
> 提交 bug 报告时请务必包含以下信息:
- 清晰描述性的标题
- 详细的 bug 描述,包括任何错误信息
- 复现步骤
- 预期行为
- **日志**,如果是后端问题,这点很重要,可以在 docker-compose 日志中找到
- 截图或视频(如果适用)
优先级划分:
| 问题类型 | 优先级 |
| -------------------------------------------------- | ---------- |
| 核心功能 bug(云服务、登录失败、应用无法使用、安全漏洞) | 紧急 |
| 非关键 bug、性能优化 | 中等优先级 |
| 小修复(拼写错误、界面混乱但可用) | 低优先级 |
### 功能请求
> [!NOTE]
> 提交功能请求时请务必包含以下信息:
- 清晰描述性的标题
- 详细的功能描述
- 功能使用场景
- 其他相关上下文或截图
优先级划分:
| 功能类型 | 优先级 |
| -------------------------------------------------- | ---------- |
| 被团队成员标记为高优先级的功能 | 高优先级 |
| 来自[社区反馈板](https://github.com/langgenius/dify/discussions/categories/feedbacks)的热门功能请求 | 中等优先级 |
| 非核心功能和小改进 | 低优先级 |
| 有价值但非紧急的功能 | 未来特性 |
## 提交 PR
### 项目设置
### PR 提交流程
1. Fork 本仓库
1. 在提交 PR 之前,请先创建 issue 讨论你想要做的修改
1. 为你的修改创建一个新的分支
1. 请为你的修改添加相应的测试
1. 确保你的代码能通过现有的测试
1. 请在 PR 描述中关联相关 issue,格式为 `fixes #<issue编号>`
1. 等待合并!
#### 前端
关于前端服务的设置,请参考 `web/README.md` 文件中的[详细指南](https://github.com/langgenius/dify/blob/main/web/README.md)。该文档提供了帮助你正确配置前端环境的详细说明。
#### 后端
关于后端服务的设置,请参考 `api/README.md` 文件中的[详细说明](https://github.com/langgenius/dify/blob/main/api/README.md)。该文档包含了帮助你顺利运行后端的步骤说明。
#### 其他注意事项
我们建议在开始设置之前仔细阅读本文档,因为它包含以下重要信息:
- 前置条件和依赖项
- 安装步骤
- 配置细节
- 常见问题解决方案
如果在设置过程中遇到任何问题,请随时联系我们。
## 获取帮助
如果你在贡献过程中遇到困难或有紧急问题,可以通过相关 GitHub issue 向我们提问,或加入我们的 [Discord](https://discord.gg/8Tpq4AcN9c) 进行快速交流。
+95
View File
@@ -0,0 +1,95 @@
# MITWIRKEN
Sie möchten also zu Dify beitragen - das ist großartig, wir können es kaum erwarten zu sehen, was Sie entwickeln. Als Startup mit begrenztem Personal und Finanzierung haben wir große Ambitionen, den intuitivsten Workflow für die Entwicklung und Verwaltung von LLM-Anwendungen zu gestalten. Jede Hilfe aus der Community zählt wirklich.
Wir müssen wendig sein und schnell liefern, aber wir möchten auch sicherstellen, dass Mitwirkende wie Sie eine möglichst reibungslose Erfahrung beim Beitragen haben. Wir haben diesen Leitfaden zusammengestellt, damit Sie sich schnell mit der Codebasis und unserer Arbeitsweise mit Mitwirkenden vertraut machen können.
Dieser Leitfaden ist, wie Dify selbst, in ständiger Entwicklung. Wir sind dankbar für Ihr Verständnis, falls er manchmal hinter dem eigentlichen Projekt zurückbleibt, und begrüßen jedes Feedback zur Verbesserung.
Bitte nehmen Sie sich einen Moment Zeit, um unsere [Lizenz- und Mitwirkungsvereinbarung](./LICENSE) zu lesen. Die Community hält sich außerdem an den [Verhaltenskodex](https://github.com/langgenius/.github/blob/main/CODE_OF_CONDUCT.md).
## Bevor Sie loslegen
Suchen Sie nach einer Aufgabe? Durchstöbern Sie unsere [Einsteiger-Issues](https://github.com/langgenius/dify/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22) und wählen Sie eines zum Einstieg!
Haben Sie eine neue Modell-Runtime oder ein Tool hinzuzufügen? Öffnen Sie einen PR in unserem [Plugin-Repository](https://github.com/langgenius/dify-plugins).
Möchten Sie eine bestehende Modell-Runtime oder ein Tool aktualisieren oder Bugs beheben? Besuchen Sie unser [offizielles Plugin-Repository](https://github.com/langgenius/dify-official-plugins)!
Vergessen Sie nicht, in der PR-Beschreibung ein bestehendes Issue zu verlinken oder ein neues zu erstellen.
### Fehlermeldungen
> [!WICHTIG]
> Bitte stellen Sie sicher, dass Sie folgende Informationen bei der Einreichung eines Fehlerberichts angeben:
- Ein klarer und beschreibender Titel
- Eine detaillierte Beschreibung des Fehlers, einschließlich Fehlermeldungen
- Schritte zur Reproduktion des Fehlers
- Erwartetes Verhalten
- **Logs** bei Backend-Problemen (sehr wichtig, zu finden in docker-compose logs)
- Screenshots oder Videos, falls zutreffend
Unsere Priorisierung:
| Fehlertyp | Priorität |
| ------------------------------------------------------------ | --------------- |
| Fehler in Kernfunktionen (Cloud-Service, Login nicht möglich, Anwendungen funktionieren nicht, Sicherheitslücken) | Kritisch |
| Nicht-kritische Fehler, Leistungsverbesserungen | Mittlere Priorität |
| Kleinere Korrekturen (Tippfehler, verwirrende aber funktionierende UI) | Niedrige Priorität |
### Feature-Anfragen
> [!HINWEIS]
> Bitte stellen Sie sicher, dass Sie folgende Informationen bei der Einreichung einer Feature-Anfrage angeben:
- Ein klarer und beschreibender Titel
- Eine detaillierte Beschreibung des Features
- Ein Anwendungsfall für das Feature
- Zusätzlicher Kontext oder Screenshots zur Feature-Anfrage
Unsere Priorisierung:
| Feature-Typ | Priorität |
| ------------------------------------------------------------ | --------------- |
| Hochprioritäre Features (durch Teammitglied gekennzeichnet) | Hohe Priorität |
| Beliebte Feature-Anfragen aus unserem [Community-Feedback-Board](https://github.com/langgenius/dify/discussions/categories/feedbacks) | Mittlere Priorität |
| Nicht-Kernfunktionen und kleinere Verbesserungen | Niedrige Priorität |
| Wertvoll, aber nicht dringend | Zukunfts-Feature |
## Einreichen Ihres PRs
### Pull-Request-Prozess
1. Repository forken
1. Vor dem Erstellen eines PRs bitte ein Issue zur Diskussion der Änderungen erstellen
1. Einen neuen Branch für Ihre Änderungen erstellen
1. Tests für Ihre Änderungen hinzufügen
1. Sicherstellen, dass Ihr Code die bestehenden Tests besteht
1. Issue in der PR-Beschreibung verlinken (`fixes #<issue_number>`)
1. Auf den Merge warten!
### Projekt einrichten
#### Frontend
Für die Einrichtung des Frontend-Service folgen Sie bitte unserer ausführlichen [Anleitung](https://github.com/langgenius/dify/blob/main/web/README.md) in der Datei `web/README.md`.
#### Backend
Für die Einrichtung des Backend-Service folgen Sie bitte unseren detaillierten [Anweisungen](https://github.com/langgenius/dify/blob/main/api/README.md) in der Datei `api/README.md`.
#### Weitere Hinweise
Wir empfehlen, dieses Dokument sorgfältig zu lesen, da es wichtige Informationen enthält über:
- Voraussetzungen und Abhängigkeiten
- Installationsschritte
- Konfigurationsdetails
- Häufige Problemlösungen
Bei Problemen während der Einrichtung können Sie sich gerne an uns wenden.
## Hilfe bekommen
Wenn Sie beim Mitwirken Fragen haben oder nicht weiterkommen, stellen Sie Ihre Fragen einfach im entsprechenden GitHub Issue oder besuchen Sie unseren [Discord](https://discord.gg/8Tpq4AcN9c) für einen schnellen Austausch.

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