Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions api/websocket_wiki.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
import traceback
from typing import Any, Dict, List

import google.generativeai as genai
from fastapi import WebSocket, WebSocketDisconnect

from api.models import ChatCompletionRequest, ChatMessage
from api.rag import RAG
from utils.logger import logger
from utils.token_utils import count_tokens
import google.generativeai as genai

google_api_key = os.environ.get("GOOGLE_API_KEY")

Expand Down Expand Up @@ -112,7 +112,7 @@ async def handle_websocket_chat(websocket: WebSocket):
You provide direct, concise, and accurate information about code repositories.
You NEVER start responses with markdown headers or code fences.
IMPORTANT:You MUST respond in English language.
</role>
</role>

<guidelines>
- Answer the user's question directly without ANY preamble or filler phrases
Expand Down Expand Up @@ -182,10 +182,6 @@ async def handle_websocket_chat(websocket: WebSocket):
"top_k": 40,
},
)
# Save prompt to file for debugging
prompt_file = "debug_prompt.txt"
with open(prompt_file, "w") as f:
f.write(prompt)

response = model.generate_content(prompt, stream=True)
# Stream the response
Expand Down
77 changes: 70 additions & 7 deletions frontend/app/[owner]/[repo]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
'use client';

import Ask from '@/components/Ask';
import Markdown from '@/components/Markdown';
import ThemeToggle from '@/components/theme-toggle';
import WikiTreeView from '@/components/WikiTreeView';
import { useLanguage } from '@/contexts/LanguageContext';
import { RepoInfo } from '@/types/repoInfo';
import Link from 'next/link';
import { useParams, useSearchParams } from 'next/navigation';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import React, {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import {
FaBitbucket,
FaBookOpen,
FaComments,
FaDownload,
FaExclamationTriangle,
FaFileExport,
Expand All @@ -19,6 +27,7 @@ import {
FaGitlab,
FaHome,
FaSync,
FaTimes,
} from 'react-icons/fa';

interface WikiSection {
Expand Down Expand Up @@ -135,7 +144,7 @@ export default function RepoWikiPage() {
WikiStructure | undefined
>();

const [effectiveRepoInfo, setEffectiveRepoInfo] = useState(repoInfo); // Track effective repo info with cached data
const [effectiveRepoInfo, setEffectiveRepoInfo] = useState(repoInfo);
const [isComprehensiveView, setIsComprehensiveView] = useState('');
const [exportError, setExportError] = useState<string | null>(null);
const [generatedPages, setGeneratedPages] = useState<
Expand All @@ -145,6 +154,10 @@ export default function RepoWikiPage() {
const [taskId, setTaskId] = useState<string | null>(null);
const intervalRef = useRef<NodeJS.Timeout | null>(null);
const effectRan = React.useRef(false);
const [isAskModalOpen, setIsAskModalOpen] = useState(false);
const askComponentRef = useRef<{ clearConversation: () => void } | null>(
null
);

const exportWiki = (format: 'markdown' | 'json') => {};
const handlePageSelect = (pageId: string) => {
Expand All @@ -153,7 +166,7 @@ export default function RepoWikiPage() {
}
};

const startWikiGeneration = async () => {
const startWikiGeneration = useCallback(async () => {
if (requestInProgress) {
console.log('Reporitory processing already in progress.');
return;
Expand Down Expand Up @@ -233,7 +246,14 @@ export default function RepoWikiPage() {
} finally {
setRequestInProgress(false);
}
};
}, [
effectiveRepoInfo.owner,
effectiveRepoInfo.repo,
effectiveRepoInfo.type,
effectiveRepoInfo.repoUrl,
messages.loading,
requestInProgress,
]);

useEffect(() => {
if (effectRan.current === false) {
Expand Down Expand Up @@ -289,10 +309,15 @@ export default function RepoWikiPage() {
} else {
console.log('Skipping duplicate repository processing');
}
}, []);
}, [
effectiveRepoInfo,
effectiveRepoInfo.owner,
effectiveRepoInfo.repo,
effectiveRepoInfo.type,
messages.loading?.initializing,
startWikiGeneration,
]);

console.log('generatedPages', generatedPages);
console.log('wikiStructure', wikiStructure);
return (
<div className='h-screen paper-texture p-4 md:p-8 flex flex-col'>
<style>{wikiStyles}</style>
Expand Down Expand Up @@ -613,6 +638,44 @@ export default function RepoWikiPage() {
<ThemeToggle />
</div>
</footer>

{!isLoading && wikiStructure && (
<button
onClick={() => setIsAskModalOpen(true)}
className='fixed bottom-6 right-6 w-14 h-14 rounded-full bg-[var(--accent-primary)] text-white shadow-lg flex items-center justify-center hover:bg-[var(--accent-primary)]/90 transition-all z-50'
aria-label={messages.ask?.title || 'Ask about this repository'}
>
<FaComments className='text-xl' />
</button>
)}

<div
className={`fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4 transition-opacity duration-300 ${
isAskModalOpen ? 'opacity-100' : 'opacity-0 pointer-events-none'
}`}
>
<div className='bg-[var(--card-bg)] rounded-lg shadow-xl w-full max-w-3xl max-h-[80vh] flex flex-col'>
<div className='flex items-center justify-end p-3 absolute top-0 right-0 z-10'>
<button
onClick={() => {
// Just close the modal without clearing the conversation
setIsAskModalOpen(false);
}}
className='text-[var(--muted)] hover:text-[var(--foreground)] transition-colors bg-[var(--card-bg)]/80 rounded-full p-2'
aria-label='Close'
>
<FaTimes className='text-xl' />
</button>
</div>
<div className='flex-1 overflow-y-auto p-4'>
<Ask
repoInfo={effectiveRepoInfo}
language={language}
onRef={(ref) => (askComponentRef.current = ref)}
/>
</div>
</div>
</div>
</div>
);
}
Loading
Loading