Skip to content

Commit caf9f02

Browse files
authored
feat: add error notification (#386)
* feat: add error notification * feat: add error collection * chore: error display * chore: error string * docs: update notes * docs: update notes * build: build error * chore: errors 5 and link length truncation
1 parent f18f94e commit caf9f02

File tree

30 files changed

+326
-261
lines changed

30 files changed

+326
-261
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Information about release notes of Coco Server is provided here.
2323
- feat: networked search data sources support search and keyboard-only operation #367
2424
- feat: add application management to the plugin #374
2525
- feat: add keyboard-only operation to history list #385
26+
- feat: add error notification #386
2627

2728
### Bug fix
2829

src-tauri/src/server/http_client.rs

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,10 @@ impl HttpClient {
3838
let request_builder =
3939
Self::get_request_builder(method, url, headers, query_params, body).await;
4040

41-
42-
let response = request_builder
43-
.send()
44-
.await
45-
.map_err(|e| {
46-
dbg!("Failed to send request: {}", &e);
47-
format!("Failed to send request: {}", e)
48-
})?;
41+
let response = request_builder.send().await.map_err(|e| {
42+
dbg!("Failed to send request: {}", &e);
43+
format!("Failed to send request: {}", e)
44+
})?;
4945
Ok(response)
5046
}
5147

@@ -58,14 +54,12 @@ impl HttpClient {
5854
) -> RequestBuilder {
5955
let client = HTTP_CLIENT.lock().await; // Acquire the lock on HTTP_CLIENT
6056

61-
6257
// Build the request
6358
let mut request_builder = client.request(method.clone(), url);
6459

6560
if let Some(h) = headers {
6661
let mut req_headers = reqwest::header::HeaderMap::new();
6762
for (key, value) in h.into_iter() {
68-
6963
match (
7064
HeaderName::from_bytes(key.as_bytes()),
7165
HeaderValue::from_str(value.trim()),
@@ -74,20 +68,22 @@ impl HttpClient {
7468
req_headers.insert(name, val);
7569
}
7670
(Err(e), _) => {
77-
eprintln!("Invalid header name: {:?}", key);
71+
eprintln!("Invalid header name: {:?}, error: {}", key, e);
7872
}
7973
(_, Err(e)) => {
80-
eprintln!("Invalid header value for {}: {:?}", key, value);
74+
eprintln!(
75+
"Invalid header value for {}: {:?}, error: {}",
76+
key, value, e
77+
);
8178
}
8279
}
8380
}
8481
request_builder = request_builder.headers(req_headers);
8582
}
8683

8784
if let Some(query) = query_params {
88-
let query: HashMap<String, String> = query.into_iter()
89-
.map(|(k, v)| (k, v.to_string()))
90-
.collect();
85+
let query: HashMap<String, String> =
86+
query.into_iter().map(|(k, v)| (k, v.to_string())).collect();
9187
request_builder = request_builder.query(&query);
9288
}
9389

@@ -173,7 +169,7 @@ impl HttpClient {
173169
query_params,
174170
body,
175171
)
176-
.await
172+
.await
177173
}
178174

179175
// Convenience method for PUT requests
@@ -193,7 +189,7 @@ impl HttpClient {
193189
query_params,
194190
body,
195191
)
196-
.await
192+
.await
197193
}
198194

199195
// Convenience method for DELETE requests
@@ -212,6 +208,6 @@ impl HttpClient {
212208
query_params,
213209
None,
214210
)
215-
.await
211+
.await
216212
}
217213
}

src-tauri/src/server/servers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ pub async fn refresh_coco_server_info<R: Runtime>(
304304
cache.get(&id).cloned()
305305
};
306306

307-
let mut server = match cached_server {
307+
let server = match cached_server {
308308
Some(server) => server,
309309
None => return Err("Server not found.".into()),
310310
};

src/api/axiosRequest.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import axios from "axios";
22

3+
import { useAppStore } from '@/stores/appStore';
4+
35
import {
46
handleChangeRequestHeader,
57
handleConfigureAuth,
@@ -40,6 +42,26 @@ axios.interceptors.response.use(
4042
}
4143
);
4244

45+
export const handleApiError = (error: any) => {
46+
const addError = useAppStore.getState().addError;
47+
48+
let message = 'Request failed';
49+
50+
if (error.response) {
51+
// Server error response
52+
message = error.response.data?.message || `Error (${error.response.status})`;
53+
} else if (error.request) {
54+
// Request failed to send
55+
message = 'Network connection failed';
56+
} else {
57+
// Other errors
58+
message = error.message;
59+
}
60+
61+
addError(message, 'error');
62+
return error;
63+
};
64+
4365
export const Get = <T>(
4466
url: string,
4567
params: IAnyObj = {},
@@ -63,6 +85,7 @@ export const Get = <T>(
6385
resolve([null, res as FcResponse<T>]);
6486
})
6587
.catch((err) => {
88+
handleApiError(err);
6689
resolve([err, undefined]);
6790
});
6891
});
@@ -88,6 +111,7 @@ export const Post = <T>(
88111
resolve([null, result.data as FcResponse<T>]);
89112
})
90113
.catch((err) => {
114+
handleApiError(err);
91115
resolve([err, undefined]);
92116
});
93117
});

