Skip to content

Commit

Permalink
Add code complete query cache, fix view validation
Browse files Browse the repository at this point in the history
  • Loading branch information
RussellCanfield committed Sep 30, 2024
1 parent 9a6e05d commit 602aeed
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 67 deletions.
24 changes: 22 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 19 additions & 18 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "wing-man",
"displayName": "Wingman-AI",
"description": "Wingman - AI powered assistant to help you write your best code, we won't leave you hanging.",
"version": "0.7.4",
"version": "0.7.5",
"publisher": "WingMan",
"license": "MIT",
"workspaces": [
Expand Down Expand Up @@ -176,39 +176,40 @@
"docs": "cd docs-site && npm run dev"
},
"dependencies": {
"@langchain/langgraph": "0.2.8",
"@langchain/community": "0.3.1",
"@langchain/openai": "0.3.0",
"@ast-grep/napi": "0.27.1",
"@langchain/anthropic": "0.3.1",
"@langchain/ollama": "0.1.0",
"@langchain/community": "0.3.1",
"@langchain/core": "0.3.3",
"@langchain/langgraph": "0.2.8",
"@langchain/ollama": "0.1.0",
"@langchain/openai": "0.3.0",
"ignore": "5.2.0",
"langchain": "0.3.2",
"node-cache": "^5.1.2",
"tree-sitter": "0.21.1",
"vectra": "0.9.0",
"vscode-languageclient": "9.0.1",
"vscode-languageserver": "9.0.1",
"vscode-languageserver-textdocument": "1.0.12",
"vscode-uri": "3.0.8",
"@ast-grep/napi": "0.27.1",
"langchain": "0.3.2",
"vectra": "0.9.0",
"zod-to-json-schema": "3.23.3",
"ignore": "5.2.0",
"zod": "3.23.8",
"tree-sitter": "0.21.1"
"zod-to-json-schema": "3.23.3"
},
"devDependencies": {
"@ast-grep/cli": "0.27.1",
"@rsbuild/core": "1.0.6",
"@rsbuild/plugin-react": "1.0.2",
"@types/mocha": "10.0.8",
"@types/node": "22.5.5",
"@types/vscode": "1.93.0",
"@types/vscode-webview": "1.57.5",
"@vscode/test-cli": "0.0.10",
"@vscode/test-electron": "2.4.1",
"adm-zip": "0.5.16",
"generate-license-file": "3.5.1",
"rimraf": "^6.0.1",
"typescript": "^5.6.2",
"@rsbuild/core": "1.0.6",
"@rsbuild/plugin-react": "1.0.2",
"@ast-grep/cli": "0.27.1",
"node-fetch": "3.3.2",
"adm-zip": "0.5.16",
"tar": "7.4.3"
"rimraf": "^6.0.1",
"tar": "7.4.3",
"typescript": "^5.6.2"
}
}
41 changes: 34 additions & 7 deletions src/providers/codeSuggestionProvider.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import * as vscode from "vscode";
import {
CancellationToken,
InlineCompletionContext,
Expand All @@ -14,14 +13,23 @@ import { getContentWindow } from "../service/utils/contentWindow";
import { InteractionSettings } from "@shared/types/Settings";
import { getSymbolsFromOpenFiles, supportedLanguages } from "./utilities";
import { getClipboardHistory } from "./clipboardTracker";
import NodeCache from "node-cache";
import { loggingProvider } from "./loggingProvider";

export class CodeSuggestionProvider implements InlineCompletionItemProvider {
public static readonly selector = supportedLanguages;
private cache: NodeCache;

constructor(
private readonly _aiProvider: AIProvider | AIStreamProvicer,
private readonly _interactionSettings: InteractionSettings
) {}
) {
this.cache = new NodeCache({
stdTTL: 300,
maxKeys: 100,
checkperiod: 120,
});
}

async provideInlineCompletionItems(
document: TextDocument,
Expand Down Expand Up @@ -73,6 +81,10 @@ export class CodeSuggestionProvider implements InlineCompletionItemProvider {
}
}

private generateCacheKey(prefix: string, suffix: string): string {
return `${prefix.slice(-100)}:${suffix.slice(0, 100)}`;
}

async bouncedRequest(
prefix: string,
signal: AbortSignal,
Expand All @@ -81,27 +93,42 @@ export class CodeSuggestionProvider implements InlineCompletionItemProvider {
additionalContext?: string
): Promise<InlineCompletionItem[]> {
try {
console.log("Clipboard", getClipboardHistory().join("\n\n"));
eventEmitter._onQueryStart.fire();
const cacheKey = this.generateCacheKey(
prefix.trim(),
suffix.trim()
);
const cachedResult = this.cache.get<string>(cacheKey);

if (cachedResult) {
loggingProvider.logInfo(
"Code complete - Serving from query cache"
);
return [new InlineCompletionItem(cachedResult)];
}

let result: string;

if ("codeCompleteStream" in this._aiProvider && streaming) {
const codeStream = await this._aiProvider.codeCompleteStream(
result = await this._aiProvider.codeCompleteStream(
prefix,
suffix,
signal,
additionalContext,
getClipboardHistory().join("\n\n")
);
return [new InlineCompletionItem(codeStream)];
} else {
const codeResponse = await this._aiProvider.codeComplete(
result = await this._aiProvider.codeComplete(
prefix,
suffix,
signal,
additionalContext,
getClipboardHistory().join("\n\n")
);
return [new InlineCompletionItem(codeResponse)];
}

this.cache.set(cacheKey, result);
return [new InlineCompletionItem(result)];
} catch (error) {
return [];
} finally {
Expand Down
7 changes: 7 additions & 0 deletions views-ui/src/Chat/SkeletonLoader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const SkeletonLoader = () => {
return (
<div className="pt-2 pb-2 tracking-wide leading-relaxed text-base animate-pulse">
<div className="h-10 bg-gray-700 rounded w-full"></div>
</div>
);
};
9 changes: 1 addition & 8 deletions views-ui/src/Chat/features/Chat/ChatEntry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { ChatMessage } from "@shared/types/Message";
import { vscode } from "../../utilities/vscode";
import { useAppContext } from "../../context";
import React from "react";
import { SkeletonLoader } from "../../SkeletonLoader";

type MarkDownObject = {
props: {
Expand Down Expand Up @@ -202,12 +203,4 @@ const ChatEntry = ({
);
};

const SkeletonLoader = () => {
return (
<div className="pt-2 pb-2 tracking-wide leading-relaxed text-base animate-pulse">
<div className="h-10 bg-gray-700 rounded w-full"></div>
</div>
);
};

export default ChatEntry;
29 changes: 12 additions & 17 deletions views-ui/src/Chat/features/Chat/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { FaPlay, FaStopCircle } from "react-icons/fa";
import { useAppContext } from "../../context";
import { useAutoFocus } from "../../hooks/useAutoFocus";
import { useOnScreen } from "../../hooks/useOnScreen";
import { useEffect } from "react";
import { useEffect, useState } from "react";

interface ChatInputProps {
onChatSubmitted: (input: string) => void;
Expand All @@ -17,6 +17,7 @@ const ChatInput = ({
}: ChatInputProps) => {
const [ref, isVisible] = useOnScreen();
const { isLightTheme } = useAppContext();
const [inputValue, setInputValue] = useState("");
const chatInputBox = useAutoFocus<HTMLTextAreaElement>();

useEffect(() => {
Expand All @@ -30,23 +31,13 @@ const ChatInput = ({
: "bg-stone-800 text-white border-stone-700";

const handleUserInput = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === "Enter") {
if (e.shiftKey) {
return;
}

const element = e.target as HTMLInputElement;
const message = element.value;

if (!message) {
return;
}
if (!inputValue.trim()) return;

if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault();

onChatSubmitted(message);

element.value = "";
onChatSubmitted(inputValue);
chatInputBox.current!.value = "";
}
};

Expand All @@ -65,7 +56,7 @@ const ChatInput = ({
<div className="flex flex-wrap items-center p-2">
<textarea
placeholder="Type here to chat with your Wingman."
ref={chatInputBox}
onChange={(e) => setInputValue(e.target.value)}
onInput={handleAutoGrow}
tabIndex={0}
rows={1}
Expand All @@ -82,7 +73,11 @@ const ChatInput = ({
size={16}
role="presentation"
title="Send message"
className="cursor-pointer"
className={`${
!inputValue.trim()
? "text-gray-500"
: "text-gray-100"
} cursor-pointer`}
onClick={() =>
handleUserInput({
key: "Enter",
Expand Down
9 changes: 1 addition & 8 deletions views-ui/src/Chat/features/Compose/ChatEntry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { useAppContext } from "../../context";
import { ComposerMessage } from "@shared/types/Composer";
import { MdOutlineDifference } from "react-icons/md";
import { LuFileCheck } from "react-icons/lu";
import { SkeletonLoader } from "../../SkeletonLoader";

export function extractCodeBlock(text: string) {
const regex = /```.*?\n([\s\S]*?)\n```/g;
Expand Down Expand Up @@ -286,12 +287,4 @@ const ChatEntry = ({
);
};

const SkeletonLoader = () => {
return (
<li className="pt-2 pb-2 tracking-wide leading-relaxed text-base animate-pulse">
<div className="h-10 bg-gray-700 rounded w-full"></div>
</li>
);
};

export default ChatEntry;
13 changes: 9 additions & 4 deletions views-ui/src/Chat/features/Compose/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ const ChatInput = ({
};

const handleUserInput = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (!inputValue.trim()) return;

if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault();
if (showDropdown && filteredDropDownItems.length > 0) {
Expand All @@ -133,7 +135,6 @@ const ChatInput = ({
chips.map((chip) => chip.path)
);
setInputValue("");
//setChips([]);
}
}
} else if (e.key === "ArrowDown") {
Expand Down Expand Up @@ -247,8 +248,12 @@ const ChatInput = ({
<FaPlay
size={16}
role="presentation"
title="Send message"
className={`cursor-pointer`}
title="Send"
className={`${
!inputValue.trim()
? "text-gray-500"
: "text-gray-100"
} cursor-pointer`}
onClick={() =>
handleUserInput({
key: "Enter",
Expand All @@ -263,7 +268,7 @@ const ChatInput = ({
size={16}
role="presentation"
title="Cancel chat"
className={`cursor-pointer`}
className="cursor-pointer"
onClick={onChatCancelled}
/>
)}
Expand Down
6 changes: 3 additions & 3 deletions views-ui/src/Diff/DiffView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ export default function DiffView() {
}

return (
<div className="bg-gray-900 rounded-lg shadow-lg">
<div className="bg-gray-800 p-4 flex justify-between items-center sticky top-0 z-10">
<div className="fixed inset-0 bg-gray-900 flex flex-col">
<div className="bg-gray-800 p-4 flex justify-between items-center z-10">
<p className="text-white font-semibold truncate">{diff.file}</p>
<button
className="bg-green-500 hover:bg-green-600 text-white font-bold py-2 px-4 rounded inline-flex items-center transition duration-300 ease-in-out"
Expand All @@ -102,7 +102,7 @@ export default function DiffView() {
<span>Accept</span>
</button>
</div>
<div className="overflow-y-auto max-h-[calc(100vh-8rem)]">
<div className="flex-grow overflow-y-auto">
<ReactDiffViewer
oldValue={diff.original}
newValue={diff.diff}
Expand Down

0 comments on commit 602aeed

Please sign in to comment.