mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-09 03:17:54 +00:00
fix(web): scope all backend calls to the active repo, not always the first
The root cause of four related issues: `repoRef.current` was never set during initial server connection — only `switchRepo()` set it. Every backend call (queries, search, grep, readFile) passed `undefined` as the repo parameter, so the server's `resolveRepo()` fell back to `repos[0]`. Changes: - Expose `setCurrentRepo` from useAppState and call it in `handleServerConnect` - Use `result.repoInfo.name` (canonical server name) instead of path parsing - Parse `?project=` URL param during auto-connect, pass it to `connectToServer` - Update URL with `?project=` on repo switch so F5/bookmarks work - Pass `projectName` as `repo` in CodeReferencesPanel's `readFile` calls Closes #139, closes #634, closes #635, closes #636 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5c4fca21c3
commit
a6c66f9777
3 changed files with 67 additions and 35 deletions
|
|
@ -45,17 +45,21 @@ const AppContent = () => {
|
|||
availableRepos,
|
||||
setAvailableRepos,
|
||||
switchRepo,
|
||||
setCurrentRepo,
|
||||
} = useAppState();
|
||||
|
||||
const graphCanvasRef = useRef<GraphCanvasHandle>(null);
|
||||
|
||||
const handleServerConnect = useCallback(
|
||||
async (result: ConnectResult): Promise<void> => {
|
||||
// Extract project name from repoPath
|
||||
// Use the canonical repo name from the server response so all subsequent
|
||||
// backend calls (queries, search, grep, readFile) scope to this repo.
|
||||
const repoName = result.repoInfo.name;
|
||||
const repoPath = result.repoInfo.repoPath ?? result.repoInfo.path;
|
||||
const parts = (repoPath || '').split('/').filter((p) => p && !p.startsWith('.'));
|
||||
const projectName = parts[parts.length - 1] || parts[0] || 'server-project';
|
||||
const projectName =
|
||||
repoName || repoPath?.split('/').filter(Boolean).pop() || 'server-project';
|
||||
setProjectName(projectName);
|
||||
setCurrentRepo(projectName);
|
||||
|
||||
// Build KnowledgeGraph from server data for visualization
|
||||
const graph = createKnowledgeGraph();
|
||||
|
|
@ -80,10 +84,18 @@ const AppContent = () => {
|
|||
console.warn('Failed to initialize agent:', err);
|
||||
}
|
||||
},
|
||||
[setViewMode, setGraph, setProjectName, initializeAgent, startEmbeddingsWithFallback],
|
||||
[
|
||||
setViewMode,
|
||||
setGraph,
|
||||
setProjectName,
|
||||
setCurrentRepo,
|
||||
initializeAgent,
|
||||
startEmbeddingsWithFallback,
|
||||
],
|
||||
);
|
||||
|
||||
// Auto-connect when ?server query param is present (bookmarkable shortcut)
|
||||
// Auto-connect when ?server query param is present (bookmarkable shortcut).
|
||||
// Also reads ?project= to connect to a specific repo.
|
||||
const autoConnectRan = useRef(false);
|
||||
useEffect(() => {
|
||||
if (autoConnectRan.current) return;
|
||||
|
|
@ -91,7 +103,10 @@ const AppContent = () => {
|
|||
if (!params.has('server')) return;
|
||||
autoConnectRan.current = true;
|
||||
|
||||
// Clean the URL so a refresh won't re-trigger
|
||||
const serverUrl = params.get('server') || window.location.origin;
|
||||
const projectParam = params.get('project') || undefined;
|
||||
|
||||
// Clean the URL so a refresh won't re-trigger auto-connect
|
||||
const cleanUrl = window.location.pathname + window.location.hash;
|
||||
window.history.replaceState(null, '', cleanUrl);
|
||||
|
||||
|
|
@ -103,36 +118,39 @@ const AppContent = () => {
|
|||
});
|
||||
setViewMode('loading');
|
||||
|
||||
const serverUrl = params.get('server') || window.location.origin;
|
||||
|
||||
const baseUrl = normalizeServerUrl(serverUrl);
|
||||
|
||||
connectToServer(serverUrl, (phase, downloaded, total) => {
|
||||
if (phase === 'validating') {
|
||||
setProgress({
|
||||
phase: 'extracting',
|
||||
percent: 5,
|
||||
message: 'Connecting to server...',
|
||||
detail: 'Validating server',
|
||||
});
|
||||
} else if (phase === 'downloading') {
|
||||
const pct = total ? Math.round((downloaded / total) * 90) + 5 : 50;
|
||||
const mb = (downloaded / (1024 * 1024)).toFixed(1);
|
||||
setProgress({
|
||||
phase: 'extracting',
|
||||
percent: pct,
|
||||
message: 'Downloading graph...',
|
||||
detail: `${mb} MB downloaded`,
|
||||
});
|
||||
} else if (phase === 'extracting') {
|
||||
setProgress({
|
||||
phase: 'extracting',
|
||||
percent: 97,
|
||||
message: 'Processing...',
|
||||
detail: 'Extracting file contents',
|
||||
});
|
||||
}
|
||||
})
|
||||
connectToServer(
|
||||
serverUrl,
|
||||
(phase, downloaded, total) => {
|
||||
if (phase === 'validating') {
|
||||
setProgress({
|
||||
phase: 'extracting',
|
||||
percent: 5,
|
||||
message: 'Connecting to server...',
|
||||
detail: 'Validating server',
|
||||
});
|
||||
} else if (phase === 'downloading') {
|
||||
const pct = total ? Math.round((downloaded / total) * 90) + 5 : 50;
|
||||
const mb = (downloaded / (1024 * 1024)).toFixed(1);
|
||||
setProgress({
|
||||
phase: 'extracting',
|
||||
percent: pct,
|
||||
message: 'Downloading graph...',
|
||||
detail: `${mb} MB downloaded`,
|
||||
});
|
||||
} else if (phase === 'extracting') {
|
||||
setProgress({
|
||||
phase: 'extracting',
|
||||
percent: 97,
|
||||
message: 'Processing...',
|
||||
detail: 'Extracting file contents',
|
||||
});
|
||||
}
|
||||
},
|
||||
undefined,
|
||||
projectParam,
|
||||
)
|
||||
.then(async (result) => {
|
||||
await handleServerConnect(result);
|
||||
setProgress(null);
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ export const CodeReferencesPanel = ({ onFocusNode }: CodeReferencesPanelProps) =
|
|||
clearCodeReferences,
|
||||
setSelectedNode,
|
||||
codeReferenceFocus,
|
||||
projectName,
|
||||
} = useAppState();
|
||||
|
||||
const nodeById = useMemo(() => {
|
||||
|
|
@ -223,10 +224,11 @@ export const CodeReferencesPanel = ({ onFocusNode }: CodeReferencesPanelProps) =
|
|||
const isWholeFile = selectedIsFile || startLine === undefined;
|
||||
|
||||
const options = isWholeFile
|
||||
? undefined
|
||||
? { repo: projectName }
|
||||
: {
|
||||
startLine: Math.max(0, startLine - CONTEXT_LINES),
|
||||
endLine: (endLine ?? startLine) + CONTEXT_LINES,
|
||||
repo: projectName,
|
||||
};
|
||||
|
||||
readFile(selectedFilePath, options)
|
||||
|
|
@ -251,6 +253,7 @@ export const CodeReferencesPanel = ({ onFocusNode }: CodeReferencesPanelProps) =
|
|||
selectedNode?.properties?.startLine,
|
||||
selectedNode?.properties?.endLine,
|
||||
selectedIsFile,
|
||||
projectName,
|
||||
]);
|
||||
|
||||
// Scroll to the selected node's startLine after content loads
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ interface AppState {
|
|||
availableRepos: BackendRepo[];
|
||||
setAvailableRepos: (repos: BackendRepo[]) => void;
|
||||
switchRepo: (repoName: string) => Promise<void>;
|
||||
setCurrentRepo: (repoName: string) => void;
|
||||
|
||||
// Worker API (shared across app)
|
||||
runQuery: (cypher: string) => Promise<any[]>;
|
||||
|
|
@ -456,6 +457,10 @@ const AppStateProviderInner = ({ children }: { children: ReactNode }) => {
|
|||
// Backend client — direct HTTP calls (no Worker/Comlink)
|
||||
const repoRef = useRef<string | undefined>(undefined);
|
||||
|
||||
const setCurrentRepo = useCallback((repoName: string) => {
|
||||
repoRef.current = repoName;
|
||||
}, []);
|
||||
|
||||
const runQuery = useCallback(async (cypher: string): Promise<any[]> => {
|
||||
return backendRunQuery(cypher, repoRef.current);
|
||||
}, []);
|
||||
|
|
@ -1077,6 +1082,11 @@ const AppStateProviderInner = ({ children }: { children: ReactNode }) => {
|
|||
setProjectName(pName);
|
||||
repoRef.current = pName;
|
||||
|
||||
// Update URL so F5 / bookmarks open the correct repo
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.set('project', pName);
|
||||
window.history.replaceState(null, '', url.toString());
|
||||
|
||||
const newGraph = createKnowledgeGraph();
|
||||
for (const node of result.nodes) newGraph.addNode(node);
|
||||
for (const rel of result.relationships) newGraph.addRelationship(rel);
|
||||
|
|
@ -1219,6 +1229,7 @@ const AppStateProviderInner = ({ children }: { children: ReactNode }) => {
|
|||
availableRepos,
|
||||
setAvailableRepos,
|
||||
switchRepo,
|
||||
setCurrentRepo,
|
||||
runQuery,
|
||||
isDatabaseReady,
|
||||
// Embedding state and methods
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue