( sessionId: string, ingressUrl: string, )
| 1585 | } |
| 1586 | |
| 1587 | export async function hydrateRemoteSession( |
| 1588 | sessionId: string, |
| 1589 | ingressUrl: string, |
| 1590 | ): Promise<boolean> { |
| 1591 | switchSession(asSessionId(sessionId)) |
| 1592 | |
| 1593 | const project = getProject() |
| 1594 | |
| 1595 | try { |
| 1596 | const remoteLogs = |
| 1597 | (await sessionIngress.getSessionLogs(sessionId, ingressUrl)) || [] |
| 1598 | |
| 1599 | // Ensure the project directory and session file exist |
| 1600 | const projectDir = getProjectDir(getOriginalCwd()) |
| 1601 | await mkdir(projectDir, { recursive: true, mode: 0o700 }) |
| 1602 | |
| 1603 | const sessionFile = getTranscriptPathForSession(sessionId) |
| 1604 | |
| 1605 | // Replace local logs with remote logs. writeFile truncates, so no |
| 1606 | // unlink is needed; an empty remoteLogs array produces an empty file. |
| 1607 | const content = remoteLogs.map(e => jsonStringify(e) + '\n').join('') |
| 1608 | await writeFile(sessionFile, content, { encoding: 'utf8', mode: 0o600 }) |
| 1609 | |
| 1610 | logForDebugging(`Hydrated ${remoteLogs.length} entries from remote`) |
| 1611 | return remoteLogs.length > 0 |
| 1612 | } catch (error) { |
| 1613 | logForDebugging(`Error hydrating session from remote: ${error}`) |
| 1614 | logForDiagnosticsNoPII('error', 'hydrate_remote_session_fail') |
| 1615 | return false |
| 1616 | } finally { |
| 1617 | // Set remote ingress URL after hydrating the remote session |
| 1618 | // to ensure we've always synced with the remote session |
| 1619 | // prior to enabling persistence |
| 1620 | project.setRemoteIngressUrl(ingressUrl) |
| 1621 | } |
| 1622 | } |
| 1623 | |
| 1624 | /** |
| 1625 | * Hydrate session state from CCR v2 internal events. |
no test coverage detected