(
request: SDKControlRequest['request'],
schema: z.Schema,
signal?: AbortSignal,
requestId: string = randomUUID(),
)
| 473 | } |
| 474 | |
| 475 | private async sendRequest<Response>( |
| 476 | request: SDKControlRequest['request'], |
| 477 | schema: z.Schema, |
| 478 | signal?: AbortSignal, |
| 479 | requestId: string = randomUUID(), |
| 480 | ): Promise<Response> { |
| 481 | const message: SDKControlRequest = { |
| 482 | type: 'control_request', |
| 483 | request_id: requestId, |
| 484 | request, |
| 485 | } |
| 486 | if (this.inputClosed) { |
| 487 | throw new Error('Stream closed') |
| 488 | } |
| 489 | if (signal?.aborted) { |
| 490 | throw new Error('Request aborted') |
| 491 | } |
| 492 | this.outbound.enqueue(message) |
| 493 | if ((request as { subtype?: string }).subtype === 'can_use_tool' && this.onControlRequestSent) { |
| 494 | this.onControlRequestSent(message) |
| 495 | } |
| 496 | const aborted = () => { |
| 497 | this.outbound.enqueue({ |
| 498 | type: 'control_cancel_request', |
| 499 | request_id: requestId, |
| 500 | }) |
| 501 | // Immediately reject the outstanding promise, without |
| 502 | // waiting for the host to acknowledge the cancellation. |
| 503 | const request = this.pendingRequests.get(requestId) |
| 504 | if (request) { |
| 505 | // Track the tool_use ID as resolved before rejecting, so that a |
| 506 | // late response from the host is ignored by the orphan handler. |
| 507 | this.trackResolvedToolUseId(request.request) |
| 508 | request.reject(new AbortError()) |
| 509 | } |
| 510 | } |
| 511 | if (signal) { |
| 512 | signal.addEventListener('abort', aborted, { |
| 513 | once: true, |
| 514 | }) |
| 515 | } |
| 516 | try { |
| 517 | return await new Promise<Response>((resolve, reject) => { |
| 518 | this.pendingRequests.set(requestId, { |
| 519 | request: { |
| 520 | type: 'control_request', |
| 521 | request_id: requestId, |
| 522 | request, |
| 523 | }, |
| 524 | resolve: result => { |
| 525 | resolve(result as Response) |
| 526 | }, |
| 527 | reject, |
| 528 | schema, |
| 529 | }) |
| 530 | }) |
| 531 | } finally { |
| 532 | if (signal) { |
no test coverage detected