( credentials: Credentials, )
| 113 | } |
| 114 | |
| 115 | export async function fetchSessions( |
| 116 | credentials: Credentials, |
| 117 | ): Promise<DecryptedSession[]> { |
| 118 | const res = await fetch(`${SERVER_URL}/v1/sessions`, { |
| 119 | headers: authHeaders(credentials.token), |
| 120 | }); |
| 121 | if (!res.ok) throw new Error(`Failed to fetch sessions: ${res.status}`); |
| 122 | |
| 123 | const data = await res.json(); |
| 124 | const sessions: DecryptedSession[] = []; |
| 125 | |
| 126 | for (const raw of data.sessions as RawSession[]) { |
| 127 | try { |
| 128 | const { key, variant } = resolveSessionKey( |
| 129 | raw.dataEncryptionKey, |
| 130 | credentials, |
| 131 | ); |
| 132 | const metadata = raw.metadata |
| 133 | ? ((await decrypt(key, variant, decodeBase64(raw.metadata))) as SessionMetadata | null) |
| 134 | : null; |
| 135 | const agentState = raw.agentState |
| 136 | ? ((await decrypt(key, variant, decodeBase64(raw.agentState))) as Record<string, unknown> | null) |
| 137 | : null; |
| 138 | |
| 139 | sessions.push({ |
| 140 | id: raw.id, |
| 141 | seq: raw.seq, |
| 142 | metadata, |
| 143 | metadataVersion: raw.metadataVersion, |
| 144 | agentState, |
| 145 | agentStateVersion: raw.agentStateVersion, |
| 146 | encryptionKey: key, |
| 147 | encryptionVariant: variant, |
| 148 | active: raw.active, |
| 149 | activeAt: raw.activeAt, |
| 150 | createdAt: raw.createdAt, |
| 151 | updatedAt: raw.updatedAt, |
| 152 | }); |
| 153 | } catch (err) { |
| 154 | console.warn('Failed to decrypt session:', raw.id, err); |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | return sessions; |
| 159 | } |
| 160 | |
| 161 | export async function fetchMessages( |
| 162 | credentials: Credentials, |
no test coverage detected