( sessionId: string, ingressUrl: string, )
| 1622 | } |
| 1623 | |
| 1624 | export async function hydrateRemoteSession( |
| 1625 | sessionId: string, |
| 1626 | ingressUrl: string, |
| 1627 | ): Promise<boolean> { |
| 1628 | switchSession(asSessionId(sessionId)) |
| 1629 | |
| 1630 | const project = getProject() |
| 1631 | |
| 1632 | try { |
| 1633 | const remoteLogs = |
| 1634 | (await sessionIngress.getSessionLogs(sessionId, ingressUrl)) || [] |
| 1635 | |
| 1636 | // Ensure the project directory and session file exist |
| 1637 | const projectDir = getProjectDir(getOriginalCwd()) |
| 1638 | await mkdir(projectDir, { recursive: true, mode: 0o700 }) |
| 1639 | |
| 1640 | const sessionFile = getTranscriptPathForSession(sessionId) |
| 1641 | |
| 1642 | // Replace local logs with remote logs. writeFile truncates, so no |
| 1643 | // unlink is needed; an empty remoteLogs array produces an empty file. |
| 1644 | const content = remoteLogs.map(e => jsonStringify(e) + '\n').join('') |
| 1645 | await writeFile(sessionFile, content, { encoding: 'utf8', mode: 0o600 }) |
| 1646 | |
| 1647 | logForDebugging(`Hydrated ${remoteLogs.length} entries from remote`) |
| 1648 | return remoteLogs.length > 0 |
| 1649 | } catch (error) { |
| 1650 | logForDebugging(`Error hydrating session from remote: ${error}`) |
| 1651 | logForDiagnosticsNoPII('error', 'hydrate_remote_session_fail') |
| 1652 | return false |
| 1653 | } finally { |
| 1654 | // Set remote ingress URL after hydrating the remote session |
| 1655 | // to ensure we've always synced with the remote session |
| 1656 | // prior to enabling persistence |
| 1657 | project.setRemoteIngressUrl(ingressUrl) |
| 1658 | } |
| 1659 | } |
| 1660 | |
| 1661 | /** |
| 1662 | * Hydrate session state from CCR v2 internal events. |
no test coverage detected