fix: better working ai chat

This commit is contained in:
2026-02-11 21:03:50 +01:00
parent 53ebe91895
commit 226298dd15
8 changed files with 311 additions and 34 deletions

View File

@@ -319,25 +319,28 @@ export class ChatEngine {
* Get the built-in default system prompt
*/
private getBuiltInSystemPrompt(): string {
return `You are an AI assistant for the Blogging Desktop Server (bDS) application.
You help users manage their blog posts and media files.
return `You are an AI assistant integrated into the Blogging Desktop Server (bDS) application.
Your role is to help users manage their blog posts and media files using ONLY the tools provided to you.
You have access to tools that allow you to:
- Search for posts using full-text search with optional category/tag filters
- Read individual post content and metadata
- List and filter posts by status, category, or tags
- View information about media files (images)
- Update metadata for posts and media files
- List all tags with post counts
- List all categories with post counts
IMPORTANT: You do NOT have access to the internet, real-time data, or any external services.
You can ONLY access information through the tools listed below. Do not claim otherwise.
When answering questions about the user's blog content:
1. Use the search or list tools to find relevant posts
2. Read specific posts to get detailed content
3. Use list_tags and list_categories to understand the taxonomy
4. Provide helpful summaries and suggestions
Available Tools:
- search_posts: Search blog posts using full-text search. Supports category/tag filters.
- read_post: Read the full content and metadata of a specific post by ID.
- list_posts: List posts with optional filtering by status, category, or tags.
- get_media: Get information about a specific media file by ID.
- list_media: List media files with optional MIME type filtering.
- update_post_metadata: Update a post's title, excerpt, tags, or categories.
- update_media_metadata: Update a media file's alt text, caption, or tags.
- list_tags: List all tags with post counts.
- list_categories: List all categories with post counts.
Be concise but thorough in your responses. When displaying post information, format it clearly.`;
When answering questions:
1. USE THE TOOLS to find information. Never make up data about posts or media.
2. If asked about something outside your tools (weather, news, websites), explain that you can only access the user's local blog content.
3. Be concise and helpful. Format post information clearly when displaying it.
4. If a search returns no results, suggest alternative queries or filters.`;
}
/**

View File

@@ -396,8 +396,10 @@ export class OpenCodeManager {
const toolUseBlocks = (data.content as AnthropicContentBlock[]).filter(
(b: AnthropicContentBlock) => b.type === 'tool_use'
);
// Capture text from any block type that has a text field (text, thinking, etc.)
const textBlocks = (data.content as AnthropicContentBlock[]).filter(
(b: AnthropicContentBlock) => b.type === 'text'
(b: AnthropicContentBlock) => b.text
);
// Accumulate and stream text content to frontend
@@ -536,10 +538,22 @@ export class OpenCodeManager {
textContent = content;
} else if (Array.isArray(content)) {
// Handle array of content parts (some models return this format)
// Accept any part that has a text field, regardless of type
textContent = content
.filter((part: { type?: string; text?: string }) => part.type === 'text' && part.text)
.filter((part: { type?: string; text?: string }) => part.text)
.map((part: { text: string }) => part.text)
.join('');
// Log what types we're seeing for debugging
const types = content.map((p: { type?: string }) => p.type).filter(Boolean);
if (types.length > 0) {
console.log('[OpenCodeManager:OpenAI] Content block types:', types);
}
} else if (content && typeof content === 'object') {
// Handle single object with text field
if ('text' in content && typeof content.text === 'string') {
textContent = content.text;
}
}
if (textContent) {
@@ -892,17 +906,17 @@ export class OpenCodeManager {
private async generateConversationTitle(
conversationId: string,
userMessage: string,
assistantResponse: string
_assistantResponse: string
): Promise<void> {
try {
const body = {
model: 'claude-haiku-4-5',
max_tokens: 100,
system: 'Generate a short, concise title (max 6 words) for this conversation. Only output the title, nothing else.',
max_tokens: 20,
system: 'Generate an ultra-short title (2-3 words, max 25 characters) for this conversation. Focus ONLY on the topic. Ignore any capability disclaimers. Output ONLY the title text.',
messages: [
{
role: 'user',
content: `User: ${userMessage.substring(0, 200)}\nAssistant: ${assistantResponse.substring(0, 200)}`,
content: `Topic: ${userMessage.substring(0, 100)}`,
},
],
};
@@ -930,7 +944,14 @@ export class OpenCodeManager {
title = data.content || '';
}
title = title.trim().replace(/^["']|["']$/g, '');
// Clean up and truncate title
title = title.trim().replace(/^["']|["']$/g, '').replace(/[.!?]+$/, '');
// Hard limit on title length
const MAX_TITLE_LENGTH = 30;
if (title.length > MAX_TITLE_LENGTH) {
title = title.substring(0, MAX_TITLE_LENGTH - 1) + '…';
}
if (title) {
await this.chatEngine.updateConversation(conversationId, { title });

View File

@@ -297,10 +297,10 @@ export interface ElectronAPI {
getApiKey: () => Promise<{ hasKey: boolean; maskedKey: string }>;
// Settings
getAvailableModels: () => Promise<Array<{ id: string; name: string }>>;
setDefaultModel: (modelId: string) => Promise<void>;
getSystemPrompt: () => Promise<string | null>;
setSystemPrompt: (prompt: string) => Promise<void>;
getAvailableModels: () => Promise<{ success: boolean; models?: Array<{ id: string; name: string }>; selectedModel?: string; error?: string }>;
setDefaultModel: (modelId: string) => Promise<{ success: boolean; error?: string }>;
getSystemPrompt: () => Promise<{ success: boolean; prompt?: string; error?: string }>;
setSystemPrompt: (prompt: string) => Promise<{ success: boolean; error?: string }>;
// Conversations
getConversations: () => Promise<unknown[]>;