runAiinConnectCliFlow function

Future<AiinConnectResult?> runAiinConnectCliFlow({
  1. required void onStatus(
    1. String
    ),
  2. Future<bool> openBrowserFn(
    1. String
    ) = openBrowser,
  3. Client? client,
  4. String authBaseUrl = aiinAuthBaseUrl,
  5. Duration timeout = const Duration(minutes: 5),
})

Runs the full AIIN connect flow for CLI/desktop hosts:

  1. binds the loopback callback server (ephemeral port),
  2. initiates the OAuth proxy flow for provider,
  3. opens the system browser at the sign-in URL (openBrowserFn),
  4. catches the redirect, exchanges the code for JWTs,
  5. registers an API key with the access JWT.

Returns null on timeout/cancel or a reported service error (status is printed through onStatus); throws AiinAuthException never — service failures surface through onStatus so callers can treat null as "not connected".

Implementation

Future<AiinConnectResult?> runAiinConnectCliFlow({
  required void Function(String) onStatus,
  Future<bool> Function(String) openBrowserFn = openBrowser,
  http.Client? client,
  String authBaseUrl = aiinAuthBaseUrl,
  Duration timeout = const Duration(minutes: 5),
}) async {
  final server = AiinCallbackServer();
  final redirectUri = await server.start(timeout: timeout);
  try {
    // The hosted sign-in page: AIIN lists every provider, runs the whole
    // round-trip (silent for an existing session) and redirects back with
    // the code + our state.
    final state = aiinGenerateState();
    final loginUrl = buildAiinLoginUrl(
      redirectUri: redirectUri,
      state: state,
      clientType: 'desktop',
      authBaseUrl: authBaseUrl,
    );
    onStatus('listening for the AIIN callback on $redirectUri');
    await _openAiinBrowser(loginUrl.toString(), openBrowserFn, onStatus);
    final callback = await server.waitForCallback();
    return await _settleAiinCallback(
      callback,
      state,
      client: client,
      authBaseUrl: authBaseUrl,
      onStatus: onStatus,
    );
  } on AiinAuthException catch (error) {
    onStatus('AIIN sign-in failed: ${error.message}');
    return null;
  } finally {
    await server.close();
  }
}