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

exit edit mode on cmd+shift+enter #3690

Merged
merged 8 commits into from
Jan 11, 2025
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { streamLines } from "../../../diff/util";
import { DEFAULT_AUTOCOMPLETE_OPTS } from "../../../util/parameters";
import { PosthogFeatureFlag, Telemetry } from "../../../util/posthog";
import { HelperVars } from "../../util/HelperVars";

Expand Down Expand Up @@ -74,12 +73,10 @@ export class StreamTransformPipeline {
fullStop,
);

const timeoutValue =
helper.options.showWhateverWeHaveAtXMs ??
(await Telemetry.getValueForFeatureFlag(
PosthogFeatureFlag.AutocompleteTimeout,
)) ??
DEFAULT_AUTOCOMPLETE_OPTS.showWhateverWeHaveAtXMs;
const timeoutValue = await Telemetry.getValueForFeatureFlag(
PosthogFeatureFlag.AutocompleteTimeout,
);
// helper.options.showWhateverWeHaveAtXMs ?? DEFAULT_AUTOCOMPLETE_OPTS.showWhateverWeHaveAtXMs

lineGenerator = showWhateverWeHaveAtXMs(lineGenerator, timeoutValue!);

Expand Down
11 changes: 10 additions & 1 deletion core/util/posthog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,21 @@ export class Telemetry {
}
}

private static featureValueCache: Record<string, any> = {};

static async getFeatureFlag(flag: PosthogFeatureFlag) {
return Telemetry.client?.getFeatureFlag(flag, Telemetry.uniqueId);
const value = Telemetry.client?.getFeatureFlag(flag, Telemetry.uniqueId);

Telemetry.featureValueCache[flag] = value;
return value;
}

static async getValueForFeatureFlag(flag: PosthogFeatureFlag) {
try {
if (Telemetry.featureValueCache[flag]) {
return Telemetry.featureValueCache[flag];
}

const userGroup = await Telemetry.getFeatureFlag(flag);
if (typeof userGroup === "string") {
return EXPERIMENTS[flag][userGroup].value;
Expand Down
1 change: 1 addition & 0 deletions extensions/vscode/package-lock.json

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

10 changes: 7 additions & 3 deletions extensions/vscode/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,10 @@ async function processDiff(
numDiffs: 0,
});
}

if (action === "accept") {
await sidebar.webviewProtocol.request("exitEditMode", undefined);
}
}

function waitForSidebarReady(
Expand Down Expand Up @@ -742,8 +746,8 @@ const getCommandsMap: (
return;
}

// Clear the sidebar to prevent overwriting changes made in fullscreen
vscode.commands.executeCommand("continue.newSession")
// Clear the sidebar to prevent overwriting changes made in fullscreen
vscode.commands.executeCommand("continue.newSession");

// Full screen not open - open it
captureCommandTelemetry("openFullScreen");
Expand Down Expand Up @@ -777,7 +781,7 @@ const getCommandsMap: (
sessionId,
);
}
sessionLoader.dispose()
sessionLoader.dispose();
});

// When panel closes, reset the webview and focus
Expand Down
9 changes: 6 additions & 3 deletions extensions/vscode/src/diff/vertical/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import {
redDecorationType,
} from "./decorations";

import type { VerticalDiffCodeLens } from "./manager";
import type { ApplyState, DiffLine } from "core";
import type { VerticalDiffCodeLens } from "./manager";

