(
sessionId: string,
title: string,
opts?: { baseUrl?: string; getAccessToken?: () => string | undefined },
)
| 336 | * Errors are swallowed — title sync is best-effort. |
| 337 | */ |
| 338 | export async function updateBridgeSessionTitle( |
| 339 | sessionId: string, |
| 340 | title: string, |
| 341 | opts?: { baseUrl?: string; getAccessToken?: () => string | undefined }, |
| 342 | ): Promise<void> { |
| 343 | const { getClaudeAIOAuthTokens } = await import('../utils/auth.js') |
| 344 | const { getOrganizationUUID } = await import('../services/oauth/client.js') |
| 345 | const { getOauthConfig } = await import('../constants/oauth.js') |
| 346 | const { getOAuthHeaders } = await import('../utils/teleport/api.js') |
| 347 | const { default: axios } = await import('axios') |
| 348 | const { isSelfHostedBridge } = await import('./bridgeConfig.js') |
| 349 | |
| 350 | const accessToken = |
| 351 | opts?.getAccessToken?.() ?? getClaudeAIOAuthTokens()?.accessToken |
| 352 | if (!accessToken) { |
| 353 | logForDebugging('[bridge] No access token for session title update') |
| 354 | return |
| 355 | } |
| 356 | |
| 357 | const orgUUID = isSelfHostedBridge() |
| 358 | ? 'self-hosted' |
| 359 | : await getOrganizationUUID() |
| 360 | if (!orgUUID) { |
| 361 | logForDebugging('[bridge] No org UUID for session title update') |
| 362 | return |
| 363 | } |
| 364 | |
| 365 | const headers = { |
| 366 | ...getOAuthHeaders(accessToken), |
| 367 | 'anthropic-beta': 'ccr-byoc-2025-07-29', |
| 368 | 'x-organization-uuid': orgUUID, |
| 369 | } |
| 370 | |
| 371 | // Compat gateway only accepts session_* (compat/convert.go:27). v2 callers |
| 372 | // pass raw cse_*; retag here so all callers can pass whatever they hold. |
| 373 | // Idempotent for v1's session_* and bridgeMain's pre-converted compatSessionId. |
| 374 | const compatId = toCompatSessionId(sessionId) |
| 375 | const url = `${opts?.baseUrl ?? getOauthConfig().BASE_API_URL}/v1/sessions/${compatId}` |
| 376 | logForDebugging(`[bridge] Updating session title: ${compatId} → ${title}`) |
| 377 | |
| 378 | try { |
| 379 | const response = await axios.patch( |
| 380 | url, |
| 381 | { title }, |
| 382 | { headers, timeout: 10_000, validateStatus: s => s < 500 }, |
| 383 | ) |
| 384 | |
| 385 | if (response.status === 200) { |
| 386 | logForDebugging(`[bridge] Session title updated successfully`) |
| 387 | } else { |
| 388 | const detail = extractErrorDetail(response.data) |
| 389 | logForDebugging( |
| 390 | `[bridge] Session title update failed with status ${response.status}${detail ? `: ${detail}` : ''}`, |
| 391 | ) |
| 392 | } |
| 393 | } catch (err: unknown) { |
| 394 | logForDebugging( |
| 395 | `[bridge] Session title update request failed: ${errorMessage(err)}`, |
no test coverage detected