Merge commit '6da4bd5f593e2f633df9e99721fb62e559b56012' into codex/product-providers-pr2-claude-code

This commit is contained in:
pku-xht
2026-08-05 07:40:22 +08:00
3 changed files with 13 additions and 37 deletions

View File

@@ -179,7 +179,7 @@ export async function startCodexRun(
const collectOutput = (): ContentBlock[] => wire.collectOutput() const collectOutput = (): ContentBlock[] => wire.collectOutput()
const result: Promise<SubagentResult> = settleRunResult({ const result: Promise<SubagentResult> = settleRunResult({
attempt: () => Promise.race([ attempt: () => Promise.race([
wire.runTurn(texts, runAbort.signal, () => runAbort.signal.aborted), wire.runTurn(texts, runAbort.signal),
processFailure, processFailure,
]), ]),
collectOutput, collectOutput,

View File

@@ -168,13 +168,11 @@ export class CodexAppServerWire {
* terminal notification. * terminal notification.
* @param texts - already validated task text blocks. * @param texts - already validated task text blocks.
* @param signal - local cancellation for the published run. * @param signal - local cancellation for the published run.
* @param cancelled - whether local cancellation has already won.
* @returns the shared subagent result. * @returns the shared subagent result.
*/ */
async runTurn( async runTurn(
texts: readonly string[], texts: readonly string[],
signal: AbortSignal, signal: AbortSignal,
cancelled: () => boolean,
): Promise<SubagentResult> { ): Promise<SubagentResult> {
const completion = Promise.withResolvers<JsonObject>() const completion = Promise.withResolvers<JsonObject>()
this.turnCompleted = completion this.turnCompleted = completion
@@ -187,8 +185,6 @@ export class CodexAppServerWire {
this.commitTurnId(string(turn.id, 'turn/start turn id')) this.commitTurnId(string(turn.id, 'turn/start turn id'))
const completed = await this.guarded(completion.promise, signal) const completed = await this.guarded(completion.promise, signal)
if (cancelled()) return { output: this.collectOutput(), stopReason: 'aborted' }
const terminal = object(completed.turn, 'turn/completed turn') const terminal = object(completed.turn, 'turn/completed turn')
const status = terminal.status const status = terminal.status
if (isContextWindowExceeded(terminal)) { if (isContextWindowExceeded(terminal)) {

View File

@@ -393,7 +393,6 @@ describe('CodexAppServerWire', () => {
const result = wire.runTurn( const result = wire.runTurn(
['first', 'second'], ['first', 'second'],
new AbortController().signal, new AbortController().signal,
() => false,
) )
const turnStart = await child.peer.nextMethod('turn/start') const turnStart = await child.peer.nextMethod('turn/start')
expect(turnStart.params).toEqual({ expect(turnStart.params).toEqual({
@@ -437,7 +436,7 @@ describe('CodexAppServerWire', () => {
it('uses the last nullable-phase answer when no explicit final exists', async () => { it('uses the last nullable-phase answer when no explicit final exists', async () => {
const { child, wire } = await initializeWire() const { child, wire } = await initializeWire()
const result = wire.runTurn(['task'], new AbortController().signal, () => false) const result = wire.runTurn(['task'], new AbortController().signal)
const turnStart = await child.peer.nextMethod('turn/start') const turnStart = await child.peer.nextMethod('turn/start')
child.peer.respond(turnStart, { turn: { id: 'turn-1' } }) child.peer.respond(turnStart, { turn: { id: 'turn-1' } })
child.peer.send( child.peer.send(
@@ -454,7 +453,7 @@ describe('CodexAppServerWire', () => {
it('maps only an explicit context-window failure to max-tokens', async () => { it('maps only an explicit context-window failure to max-tokens', async () => {
const { child, wire } = await initializeWire() const { child, wire } = await initializeWire()
const result = wire.runTurn(['task'], new AbortController().signal, () => false) const result = wire.runTurn(['task'], new AbortController().signal)
const turnStart = await child.peer.nextMethod('turn/start') const turnStart = await child.peer.nextMethod('turn/start')
child.peer.respond(turnStart, { turn: { id: 'turn-1' } }) child.peer.respond(turnStart, { turn: { id: 'turn-1' } })
child.peer.send( child.peer.send(
@@ -494,7 +493,7 @@ describe('CodexAppServerWire', () => {
} }
{ {
const { child, wire } = await initializeWire() const { child, wire } = await initializeWire()
const pending = wire.runTurn(['task'], new AbortController().signal, () => false) const pending = wire.runTurn(['task'], new AbortController().signal)
const frame = await child.peer.nextMethod('turn/start') const frame = await child.peer.nextMethod('turn/start')
child.peer.respond(frame, { turn: { id: '' } }) child.peer.respond(frame, { turn: { id: '' } })
await expect(pending).rejects.toThrow('turn/start turn id') await expect(pending).rejects.toThrow('turn/start turn id')
@@ -542,7 +541,7 @@ describe('CodexAppServerWire', () => {
] ]
for (const scenario of scenarios) { for (const scenario of scenarios) {
const { child, wire } = await initializeWire() const { child, wire } = await initializeWire()
const result = wire.runTurn(['task'], new AbortController().signal, () => false) const result = wire.runTurn(['task'], new AbortController().signal)
const turnStart = await child.peer.nextMethod('turn/start') const turnStart = await child.peer.nextMethod('turn/start')
child.peer.respond(turnStart, { turn: { id: 'turn-1' } }) child.peer.respond(turnStart, { turn: { id: 'turn-1' } })
child.peer.send(...scenario.frames) child.peer.send(...scenario.frames)
@@ -553,7 +552,7 @@ describe('CodexAppServerWire', () => {
it('fails closed when terminal notification params are not an object', async () => { it('fails closed when terminal notification params are not an object', async () => {
const { child, wire } = await initializeWire() const { child, wire } = await initializeWire()
const result = wire.runTurn(['task'], new AbortController().signal, () => false) const result = wire.runTurn(['task'], new AbortController().signal)
const turnStart = await child.peer.nextMethod('turn/start') const turnStart = await child.peer.nextMethod('turn/start')
child.peer.respond(turnStart, { turn: { id: 'turn-1' } }) child.peer.respond(turnStart, { turn: { id: 'turn-1' } })
child.peer.send({ method: 'turn/completed', params: null }) child.peer.send({ method: 'turn/completed', params: null })
@@ -563,7 +562,7 @@ describe('CodexAppServerWire', () => {
it('keeps an unsupported request authoritative over an early terminal in the same chunk', async () => { it('keeps an unsupported request authoritative over an early terminal in the same chunk', async () => {
const { child, wire } = await initializeWire() const { child, wire } = await initializeWire()
const result = wire.runTurn(['task'], new AbortController().signal, () => false) const result = wire.runTurn(['task'], new AbortController().signal)
const turnStart = await child.peer.nextMethod('turn/start') const turnStart = await child.peer.nextMethod('turn/start')
child.peer.send( child.peer.send(
{ id: turnStart.id, result: { turn: { id: 'turn-1' } } }, { id: turnStart.id, result: { turn: { id: 'turn-1' } } },
@@ -575,28 +574,9 @@ describe('CodexAppServerWire', () => {
wire.close() wire.close()
}) })
it('gives local cancellation precedence over a remote completed turn', async () => {
const { child, wire } = await initializeWire()
let cancelled = false
const result = wire.runTurn(
['task'],
new AbortController().signal,
() => cancelled,
)
const turnStart = await child.peer.nextMethod('turn/start')
child.peer.respond(turnStart, { turn: { id: 'turn-1' } })
cancelled = true
child.peer.send(agentMessage('late', 'final_answer'), turnCompleted('completed'))
await expect(result).resolves.toEqual({
output: [{ type: 'text', text: 'late' }],
stopReason: 'aborted',
})
wire.close()
})
it('answers all five unattended request classes without granting authority', async () => { it('answers all five unattended request classes without granting authority', async () => {
const { child, wire } = await initializeWire() const { child, wire } = await initializeWire()
const result = wire.runTurn(['task'], new AbortController().signal, () => false) const result = wire.runTurn(['task'], new AbortController().signal)
const turnStart = await child.peer.nextMethod('turn/start') const turnStart = await child.peer.nextMethod('turn/start')
child.peer.send({ child.peer.send({
@@ -699,7 +679,7 @@ describe('CodexAppServerWire', () => {
}, },
]) { ]) {
const { child, wire } = await initializeWire() const { child, wire } = await initializeWire()
const result = wire.runTurn(['task'], new AbortController().signal, () => false) const result = wire.runTurn(['task'], new AbortController().signal)
const turnStart = await child.peer.nextMethod('turn/start') const turnStart = await child.peer.nextMethod('turn/start')
child.peer.respond(turnStart, { turn: { id: 'turn-1' } }) child.peer.respond(turnStart, { turn: { id: 'turn-1' } })
await nextTask() await nextTask()
@@ -713,7 +693,7 @@ describe('CodexAppServerWire', () => {
it('rejects conflicting early turn identities before accepting output', async () => { it('rejects conflicting early turn identities before accepting output', async () => {
const { child, wire } = await initializeWire() const { child, wire } = await initializeWire()
const result = wire.runTurn(['task'], new AbortController().signal, () => false) const result = wire.runTurn(['task'], new AbortController().signal)
const turnStart = await child.peer.nextMethod('turn/start') const turnStart = await child.peer.nextMethod('turn/start')
child.peer.send({ child.peer.send({
method: 'turn/started', method: 'turn/started',
@@ -738,7 +718,7 @@ describe('CodexAppServerWire', () => {
} }
{ {
const { child, wire } = await initializeWire() const { child, wire } = await initializeWire()
const result = wire.runTurn(['task'], new AbortController().signal, () => false) const result = wire.runTurn(['task'], new AbortController().signal)
await child.peer.nextMethod('turn/start') await child.peer.nextMethod('turn/start')
child.peer.send( child.peer.send(
{ {
@@ -755,7 +735,7 @@ describe('CodexAppServerWire', () => {
it('interrupts only an active open turn and contains remote interrupt failure', async () => { it('interrupts only an active open turn and contains remote interrupt failure', async () => {
const { child, wire } = await initializeWire() const { child, wire } = await initializeWire()
wire.interrupt() wire.interrupt()
const result = wire.runTurn(['task'], new AbortController().signal, () => false) const result = wire.runTurn(['task'], new AbortController().signal)
const turnStart = await child.peer.nextMethod('turn/start') const turnStart = await child.peer.nextMethod('turn/start')
child.peer.respond(turnStart, { turn: { id: 'turn-1' } }) child.peer.respond(turnStart, { turn: { id: 'turn-1' } })
await nextTask() await nextTask()
@@ -790,7 +770,7 @@ describe('CodexAppServerWire', () => {
) )
await nextTask() await nextTask()
const result = wire.runTurn(['task'], new AbortController().signal, () => false) const result = wire.runTurn(['task'], new AbortController().signal)
const turnStart = await child.peer.nextMethod('turn/start') const turnStart = await child.peer.nextMethod('turn/start')
child.peer.respond(turnStart, { turn: { id: 'turn-1' } }) child.peer.respond(turnStart, { turn: { id: 'turn-1' } })
await nextTask() await nextTask()