历史回读保留尚未落盘的运行时消息;过程卡不再渲染流式正文
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 5m8s
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 5m38s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 4m53s
Project CI / Backend tests (pull_request) Failing after 11s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 4m0s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m44s
Project CI / Repository checks (pull_request) Failing after 11s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 3m14s
Project CI / AI game creator shell web tests (pull_request) Failing after 3m14s
Project CI / Frontend tests (pull_request) Failing after 3m29s
Project CI / Native shell tests (pull_request) Successful in 7m10s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 5m8s
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 5m38s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 4m53s
Project CI / Backend tests (pull_request) Failing after 11s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 4m0s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m44s
Project CI / Repository checks (pull_request) Failing after 11s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 3m14s
Project CI / AI game creator shell web tests (pull_request) Failing after 3m14s
Project CI / Frontend tests (pull_request) Failing after 3m29s
Project CI / Native shell tests (pull_request) Successful in 7m10s
This commit is contained in:
@@ -534,6 +534,41 @@ function claimInitialSupervisorMessageForPage(projectPath: string) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 历史回读与"尚未落盘的运行时消息"合并。
|
||||
*
|
||||
* 初始需求是**乐观插入**到 messages 的(latch 命中后先插一条 user 消息,再发起回合),
|
||||
* 而历史回读在 replace 分支里是无条件整体替换 —— 只要回读晚于乐观插入,那条用户消息
|
||||
* 就会被冲掉(界面上看不到初始需求,但回合其实已经跑起来了)。
|
||||
* 这里把当前 messages 里"运行时拥有、且回读结果里没有"的消息保留在末尾(它们是最新的)。
|
||||
*/
|
||||
function mergeLoadedConversationWithPendingRuntimeMessages(
|
||||
loaded: ChatMessage[],
|
||||
current: ChatMessage[],
|
||||
): ChatMessage[] {
|
||||
if (current.length === 0) {
|
||||
return loaded;
|
||||
}
|
||||
const loadedIds = new Set(
|
||||
loaded
|
||||
.map((message) => message.messageId)
|
||||
.filter((id): id is string => Boolean(id)),
|
||||
);
|
||||
const loadedTexts = new Set(
|
||||
loaded.map((message) => `${message.role}\u0000${message.text}`),
|
||||
);
|
||||
const pending = current.filter((message) => {
|
||||
if (!message.runtimeOwned) {
|
||||
return false;
|
||||
}
|
||||
if (message.messageId) {
|
||||
return !loadedIds.has(message.messageId);
|
||||
}
|
||||
return !loadedTexts.has(`${message.role}\u0000${message.text}`);
|
||||
});
|
||||
return pending.length > 0 ? [...loaded, ...pending] : loaded;
|
||||
}
|
||||
|
||||
export { AuthenticatedClient } from './app/AuthenticatedClient';
|
||||
export type { PendingCommand } from './app/types';
|
||||
export {
|
||||
@@ -3475,8 +3510,12 @@ export function App({
|
||||
setProjectSupervisorResponseStream(null);
|
||||
}
|
||||
setConversationVisibleCount(CONVERSATION_INITIAL_VISIBLE_COUNT);
|
||||
setMessages(() => {
|
||||
const nextMessages = conversationMessages;
|
||||
setMessages((current) => {
|
||||
// 不能整体替换:乐观插入、尚未落盘的用户消息会被冲掉(初始需求看不到就是这个原因)。
|
||||
const nextMessages = mergeLoadedConversationWithPendingRuntimeMessages(
|
||||
conversationMessages,
|
||||
current,
|
||||
);
|
||||
savedConversationProjectPathRef.current = nextProjectPath;
|
||||
savedConversationCountRef.current = nextMessages.length;
|
||||
latestMessagesRef.current = nextMessages;
|
||||
@@ -3690,7 +3729,12 @@ export function App({
|
||||
}
|
||||
setProjectSupervisorRuntimeError(runtimeError || resumeError);
|
||||
setMessages((current) => {
|
||||
const nextConversationMessages = conversationMessages;
|
||||
// replace 分支同样不能丢掉尚未落盘的运行时消息(初始需求)。
|
||||
const nextConversationMessages =
|
||||
mergeLoadedConversationWithPendingRuntimeMessages(
|
||||
conversationMessages,
|
||||
current,
|
||||
);
|
||||
const hasOnlyDefaultGreeting =
|
||||
current.length === 1 &&
|
||||
current[0]?.role === 'assistant' &&
|
||||
|
||||
@@ -591,15 +591,7 @@ export function ProjectSupervisorView({
|
||||
: '陶泥儿正在处理'}
|
||||
</strong>
|
||||
</header>
|
||||
{transientReply ? (
|
||||
<div aria-label="陶泥儿实时回复">
|
||||
<ChatMarkdownMessage
|
||||
role="assistant"
|
||||
text={transientReply}
|
||||
streaming
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{directProcessDetail ? (
|
||||
<div className="project-supervisor-process-detail">
|
||||
<p
|
||||
|
||||
Reference in New Issue
Block a user