@@ -25,7 +25,7 @@ import {
|
||||
getSupabaseClientCode,
|
||||
} from "../../supabase_admin/supabase_context";
|
||||
import { SUMMARIZE_CHAT_SYSTEM_PROMPT } from "../../prompts/summarize_chat_system_prompt";
|
||||
import * as fs from "fs";
|
||||
import fs from "node:fs";
|
||||
import * as path from "path";
|
||||
import * as os from "os";
|
||||
import * as crypto from "crypto";
|
||||
@@ -38,6 +38,7 @@ import { GoogleGenerativeAIProviderOptions } from "@ai-sdk/google";
|
||||
import { getExtraProviderOptions } from "../utils/thinking_utils";
|
||||
|
||||
import { safeSend } from "../utils/safe_sender";
|
||||
import { cleanFullResponse } from "../utils/cleanFullResponse";
|
||||
|
||||
const logger = log.scope("chat_stream_handlers");
|
||||
|
||||
@@ -258,7 +259,6 @@ ${componentSnippet}
|
||||
abortController,
|
||||
updatedChat,
|
||||
);
|
||||
fullResponse = cleanThinkingByEscapingDyadTags(fullResponse);
|
||||
} else {
|
||||
// Normal AI processing for non-test prompts
|
||||
const settings = readSettings();
|
||||
@@ -515,6 +515,7 @@ This conversation includes one or more image attachments. When the user uploads
|
||||
}
|
||||
|
||||
fullResponse += chunk;
|
||||
fullResponse = cleanFullResponse(fullResponse);
|
||||
|
||||
if (
|
||||
fullResponse.includes("$$SUPABASE_CLIENT_CODE$$") &&
|
||||
@@ -815,25 +816,6 @@ async function prepareMessageWithAttachments(
|
||||
};
|
||||
}
|
||||
|
||||
function cleanThinkingByEscapingDyadTags(text: string): string {
|
||||
// Extract content inside <think> </think> tags
|
||||
const thinkRegex = /<think>([\s\S]*?)<\/think>/g;
|
||||
|
||||
return text.replace(thinkRegex, (match, content) => {
|
||||
// We are replacing the opening tag with a look-alike character
|
||||
// to avoid issues where thinking content includes dyad tags
|
||||
// and are mishandled by:
|
||||
// 1. FE markdown parser
|
||||
// 2. Main process response processor
|
||||
const processedContent = content
|
||||
.replace(/<dyad/g, "<dyad")
|
||||
.replace(/<\/dyad/g, "</dyad");
|
||||
|
||||
// Return the modified think tag with processed content
|
||||
return `<think>${processedContent}</think>`;
|
||||
});
|
||||
}
|
||||
|
||||
function removeThinkingTags(text: string): string {
|
||||
const thinkRegex = /<think>([\s\S]*?)<\/think>/g;
|
||||
return text.replace(thinkRegex, "").trim();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { safeSend } from "../utils/safe_sender";
|
||||
import { cleanFullResponse } from "../utils/cleanFullResponse";
|
||||
|
||||
// e.g. [dyad-qa=add-dep]
|
||||
// Canned responses for test prompts
|
||||
@@ -18,6 +19,12 @@ const TEST_RESPONSES: Record<string, string> = {
|
||||
<dyad-add-dependency packages="react-router-dom react-query"></dyad-add-dependency>
|
||||
|
||||
EOM`,
|
||||
"string-literal-leak": `BEFORE TAG
|
||||
<dyad-write path="src/pages/locations/neighborhoods/louisville/Highlands.tsx" description="Updating Highlands neighborhood page to use <a> tags.">
|
||||
import React from 'react';
|
||||
</dyad-write>
|
||||
AFTER TAG
|
||||
`,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -64,6 +71,7 @@ export async function streamTestResponse(
|
||||
|
||||
// Add the word plus a space
|
||||
fullResponse += chunk + " ";
|
||||
fullResponse = cleanFullResponse(fullResponse);
|
||||
|
||||
// Send the current accumulated response
|
||||
safeSend(event.sender, "chat:response:chunk", {
|
||||
|
||||
15
src/ipc/utils/cleanFullResponse.ts
Normal file
15
src/ipc/utils/cleanFullResponse.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
export function cleanFullResponse(text: string): string {
|
||||
// Replace < characters inside dyad-* attributes with fullwidth less-than sign <
|
||||
// This prevents parsing issues when attributes contain HTML tags like <a> or <div>
|
||||
return text.replace(/<dyad-[^<>]*(?:"[^"]*"[^<>]*)*>/g, (match: string) => {
|
||||
// Find all attribute values (content within quotes) and replace < with < and > with >
|
||||
const processedMatch = match.replace(
|
||||
/="([^"]*)"/g,
|
||||
(attrMatch: string, attrValue: string) => {
|
||||
const cleanedValue = attrValue.replace(/</g, "<").replace(/>/g, ">");
|
||||
return `="${cleanedValue}"`;
|
||||
},
|
||||
);
|
||||
return processedMatch;
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user