Merge commit '6da4bd5f593e2f633df9e99721fb62e559b56012' into codex/product-providers-pr2-claude-code
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
@@ -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)) {
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user