export interface VerticalDiffHandlerOptions {
input?: string;
Expand Down Expand Up @@ -486,9 +486,12 @@ export class VerticalDiffHandler implements vscode.Disposable {
* we have received all of the diff lines.
*/
async reapplyWithMeyersDiff(diffLines: DiffLine[]) {
// Diff is messed up without this delay.
await new Promise((resolve) => setTimeout(resolve, 100));

// First, we reset the original diff by rejecting all pending diff blocks
for (const block of this.editorToVerticalDiffCodeLens.get(this.fileUri) ??
[]) {
const blocks = this.editorToVerticalDiffCodeLens.get(this.fileUri) ?? [];
for (const block of blocks.reverse()) {
await this.acceptRejectBlock(
false,
block.start,
Expand Down
2 changes: 1 addition & 1 deletion extensions/vscode/src/webviewProtocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export class VsCodeWebviewProtocol
status: "success",
});
} else {
respond({ done: true, content: response || {}, status: "success" });
respond({ done: true, content: response ?? {}, status: "success" });
}
} catch (e: any) {
respond({ done: true, error: e.message, status: "error" });
Expand Down
1 change: 1 addition & 0 deletions gui/package-lock.json

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

Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import { ChevronDownIcon } from "@heroicons/react/24/outline";
import { inferResolvedUriFromRelativePath } from "core/util/ideUtils";
import { debounce } from "lodash";
import { useContext, useEffect, useRef, useState } from "react";
import styled from "styled-components";
import { v4 as uuidv4 } from "uuid";
import { defaultBorderRadius, lightGray, vscEditorBackground } from "../..";
import { lightGray, vscEditorBackground } from "../..";
import { IdeMessengerContext } from "../../../context/IdeMessenger";
import { useWebviewListener } from "../../../hooks/useWebviewListener";
import { useAppSelector } from "../../../redux/hooks";
import { selectDefaultModel } from "../../../redux/slices/configSlice";
import {
selectApplyStateByStreamId,
selectIsInEditMode,
} from "../../../redux/slices/sessionSlice";
import { getFontSize } from "../../../util";
import { childrenToText, isTerminalCodeBlock } from "../utils";
import ApplyActions from "./ApplyActions";
import CopyButton from "./CopyButton";
import FileInfo from "./FileInfo";
import GeneratingCodeLoader from "./GeneratingCodeLoader";
import RunInTerminalButton from "./RunInTerminalButton";
import { useAppSelector } from "../../../redux/hooks";
import { selectDefaultModel } from "../../../redux/slices/configSlice";
import {
selectApplyStateByStreamId,
selectIsInEditMode,
} from "../../../redux/slices/sessionSlice";
import { inferResolvedUriFromRelativePath } from "core/util/ideUtils";

const TopDiv = styled.div`
outline: 0.5px solid rgba(153, 153, 152);
Expand Down Expand Up @@ -94,11 +94,21 @@ export default function StepContainerPreToolbar(
return;
}

const fileUri = await inferResolvedUriFromRelativePath(
let fileUri = await inferResolvedUriFromRelativePath(
props.relativeFilepath,
ideMessenger.ide,
);

// Sometimes the model will decide to only output the base name
// in which case we shouldn't create a new file if it matches the current file
const exists = await ideMessenger.ide.fileExists(fileUri);
if (!exists) {
const activeFile = await ideMessenger.ide.getCurrentFile();
if (activeFile && activeFile.path.endsWith(props.relativeFilepath)) {
fileUri = activeFile.path;
}
}

ideMessenger.post("applyToFile", {
streamId: streamIdRef.current,
filepath: fileUri,
Expand Down
53 changes: 21 additions & 32 deletions gui/src/components/markdown/StyledMarkdownPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,30 @@ import rehypeKatex from "rehype-katex";
import remarkMath from "remark-math";
import styled from "styled-components";
import { visit } from "unist-util-visit";
import { v4 as uuidv4 } from "uuid";
import {
defaultBorderRadius,
vscBackground,
vscEditorBackground,
vscForeground,
} from "..";
import useUpdatingRef from "../../hooks/useUpdatingRef";
import { useAppSelector } from "../../redux/hooks";
import { selectUIConfig } from "../../redux/slices/configSlice";
import { getContextItemsFromHistory } from "../../redux/thunks/updateFileSymbols";
import { getFontSize, isJetBrains } from "../../util";
import { ToolTip } from "../gui/Tooltip";
import FilenameLink from "./FilenameLink";
import "./katex.css";
import "./markdown.css";
import StepContainerPreActionButtons from "./StepContainerPreActionButtons";
import StepContainerPreToolbar from "./StepContainerPreToolbar";
import SymbolLink from "./SymbolLink";
import useUpdatingRef from "../../hooks/useUpdatingRef";
import { remarkTables } from "./utils/remarkTables";
import { SyntaxHighlightedPre } from "./SyntaxHighlightedPre";
import { patchNestedMarkdown } from "./utils/patchNestedMarkdown";
import { useAppSelector } from "../../redux/hooks";
import { isSymbolNotRif, matchCodeToSymbolOrFile } from "./utils";
import { fixDoubleDollarNewLineLatex } from "./utils/fixDoubleDollarLatex";
import { selectUIConfig } from "../../redux/slices/configSlice";
import { ToolTip } from "../gui/Tooltip";
import { v4 as uuidv4 } from "uuid";
import { ContextItemWithId, RangeInFileWithContents } from "core";
import { getContextItemsFromHistory } from "../../redux/thunks/updateFileSymbols";
import { patchNestedMarkdown } from "./utils/patchNestedMarkdown";
import { remarkTables } from "./utils/remarkTables";

const StyledMarkdown = styled.div<{
fontSize?: number;
Expand Down Expand Up @@ -301,30 +301,19 @@ const StyledMarkdownPreview = memo(function StyledMarkdownPreview(
if (content) {
const { symbols, rifs } = pastFileInfoRef.current;

// Insert file links for matching previous context items
// With some reasonable limitations on what might be a filename
if (rifs.length && content.includes(".") && content.length > 2) {
const match = rifs.find(
(rif) => rif.filepath.split("/").pop() === content, // Exact match for last segment of URI
);

if (match) {
return <FilenameLink rif={match} />;
}
}

// Insert symbols for exact matches
const exactSymbol = symbols.find((s) => s.name === content);
if (exactSymbol) {
return <SymbolLink content={content} symbol={exactSymbol} />;
}

// Partial matches - this is the case where the llm returns e.g. `subtract(number)` instead of `subtract`
const partialSymbol = symbols.find((s) =>
content.startsWith(s.name),
const matchedSymbolOrFile = matchCodeToSymbolOrFile(
content,
symbols,
rifs,
);
if (partialSymbol) {
return <SymbolLink content={content} symbol={partialSymbol} />;
if (matchedSymbolOrFile) {
if (isSymbolNotRif(matchedSymbolOrFile)) {
return (
<SymbolLink content={content} symbol={matchedSymbolOrFile} />
);
} else {
return <FilenameLink rif={matchedSymbolOrFile} />;
}
}
}
return <code {...codeProps}>{codeProps.children}</code>;
Expand Down
38 changes: 38 additions & 0 deletions gui/src/components/markdown/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { RangeInFileWithContents, SymbolWithRange } from "core";

const terminalLanguages = ["bash", "sh"];
const commonTerminalCommands = [
"npm",
Expand Down Expand Up @@ -52,3 +54,39 @@ function childToText(child: any): string {
export function childrenToText(children: any) {
return children.map((child: any) => childToText(child)).join("");
}

export function matchCodeToSymbolOrFile(
content: string,
symbols: SymbolWithRange[],
rifs: RangeInFileWithContents[],
): SymbolWithRange | RangeInFileWithContents | undefined {
// Insert file links for matching previous context items
// With some reasonable limitations on what might be a filename
if (rifs.length && content.includes(".") && content.length > 2) {
const match = rifs.find(
(rif) => rif.filepath.split("/").pop() === content, // Exact match for last segment of URI
);

if (match) {
return match;
}
}

// Insert symbols for exact matches
const exactSymbol = symbols.find((s) => s.name === content);
if (exactSymbol) {
return exactSymbol;
}

// Partial matches - this is the case where the llm returns e.g. `subtract(number)` instead of `subtract`
const partialSymbol = symbols.find((s) => content.startsWith(s.name));
if (partialSymbol) {
return partialSymbol;
}
}

export function isSymbolNotRif(
item: SymbolWithRange | RangeInFileWithContents,
): item is SymbolWithRange {
return (item as SymbolWithRange).type !== undefined;
}
Loading