Skip to content

Commit 855fb2a

Browse files
authored
feat: support sending files in chat messages (#764)
* feat: support sending files in chat messages * update * update * update * update * update * update * update * update * update * update * update * update * update * update * update * update * update * update * update * update * update * update * update * update * update * update * update * update * update * docs: update changelog
1 parent d2735ec commit 855fb2a

File tree

31 files changed

+605
-328
lines changed

31 files changed

+605
-328
lines changed

docs/content.en/docs/release-notes/_index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Information about release notes of Coco App is provided here.
1515

1616
- feat: enhance ui for skipped version #834
1717
- feat: support installing local extensions #749
18+
- feat: support sending files in chat messages #764
1819

1920
### 🐛 Bug fix
2021

src-tauri/src/assistant/mod.rs

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -115,21 +115,34 @@ pub async fn cancel_session_chat(
115115
pub async fn chat_create(
116116
app_handle: AppHandle,
117117
server_id: String,
118-
message: String,
118+
message: Option<String>,
119+
attachments: Option<Vec<String>>,
119120
query_params: Option<HashMap<String, Value>>,
120121
client_id: String,
121122
) -> Result<(), String> {
122-
let body = if !message.is_empty() {
123-
let message = ChatRequestMessage {
124-
message: Some(message),
123+
println!("chat_create message: {:?}", message);
124+
println!("chat_create attachments: {:?}", attachments);
125+
126+
let message_empty = message.as_ref().map_or(true, |m| m.is_empty());
127+
let attachments_empty = attachments.as_ref().map_or(true, |a| a.is_empty());
128+
129+
if message_empty && attachments_empty {
130+
return Err("Message and attachments are empty".to_string());
131+
}
132+
133+
let body = {
134+
let request_message: ChatRequestMessage = ChatRequestMessage {
135+
message,
136+
attachments,
125137
};
138+
139+
println!("chat_create body: {:?}", request_message);
140+
126141
Some(
127-
serde_json::to_string(&message)
142+
serde_json::to_string(&request_message)
128143
.map_err(|e| format!("Failed to serialize message: {}", e))?
129144
.into(),
130145
)
131-
} else {
132-
None
133146
};
134147

135148
let response = HttpClient::advanced_post(
@@ -165,8 +178,6 @@ pub async fn chat_create(
165178
if let Err(err) = app_handle.emit(&client_id, line) {
166179
log::error!("Emit failed: {:?}", err);
167180

168-
print!("Error sending message: {:?}", err);
169-
170181
let _ = app_handle.emit("chat-create-error", format!("Emit failed: {:?}", err));
171182
}
172183
}
@@ -179,21 +190,34 @@ pub async fn chat_chat(
179190
app_handle: AppHandle,
180191
server_id: String,
181192
session_id: String,
182-
message: String,
193+
message: Option<String>,
194+
attachments: Option<Vec<String>>,
183195
query_params: Option<HashMap<String, Value>>, //search,deep_thinking
184196
client_id: String,
185197
) -> Result<(), String> {
186-
let body = if !message.is_empty() {
187-
let message = ChatRequestMessage {
188-
message: Some(message),
198+
println!("chat_chat message: {:?}", message);
199+
println!("chat_chat attachments: {:?}", attachments);
200+
201+
let message_empty = message.as_ref().map_or(true, |m| m.is_empty());
202+
let attachments_empty = attachments.as_ref().map_or(true, |a| a.is_empty());
203+
204+
if message_empty && attachments_empty {
205+
return Err("Message and attachments are empty".to_string());
206+
}
207+
208+
let body = {
209+
let request_message = ChatRequestMessage {
210+
message,
211+
attachments,
189212
};
213+
214+
println!("chat_chat body: {:?}", request_message);
215+
190216
Some(
191-
serde_json::to_string(&message)
217+
serde_json::to_string(&request_message)
192218
.map_err(|e| format!("Failed to serialize message: {}", e))?
193219
.into(),
194220
)
195-
} else {
196-
None
197221
};
198222

199223
let path = format!("/chat/{}/_chat", session_id);
@@ -235,6 +259,9 @@ pub async fn chat_chat(
235259

236260
if let Err(err) = app_handle.emit(&client_id, line) {
237261
log::error!("Emit failed: {:?}", err);
262+
263+
print!("Error sending message: {:?}", err);
264+
238265
let _ = app_handle.emit("chat-create-error", format!("Emit failed: {:?}", err));
239266
}
240267
}

src-tauri/src/common/assistant.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ use serde_json::Value;
33

44
#[derive(Debug, Clone, Serialize, Deserialize)]
55
pub struct ChatRequestMessage {
6+
#[serde(skip_serializing_if = "Option::is_none")]
67
pub message: Option<String>,
8+
#[serde(skip_serializing_if = "Option::is_none")]
9+
pub attachments: Option<Vec<String>>,
710
}
811

912
#[allow(dead_code)]

src-tauri/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ pub fn run() {
145145
// server::get_coco_server_connectors,
146146
get_app_search_source,
147147
server::attachment::upload_attachment,
148-
server::attachment::get_attachment,
148+
server::attachment::get_attachment_by_ids,
149149
server::attachment::delete_attachment,
150150
server::transcription::transcription,
151151
server::system_settings::get_system_settings,

src-tauri/src/server/attachment.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,19 @@ pub async fn upload_attachment(
7272
}
7373

7474
#[command]
75-
pub async fn get_attachment(server_id: String, session_id: String) -> Result<Value, String> {
76-
let mut query_params = Vec::new();
77-
query_params.push(format!("session={}", session_id));
75+
pub async fn get_attachment_by_ids(
76+
server_id: String,
77+
attachments: Vec<String>,
78+
) -> Result<Value, String> {
79+
println!("get_attachment_by_ids server_id: {}", server_id);
80+
println!("get_attachment_by_ids attachments: {:?}", attachments);
81+
82+
let request_body = serde_json::json!({
83+
"attachments": attachments
84+
});
85+
let body = reqwest::Body::from(serde_json::to_string(&request_body).unwrap());
7886

79-
let response = HttpClient::get(&server_id, "/attachment/_search", Some(query_params))
87+
let response = HttpClient::post(&server_id, "/attachment/_search", None, Some(body))
8088
.await
8189
.map_err(|e| format!("Request error: {}", e))?;
8290

src/commands/servers.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
GetResponse,
99
UploadAttachmentPayload,
1010
UploadAttachmentResponse,
11-
GetAttachmentPayload,
11+
GetAttachmentByIdsPayload,
1212
GetAttachmentResponse,
1313
DeleteAttachmentPayload,
1414
TranscriptionPayload,
@@ -255,17 +255,20 @@ export function cancel_session_chat({
255255
export function chat_create({
256256
serverId,
257257
message,
258+
attachments,
258259
queryParams,
259260
clientId,
260261
}: {
261262
serverId: string;
262263
message: string;
264+
attachments: string[];
263265
queryParams?: Record<string, any>;
264266
clientId: string;
265267
}): Promise<GetResponse> {
266268
return invokeWithErrorHandler(`chat_create`, {
267269
serverId,
268270
message,
271+
attachments,
269272
queryParams,
270273
clientId,
271274
});
@@ -275,19 +278,22 @@ export function chat_chat({
275278
serverId,
276279
sessionId,
277280
message,
281+
attachments,
278282
queryParams,
279283
clientId,
280284
}: {
281285
serverId: string;
282286
sessionId: string;
283287
message: string;
288+
attachments: string[];
284289
queryParams?: Record<string, any>;
285290
clientId: string;
286291
}): Promise<string> {
287292
return invokeWithErrorHandler(`chat_chat`, {
288293
serverId,
289294
sessionId,
290295
message,
296+
attachments,
291297
queryParams,
292298
clientId,
293299
});
@@ -342,10 +348,13 @@ export const upload_attachment = async (payload: UploadAttachmentPayload) => {
342348
}
343349
};
344350

345-
export const get_attachment = (payload: GetAttachmentPayload) => {
346-
return invokeWithErrorHandler<GetAttachmentResponse>("get_attachment", {
347-
...payload,
348-
});
351+
export const get_attachment_by_ids = (payload: GetAttachmentByIdsPayload) => {
352+
return invokeWithErrorHandler<GetAttachmentResponse>(
353+
"get_attachment_by_ids",
354+
{
355+
...payload,
356+
}
357+
);
349358
};
350359

351360
export const delete_attachment = (payload: DeleteAttachmentPayload) => {

0 commit comments

Comments
 (0)