Run prettier on everything (#104)

This commit is contained in:
Will Chen
2025-05-06 23:02:28 -07:00
committed by GitHub
parent 744ea68ac8
commit 0d56651220
168 changed files with 1980 additions and 1907 deletions

View File

@@ -74,7 +74,7 @@ async function executeAppLocalNode({
shell: true,
stdio: "pipe", // Ensure stdio is piped so we can capture output/errors and detect close
detached: false, // Ensure child process is attached to the main process lifecycle unless explicitly backgrounded
}
},
);
// Check if process spawned correctly
@@ -86,7 +86,7 @@ async function executeAppLocalNode({
throw new Error(
`Failed to spawn process for app ${appId}. Error: ${
errorOutput || "Unknown spawn error"
}`
}`,
);
}
@@ -118,7 +118,7 @@ async function executeAppLocalNode({
// Handle process exit/close
process.on("close", (code, signal) => {
logger.log(
`App ${appId} (PID: ${process.pid}) process closed with code ${code}, signal ${signal}.`
`App ${appId} (PID: ${process.pid}) process closed with code ${code}, signal ${signal}.`,
);
removeAppIfCurrentProcess(appId, process);
});
@@ -126,7 +126,7 @@ async function executeAppLocalNode({
// Handle errors during process lifecycle (e.g., command not found)
process.on("error", (err) => {
logger.error(
`Error in app ${appId} (PID: ${process.pid}) process: ${err.message}`
`Error in app ${appId} (PID: ${process.pid}) process: ${err.message}`,
);
removeAppIfCurrentProcess(appId, process);
// Note: We don't throw here as the error is asynchronous. The caller got a success response already.
@@ -173,7 +173,7 @@ export function registerAppHandlers() {
// Copy scaffold asynchronously
await copyDirectoryRecursive(
path.join(__dirname, "..", "..", "scaffold"),
fullAppPath
fullAppPath,
);
// Initialize git repo and create first commit
await git.init({
@@ -285,7 +285,7 @@ export function registerAppHandlers() {
logger.error(`Error reading file ${filePath} for app ${appId}:`, error);
throw new Error("Failed to read file");
}
}
},
);
ipcMain.handle("get-env-vars", async () => {
@@ -300,7 +300,7 @@ export function registerAppHandlers() {
"run-app",
async (
event: Electron.IpcMainInvokeEvent,
{ appId }: { appId: number }
{ appId }: { appId: number },
) => {
return withLock(appId, async () => {
// Check if app is already running
@@ -337,19 +337,19 @@ export function registerAppHandlers() {
throw new Error(`Failed to run app ${appId}: ${error.message}`);
}
});
}
},
);
ipcMain.handle("stop-app", async (_, { appId }: { appId: number }) => {
logger.log(
`Attempting to stop app ${appId}. Current running apps: ${runningApps.size}`
`Attempting to stop app ${appId}. Current running apps: ${runningApps.size}`,
);
return withLock(appId, async () => {
const appInfo = runningApps.get(appId);
if (!appInfo) {
logger.log(
`App ${appId} not found in running apps map. Assuming already stopped.`
`App ${appId} not found in running apps map. Assuming already stopped.`,
);
return {
success: true,
@@ -359,13 +359,13 @@ export function registerAppHandlers() {
const { process, processId } = appInfo;
logger.log(
`Found running app ${appId} with processId ${processId} (PID: ${process.pid}). Attempting to stop.`
`Found running app ${appId} with processId ${processId} (PID: ${process.pid}). Attempting to stop.`,
);
// Check if the process is already exited or closed
if (process.exitCode !== null || process.signalCode !== null) {
logger.log(
`Process for app ${appId} (PID: ${process.pid}) already exited (code: ${process.exitCode}, signal: ${process.signalCode}). Cleaning up map.`
`Process for app ${appId} (PID: ${process.pid}) already exited (code: ${process.exitCode}, signal: ${process.signalCode}). Cleaning up map.`,
);
runningApps.delete(appId); // Ensure cleanup if somehow missed
return { success: true, message: "Process already exited." };
@@ -382,7 +382,7 @@ export function registerAppHandlers() {
} catch (error: any) {
logger.error(
`Error stopping app ${appId} (PID: ${process.pid}, processId: ${processId}):`,
error
error,
);
// Attempt cleanup even if an error occurred during the stop process
removeAppIfCurrentProcess(appId, process);
@@ -398,7 +398,7 @@ export function registerAppHandlers() {
{
appId,
removeNodeModules,
}: { appId: number; removeNodeModules?: boolean }
}: { appId: number; removeNodeModules?: boolean },
) => {
logger.log(`Restarting app ${appId}`);
return withLock(appId, async () => {
@@ -408,7 +408,7 @@ export function registerAppHandlers() {
if (appInfo) {
const { process, processId } = appInfo;
logger.log(
`Stopping app ${appId} (processId ${processId}) before restart`
`Stopping app ${appId} (processId ${processId}) before restart`,
);
await killProcess(process);
@@ -435,7 +435,7 @@ export function registerAppHandlers() {
if (removeNodeModules) {
const nodeModulesPath = path.join(appPath, "node_modules");
logger.log(
`Removing node_modules for app ${appId} at ${nodeModulesPath}`
`Removing node_modules for app ${appId} at ${nodeModulesPath}`,
);
if (fs.existsSync(nodeModulesPath)) {
await fsPromises.rm(nodeModulesPath, {
@@ -449,7 +449,7 @@ export function registerAppHandlers() {
}
logger.debug(
`Executing app ${appId} in path ${app.path} after restart request`
`Executing app ${appId} in path ${app.path} after restart request`,
); // Adjusted log
await executeApp({ appPath, appId, event }); // This will handle starting either mode
@@ -460,7 +460,7 @@ export function registerAppHandlers() {
throw error;
}
});
}
},
);
ipcMain.handle(
@@ -471,7 +471,7 @@ export function registerAppHandlers() {
appId,
filePath,
content,
}: { appId: number; filePath: string; content: string }
}: { appId: number; filePath: string; content: string },
) => {
const app = await db.query.apps.findFirst({
where: eq(apps.id, appId),
@@ -517,7 +517,7 @@ export function registerAppHandlers() {
logger.error(`Error writing file ${filePath} for app ${appId}:`, error);
throw new Error(`Failed to write file: ${error.message}`);
}
}
},
);
ipcMain.handle("delete-app", async (_, { appId }: { appId: number }) => {
@@ -575,7 +575,7 @@ export function registerAppHandlers() {
appId,
appName,
appPath,
}: { appId: number; appName: string; appPath: string }
}: { appId: number; appName: string; appPath: string },
) => {
return withLock(appId, async () => {
// Check if app exists
@@ -613,7 +613,7 @@ export function registerAppHandlers() {
} catch (error: any) {
logger.error(`Error stopping app ${appId} before renaming:`, error);
throw new Error(
`Failed to stop app before renaming: ${error.message}`
`Failed to stop app before renaming: ${error.message}`,
);
}
}
@@ -627,7 +627,7 @@ export function registerAppHandlers() {
// Check if destination directory already exists
if (fs.existsSync(newAppPath)) {
throw new Error(
`Destination path '${newAppPath}' already exists`
`Destination path '${newAppPath}' already exists`,
);
}
@@ -641,7 +641,7 @@ export function registerAppHandlers() {
} catch (error: any) {
logger.error(
`Error moving app files from ${oldAppPath} to ${newAppPath}:`,
error
error,
);
throw new Error(`Failed to move app files: ${error.message}`);
}
@@ -667,7 +667,7 @@ export function registerAppHandlers() {
} catch (rollbackError) {
logger.error(
`Failed to rollback file move during rename error:`,
rollbackError
rollbackError,
);
}
}
@@ -676,7 +676,7 @@ export function registerAppHandlers() {
throw new Error(`Failed to update app in database: ${error.message}`);
}
});
}
},
);
ipcMain.handle("reset-all", async () => {

View File

@@ -52,7 +52,7 @@ export function registerChatHandlers() {
"for app:",
appId,
"with initial commit hash:",
initialCommitHash
initialCommitHash,
);
return chat.id;
});
@@ -101,7 +101,7 @@ export function registerChatHandlers() {
const allChats = await query;
return allChats;
}
},
);
ipcMain.handle("delete-chat", async (_, chatId: number) => {

View File

@@ -124,7 +124,7 @@ export function registerChatStreamHandlers() {
await db
.delete(messages)
.where(
eq(messages.id, chatMessages[lastUserMessageIndex + 1].id)
eq(messages.id, chatMessages[lastUserMessageIndex + 1].id),
);
}
}
@@ -220,7 +220,7 @@ export function registerChatStreamHandlers() {
req.chatId,
testResponse,
abortController,
updatedChat
updatedChat,
);
} else {
// Normal AI processing for non-test prompts
@@ -242,7 +242,7 @@ export function registerChatStreamHandlers() {
"codebaseInfo: length",
codebaseInfo.length,
"estimated tokens",
codebaseInfo.length / 4
codebaseInfo.length / 4,
);
// Prepare message history for the AI
@@ -266,7 +266,7 @@ export function registerChatStreamHandlers() {
systemPrompt += "\n\n" + SUPABASE_NOT_AVAILABLE_SYSTEM_PROMPT;
}
const isSummarizeIntent = req.prompt.startsWith(
"Summarize from chat-id="
"Summarize from chat-id=",
);
if (isSummarizeIntent) {
systemPrompt = SUMMARIZE_CHAT_SYSTEM_PROMPT;
@@ -276,7 +276,7 @@ export function registerChatStreamHandlers() {
const hasImageAttachments =
req.attachments &&
req.attachments.some((attachment) =>
attachment.type.startsWith("image/")
attachment.type.startsWith("image/"),
);
if (hasImageAttachments) {
@@ -316,7 +316,7 @@ This conversation includes one or more image attachments. When the user uploads
// Replace the last message with one that includes attachments
chatMessages[lastUserIndex] = await prepareMessageWithAttachments(
lastUserMessage,
attachmentPaths
attachmentPaths,
);
}
}
@@ -353,7 +353,7 @@ This conversation includes one or more image attachments. When the user uploads
(error as any)?.error?.message || JSON.stringify(error);
event.sender.send(
"chat:response:error",
`Sorry, there was an error from the AI: ${message}`
`Sorry, there was an error from the AI: ${message}`,
);
// Clean up the abort controller
activeStreams.delete(req.chatId);
@@ -374,7 +374,7 @@ This conversation includes one or more image attachments. When the user uploads
});
fullResponse = fullResponse.replace(
"$$SUPABASE_CLIENT_CODE$$",
supabaseClientCode
supabaseClientCode,
);
}
// Store the current partial response
@@ -421,13 +421,13 @@ This conversation includes one or more image attachments. When the user uploads
.where(eq(messages.id, placeholderAssistantMessage.id));
logger.log(
`Updated cancelled response for placeholder message ${placeholderAssistantMessage.id} in chat ${chatId}`
`Updated cancelled response for placeholder message ${placeholderAssistantMessage.id} in chat ${chatId}`,
);
partialResponses.delete(req.chatId);
} catch (error) {
logger.error(
`Error saving partial response for chat ${chatId}:`,
error
error,
);
}
}
@@ -441,7 +441,7 @@ This conversation includes one or more image attachments. When the user uploads
if (!abortController.signal.aborted && fullResponse) {
// Scrape from: <dyad-chat-summary>Renaming profile file</dyad-chat-title>
const chatTitle = fullResponse.match(
/<dyad-chat-summary>(.*?)<\/dyad-chat-summary>/
/<dyad-chat-summary>(.*?)<\/dyad-chat-summary>/,
);
if (chatTitle) {
await db
@@ -461,7 +461,7 @@ This conversation includes one or more image attachments. When the user uploads
const status = await processFullResponseActions(
fullResponse,
req.chatId,
{ chatSummary, messageId: placeholderAssistantMessage.id } // Use placeholder ID
{ chatSummary, messageId: placeholderAssistantMessage.id }, // Use placeholder ID
);
const chat = await db.query.chats.findFirst({
@@ -481,7 +481,7 @@ This conversation includes one or more image attachments. When the user uploads
if (status.error) {
event.sender.send(
"chat:response:error",
`Sorry, there was an error applying the AI's changes: ${status.error}`
`Sorry, there was an error applying the AI's changes: ${status.error}`,
);
}
@@ -505,12 +505,15 @@ This conversation includes one or more image attachments. When the user uploads
try {
// We don't immediately delete files because they might be needed for reference
// Instead, schedule them for deletion after some time
setTimeout(async () => {
if (fs.existsSync(filePath)) {
await unlink(filePath);
logger.log(`Deleted temporary file: ${filePath}`);
}
}, 30 * 60 * 1000); // Delete after 30 minutes
setTimeout(
async () => {
if (fs.existsSync(filePath)) {
await unlink(filePath);
logger.log(`Deleted temporary file: ${filePath}`);
}
},
30 * 60 * 1000,
); // Delete after 30 minutes
} catch (error) {
logger.error(`Error scheduling file deletion: ${error}`);
}
@@ -523,7 +526,7 @@ This conversation includes one or more image attachments. When the user uploads
logger.error("Error calling LLM:", error);
event.sender.send(
"chat:response:error",
`Sorry, there was an error processing your request: ${error}`
`Sorry, there was an error processing your request: ${error}`,
);
// Clean up the abort controller
activeStreams.delete(req.chatId);
@@ -555,7 +558,7 @@ This conversation includes one or more image attachments. When the user uploads
}
export function formatMessages(
messages: { role: string; content: string | undefined }[]
messages: { role: string; content: string | undefined }[],
) {
return messages
.map((m) => `<message role="${m.role}">${m.content}</message>`)
@@ -566,7 +569,7 @@ export function formatMessages(
async function replaceTextAttachmentWithContent(
text: string,
filePath: string,
fileName: string
fileName: string,
): Promise<string> {
try {
if (await isTextFile(filePath)) {
@@ -577,16 +580,16 @@ async function replaceTextAttachmentWithContent(
const escapedPath = filePath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const tagPattern = new RegExp(
`<dyad-text-attachment filename="[^"]*" type="[^"]*" path="${escapedPath}">\\s*<\\/dyad-text-attachment>`,
"g"
"g",
);
const replacedText = text.replace(
tagPattern,
`Full content of ${fileName}:\n\`\`\`\n${fullContent}\n\`\`\``
`Full content of ${fileName}:\n\`\`\`\n${fullContent}\n\`\`\``,
);
logger.log(
`Replaced text attachment content for: ${fileName} - length before: ${text.length} - length after: ${replacedText.length}`
`Replaced text attachment content for: ${fileName} - length before: ${text.length} - length after: ${replacedText.length}`,
);
return replacedText;
}
@@ -600,13 +603,13 @@ async function replaceTextAttachmentWithContent(
// Helper function to convert traditional message to one with proper image attachments
async function prepareMessageWithAttachments(
message: CoreMessage,
attachmentPaths: string[]
attachmentPaths: string[],
): Promise<CoreMessage> {
let textContent = message.content;
// Get the original text content
if (typeof textContent !== "string") {
logger.warn(
"Message content is not a string - shouldn't happen but using message as-is"
"Message content is not a string - shouldn't happen but using message as-is",
);
return message;
}
@@ -617,7 +620,7 @@ async function prepareMessageWithAttachments(
textContent = await replaceTextAttachmentWithContent(
textContent,
filePath,
fileName
fileName,
);
}

View File

@@ -91,7 +91,7 @@ export function registerDebugHandlers() {
async (): Promise<SystemDebugInfo> => {
console.log("IPC: get-system-debug-info called");
return getSystemDebugInfo();
}
},
);
ipcMain.handle(
@@ -151,7 +151,7 @@ export function registerDebugHandlers() {
console.error(`Error in get-chat-logs:`, error);
throw error;
}
}
},
);
console.log("Registered debug IPC handlers");

View File

@@ -10,7 +10,7 @@ export function registerDependencyHandlers() {
"chat:add-dep",
async (
_event,
{ chatId, packages }: { chatId: number; packages: string[] }
{ chatId, packages }: { chatId: number; packages: string[] },
) => {
// Find the message from the database
const foundMessages = await db.query.messages.findMany({
@@ -39,13 +39,13 @@ export function registerDependencyHandlers() {
.reverse()
.find((m) =>
m.content.includes(
`<dyad-add-dependency packages="${packages.join(" ")}">`
)
`<dyad-add-dependency packages="${packages.join(" ")}">`,
),
);
if (!message) {
throw new Error(
`Message with packages ${packages.join(", ")} not found`
`Message with packages ${packages.join(", ")} not found`,
);
}
@@ -54,6 +54,6 @@ export function registerDependencyHandlers() {
message,
appPath: getDyadAppPath(app.path),
});
}
},
);
}

View File

@@ -131,7 +131,7 @@ async function pollForAccessToken(event: IpcMainInvokeEvent) {
// Schedule next poll
currentFlowState.timeoutId = setTimeout(
() => pollForAccessToken(event),
interval * 1000
interval * 1000,
);
break;
case "slow_down":
@@ -143,7 +143,7 @@ async function pollForAccessToken(event: IpcMainInvokeEvent) {
});
currentFlowState.timeoutId = setTimeout(
() => pollForAccessToken(event),
newInterval * 1000
newInterval * 1000,
);
break;
case "expired_token":
@@ -162,7 +162,7 @@ async function pollForAccessToken(event: IpcMainInvokeEvent) {
break;
default:
logger.error(
`Unknown GitHub error: ${data.error_description || data.error}`
`Unknown GitHub error: ${data.error_description || data.error}`,
);
event.sender.send("github:flow-error", {
error: `GitHub authorization error: ${
@@ -202,7 +202,7 @@ function stopPolling() {
function handleStartGithubFlow(
event: IpcMainInvokeEvent,
args: { appId: number | null }
args: { appId: number | null },
) {
logger.debug(`Received github:start-flow for appId: ${args.appId}`);
@@ -249,7 +249,7 @@ function handleStartGithubFlow(
if (!res.ok) {
return res.json().then((errData) => {
throw new Error(
`GitHub API Error: ${errData.error_description || res.statusText}`
`GitHub API Error: ${errData.error_description || res.statusText}`,
);
});
}
@@ -273,7 +273,7 @@ function handleStartGithubFlow(
// Start polling after the initial interval
currentFlowState.timeoutId = setTimeout(
() => pollForAccessToken(event),
currentFlowState.interval * 1000
currentFlowState.interval * 1000,
);
})
.catch((error) => {
@@ -289,7 +289,7 @@ function handleStartGithubFlow(
// --- GitHub Repo Availability Handler ---
async function handleIsRepoAvailable(
event: IpcMainInvokeEvent,
{ org, repo }: { org: string; repo: string }
{ org, repo }: { org: string; repo: string },
) {
try {
// Get access token from settings
@@ -327,7 +327,7 @@ async function handleIsRepoAvailable(
// --- GitHub Create Repo Handler ---
async function handleCreateRepo(
event: IpcMainInvokeEvent,
{ org, repo, appId }: { org: string; repo: string; appId: number }
{ org, repo, appId }: { org: string; repo: string; appId: number },
) {
try {
// Get access token from settings
@@ -376,7 +376,7 @@ async function handleCreateRepo(
// --- GitHub Push Handler ---
async function handlePushToGithub(
event: IpcMainInvokeEvent,
{ appId }: { appId: number }
{ appId }: { appId: number },
) {
try {
// Get access token from settings
@@ -424,7 +424,7 @@ async function handlePushToGithub(
async function handleDisconnectGithubRepo(
event: IpcMainInvokeEvent,
{ appId }: { appId: number }
{ appId }: { appId: number },
) {
try {
logger.log(`Disconnecting GitHub repo for appId: ${appId}`);
@@ -464,6 +464,6 @@ export function registerGithubHandlers() {
ipcMain.handle("github:create-repo", handleCreateRepo);
ipcMain.handle("github:push", handlePushToGithub);
ipcMain.handle("github:disconnect", (event, args: { appId: number }) =>
handleDisconnectGithubRepo(event, args)
handleDisconnectGithubRepo(event, args),
);
}

View File

@@ -11,15 +11,17 @@ export interface LMStudioModel {
publisher: string;
state: "loaded" | "not-loaded";
max_context_length: number;
quantization: string
compatibility_type: string
quantization: string;
compatibility_type: string;
arch: string;
[key: string]: any;
}
export async function fetchLMStudioModels(): Promise<LocalModelListResponse> {
try {
const modelsResponse: Response = await fetch("http://localhost:1234/api/v0/models");
const modelsResponse: Response = await fetch(
"http://localhost:1234/api/v0/models",
);
if (!modelsResponse.ok) {
throw new Error("Failed to fetch models from LM Studio");
}
@@ -30,7 +32,7 @@ export async function fetchLMStudioModels(): Promise<LocalModelListResponse> {
.map((model: any) => ({
modelName: model.id,
displayName: model.id,
provider: "lmstudio"
provider: "lmstudio",
}));
logger.info(`Successfully fetched ${models.length} models from LM Studio`);
@@ -41,7 +43,10 @@ export async function fetchLMStudioModels(): Promise<LocalModelListResponse> {
}
export function registerLMStudioHandlers() {
ipcMain.handle('local-models:list-lmstudio', async (): Promise<LocalModelListResponse> => {
return fetchLMStudioModels();
});
}
ipcMain.handle(
"local-models:list-lmstudio",
async (): Promise<LocalModelListResponse> => {
return fetchLMStudioModels();
},
);
}

View File

@@ -31,12 +31,13 @@ export async function fetchOllamaModels(): Promise<LocalModelListResponse> {
const ollamaModels: OllamaModel[] = data.models || [];
const models: LocalModel[] = ollamaModels.map((model: OllamaModel) => {
const displayName = model.name.split(':')[0]
.replace(/-/g, ' ')
.replace(/(\d+)/, ' $1 ')
.split(' ')
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ')
const displayName = model.name
.split(":")[0]
.replace(/-/g, " ")
.replace(/(\d+)/, " $1 ")
.split(" ")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ")
.trim();
return {
@@ -45,14 +46,18 @@ export async function fetchOllamaModels(): Promise<LocalModelListResponse> {
provider: "ollama",
};
});
logger.info(`Successfully fetched ${models.length} models from Ollama`);
return { models, error: null };
logger.info(`Successfully fetched ${models.length} models from Ollama`);
return { models, error: null };
} catch (error) {
if (error instanceof TypeError && (error as Error).message.includes('fetch failed')) {
if (
error instanceof TypeError &&
(error as Error).message.includes("fetch failed")
) {
logger.error("Could not connect to Ollama");
return {
models: [],
error: "Could not connect to Ollama. Make sure it's running at http://localhost:11434"
error:
"Could not connect to Ollama. Make sure it's running at http://localhost:11434",
};
}
return { models: [], error: "Failed to fetch models from Ollama" };
@@ -60,7 +65,10 @@ export async function fetchOllamaModels(): Promise<LocalModelListResponse> {
}
export function registerOllamaHandlers() {
ipcMain.handle('local-models:list-ollama', async (): Promise<LocalModelListResponse> => {
return fetchOllamaModels();
});
}
ipcMain.handle(
"local-models:list-ollama",
async (): Promise<LocalModelListResponse> => {
return fetchOllamaModels();
},
);
}

View File

@@ -14,7 +14,7 @@ export function registerNodeHandlers() {
"handling ipc: nodejs-status for platform:",
platform(),
"and arch:",
arch()
arch(),
);
// Run checks in parallel
const [nodeVersion, pnpmVersion] = await Promise.all([
@@ -23,7 +23,7 @@ export function registerNodeHandlers() {
// If not, try to install it using corepack.
// If both fail, then pnpm is not available.
runShellCommand(
"pnpm --version || (corepack enable pnpm && pnpm --version) || (npm install -g pnpm@latest-10 && pnpm --version)"
"pnpm --version || (corepack enable pnpm && pnpm --version) || (npm install -g pnpm@latest-10 && pnpm --version)",
),
]);
// Default to mac download url.

View File

@@ -80,7 +80,7 @@ function cleanupExpiredCacheEntries() {
if (expiredCount > 0) {
logger.log(
`Cleaned up ${expiredCount} expired codebase token cache entries`
`Cleaned up ${expiredCount} expired codebase token cache entries`,
);
}
}
@@ -90,7 +90,7 @@ async function getCodebaseTokenCount(
chatId: number,
messageId: number,
messageContent: string,
appPath: string
appPath: string,
): Promise<number> {
// Clean up expired cache entries first
cleanupExpiredCacheEntries();
@@ -128,7 +128,7 @@ async function getCodebaseTokenCount(
const getProposalHandler = async (
_event: IpcMainInvokeEvent,
{ chatId }: { chatId: number }
{ chatId }: { chatId: number },
): Promise<ProposalResult | null> => {
return withLock("get-proposal:" + chatId, async () => {
logger.log(`IPC: get-proposal called for chatId: ${chatId}`);
@@ -152,7 +152,7 @@ const getProposalHandler = async (
) {
const messageId = latestAssistantMessage.id; // Get the message ID
logger.log(
`Found latest assistant message (ID: ${messageId}), parsing content...`
`Found latest assistant message (ID: ${messageId}), parsing content...`,
);
const messageContent = latestAssistantMessage.content;
@@ -211,7 +211,7 @@ const getProposalHandler = async (
"files=",
proposal.filesChanged.length,
"packages=",
proposal.packagesAdded.length
proposal.packagesAdded.length,
);
return {
@@ -221,19 +221,23 @@ const getProposalHandler = async (
};
} else {
logger.log(
"No relevant tags found in the latest assistant message content."
"No relevant tags found in the latest assistant message content.",
);
}
}
const actions: ActionProposal["actions"] = [];
if (latestAssistantMessage?.content) {
const writeTags = getDyadWriteTags(latestAssistantMessage.content);
const refactorTarget = writeTags.reduce((largest, tag) => {
const lineCount = tag.content.split("\n").length;
return lineCount > 500 && (!largest || lineCount > largest.lineCount)
? { path: tag.path, lineCount }
: largest;
}, null as { path: string; lineCount: number } | null);
const refactorTarget = writeTags.reduce(
(largest, tag) => {
const lineCount = tag.content.split("\n").length;
return lineCount > 500 &&
(!largest || lineCount > largest.lineCount)
? { path: tag.path, lineCount }
: largest;
},
null as { path: string; lineCount: number } | null,
);
if (refactorTarget) {
actions.push({
id: "refactor-file",
@@ -288,7 +292,7 @@ const getProposalHandler = async (
chatId,
latestAssistantMessage.id,
latestAssistantMessage.content || "",
chat.app.path
chat.app.path,
);
const totalTokens = messagesTokenCount + codebaseTokenCount;
@@ -296,13 +300,13 @@ const getProposalHandler = async (
logger.log(
`Token usage: ${totalTokens}/${contextWindow} (${
(totalTokens / contextWindow) * 100
}%)`
}%)`,
);
// If we're using more than 80% of the context window, suggest summarizing
if (totalTokens > contextWindow * 0.8) {
logger.log(
`Token usage high (${totalTokens}/${contextWindow}), suggesting summarize action`
`Token usage high (${totalTokens}/${contextWindow}), suggesting summarize action`,
);
actions.push({
id: "summarize-in-new-chat",
@@ -330,14 +334,14 @@ const getProposalHandler = async (
// Handler to approve a proposal (process actions and update message)
const approveProposalHandler = async (
_event: IpcMainInvokeEvent,
{ chatId, messageId }: { chatId: number; messageId: number }
{ chatId, messageId }: { chatId: number; messageId: number },
): Promise<{
success: boolean;
error?: string;
uncommittedFiles?: string[];
}> => {
logger.log(
`IPC: approve-proposal called for chatId: ${chatId}, messageId: ${messageId}`
`IPC: approve-proposal called for chatId: ${chatId}, messageId: ${messageId}`,
);
try {
@@ -346,7 +350,7 @@ const approveProposalHandler = async (
where: and(
eq(messages.id, messageId),
eq(messages.chatId, chatId),
eq(messages.role, "assistant")
eq(messages.role, "assistant"),
),
columns: {
content: true,
@@ -355,7 +359,7 @@ const approveProposalHandler = async (
if (!messageToApprove?.content) {
logger.error(
`Assistant message not found for chatId: ${chatId}, messageId: ${messageId}`
`Assistant message not found for chatId: ${chatId}, messageId: ${messageId}`,
);
return { success: false, error: "Assistant message not found." };
}
@@ -368,13 +372,13 @@ const approveProposalHandler = async (
{
chatSummary: chatSummary ?? undefined,
messageId,
} // Pass summary if found
}, // Pass summary if found
);
if (processResult.error) {
logger.error(
`Error processing actions for message ${messageId}:`,
processResult.error
processResult.error,
);
// Optionally: Update message state to 'error' or similar?
// For now, just return error to frontend
@@ -397,10 +401,10 @@ const approveProposalHandler = async (
// Handler to reject a proposal (just update message state)
const rejectProposalHandler = async (
_event: IpcMainInvokeEvent,
{ chatId, messageId }: { chatId: number; messageId: number }
{ chatId, messageId }: { chatId: number; messageId: number },
): Promise<{ success: boolean; error?: string }> => {
logger.log(
`IPC: reject-proposal called for chatId: ${chatId}, messageId: ${messageId}`
`IPC: reject-proposal called for chatId: ${chatId}, messageId: ${messageId}`,
);
try {
@@ -409,14 +413,14 @@ const rejectProposalHandler = async (
where: and(
eq(messages.id, messageId),
eq(messages.chatId, chatId),
eq(messages.role, "assistant")
eq(messages.role, "assistant"),
),
columns: { id: true },
});
if (!messageToReject) {
logger.error(
`Assistant message not found for chatId: ${chatId}, messageId: ${messageId}`
`Assistant message not found for chatId: ${chatId}, messageId: ${messageId}`,
);
return { success: false, error: "Assistant message not found." };
}

View File

@@ -15,7 +15,7 @@ export function registerSettingsHandlers() {
if (
Object.prototype.hasOwnProperty.call(
settings.providerSettings,
providerKey
providerKey,
)
) {
const providerSetting = settings.providerSettings[providerKey];
@@ -35,6 +35,6 @@ export function registerSettingsHandlers() {
async (_, settings: Partial<UserSettings>) => {
writeSettings(settings);
return readSettings();
}
},
);
}

View File

@@ -39,7 +39,7 @@ export function registerSupabaseHandlers() {
logger.error("Error setting Supabase project for app:", error);
throw error;
}
}
},
);
// Unset app project - removes the link between a Dyad app and a Supabase project
@@ -58,6 +58,6 @@ export function registerSupabaseHandlers() {
logger.error("Error unsetting Supabase project for app:", error);
throw error;
}
}
},
);
}

View File

@@ -46,7 +46,7 @@ export async function streamTestResponse(
chatId: number,
testResponse: string,
abortController: AbortController,
updatedChat: any
updatedChat: any,
): Promise<string> {
console.log(`Using canned response for test prompt`);

View File

@@ -62,7 +62,7 @@ export function registerTokenCountHandlers() {
}
const systemPromptTokens = estimateTokens(
systemPrompt + supabaseContext
systemPrompt + supabaseContext,
);
// Extract codebase information if app is associated with the chat
@@ -75,7 +75,7 @@ export function registerTokenCountHandlers() {
codebaseInfo = await extractCodebase(appPath);
codebaseTokens = estimateTokens(codebaseInfo);
logger.log(
`Extracted codebase information from ${appPath}, tokens: ${codebaseTokens}`
`Extracted codebase information from ${appPath}, tokens: ${codebaseTokens}`,
);
} catch (error) {
logger.error("Error extracting codebase:", error);
@@ -101,6 +101,6 @@ export function registerTokenCountHandlers() {
logger.error("Error counting tokens:", error);
throw error;
}
}
},
);
}

View File

@@ -39,7 +39,7 @@ export function registerUploadHandlers() {
if (!response.ok) {
throw new Error(
`Upload failed with status ${response.status}: ${response.statusText}`
`Upload failed with status ${response.status}: ${response.statusText}`,
);
}
@@ -52,7 +52,7 @@ export function registerUploadHandlers() {
error: error instanceof Error ? error.message : String(error),
};
}
}
},
);
logger.debug("Registered upload IPC handlers");

View File

@@ -95,14 +95,17 @@ export function registerVersionHandlers() {
errorMessage: `Failed to get current branch: ${error.message}`,
};
}
}
},
);
ipcMain.handle(
"revert-version",
async (
_,
{ appId, previousVersionId }: { appId: number; previousVersionId: string }
{
appId,
previousVersionId,
}: { appId: number; previousVersionId: string },
) => {
return withLock(appId, async () => {
const app = await db.query.apps.findFirst({
@@ -198,13 +201,13 @@ export function registerVersionHandlers() {
const messagesToDelete = await db.query.messages.findMany({
where: and(
eq(messages.chatId, chatId),
gt(messages.id, messageWithCommit.id)
gt(messages.id, messageWithCommit.id),
),
orderBy: desc(messages.id),
});
logger.log(
`Deleting ${messagesToDelete.length} messages after commit ${previousVersionId} from chat ${chatId}`
`Deleting ${messagesToDelete.length} messages after commit ${previousVersionId} from chat ${chatId}`,
);
// Delete the messages
@@ -214,8 +217,8 @@ export function registerVersionHandlers() {
.where(
and(
eq(messages.chatId, chatId),
gt(messages.id, messageWithCommit.id)
)
gt(messages.id, messageWithCommit.id),
),
);
}
}
@@ -224,12 +227,12 @@ export function registerVersionHandlers() {
} catch (error: any) {
logger.error(
`Error reverting to version ${previousVersionId} for app ${appId}:`,
error
error,
);
throw new Error(`Failed to revert version: ${error.message}`);
}
});
}
},
);
ipcMain.handle(
@@ -259,11 +262,11 @@ export function registerVersionHandlers() {
} catch (error: any) {
logger.error(
`Error checking out version ${versionId} for app ${appId}:`,
error
error,
);
throw new Error(`Failed to checkout version: ${error.message}`);
}
});
}
},
);
}