fix(native-chat): report a failed Stop child end through the host logger (#24437)

#24334 reported it through onEventSinkError, which #24312 replaced with the
required diagnostics logger; main did not typecheck after both merged.
This commit is contained in:
Jinwoo Hong
2026-10-01 14:35:01 -04:00
committed by GitHub
parent 56c7642aae
commit 9bcdb6ad86
4 changed files with 24 additions and 8 deletions
@@ -85,7 +85,12 @@ export function mutateWithChatStop<TValue>(
clientOperationId: envelope.clientOperationId,
...named,
stopChild: () => context.stopAgent(sessionId),
onStopChildError: (error) => context.deps.onEventSinkError?.({ sessionId, error }),
onStopChildError: (error) =>
context.deps.logger.warn('ending the agent process on Stop failed', {
scope: 'stop-child',
sessionId,
error
}),
// The host drops its child only once the exit is proven, and nothing else runs meanwhile.
childReleased: () => context.sessions.get(sessionId)?.child !== child,
endSession: (owed) => {
@@ -26,7 +26,7 @@ import {
resetHostTestOperationIds
} from './structured-agent-session-host-test-data'
import { openTestJournalHostDatabase } from '../agent-session-journal/journal-host-database-test-support'
import { createStructuredAgentSessionLogger } from './structured-agent-session-logger'
import { recordingStructuredAgentSessionLogger } from './structured-agent-session-logger-test-support'
const CALLER = { callerKey: 'client-1' }
@@ -42,7 +42,7 @@ let acknowledgeSessionRelease: Mock<
>
/** Codex's answer by default: its Stop keeps the child. */
let stopEndsSession: boolean
let onEventSinkError: Mock<(failure: { sessionId: string; error: unknown }) => void>
let log: ReturnType<typeof recordingStructuredAgentSessionLogger>
let events: StructuredAgentSessionEventSink | undefined
function eventually(assertion: () => void | Promise<void>): Promise<void> {
@@ -59,10 +59,10 @@ beforeEach(async () => {
closeSession = vi.fn(async () => true)
acknowledgeSessionRelease = vi.fn()
stopEndsSession = false
onEventSinkError = vi.fn()
log = recordingStructuredAgentSessionLogger()
store = await openTestAgentSessionRecordStore(root)
host = new StructuredAgentSessionHost({
logger: createStructuredAgentSessionLogger(),
logger: log.logger,
store,
adapter: {
acquire: async ({ fence, spawnToken, events: sink }) => {
@@ -97,7 +97,6 @@ beforeEach(async () => {
journalDatabase: openTestJournalHostDatabase(root),
claimKeyId: 'key-1',
mintSpawnToken: () => 'spawn-1',
onEventSinkError,
now: () => NOW
})
expect(await host.attach(CALLER, hostTestAttachParams(null))).toMatchObject({ ok: true })
@@ -288,7 +287,11 @@ describe('a Stop that names no turn', () => {
expect(await stop()).toMatchObject({ ok: true, value: { cancelled: false } })
expect(closeSession).toHaveBeenCalledExactlyOnceWith(SESSION, 'user-stop')
expect(onEventSinkError).toHaveBeenCalledWith(expect.objectContaining({ sessionId: SESSION }))
expect(log.entries).toContainEqual(
expect.objectContaining({
fields: expect.objectContaining({ scope: 'stop-child', sessionId: SESSION })
})
)
expect(await statusRows()).toEqual(["Codex didn't stop: failed to interrupt turn."])
})
@@ -304,7 +307,11 @@ describe('a Stop that names no turn', () => {
expect(await stop()).toMatchObject({ ok: true, value: { cancelled: true } })
expect(closeSession).toHaveBeenCalledExactlyOnceWith(SESSION, 'user-stop')
expect(onEventSinkError).toHaveBeenCalledWith(expect.objectContaining({ sessionId: SESSION }))
expect(log.entries).toContainEqual(
expect.objectContaining({
fields: expect.objectContaining({ scope: 'stop-child', sessionId: SESSION })
})
)
expect(await statusRows()).toEqual(['Cancellation requested.'])
})
@@ -14,6 +14,7 @@ import { openTestAgentSessionRecordStore } from '../../runtime/agent-session-rec
import { openTestJournalHostDatabase } from '../agent-session-journal/journal-host-database-test-support'
import type { StructuredAgentSessionAdapter } from './structured-agent-session-adapter'
import { StructuredAgentSessionHost } from './structured-agent-session-host'
import { createStructuredAgentSessionLogger } from './structured-agent-session-logger'
import {
HOST_TEST_NOW as NOW,
HOST_TEST_SESSION as SESSION,
@@ -42,6 +43,7 @@ beforeEach(async () => {
cancelTurn = vi.fn(async () => ({ cancelled: true }))
store = await openTestAgentSessionRecordStore(root)
host = new StructuredAgentSessionHost({
logger: createStructuredAgentSessionLogger(),
store,
adapter: {
acquire: async ({ fence, spawnToken }) => ({
@@ -8,6 +8,7 @@ import { openTestAgentSessionRecordStore } from '../../runtime/agent-session-rec
import { openTestJournalHostDatabase } from '../agent-session-journal/journal-host-database-test-support'
import type { StructuredAgentSessionAdapter } from './structured-agent-session-adapter'
import { StructuredAgentSessionHost } from './structured-agent-session-host'
import { createStructuredAgentSessionLogger } from './structured-agent-session-logger'
import {
adapter,
attach,
@@ -101,6 +102,7 @@ describe('a Stop pressed again', () => {
await store.renewLeases([])
const relaunchedStore = await openTestAgentSessionRecordStore(root)
const relaunched = new StructuredAgentSessionHost({
logger: createStructuredAgentSessionLogger(),
store: relaunchedStore,
adapter: adapter(),
journalDatabase: openTestJournalHostDatabase(root),