src/commands/servers.ts

Lines changed: 70 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,38 +13,74 @@ import {
1313
DeleteAttachmentPayload,
1414
TranscriptionPayload,
1515
TranscriptionResponse,
16+
MultiSourceQueryResponse,
1617
} from "@/types/commands";
18+
import { useAppStore } from '@/stores/appStore';
19+
20+
async function invokeWithErrorHandler<T>(
21+
command: string,
22+
args?: Record<string, any>
23+
): Promise<T> {
24+
const addError = useAppStore.getState().addError;
25+
try {
26+
const result = await invoke<T>(command, args);
27+
console.log(command, result);
28+
29+
if (result && typeof result === 'object' && 'failed' in result) {
30+
const failedResult = result as any;
31+
if (failedResult.failed?.length > 0) {
32+
failedResult.failed.forEach((error: any) => {
33+
// addError(error.error, 'error');
34+
console.log(error.error);
35+
});
36+
}
37+
}
38+
39+
if (typeof result === 'string') {
40+
const res = JSON.parse(result);
41+
if (typeof res === 'string') {
42+
throw new Error(result);
43+
}
44+
}
45+
46+
return result;
47+
} catch (error: any) {
48+
const errorMessage = error || 'Command execution failed';
49+
addError(errorMessage, 'error');
50+
throw error;
51+
}
52+
}
1753

1854
export function get_server_token(id: string): Promise<ServerTokenResponse> {
19-
return invoke(`get_server_token`, { id });
55+
return invokeWithErrorHandler(`get_server_token`, { id });
2056
}
2157

2258
export function list_coco_servers(): Promise<Server[]> {
23-
return invoke(`list_coco_servers`);
59+
return invokeWithErrorHandler(`list_coco_servers`);
2460
}
2561

2662
export function add_coco_server(endpoint: string): Promise<Server> {
27-
return invoke(`add_coco_server`, { endpoint });
63+
return invokeWithErrorHandler(`add_coco_server`, { endpoint });
2864
}
2965

3066
export function enable_server(id: string): Promise<void> {
31-
return invoke(`enable_server`, { id });
67+
return invokeWithErrorHandler(`enable_server`, { id });
3268
}
3369

3470
export function disable_server(id: string): Promise<void> {
35-
return invoke(`disable_server`, { id });
71+
return invokeWithErrorHandler(`disable_server`, { id });
3672
}
3773

3874
export function remove_coco_server(id: string): Promise<void> {
39-
return invoke(`remove_coco_server`, { id });
75+
return invokeWithErrorHandler(`remove_coco_server`, { id });
4076
}
4177

4278
export function logout_coco_server(id: string): Promise<void> {
43-
return invoke(`logout_coco_server`, { id });
79+
return invokeWithErrorHandler(`logout_coco_server`, { id });
4480
}
4581

4682
export function refresh_coco_server_info(id: string): Promise<Server> {
47-
return invoke(`refresh_coco_server_info`, { id });
83+
return invokeWithErrorHandler(`refresh_coco_server_info`, { id });
4884
}
4985

