(
sessionId: string,
input: UserMessageInput,
run: AgentRun,
execution: PendingExecutionClaim,
steering = false,
onRunStarted?: (runId: string, initialHeader: SessionHeader) => void | Promise<void>,
initialHeader?: SessionHeader,
)
| 1448 | } |
| 1449 | |
| 1450 | private async *runAgentTurn( |
| 1451 | sessionId: string, |
| 1452 | input: UserMessageInput, |
| 1453 | run: AgentRun, |
| 1454 | execution: PendingExecutionClaim, |
| 1455 | steering = false, |
| 1456 | onRunStarted?: (runId: string, initialHeader: SessionHeader) => void | Promise<void>, |
| 1457 | initialHeader?: SessionHeader, |
| 1458 | ): AsyncIterable<SessionEvent> { |
| 1459 | const sessionEvents = new DeliveryAckQueue<SessionEvent>(); |
| 1460 | const { abortController, release: releaseExecutionAbort } = |
| 1461 | this.inheritExecutionAbort(execution); |
| 1462 | let flowDone = false; |
| 1463 | const owners = this.createRunOwnerScope(run, execution); |
| 1464 | let begin: AgentRunBeginResult; |
| 1465 | try { |
| 1466 | if (steering) { |
| 1467 | owners.bindMessage(this.deps.messageAuthority, { |
| 1468 | sessionId, |
| 1469 | turnId: run.turnId, |
| 1470 | runId: run.runId, |
| 1471 | }); |
| 1472 | } |
| 1473 | begin = await this.runBackendActivation(async () => { |
| 1474 | const started = await run.begin(); |
| 1475 | await owners.bindInteraction(this.deps.interactionAuthority, { |
| 1476 | sessionId, |
| 1477 | turnId: run.turnId, |
| 1478 | runId: run.runId, |
| 1479 | }); |
| 1480 | return started; |
| 1481 | }); |
| 1482 | if (onRunStarted && initialHeader) await onRunStarted(run.runId, initialHeader); |
| 1483 | } catch (error) { |
| 1484 | releaseExecutionAbort(); |
| 1485 | await this.finalizeFailedRunStart(owners, run, execution, error); |
| 1486 | return; |
| 1487 | } |
| 1488 | |
| 1489 | const interactionRun = owners.interactionRun; |
| 1490 | const messageOwner = owners.messageOwner; |
| 1491 | |
| 1492 | // Steering is a top-level-turn affordance only; child agent turns run |
| 1493 | // without a queue. Hosted ownership is bound before begin so a pre-start |
| 1494 | // cancellation can release the exact admitted owner. The pull hook still |
| 1495 | // re-checks this run's turnId so stale or overlapping runs cannot drain |
| 1496 | // messages queued for the current owner. |
| 1497 | let pullSteering: (() => readonly SteeringLease[]) | undefined; |
| 1498 | let ackSteering: ((leaseIds: readonly string[]) => void) | undefined; |
| 1499 | let nackSteering: ((leaseIds: readonly string[]) => void) | undefined; |
| 1500 | if (messageOwner) { |
| 1501 | pullSteering = () => messageOwner?.pull() ?? []; |
| 1502 | ackSteering = (leaseIds) => messageOwner?.ack(leaseIds); |
| 1503 | nackSteering = (leaseIds) => messageOwner?.nack(leaseIds); |
| 1504 | } else if (steering) { |
| 1505 | const state = this.ensureSteering(sessionId); |
| 1506 | state.sink = (event) => { |
| 1507 | void sessionEvents.push(event).catch(() => {}); |
no test coverage detected