ag-ui-dify-adapter 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Chuanlong
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,8 @@
1
+ include README.md
2
+ include README_zh_CN.md
3
+ include LICENSE
4
+ include pyproject.toml
5
+ graft ag_ui_dify
6
+ graft tests
7
+ prune __pycache__
8
+ prune *.pyc
@@ -0,0 +1,240 @@
1
+ Metadata-Version: 2.4
2
+ Name: ag-ui-dify-adapter
3
+ Version: 0.1.0
4
+ Summary: AG-UI protocol adapter for Dify — translates Dify API responses to AG-UI streaming events
5
+ Author: Chuanlong
6
+ License-Expression: MIT
7
+ Project-URL: Repository, https://gitee.com/chuanlong/ag-ui-dify-adapter
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.9
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
17
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
+ Requires-Python: >=3.9
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: ag-ui-protocol>=0.1.17
22
+ Requires-Dist: httpx>=0.27.0
23
+ Requires-Dist: pydantic>=2.11.0
24
+ Provides-Extra: server
25
+ Requires-Dist: starlette>=0.40.0; extra == "server"
26
+ Requires-Dist: uvicorn>=0.30.0; extra == "server"
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest>=8.0; extra == "dev"
29
+ Requires-Dist: pytest-asyncio>=0.24.0; extra == "dev"
30
+ Requires-Dist: pytest-httpx>=0.30.0; extra == "dev"
31
+ Dynamic: license-file
32
+
33
+ # ag-ui-dify-adapter
34
+
35
+ AG-UI protocol adapter for Dify — translates [Dify](https://dify.ai) API responses to [AG-UI](https://ag-ui.com) streaming events, enabling Dify-powered AI agents to integrate with any AG-UI-compatible frontend.
36
+
37
+ ## Features
38
+
39
+ - **All 4 Dify app types**: Chat, Agent, Workflow, Completion
40
+ - **Complete event mapping**: Maps all Dify SSE events to AG-UI's 17 standard event types
41
+ - **Tool call support**: Agent tool calls (ReAct loops) translated to `TOOL_CALL_START/ARGS/END`
42
+ - **Streaming**: Real-time text streaming via `TEXT_MESSAGE_START/CONTENT/END`
43
+ - **Multi-turn conversation**: `thread_id` ↔ `conversation_id` tracking
44
+ - **State & context**: AG-UI state/context/forwardedProps → Dify input variables
45
+ - **File support**: File attachments via Dify's file upload API
46
+ - **HTTP server**: Built-in Starlette endpoint with SSE streaming
47
+ - **Async**: Full async support with `httpx`
48
+
49
+ ## Installation
50
+
51
+ ```bash
52
+ pip install ag-ui-dify-adapter
53
+ ```
54
+
55
+ For the HTTP server:
56
+
57
+ ```bash
58
+ pip install ag-ui-dify-adapter[server]
59
+ ```
60
+
61
+ ## Quick Start
62
+
63
+ ### Usage as a library
64
+
65
+ ```python
66
+ import asyncio
67
+ from ag_ui_dify import DifyAgent, DifyConfig, DifyAppType
68
+ from ag_ui.core import RunAgentInput, UserMessage
69
+
70
+ async def main():
71
+ agent = DifyAgent(DifyConfig(
72
+ api_key="app-xxx",
73
+ base_url="https://api.dify.ai/v1",
74
+ app_type=DifyAppType.AGENT, # auto-detected if omitted
75
+ ))
76
+
77
+ input = RunAgentInput(
78
+ thread_id="thread-1",
79
+ run_id="run-1",
80
+ state=None,
81
+ messages=[UserMessage(id="u1", role="user", content="Hello!")],
82
+ tools=[],
83
+ context=[],
84
+ forwarded_props={},
85
+ )
86
+
87
+ async for event in agent.run(input):
88
+ print(event.model_dump_json(by_alias=True))
89
+
90
+ asyncio.run(main())
91
+ ```
92
+
93
+ ### Usage as an HTTP server
94
+
95
+ ```python
96
+ from ag_ui_dify import create_app
97
+ import uvicorn
98
+
99
+ app = create_app()
100
+ uvicorn.run(app, host="0.0.0.0", port=8080)
101
+ ```
102
+
103
+ Then send requests:
104
+
105
+ ```bash
106
+ curl -X POST http://localhost:8080/ \
107
+ -H "Content-Type: application/json" \
108
+ -d '{
109
+ "threadId": "t1",
110
+ "runId": "r1",
111
+ "messages": [{"id": "u1", "role": "user", "content": "Hello!"}],
112
+ "tools": [],
113
+ "context": [],
114
+ "forwardedProps": {
115
+ "apiKey": "app-xxx",
116
+ "baseUrl": "https://api.dify.ai/v1",
117
+ "appType": "agent"
118
+ }
119
+ }'
120
+ ```
121
+
122
+ ## Dify → AG-UI Event Mapping
123
+
124
+ ### Agent App
125
+
126
+ | Dify SSE Event | AG-UI Event(s) |
127
+ |---|---|
128
+ | `agent_thought` (with thought) | `STEP_STARTED` + `CUSTOM` (thought) |
129
+ | `agent_thought` (with tool) | `TOOL_CALL_START` + `TOOL_CALL_ARGS` + `TOOL_CALL_END` |
130
+ | `agent_thought` (with observation) | `CUSTOM` (observation) + `STEP_FINISHED` |
131
+ | `agent_message` (first) | `TEXT_MESSAGE_START` |
132
+ | `agent_message` | `TEXT_MESSAGE_CONTENT` |
133
+ | `message_end` | `TEXT_MESSAGE_END` + `RUN_FINISHED` |
134
+
135
+ ### Workflow App
136
+
137
+ | Dify SSE Event | AG-UI Event(s) |
138
+ |---|---|
139
+ | `workflow_started` | `RUN_STARTED` |
140
+ | `node_started` | `STEP_STARTED` |
141
+ | `agent_log` | `STEP_STARTED` / `STEP_FINISHED` |
142
+ | `text_chunk` | `TEXT_MESSAGE_CONTENT` |
143
+ | `node_finished` | `STEP_FINISHED` |
144
+ | `workflow_finished` | `TEXT_MESSAGE_END` + `RUN_FINISHED` |
145
+
146
+ ### Chat App
147
+
148
+ | Dify SSE Event | AG-UI Event(s) |
149
+ |---|---|
150
+ | `message` (first) | `TEXT_MESSAGE_START` |
151
+ | `message` | `TEXT_MESSAGE_CONTENT` |
152
+ | `message_end` | `TEXT_MESSAGE_END` + `RUN_FINISHED` |
153
+ | `message_file` | `CUSTOM` |
154
+
155
+ ### Completion App
156
+
157
+ | Dify SSE Event | AG-UI Event(s) |
158
+ |---|---|
159
+ | `message` (first) | `TEXT_MESSAGE_START` |
160
+ | `message` | `TEXT_MESSAGE_CONTENT` |
161
+ | `message_end` | `TEXT_MESSAGE_END` + `RUN_FINISHED` |
162
+
163
+ All app types: `RUN_STARTED` at the beginning, `RUN_ERROR` on error, `ping` ignored.
164
+
165
+ ## API Reference
166
+
167
+ ### DifyAgent
168
+
169
+ ```python
170
+ agent = DifyAgent(DifyConfig(
171
+ api_key="app-xxx", # Required: Dify API key
172
+ base_url="...", # Default: https://api.dify.ai/v1
173
+ app_type=DifyAppType.AGENT, # Auto-detected if omitted
174
+ user="ag-ui-user", # Default user identifier
175
+ timeout=120.0, # HTTP timeout in seconds
176
+ ))
177
+
178
+ async for event in agent.run(run_input):
179
+ ...
180
+ ```
181
+
182
+ ### DifyClient
183
+
184
+ Low-level async client for all Dify API endpoints:
185
+
186
+ ```python
187
+ client = DifyClient(config)
188
+ async for evt in client.stream_chat(query="Hello", inputs={}):
189
+ ...
190
+ async for evt in client.stream_workflow(inputs={"url": "..."}):
191
+ ...
192
+ async for evt in client.stream_completion(inputs={}):
193
+ ...
194
+ await client.stop_chat(task_id="...")
195
+ messages = await client.get_messages(conversation_id="...", user="...")
196
+ convs = await client.get_conversations(user="...")
197
+ upload_result = await client.upload_file(file_path="...", user="...")
198
+ ```
199
+
200
+ ## Project Structure
201
+
202
+ ```
203
+ ag_ui_dify/
204
+ ├── __init__.py # Package exports
205
+ ├── types.py # Dify type definitions (Pydantic models)
206
+ ├── dify_client.py # Async HTTP client for all Dify endpoints
207
+ ├── event_translator.py # Event translators (Chat/Agent/Workflow/Completion)
208
+ ├── agent.py # DifyAgent main adapter
209
+ └── server.py # Starlette HTTP SSE endpoint
210
+ tests/
211
+ ├── test_types.py # Type model tests (19)
212
+ ├── test_translator.py # Translator tests (14)
213
+ ├── test_client.py # Client tests (5)
214
+ ├── test_agent.py # Agent tests (10)
215
+ └── test_integration.py # Real-environment integration tests
216
+ ```
217
+
218
+ ## Verification Status
219
+
220
+ All 4 Dify app types have been verified against a real Dify instance:
221
+
222
+ | App Type | Real Dify Tested | Notes |
223
+ |---|---|---|
224
+ | Agent | ✓ | Tool calls, reasoning chain, multi-turn conversation |
225
+ | Workflow | ✓ | Node execution, agent_log sub-steps, text output |
226
+ | Chat | ✓ | Streaming text, message lifecycle |
227
+ | Completion | ✓ | Streaming text, input variables |
228
+
229
+ ## Requirements
230
+
231
+ - Python >= 3.9
232
+ - ag-ui-protocol >= 0.1.17
233
+ - httpx >= 0.27.0
234
+ - pydantic >= 2.11.0
235
+ - starlette >= 0.40.0 (optional, for HTTP server)
236
+ - uvicorn (optional, for HTTP server)
237
+
238
+ ## License
239
+
240
+ MIT
@@ -0,0 +1,208 @@
1
+ # ag-ui-dify-adapter
2
+
3
+ AG-UI protocol adapter for Dify — translates [Dify](https://dify.ai) API responses to [AG-UI](https://ag-ui.com) streaming events, enabling Dify-powered AI agents to integrate with any AG-UI-compatible frontend.
4
+
5
+ ## Features
6
+
7
+ - **All 4 Dify app types**: Chat, Agent, Workflow, Completion
8
+ - **Complete event mapping**: Maps all Dify SSE events to AG-UI's 17 standard event types
9
+ - **Tool call support**: Agent tool calls (ReAct loops) translated to `TOOL_CALL_START/ARGS/END`
10
+ - **Streaming**: Real-time text streaming via `TEXT_MESSAGE_START/CONTENT/END`
11
+ - **Multi-turn conversation**: `thread_id` ↔ `conversation_id` tracking
12
+ - **State & context**: AG-UI state/context/forwardedProps → Dify input variables
13
+ - **File support**: File attachments via Dify's file upload API
14
+ - **HTTP server**: Built-in Starlette endpoint with SSE streaming
15
+ - **Async**: Full async support with `httpx`
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ pip install ag-ui-dify-adapter
21
+ ```
22
+
23
+ For the HTTP server:
24
+
25
+ ```bash
26
+ pip install ag-ui-dify-adapter[server]
27
+ ```
28
+
29
+ ## Quick Start
30
+
31
+ ### Usage as a library
32
+
33
+ ```python
34
+ import asyncio
35
+ from ag_ui_dify import DifyAgent, DifyConfig, DifyAppType
36
+ from ag_ui.core import RunAgentInput, UserMessage
37
+
38
+ async def main():
39
+ agent = DifyAgent(DifyConfig(
40
+ api_key="app-xxx",
41
+ base_url="https://api.dify.ai/v1",
42
+ app_type=DifyAppType.AGENT, # auto-detected if omitted
43
+ ))
44
+
45
+ input = RunAgentInput(
46
+ thread_id="thread-1",
47
+ run_id="run-1",
48
+ state=None,
49
+ messages=[UserMessage(id="u1", role="user", content="Hello!")],
50
+ tools=[],
51
+ context=[],
52
+ forwarded_props={},
53
+ )
54
+
55
+ async for event in agent.run(input):
56
+ print(event.model_dump_json(by_alias=True))
57
+
58
+ asyncio.run(main())
59
+ ```
60
+
61
+ ### Usage as an HTTP server
62
+
63
+ ```python
64
+ from ag_ui_dify import create_app
65
+ import uvicorn
66
+
67
+ app = create_app()
68
+ uvicorn.run(app, host="0.0.0.0", port=8080)
69
+ ```
70
+
71
+ Then send requests:
72
+
73
+ ```bash
74
+ curl -X POST http://localhost:8080/ \
75
+ -H "Content-Type: application/json" \
76
+ -d '{
77
+ "threadId": "t1",
78
+ "runId": "r1",
79
+ "messages": [{"id": "u1", "role": "user", "content": "Hello!"}],
80
+ "tools": [],
81
+ "context": [],
82
+ "forwardedProps": {
83
+ "apiKey": "app-xxx",
84
+ "baseUrl": "https://api.dify.ai/v1",
85
+ "appType": "agent"
86
+ }
87
+ }'
88
+ ```
89
+
90
+ ## Dify → AG-UI Event Mapping
91
+
92
+ ### Agent App
93
+
94
+ | Dify SSE Event | AG-UI Event(s) |
95
+ |---|---|
96
+ | `agent_thought` (with thought) | `STEP_STARTED` + `CUSTOM` (thought) |
97
+ | `agent_thought` (with tool) | `TOOL_CALL_START` + `TOOL_CALL_ARGS` + `TOOL_CALL_END` |
98
+ | `agent_thought` (with observation) | `CUSTOM` (observation) + `STEP_FINISHED` |
99
+ | `agent_message` (first) | `TEXT_MESSAGE_START` |
100
+ | `agent_message` | `TEXT_MESSAGE_CONTENT` |
101
+ | `message_end` | `TEXT_MESSAGE_END` + `RUN_FINISHED` |
102
+
103
+ ### Workflow App
104
+
105
+ | Dify SSE Event | AG-UI Event(s) |
106
+ |---|---|
107
+ | `workflow_started` | `RUN_STARTED` |
108
+ | `node_started` | `STEP_STARTED` |
109
+ | `agent_log` | `STEP_STARTED` / `STEP_FINISHED` |
110
+ | `text_chunk` | `TEXT_MESSAGE_CONTENT` |
111
+ | `node_finished` | `STEP_FINISHED` |
112
+ | `workflow_finished` | `TEXT_MESSAGE_END` + `RUN_FINISHED` |
113
+
114
+ ### Chat App
115
+
116
+ | Dify SSE Event | AG-UI Event(s) |
117
+ |---|---|
118
+ | `message` (first) | `TEXT_MESSAGE_START` |
119
+ | `message` | `TEXT_MESSAGE_CONTENT` |
120
+ | `message_end` | `TEXT_MESSAGE_END` + `RUN_FINISHED` |
121
+ | `message_file` | `CUSTOM` |
122
+
123
+ ### Completion App
124
+
125
+ | Dify SSE Event | AG-UI Event(s) |
126
+ |---|---|
127
+ | `message` (first) | `TEXT_MESSAGE_START` |
128
+ | `message` | `TEXT_MESSAGE_CONTENT` |
129
+ | `message_end` | `TEXT_MESSAGE_END` + `RUN_FINISHED` |
130
+
131
+ All app types: `RUN_STARTED` at the beginning, `RUN_ERROR` on error, `ping` ignored.
132
+
133
+ ## API Reference
134
+
135
+ ### DifyAgent
136
+
137
+ ```python
138
+ agent = DifyAgent(DifyConfig(
139
+ api_key="app-xxx", # Required: Dify API key
140
+ base_url="...", # Default: https://api.dify.ai/v1
141
+ app_type=DifyAppType.AGENT, # Auto-detected if omitted
142
+ user="ag-ui-user", # Default user identifier
143
+ timeout=120.0, # HTTP timeout in seconds
144
+ ))
145
+
146
+ async for event in agent.run(run_input):
147
+ ...
148
+ ```
149
+
150
+ ### DifyClient
151
+
152
+ Low-level async client for all Dify API endpoints:
153
+
154
+ ```python
155
+ client = DifyClient(config)
156
+ async for evt in client.stream_chat(query="Hello", inputs={}):
157
+ ...
158
+ async for evt in client.stream_workflow(inputs={"url": "..."}):
159
+ ...
160
+ async for evt in client.stream_completion(inputs={}):
161
+ ...
162
+ await client.stop_chat(task_id="...")
163
+ messages = await client.get_messages(conversation_id="...", user="...")
164
+ convs = await client.get_conversations(user="...")
165
+ upload_result = await client.upload_file(file_path="...", user="...")
166
+ ```
167
+
168
+ ## Project Structure
169
+
170
+ ```
171
+ ag_ui_dify/
172
+ ├── __init__.py # Package exports
173
+ ├── types.py # Dify type definitions (Pydantic models)
174
+ ├── dify_client.py # Async HTTP client for all Dify endpoints
175
+ ├── event_translator.py # Event translators (Chat/Agent/Workflow/Completion)
176
+ ├── agent.py # DifyAgent main adapter
177
+ └── server.py # Starlette HTTP SSE endpoint
178
+ tests/
179
+ ├── test_types.py # Type model tests (19)
180
+ ├── test_translator.py # Translator tests (14)
181
+ ├── test_client.py # Client tests (5)
182
+ ├── test_agent.py # Agent tests (10)
183
+ └── test_integration.py # Real-environment integration tests
184
+ ```
185
+
186
+ ## Verification Status
187
+
188
+ All 4 Dify app types have been verified against a real Dify instance:
189
+
190
+ | App Type | Real Dify Tested | Notes |
191
+ |---|---|---|
192
+ | Agent | ✓ | Tool calls, reasoning chain, multi-turn conversation |
193
+ | Workflow | ✓ | Node execution, agent_log sub-steps, text output |
194
+ | Chat | ✓ | Streaming text, message lifecycle |
195
+ | Completion | ✓ | Streaming text, input variables |
196
+
197
+ ## Requirements
198
+
199
+ - Python >= 3.9
200
+ - ag-ui-protocol >= 0.1.17
201
+ - httpx >= 0.27.0
202
+ - pydantic >= 2.11.0
203
+ - starlette >= 0.40.0 (optional, for HTTP server)
204
+ - uvicorn (optional, for HTTP server)
205
+
206
+ ## License
207
+
208
+ MIT
@@ -0,0 +1,208 @@
1
+ # ag-ui-dify-adapter
2
+
3
+ AG-UI 协议 Dify 适配器 — 将 [Dify](https://dify.ai) API 响应转换为 [AG-UI](https://ag-ui.com) 流式事件,使 Dify 驱动的 AI Agent 能够集成到任何兼容 AG-UI 的前端应用中。
4
+
5
+ ## 特性
6
+
7
+ - **全部 4 种 Dify 应用类型**:Chat(对话)、Agent(智能体)、Workflow(工作流)、Completion(文本生成)
8
+ - **完整事件映射**:将全部 Dify SSE 事件映射为 AG-UI 的 17 种标准事件类型
9
+ - **工具调用支持**:Agent 工具调用(ReAct 循环)转换为 `TOOL_CALL_START/ARGS/END`
10
+ - **实时流式输出**:通过 `TEXT_MESSAGE_START/CONTENT/END` 实现逐 token 流式文本输出
11
+ - **多轮对话**:`thread_id` ↔ `conversation_id` 映射追踪
12
+ - **状态与上下文**:AG-UI 的 state/context/forwardedProps → Dify 的 input 变量
13
+ - **文件支持**:通过 Dify 文件上传 API 支持文件附件
14
+ - **HTTP 服务**:内置 Starlette SSE 流式端点
15
+ - **全异步**:基于 `httpx` 的完整异步支持
16
+
17
+ ## 安装
18
+
19
+ ```bash
20
+ pip install ag-ui-dify-adapter
21
+ ```
22
+
23
+ 如需 HTTP 服务端:
24
+
25
+ ```bash
26
+ pip install ag-ui-dify-adapter[server]
27
+ ```
28
+
29
+ ## 快速开始
30
+
31
+ ### 作为库使用
32
+
33
+ ```python
34
+ import asyncio
35
+ from ag_ui_dify import DifyAgent, DifyConfig, DifyAppType
36
+ from ag_ui.core import RunAgentInput, UserMessage
37
+
38
+ async def main():
39
+ agent = DifyAgent(DifyConfig(
40
+ api_key="app-xxx",
41
+ base_url="https://api.dify.ai/v1",
42
+ app_type=DifyAppType.AGENT, # 不指定则自动检测
43
+ ))
44
+
45
+ input = RunAgentInput(
46
+ thread_id="thread-1",
47
+ run_id="run-1",
48
+ state=None,
49
+ messages=[UserMessage(id="u1", role="user", content="你好!")],
50
+ tools=[],
51
+ context=[],
52
+ forwarded_props={},
53
+ )
54
+
55
+ async for event in agent.run(input):
56
+ print(event.model_dump_json(by_alias=True))
57
+
58
+ asyncio.run(main())
59
+ ```
60
+
61
+ ### 作为 HTTP 服务运行
62
+
63
+ ```python
64
+ from ag_ui_dify import create_app
65
+ import uvicorn
66
+
67
+ app = create_app()
68
+ uvicorn.run(app, host="0.0.0.0", port=8080)
69
+ ```
70
+
71
+ 发送请求:
72
+
73
+ ```bash
74
+ curl -X POST http://localhost:8080/ \
75
+ -H "Content-Type: application/json" \
76
+ -d '{
77
+ "threadId": "t1",
78
+ "runId": "r1",
79
+ "messages": [{"id": "u1", "role": "user", "content": "你好!"}],
80
+ "tools": [],
81
+ "context": [],
82
+ "forwardedProps": {
83
+ "apiKey": "app-xxx",
84
+ "baseUrl": "https://api.dify.ai/v1",
85
+ "appType": "agent"
86
+ }
87
+ }'
88
+ ```
89
+
90
+ ## Dify → AG-UI 事件映射
91
+
92
+ ### Agent(智能体)应用
93
+
94
+ | Dify SSE 事件 | AG-UI 事件 |
95
+ |---|---|
96
+ | `agent_thought`(带思考内容) | `STEP_STARTED` + `CUSTOM`(思考) |
97
+ | `agent_thought`(带工具调用) | `TOOL_CALL_START` + `TOOL_CALL_ARGS` + `TOOL_CALL_END` |
98
+ | `agent_thought`(带观察结果) | `CUSTOM`(观察)+ `STEP_FINISHED` |
99
+ | `agent_message`(首条) | `TEXT_MESSAGE_START` |
100
+ | `agent_message` | `TEXT_MESSAGE_CONTENT` |
101
+ | `message_end` | `TEXT_MESSAGE_END` + `RUN_FINISHED` |
102
+
103
+ ### Workflow(工作流)应用
104
+
105
+ | Dify SSE 事件 | AG-UI 事件 |
106
+ |---|---|
107
+ | `workflow_started` | `RUN_STARTED` |
108
+ | `node_started` | `STEP_STARTED` |
109
+ | `agent_log` | `STEP_STARTED` / `STEP_FINISHED` |
110
+ | `text_chunk` | `TEXT_MESSAGE_CONTENT` |
111
+ | `node_finished` | `STEP_FINISHED` |
112
+ | `workflow_finished` | `TEXT_MESSAGE_END` + `RUN_FINISHED` |
113
+
114
+ ### Chat(对话)应用
115
+
116
+ | Dify SSE 事件 | AG-UI 事件 |
117
+ |---|---|
118
+ | `message`(首条) | `TEXT_MESSAGE_START` |
119
+ | `message` | `TEXT_MESSAGE_CONTENT` |
120
+ | `message_end` | `TEXT_MESSAGE_END` + `RUN_FINISHED` |
121
+ | `message_file` | `CUSTOM` |
122
+
123
+ ### Completion(文本生成)应用
124
+
125
+ | Dify SSE 事件 | AG-UI 事件 |
126
+ |---|---|
127
+ | `message`(首条) | `TEXT_MESSAGE_START` |
128
+ | `message` | `TEXT_MESSAGE_CONTENT` |
129
+ | `message_end` | `TEXT_MESSAGE_END` + `RUN_FINISHED` |
130
+
131
+ 所有应用类型:开头均发送 `RUN_STARTED`,出错时发送 `RUN_ERROR`,`ping` 心跳事件被忽略。
132
+
133
+ ## API 参考
134
+
135
+ ### DifyAgent
136
+
137
+ ```python
138
+ agent = DifyAgent(DifyConfig(
139
+ api_key="app-xxx", # 必填:Dify API 密钥
140
+ base_url="...", # 默认:https://api.dify.ai/v1
141
+ app_type=DifyAppType.AGENT, # 不指定则自动检测
142
+ user="ag-ui-user", # 默认用户标识
143
+ timeout=120.0, # HTTP 超时时间(秒)
144
+ ))
145
+
146
+ async for event in agent.run(run_input):
147
+ ...
148
+ ```
149
+
150
+ ### DifyClient
151
+
152
+ 底层异步客户端,覆盖全部 Dify API 端点:
153
+
154
+ ```python
155
+ client = DifyClient(config)
156
+ async for evt in client.stream_chat(query="你好", inputs={}):
157
+ ...
158
+ async for evt in client.stream_workflow(inputs={"url": "..."}):
159
+ ...
160
+ async for evt in client.stream_completion(inputs={}):
161
+ ...
162
+ await client.stop_chat(task_id="...")
163
+ messages = await client.get_messages(conversation_id="...", user="...")
164
+ convs = await client.get_conversations(user="...")
165
+ upload_result = await client.upload_file(file_path="...", user="...")
166
+ ```
167
+
168
+ ## 依赖
169
+
170
+ - Python >= 3.9
171
+ - ag-ui-protocol >= 0.1.17
172
+ - httpx >= 0.27.0
173
+ - pydantic >= 2.11.0
174
+ - starlette >= 0.40.0(可选,用于 HTTP 服务)
175
+ - uvicorn(可选,用于 HTTP 服务)
176
+
177
+ ## 项目结构
178
+
179
+ ```
180
+ ag_ui_dify/
181
+ ├── __init__.py # 包导出
182
+ ├── types.py # Dify 类型定义(Pydantic 模型)
183
+ ├── dify_client.py # Dify API 异步 HTTP 客户端
184
+ ├── event_translator.py # 事件转换器(Chat/Agent/Workflow/Completion)
185
+ ├── agent.py # DifyAgent 主适配器
186
+ └── server.py # Starlette HTTP SSE 端点
187
+ tests/
188
+ ├── test_types.py # 类型模型测试(19 个)
189
+ ├── test_translator.py # 转换器测试(14 个)
190
+ ├── test_client.py # 客户端测试(5 个)
191
+ ├── test_agent.py # Agent 测试(10 个)
192
+ └── test_integration.py # 实际环境集成测试
193
+ ```
194
+
195
+ ## 验证状态
196
+
197
+ 全部 4 种 Dify 应用类型已在真实 Dify 实例上完成验证:
198
+
199
+ | App 类型 | 实际 Dify 环境 | 验证内容 |
200
+ |---|---|---|
201
+ | Agent(智能体) | ✅ | 工具调用、思考链、多轮对话 |
202
+ | Workflow(工作流) | ✅ | 节点执行、Agent 子步骤、文本输出 |
203
+ | Chat(对话) | ✅ | 流式文本、消息生命周期 |
204
+ | Completion(文本生成) | ✅ | 流式文本、输入变量 |
205
+
206
+ ## License
207
+
208
+ MIT