(message: StdoutMessage)
| 570 | // ----------------------------------------------------------------------- |
| 571 | |
| 572 | async write(message: StdoutMessage): Promise<void> { |
| 573 | const authHeaders = this.getAuthHeaders() |
| 574 | if (Object.keys(authHeaders).length === 0) { |
| 575 | logForDebugging('SSETransport: No session token available for POST') |
| 576 | logForDiagnosticsNoPII('warn', 'cli_sse_post_no_token') |
| 577 | return |
| 578 | } |
| 579 | |
| 580 | const headers: Record<string, string> = { |
| 581 | ...authHeaders, |
| 582 | 'Content-Type': 'application/json', |
| 583 | 'anthropic-version': '2023-06-01', |
| 584 | 'User-Agent': getClaudeCodeUserAgent(), |
| 585 | } |
| 586 | |
| 587 | logForDebugging( |
| 588 | `SSETransport: POST body keys=${Object.keys(message as Record<string, unknown>).join(',')}`, |
| 589 | ) |
| 590 | |
| 591 | for (let attempt = 1; attempt <= POST_MAX_RETRIES; attempt++) { |
| 592 | try { |
| 593 | const response = await axios.post(this.postUrl, message, { |
| 594 | headers, |
| 595 | validateStatus: alwaysValidStatus, |
| 596 | }) |
| 597 | |
| 598 | if (response.status === 200 || response.status === 201) { |
| 599 | logForDebugging(`SSETransport: POST success type=${message.type}`) |
| 600 | return |
| 601 | } |
| 602 | |
| 603 | logForDebugging( |
| 604 | `SSETransport: POST ${response.status} body=${jsonStringify(response.data).slice(0, 200)}`, |
| 605 | ) |
| 606 | // 4xx errors (except 429) are permanent - don't retry |
| 607 | if ( |
| 608 | response.status >= 400 && |
| 609 | response.status < 500 && |
| 610 | response.status !== 429 |
| 611 | ) { |
| 612 | logForDebugging( |
| 613 | `SSETransport: POST returned ${response.status} (client error), not retrying`, |
| 614 | ) |
| 615 | logForDiagnosticsNoPII('warn', 'cli_sse_post_client_error', { |
| 616 | status: response.status, |
| 617 | }) |
| 618 | return |
| 619 | } |
| 620 | |
| 621 | // 429 or 5xx - retry |
| 622 | logForDebugging( |
| 623 | `SSETransport: POST returned ${response.status}, attempt ${attempt}/${POST_MAX_RETRIES}`, |
| 624 | ) |
| 625 | logForDiagnosticsNoPII('warn', 'cli_sse_post_retryable_error', { |
| 626 | status: response.status, |
| 627 | attempt, |
| 628 | }) |
| 629 | } catch (error) { |
no test coverage detected