(
sessionId: string,
afterId: string | null = null,
opts?: { skipMetadata?: boolean },
)
| 720 | * per-call GET /v1/sessions/{id} when branch/status aren't needed. |
| 721 | */ |
| 722 | export async function pollRemoteSessionEvents( |
| 723 | sessionId: string, |
| 724 | afterId: string | null = null, |
| 725 | opts?: { skipMetadata?: boolean }, |
| 726 | ): Promise<PollRemoteSessionResponse> { |
| 727 | const accessToken = getClaudeAIOAuthTokens()?.accessToken; |
| 728 | if (!accessToken) { |
| 729 | throw new Error('No access token for polling'); |
| 730 | } |
| 731 | |
| 732 | const orgUUID = await getOrganizationUUID(); |
| 733 | if (!orgUUID) { |
| 734 | throw new Error('No org UUID for polling'); |
| 735 | } |
| 736 | |
| 737 | const headers = { |
| 738 | ...getOAuthHeaders(accessToken), |
| 739 | 'anthropic-beta': 'ccr-byoc-2025-07-29', |
| 740 | 'x-organization-uuid': orgUUID, |
| 741 | }; |
| 742 | const eventsUrl = `${getOauthConfig().BASE_API_URL}/v1/sessions/${sessionId}/events`; |
| 743 | |
| 744 | type EventsResponse = { |
| 745 | data: unknown[]; |
| 746 | has_more: boolean; |
| 747 | first_id: string | null; |
| 748 | last_id: string | null; |
| 749 | }; |
| 750 | |
| 751 | // Cap is a safety valve against stuck cursors; steady-state is 0–1 pages. |
| 752 | const MAX_EVENT_PAGES = 50; |
| 753 | const sdkMessages: SDKMessage[] = []; |
| 754 | let cursor = afterId; |
| 755 | for (let page = 0; page < MAX_EVENT_PAGES; page++) { |
| 756 | const eventsResponse = await axios.get(eventsUrl, { |
| 757 | headers, |
| 758 | params: cursor ? { after_id: cursor } : undefined, |
| 759 | timeout: 30000, |
| 760 | }); |
| 761 | |
| 762 | if (eventsResponse.status !== 200) { |
| 763 | throw new Error(`Failed to fetch session events: ${eventsResponse.statusText}`); |
| 764 | } |
| 765 | |
| 766 | const eventsData: EventsResponse = eventsResponse.data; |
| 767 | if (!eventsData?.data || !Array.isArray(eventsData.data)) { |
| 768 | throw new Error('Invalid events response'); |
| 769 | } |
| 770 | |
| 771 | for (const event of eventsData.data) { |
| 772 | if (event && typeof event === 'object' && 'type' in event) { |
| 773 | if (event.type === 'env_manager_log' || event.type === 'control_response') { |
| 774 | continue; |
| 775 | } |
| 776 | if ('session_id' in event) { |
| 777 | sdkMessages.push(event as SDKMessage); |
| 778 | } |
| 779 | } |
no test coverage detected