neoagent 2.4.2-beta.4 → 2.4.2-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.env.example CHANGED
@@ -67,15 +67,6 @@ NEOAGENT_RELEASE_CHANNEL=stable
67
67
  # Example: http://localhost:3333,https://yourdomain.com
68
68
  ALLOWED_ORIGINS=
69
69
 
70
- ########################################
71
- # Analytics
72
- ########################################
73
-
74
- # Mixpanel project token used by the Flutter app.
75
- # Leave this blank to disable analytics, or set your own public project token.
76
- # Keep the token below if you want to support the development of NeoAgent with anonymous usage analytics.
77
- NEOAGENT_MIXPANEL_TOKEN=4a47ae6a05cf39a8faf0438a1200dde6
78
-
79
70
  ########################################
80
71
  # Service email
81
72
  ########################################
@@ -127,16 +127,6 @@ Optional. When configured, NeoAgent uses SMTP for account flows: signup confirma
127
127
 
128
128
  Runtime profiles (`trusted-host`, `secure-vm`) are set in user settings, not `.env`. See [Capabilities: Runtime Modes](capabilities.md#runtime-modes).
129
129
 
130
- ## Analytics
131
-
132
- NeoAgent can send anonymous usage events to your own Mixpanel project. Events cover navigation and feature usage only — no message content, credentials, or personal data.
133
-
134
- | Variable | Description |
135
- |---|---|
136
- | `NEOAGENT_MIXPANEL_TOKEN` | Public Mixpanel project token — leave blank to disable analytics |
137
-
138
- When analytics is enabled, the web client shows a cookie-consent banner until accepted or declined.
139
-
140
130
  ## Runtime Paths
141
131
 
142
132
  | Path | Contents |
@@ -28,7 +28,6 @@ import 'src/android_apk_drop_zone.dart';
28
28
  import 'src/android_launcher_bridge.dart';
29
29
  import 'src/app_launch_bridge.dart';
30
30
  import 'src/app_release_updater.dart' as app_release_updater;
31
- import 'src/analytics_service.dart';
32
31
  import 'src/backend_client.dart';
33
32
  import 'src/desktop_companion.dart';
34
33
  import 'src/desktop_screen_capture.dart';
@@ -37,7 +37,6 @@ class NeoAgentController extends ChangeNotifier {
37
37
  final OAuthLauncher _oauthLauncher;
38
38
  final app_release_updater.AppReleaseUpdater _appReleaseUpdater =
39
39
  app_release_updater.AppReleaseUpdater();
40
- final AppAnalytics _analytics = AppAnalytics();
41
40
  final LiveVoiceCapture _liveVoiceCapture = LiveVoiceCapture();
42
41
  final DesktopScreenCapture _desktopScreenCapture =
43
42
  createDesktopScreenCapture();
@@ -104,10 +103,6 @@ class NeoAgentController extends ChangeNotifier {
104
103
  bool networkStatusKnown = false;
105
104
  bool _desktopFloatingToolbarPopupRequested = false;
106
105
  bool _voiceAssistantIncludeScreenContext = false;
107
- bool _didTrackAppOpen = false;
108
- bool _analyticsConfigured = false;
109
- bool _analyticsConsentResolved = false;
110
- bool _analyticsConsentGranted = false;
111
106
 
112
107
  io.Socket? get streamSocket => socketConnected ? _socket : null;
113
108
 
@@ -343,7 +338,6 @@ class NeoAgentController extends ChangeNotifier {
343
338
  _diagnosticLogSubscription?.cancel();
344
339
  _connectivitySubscription?.cancel();
345
340
  _appReleaseUpdater.dispose();
346
- unawaited(_analytics.dispose());
347
341
  _desktopCompanion.removeListener(notifyListeners);
348
342
  unawaited(_desktopCompanion.disconnect());
349
343
  _recordingBridge.removeListener(_handleRecordingBridgeChanged);
@@ -374,12 +368,6 @@ class NeoAgentController extends ChangeNotifier {
374
368
  bool get canCaptureVoiceAssistantScreenContext =>
375
369
  _desktopScreenCapture.isSupported;
376
370
 
377
- bool get showAnalyticsConsentBanner =>
378
- kIsWeb && _analyticsConfigured && !_analyticsConsentResolved;
379
-
380
- bool get analyticsConsentGranted =>
381
- _analyticsConsentResolved && _analyticsConsentGranted;
382
-
383
371
  bool get isLiveVoiceCaptureEngaged =>
384
372
  _isStartingLiveVoice || _liveVoiceCaptureActive;
385
373
 
@@ -735,7 +723,6 @@ class NeoAgentController extends ChangeNotifier {
735
723
  appUpdateAutoCheckEnabled =
736
724
  _prefs?.getBool('app.update.autoCheckEnabled') ?? true;
737
725
  installedAppVersion = await _safeLoadInstalledAppVersion();
738
- await _initializeAnalytics();
739
726
  await refreshConnectivityStatus();
740
727
  if (_connectivityPluginAvailable && _connectivitySubscription == null) {
741
728
  try {
@@ -898,105 +885,6 @@ class NeoAgentController extends ChangeNotifier {
898
885
  }
899
886
  }
900
887
 
901
- Future<void> _initializeAnalytics() async {
902
- try {
903
- final runtimeConfig = await _backendClient.fetchRuntimeConfig(backendUrl);
904
- final analyticsConfig = runtimeConfig['analytics'];
905
- final mixpanelConfig = analyticsConfig is Map
906
- ? analyticsConfig['mixpanel']
907
- : null;
908
- final token = mixpanelConfig is Map
909
- ? mixpanelConfig['token']?.toString()
910
- : null;
911
- _analyticsConfigured = token != null && token.trim().isNotEmpty;
912
- final consentState = _prefs?.getBool('analytics.cookieConsent');
913
- // On web, require explicit opt-in (GDPR). On native, consent is implicit
914
- // unless the user has previously declined.
915
- _analyticsConsentResolved = consentState != null || !kIsWeb;
916
- _analyticsConsentGranted = kIsWeb
917
- ? consentState == true
918
- : consentState != false;
919
- await _analytics.initialize(
920
- token: token,
921
- consentGranted: _analyticsConsentGranted,
922
- );
923
- _trackAppOpenedIfNeeded();
924
- } catch (_) {
925
- _analyticsConfigured = false;
926
- _analyticsConsentResolved = false;
927
- _analyticsConsentGranted = false;
928
- await _analytics.initialize(token: null, consentGranted: false);
929
- }
930
- }
931
-
932
- void _trackAppOpenedIfNeeded({String? consentSource}) {
933
- if (!_analytics.enabled || _didTrackAppOpen) {
934
- return;
935
- }
936
- _didTrackAppOpen = true;
937
- unawaited(
938
- _analytics.trackAppOpened(
939
- appMode: appMode.name,
940
- platform: _analyticsPlatformLabel(),
941
- backendMode: backendUrl.trim().isEmpty ? 'same_origin' : 'custom',
942
- selectedSection: selectedSection.label,
943
- deploymentProfile: deploymentProfile,
944
- authenticated: isAuthenticated,
945
- ),
946
- );
947
- if (consentSource != null) {
948
- unawaited(
949
- _analytics.track(
950
- 'analytics_consent_granted',
951
- properties: <String, Object?>{'consent_source': consentSource},
952
- ),
953
- );
954
- }
955
- }
956
-
957
- String _analyticsPlatformLabel() {
958
- if (kIsWeb) {
959
- return 'web';
960
- }
961
- switch (defaultTargetPlatform) {
962
- case TargetPlatform.android:
963
- return 'android';
964
- case TargetPlatform.iOS:
965
- return 'ios';
966
- case TargetPlatform.macOS:
967
- return 'macos';
968
- case TargetPlatform.windows:
969
- return 'windows';
970
- case TargetPlatform.linux:
971
- return 'linux';
972
- case TargetPlatform.fuchsia:
973
- return 'fuchsia';
974
- }
975
- }
976
-
977
- Future<void> acceptAnalyticsConsent() async {
978
- if (!_analyticsConfigured) {
979
- return;
980
- }
981
- _analyticsConsentResolved = true;
982
- _analyticsConsentGranted = true;
983
- await _prefs?.setBool('analytics.cookieConsent', true);
984
- await _analytics.setConsentGranted(true);
985
- _trackAppOpenedIfNeeded(consentSource: 'banner');
986
- notifyListeners();
987
- }
988
-
989
- Future<void> declineAnalyticsConsent() async {
990
- if (!_analyticsConfigured) {
991
- return;
992
- }
993
- _analyticsConsentResolved = true;
994
- _analyticsConsentGranted = false;
995
- await _prefs?.setBool('analytics.cookieConsent', false);
996
- await _analytics.setConsentGranted(false);
997
- notifyListeners();
998
- }
999
-
1000
888
  Future<void> setAppUpdateChannel(String channel) async {
1001
889
  final normalized = channel.trim().toLowerCase() == 'beta'
1002
890
  ? 'beta'
@@ -1021,7 +909,6 @@ class NeoAgentController extends ChangeNotifier {
1021
909
  if (isCheckingAppUpdate) {
1022
910
  return;
1023
911
  }
1024
- unawaited(_analytics.trackAppUpdateCheck(silent: silent));
1025
912
  if (!appUpdaterConfigured) {
1026
913
  appUpdateErrorMessage = kIsWeb
1027
914
  ? null
@@ -1120,11 +1007,6 @@ class NeoAgentController extends ChangeNotifier {
1120
1007
  isBooting = true;
1121
1008
  notifyListeners();
1122
1009
  await bootstrap();
1123
- unawaited(
1124
- _analytics.trackBackendUrlSaved(
1125
- backendMode: backendUrl.trim().isEmpty ? 'same_origin' : 'custom',
1126
- ),
1127
- );
1128
1010
  return true;
1129
1011
  } catch (error) {
1130
1012
  errorMessage = _friendlyErrorMessage(error);
@@ -1370,14 +1252,6 @@ class NeoAgentController extends ChangeNotifier {
1370
1252
  _clearQrLoginChallenge();
1371
1253
  await _persistCredentials();
1372
1254
  await refresh();
1373
- if (isAuthenticated) {
1374
- unawaited(
1375
- _analytics.trackSignedIn(
1376
- authMethod: authMethod,
1377
- isRegistration: isRegistration,
1378
- ),
1379
- );
1380
- }
1381
1255
  if (!isAuthenticated && retentionErrorMessage != null) {
1382
1256
  errorMessage = retentionErrorMessage;
1383
1257
  }
@@ -1596,7 +1470,6 @@ class NeoAgentController extends ChangeNotifier {
1596
1470
  final logoutFuture = _backendClient.logout(backendUrl);
1597
1471
  _authCycle += 1;
1598
1472
  _clearAuthenticatedState();
1599
- unawaited(_analytics.trackSignedOut());
1600
1473
  isAuthenticating = true;
1601
1474
  notifyListeners();
1602
1475
 
@@ -1614,7 +1487,6 @@ class NeoAgentController extends ChangeNotifier {
1614
1487
  notifyListeners();
1615
1488
  try {
1616
1489
  await _backendClient.completeOnboarding(backendUrl);
1617
- unawaited(_analytics.trackOnboardingDismissed());
1618
1490
  if (isAuthenticated && user != null) {
1619
1491
  user!['hasCompletedOnboarding'] = true;
1620
1492
  }
@@ -1795,14 +1667,6 @@ class NeoAgentController extends ChangeNotifier {
1795
1667
  if (section == AppSection.accountSettings) {
1796
1668
  unawaited(refreshAccountSettings());
1797
1669
  }
1798
- if (previousSection != section) {
1799
- unawaited(
1800
- _analytics.trackSectionChanged(
1801
- section: section.label,
1802
- previousSection: previousSection.label,
1803
- ),
1804
- );
1805
- }
1806
1670
  notifyListeners();
1807
1671
  }
1808
1672
 
@@ -2651,9 +2515,6 @@ class NeoAgentController extends ChangeNotifier {
2651
2515
  }
2652
2516
 
2653
2517
  Future<void> refreshWidgets({bool all = false}) async {
2654
- if (all) {
2655
- unawaited(_analytics.trackWidgetRefreshRequested(all: all));
2656
- }
2657
2518
  widgets = _decodeModelList(
2658
2519
  'widgets',
2659
2520
  await _backendClient.fetchWidgets(
@@ -3661,7 +3522,6 @@ class NeoAgentController extends ChangeNotifier {
3661
3522
  }
3662
3523
 
3663
3524
  Future<void> startBackgroundRecording() async {
3664
- unawaited(_analytics.trackRecordingStarted(kind: 'background'));
3665
3525
  await _startRecordingCapture(
3666
3526
  logKey: 'start_background',
3667
3527
  payload: buildAndroidBackgroundRecordingPayload(),
@@ -3688,7 +3548,6 @@ class NeoAgentController extends ChangeNotifier {
3688
3548
  }
3689
3549
  return;
3690
3550
  }
3691
- unawaited(_analytics.trackRecordingStarted(kind: 'desktop'));
3692
3551
  await _startRecordingCapture(
3693
3552
  logKey: 'start_desktop',
3694
3553
  payload: buildDesktopRecordingPayload(),
@@ -4072,16 +3931,6 @@ class NeoAgentController extends ChangeNotifier {
4072
3931
  notifyListeners();
4073
3932
  try {
4074
3933
  _desktopFloatingToolbarPopupRequested = false;
4075
- unawaited(
4076
- _analytics.trackRecordingStopped(
4077
- kind:
4078
- recordingRuntime.supportsBackgroundMic &&
4079
- !recordingRuntime.supportsScreenAndMic
4080
- ? 'background'
4081
- : 'desktop',
4082
- stopReason: stopReason,
4083
- ),
4084
- );
4085
3934
  await _recordingBridge.stopActiveRecording();
4086
3935
  if (isAndroidBackgroundStop) {
4087
3936
  await Future<void>.delayed(const Duration(milliseconds: 600));
@@ -4735,13 +4584,6 @@ class NeoAgentController extends ChangeNotifier {
4735
4584
  if (outgoingTask.isEmpty || (isSendingMessage && !canSteerLiveRun)) {
4736
4585
  return;
4737
4586
  }
4738
- unawaited(
4739
- _analytics.trackChatMessageSent(
4740
- length: trimmed.length,
4741
- steeringLiveRun: canSteerLiveRun,
4742
- ),
4743
- );
4744
-
4745
4587
  final optimistic = ChatEntry(
4746
4588
  id: '',
4747
4589
  role: 'user',
@@ -5204,7 +5046,6 @@ class NeoAgentController extends ChangeNotifier {
5204
5046
  errorMessage = null;
5205
5047
  notifyListeners();
5206
5048
  try {
5207
- unawaited(_analytics.trackAppUpdateTriggered());
5208
5049
  await _backendClient.triggerUpdate(backendUrl);
5209
5050
  await refreshUpdateStatus();
5210
5051
  } catch (error) {
@@ -6083,7 +5924,6 @@ class NeoAgentController extends ChangeNotifier {
6083
5924
  return;
6084
5925
  }
6085
5926
  _startManualRunCooldown('task', '$id');
6086
- unawaited(_analytics.trackTaskRunRequested(taskId: id));
6087
5927
  await _backendClient.runSavedTask(backendUrl, id);
6088
5928
  await refreshTasks();
6089
5929
  await refreshRunsOnly();
@@ -4842,6 +4842,7 @@ class _TaskTriggerOption {
4842
4842
  required this.description,
4843
4843
  required this.icon,
4844
4844
  this.providerKey,
4845
+ this.appKey,
4845
4846
  });
4846
4847
 
4847
4848
  final String type;
@@ -4854,6 +4855,12 @@ class _TaskTriggerOption {
4854
4855
  /// When set, the task editor shows a connected-account dropdown instead of
4855
4856
  /// a raw connection ID text field.
4856
4857
  final String? providerKey;
4858
+
4859
+ /// The app within the provider (matches [OfficialIntegrationAppItem.id]).
4860
+ /// Narrows account lookup to just the relevant app so multi-app providers
4861
+ /// (e.g. Google Workspace with Gmail + Drive + Calendar) don't show
4862
+ /// duplicate accounts.
4863
+ final String? appKey;
4857
4864
  }
4858
4865
 
4859
4866
  const List<_TaskTriggerOption> _taskTriggerOptions = <_TaskTriggerOption>[
@@ -4878,6 +4885,7 @@ const List<_TaskTriggerOption> _taskTriggerOptions = <_TaskTriggerOption>[
4878
4885
  description: 'Run when a matching Gmail message arrives.',
4879
4886
  icon: Icons.mail_rounded,
4880
4887
  providerKey: 'google_workspace',
4888
+ appKey: 'gmail',
4881
4889
  ),
4882
4890
  _TaskTriggerOption(
4883
4891
  type: 'outlook_email_received',
@@ -4886,6 +4894,7 @@ const List<_TaskTriggerOption> _taskTriggerOptions = <_TaskTriggerOption>[
4886
4894
  description: 'Run when a matching Outlook email arrives.',
4887
4895
  icon: Icons.markunread_rounded,
4888
4896
  providerKey: 'microsoft_365',
4897
+ appKey: 'outlook',
4889
4898
  ),
4890
4899
  _TaskTriggerOption(
4891
4900
  type: 'slack_message_received',
@@ -4894,6 +4903,7 @@ const List<_TaskTriggerOption> _taskTriggerOptions = <_TaskTriggerOption>[
4894
4903
  description: 'Run when a Slack message matches the selected scope.',
4895
4904
  icon: Icons.forum_rounded,
4896
4905
  providerKey: 'slack',
4906
+ appKey: 'slack',
4897
4907
  ),
4898
4908
  _TaskTriggerOption(
4899
4909
  type: 'teams_message_received',
@@ -4902,6 +4912,7 @@ const List<_TaskTriggerOption> _taskTriggerOptions = <_TaskTriggerOption>[
4902
4912
  description: 'Run when a Teams chat message matches the selected scope.',
4903
4913
  icon: Icons.groups_rounded,
4904
4914
  providerKey: 'microsoft_365',
4915
+ appKey: 'teams',
4905
4916
  ),
4906
4917
  _TaskTriggerOption(
4907
4918
  type: 'weather_event',
@@ -4911,6 +4922,7 @@ const List<_TaskTriggerOption> _taskTriggerOptions = <_TaskTriggerOption>[
4911
4922
  'Run when configured weather events are forecast for a location.',
4912
4923
  icon: Icons.cloudy_snowing,
4913
4924
  providerKey: 'weather',
4925
+ appKey: 'forecast',
4914
4926
  ),
4915
4927
  _TaskTriggerOption(
4916
4928
  type: 'whatsapp_personal_message_received',
@@ -4919,6 +4931,7 @@ const List<_TaskTriggerOption> _taskTriggerOptions = <_TaskTriggerOption>[
4919
4931
  description: 'Run on inbound personal WhatsApp messages.',
4920
4932
  icon: Icons.chat_bubble_rounded,
4921
4933
  providerKey: 'whatsapp_personal',
4934
+ appKey: 'personal',
4922
4935
  ),
4923
4936
  ];
4924
4937
 
@@ -5578,13 +5591,16 @@ class _TasksPanelState extends State<TasksPanel> {
5578
5591
  List<OfficialIntegrationAccountItem> _connectedAccountsForTrigger(
5579
5592
  String triggerType,
5580
5593
  ) {
5581
- final providerKey = _taskTriggerOptionForType(triggerType).providerKey;
5594
+ final option = _taskTriggerOptionForType(triggerType);
5595
+ final providerKey = option.providerKey;
5582
5596
  if (providerKey == null) return const <OfficialIntegrationAccountItem>[];
5597
+ final appKey = option.appKey;
5583
5598
  final seen = <int>{};
5584
5599
  final result = <OfficialIntegrationAccountItem>[];
5585
5600
  for (final integration in controller.officialIntegrations) {
5586
5601
  if (integration.id != providerKey) continue;
5587
5602
  for (final app in integration.apps) {
5603
+ if (appKey != null && app.id != appKey) continue;
5588
5604
  for (final account in app.accounts) {
5589
5605
  if (account.connected && seen.add(account.id)) {
5590
5606
  result.add(account);
@@ -636,28 +636,6 @@ class _NeoAgentAppState extends State<NeoAgentApp>
636
636
  ),
637
637
  ),
638
638
  ),
639
- if (!_desktopToolbarWindowMode &&
640
- !_desktopAssistantPopupWindowMode &&
641
- _controller.showAnalyticsConsentBanner)
642
- Positioned(
643
- left: 0,
644
- right: 0,
645
- bottom: 0,
646
- child: SafeArea(
647
- top: false,
648
- child: Padding(
649
- padding: const EdgeInsets.fromLTRB(12, 0, 12, 12),
650
- child: Center(
651
- child: ConstrainedBox(
652
- constraints: const BoxConstraints(maxWidth: 980),
653
- child: _GlobalAnalyticsConsentBanner(
654
- controller: _controller,
655
- ),
656
- ),
657
- ),
658
- ),
659
- ),
660
- ),
661
639
  if (_supportsDesktopShell &&
662
640
  !_desktopToolbarWindowMode &&
663
641
  !_desktopAssistantPopupWindowMode)
@@ -2393,167 +2393,6 @@ class _GlobalWebUpdateBanner extends StatelessWidget {
2393
2393
  }
2394
2394
  }
2395
2395
 
2396
- class _GlobalAnalyticsConsentBanner extends StatelessWidget {
2397
- const _GlobalAnalyticsConsentBanner({required this.controller});
2398
-
2399
- final NeoAgentController controller;
2400
-
2401
- @override
2402
- Widget build(BuildContext context) {
2403
- return LayoutBuilder(
2404
- builder: (context, constraints) {
2405
- final compact = constraints.maxWidth < 700;
2406
- final body = Text(
2407
- 'NeoAgent uses anonymous analytics to understand startup, navigation, and setup flows. No messages, credentials, or personal content are collected.',
2408
- style: TextStyle(color: _textSecondary, height: 1.35),
2409
- );
2410
- return Material(
2411
- color: Colors.transparent,
2412
- child: _GlassSurface(
2413
- borderRadius: BorderRadius.circular(22),
2414
- blurSigma: 26,
2415
- fillColor: _bgCard.withValues(alpha: 0.94),
2416
- borderColor: _accent.withValues(alpha: 0.18),
2417
- overlayGradient: LinearGradient(
2418
- colors: <Color>[
2419
- _accent.withValues(alpha: 0.12),
2420
- _bgCard.withValues(alpha: 0.88),
2421
- _bgSecondary.withValues(alpha: 0.86),
2422
- ],
2423
- stops: const <double>[0, 0.22, 1],
2424
- begin: const Alignment(-1, -1),
2425
- end: const Alignment(1, 1),
2426
- ),
2427
- boxShadow: <BoxShadow>[
2428
- BoxShadow(
2429
- color: Colors.black.withValues(alpha: 0.22),
2430
- blurRadius: 34,
2431
- offset: const Offset(0, 18),
2432
- ),
2433
- BoxShadow(
2434
- color: _accent.withValues(alpha: 0.1),
2435
- blurRadius: 24,
2436
- offset: const Offset(0, 8),
2437
- ),
2438
- ],
2439
- padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 16),
2440
- child: compact
2441
- ? Column(
2442
- crossAxisAlignment: CrossAxisAlignment.start,
2443
- children: <Widget>[
2444
- Row(
2445
- crossAxisAlignment: CrossAxisAlignment.start,
2446
- children: <Widget>[
2447
- Container(
2448
- padding: const EdgeInsets.all(10),
2449
- decoration: BoxDecoration(
2450
- color: _accent.withValues(alpha: 0.16),
2451
- shape: BoxShape.circle,
2452
- border: Border.all(
2453
- color: _accent.withValues(alpha: 0.24),
2454
- ),
2455
- ),
2456
- child: Icon(
2457
- Icons.cookie_outlined,
2458
- color: _accent,
2459
- size: 22,
2460
- ),
2461
- ),
2462
- const SizedBox(width: 12),
2463
- Expanded(
2464
- child: Column(
2465
- crossAxisAlignment: CrossAxisAlignment.start,
2466
- children: <Widget>[
2467
- Text(
2468
- 'Analytics cookies',
2469
- style: TextStyle(
2470
- color: _textPrimary,
2471
- fontSize: 15,
2472
- fontWeight: FontWeight.w700,
2473
- ),
2474
- ),
2475
- const SizedBox(height: 6),
2476
- body,
2477
- ],
2478
- ),
2479
- ),
2480
- ],
2481
- ),
2482
- const SizedBox(height: 14),
2483
- Row(
2484
- children: <Widget>[
2485
- Expanded(
2486
- child: OutlinedButton(
2487
- onPressed: controller.declineAnalyticsConsent,
2488
- child: const Text('Decline'),
2489
- ),
2490
- ),
2491
- const SizedBox(width: 10),
2492
- Expanded(
2493
- child: FilledButton(
2494
- onPressed: controller.acceptAnalyticsConsent,
2495
- child: const Text('Allow analytics'),
2496
- ),
2497
- ),
2498
- ],
2499
- ),
2500
- ],
2501
- )
2502
- : Row(
2503
- crossAxisAlignment: CrossAxisAlignment.center,
2504
- children: <Widget>[
2505
- Container(
2506
- padding: const EdgeInsets.all(10),
2507
- decoration: BoxDecoration(
2508
- color: _accent.withValues(alpha: 0.16),
2509
- shape: BoxShape.circle,
2510
- border: Border.all(
2511
- color: _accent.withValues(alpha: 0.24),
2512
- ),
2513
- ),
2514
- child: Icon(
2515
- Icons.cookie_outlined,
2516
- color: _accent,
2517
- size: 22,
2518
- ),
2519
- ),
2520
- const SizedBox(width: 14),
2521
- Expanded(
2522
- child: Column(
2523
- crossAxisAlignment: CrossAxisAlignment.start,
2524
- children: <Widget>[
2525
- Text(
2526
- 'Analytics cookies',
2527
- style: TextStyle(
2528
- color: _textPrimary,
2529
- fontSize: 15,
2530
- fontWeight: FontWeight.w700,
2531
- ),
2532
- ),
2533
- const SizedBox(height: 6),
2534
- body,
2535
- ],
2536
- ),
2537
- ),
2538
- const SizedBox(width: 16),
2539
- OutlinedButton(
2540
- onPressed: controller.declineAnalyticsConsent,
2541
- child: const Text('Decline'),
2542
- ),
2543
- const SizedBox(width: 10),
2544
- FilledButton(
2545
- onPressed: controller.acceptAnalyticsConsent,
2546
- child: const Text('Allow analytics'),
2547
- ),
2548
- ],
2549
- ),
2550
- ),
2551
- );
2552
- },
2553
- );
2554
- }
2555
- }
2556
-
2557
2396
  class _DesktopCloseDecision {
2558
2397
  const _DesktopCloseDecision({
2559
2398
  required this.keepRunning,
@@ -12,7 +12,6 @@ import file_picker
12
12
  import flutter_secure_storage_macos
13
13
  import geolocator_apple
14
14
  import hotkey_manager_macos
15
- import mixpanel_flutter
16
15
  import mobile_scanner
17
16
  import package_info_plus
18
17
  import path_provider_foundation
@@ -33,7 +32,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
33
32
  FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
34
33
  GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin"))
35
34
  HotkeyManagerMacosPlugin.register(with: registry.registrar(forPlugin: "HotkeyManagerMacosPlugin"))
36
- MixpanelFlutterPlugin.register(with: registry.registrar(forPlugin: "MixpanelFlutterPlugin"))
37
35
  MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin"))
38
36
  FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
39
37
  PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
@@ -598,14 +598,6 @@ packages:
598
598
  url: "https://pub.dev"
599
599
  source: hosted
600
600
  version: "1.18.0"
601
- mixpanel_flutter:
602
- dependency: "direct main"
603
- description:
604
- name: mixpanel_flutter
605
- sha256: "6962b8ce61eb6202d6545bee648e21a7bc9f7e804fa293912e9673329f499ece"
606
- url: "https://pub.dev"
607
- source: hosted
608
- version: "2.7.0"
609
601
  mobile_scanner:
610
602
  dependency: "direct main"
611
603
  description:
@@ -15,7 +15,6 @@ dependencies:
15
15
  google_fonts: ^8.1.0
16
16
  image: ^4.5.4
17
17
  http: ^1.5.0
18
- mixpanel_flutter: ^2.6.1
19
18
  connectivity_plus: 6.1.5
20
19
  shared_preferences: ^2.5.3
21
20
  flutter_secure_storage: ^9.2.2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neoagent",
3
- "version": "2.4.2-beta.4",
3
+ "version": "2.4.2-beta.5",
4
4
  "description": "Proactive personal AI agent with no limits",
5
5
  "license": "AGPL-3.0-only",
6
6
  "main": "server/index.js",