fix(session): remove duplicated turn-end step

This commit is contained in:
_Kerman
2026-08-04 14:10:07 +08:00
parent e874910a76
commit ab441389b2
10 changed files with 46 additions and 46 deletions

View File

@@ -87,10 +87,6 @@ function validateEvent(
if (trace.openStep !== null) {
fail(`turn/end ${event.data.turn} while step ${trace.openStep} is still open`)
}
const lastStep = trace.nextStep - 1
if (event.data.step !== lastStep) {
fail(`turn/end ${event.data.turn} expected last step ${lastStep}, got ${event.data.step}`)
}
openTurn = null
nextTurn += 1
break

View File

@@ -46,7 +46,6 @@ export const TOOL_OUTCOME_UNKNOWN = 'TOOL_OUTCOME_UNKNOWN'
export function interruptedTurnClosers(events: readonly SessionEvent[]): SessionEvent[] {
let openTurn: number | null = null
let openStep: number | null = null
let lastStep = 0
// Reset at each turn boundary so earlier calls cannot leak into tail repair.
// Assistant blocks register calls; later tool/call events add provenance seqs.
const pendingCalls = new Map<CallId, { step: number; callSeq?: number }>()
@@ -55,18 +54,15 @@ export function interruptedTurnClosers(events: readonly SessionEvent[]): Session
case 'turn/start':
openTurn = event.data.turn
openStep = null
lastStep = 0
pendingCalls.clear()
break
case 'turn/end':
openTurn = null
openStep = null
lastStep = 0
pendingCalls.clear()
break
case 'step/start':
openStep = event.data.step
lastStep = event.data.step
break
case 'step/end':
pendingCalls.clear()
@@ -151,6 +147,6 @@ export function interruptedTurnClosers(events: readonly SessionEvent[]): Session
if (openStep !== null) {
closers.push({ type: 'step/end', seq: seq++, time, data: { turn: openTurn, step: openStep } })
}
closers.push({ type: 'turn/end', seq: seq++, time, data: { turn: openTurn, step: lastStep, reason: { kind: 'interrupted' } } })
closers.push({ type: 'turn/end', seq: seq++, time, data: { turn: openTurn, reason: { kind: 'interrupted' } } })
return closers
}

View File

@@ -196,14 +196,14 @@ export interface SessionEventMap {
*/
'turn/start': { turn: number }
/**
* Closes turn `turn` after `step`, the last entered step (`0` when none),
* with the {@link TurnEndReason} that ended it. The loop does not await a
* Closes turn `turn` with the {@link TurnEndReason} that ended it. A turn
* with no entered step has no `step/start` or `step/end`. The loop does not await a
* flush at turn boundaries: `dsh-session-checkpoint-policy` owns the
* per-request durability checkpoint, and consumers that read storage after
* `whenIdle()` flush themselves. Success commits the turn; rejection is
* reported live and does not prevent later work.
*/
'turn/end': { turn: number; step: number; reason: TurnEndReason }
'turn/end': { turn: number; reason: TurnEndReason }
/** Opens step `step` of turn `turn` — one model call plus the tool executions it requested. */
'step/start': { turn: number; step: number }
/** Closes step `step` of turn `turn`. */