* Report tool completion to the server via the existing /api/copilot/confirm endpoint. * This persists the durable async-tool row and wakes the server-side waiter so * it can continue the paused Copilot run and notify Go.
( toolCallId: string, status: AsyncConfirmationStatus, message?: string, data?: AsyncCompletionData )
| 573 | * it can continue the paused Copilot run and notify Go. |
| 574 | */ |
| 575 | async function reportCompletion( |
| 576 | toolCallId: string, |
| 577 | status: AsyncConfirmationStatus, |
| 578 | message?: string, |
| 579 | data?: AsyncCompletionData |
| 580 | ): Promise<void> { |
| 581 | const basePayload = { |
| 582 | toolCallId, |
| 583 | status, |
| 584 | message: message || (status === 'success' ? 'Tool completed' : 'Tool failed'), |
| 585 | ...(data !== undefined ? { data } : {}), |
| 586 | } |
| 587 | const send = async (body: string) => |
| 588 | fetch(COPILOT_CONFIRM_API_PATH, { |
| 589 | method: 'POST', |
| 590 | headers: { 'Content-Type': 'application/json', ...traceparentHeader() }, |
| 591 | body, |
| 592 | }) |
| 593 | |
| 594 | const body = JSON.stringify(basePayload) |
| 595 | const LARGE_PAYLOAD_THRESHOLD = 10 * 1024 * 1024 |
| 596 | const bodySize = new Blob([body]).size |
| 597 | let lastError: Error | null = null |
| 598 | |
| 599 | for (let attempt = 1; attempt <= 2; attempt++) { |
| 600 | try { |
| 601 | const res = await send(body) |
| 602 | if (res.ok) return |
| 603 | |
| 604 | if (isRecordLike(data) && bodySize > LARGE_PAYLOAD_THRESHOLD) { |
| 605 | const { logs: _logs, ...dataWithoutLogs } = data |
| 606 | logger.warn('[RunTool] reportCompletion failed with large payload, retrying without logs', { |
| 607 | toolCallId, |
| 608 | status: res.status, |
| 609 | bodySize, |
| 610 | }) |
| 611 | const retryRes = await send( |
| 612 | JSON.stringify({ |
| 613 | toolCallId, |
| 614 | status, |
| 615 | message: message || (status === 'success' ? 'Tool completed' : 'Tool failed'), |
| 616 | data: dataWithoutLogs, |
| 617 | }) |
| 618 | ) |
| 619 | if (retryRes.ok) return |
| 620 | lastError = new Error(`reportCompletion retry failed with status ${retryRes.status}`) |
| 621 | } else { |
| 622 | lastError = new Error(`reportCompletion failed with status ${res.status}`) |
| 623 | } |
| 624 | } catch (err) { |
| 625 | lastError = toError(err) |
| 626 | } |
| 627 | |
| 628 | if (attempt < 2) { |
| 629 | await sleep(250) |
| 630 | } |
| 631 | } |
| 632 |
no test coverage detected