fix(delegate-task): fetch session result before honoring abort signal (#2702)
The sync poller returned 'Task aborted' immediately when the abort signal fired, even when a terminal assistant message had already arrived during the previous wait. Now attempts one final fetch and returns the completion result if available before emitting the abort message. 🤖 Generated with OhMyOpenCode assistance https://github.com/code-yeongyu/oh-my-opencode
This commit is contained in:
@@ -23,6 +23,15 @@ function abortSyncSession(client: OpencodeClient, sessionID: string, reason: str
|
||||
})
|
||||
}
|
||||
|
||||
async function fetchSessionMessages(
|
||||
client: OpencodeClient,
|
||||
sessionID: string
|
||||
): Promise<SessionMessage[]> {
|
||||
const messagesResult = await client.session.messages({ path: { id: sessionID } })
|
||||
const rawData = (messagesResult as { data?: unknown })?.data ?? messagesResult
|
||||
return Array.isArray(rawData) ? (rawData as SessionMessage[]) : []
|
||||
}
|
||||
|
||||
export function isSessionComplete(messages: SessionMessage[]): boolean {
|
||||
let lastUser: SessionMessage | undefined
|
||||
let lastAssistant: SessionMessage | undefined
|
||||
@@ -69,6 +78,21 @@ export async function pollSyncSession(
|
||||
|
||||
while (Date.now() - pollStart < maxPollTimeMs) {
|
||||
if (ctx.abort?.aborted) {
|
||||
try {
|
||||
const messages = await fetchSessionMessages(client, input.sessionID)
|
||||
const hasNewMessages =
|
||||
input.anchorMessageCount === undefined || messages.length > input.anchorMessageCount
|
||||
if (hasNewMessages && isSessionComplete(messages)) {
|
||||
log("[task] Abort detected after session already completed", { sessionID: input.sessionID })
|
||||
return null
|
||||
}
|
||||
} catch (error) {
|
||||
log("[task] Final messages fetch failed after abort, continuing with abort", {
|
||||
sessionID: input.sessionID,
|
||||
error: String(error),
|
||||
})
|
||||
}
|
||||
|
||||
log("[task] Aborted by user", { sessionID: input.sessionID })
|
||||
abortSyncSession(client, input.sessionID, "parent_abort")
|
||||
if (input.toastManager && input.taskId) input.toastManager.removeTask(input.taskId)
|
||||
@@ -101,27 +125,25 @@ export async function pollSyncSession(
|
||||
continue
|
||||
}
|
||||
|
||||
let messagesResult: { data?: unknown } | SessionMessage[]
|
||||
let messages: SessionMessage[]
|
||||
try {
|
||||
messagesResult = await client.session.messages({ path: { id: input.sessionID } })
|
||||
messages = await fetchSessionMessages(client, input.sessionID)
|
||||
} catch (error) {
|
||||
log("[task] Poll messages fetch failed, retrying", { sessionID: input.sessionID, error: String(error) })
|
||||
continue
|
||||
}
|
||||
const rawData = (messagesResult as { data?: unknown })?.data ?? messagesResult
|
||||
const msgs = Array.isArray(rawData) ? (rawData as SessionMessage[]) : []
|
||||
|
||||
if (input.anchorMessageCount !== undefined && msgs.length <= input.anchorMessageCount) {
|
||||
if (input.anchorMessageCount !== undefined && messages.length <= input.anchorMessageCount) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (isSessionComplete(msgs)) {
|
||||
if (isSessionComplete(messages)) {
|
||||
log("[task] Poll complete - terminal finish detected", { sessionID: input.sessionID, pollCount })
|
||||
break
|
||||
}
|
||||
|
||||
// 计数新出现的 assistant 轮次,用于熔断无限循环
|
||||
const lastAssistant = [...msgs].reverse().find((m) => m.info?.role === "assistant")
|
||||
const lastAssistant = [...messages].reverse().find((m) => m.info?.role === "assistant")
|
||||
if (lastAssistant?.info?.id && lastAssistant.info.id !== lastSeenAssistantId) {
|
||||
lastSeenAssistantId = lastAssistant.info.id
|
||||
assistantTurnCount++
|
||||
@@ -137,7 +159,7 @@ export async function pollSyncSession(
|
||||
}
|
||||
}
|
||||
|
||||
const hasAssistantText = msgs.some((m) => {
|
||||
const hasAssistantText = messages.some((m) => {
|
||||
if (m.info?.role !== "assistant") return false
|
||||
const parts = m.parts ?? []
|
||||
return parts.some((p) => {
|
||||
|
||||
Reference in New Issue
Block a user