| 1197 | } |
| 1198 | |
| 1199 | func readSessionLedger(path string) (contract.MemorySessionLedgerResponse, error) { |
| 1200 | data, err := os.ReadFile(path) |
| 1201 | if err != nil { |
| 1202 | return contract.MemorySessionLedgerResponse{}, fmt.Errorf( |
| 1203 | "daemon: read memory session ledger %q: %w", |
| 1204 | path, |
| 1205 | err, |
| 1206 | ) |
| 1207 | } |
| 1208 | checksum := sha256.Sum256(data) |
| 1209 | scanner := bufio.NewScanner(bytes.NewReader(data)) |
| 1210 | scanner.Buffer(make([]byte, 0, 64*1024), 1024*1024) |
| 1211 | response := contract.MemorySessionLedgerResponse{ |
| 1212 | Events: make([]contract.MemorySessionLedgerEntryPayload, 0), |
| 1213 | } |
| 1214 | for scanner.Scan() { |
| 1215 | raw := bytes.TrimSpace(scanner.Bytes()) |
| 1216 | if len(raw) == 0 { |
| 1217 | continue |
| 1218 | } |
| 1219 | var lineType sessionLedgerLineType |
| 1220 | if err := json.Unmarshal(raw, &lineType); err != nil { |
| 1221 | return contract.MemorySessionLedgerResponse{}, fmt.Errorf("daemon: decode ledger line type: %w", err) |
| 1222 | } |
| 1223 | switch lineType.Type { |
| 1224 | case "ledger_meta": |
| 1225 | var meta sessionLedgerMetaLine |
| 1226 | if err := json.Unmarshal(raw, &meta); err != nil { |
| 1227 | return contract.MemorySessionLedgerResponse{}, fmt.Errorf("daemon: decode ledger meta: %w", err) |
| 1228 | } |
| 1229 | response.Meta = contract.MemorySessionLedgerMetaPayload{ |
| 1230 | Version: meta.Version, |
| 1231 | SessionID: strings.TrimSpace(meta.SessionID), |
| 1232 | WorkspaceID: strings.TrimSpace(meta.WorkspaceID), |
| 1233 | RootSessionID: strings.TrimSpace(meta.RootSessionID), |
| 1234 | ParentSessionID: strings.TrimSpace(meta.SpawnParentID), |
| 1235 | SpawnDepth: meta.SpawnDepth, |
| 1236 | Path: path, |
| 1237 | Checksum: hex.EncodeToString(checksum[:]), |
| 1238 | CreatedAt: parseMemoryTime(meta.StartedAt), |
| 1239 | } |
| 1240 | if stoppedAt := parseMemoryTime(meta.EndedAt); !stoppedAt.IsZero() { |
| 1241 | response.Meta.StoppedAt = &stoppedAt |
| 1242 | } |
| 1243 | case "session_event": |
| 1244 | var event sessionLedgerEventLine |
| 1245 | if err := json.Unmarshal(raw, &event); err != nil { |
| 1246 | return contract.MemorySessionLedgerResponse{}, fmt.Errorf("daemon: decode ledger event: %w", err) |
| 1247 | } |
| 1248 | response.Events = append(response.Events, contract.MemorySessionLedgerEntryPayload{ |
| 1249 | Sequence: event.Sequence, |
| 1250 | EventType: strings.TrimSpace(event.EventType), |
| 1251 | EmittedAt: parseMemoryTime(event.Timestamp), |
| 1252 | Payload: ledgerPayload(event.Content), |
| 1253 | }) |
| 1254 | } |
| 1255 | } |
| 1256 | if err := scanner.Err(); err != nil { |