diff --git a/AIClasses/BaseAIClass.ts b/AIClasses/BaseAIClass.ts index b5cfb0a..5985741 100644 --- a/AIClasses/BaseAIClass.ts +++ b/AIClasses/BaseAIClass.ts @@ -138,6 +138,9 @@ export abstract class BaseAIClass implements IAIClass { for (const attachment of attachments) { try { + if (attachment.base64.trim() === "") { + Exception.throw("File has no content!"); + } await this.aiFileService.uploadFile(attachment); } catch (error) { Exception.log(`Failed to upload ${attachment.fileName}: ${Exception.messageFrom(error)}`); diff --git a/AIClasses/Claude/Claude.ts b/AIClasses/Claude/Claude.ts index 0a9356b..1758a9e 100644 --- a/AIClasses/Claude/Claude.ts +++ b/AIClasses/Claude/Claude.ts @@ -11,7 +11,8 @@ import { Role } from "Enums/Role"; import type { RawMessageStreamEvent, ContentBlockParam, Tool } from '@anthropic-ai/sdk/resources/messages'; import { Exception } from "Helpers/Exception"; import { MimeType, toMimeType } from "Enums/MimeType"; -import { isTextFile, MimeTypeToFileTypes } from "Enums/FileType"; +import { isTextFile } from "Enums/FileType"; +import { MimeTypeToFileTypes } from "Enums/FileTypeMimeTypeMapping"; export class Claude extends BaseAIClass { @@ -286,7 +287,7 @@ export class Claude extends BaseAIClass { } return [ - {type: "text", text: attachment.fileName}, + {type: "text", text: `Binary data for ${attachment.fileName} follows in next message` }, { type: isPlainText || mimeType === MimeType.APPLICATION_PDF ? "document" : "image", source: { diff --git a/AIClasses/Gemini/Gemini.ts b/AIClasses/Gemini/Gemini.ts index 553c9e0..b8a841c 100644 --- a/AIClasses/Gemini/Gemini.ts +++ b/AIClasses/Gemini/Gemini.ts @@ -11,7 +11,8 @@ import type { ConversationContent } from "Conversations/ConversationContent"; import type { Candidate, Part, FunctionDeclaration } from "@google/genai"; import { FinishReason } from "@google/genai"; import { MimeType, toMimeType } from "Enums/MimeType"; -import { isTextFile, MimeTypeToFileTypes } from "Enums/FileType"; +import { isTextFile } from "Enums/FileType"; +import { MimeTypeToFileTypes } from "Enums/FileTypeMimeTypeMapping"; export class Gemini extends BaseAIClass { @@ -30,6 +31,8 @@ export class Gemini extends BaseAIClass { // Images MimeType.IMAGE_JPEG, MimeType.IMAGE_PNG, + // PDF + MimeType.APPLICATION_PDF, // Data Formats MimeType.APPLICATION_JSON, MimeType.APPLICATION_XML, @@ -328,7 +331,7 @@ export class Gemini extends BaseAIClass { continue; } - parts.push({text: attachment.fileName}); + parts.push({ text: `Binary data for ${attachment.fileName} follows in next message` }); parts.push({ fileData: { mimeType: mimeType, diff --git a/AIClasses/OpenAI/OpenAI.ts b/AIClasses/OpenAI/OpenAI.ts index f5ebf14..dfbe0bf 100644 --- a/AIClasses/OpenAI/OpenAI.ts +++ b/AIClasses/OpenAI/OpenAI.ts @@ -11,7 +11,8 @@ import type { ResponseEvent, ResponseOutputTextDelta, ResponseOutputItemDone, Re import { Exception } from "Helpers/Exception"; import { ApiErrorType } from "Types/ApiError"; import { MimeType, toMimeType } from "Enums/MimeType"; -import { isTextFile, MimeTypeToFileTypes } from "Enums/FileType"; +import { isTextFile } from "Enums/FileType"; +import { MimeTypeToFileTypes } from "Enums/FileTypeMimeTypeMapping"; export class OpenAI extends BaseAIClass { @@ -332,14 +333,17 @@ export class OpenAI extends BaseAIClass { } if (!isPlainText && !this.isSupportedMimeType(mimeType)) { - contentBlocks.push([{ type: "input_text", text: `Unsupported mime type '${mimeType}': ${attachment.fileName}` }]); + contentBlocks.push({ type: "input_text", text: `Unsupported mime type '${mimeType}': ${attachment.fileName}` }); continue; } - contentBlocks.push({ - type: isPlainText || mimeType === MimeType.APPLICATION_PDF ? "input_file" : "input_image", - file_id: fileID - }); + contentBlocks.push( + { type: "input_text", text: `Binary data for ${attachment.fileName} follows in next message` }, + { + type: isPlainText || mimeType === MimeType.APPLICATION_PDF ? "input_file" : "input_image", + file_id: fileID + } + ); } return JSON.stringify([{ diff --git a/Components/ChatArea.svelte b/Components/ChatArea.svelte index 2eac1a2..12ada55 100644 --- a/Components/ChatArea.svelte +++ b/Components/ChatArea.svelte @@ -66,7 +66,7 @@ if (!shouldSettle) { padding = Math.max(padding, 25); } - chatAreaPaddingElement.style.padding = `${Math.max(0, padding / 2)}px`; + chatAreaPaddingElement.style.paddingBottom = `${Math.max(0, padding)}px`; tick().then(() => { if (behavior && (autoScroll || shouldSettle)) { @@ -259,16 +259,32 @@ {#if message.role === Role.User}