fix: better working ai chat
This commit is contained in:
@@ -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.`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -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[]>;
|
||||
|
||||
Reference in New Issue
Block a user