Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
bit-pm
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
燕伟桐
bit-pm
Commits
f4c7d614
Unverified
提交
f4c7d614
authored
5月 22, 2025
作者:
Will Chen
提交者:
GitHub
5月 22, 2025
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Escape dyad tags inside thinking blocks (#229)
上级
5e86f4b5
隐藏空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
52 行增加
和
4 行删除
+52
-4
chat_stream_handlers.ts
src/ipc/handlers/chat_stream_handlers.ts
+30
-1
index.ts
testing/fake-llm-server/index.ts
+22
-3
没有找到文件。
src/ipc/handlers/chat_stream_handlers.ts
浏览文件 @
f4c7d614
...
@@ -215,6 +215,7 @@ export function registerChatStreamHandlers() {
...
@@ -215,6 +215,7 @@ export function registerChatStreamHandlers() {
abortController
,
abortController
,
updatedChat
,
updatedChat
,
);
);
fullResponse
=
cleanThinkingByEscapingDyadTags
(
fullResponse
);
}
else
{
}
else
{
// Normal AI processing for non-test prompts
// Normal AI processing for non-test prompts
const
settings
=
readSettings
();
const
settings
=
readSettings
();
...
@@ -348,7 +349,10 @@ This conversation includes one or more image attachments. When the user uploads
...
@@ -348,7 +349,10 @@ This conversation includes one or more image attachments. When the user uploads
...
codebasePrefix
,
...
codebasePrefix
,
...
limitedMessageHistory
.
map
((
msg
)
=>
({
...
limitedMessageHistory
.
map
((
msg
)
=>
({
role
:
msg
.
role
as
"user"
|
"assistant"
|
"system"
,
role
:
msg
.
role
as
"user"
|
"assistant"
|
"system"
,
content
:
msg
.
content
,
// Why remove thinking tags?
// Thinking tags are generally not critical for the context
// and eats up extra tokens.
content
:
removeThinkingTags
(
msg
.
content
),
})),
})),
];
];
...
@@ -411,6 +415,7 @@ This conversation includes one or more image attachments. When the user uploads
...
@@ -411,6 +415,7 @@ This conversation includes one or more image attachments. When the user uploads
try
{
try
{
for
await
(
const
textPart
of
textStream
)
{
for
await
(
const
textPart
of
textStream
)
{
fullResponse
+=
textPart
;
fullResponse
+=
textPart
;
fullResponse
=
cleanThinkingByEscapingDyadTags
(
fullResponse
);
if
(
if
(
fullResponse
.
includes
(
"$$SUPABASE_CLIENT_CODE$$"
)
&&
fullResponse
.
includes
(
"$$SUPABASE_CLIENT_CODE$$"
)
&&
updatedChat
.
app
?.
supabaseProjectId
updatedChat
.
app
?.
supabaseProjectId
...
@@ -707,3 +712,27 @@ async function prepareMessageWithAttachments(
...
@@ -707,3 +712,27 @@ async function prepareMessageWithAttachments(
content
:
contentParts
,
content
:
contentParts
,
};
};
}
}
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
();
}
testing/fake-llm-server/index.ts
浏览文件 @
f4c7d614
...
@@ -32,9 +32,28 @@ function createStreamChunk(
...
@@ -32,9 +32,28 @@ function createStreamChunk(
return
`data:
${
JSON
.
stringify
(
chunk
)}
\n\n
${
isLast
?
"data: [DONE]
\
n
\
n"
:
""
}
`
;
return
`data:
${
JSON
.
stringify
(
chunk
)}
\n\n
${
isLast
?
"data: [DONE]
\
n
\
n"
:
""
}
`
;
}
}
const
CANNED_MESSAGE
=
`
<think>
\`<dyad-write>\`:
I'll think about the problem and write a bug report.
<dyad-write>
<dyad-write path="file1.txt">
Fake dyad write
</dyad-write>
</think>
<dyad-write path="file1.txt">
A file (2)
</dyad-write>
More
EOM`
;
// Handle POST requests to /v1/chat/completions
// Handle POST requests to /v1/chat/completions
app
.
post
(
"/v1/chat/completions"
,
(
req
,
res
)
=>
{
app
.
post
(
"/v1/chat/completions"
,
(
req
,
res
)
=>
{
const
{
stream
=
false
,
messages
=
[]
}
=
req
.
body
;
const
{
stream
=
false
,
messages
=
[]
}
=
req
.
body
;
console
.
log
(
"* Received messages"
,
messages
);
// Check if the last message contains "[429]" to simulate rate limiting
// Check if the last message contains "[429]" to simulate rate limiting
const
lastMessage
=
messages
[
messages
.
length
-
1
];
const
lastMessage
=
messages
[
messages
.
length
-
1
];
...
@@ -61,7 +80,7 @@ app.post("/v1/chat/completions", (req, res) => {
...
@@ -61,7 +80,7 @@ app.post("/v1/chat/completions", (req, res) => {
index
:
0
,
index
:
0
,
message
:
{
message
:
{
role
:
"assistant"
,
role
:
"assistant"
,
content
:
"hello world"
,
content
:
CANNED_MESSAGE
,
},
},
finish_reason
:
"stop"
,
finish_reason
:
"stop"
,
},
},
...
@@ -75,7 +94,7 @@ app.post("/v1/chat/completions", (req, res) => {
...
@@ -75,7 +94,7 @@ app.post("/v1/chat/completions", (req, res) => {
res
.
setHeader
(
"Connection"
,
"keep-alive"
);
res
.
setHeader
(
"Connection"
,
"keep-alive"
);
// Split the "hello world" message into characters to simulate streaming
// Split the "hello world" message into characters to simulate streaming
const
message
=
"hello world"
;
const
message
=
CANNED_MESSAGE
;
const
messageChars
=
message
.
split
(
""
);
const
messageChars
=
message
.
split
(
""
);
// Stream each character with a delay
// Stream each character with a delay
...
@@ -94,7 +113,7 @@ app.post("/v1/chat/completions", (req, res) => {
...
@@ -94,7 +113,7 @@ app.post("/v1/chat/completions", (req, res) => {
clearInterval
(
interval
);
clearInterval
(
interval
);
res
.
end
();
res
.
end
();
}
}
},
10
0
);
},
10
);
});
});
// Start the server
// Start the server
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论