neoagent 3.1.1-beta.9 → 3.2.0
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 +2 -2
- package/README.md +5 -1
- package/docs/architecture.md +1 -1
- package/docs/benchmarking.md +68 -87
- package/docs/capabilities.md +1 -1
- package/docs/clients-and-devices.md +3 -4
- package/docs/configuration.md +1 -1
- package/docs/devices.md +1 -2
- package/docs/health.md +24 -0
- package/docs/index.md +2 -2
- package/docs/integrations-architecture.md +6 -0
- package/docs/integrations.md +15 -1
- package/docs/models.md +1 -1
- package/docs/persistence.md +1 -1
- package/docs/why-neoagent.md +1 -1
- package/flutter_app/README.md +0 -5
- package/flutter_app/android/app/src/main/AndroidManifest.xml +0 -14
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/MainActivity.kt +0 -98
- package/flutter_app/lib/main.dart +0 -6
- package/flutter_app/lib/main_app_shell.dart +0 -2
- package/flutter_app/lib/main_controller.dart +2 -867
- package/flutter_app/lib/main_devices.dart +0 -73
- package/flutter_app/lib/main_integrations.dart +339 -187
- package/flutter_app/lib/main_launcher.dart +2 -212
- package/flutter_app/lib/main_models.dart +0 -259
- package/flutter_app/lib/main_navigation.dart +2 -14
- package/flutter_app/lib/main_operations.dart +322 -364
- package/flutter_app/lib/main_runtime.dart +9 -208
- package/flutter_app/lib/main_settings.dart +17 -199
- package/flutter_app/lib/main_shared.dart +20 -591
- package/flutter_app/lib/main_timeline.dart +26 -122
- package/flutter_app/lib/main_voice_assistant.dart +0 -5
- package/flutter_app/lib/src/backend_client.dart +0 -102
- package/flutter_app/lib/src/desktop_companion_io.dart +1 -65
- package/flutter_app/lib/src/desktop_companion_stub.dart +0 -12
- package/flutter_app/linux/flutter/generated_plugin_registrant.cc +0 -4
- package/flutter_app/linux/flutter/generated_plugins.cmake +0 -1
- package/flutter_app/macos/Flutter/GeneratedPluginRegistrant.swift +0 -2
- package/flutter_app/macos/Podfile.lock +56 -5
- package/flutter_app/pubspec.lock +0 -7
- package/flutter_app/pubspec.yaml +0 -2
- package/flutter_app/web/index.html +174 -0
- package/flutter_app/windows/flutter/generated_plugin_registrant.cc +0 -3
- package/flutter_app/windows/flutter/generated_plugins.cmake +0 -1
- package/landing/index.html +0 -2
- package/lib/manager.js +1 -1
- package/lib/schema_migrations.js +75 -0
- package/package.json +1 -4
- package/server/db/database.js +1 -133
- package/server/http/middleware.js +2 -16
- package/server/http/routes.js +0 -2
- package/server/public/.last_build_id +1 -1
- package/server/public/assets/NOTICES +0 -25
- package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/public/index.html +174 -0
- package/server/public/main.dart.js +88081 -90036
- package/server/routes/auth.js +11 -2
- package/server/routes/settings.js +0 -5
- package/server/routes/voice_assistant.js +1 -128
- package/server/services/account/erasure.js +0 -3
- package/server/services/ai/deliverables/artifact_helpers.js +1 -1
- package/server/services/ai/loop/conversation_loop.js +6 -2
- package/server/services/ai/loop/tool_dispatch.js +0 -3
- package/server/services/ai/messagingFallback.js +1 -1
- package/server/services/ai/settings.js +0 -6
- package/server/services/ai/toolEvidence.js +1 -4
- package/server/services/ai/tools.js +0 -234
- package/server/services/desktop/auth.js +0 -3
- package/server/services/desktop/registry.js +2 -50
- package/server/services/integrations/neoarchive/provider.js +616 -0
- package/server/services/integrations/neorecall/client.js +140 -0
- package/server/services/integrations/neorecall/constants.js +87 -0
- package/server/services/integrations/neorecall/provider.js +163 -0
- package/server/services/integrations/registry.js +4 -2
- package/server/services/manager.js +0 -22
- package/server/services/memory/manager.js +44 -19
- package/server/services/memory/retrieval_reasoning.js +36 -14
- package/server/services/messaging/whatsapp.js +18 -0
- package/server/services/security/tool_categories.js +0 -5
- package/server/services/social_video/service.js +2 -20
- package/server/services/tasks/adapters/index.js +1 -1
- package/server/services/tasks/integration_runtime.js +3 -67
- package/server/services/tasks/runtime.js +1 -6
- package/server/services/tasks/task_repository.js +6 -13
- package/server/services/timeline/service.js +0 -224
- package/server/services/voice/message.js +0 -24
- package/server/services/voice/providers.js +42 -1
- package/server/services/voice/runtimeManager.js +9 -5
- package/server/services/voice/turnRunner.js +0 -22
- package/server/services/wearable/service.js +0 -5
- package/docs/recordings-and-health.md +0 -41
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingBootReceiver.kt +0 -21
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingForegroundService.kt +0 -586
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingStateStore.kt +0 -78
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingUploadClient.kt +0 -104
- package/flutter_app/lib/main_recordings.dart +0 -920
- package/flutter_app/lib/src/desktop_ocr_bridge.dart +0 -2
- package/flutter_app/lib/src/desktop_ocr_bridge_io.dart +0 -125
- package/flutter_app/lib/src/desktop_ocr_bridge_stub.dart +0 -30
- package/flutter_app/lib/src/desktop_passive_history.dart +0 -332
- package/flutter_app/lib/src/recording_bridge.dart +0 -232
- package/flutter_app/lib/src/recording_bridge_io.dart +0 -1027
- package/flutter_app/lib/src/recording_bridge_stub.dart +0 -120
- package/flutter_app/lib/src/recording_bridge_web.dart +0 -702
- package/flutter_app/lib/src/recording_chunk_queue.dart +0 -149
- package/flutter_app/lib/src/recording_chunk_queue_io.dart +0 -182
- package/flutter_app/lib/src/recording_payloads.dart +0 -95
- package/flutter_app/third_party/desktop_audio_capture/LICENSE +0 -21
- package/flutter_app/third_party/desktop_audio_capture/README.md +0 -262
- package/flutter_app/third_party/desktop_audio_capture/lib/audio_capture.dart +0 -65
- package/flutter_app/third_party/desktop_audio_capture/lib/config/mic_audio_config.dart +0 -153
- package/flutter_app/third_party/desktop_audio_capture/lib/config/system_adudio_config.dart +0 -110
- package/flutter_app/third_party/desktop_audio_capture/lib/mic/mic_audio_capture.dart +0 -461
- package/flutter_app/third_party/desktop_audio_capture/lib/model/audio_status.dart +0 -91
- package/flutter_app/third_party/desktop_audio_capture/lib/model/decibel_data.dart +0 -106
- package/flutter_app/third_party/desktop_audio_capture/lib/model/input_device_type.dart +0 -219
- package/flutter_app/third_party/desktop_audio_capture/lib/system/system_audio_capture.dart +0 -336
- package/flutter_app/third_party/desktop_audio_capture/linux/CMakeLists.txt +0 -101
- package/flutter_app/third_party/desktop_audio_capture/linux/audio_capture_plugin.cc +0 -692
- package/flutter_app/third_party/desktop_audio_capture/linux/include/audio_capture/audio_capture_plugin.h +0 -35
- package/flutter_app/third_party/desktop_audio_capture/linux/include/audio_capture/mic_capture_plugin.h +0 -36
- package/flutter_app/third_party/desktop_audio_capture/linux/include/desktop_audio_capture/audio_capture_plugin.h +0 -32
- package/flutter_app/third_party/desktop_audio_capture/linux/include/desktop_audio_capture/mic_capture_plugin.h +0 -32
- package/flutter_app/third_party/desktop_audio_capture/linux/mic_capture_plugin.cc +0 -878
- package/flutter_app/third_party/desktop_audio_capture/macos/Classes/AudioCapturePlugin.swift +0 -27
- package/flutter_app/third_party/desktop_audio_capture/macos/Classes/MicCapturePlugin.swift +0 -1172
- package/flutter_app/third_party/desktop_audio_capture/macos/Classes/SystemCapturePlugin.swift +0 -655
- package/flutter_app/third_party/desktop_audio_capture/macos/Resources/PrivacyInfo.xcprivacy +0 -12
- package/flutter_app/third_party/desktop_audio_capture/macos/desktop_audio_capture.podspec +0 -30
- package/flutter_app/third_party/desktop_audio_capture/pubspec.yaml +0 -87
- package/flutter_app/third_party/desktop_audio_capture/windows/CMakeLists.txt +0 -105
- package/flutter_app/third_party/desktop_audio_capture/windows/audio_capture_plugin.cpp +0 -80
- package/flutter_app/third_party/desktop_audio_capture/windows/audio_capture_plugin.h +0 -31
- package/flutter_app/third_party/desktop_audio_capture/windows/audio_capture_plugin_c_api.cpp +0 -12
- package/flutter_app/third_party/desktop_audio_capture/windows/include/audio_capture/audio_capture_plugin_c_api.h +0 -23
- package/flutter_app/third_party/desktop_audio_capture/windows/include/desktop_audio_capture/audio_capture_plugin.h +0 -25
- package/flutter_app/third_party/desktop_audio_capture/windows/mic_capture_plugin.cpp +0 -1117
- package/flutter_app/third_party/desktop_audio_capture/windows/mic_capture_plugin.h +0 -115
- package/flutter_app/third_party/desktop_audio_capture/windows/system_audio_capture_plugin.cpp +0 -777
- package/flutter_app/third_party/desktop_audio_capture/windows/system_audio_capture_plugin.h +0 -87
- package/server/routes/recordings.js +0 -335
- package/server/routes/screenHistory.js +0 -190
- package/server/services/ai/recordingInsights.js +0 -105
- package/server/services/integrations/neomail/provider.js +0 -993
- package/server/services/recordings/deepgram.js +0 -58
- package/server/services/recordings/manager.js +0 -1273
- package/server/services/tasks/adapters/neomail_email_received.js +0 -46
- package/server/services/voice/screenshotContext.js +0 -73
- package/server/services/voice/turnCoordinator.js +0 -51
|
@@ -418,7 +418,6 @@ List<AppSection> _mainSections(NeoAgentController controller) {
|
|
|
418
418
|
return <AppSection>[
|
|
419
419
|
AppSection.chat,
|
|
420
420
|
AppSection.timeline,
|
|
421
|
-
AppSection.recordings,
|
|
422
421
|
AppSection.devices,
|
|
423
422
|
AppSection.tasks,
|
|
424
423
|
AppSection.widgets,
|
|
@@ -2416,63 +2415,6 @@ class _DesktopCloseDecision {
|
|
|
2416
2415
|
final bool rememberChoice;
|
|
2417
2416
|
}
|
|
2418
2417
|
|
|
2419
|
-
class _RecordingPermissionBadge extends StatelessWidget {
|
|
2420
|
-
const _RecordingPermissionBadge({required this.label, required this.state});
|
|
2421
|
-
|
|
2422
|
-
final String label;
|
|
2423
|
-
final RecordingPermissionState state;
|
|
2424
|
-
|
|
2425
|
-
@override
|
|
2426
|
-
Widget build(BuildContext context) {
|
|
2427
|
-
final (color, icon, text) = switch (state) {
|
|
2428
|
-
RecordingPermissionState.granted => (
|
|
2429
|
-
_success,
|
|
2430
|
-
Icons.check_circle,
|
|
2431
|
-
'Ready',
|
|
2432
|
-
),
|
|
2433
|
-
RecordingPermissionState.denied => (
|
|
2434
|
-
_danger,
|
|
2435
|
-
Icons.lock_outline,
|
|
2436
|
-
'Blocked',
|
|
2437
|
-
),
|
|
2438
|
-
RecordingPermissionState.needsRestart => (
|
|
2439
|
-
_warning,
|
|
2440
|
-
Icons.restart_alt_rounded,
|
|
2441
|
-
'Restart needed',
|
|
2442
|
-
),
|
|
2443
|
-
RecordingPermissionState.unsupported => (
|
|
2444
|
-
_textSecondary,
|
|
2445
|
-
Icons.do_not_disturb_alt_outlined,
|
|
2446
|
-
'Unsupported',
|
|
2447
|
-
),
|
|
2448
|
-
RecordingPermissionState.unknown => (
|
|
2449
|
-
_warning,
|
|
2450
|
-
Icons.help_outline,
|
|
2451
|
-
'Check access',
|
|
2452
|
-
),
|
|
2453
|
-
};
|
|
2454
|
-
|
|
2455
|
-
return _GlassSurface(
|
|
2456
|
-
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 9),
|
|
2457
|
-
borderRadius: BorderRadius.circular(16),
|
|
2458
|
-
blurSigma: 10,
|
|
2459
|
-
fillColor: color.withValues(alpha: 0.09),
|
|
2460
|
-
borderColor: color.withValues(alpha: 0.22),
|
|
2461
|
-
child: Row(
|
|
2462
|
-
mainAxisSize: MainAxisSize.min,
|
|
2463
|
-
children: <Widget>[
|
|
2464
|
-
Icon(icon, size: 16, color: color),
|
|
2465
|
-
const SizedBox(width: 8),
|
|
2466
|
-
Text(
|
|
2467
|
-
'$label · $text',
|
|
2468
|
-
style: TextStyle(color: color, fontWeight: FontWeight.w700),
|
|
2469
|
-
),
|
|
2470
|
-
],
|
|
2471
|
-
),
|
|
2472
|
-
);
|
|
2473
|
-
}
|
|
2474
|
-
}
|
|
2475
|
-
|
|
2476
2418
|
class _CompanionPermissionBadge extends StatelessWidget {
|
|
2477
2419
|
const _CompanionPermissionBadge({required this.label, required this.state});
|
|
2478
2420
|
|
|
@@ -2514,254 +2456,6 @@ class _CompanionPermissionBadge extends StatelessWidget {
|
|
|
2514
2456
|
}
|
|
2515
2457
|
}
|
|
2516
2458
|
|
|
2517
|
-
class _AudioLevelBar extends StatelessWidget {
|
|
2518
|
-
const _AudioLevelBar({
|
|
2519
|
-
required this.label,
|
|
2520
|
-
required this.valueDb,
|
|
2521
|
-
required this.color,
|
|
2522
|
-
this.compact = false,
|
|
2523
|
-
});
|
|
2524
|
-
|
|
2525
|
-
final String label;
|
|
2526
|
-
final double valueDb;
|
|
2527
|
-
final Color color;
|
|
2528
|
-
final bool compact;
|
|
2529
|
-
|
|
2530
|
-
@override
|
|
2531
|
-
Widget build(BuildContext context) {
|
|
2532
|
-
final progress = ((valueDb + 72) / 72).clamp(0.0, 1.0);
|
|
2533
|
-
return _GlassSurface(
|
|
2534
|
-
width: compact ? 168 : 240,
|
|
2535
|
-
padding: const EdgeInsets.all(12),
|
|
2536
|
-
borderRadius: BorderRadius.circular(18),
|
|
2537
|
-
blurSigma: 10,
|
|
2538
|
-
fillColor: _bgCard.withValues(alpha: 0.88),
|
|
2539
|
-
borderColor: _borderLight,
|
|
2540
|
-
child: Column(
|
|
2541
|
-
crossAxisAlignment: CrossAxisAlignment.start,
|
|
2542
|
-
children: <Widget>[
|
|
2543
|
-
Row(
|
|
2544
|
-
children: <Widget>[
|
|
2545
|
-
Text(
|
|
2546
|
-
label,
|
|
2547
|
-
style: TextStyle(
|
|
2548
|
-
color: _textSecondary,
|
|
2549
|
-
fontSize: compact ? 11 : 12,
|
|
2550
|
-
fontWeight: FontWeight.w700,
|
|
2551
|
-
letterSpacing: 0.3,
|
|
2552
|
-
),
|
|
2553
|
-
),
|
|
2554
|
-
const Spacer(),
|
|
2555
|
-
Text(
|
|
2556
|
-
valueDb <= -119 ? 'Silent' : '${valueDb.toStringAsFixed(0)} dB',
|
|
2557
|
-
style: TextStyle(
|
|
2558
|
-
color: _textSecondary,
|
|
2559
|
-
fontSize: compact ? 11 : 12,
|
|
2560
|
-
),
|
|
2561
|
-
),
|
|
2562
|
-
],
|
|
2563
|
-
),
|
|
2564
|
-
const SizedBox(height: 10),
|
|
2565
|
-
ClipRRect(
|
|
2566
|
-
borderRadius: BorderRadius.circular(999),
|
|
2567
|
-
child: TweenAnimationBuilder<double>(
|
|
2568
|
-
tween: Tween<double>(begin: 0, end: progress),
|
|
2569
|
-
duration: const Duration(milliseconds: 220),
|
|
2570
|
-
curve: Curves.easeOutCubic,
|
|
2571
|
-
builder: (context, animatedValue, _) {
|
|
2572
|
-
return LinearProgressIndicator(
|
|
2573
|
-
value: animatedValue,
|
|
2574
|
-
minHeight: compact ? 7 : 8,
|
|
2575
|
-
color: color,
|
|
2576
|
-
backgroundColor: _borderLight,
|
|
2577
|
-
);
|
|
2578
|
-
},
|
|
2579
|
-
),
|
|
2580
|
-
),
|
|
2581
|
-
],
|
|
2582
|
-
),
|
|
2583
|
-
);
|
|
2584
|
-
}
|
|
2585
|
-
}
|
|
2586
|
-
|
|
2587
|
-
class _DesktopFloatingToolbar extends StatefulWidget {
|
|
2588
|
-
const _DesktopFloatingToolbar({required this.controller});
|
|
2589
|
-
|
|
2590
|
-
final NeoAgentController controller;
|
|
2591
|
-
|
|
2592
|
-
@override
|
|
2593
|
-
State<_DesktopFloatingToolbar> createState() =>
|
|
2594
|
-
_DesktopFloatingToolbarState();
|
|
2595
|
-
}
|
|
2596
|
-
|
|
2597
|
-
class _DesktopFloatingToolbarState extends State<_DesktopFloatingToolbar> {
|
|
2598
|
-
Timer? _ticker;
|
|
2599
|
-
|
|
2600
|
-
@override
|
|
2601
|
-
void initState() {
|
|
2602
|
-
super.initState();
|
|
2603
|
-
_syncTicker();
|
|
2604
|
-
}
|
|
2605
|
-
|
|
2606
|
-
@override
|
|
2607
|
-
void didUpdateWidget(covariant _DesktopFloatingToolbar oldWidget) {
|
|
2608
|
-
super.didUpdateWidget(oldWidget);
|
|
2609
|
-
_syncTicker();
|
|
2610
|
-
}
|
|
2611
|
-
|
|
2612
|
-
@override
|
|
2613
|
-
void dispose() {
|
|
2614
|
-
_ticker?.cancel();
|
|
2615
|
-
super.dispose();
|
|
2616
|
-
}
|
|
2617
|
-
|
|
2618
|
-
void _syncTicker() {
|
|
2619
|
-
final runtime = widget.controller.recordingRuntime;
|
|
2620
|
-
final shouldTick =
|
|
2621
|
-
runtime.active &&
|
|
2622
|
-
runtime.startedAt != null &&
|
|
2623
|
-
runtime.floatingToolbarVisible;
|
|
2624
|
-
if (!shouldTick) {
|
|
2625
|
-
_ticker?.cancel();
|
|
2626
|
-
_ticker = null;
|
|
2627
|
-
return;
|
|
2628
|
-
}
|
|
2629
|
-
_ticker ??= Timer.periodic(const Duration(seconds: 1), (_) {
|
|
2630
|
-
if (mounted) {
|
|
2631
|
-
setState(() {});
|
|
2632
|
-
}
|
|
2633
|
-
});
|
|
2634
|
-
}
|
|
2635
|
-
|
|
2636
|
-
@override
|
|
2637
|
-
Widget build(BuildContext context) {
|
|
2638
|
-
final controller = widget.controller;
|
|
2639
|
-
final runtime = controller.recordingRuntime;
|
|
2640
|
-
if (!runtime.supportsFloatingToolbar ||
|
|
2641
|
-
!runtime.active ||
|
|
2642
|
-
!runtime.floatingToolbarVisible) {
|
|
2643
|
-
return const SizedBox.shrink();
|
|
2644
|
-
}
|
|
2645
|
-
|
|
2646
|
-
final elapsed = runtime.startedAt == null
|
|
2647
|
-
? '00:00'
|
|
2648
|
-
: _formatDuration(
|
|
2649
|
-
DateTime.now().difference(runtime.startedAt!).inMilliseconds,
|
|
2650
|
-
);
|
|
2651
|
-
|
|
2652
|
-
return Positioned(
|
|
2653
|
-
top: 10,
|
|
2654
|
-
left: 0,
|
|
2655
|
-
right: 0,
|
|
2656
|
-
child: SafeArea(
|
|
2657
|
-
child: IgnorePointer(
|
|
2658
|
-
ignoring: false,
|
|
2659
|
-
child: Align(
|
|
2660
|
-
alignment: Alignment.topCenter,
|
|
2661
|
-
child: _DesktopFloatingToolbarSurface(
|
|
2662
|
-
controller: controller,
|
|
2663
|
-
elapsedLabel: elapsed,
|
|
2664
|
-
compactWindow: false,
|
|
2665
|
-
onOpenMainWindow: null,
|
|
2666
|
-
),
|
|
2667
|
-
),
|
|
2668
|
-
),
|
|
2669
|
-
),
|
|
2670
|
-
);
|
|
2671
|
-
}
|
|
2672
|
-
}
|
|
2673
|
-
|
|
2674
|
-
class _DetachedDesktopFloatingToolbarShell extends StatefulWidget {
|
|
2675
|
-
const _DetachedDesktopFloatingToolbarShell({
|
|
2676
|
-
required this.controller,
|
|
2677
|
-
required this.onOpenMainWindow,
|
|
2678
|
-
});
|
|
2679
|
-
|
|
2680
|
-
final NeoAgentController controller;
|
|
2681
|
-
final Future<void> Function() onOpenMainWindow;
|
|
2682
|
-
|
|
2683
|
-
@override
|
|
2684
|
-
State<_DetachedDesktopFloatingToolbarShell> createState() =>
|
|
2685
|
-
_DetachedDesktopFloatingToolbarShellState();
|
|
2686
|
-
}
|
|
2687
|
-
|
|
2688
|
-
class _DetachedDesktopFloatingToolbarShellState
|
|
2689
|
-
extends State<_DetachedDesktopFloatingToolbarShell> {
|
|
2690
|
-
Timer? _ticker;
|
|
2691
|
-
|
|
2692
|
-
@override
|
|
2693
|
-
void initState() {
|
|
2694
|
-
super.initState();
|
|
2695
|
-
_syncTicker();
|
|
2696
|
-
}
|
|
2697
|
-
|
|
2698
|
-
@override
|
|
2699
|
-
void didUpdateWidget(
|
|
2700
|
-
covariant _DetachedDesktopFloatingToolbarShell oldWidget,
|
|
2701
|
-
) {
|
|
2702
|
-
super.didUpdateWidget(oldWidget);
|
|
2703
|
-
_syncTicker();
|
|
2704
|
-
}
|
|
2705
|
-
|
|
2706
|
-
@override
|
|
2707
|
-
void dispose() {
|
|
2708
|
-
_ticker?.cancel();
|
|
2709
|
-
super.dispose();
|
|
2710
|
-
}
|
|
2711
|
-
|
|
2712
|
-
void _syncTicker() {
|
|
2713
|
-
final runtime = widget.controller.recordingRuntime;
|
|
2714
|
-
final shouldTick =
|
|
2715
|
-
runtime.active &&
|
|
2716
|
-
runtime.startedAt != null &&
|
|
2717
|
-
runtime.floatingToolbarVisible;
|
|
2718
|
-
if (!shouldTick) {
|
|
2719
|
-
_ticker?.cancel();
|
|
2720
|
-
_ticker = null;
|
|
2721
|
-
return;
|
|
2722
|
-
}
|
|
2723
|
-
_ticker ??= Timer.periodic(const Duration(seconds: 1), (_) {
|
|
2724
|
-
if (mounted) {
|
|
2725
|
-
setState(() {});
|
|
2726
|
-
}
|
|
2727
|
-
});
|
|
2728
|
-
}
|
|
2729
|
-
|
|
2730
|
-
@override
|
|
2731
|
-
Widget build(BuildContext context) {
|
|
2732
|
-
final runtime = widget.controller.recordingRuntime;
|
|
2733
|
-
if (!runtime.active || !runtime.floatingToolbarVisible) {
|
|
2734
|
-
return const SizedBox.shrink();
|
|
2735
|
-
}
|
|
2736
|
-
|
|
2737
|
-
final elapsed = runtime.startedAt == null
|
|
2738
|
-
? '00:00'
|
|
2739
|
-
: _formatDuration(
|
|
2740
|
-
DateTime.now().difference(runtime.startedAt!).inMilliseconds,
|
|
2741
|
-
);
|
|
2742
|
-
|
|
2743
|
-
return DecoratedBox(
|
|
2744
|
-
decoration: const BoxDecoration(color: Colors.transparent),
|
|
2745
|
-
child: Scaffold(
|
|
2746
|
-
backgroundColor: Colors.transparent,
|
|
2747
|
-
body: SafeArea(
|
|
2748
|
-
child: Center(
|
|
2749
|
-
child: Padding(
|
|
2750
|
-
padding: const EdgeInsets.all(10),
|
|
2751
|
-
child: _DesktopFloatingToolbarSurface(
|
|
2752
|
-
controller: widget.controller,
|
|
2753
|
-
elapsedLabel: elapsed,
|
|
2754
|
-
compactWindow: true,
|
|
2755
|
-
onOpenMainWindow: widget.onOpenMainWindow,
|
|
2756
|
-
),
|
|
2757
|
-
),
|
|
2758
|
-
),
|
|
2759
|
-
),
|
|
2760
|
-
),
|
|
2761
|
-
);
|
|
2762
|
-
}
|
|
2763
|
-
}
|
|
2764
|
-
|
|
2765
2459
|
bool _desktopAssistantUsesToggleControls() {
|
|
2766
2460
|
if (kIsWeb) {
|
|
2767
2461
|
return false;
|
|
@@ -2802,10 +2496,6 @@ String _desktopAssistantIdleHint() {
|
|
|
2802
2496
|
: 'Hold Ctrl+Shift+Space to talk';
|
|
2803
2497
|
}
|
|
2804
2498
|
|
|
2805
|
-
String _desktopAssistantScreenContextHint(bool enabled) {
|
|
2806
|
-
return enabled ? 'Current screen will be attached' : 'Audio only';
|
|
2807
|
-
}
|
|
2808
|
-
|
|
2809
2499
|
class _DesktopAssistantControlState {
|
|
2810
2500
|
const _DesktopAssistantControlState({
|
|
2811
2501
|
required this.isCapturing,
|
|
@@ -2819,17 +2509,13 @@ class _DesktopAssistantControlState {
|
|
|
2819
2509
|
required this.primaryIcon,
|
|
2820
2510
|
required this.primaryColor,
|
|
2821
2511
|
required this.idleHint,
|
|
2822
|
-
required this.screenContextHint,
|
|
2823
|
-
required this.sourceSummary,
|
|
2824
2512
|
});
|
|
2825
2513
|
|
|
2826
2514
|
factory _DesktopAssistantControlState.fromController(
|
|
2827
|
-
NeoAgentController controller,
|
|
2828
|
-
|
|
2829
|
-
}) {
|
|
2515
|
+
NeoAgentController controller,
|
|
2516
|
+
) {
|
|
2830
2517
|
final liveState = controller.voiceAssistantLiveState;
|
|
2831
2518
|
final isCapturing = controller.isLiveVoiceCaptureEngaged;
|
|
2832
|
-
final includeScreenContext = controller.voiceAssistantIncludeScreenContext;
|
|
2833
2519
|
final useToggleCapture = _desktopAssistantUsesToggleControls();
|
|
2834
2520
|
final transcriptPreview = liveState.partialTranscript.trim().isEmpty
|
|
2835
2521
|
? liveState.finalTranscript.trim()
|
|
@@ -2838,24 +2524,16 @@ class _DesktopAssistantControlState {
|
|
|
2838
2524
|
isCapturing: isCapturing,
|
|
2839
2525
|
isBusy: liveState.isBusy,
|
|
2840
2526
|
useToggleCapture: useToggleCapture,
|
|
2841
|
-
statusLabel:
|
|
2842
|
-
?
|
|
2843
|
-
: (
|
|
2844
|
-
|
|
2845
|
-
: _desktopAssistantStatusLabel(liveState.state)),
|
|
2846
|
-
statusColor: blockedHintVisible
|
|
2847
|
-
? _warning
|
|
2848
|
-
: (isCapturing ? _success : _accent),
|
|
2527
|
+
statusLabel: isCapturing
|
|
2528
|
+
? _desktopAssistantPrimaryLabel(true)
|
|
2529
|
+
: _desktopAssistantStatusLabel(liveState.state),
|
|
2530
|
+
statusColor: isCapturing ? _success : _accent,
|
|
2849
2531
|
transcriptPreview: transcriptPreview,
|
|
2850
2532
|
primaryLabel: _desktopAssistantPrimaryLabel(isCapturing),
|
|
2851
2533
|
primaryCaption: _desktopAssistantPrimaryCaption(isCapturing),
|
|
2852
2534
|
primaryIcon: isCapturing ? Icons.stop_rounded : Icons.mic,
|
|
2853
2535
|
primaryColor: isCapturing ? _warning : _success,
|
|
2854
2536
|
idleHint: _desktopAssistantIdleHint(),
|
|
2855
|
-
screenContextHint: _desktopAssistantScreenContextHint(
|
|
2856
|
-
includeScreenContext,
|
|
2857
|
-
),
|
|
2858
|
-
sourceSummary: includeScreenContext ? 'Mic + screen' : 'Direct mic',
|
|
2859
2537
|
);
|
|
2860
2538
|
}
|
|
2861
2539
|
|
|
@@ -2870,72 +2548,16 @@ class _DesktopAssistantControlState {
|
|
|
2870
2548
|
final IconData primaryIcon;
|
|
2871
2549
|
final Color primaryColor;
|
|
2872
2550
|
final String idleHint;
|
|
2873
|
-
final String screenContextHint;
|
|
2874
|
-
final String sourceSummary;
|
|
2875
|
-
}
|
|
2876
|
-
|
|
2877
|
-
class _VoiceAssistantScreenContextButton extends StatelessWidget {
|
|
2878
|
-
const _VoiceAssistantScreenContextButton({
|
|
2879
|
-
required this.controller,
|
|
2880
|
-
required this.compact,
|
|
2881
|
-
});
|
|
2882
|
-
|
|
2883
|
-
final NeoAgentController controller;
|
|
2884
|
-
final bool compact;
|
|
2885
|
-
|
|
2886
|
-
@override
|
|
2887
|
-
Widget build(BuildContext context) {
|
|
2888
|
-
final enabled = controller.voiceAssistantIncludeScreenContext;
|
|
2889
|
-
final onPressed = controller.canCaptureVoiceAssistantScreenContext
|
|
2890
|
-
? () {
|
|
2891
|
-
unawaited(controller.toggleVoiceAssistantScreenContext());
|
|
2892
|
-
}
|
|
2893
|
-
: null;
|
|
2894
|
-
|
|
2895
|
-
if (compact) {
|
|
2896
|
-
return IconButton(
|
|
2897
|
-
tooltip: enabled
|
|
2898
|
-
? 'Stop including the current screen'
|
|
2899
|
-
: 'Include the current screen',
|
|
2900
|
-
onPressed: onPressed,
|
|
2901
|
-
style: IconButton.styleFrom(
|
|
2902
|
-
visualDensity: VisualDensity.compact,
|
|
2903
|
-
padding: const EdgeInsets.all(8),
|
|
2904
|
-
minimumSize: const Size(30, 30),
|
|
2905
|
-
backgroundColor: enabled
|
|
2906
|
-
? _accent.withValues(alpha: 0.14)
|
|
2907
|
-
: _bgSecondary.withValues(alpha: 0.9),
|
|
2908
|
-
foregroundColor: enabled ? _accent : _textSecondary,
|
|
2909
|
-
),
|
|
2910
|
-
icon: Icon(
|
|
2911
|
-
enabled
|
|
2912
|
-
? Icons.desktop_windows_rounded
|
|
2913
|
-
: Icons.desktop_windows_outlined,
|
|
2914
|
-
size: 15,
|
|
2915
|
-
),
|
|
2916
|
-
);
|
|
2917
|
-
}
|
|
2918
|
-
|
|
2919
|
-
return _VoiceAssistantActionButton(
|
|
2920
|
-
icon: enabled
|
|
2921
|
-
? Icons.desktop_windows_rounded
|
|
2922
|
-
: Icons.desktop_windows_outlined,
|
|
2923
|
-
label: enabled ? 'Screen on' : 'Screen off',
|
|
2924
|
-
onTap: onPressed,
|
|
2925
|
-
);
|
|
2926
|
-
}
|
|
2927
2551
|
}
|
|
2928
2552
|
|
|
2929
2553
|
class _DesktopAssistantPopupShell extends StatelessWidget {
|
|
2930
2554
|
const _DesktopAssistantPopupShell({
|
|
2931
2555
|
required this.controller,
|
|
2932
|
-
required this.blockedHintVisible,
|
|
2933
2556
|
required this.onPrimaryAction,
|
|
2934
2557
|
required this.onCancel,
|
|
2935
2558
|
});
|
|
2936
2559
|
|
|
2937
2560
|
final NeoAgentController controller;
|
|
2938
|
-
final bool blockedHintVisible;
|
|
2939
2561
|
final Future<void> Function() onPrimaryAction;
|
|
2940
2562
|
final Future<void> Function() onCancel;
|
|
2941
2563
|
|
|
@@ -2943,7 +2565,6 @@ class _DesktopAssistantPopupShell extends StatelessWidget {
|
|
|
2943
2565
|
Widget build(BuildContext context) {
|
|
2944
2566
|
final assistantUi = _DesktopAssistantControlState.fromController(
|
|
2945
2567
|
controller,
|
|
2946
|
-
blockedHintVisible: blockedHintVisible,
|
|
2947
2568
|
);
|
|
2948
2569
|
|
|
2949
2570
|
return DecoratedBox(
|
|
@@ -3011,34 +2632,26 @@ class _DesktopAssistantPopupShell extends StatelessWidget {
|
|
|
3011
2632
|
fontSize: 12.5,
|
|
3012
2633
|
),
|
|
3013
2634
|
),
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
height: 1.35,
|
|
3025
|
-
),
|
|
2635
|
+
Text(
|
|
2636
|
+
assistantUi.transcriptPreview.isEmpty
|
|
2637
|
+
? assistantUi.idleHint
|
|
2638
|
+
: assistantUi.transcriptPreview,
|
|
2639
|
+
maxLines: 1,
|
|
2640
|
+
overflow: TextOverflow.ellipsis,
|
|
2641
|
+
style: TextStyle(
|
|
2642
|
+
color: _textMuted,
|
|
2643
|
+
fontSize: 11.5,
|
|
2644
|
+
height: 1.35,
|
|
3026
2645
|
),
|
|
2646
|
+
),
|
|
3027
2647
|
],
|
|
3028
2648
|
),
|
|
3029
2649
|
),
|
|
3030
2650
|
const SizedBox(width: 8),
|
|
3031
|
-
_VoiceAssistantScreenContextButton(
|
|
3032
|
-
controller: controller,
|
|
3033
|
-
compact: true,
|
|
3034
|
-
),
|
|
3035
|
-
const SizedBox(width: 4),
|
|
3036
2651
|
FilledButton.icon(
|
|
3037
|
-
onPressed:
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
unawaited(onPrimaryAction());
|
|
3041
|
-
},
|
|
2652
|
+
onPressed: () {
|
|
2653
|
+
unawaited(onPrimaryAction());
|
|
2654
|
+
},
|
|
3042
2655
|
style: FilledButton.styleFrom(
|
|
3043
2656
|
visualDensity: VisualDensity.compact,
|
|
3044
2657
|
padding: const EdgeInsets.symmetric(
|
|
@@ -3229,190 +2842,6 @@ class _DesktopAssistantWaveformState extends State<_DesktopAssistantWaveform>
|
|
|
3229
2842
|
}
|
|
3230
2843
|
}
|
|
3231
2844
|
|
|
3232
|
-
class _DesktopFloatingToolbarSurface extends StatelessWidget {
|
|
3233
|
-
const _DesktopFloatingToolbarSurface({
|
|
3234
|
-
required this.controller,
|
|
3235
|
-
required this.elapsedLabel,
|
|
3236
|
-
required this.compactWindow,
|
|
3237
|
-
required this.onOpenMainWindow,
|
|
3238
|
-
});
|
|
3239
|
-
|
|
3240
|
-
final NeoAgentController controller;
|
|
3241
|
-
final String elapsedLabel;
|
|
3242
|
-
final bool compactWindow;
|
|
3243
|
-
final Future<void> Function()? onOpenMainWindow;
|
|
3244
|
-
|
|
3245
|
-
@override
|
|
3246
|
-
Widget build(BuildContext context) {
|
|
3247
|
-
final runtime = controller.recordingRuntime;
|
|
3248
|
-
return Material(
|
|
3249
|
-
color: Colors.transparent,
|
|
3250
|
-
child: Container(
|
|
3251
|
-
constraints: BoxConstraints(
|
|
3252
|
-
maxWidth: compactWindow ? double.infinity : 680,
|
|
3253
|
-
),
|
|
3254
|
-
margin: compactWindow
|
|
3255
|
-
? EdgeInsets.zero
|
|
3256
|
-
: const EdgeInsets.symmetric(horizontal: 16),
|
|
3257
|
-
padding: EdgeInsets.symmetric(
|
|
3258
|
-
horizontal: compactWindow ? 10 : 14,
|
|
3259
|
-
vertical: compactWindow ? 8 : 12,
|
|
3260
|
-
),
|
|
3261
|
-
decoration: BoxDecoration(
|
|
3262
|
-
gradient: LinearGradient(
|
|
3263
|
-
colors: <Color>[
|
|
3264
|
-
_bgCard.withValues(alpha: 0.98),
|
|
3265
|
-
_bgCard.withValues(alpha: 0.92),
|
|
3266
|
-
],
|
|
3267
|
-
),
|
|
3268
|
-
borderRadius: BorderRadius.circular(compactWindow ? 22 : 24),
|
|
3269
|
-
border: Border.all(color: _borderLight),
|
|
3270
|
-
boxShadow: <BoxShadow>[
|
|
3271
|
-
BoxShadow(
|
|
3272
|
-
color: Colors.black.withValues(alpha: 0.24),
|
|
3273
|
-
blurRadius: 24,
|
|
3274
|
-
offset: const Offset(0, 12),
|
|
3275
|
-
),
|
|
3276
|
-
],
|
|
3277
|
-
),
|
|
3278
|
-
child: Wrap(
|
|
3279
|
-
spacing: 10,
|
|
3280
|
-
runSpacing: 10,
|
|
3281
|
-
crossAxisAlignment: WrapCrossAlignment.center,
|
|
3282
|
-
children: <Widget>[
|
|
3283
|
-
if (compactWindow)
|
|
3284
|
-
const _BrandLockup(
|
|
3285
|
-
logoSize: 34,
|
|
3286
|
-
titleFontSize: 16,
|
|
3287
|
-
direction: Axis.horizontal,
|
|
3288
|
-
spacing: 10,
|
|
3289
|
-
alignment: CrossAxisAlignment.start,
|
|
3290
|
-
),
|
|
3291
|
-
if (compactWindow)
|
|
3292
|
-
DragToMoveArea(
|
|
3293
|
-
child: Container(
|
|
3294
|
-
padding: const EdgeInsets.symmetric(
|
|
3295
|
-
horizontal: 8,
|
|
3296
|
-
vertical: 6,
|
|
3297
|
-
),
|
|
3298
|
-
decoration: BoxDecoration(
|
|
3299
|
-
color: _bgSecondary.withValues(alpha: 0.78),
|
|
3300
|
-
borderRadius: BorderRadius.circular(12),
|
|
3301
|
-
border: Border.all(color: _borderLight),
|
|
3302
|
-
),
|
|
3303
|
-
child: Icon(
|
|
3304
|
-
Icons.drag_indicator_rounded,
|
|
3305
|
-
size: 14,
|
|
3306
|
-
color: _textMuted,
|
|
3307
|
-
),
|
|
3308
|
-
),
|
|
3309
|
-
),
|
|
3310
|
-
Container(
|
|
3311
|
-
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
|
3312
|
-
decoration: BoxDecoration(
|
|
3313
|
-
color: (runtime.paused ? _warning : _danger).withValues(
|
|
3314
|
-
alpha: 0.10,
|
|
3315
|
-
),
|
|
3316
|
-
borderRadius: BorderRadius.circular(16),
|
|
3317
|
-
border: Border.all(
|
|
3318
|
-
color: (runtime.paused ? _warning : _danger).withValues(
|
|
3319
|
-
alpha: 0.20,
|
|
3320
|
-
),
|
|
3321
|
-
),
|
|
3322
|
-
),
|
|
3323
|
-
child: Row(
|
|
3324
|
-
mainAxisSize: MainAxisSize.min,
|
|
3325
|
-
children: <Widget>[
|
|
3326
|
-
Icon(
|
|
3327
|
-
runtime.paused
|
|
3328
|
-
? Icons.pause_circle_outline
|
|
3329
|
-
: Icons.fiber_manual_record_rounded,
|
|
3330
|
-
color: runtime.paused ? _warning : _danger,
|
|
3331
|
-
size: 18,
|
|
3332
|
-
),
|
|
3333
|
-
const SizedBox(width: 8),
|
|
3334
|
-
Text(
|
|
3335
|
-
runtime.paused ? 'Paused' : 'Recording',
|
|
3336
|
-
style: TextStyle(
|
|
3337
|
-
color: runtime.paused ? _warning : _danger,
|
|
3338
|
-
fontSize: 12,
|
|
3339
|
-
fontWeight: FontWeight.w800,
|
|
3340
|
-
),
|
|
3341
|
-
),
|
|
3342
|
-
const SizedBox(width: 10),
|
|
3343
|
-
Text(
|
|
3344
|
-
elapsedLabel,
|
|
3345
|
-
style: TextStyle(
|
|
3346
|
-
color: _textPrimary,
|
|
3347
|
-
fontSize: 12,
|
|
3348
|
-
fontWeight: FontWeight.w700,
|
|
3349
|
-
),
|
|
3350
|
-
),
|
|
3351
|
-
],
|
|
3352
|
-
),
|
|
3353
|
-
),
|
|
3354
|
-
_AudioLevelBar(
|
|
3355
|
-
label: 'MIC',
|
|
3356
|
-
valueDb: runtime.microphoneLevelDb,
|
|
3357
|
-
color: _accent,
|
|
3358
|
-
compact: true,
|
|
3359
|
-
),
|
|
3360
|
-
_AudioLevelBar(
|
|
3361
|
-
label: 'SYSTEM',
|
|
3362
|
-
valueDb: runtime.systemAudioLevelDb,
|
|
3363
|
-
color: _accentAlt,
|
|
3364
|
-
compact: true,
|
|
3365
|
-
),
|
|
3366
|
-
if (compactWindow && onOpenMainWindow != null)
|
|
3367
|
-
IconButton(
|
|
3368
|
-
tooltip: 'Open NeoAgent',
|
|
3369
|
-
onPressed: onOpenMainWindow,
|
|
3370
|
-
style: IconButton.styleFrom(
|
|
3371
|
-
backgroundColor: _bgSecondary,
|
|
3372
|
-
foregroundColor: _textPrimary,
|
|
3373
|
-
),
|
|
3374
|
-
icon: const Icon(Icons.open_in_full_rounded),
|
|
3375
|
-
),
|
|
3376
|
-
IconButton(
|
|
3377
|
-
tooltip: runtime.paused ? 'Resume recording' : 'Pause recording',
|
|
3378
|
-
onPressed: runtime.paused
|
|
3379
|
-
? controller.resumeDesktopRecording
|
|
3380
|
-
: controller.pauseDesktopRecording,
|
|
3381
|
-
style: IconButton.styleFrom(
|
|
3382
|
-
backgroundColor: _bgSecondary,
|
|
3383
|
-
foregroundColor: _textPrimary,
|
|
3384
|
-
),
|
|
3385
|
-
icon: Icon(
|
|
3386
|
-
runtime.paused ? Icons.play_arrow_rounded : Icons.pause_rounded,
|
|
3387
|
-
),
|
|
3388
|
-
),
|
|
3389
|
-
IconButton(
|
|
3390
|
-
tooltip: 'Stop recording',
|
|
3391
|
-
onPressed: controller.isStoppingRecording
|
|
3392
|
-
? null
|
|
3393
|
-
: controller.stopRecording,
|
|
3394
|
-
style: IconButton.styleFrom(
|
|
3395
|
-
backgroundColor: _danger.withValues(alpha: 0.12),
|
|
3396
|
-
foregroundColor: _danger,
|
|
3397
|
-
),
|
|
3398
|
-
icon: const Icon(Icons.stop_rounded),
|
|
3399
|
-
),
|
|
3400
|
-
IconButton(
|
|
3401
|
-
tooltip: 'Hide floating bar',
|
|
3402
|
-
onPressed: controller.hideDesktopFloatingToolbar,
|
|
3403
|
-
style: IconButton.styleFrom(
|
|
3404
|
-
backgroundColor: _bgSecondary,
|
|
3405
|
-
foregroundColor: _textSecondary,
|
|
3406
|
-
),
|
|
3407
|
-
icon: const Icon(Icons.close_rounded),
|
|
3408
|
-
),
|
|
3409
|
-
],
|
|
3410
|
-
),
|
|
3411
|
-
),
|
|
3412
|
-
);
|
|
3413
|
-
}
|
|
3414
|
-
}
|
|
3415
|
-
|
|
3416
2845
|
String _ensureModelValue(
|
|
3417
2846
|
String value,
|
|
3418
2847
|
List<ModelMeta> models, {
|