fix(mothership): minor followups (#3709)

* fix(mothership): abort fix

* diff engine fix
This commit is contained in:
Vikhyath Mondreti
2026-03-22 02:29:09 -07:00
committed by GitHub
parent 59307e22bd
commit 4cb5e3469f
3 changed files with 34 additions and 9 deletions
@@ -420,7 +420,6 @@ export function useChat(
chatIdRef.current = undefined
setResolvedChatId(undefined)
appliedChatIdRef.current = undefined
abortControllerRef.current?.abort()
abortControllerRef.current = null
sendingRef.current = false
setMessages([])
@@ -445,7 +444,26 @@ export function useChat(
appliedChatIdRef.current = chatHistory.id
const mappedMessages = chatHistory.messages.map(mapStoredMessage)
setMessages(mappedMessages)
const shouldPreserveActiveStreamingMessage =
sendingRef.current && Boolean(activeStreamId) && activeStreamId === streamIdRef.current
if (shouldPreserveActiveStreamingMessage) {
setMessages((prev) => {
const localStreamingAssistant = prev[prev.length - 1]
if (localStreamingAssistant?.role !== 'assistant') {
return mappedMessages
}
const nextMessages =
mappedMessages[mappedMessages.length - 1]?.role === 'assistant'
? mappedMessages.slice(0, -1)
: mappedMessages
return [...nextMessages, localStreamingAssistant]
})
} else {
setMessages(mappedMessages)
}
if (chatHistory.resources.some((r) => r.id === 'streaming-file')) {
fetch('/api/copilot/chat/resources', {
@@ -1467,7 +1485,6 @@ export function useChat(
return () => {
streamReaderRef.current?.cancel().catch(() => {})
streamReaderRef.current = null
abortControllerRef.current?.abort()
abortControllerRef.current = null
streamGenRef.current++
sendingRef.current = false
-1
View File
@@ -353,7 +353,6 @@ export function createSSEStream(params: StreamingOrchestrationParams): ReadableS
},
cancel() {
clientDisconnected = true
abortController.abort()
if (eventWriter) {
eventWriter.flush().catch(() => {})
}
+14 -5
View File
@@ -505,12 +505,21 @@ export class WorkflowDiffEngine {
try {
const baselineBlockIds = new Set(Object.keys(mergedBaseline.blocks))
// Identify blocks that need positioning: genuinely new blocks AND
// blocks inserted into subflows (position reset to 0,0). Extracted
// blocks are excluded — the server computes valid absolute positions
// from the container offset, so they don't need repositioning.
// Identify blocks that need positioning: genuinely new blocks that
// don't have valid positions yet. Blocks already positioned by a
// previous server-side layout (non-origin position) are skipped to
// avoid redundant client-side re-layout that can shift blocks when
// block metrics change between edits (e.g. condition handle offsets).
const blocksNeedingLayout = Object.keys(finalBlocks).filter((id) => {
if (!baselineBlockIds.has(id)) return true
if (!baselineBlockIds.has(id)) {
const pos = finalBlocks[id]?.position
const hasValidPosition =
pos &&
Number.isFinite(pos.x) &&
Number.isFinite(pos.y) &&
!(pos.x === 0 && pos.y === 0)
return !hasValidPosition
}
const baselineParent = mergedBaseline.blocks[id]?.data?.parentId ?? null
const proposedParent = finalBlocks[id]?.data?.parentId ?? null
if (baselineParent === proposedParent) return false