diff --git a/app/src/renderer/Resource/components/TextResource.svelte b/app/src/renderer/Resource/components/TextResource.svelte
index ccf1a503e..443e9a433 100644
--- a/app/src/renderer/Resource/components/TextResource.svelte
+++ b/app/src/renderer/Resource/components/TextResource.svelte
@@ -89,7 +89,6 @@
} from '@deta/services/constants'
import type { MentionAction } from '@deta/editor/src/lib/extensions/Mention'
import { type AITool, ModelTiers, Provider } from '@deta/types/src/ai.types'
- import { Toast, useToasts } from '@deta/ui'
import { useConfig } from '@deta/services'
import { createWikipediaAPI, WebParser } from '@deta/web-parser'
import EmbeddedResource from './EmbeddedResource.svelte'
@@ -137,7 +136,6 @@
const log = useLogScope('TextCard')
const resourceManager = useResourceManager()
const ai = useAI()
- const toasts = useToasts()
const config = useConfig()
const wikipediaAPI = createWikipediaAPI()
@@ -717,14 +715,9 @@
}
const handleEditorFilePaste = async (e: CustomEvent<{ files: File[]; htmlData?: string }>) => {
- let toast: Toast | null = null
try {
const { files, htmlData } = e.detail
- if (toasts) {
- toast = toasts.loading('Importing pasted items…')
- }
-
let parsed: any[] = []
// If we have direct files, use them
@@ -831,9 +824,6 @@
}
}
- if (toast) {
- toast.success('Items imported!')
- }
return
}
}
@@ -873,20 +863,12 @@
await processDropResource(position, resource, true, { x: 0, y: 0 })
}
-
- if (toast) {
- toast.success('Items imported!')
- }
} catch (err) {
- if (toast) {
- toast.error('Failed to import pasted items!')
- }
log.error(err)
}
}
const handlePaste = async (e: ClipboardEvent) => {
- let toast: Toast | null = null
e.preventDefault()
try {
var parsed = await processPaste(e)
@@ -895,8 +877,6 @@
parsed = parsed.filter((e) => e.type === 'file')
if (parsed.length <= 0) return
- toast = toasts.loading('Importing pasted items…')
-
const newResources = await createResourcesFromMediaItems(resourceManager, parsed, '', [
ResourceTag.paste(),
ResourceTag.silent()
@@ -911,17 +891,12 @@
await processDropResource(position, resource, true, { x: 0, y: 0 })
}
-
- toast.success('Items imported!')
} catch (e) {
- toast?.error('Failed to import pasted items!')
-
log.error(e)
}
}
const handleDrop = async (drag) => {
- let toast: Toast | null = null
try {
const editor = editorElem.getEditor()
const position = dragPosition ?? editor.view.state.selection.from
@@ -932,8 +907,6 @@
if (drag.isNative) {
if (drag.dataTransfer?.getData('text/html')?.includes('
{
@@ -1375,16 +1338,7 @@
log.debug('autocomplete response', response)
if (response.error) {
log.error('Error generating AI output', response.error)
- let errorMsg = response.error.message
- if (response.error.type === PageChatMessageSentEventError.TooManyRequests) {
- errorMsg = 'Too many requests, please try again later'
- } else if (response.error.type === PageChatMessageSentEventError.BadRequest) {
- errorMsg =
- 'Sorry your query did not pass our content policy, please try again with a different query.'
- } else if (response.error.type === PageChatMessageSentEventError.RAGEmptyContext) {
- errorMsg =
- 'No relevant context found. Please add more resources or try a different query.'
- }
+ let errorMsg = response.error.message || 'An unknown error occurred'
aiGeneration.updateStatus('failed')
chatInputComp?.showStatus({
type: 'error',
@@ -1472,7 +1426,6 @@
if (type === MentionItemType.BUILT_IN || type === MentionItemType.MODEL) {
log.debug('Built-in or model mention clicked, cannot be opened')
- toasts.info('This is a built-in mention and cannot be opened')
return
}
@@ -1501,54 +1454,8 @@
log.debug('Cannot open mention', item, action)
return
}
-
- if (action === 'overlay') {
- if (id === INBOX_MENTION.id) {
- openSpaceInStuff('inbox')
- } else if (id === EVERYTHING_MENTION.id) {
- openSpaceInStuff('all')
- } else if (type === MentionItemType.RESOURCE) {
- // oasis.openResourceDetailsSidebar(id, { select: true, selectedSpace: 'auto' })
- } else if (type === MentionItemType.CONTEXT) {
- openSpaceInStuff(id)
- } else {
- toasts.info('This is a built-in mention and cannot be opened')
- }
- } else {
- if (type === MentionItemType.BUILT_IN || type === MentionItemType.MODEL) {
- toasts.info('This is a built-in mention and cannot be opened')
- return
- }
-
- // if (type === MentionItemType.RESOURCE) {
- // tabsManager.openResourcFromContextAsPageTab(id, {
- // active: action !== 'new-background-tab'
- // })
- // return
- // }
-
- // if (action === 'open') {
- // tabsManager.changeScope(
- // id === INBOX_MENTION.id || id === EVERYTHING_MENTION.id ? null : id,
- // ChangeContextEventTrigger.Note
- // )
-
- // return
- // }
-
- // const space = await oasis.getSpace(id)
- // if (!space) {
- // log.error('Space not found', id)
- // return
- // }
-
- // tabsManager.addSpaceTab(space, {
- // active: action === 'new-tab'
- // })
- }
} catch (e) {
log.error('Error handling mention click', e)
- toasts.error('Failed to handle mention click')
}
}
@@ -1594,20 +1501,6 @@
if (response.error) {
log.error('Error generating AI output', response.error)
- if (response.error.type === PageChatMessageSentEventError.TooManyRequests) {
- toasts.error('Too many requests, please try again later')
- } else if (response.error.type === PageChatMessageSentEventError.RAGEmptyContext) {
- toasts.error(
- 'No relevant context found. Please add more resources or try a different query.'
- )
- } else if (response.error.type === PageChatMessageSentEventError.BadRequest) {
- toasts.error(
- 'Sorry your query did not pass our content policy, please try again with a different query.'
- )
- } else {
- toasts.error('Something went wrong generating the AI output. Please try again.')
- }
-
return
}
@@ -1636,7 +1529,6 @@
showBubbleMenu.set(true)
} catch (e) {
log.error('Error rewriting', e)
- toasts.error('Failed to rewrite')
showBubbleMenu.set(false)
}
}
@@ -1715,7 +1607,6 @@
const checkIfAlreadyRunning = (kind: string = 'ai generation') => {
if ($isGeneratingAI) {
log.debug(`Ignoring ${kind} request - AI generation already in progress`)
- toasts.info('AI generation already running, please wait')
return true
}
@@ -1755,7 +1646,6 @@
selectedContext.set(e.detail)
} catch (e) {
log.error('Error selecting context', e)
- toasts.error('Failed to select context')
}
}
@@ -1841,7 +1731,6 @@
}
} catch (e) {
log.error('Error handling note button click', e)
- toasts.error('Failed to handle note button click')
}
}
@@ -2021,7 +1910,6 @@
)
} catch (e) {
log.error('Error doing magic', e)
- toasts.error('Failed to autocomplete')
}
}
@@ -2058,7 +1946,6 @@
if (!generatedPrompts) {
log.error('Failed to generate prompts')
- toasts.error('Failed to generate suggestions')
generatingPrompts.set(false)
return
}
@@ -2067,7 +1954,6 @@
prompts.set(generatedPrompts)
} catch (e) {
log.error('Error generating prompts', e)
- toasts.error('Failed to generate suggestions')
} finally {
generatingPrompts.set(false)
}
@@ -2100,7 +1986,6 @@
)
} catch (e) {
log.error('Error doing magic', e)
- toasts.error('Failed to generate suggestion')
}
}
@@ -2391,7 +2276,6 @@
log.debug('Inserted onboarding mention into editor', mentionItem)
} catch (error) {
log.error('Error inserting onboarding mention', error)
- toasts.error('Failed to insert mention')
}
}
@@ -2425,7 +2309,6 @@
log.debug('UseAsDefaultBrowser extension inserted successfully at the end of the document')
} catch (err) {
log.error('Error inserting UseAsDefaultBrowser extension', err)
- toasts.error('Failed to insert default browser prompt')
}
}
@@ -2475,7 +2358,6 @@
// editor.commands.focus()
} catch (err) {
log.error('Error inserting extension', err)
- toasts.error('Failed to insert content')
}
}
@@ -2539,7 +2421,6 @@
log.debug('Onboarding footer with links inserted successfully')
} catch (err) {
log.error('Error inserting onboarding footer', err)
- toasts.error('Failed to insert resource links')
}
}
diff --git a/packages/backend/src/ai/llm/client/mod.rs b/packages/backend/src/ai/llm/client/mod.rs
index 0118a32fc..c23327edc 100644
--- a/packages/backend/src/ai/llm/client/mod.rs
+++ b/packages/backend/src/ai/llm/client/mod.rs
@@ -318,13 +318,16 @@ impl Provider {
messages: &[Message],
response_format: Option<&serde_json::Value>,
) -> BackendResult {
- serde_json::to_string(&serde_json::json!({
+ let mut json_obj = serde_json::json!({
"model": model,
"stream": stream,
"messages": messages,
- "response_format": response_format
- }))
- .map_err(|err| {
+ });
+ if let Some(format) = response_format {
+ json_obj["response_format"] = serde_json::json!(format);
+ }
+
+ serde_json::to_string(&json_obj).map_err(|err| {
BackendError::GenericError(format!(
"failed to serialize openai completion request: {err}"
))
@@ -691,7 +694,7 @@ impl LLMClient {
}
// TODO: are there other cases of bad request
if status == reqwest::StatusCode::BAD_REQUEST {
- return Err(BackendError::LLMClientErrorBadRequest);
+ return Err(BackendError::LLMClientErrorBadRequest(response.text()?));
}
if status == reqwest::StatusCode::UNAUTHORIZED {
return Err(BackendError::LLMClientErrorUnauthorized);
diff --git a/packages/backend/src/lib.rs b/packages/backend/src/lib.rs
index 86b0f56c1..73dbf58c3 100644
--- a/packages/backend/src/lib.rs
+++ b/packages/backend/src/lib.rs
@@ -24,8 +24,8 @@ pub enum BackendError {
LLMClientError { r#type: String, message: String },
#[error("LLM API Key Missing error")]
LLMClientErrorAPIKeyMissing,
- #[error("LLM Bad Request error")]
- LLMClientErrorBadRequest,
+ #[error("LLM Bad Request error: {0}")]
+ LLMClientErrorBadRequest(String),
#[error("LLM Too Many Requests error")]
LLMClientErrorTooManyRequests,
#[error("LLM Unauthorized error")]
diff --git a/packages/backend/types/index.ts b/packages/backend/types/index.ts
index fccb70b12..6e81cc876 100644
--- a/packages/backend/types/index.ts
+++ b/packages/backend/types/index.ts
@@ -99,8 +99,8 @@ export class APIKeyMissingError extends Error {
}
export class BadRequestError extends Error {
- constructor() {
- super('Bad request')
+ constructor(message?: string) {
+ super(message || 'Bad request')
this.name = 'BadRequestError'
// Maintains proper stack trace for where error was thrown (only available on V8)
if (Error.captureStackTrace) {
diff --git a/packages/services/src/lib/ai/helpers.ts b/packages/services/src/lib/ai/helpers.ts
index 0c0e03cc4..1ec389912 100644
--- a/packages/services/src/lib/ai/helpers.ts
+++ b/packages/services/src/lib/ai/helpers.ts
@@ -288,7 +288,8 @@ export const parseAIError = (e: any) => {
content = 'API key is missing. Configure an API key in your Settings to continue.'
} else if (e instanceof BadRequestError) {
error = PageChatMessageSentEventError.BadRequest
- content = 'The AI server sent a bad request error. You can try again with a different query.'
+ content =
+ e.message || 'The AI server sent a bad request response, you can try modifying your query'
} else if (e instanceof UnauthorizedError) {
error = PageChatMessageSentEventError.Unauthorized
content =
diff --git a/packages/services/src/lib/sffs.ts b/packages/services/src/lib/sffs.ts
index 656748dd0..f36a4c947 100644
--- a/packages/services/src/lib/sffs.ts
+++ b/packages/services/src/lib/sffs.ts
@@ -976,7 +976,7 @@ export class SFFS {
typeof error === 'string' ? error : error instanceof Error ? error.message : undefined
if (message) {
if (message.includes('LLM Bad Request error')) {
- throw new BadRequestError()
+ throw new BadRequestError(message.replace('LLM Bad Request error: ', ''))
}
if (message.includes('LLM API Key Missing error')) {
throw new APIKeyMissingError()