feat: Add conversational AI assistant panel for project codebase Q&A

Implement a slide-in chat panel that allows users to ask questions about
their codebase using Claude Opus 4.5 with read-only access to project files.

Backend changes:
- Add SQLAlchemy models for conversation persistence (assistant_database.py)
- Create AssistantChatSession with read-only Claude SDK client
- Add WebSocket endpoint for real-time chat streaming
- Include read-only MCP tools: feature_get_stats, feature_get_next, etc.

Frontend changes:
- Add floating action button (bottom-right) to toggle panel
- Create slide-in panel component (400px width)
- Implement WebSocket hook with reconnection logic
- Add keyboard shortcut 'A' to toggle assistant

Key features:
- Read-only access: Only Read, Glob, Grep, WebFetch, WebSearch tools
- Persistent history: Conversations saved to SQLite per project
- Real-time streaming: Text chunks streamed as Claude generates response
- Tool visibility: Shows when assistant is using tools to explore code

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Auto
2026-01-04 14:57:58 +02:00
parent 88951e454a
commit 908754302a
13 changed files with 1657 additions and 6 deletions

View File

@@ -14,6 +14,8 @@ import type {
SetupStatus,
DirectoryListResponse,
PathValidationResponse,
AssistantConversation,
AssistantConversationDetail,
} from './types'
const API_BASE = '/api'
@@ -228,3 +230,40 @@ export async function validatePath(path: string): Promise<PathValidationResponse
body: JSON.stringify({ path }),
})
}
// ============================================================================
// Assistant Chat API
// ============================================================================
export async function listAssistantConversations(
projectName: string
): Promise<AssistantConversation[]> {
return fetchJSON(`/assistant/conversations/${encodeURIComponent(projectName)}`)
}
export async function getAssistantConversation(
projectName: string,
conversationId: number
): Promise<AssistantConversationDetail> {
return fetchJSON(
`/assistant/conversations/${encodeURIComponent(projectName)}/${conversationId}`
)
}
export async function createAssistantConversation(
projectName: string
): Promise<AssistantConversation> {
return fetchJSON(`/assistant/conversations/${encodeURIComponent(projectName)}`, {
method: 'POST',
})
}
export async function deleteAssistantConversation(
projectName: string,
conversationId: number
): Promise<void> {
await fetchJSON(
`/assistant/conversations/${encodeURIComponent(projectName)}/${conversationId}`,
{ method: 'DELETE' }
)
}

View File

@@ -229,3 +229,69 @@ export interface ChatMessage {
questions?: SpecQuestion[]
isStreaming?: boolean
}
// ============================================================================
// Assistant Chat Types
// ============================================================================
export interface AssistantConversation {
id: number
project_name: string
title: string | null
created_at: string | null
updated_at: string | null
message_count: number
}
export interface AssistantMessage {
id: number
role: 'user' | 'assistant' | 'system'
content: string
timestamp: string | null
}
export interface AssistantConversationDetail {
id: number
project_name: string
title: string | null
created_at: string | null
updated_at: string | null
messages: AssistantMessage[]
}
export interface AssistantChatTextMessage {
type: 'text'
content: string
}
export interface AssistantChatToolCallMessage {
type: 'tool_call'
tool: string
input: Record<string, unknown>
}
export interface AssistantChatResponseDoneMessage {
type: 'response_done'
}
export interface AssistantChatErrorMessage {
type: 'error'
content: string
}
export interface AssistantChatConversationCreatedMessage {
type: 'conversation_created'
conversation_id: number
}
export interface AssistantChatPongMessage {
type: 'pong'
}
export type AssistantChatServerMessage =
| AssistantChatTextMessage
| AssistantChatToolCallMessage
| AssistantChatResponseDoneMessage
| AssistantChatErrorMessage
| AssistantChatConversationCreatedMessage
| AssistantChatPongMessage