dify_client/
response.rs

1//! This module contains the response structures used in the Dify SDK.
2//!
3//! It includes error responses, result responses, chat message responses, and more.
4//! These structures are used to deserialize JSON responses from the Dify API.
5//!
6//! # Examples
7//!
8//! Deserialize an error response:
9//!
10//! ```no_run
11//! use dify_client::response::ErrorResponse;
12//!
13//! let json = r#"
14//!     {
15//!         "code": "unknown_error",
16//!         "message": "An unknown error occurred",
17//!         "status": 503
18//!     }
19//! "#;
20//!
21//! let error_response: ErrorResponse = serde_json::from_str(json).unwrap();
22//!
23//! assert_eq!(error_response.code, "unknown_error");
24//! assert_eq!(error_response.message, "An unknown error occurred");
25//! assert_eq!(error_response.status, 503);
26//! ```
27//!
28//! Deserialize a chat message response:
29//!
30//! ```no_run
31//! use dify_client::response::{ChatMessagesResponse, AppMode};
32//! use serde_json::json;
33//! use std::collections::HashMap;
34//!
35//! let json = r#"
36//!     {
37//!         "base": {
38//!             "message_id": "12345",
39//!             "conversation_id": "67890",
40//!             "created_at": 1705395332
41//!         },
42//!         "event": "message",
43//!         "mode": "chat",
44//!         "answer": "Hello, how can I help you?",
45//!         "metadata": {
46//!             "key1": "value1",
47//!             "key2": "value2"
48//!         }
49//!     }
50//! "#;
51//!
52//! let mut metadata = HashMap::new();
53//! metadata.insert("key1".to_string(), json!("value1"));
54//! metadata.insert("key2".to_string(), json!("value2"));
55//!
56//! let chat_response: ChatMessagesResponse = serde_json::from_str(json).unwrap();
57//!
58//! assert_eq!(chat_response.base.message_id, "12345");
59//! assert_eq!(chat_response.base.conversation_id.unwrap(), "67890");
60//! assert_eq!(chat_response.base.created_at, 1705395332);
61//! assert_eq!(chat_response.event, "message");
62//! assert_eq!(chat_response.mode, AppMode::Chat);
63//! assert_eq!(chat_response.answer, "Hello, how can I help you?");
64//! assert_eq!(chat_response.metadata, metadata);
65//! ```
66//!
67use super::request::{Feedback, FileType};
68use anyhow::{anyhow, bail, Result as AnyResult};
69use eventsource_stream::EventStream;
70use futures::Stream;
71use pin_project_lite::pin_project;
72use serde::{Deserialize, Serialize};
73use serde_json::Value as JsonValue;
74use serde_with::{serde_as, EnumMap};
75use std::{
76    collections::HashMap,
77    fmt::{Display, Formatter, Result as FmtResult},
78    pin::Pin,
79    task::{Context, Poll},
80};
81
82/// 错误响应
83#[derive(Debug, Clone, Serialize, Deserialize)]
84pub struct ErrorResponse {
85    pub code: String,
86    pub message: String,
87    pub status: u32,
88}
89
90impl Display for ErrorResponse {
91    fn fmt(&self, f: &mut Formatter) -> FmtResult {
92        write!(f, "{}", serde_json::to_string(&self).unwrap())
93    }
94}
95
96impl ErrorResponse {
97    pub fn unknown<T>(message: T) -> Self
98    where
99        T: ToString,
100    {
101        ErrorResponse {
102            code: "unknown_error".into(),
103            message: message.to_string(),
104            status: 503,
105        }
106    }
107}
108
109/// 通用结果响应
110#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct ResultResponse {
112    pub result: String,
113}
114
115/// 对话基础信息
116#[derive(Debug, Clone, Serialize, Deserialize)]
117pub struct MessageBase {
118    /// 消息唯一 ID
119    pub message_id: String,
120    /// 会话 ID
121    pub conversation_id: Option<String>,
122    /// 创建时间戳,如:1705395332
123    pub created_at: u64,
124}
125
126/// 发送对话消息的响应
127#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct ChatMessagesResponse {
129    /// 消息基础信息
130    #[serde(flatten)]
131    pub base: MessageBase,
132    /// 事件
133    pub event: String,
134    /// App 模式
135    pub mode: AppMode,
136    /// 完整回复内容
137    pub answer: String,
138    /// 元数据
139    pub metadata: HashMap<String, JsonValue>,
140}
141
142/// 流式模式分块数据事件
143#[derive(Debug, Clone, Serialize, Deserialize)]
144#[serde(tag = "event", rename_all = "snake_case")]
145pub enum SseMessageEvent {
146    /// LLM 返回文本块事件,即:完整的文本以分块的方式输出。
147    Message {
148        /// 消息基础信息
149        #[serde(flatten)]
150        base: Option<MessageBase>,
151        /// 消息 ID
152        id: String,
153        /// 任务 ID,用于请求跟踪和下方的停止响应接口
154        task_id: String,
155        /// LLM 返回文本块内容
156        answer: String,
157        #[serde(flatten)]
158        extra: HashMap<String, JsonValue>,
159    },
160    /// 文件事件,表示有新文件需要展示
161    MessageFile {
162        /// 消息基础信息
163        #[serde(flatten)]
164        base: Option<MessageBase>,
165        /// 文件唯一 ID
166        id: String,
167        /// 文件类型,目前仅为 image
168        #[serde(rename = "type")]
169        type_: FileType,
170        /// 文件归属,user 或 assistant,该接口返回仅为 assistant
171        belongs_to: BelongsTo,
172        /// 文件访问地址
173        url: String,
174        #[serde(flatten)]
175        extra: HashMap<String, JsonValue>,
176    },
177    /// 消息结束事件,收到此事件则代表流式返回结束。
178    MessageEnd {
179        /// 消息基础信息
180        #[serde(flatten)]
181        base: Option<MessageBase>,
182        /// 消息 ID
183        id: String,
184        /// 任务 ID,用于请求跟踪和下方的停止响应接口
185        task_id: String,
186        /// 元数据
187        metadata: HashMap<String, JsonValue>,
188        #[serde(flatten)]
189        extra: HashMap<String, JsonValue>,
190    },
191    /// 消息内容替换事件  
192    /// 开启内容审查和审查输出内容时,若命中了审查条件,则会通过此事件替换消息内容为预设回复。
193    MessageReplace {
194        /// 消息基础信息
195        #[serde(flatten)]
196        base: Option<MessageBase>,
197        /// 任务 ID,用于请求跟踪和下方的停止响应接口
198        task_id: String,
199        /// 替换内容(直接替换 LLM 所有回复文本)
200        answer: String,
201        #[serde(flatten)]
202        extra: HashMap<String, JsonValue>,
203    },
204    /// workflow 开始执行
205    WorkflowStarted {
206        /// 消息基础信息
207        #[serde(flatten)]
208        base: Option<MessageBase>,
209        /// 任务 ID,用于请求跟踪和下方的停止响应接口
210        task_id: String,
211        /// workflow 执行 ID
212        workflow_run_id: String,
213        /// workflow 详细内容
214        data: WorkflowStartedData,
215        #[serde(flatten)]
216        extra: HashMap<String, JsonValue>,
217    },
218
219    /// node 执行开始
220    NodeStarted {
221        /// 消息基础信息
222        #[serde(flatten)]
223        base: Option<MessageBase>,
224        /// 任务 ID,用于请求跟踪和下方的停止响应接口
225        task_id: String,
226        /// workflow 执行 ID
227        workflow_run_id: String,
228        /// node 详细内容
229        data: NodeStartedData,
230        #[serde(flatten)]
231        extra: HashMap<String, JsonValue>,
232    },
233    /// node 执行结束, 成功失败同一事件中不同状态
234    NodeFinished {
235        /// 消息基础信息
236        #[serde(flatten)]
237        base: Option<MessageBase>,
238        /// 任务 ID,用于请求跟踪和下方的停止响应接口
239        task_id: String,
240        /// workflow 执行 ID
241        workflow_run_id: String,
242        /// node 执行结束详细内容
243        data: NodeFinishedData,
244        #[serde(flatten)]
245        extra: HashMap<String, JsonValue>,
246    },
247    /// workflow 执行结束,成功失败同一事件中不同状态
248    WorkflowFinished {
249        /// 消息基础信息
250        #[serde(flatten)]
251        base: Option<MessageBase>,
252        /// 任务 ID,用于请求跟踪和下方的停止响应接口
253        task_id: String,
254        /// workflow 执行 ID
255        workflow_run_id: String,
256        /// workflow 详细内容
257        data: WorkflowFinishedData,
258        #[serde(flatten)]
259        extra: HashMap<String, JsonValue>,
260    },
261    /// Agent模式下返回文本块事件,即:在Agent模式下,文章的文本以分块的方式输出(仅Agent模式下使用)
262    AgentMessage {
263        /// 消息基础信息
264        #[serde(flatten)]
265        base: Option<MessageBase>,
266        /// 消息 ID
267        id: String,
268        /// 任务 ID,用于请求跟踪和下方的停止响应接口
269        task_id: String,
270        /// LLM 返回文本块内容
271        answer: String,
272        #[serde(flatten)]
273        extra: HashMap<String, JsonValue>,
274    },
275    /// Agent模式下有关Agent思考步骤的相关内容,涉及到工具调用(仅Agent模式下使用)
276    AgentThought {
277        /// 消息基础信息
278        #[serde(flatten)]
279        base: Option<MessageBase>,
280        /// 消息 ID
281        id: String,
282        /// 任务 ID,用于请求跟踪和下方的停止响应接口
283        task_id: String,
284        /// agent_thought在消息中的位置,如第一轮迭代position为1
285        position: u32,
286        /// agent的思考内容
287        thought: String,
288        /// 工具调用的返回结果
289        observation: String,
290        /// 使用的工具列表,以 ; 分割多个工具
291        tool: String,
292        /// 工具的标签
293        tool_labels: JsonValue,
294        /// 工具的输入,JSON格式的字符串
295        tool_input: String,
296        /// 当前 agent_thought 关联的文件ID
297        message_files: Vec<String>,
298    },
299    /// 流式输出过程中出现的异常会以 stream event 形式输出,收到异常事件后即结束。
300    Error {
301        /// 消息基础信息
302        #[serde(flatten)]
303        base: Option<MessageBase>,
304        /// HTTP 状态码
305        status: u32,
306        /// 错误码
307        code: String,
308        /// 错误消息
309        message: String,
310        #[serde(flatten)]
311        extra: HashMap<String, JsonValue>,
312    },
313    // 每 10s 一次的 ping 事件,保持连接存活。
314    Ping,
315}
316
317/// workflow 详细内容
318#[derive(Debug, Clone, Serialize, Deserialize)]
319pub struct WorkflowStartedData {
320    /// workflow 执行 ID
321    pub id: String,
322    /// 关联 Workflow ID
323    pub workflow_id: String,
324    /// 自增序号,App 内自增,从 1 开始
325    pub sequence_number: u32,
326    /// 输入数据
327    pub inputs: JsonValue,
328    /// 开始时间
329    pub created_at: u64,
330}
331
332/// workflow 执行结束详细内容
333#[derive(Debug, Clone, Serialize, Deserialize)]
334pub struct WorkflowFinishedData {
335    /// workflow 执行 ID
336    pub id: String,
337    /// 关联 Workflow ID
338    pub workflow_id: String,
339    /// 执行状态 running / succeeded / failed / stopped
340    pub status: FinishedStatus,
341    /// 输出内容
342    pub outputs: Option<JsonValue>,
343    /// 错误原因
344    pub error: Option<String>,
345    /// 耗时(s)
346    pub elapsed_time: Option<f64>,
347    /// 总使用 tokens
348    pub total_tokens: Option<u32>,
349    /// 总步数(冗余),默认 0
350    pub total_steps: u32,
351    /// 开始时间
352    pub created_at: u64,
353    /// 结束时间
354    pub finished_at: u64,
355    #[serde(flatten)]
356    pub extra: HashMap<String, JsonValue>,
357}
358
359/// node 详细内容
360#[derive(Debug, Clone, Serialize, Deserialize)]
361pub struct NodeStartedData {
362    /// workflow 执行 ID
363    pub id: String,
364    /// 节点 ID
365    pub node_id: String,
366    /// 节点类型
367    pub node_type: String,
368    /// 节点名称
369    pub title: String,
370    /// 执行序号,用于展示 Tracing Node 顺序
371    pub index: u32,
372    /// 前置节点 ID,用于画布展示执行路径
373    pub predecessor_node_id: Option<String>,
374    /// 节点中所有使用到的前置节点变量内容
375    pub inputs: Option<JsonValue>,
376    /// 开始时间
377    pub created_at: u64,
378}
379
380/// node 执行结束详细内容
381#[derive(Debug, Clone, Serialize, Deserialize)]
382pub struct NodeFinishedData {
383    /// node 执行 ID
384    pub id: String,
385    /// 节点 ID
386    pub node_id: String,
387    /// 执行序号,用于展示 Tracing Node 顺序
388    pub index: u32,
389    /// 前置节点 ID,用于画布展示执行路径
390    pub predecessor_node_id: Option<String>,
391    /// 节点中所有使用到的前置节点变量内容
392    pub inputs: Option<JsonValue>,
393    /// 节点过程数据
394    pub process_data: Option<JsonValue>,
395    /// 输出内容
396    pub outputs: Option<JsonValue>,
397    /// 执行状态 running / succeeded / failed / stopped
398    pub status: FinishedStatus,
399    /// 错误原因
400    pub error: Option<String>,
401    /// 耗时(s)
402    pub elapsed_time: Option<f64>,
403    /// 执行节点元数据
404    pub execution_metadata: Option<ExecutionMetadata>,
405    /// 开始时间
406    pub created_at: u64,
407    #[serde(flatten)]
408    pub extra: HashMap<String, JsonValue>,
409}
410
411/// 执行结束状态
412#[derive(Debug, Clone, Serialize, Deserialize)]
413#[serde(rename_all = "snake_case")]
414pub enum FinishedStatus {
415    Running,
416    Succeeded,
417    Failed,
418    Stopped,
419}
420
421/// 执行节点元数据
422#[derive(Debug, Clone, Serialize, Deserialize)]
423pub struct ExecutionMetadata {
424    /// 总使用 tokens
425    pub total_tokens: Option<u32>,
426    /// 总费用
427    pub total_price: Option<String>,
428    /// 货币,如 USD / RMB
429    pub currency: Option<String>,
430}
431
432/// 应用类型
433#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
434#[serde(rename_all = "kebab-case")]
435pub enum AppMode {
436    Completion,
437    Workflow,
438    Chat,
439    AdvancedChat,
440    AgentChat,
441    Channel,
442}
443
444/// 获取下一轮建议问题列表的响应
445#[derive(Debug, Clone, Deserialize, Serialize)]
446pub struct MessagesSuggestedResponse {
447    pub result: String,
448    /// 建议问题列表
449    pub data: Vec<String>,
450}
451
452/// 获取会话历史消息的响应
453#[derive(Debug, Clone, Deserialize, Serialize)]
454pub struct MessagesResponse {
455    /// 返回条数,若传入超过系统限制,返回系统限制数量
456    pub limit: u32,
457    /// 是否存在下一页
458    pub has_more: bool,
459    /// 消息列表
460    pub data: Vec<MessageData>,
461}
462
463/// 历史消息数据
464#[derive(Debug, Clone, Deserialize, Serialize)]
465pub struct MessageData {
466    /// 消息 ID
467    pub id: String,
468    /// 会话 ID
469    pub conversation_id: String,
470    /// 用户输入参数。
471    pub inputs: JsonValue,
472    /// 用户输入 / 提问内容。
473    pub query: String,
474    /// 回答消息内容
475    pub answer: String,
476    /// 消息文件
477    pub message_files: Vec<MessageFile>,
478    /// 反馈信息
479    pub feedback: Option<MessageFeedback>,
480    /// 引用和归属分段列表
481    pub retriever_resources: Vec<JsonValue>,
482    /// 创建时间
483    pub created_at: u64,
484}
485
486/// 历史消息数据中的文件信息
487#[derive(Debug, Clone, Serialize, Deserialize)]
488pub struct MessageFile {
489    /// ID
490    pub id: String,
491    /// 文件类型,image 图片
492    #[serde(rename = "type")]
493    pub type_: FileType,
494    /// 预览图片地址
495    pub url: String,
496    /// 文件归属方,user 或 assistant
497    pub belongs_to: BelongsTo,
498}
499
500/// 文件归属方
501#[derive(Debug, Clone, Serialize, Deserialize)]
502#[serde(rename_all = "snake_case")]
503pub enum BelongsTo {
504    User,
505    Assistant,
506}
507
508/// 历史消息数据中的反馈信息
509#[derive(Debug, Clone, Deserialize, Serialize)]
510pub struct MessageFeedback {
511    /// 点赞 like / 点踩 dislike
512    pub rating: Feedback,
513}
514
515/// 获取会话列表的响应
516#[derive(Debug, Clone, Deserialize, Serialize)]
517pub struct ConversationsResponse {
518    /// 是否存在下一页
519    pub has_more: bool,
520    /// 返回条数,若传入超过系统限制,返回系统限制数量
521    pub limit: u32,
522    /// 会话列表
523    pub data: Vec<ConversationData>,
524}
525
526/// 会话数据
527#[derive(Debug, Clone, Deserialize, Serialize)]
528pub struct ConversationData {
529    /// 会话 ID
530    pub id: String,
531    /// 会话名称,默认为会话中用户最开始问题的截取。
532    pub name: String,
533    /// 用户输入参数。
534    pub inputs: HashMap<String, String>,
535    /// 开场白
536    pub introduction: String,
537    /// 创建时间
538    pub created_at: u64,
539}
540
541#[serde_as]
542#[derive(Debug, Clone, Deserialize, Serialize)]
543/// 获取应用配置信息的响应
544pub struct ParametersResponse {
545    /// 开场白
546    pub opening_statement: String,
547    /// 开场推荐问题列表
548    pub suggested_questions: Vec<String>,
549    /// 启用回答后给出推荐问题。
550    pub suggested_questions_after_answer: ParameterSuggestedQuestionsAfterAnswer,
551    /// 语音转文本
552    pub speech_to_text: ParameterSpeechToText,
553    /// 引用和归属
554    pub retriever_resource: ParameterRetrieverResource,
555    /// 标记回复
556    pub annotation_reply: ParameterAnnotationReply,
557    /// 用户输入表单配置
558    pub user_input_form: Vec<ParameterUserInputFormItem>,
559    /// 文件上传配置
560    #[serde_as(as = "EnumMap")]
561    pub file_upload: Vec<ParameterFileUploadItem>,
562    pub system_parameters: SystemParameters,
563}
564
565#[derive(Debug, Clone, Deserialize, Serialize)]
566/// 启用回答后给出推荐问题。
567pub struct ParameterSuggestedQuestionsAfterAnswer {
568    /// 是否开启
569    pub enabled: bool,
570}
571
572#[derive(Debug, Clone, Deserialize, Serialize)]
573/// 语音转文本
574pub struct ParameterSpeechToText {
575    /// 是否开启
576    pub enabled: bool,
577}
578
579#[derive(Debug, Clone, Deserialize, Serialize)]
580/// 引用和归属
581pub struct ParameterRetrieverResource {
582    /// 是否开启
583    pub enabled: bool,
584}
585
586#[derive(Debug, Clone, Deserialize, Serialize)]
587/// 标记回复
588pub struct ParameterAnnotationReply {
589    /// 是否开启
590    pub enabled: bool,
591}
592
593#[derive(Debug, Clone, Deserialize, Serialize)]
594#[serde(rename_all = "snake_case")]
595/// 用户输入表单配置
596pub enum ParameterUserInputFormItem {
597    /// 文本输入控件
598    #[serde(rename = "text-input")]
599    TextInput {
600        /// 控件展示标签名
601        label: String,
602        /// 控件 ID
603        variable: String,
604        /// 是否必填
605        required: bool,
606    },
607    /// 段落文本输入控件
608    Paragraph {
609        /// 控件展示标签名
610        label: String,
611        /// 控件 ID
612        variable: String,
613        /// 是否必填
614        required: bool,
615    },
616    /// 数字输入空间
617    Number {
618        /// 控件展示标签名
619        label: String,
620        /// 控件 ID
621        variable: String,
622        /// 是否必填
623        required: bool,
624    },
625    Select {
626        /// 控件展示标签名
627        label: String,
628        /// 控件 ID
629        variable: String,
630        /// 是否必填
631        required: bool,
632        /// 选项值
633        options: Vec<String>,
634    },
635}
636
637#[derive(Debug, Clone, Deserialize, Serialize)]
638#[serde(rename_all = "snake_case")]
639/// 文件上传配置
640pub enum ParameterFileUploadItem {
641    /// 当前仅支持图片类型
642    Image {
643        /// 是否开启
644        enabled: bool,
645        /// 图片数量限制,默认 3
646        number_limits: u32,
647        /// 传递方式
648        transfer_methods: Vec<TransferMethod>,
649    },
650}
651
652/// 文件传递方式
653#[derive(Debug, Clone, Deserialize, Serialize)]
654#[serde(rename_all = "snake_case")]
655pub enum TransferMethod {
656    RemoteUrl,
657    LocalFile,
658}
659
660/// 系统参数
661#[derive(Debug, Clone, Deserialize, Serialize)]
662pub struct SystemParameters {
663    /// 图片文件上传大小限制(MB)
664    pub image_file_size_limit: String,
665}
666
667#[derive(Debug, Clone, Deserialize, Serialize)]
668/// 获取应用Meta信息的响应
669pub struct MetaResponse {
670    pub tool_icons: HashMap<String, ToolIcon>,
671}
672
673/// 工具图标
674#[derive(Debug, Clone, Deserialize, Serialize)]
675#[serde(untagged)]
676pub enum ToolIcon {
677    Url(String),
678    Emoji { background: String, content: String },
679}
680
681/// 语音转文字响应
682#[derive(Debug, Clone, Deserialize, Serialize)]
683pub struct AudioToTextResponse {
684    /// 输出文字
685    pub text: String,
686}
687
688/// 上传文件响应
689#[derive(Debug, Clone, Deserialize, Serialize)]
690pub struct FilesUploadResponse {
691    /// ID
692    pub id: String,
693    /// 文件名
694    pub name: String,
695    /// 文件大小(byte)
696    pub size: u64,
697    /// 文件后缀
698    pub extension: String,
699    /// 文件 mime-type
700    pub mime_type: String,
701    /// 上传人 ID
702    pub created_by: String,
703    /// 上传时间
704    pub created_at: u64,
705}
706
707/// 执行 workflow 响应
708#[derive(Debug, Clone, Deserialize, Serialize)]
709pub struct WorkflowsRunResponse {
710    /// workflow 执行 ID
711    pub workflow_run_id: String,
712    /// 任务 ID,用于请求跟踪和下方的停止响应接口
713    pub task_id: String,
714    /// 详细内容
715    pub data: WorkflowFinishedData,
716}
717
718/// 文本生成的响应
719#[derive(Debug, Clone, Serialize, Deserialize)]
720pub struct CompletionMessagesResponse {
721    /// 消息基础信息
722    #[serde(flatten)]
723    pub base: MessageBase,
724    /// 任务 ID,用于请求跟踪和下方的停止响应接口
725    pub task_id: String,
726    /// 事件
727    pub event: String,
728    /// App 模式
729    pub mode: AppMode,
730    /// 完整回复内容
731    pub answer: String,
732    /// 元数据
733    pub metadata: HashMap<String, JsonValue>,
734}
735
736pin_project! {
737    /// A Stream of SSE message events.
738    pub struct SseMessageEventStream<S>
739    {
740        #[pin]
741        stream: EventStream<S>,
742        terminated: bool,
743    }
744}
745
746impl<S> SseMessageEventStream<S> {
747    /// Initialize the SSE message events stream with a Stream
748    pub fn new(stream: EventStream<S>) -> Self {
749        Self {
750            stream,
751            terminated: false,
752        }
753    }
754}
755
756impl<S, B, E> Stream for SseMessageEventStream<S>
757where
758    S: Stream<Item = Result<B, E>>,
759    B: AsRef<[u8]>,
760    E: Display,
761{
762    type Item = AnyResult<SseMessageEvent>;
763
764    fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
765        let mut this = self.project();
766        if *this.terminated {
767            return Poll::Ready(None);
768        }
769
770        loop {
771            match this.stream.as_mut().poll_next(cx) {
772                Poll::Ready(Some(Ok(event))) => match event.event.as_str() {
773                    "message" => match serde_json::from_str::<SseMessageEvent>(&event.data) {
774                        Ok(msg_event) => return Poll::Ready(Some(Ok(msg_event))),
775                        Err(e) => return Poll::Ready(Some(Err(e.into()))),
776                    },
777                    _ => {}
778                },
779                Poll::Ready(Some(Err(e))) => return Poll::Ready(Some(Err(anyhow!(e.to_string())))),
780                Poll::Ready(None) => {
781                    *this.terminated = true;
782                    return Poll::Ready(None);
783                }
784                Poll::Pending => return Poll::Pending,
785            }
786        }
787    }
788}
789
790/// 解析响应
791pub(crate) fn parse_response<T>(text: &str) -> AnyResult<T>
792where
793    T: serde::de::DeserializeOwned,
794{
795    if let Ok(data) = serde_json::from_str::<T>(text) {
796        Ok(data)
797    } else {
798        parse_error_response(text)
799    }
800}
801
802/// 解析错误响应
803pub(crate) fn parse_error_response<T>(text: &str) -> AnyResult<T> {
804    if let Ok(err) = serde_json::from_str::<ErrorResponse>(text) {
805        bail!(err)
806    } else {
807        bail!(ErrorResponse::unknown(text))
808    }
809}