Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CON-1067: Create 'indexing failed', 'indexing not loaded', states #1220

Merged
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/context/providers/FolderContextProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { getBasename, getLastNPathParts } from "../../util";
class FolderContextProvider extends BaseContextProvider {
static description: ContextProviderDescription = {
title: "folder",
displayTitle: "Folders",
displayTitle: "Folder",
description: "Type to search",
type: "submenu",
};
Expand Down
1 change: 1 addition & 0 deletions core/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export interface Chunk extends ChunkWithoutID {
export interface IndexingProgressUpdate {
progress: number;
desc: string;
failed?: boolean;
}

export interface LLMReturnValue {
Expand Down
12 changes: 11 additions & 1 deletion core/indexing/indexCodebase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { getComputeDeleteAddRemove } from "./refreshIndex";
import { CodebaseIndex } from "./types";

export class PauseToken {
constructor(private _paused: boolean) {}
constructor(private _paused: boolean) { }

set paused(value: boolean) {
this._paused = value;
Expand Down Expand Up @@ -70,6 +70,14 @@ export class CodebaseIndexer {
return;
}

//Test to see if embeddings provider is configured properly
try {
await config.embeddingsProvider.embed(['sample text']);
} catch (error) {
yield { progress: 1, desc: "Indexing failed while testing provider", failed: true };
return
}

const indexesToBuild = await this.getIndexesToBuild();

let completedDirs = 0;
Expand All @@ -80,6 +88,7 @@ export class CodebaseIndexer {
yield {
progress: 0,
desc: "Starting indexing...",
failed: false
};

for (let directory of workspaceDirs) {
Expand Down Expand Up @@ -114,6 +123,7 @@ export class CodebaseIndexer {
yield {
progress: 1,
desc: "Indexing cancelled",
failed: true
};
return;
}
Expand Down
4 changes: 3 additions & 1 deletion core/web/webviewProtocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export type WebviewProtocol = Protocol &
errorPopup: [{ message: string }, void];
"index/setPaused": [boolean, void];
"index/forceReIndex": [undefined, void];
"index/indexingProgressBarInitialized": [{ready: boolean}, void]
openUrl: [string, void];
applyToCurrentFile: [{ text: string }, void];
showTutorial: [undefined, void];
Expand Down Expand Up @@ -127,7 +128,8 @@ export type ReverseWebviewProtocol = {
addModel: [undefined, void];
openSettings: [undefined, void];
viewHistory: [undefined, void];
indexProgress: [{ progress: number; desc: string }, void];
indexProgress: [{ progress: number; desc: string; failed?: boolean }, void];
indexingProgressBarInitialized: [{ready: boolean}, void]
newSession: [undefined, void];
refreshSubmenuItems: [undefined, void];
setTheme: [{ theme: any }, void];
Expand Down
40 changes: 35 additions & 5 deletions extensions/vscode/src/extension/vscodeExtension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,16 @@ export class VsCodeExtension {
this.webviewProtocol.on("index/forceReIndex", (msg) => {
this.ide
.getWorkspaceDirs()
.then((dirs) => this.refreshCodebaseIndex(dirs));
.then((dirs) => this.refreshCodebaseIndex(dirs, context));
});

this.webviewProtocol.on("index/indexingProgressBarInitialized", (msg) => {
// Triggered when progress bar is initialized. Purpose: To relay global state values to the progress bar
let progress = context.globalState.get<number>("continue.indexingProgress") as number
let desc = context.globalState.get<string>("continue.indexingDesc") as string
let failed = context.globalState.get<boolean>("continue.indexingFailed") as boolean
this.webviewProtocol?.request("indexProgress", {progress, desc, failed})
});

this.diffManager.webviewProtocol = this.webviewProtocol;

const userTokenPromise: Promise<string | undefined> = new Promise(
Expand Down Expand Up @@ -189,7 +196,7 @@ export class VsCodeExtension {
registerDebugTracker(this.webviewProtocol, this.ide);

// Indexing
this.ide.getWorkspaceDirs().then((dirs) => this.refreshCodebaseIndex(dirs));
this.ide.getWorkspaceDirs().then((dirs) => this.refreshCodebaseIndex(dirs, context));

// Listen for file saving - use global file watcher so that changes
// from outside the window are also caught
Expand Down Expand Up @@ -231,7 +238,7 @@ export class VsCodeExtension {
currentBranch !== this.PREVIOUS_BRANCH_FOR_WORKSPACE_DIR[dir]
) {
// Trigger refresh of index only in this directory
this.refreshCodebaseIndex([dir]);
this.refreshCodebaseIndex([dir], context);
}
}

Expand Down Expand Up @@ -267,16 +274,39 @@ export class VsCodeExtension {
private PREVIOUS_BRANCH_FOR_WORKSPACE_DIR: { [dir: string]: string } = {};
private indexingCancellationController: AbortController | undefined;

private async refreshCodebaseIndex(dirs: string[]) {
private async refreshCodebaseIndex(dirs: string[], context: vscode.ExtensionContext) {
//reset all state variables
console.log("Codebase indexing starting up")
this.webviewProtocol?.request("indexProgress", {progress: 0, desc: "", failed:false});
context.globalState.update("continue.indexingFailed", false)
context.globalState.update("continue.indexingProgress", 0)
context.globalState.update("continue.indexingDesc", "")

if (this.indexingCancellationController) {
this.indexingCancellationController.abort();
}
this.indexingCancellationController = new AbortController();
let err = undefined
for await (const update of this.indexer.refresh(
dirs,
this.indexingCancellationController.signal,
)) {
this.webviewProtocol.request("indexProgress", update);
if (update.failed) {
err = update.desc
context.globalState.update("continue.indexingFailed", true)
break
} else {
context.globalState.update("continue.indexingProgress", update.progress)
context.globalState.update("continue.indexingDesc", update.desc)
}
}

if (err) {
console.log("Codebase Indexing Failed: ", err)
} else {
console.log("Codebase Indexing Complete")
}

}
}
5 changes: 4 additions & 1 deletion gui/src/components/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ const Layout = () => {
useWebviewListener("indexProgress", async (data) => {
setIndexingProgress(data.progress);
setIndexingTask(data.desc);
setIndexingFailed(data.failed)
});

useEffect(() => {
Expand All @@ -185,8 +186,9 @@ const Layout = () => {
}
}, [location]);

const [indexingProgress, setIndexingProgress] = useState(1);
const [indexingProgress, setIndexingProgress] = useState(-1);
const [indexingTask, setIndexingTask] = useState("Indexing Codebase");
const [indexingFailed, setIndexingFailed] = useState(false);

return (
<LayoutTopDiv>
Expand Down Expand Up @@ -259,6 +261,7 @@ const Layout = () => {
currentlyIndexing={indexingTask}
completed={indexingProgress * 100}
total={100}
indexingFailed={indexingFailed}
/>
)}
</div>
Expand Down
37 changes: 33 additions & 4 deletions gui/src/components/loaders/IndexingProgressBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,14 @@ interface ProgressBarProps {
completed: number;
total: number;
currentlyIndexing?: string;
indexingFailed?: boolean;
}

const IndexingProgressBar = ({
completed,
total,
currentlyIndexing,
indexingFailed = false
}: ProgressBarProps) => {
const fillPercentage = Math.min(100, Math.max(0, (completed / total) * 100));

Expand All @@ -66,22 +68,49 @@ const IndexingProgressBar = ({
const [expanded, setExpanded] = useState(true);
const [hovered, setHovered] = useState(false);

useEffect(() => {
postToIde("index/indexingProgressBarInitialized", {ready:true})
}, []);

useEffect(() => {
postToIde("index/setPaused", !expanded);
}, [expanded]);

return (
<div
onClick={() => {
if (completed < total) {
if (!indexingFailed && completed < total && completed >= 0) {
setExpanded((prev) => !prev);
} else {
postToIde("index/forceReIndex", undefined);
}
}}
className="cursor-pointer"
>
{completed >= total ? (
{
(completed < 0 && !indexingFailed) ? ( // ice-blue 'indexing starting up' dot
<>
<CircleDiv data-tooltip-id="indexingNotLoaded_dot" color="#72aec2"></CircleDiv>
{tooltipPortalDiv &&
ReactDOM.createPortal(
<StyledTooltip id="indexingNotLoaded_dot" place="top">
Codebase indexing is starting up.
</StyledTooltip>,
tooltipPortalDiv,
)}
</>
) : indexingFailed ? ( //red 'failed' dot
<>
<CircleDiv data-tooltip-id="indexingFailed_dot" color="#ff0000"></CircleDiv>
{tooltipPortalDiv &&
ReactDOM.createPortal(
<StyledTooltip id="indexingFailed_dot" place="top">
Codebase not indexed. Click to retry
</StyledTooltip>,
tooltipPortalDiv,
)}
</>
) : completed >= total ? ( //indexing complete green dot
<>
<CircleDiv data-tooltip-id="progress_dot" color="#090"></CircleDiv>
{tooltipPortalDiv &&
Expand All @@ -92,7 +121,7 @@ const IndexingProgressBar = ({
tooltipPortalDiv,
)}
</>
) : expanded ? (
) : expanded ? ( //progress bar
<>
<GridDiv
data-tooltip-id="usage_progress_bar"
Expand All @@ -116,7 +145,7 @@ const IndexingProgressBar = ({
tooltipPortalDiv,
)}
</>
) : (
) : ( //yellow 'paused' dot
<>
<CircleDiv data-tooltip-id="progress_dot" color="#bb0"></CircleDiv>
{tooltipPortalDiv &&
Expand Down