Skip to main content

zai_rs/knowledge/
update.rs

1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4use validator::Validate;
5
6use super::create::{BackgroundColor, EmbeddingId, KnowledgeIcon};
7use crate::client::ZaiClient;
8
9/// Update body for editing a knowledge base
10#[derive(Debug, Clone, Default, Serialize, Deserialize, Validate)]
11pub struct UpdateKnowledgeBody {
12    /// Embedding model id (3 or 11)
13    #[serde(skip_serializing_if = "Option::is_none")]
14    pub embedding_id: Option<EmbeddingId>,
15    /// Knowledge base name
16    #[serde(skip_serializing_if = "Option::is_none")]
17    #[validate(length(min = 1))]
18    pub name: Option<String>,
19    /// Knowledge base description
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub description: Option<String>,
22    /// Background color
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub background: Option<BackgroundColor>,
25    /// Icon name
26    #[serde(skip_serializing_if = "Option::is_none")]
27    pub icon: Option<KnowledgeIcon>,
28    /// Callback URL when rebuilding is required
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub callback_url: Option<String>,
31    /// Callback headers as key-value
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub callback_header: Option<HashMap<String, String>>,
34}
35
36impl UpdateKnowledgeBody {
37    /// Returns true if no fields are set
38    fn is_empty(&self) -> bool {
39        self.embedding_id.is_none()
40            && self.name.is_none()
41            && self.description.is_none()
42            && self.background.is_none()
43            && self.icon.is_none()
44            && self.callback_url.is_none()
45            && self.callback_header.is_none()
46    }
47}
48
49/// Knowledge update request (PUT /llm-application/open/knowledge/{id})
50///
51/// Credentials and transport live on the [`ZaiClient`], passed to
52/// [`send_via`](Self::send_via).
53pub struct KnowledgeUpdateRequest {
54    id: String,
55    body: UpdateKnowledgeBody,
56}
57
58impl KnowledgeUpdateRequest {
59    /// Build update request targeting a specific id with empty body.
60    pub fn new(id: impl Into<String>) -> Self {
61        Self {
62            id: id.into(),
63            body: UpdateKnowledgeBody::default(),
64        }
65    }
66
67    /// Setters to update individual fields
68    /// Set the embedding model id.
69    pub fn with_embedding_id(mut self, id: EmbeddingId) -> Self {
70        self.body.embedding_id = Some(id);
71        self
72    }
73    /// Set the knowledge-base name.
74    pub fn with_name(mut self, name: impl Into<String>) -> Self {
75        self.body.name = Some(name.into());
76        self
77    }
78    /// Set the description.
79    pub fn with_description(mut self, desc: impl Into<String>) -> Self {
80        self.body.description = Some(desc.into());
81        self
82    }
83    /// Set the background color.
84    pub fn with_background(mut self, bg: BackgroundColor) -> Self {
85        self.body.background = Some(bg);
86        self
87    }
88    /// Set the icon.
89    pub fn with_icon(mut self, icon: KnowledgeIcon) -> Self {
90        self.body.icon = Some(icon);
91        self
92    }
93    /// Set the callback URL (notified when rebuilding completes).
94    pub fn with_callback_url(mut self, url: impl Into<String>) -> Self {
95        self.body.callback_url = Some(url.into());
96        self
97    }
98    /// Set the callback headers.
99    pub fn with_callback_header(mut self, headers: HashMap<String, String>) -> Self {
100        self.body.callback_header = Some(headers);
101        self
102    }
103
104    /// Send the update request via a [`ZaiClient`] and parse the typed response.
105    pub async fn send_via(&self, client: &ZaiClient) -> crate::ZaiResult<KnowledgeUpdateResponse> {
106        if self.body.is_empty() {
107            return Err(crate::client::error::ZaiError::ApiError {
108                code: crate::client::error::codes::SDK_VALIDATION,
109                message: "update body is empty; set at least one field".to_string(),
110            });
111        }
112        self.body.validate()?;
113        let route = crate::client::routes::KNOWLEDGE_UPDATE;
114        let url = client.endpoints().resolve_route(route, &[&self.id])?;
115        client
116            .send_json::<_, KnowledgeUpdateResponse>(route.method(), url, &self.body)
117            .await
118    }
119}
120
121/// Update response envelope without data
122#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
123pub struct KnowledgeUpdateResponse {
124    /// Business status code.
125    #[serde(skip_serializing_if = "Option::is_none")]
126    pub code: Option<i64>,
127    /// Human-readable message.
128    #[serde(skip_serializing_if = "Option::is_none")]
129    pub message: Option<String>,
130    /// Server timestamp.
131    #[serde(skip_serializing_if = "Option::is_none")]
132    pub timestamp: Option<u64>,
133}