connect static method

Future<DevSessionClient> connect({
  1. required String projectDirectory,
  2. String? sessionId,
})

Resolves only sessions in this project. Stale descriptors are ignored; multiple live sessions require an explicit id, never an arbitrary choice.

Implementation

static Future<DevSessionClient> connect({
  required String projectDirectory,
  String? sessionId,
}) async {
  final directory = Directory(
    '${_projectRoot(projectDirectory).path}/.dart_tool/fleury/sessions',
  );
  final candidates = <DevSessionClient>[];
  if (await directory.exists()) {
    await for (final file in directory.list()) {
      if (file is! File || !file.path.endsWith('.json')) continue;
      DevSessionClient? client;
      try {
        final data = jsonDecode(await file.readAsString()) as Map;
        if (data['protocol'] != devSessionProtocolVersion ||
            (sessionId != null && data['sessionId'] != sessionId)) {
          continue;
        }
        client = DevSessionClient._(
          data['sessionId'] as String,
          data['port'] as int,
          data['token'] as String,
        );
        await client.request('status').timeout(const Duration(seconds: 2));
        candidates.add(client);
      } catch (_) {
        client?.close();
      }
    }
  }
  if (candidates.length == 1) return candidates.single;
  for (final candidate in candidates) {
    candidate.close();
  }
  throw DevSessionException(
    candidates.isEmpty
        ? 'No live Fleury development session. Start fleury run --agent in this project.'
        : 'Multiple Fleury sessions: ${candidates.map((c) => c.sessionId).join(', ')}. Pass --session=<id>.',
  );
}