5086
export function handle_sso_callback({
@@ -56,27 +92,27 @@ export function handle_sso_callback({
5692
requestId: string;
5793
code: string;
5894
}): Promise<void> {
59-
return invoke(`handle_sso_callback`, {
95+
return invokeWithErrorHandler(`handle_sso_callback`, {
6096
serverId,
6197
requestId,
6298
code,
6399
});
64100
}
65101

66102
export function get_connectors_by_server(id: string): Promise<Connector[]> {
67-
return invoke(`get_connectors_by_server`, { id });
103+
return invokeWithErrorHandler(`get_connectors_by_server`, { id });
68104
}
69105

70106
export function get_datasources_by_server(id: string): Promise<DataSource[]> {
71-
return invoke(`get_datasources_by_server`, { id });
107+
return invokeWithErrorHandler(`get_datasources_by_server`, { id });
72108
}
73109

74110
export function connect_to_server(id: string, clientId: string): Promise<void> {
75-
return invoke(`connect_to_server`, { id, clientId });
111+
return invokeWithErrorHandler(`connect_to_server`, { id, clientId });
76112
}
77113

78114
export function disconnect(clientId: string): Promise<void> {
79-
return invoke(`disconnect`, { clientId });
115+
return invokeWithErrorHandler(`disconnect`, { clientId });
80116
}
81117

82118
export function chat_history({
@@ -90,7 +126,7 @@ export function chat_history({
90126
size?: number;
91127
query?: string;
92128
}): Promise<string> {
93-
return invoke(`chat_history`, {
129+
return invokeWithErrorHandler(`chat_history`, {
94130
serverId,
95131
from,
96132
size,
@@ -109,7 +145,7 @@ export function session_chat_history({
109145
from?: number;
110146
size?: number;
111147
}): Promise<string> {
112-
return invoke(`session_chat_history`, {
148+
return invokeWithErrorHandler(`session_chat_history`, {
113149
serverId,
114150
sessionId,
115151
from,
@@ -124,7 +160,7 @@ export function close_session_chat({
124160
serverId: string;
125161
sessionId: string;
126162
}): Promise<string> {
127-
return invoke(`close_session_chat`, {
163+
return invokeWithErrorHandler(`close_session_chat`, {
128164
serverId,
129165
sessionId,
130166
});
@@ -137,7 +173,7 @@ export function open_session_chat({
137173
serverId: string;
138174
sessionId: string;
139175
}): Promise<string> {
140-
return invoke(`open_session_chat`, {
176+
return invokeWithErrorHandler(`open_session_chat`, {
141177
serverId,
142178
sessionId,
143179
});
@@ -150,7 +186,7 @@ export function cancel_session_chat({
150186
serverId: string;
151187
sessionId: string;
152188
}): Promise<string> {
153-
return invoke(`cancel_session_chat`, {
189+
return invokeWithErrorHandler(`cancel_session_chat`, {
154190
serverId,
155191
sessionId,
156192
});
@@ -167,7 +203,7 @@ export function new_chat({
167203
message: string;
168204
queryParams?: Record<string, any>;
169205
}): Promise<GetResponse> {
170-
return invoke(`new_chat`, {
206+
return invokeWithErrorHandler(`new_chat`, {
171207
serverId,
172208
websocketId,
173209
message,
@@ -188,7 +224,7 @@ export function send_message({
188224
message: string;
189225
queryParams?: Record<string, any>;
190226
}): Promise<string> {
191-
return invoke(`send_message`, {
227+
return invokeWithErrorHandler(`send_message`, {
192228
serverId,
193229
websocketId,
194230
sessionId,
@@ -198,7 +234,7 @@ export function send_message({
198234
}
199235

200236
export const delete_session_chat = (serverId: string, sessionId: string) => {
201-
return invoke<boolean>(`delete_session_chat`, { serverId, sessionId });
237+
return invokeWithErrorHandler<boolean>(`delete_session_chat`, { serverId, sessionId });
202238
};
203239

204240
export const update_session_chat = (payload: {
@@ -209,11 +245,11 @@ export const update_session_chat = (payload: {
209245
attachments?: string[];
210246
};
211247
}): Promise<boolean> => {
212-
return invoke<boolean>("update_session_chat", payload);
248+
return invokeWithErrorHandler<boolean>("update_session_chat", payload);
213249
};
214250

215251
export const upload_attachment = async (payload: UploadAttachmentPayload) => {
216-
const response = await invoke<UploadAttachmentResponse>("upload_attachment", {
252+
const response = await invokeWithErrorHandler<UploadAttachmentResponse>("upload_attachment", {
217253
...payload,
218254
});
219255

@@ -223,13 +259,21 @@ export const upload_attachment = async (payload: UploadAttachmentPayload) => {
223259
};
224260

225261
export const get_attachment = (payload: GetAttachmentPayload) => {
226-
return invoke<GetAttachmentResponse>("get_attachment", { ...payload });
262+
return invokeWithErrorHandler<GetAttachmentResponse>("get_attachment", { ...payload });
227263
};
228264

229265
export const delete_attachment = (payload: DeleteAttachmentPayload) => {
230-
return invoke<boolean>("delete_attachment", { ...payload });
266+
return invokeWithErrorHandler<boolean>("delete_attachment", { ...payload });
231267
};
232268

233269
export const transcription = (payload: TranscriptionPayload) => {
234-
return invoke<TranscriptionResponse>("transcription", { ...payload });
270+
return invokeWithErrorHandler<TranscriptionResponse>("transcription", { ...payload });
271+
};
272+
273+
export const query_coco_fusion = (payload: {
274+
from: number;
275+
size: number;
276+
query_strings: Record<string, string>;
277+
}) => {
278+
return invokeWithErrorHandler<MultiSourceQueryResponse>("query_coco_fusion", { ...payload });
235279
};

0 commit comments

Comments
 (0)