Improve check error performance by off-loading to worker thread w/ incremental compilation (#575)

This commit is contained in:
Will Chen
2025-07-07 12:47:33 -07:00
committed by GitHub
parent 97b5c29f11
commit bc38f9b2d7
22 changed files with 695 additions and 396 deletions

View File

@@ -15,149 +15,21 @@ import {
executeSupabaseSql,
} from "../../supabase_admin/supabase_management_client";
import { isServerFunction } from "../../supabase_admin/supabase_utils";
import { SqlQuery, UserSettings } from "../../lib/schemas";
import { UserSettings } from "../../lib/schemas";
import { gitCommit } from "../utils/git_utils";
import { readSettings } from "@/main/settings";
import { writeMigrationFile } from "../utils/file_utils";
import { normalizePath } from "./normalizePath";
import {
getDyadWriteTags,
getDyadRenameTags,
getDyadDeleteTags,
getDyadAddDependencyTags,
getDyadExecuteSqlTags,
} from "../utils/dyad_tag_parser";
const readFile = fs.promises.readFile;
const logger = log.scope("response_processor");
export function getDyadWriteTags(fullResponse: string): {
path: string;
content: string;
description?: string;
}[] {
const dyadWriteRegex = /<dyad-write([^>]*)>([\s\S]*?)<\/dyad-write>/gi;
const pathRegex = /path="([^"]+)"/;
const descriptionRegex = /description="([^"]+)"/;
let match;
const tags: { path: string; content: string; description?: string }[] = [];
while ((match = dyadWriteRegex.exec(fullResponse)) !== null) {
const attributesString = match[1];
let content = match[2].trim();
const pathMatch = pathRegex.exec(attributesString);
const descriptionMatch = descriptionRegex.exec(attributesString);
if (pathMatch && pathMatch[1]) {
const path = pathMatch[1];
const description = descriptionMatch?.[1];
const contentLines = content.split("\n");
if (contentLines[0]?.startsWith("```")) {
contentLines.shift();
}
if (contentLines[contentLines.length - 1]?.startsWith("```")) {
contentLines.pop();
}
content = contentLines.join("\n");
tags.push({ path: normalizePath(path), content, description });
} else {
logger.warn(
"Found <dyad-write> tag without a valid 'path' attribute:",
match[0],
);
}
}
return tags;
}
export function getDyadRenameTags(fullResponse: string): {
from: string;
to: string;
}[] {
const dyadRenameRegex =
/<dyad-rename from="([^"]+)" to="([^"]+)"[^>]*>([\s\S]*?)<\/dyad-rename>/g;
let match;
const tags: { from: string; to: string }[] = [];
while ((match = dyadRenameRegex.exec(fullResponse)) !== null) {
tags.push({
from: normalizePath(match[1]),
to: normalizePath(match[2]),
});
}
return tags;
}
export function getDyadDeleteTags(fullResponse: string): string[] {
const dyadDeleteRegex =
/<dyad-delete path="([^"]+)"[^>]*>([\s\S]*?)<\/dyad-delete>/g;
let match;
const paths: string[] = [];
while ((match = dyadDeleteRegex.exec(fullResponse)) !== null) {
paths.push(normalizePath(match[1]));
}
return paths;
}
export function getDyadAddDependencyTags(fullResponse: string): string[] {
const dyadAddDependencyRegex =
/<dyad-add-dependency packages="([^"]+)">[^<]*<\/dyad-add-dependency>/g;
let match;
const packages: string[] = [];
while ((match = dyadAddDependencyRegex.exec(fullResponse)) !== null) {
packages.push(...match[1].split(" "));
}
return packages;
}
export function getDyadChatSummaryTag(fullResponse: string): string | null {
const dyadChatSummaryRegex =
/<dyad-chat-summary>([\s\S]*?)<\/dyad-chat-summary>/g;
const match = dyadChatSummaryRegex.exec(fullResponse);
if (match && match[1]) {
return match[1].trim();
}
return null;
}
export function getDyadExecuteSqlTags(fullResponse: string): SqlQuery[] {
const dyadExecuteSqlRegex =
/<dyad-execute-sql([^>]*)>([\s\S]*?)<\/dyad-execute-sql>/g;
const descriptionRegex = /description="([^"]+)"/;
let match;
const queries: { content: string; description?: string }[] = [];
while ((match = dyadExecuteSqlRegex.exec(fullResponse)) !== null) {
const attributesString = match[1] || "";
let content = match[2].trim();
const descriptionMatch = descriptionRegex.exec(attributesString);
const description = descriptionMatch?.[1];
// Handle markdown code blocks if present
const contentLines = content.split("\n");
if (contentLines[0]?.startsWith("```")) {
contentLines.shift();
}
if (contentLines[contentLines.length - 1]?.startsWith("```")) {
contentLines.pop();
}
content = contentLines.join("\n");
queries.push({ content, description });
}
return queries;
}
export function getDyadCommandTags(fullResponse: string): string[] {
const dyadCommandRegex =
/<dyad-command type="([^"]+)"[^>]*><\/dyad-command>/g;
let match;
const commands: string[] = [];
while ((match = dyadCommandRegex.exec(fullResponse)) !== null) {
commands.push(match[1]);
}
return commands;
}
interface Output {
message: string;
error: unknown;