uploadUserSettingsInBackground method

Future<void> uploadUserSettingsInBackground()

Upload local settings to remote (interactive CLI only). Called from preAction. Runs in background — caller should not await.

Implementation

Future<void> uploadUserSettingsInBackground() async {
  try {
    if (!isUploadFeatureEnabled() ||
        !isUploadGateEnabled() ||
        !isInteractive() ||
        !_isUsingOAuthInternal()) {
      logDiagnostics('info', 'settings_sync_upload_skipped');
      logEvent('tengu_settings_sync_upload_skipped_ineligible', {});
      return;
    }

    logDiagnostics('info', 'settings_sync_upload_starting');
    final result = await _fetchUserSettings();
    if (!result.success) {
      logDiagnostics('warn', 'settings_sync_upload_fetch_failed');
      logEvent('tengu_settings_sync_upload_fetch_failed', {});
      return;
    }

    final projectId = await getRepoRemoteHash();
    final localEntries = await _buildEntriesFromLocalFiles(projectId);
    final remoteEntries = result.isEmpty
        ? <String, String>{}
        : result.data!.content.entries;

    final changedEntries = <String, String>{};
    for (final entry in localEntries.entries) {
      if (remoteEntries[entry.key] != entry.value) {
        changedEntries[entry.key] = entry.value;
      }
    }

    final entryCount = changedEntries.length;
    if (entryCount == 0) {
      logDiagnostics('info', 'settings_sync_upload_no_changes');
      logEvent('tengu_settings_sync_upload_skipped', {});
      return;
    }

    final uploadResult = await _uploadUserSettings(changedEntries);
    if (uploadResult.success) {
      logDiagnostics('info', 'settings_sync_upload_success');
      logEvent('tengu_settings_sync_upload_success', {
        'entryCount': entryCount,
      });
    } else {
      logDiagnostics('warn', 'settings_sync_upload_failed');
      logEvent('tengu_settings_sync_upload_failed', {
        'entryCount': entryCount,
      });
    }
  } catch (_) {
    logDiagnostics('error', 'settings_sync_unexpected_error');
  }
}