neoagent 2.4.1-beta.30 → 2.4.1-beta.32
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/flutter_app/assets/branding/onboarding_intro.mp4 +0 -0
- package/flutter_app/lib/features/onboarding/onboarding_chrome.dart +391 -382
- package/flutter_app/lib/features/onboarding/onboarding_companion_step.dart +78 -56
- package/flutter_app/lib/features/onboarding/onboarding_messaging_step.dart +18 -16
- package/flutter_app/lib/features/onboarding/onboarding_model_step.dart +18 -17
- package/flutter_app/lib/features/onboarding/onboarding_shell.dart +2 -1
- package/flutter_app/lib/features/onboarding/onboarding_video_step.dart +16 -13
- package/flutter_app/lib/features/onboarding/onboarding_welcome_step.dart +15 -11
- package/flutter_app/lib/main_account_settings.dart +1 -1
- package/flutter_app/lib/main_admin.dart +1 -1
- package/flutter_app/lib/main_app_shell.dart +190 -191
- package/flutter_app/lib/main_chat.dart +381 -228
- package/flutter_app/lib/main_devices.dart +1 -1
- package/flutter_app/lib/main_launcher.dart +1 -1
- package/flutter_app/lib/main_operations.dart +3 -3
- package/flutter_app/lib/main_shared.dart +336 -340
- package/flutter_app/lib/main_spacing.dart +4 -4
- package/flutter_app/lib/main_theme.dart +20 -14
- package/flutter_app/lib/src/theme/palette.dart +76 -34
- package/flutter_app/pubspec.lock +2 -2
- package/flutter_app/pubspec.yaml +1 -1
- package/package.json +1 -1
- package/server/public/.last_build_id +1 -1
- package/server/public/assets/assets/branding/onboarding_intro.mp4 +0 -0
- package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/public/main.dart.js +60738 -60521
- package/server/services/ai/tools.js +51 -7
- package/server/services/messaging/formatting_guides.js +26 -1
- package/server/services/messaging/manager.js +5 -2
- package/server/services/tasks/runtime.js +182 -7
- package/server/services/tasks/task_repository.js +13 -0
|
@@ -357,268 +357,422 @@ class _ChatPanelState extends State<ChatPanel> with WidgetsBindingObserver {
|
|
|
357
357
|
final messages = controller.visibleChatMessages;
|
|
358
358
|
_maybeFollowChatContent(messages, controller);
|
|
359
359
|
|
|
360
|
+
final threadChildren = <Widget>[
|
|
361
|
+
if (controller.errorMessage != null) ...<Widget>[
|
|
362
|
+
_InlineError(message: controller.errorMessage!),
|
|
363
|
+
const SizedBox(height: 16),
|
|
364
|
+
],
|
|
365
|
+
if (controller.activeRun != null || controller.toolEvents.isNotEmpty)
|
|
366
|
+
Padding(
|
|
367
|
+
padding: const EdgeInsets.only(bottom: 16),
|
|
368
|
+
child: _RunStatusPanel(
|
|
369
|
+
run: controller.activeRun,
|
|
370
|
+
tools: controller.toolEvents,
|
|
371
|
+
),
|
|
372
|
+
),
|
|
373
|
+
if (messages.isEmpty)
|
|
374
|
+
Padding(
|
|
375
|
+
padding: const EdgeInsets.only(top: 64),
|
|
376
|
+
child: Center(
|
|
377
|
+
child: _EmptyState(
|
|
378
|
+
title: 'How can I help?',
|
|
379
|
+
subtitle:
|
|
380
|
+
'Runs, tools, memory, scheduling, skills, and MCP are all available here.',
|
|
381
|
+
),
|
|
382
|
+
),
|
|
383
|
+
)
|
|
384
|
+
else
|
|
385
|
+
...messages.map(
|
|
386
|
+
(entry) => Padding(
|
|
387
|
+
padding: const EdgeInsets.only(bottom: 18),
|
|
388
|
+
child: _ChatBubble(
|
|
389
|
+
entry: entry,
|
|
390
|
+
onLoadRunDetail: controller.fetchRunDetail,
|
|
391
|
+
),
|
|
392
|
+
),
|
|
393
|
+
),
|
|
394
|
+
];
|
|
395
|
+
|
|
396
|
+
Future<void> sendComposerMessage() async {
|
|
397
|
+
final task = _composerController.text;
|
|
398
|
+
if ((task.trim().isEmpty && _pendingSharedAttachments.isEmpty) ||
|
|
399
|
+
_isSendingChatMessage) {
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
setState(() {
|
|
403
|
+
_isSendingChatMessage = true;
|
|
404
|
+
});
|
|
405
|
+
_composerController.clear();
|
|
406
|
+
final outgoingAttachments = _pendingSharedAttachments;
|
|
407
|
+
_clearSharedPayload();
|
|
408
|
+
try {
|
|
409
|
+
await controller.sendMessage(
|
|
410
|
+
task,
|
|
411
|
+
sharedAttachments: outgoingAttachments,
|
|
412
|
+
);
|
|
413
|
+
} finally {
|
|
414
|
+
if (mounted) {
|
|
415
|
+
setState(() {
|
|
416
|
+
_isSendingChatMessage = false;
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
final sidePadding = _chatSidePadding(context);
|
|
423
|
+
|
|
360
424
|
return Column(
|
|
361
425
|
children: <Widget>[
|
|
426
|
+
_ChatTopBar(controller: controller),
|
|
362
427
|
Expanded(
|
|
363
428
|
child: SelectionArea(
|
|
364
429
|
child: ListView(
|
|
365
430
|
controller: _scrollController,
|
|
366
|
-
padding:
|
|
431
|
+
padding: EdgeInsets.fromLTRB(sidePadding, 30, sidePadding, 18),
|
|
367
432
|
children: <Widget>[
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
crossAxisAlignment: WrapCrossAlignment.center,
|
|
375
|
-
children: <Widget>[
|
|
376
|
-
FilledButton.icon(
|
|
377
|
-
onPressed: () => controller.setSelectedSection(
|
|
378
|
-
AppSection.voiceAssistant,
|
|
379
|
-
),
|
|
380
|
-
icon: Icon(Icons.call),
|
|
381
|
-
label: Text('Call'),
|
|
382
|
-
),
|
|
383
|
-
_MetaPill(
|
|
384
|
-
label: controller.modelIndicator,
|
|
385
|
-
icon: Icons.memory_outlined,
|
|
386
|
-
),
|
|
387
|
-
_MetaPill(
|
|
388
|
-
label: 'Agent: ${controller.activeAgentLabel}',
|
|
389
|
-
icon: Icons.smart_toy_outlined,
|
|
390
|
-
),
|
|
391
|
-
],
|
|
392
|
-
),
|
|
393
|
-
),
|
|
394
|
-
if (controller.errorMessage != null) ...<Widget>[
|
|
395
|
-
_InlineError(message: controller.errorMessage!),
|
|
396
|
-
const SizedBox(height: 16),
|
|
397
|
-
],
|
|
398
|
-
if (controller.activeRun != null ||
|
|
399
|
-
controller.toolEvents.isNotEmpty)
|
|
400
|
-
Padding(
|
|
401
|
-
padding: const EdgeInsets.only(bottom: 16),
|
|
402
|
-
child: _RunStatusPanel(
|
|
403
|
-
run: controller.activeRun,
|
|
404
|
-
tools: controller.toolEvents,
|
|
405
|
-
),
|
|
406
|
-
),
|
|
407
|
-
if (messages.isEmpty)
|
|
408
|
-
Padding(
|
|
409
|
-
padding: EdgeInsets.only(top: 64),
|
|
410
|
-
child: Center(
|
|
411
|
-
child: _EmptyState(
|
|
412
|
-
title: 'How can I help?',
|
|
413
|
-
subtitle:
|
|
414
|
-
'Runs, tools, memory, scheduling, skills, and MCP are all available here.',
|
|
415
|
-
),
|
|
416
|
-
),
|
|
417
|
-
)
|
|
418
|
-
else
|
|
419
|
-
...messages.map(
|
|
420
|
-
(entry) => Padding(
|
|
421
|
-
padding: const EdgeInsets.only(bottom: 18),
|
|
422
|
-
child: _ChatBubble(
|
|
423
|
-
entry: entry,
|
|
424
|
-
onLoadRunDetail: controller.fetchRunDetail,
|
|
425
|
-
),
|
|
433
|
+
Center(
|
|
434
|
+
child: ConstrainedBox(
|
|
435
|
+
constraints: const BoxConstraints(maxWidth: 860),
|
|
436
|
+
child: Column(
|
|
437
|
+
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
438
|
+
children: threadChildren,
|
|
426
439
|
),
|
|
427
440
|
),
|
|
441
|
+
),
|
|
428
442
|
],
|
|
429
443
|
),
|
|
430
444
|
),
|
|
431
445
|
),
|
|
432
446
|
Container(
|
|
433
|
-
padding:
|
|
447
|
+
padding: EdgeInsets.fromLTRB(sidePadding, 12, sidePadding, 16),
|
|
434
448
|
decoration: BoxDecoration(
|
|
435
|
-
color: _bgPrimary,
|
|
449
|
+
color: _bgPrimary.withValues(alpha: 0.88),
|
|
436
450
|
border: Border(top: BorderSide(color: _border)),
|
|
437
451
|
),
|
|
438
|
-
child:
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
Container(
|
|
467
|
-
padding: const EdgeInsets.fromLTRB(16, 4, 4, 4),
|
|
468
|
-
decoration: BoxDecoration(
|
|
469
|
-
color: _bgTertiary,
|
|
470
|
-
borderRadius: BorderRadius.circular(14),
|
|
471
|
-
border: Border.all(color: _border),
|
|
472
|
-
),
|
|
473
|
-
child: Row(
|
|
474
|
-
crossAxisAlignment: CrossAxisAlignment.end,
|
|
475
|
-
children: <Widget>[
|
|
476
|
-
Expanded(
|
|
477
|
-
child: TextField(
|
|
478
|
-
controller: _composerController,
|
|
479
|
-
minLines: 1,
|
|
480
|
-
maxLines: 6,
|
|
481
|
-
keyboardType: TextInputType.multiline,
|
|
482
|
-
textInputAction: TextInputAction.newline,
|
|
483
|
-
decoration: InputDecoration(
|
|
484
|
-
hintText: controller.chatComposerHint,
|
|
485
|
-
isDense: true,
|
|
486
|
-
filled: false,
|
|
487
|
-
border: InputBorder.none,
|
|
488
|
-
enabledBorder: InputBorder.none,
|
|
489
|
-
focusedBorder: InputBorder.none,
|
|
490
|
-
),
|
|
452
|
+
child: Center(
|
|
453
|
+
child: ConstrainedBox(
|
|
454
|
+
constraints: const BoxConstraints(maxWidth: 860),
|
|
455
|
+
child: Column(
|
|
456
|
+
children: <Widget>[
|
|
457
|
+
if (_pendingSharedAttachments.isNotEmpty)
|
|
458
|
+
Padding(
|
|
459
|
+
padding: const EdgeInsets.only(bottom: 10),
|
|
460
|
+
child: _SharedAttachmentTray(
|
|
461
|
+
attachments: _pendingSharedAttachments,
|
|
462
|
+
onRemoveAt: (index) {
|
|
463
|
+
setState(() {
|
|
464
|
+
_pendingSharedAttachments =
|
|
465
|
+
_pendingSharedAttachments
|
|
466
|
+
.asMap()
|
|
467
|
+
.entries
|
|
468
|
+
.where((entry) => entry.key != index)
|
|
469
|
+
.map((entry) => entry.value)
|
|
470
|
+
.toList(growable: false);
|
|
471
|
+
});
|
|
472
|
+
if (_stickToBottom) {
|
|
473
|
+
_scheduleScrollToBottom();
|
|
474
|
+
}
|
|
475
|
+
if (_pendingSharedAttachments.isEmpty) {
|
|
476
|
+
_clearSharedPayload();
|
|
477
|
+
}
|
|
478
|
+
},
|
|
479
|
+
onClear: _clearSharedPayload,
|
|
491
480
|
),
|
|
492
481
|
),
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
color:
|
|
482
|
+
Container(
|
|
483
|
+
padding: const EdgeInsets.fromLTRB(8, 8, 8, 8),
|
|
484
|
+
decoration: BoxDecoration(
|
|
485
|
+
color: _bgCard,
|
|
486
|
+
borderRadius: BorderRadius.circular(21),
|
|
487
|
+
border: Border.all(color: _borderLight),
|
|
488
|
+
boxShadow: <BoxShadow>[
|
|
489
|
+
BoxShadow(
|
|
490
|
+
color: Colors.black.withValues(alpha: 0.08),
|
|
491
|
+
blurRadius: 18,
|
|
492
|
+
offset: const Offset(0, 6),
|
|
493
|
+
),
|
|
494
|
+
],
|
|
499
495
|
),
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
496
|
+
child: Row(
|
|
497
|
+
crossAxisAlignment: CrossAxisAlignment.end,
|
|
498
|
+
children: <Widget>[
|
|
499
|
+
_ChatComposerIconButton(
|
|
500
|
+
tooltip: 'Attach files',
|
|
501
|
+
icon: Icons.attach_file_rounded,
|
|
502
|
+
onPressed: _attachFiles,
|
|
503
|
+
),
|
|
504
|
+
const SizedBox(width: 8),
|
|
505
|
+
Expanded(
|
|
506
|
+
child: TextField(
|
|
507
|
+
controller: _composerController,
|
|
508
|
+
minLines: 1,
|
|
509
|
+
maxLines: 6,
|
|
510
|
+
keyboardType: TextInputType.multiline,
|
|
511
|
+
textInputAction: TextInputAction.newline,
|
|
512
|
+
decoration: InputDecoration(
|
|
513
|
+
hintText: controller.chatComposerHint,
|
|
514
|
+
isDense: true,
|
|
515
|
+
filled: false,
|
|
516
|
+
border: InputBorder.none,
|
|
517
|
+
enabledBorder: InputBorder.none,
|
|
518
|
+
focusedBorder: InputBorder.none,
|
|
519
|
+
contentPadding: const EdgeInsets.symmetric(
|
|
520
|
+
vertical: 10,
|
|
521
|
+
),
|
|
521
522
|
),
|
|
522
|
-
color: _isDictating
|
|
523
|
-
? Theme.of(context).colorScheme.error
|
|
524
|
-
: _textSecondary,
|
|
525
523
|
),
|
|
526
|
-
const SizedBox(width: 2),
|
|
527
|
-
FilledButton(
|
|
528
|
-
onPressed: () => controller.setSelectedSection(
|
|
529
|
-
AppSection.voiceAssistant,
|
|
530
|
-
),
|
|
531
|
-
style: FilledButton.styleFrom(
|
|
532
|
-
minimumSize: const Size(46, 42),
|
|
533
|
-
padding: const EdgeInsets.symmetric(horizontal: 12),
|
|
534
|
-
backgroundColor: _success,
|
|
535
|
-
shape: RoundedRectangleBorder(
|
|
536
|
-
borderRadius: BorderRadius.circular(10),
|
|
537
524
|
),
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
}
|
|
573
|
-
},
|
|
574
|
-
style: FilledButton.styleFrom(
|
|
575
|
-
minimumSize: const Size(46, 42),
|
|
576
|
-
padding: const EdgeInsets.symmetric(horizontal: 12),
|
|
577
|
-
backgroundColor: _accent,
|
|
578
|
-
shape: RoundedRectangleBorder(
|
|
579
|
-
borderRadius: BorderRadius.circular(10),
|
|
525
|
+
const SizedBox(width: 8),
|
|
526
|
+
_isTranscribing
|
|
527
|
+
? const SizedBox(
|
|
528
|
+
width: 40,
|
|
529
|
+
height: 40,
|
|
530
|
+
child: Padding(
|
|
531
|
+
padding: EdgeInsets.all(10),
|
|
532
|
+
child: CircularProgressIndicator(
|
|
533
|
+
strokeWidth: 2,
|
|
534
|
+
),
|
|
535
|
+
),
|
|
536
|
+
)
|
|
537
|
+
: _ChatComposerIconButton(
|
|
538
|
+
tooltip: _isDictating
|
|
539
|
+
? 'Stop & transcribe'
|
|
540
|
+
: 'Dictate',
|
|
541
|
+
icon: _isDictating
|
|
542
|
+
? Icons.stop_circle_outlined
|
|
543
|
+
: Icons.mic_none_rounded,
|
|
544
|
+
color: _isDictating
|
|
545
|
+
? Theme.of(context).colorScheme.error
|
|
546
|
+
: null,
|
|
547
|
+
onPressed: _isDictating
|
|
548
|
+
? _stopAndTranscribe
|
|
549
|
+
: _startDictation,
|
|
550
|
+
),
|
|
551
|
+
const SizedBox(width: 6),
|
|
552
|
+
_ChatComposerIconButton(
|
|
553
|
+
tooltip: 'Call agent',
|
|
554
|
+
icon: Icons.call_rounded,
|
|
555
|
+
color: Colors.white,
|
|
556
|
+
backgroundColor: _success,
|
|
557
|
+
onPressed: () => controller.setSelectedSection(
|
|
558
|
+
AppSection.voiceAssistant,
|
|
580
559
|
),
|
|
581
560
|
),
|
|
582
|
-
|
|
583
|
-
|
|
561
|
+
const SizedBox(width: 6),
|
|
562
|
+
_ChatComposerIconButton(
|
|
563
|
+
tooltip: 'Send',
|
|
564
|
+
icon: controller.hasLiveRun
|
|
584
565
|
? Icons.alt_route_rounded
|
|
585
566
|
: Icons.north_east_rounded,
|
|
586
567
|
color: Colors.white,
|
|
568
|
+
backgroundColor: _accent,
|
|
569
|
+
onPressed: _isSendingChatMessage
|
|
570
|
+
? null
|
|
571
|
+
: sendComposerMessage,
|
|
572
|
+
),
|
|
573
|
+
],
|
|
574
|
+
),
|
|
575
|
+
),
|
|
576
|
+
const SizedBox(height: 10),
|
|
577
|
+
Row(
|
|
578
|
+
children: <Widget>[
|
|
579
|
+
Expanded(
|
|
580
|
+
child: Row(
|
|
581
|
+
children: <Widget>[
|
|
582
|
+
Container(
|
|
583
|
+
width: 6,
|
|
584
|
+
height: 6,
|
|
585
|
+
decoration: BoxDecoration(
|
|
586
|
+
shape: BoxShape.circle,
|
|
587
|
+
color: controller.hasLiveRun
|
|
588
|
+
? _success
|
|
589
|
+
: _textMuted,
|
|
590
|
+
),
|
|
591
|
+
),
|
|
592
|
+
const SizedBox(width: 7),
|
|
593
|
+
Expanded(
|
|
594
|
+
child: Text(
|
|
595
|
+
controller.chatStatusLabel,
|
|
596
|
+
maxLines: 1,
|
|
597
|
+
overflow: TextOverflow.ellipsis,
|
|
598
|
+
style: GoogleFonts.geistMono(
|
|
599
|
+
fontSize: 11.5,
|
|
600
|
+
color: _textMuted,
|
|
601
|
+
),
|
|
602
|
+
),
|
|
603
|
+
),
|
|
604
|
+
],
|
|
587
605
|
),
|
|
588
606
|
),
|
|
607
|
+
const SizedBox(width: 12),
|
|
608
|
+
Flexible(
|
|
609
|
+
child: Container(
|
|
610
|
+
padding: const EdgeInsets.symmetric(
|
|
611
|
+
horizontal: 9,
|
|
612
|
+
vertical: 4,
|
|
613
|
+
),
|
|
614
|
+
decoration: BoxDecoration(
|
|
615
|
+
color: _bgCard,
|
|
616
|
+
borderRadius: BorderRadius.circular(8),
|
|
617
|
+
border: Border.all(color: _border),
|
|
618
|
+
),
|
|
619
|
+
child: Row(
|
|
620
|
+
mainAxisSize: MainAxisSize.min,
|
|
621
|
+
children: <Widget>[
|
|
622
|
+
Flexible(
|
|
623
|
+
child: Text(
|
|
624
|
+
controller.hasLiveRun
|
|
625
|
+
? 'Steering mode'
|
|
626
|
+
: controller.modelIndicator,
|
|
627
|
+
maxLines: 1,
|
|
628
|
+
overflow: TextOverflow.ellipsis,
|
|
629
|
+
style: GoogleFonts.geistMono(
|
|
630
|
+
fontSize: 11.5,
|
|
631
|
+
color: _textSecondary,
|
|
632
|
+
),
|
|
633
|
+
),
|
|
634
|
+
),
|
|
635
|
+
const SizedBox(width: 5),
|
|
636
|
+
Icon(
|
|
637
|
+
Icons.keyboard_arrow_down_rounded,
|
|
638
|
+
size: 13,
|
|
639
|
+
color: _textMuted,
|
|
640
|
+
),
|
|
641
|
+
],
|
|
642
|
+
),
|
|
643
|
+
),
|
|
644
|
+
),
|
|
645
|
+
],
|
|
646
|
+
),
|
|
647
|
+
],
|
|
648
|
+
),
|
|
649
|
+
),
|
|
650
|
+
),
|
|
651
|
+
),
|
|
652
|
+
],
|
|
653
|
+
);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
double _chatSidePadding(BuildContext context) {
|
|
658
|
+
final width = MediaQuery.sizeOf(context).width;
|
|
659
|
+
if (width >= 1280) return 40;
|
|
660
|
+
if (width >= 900) return 30;
|
|
661
|
+
return 20;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
class _ChatTopBar extends StatelessWidget {
|
|
665
|
+
const _ChatTopBar({required this.controller});
|
|
666
|
+
|
|
667
|
+
final NeoAgentController controller;
|
|
668
|
+
|
|
669
|
+
@override
|
|
670
|
+
Widget build(BuildContext context) {
|
|
671
|
+
return Container(
|
|
672
|
+
height: 58,
|
|
673
|
+
padding: EdgeInsets.symmetric(horizontal: _chatSidePadding(context)),
|
|
674
|
+
decoration: BoxDecoration(
|
|
675
|
+
color: _bgPrimary.withValues(alpha: 0.72),
|
|
676
|
+
border: Border(bottom: BorderSide(color: _border)),
|
|
677
|
+
),
|
|
678
|
+
child: Row(
|
|
679
|
+
children: <Widget>[
|
|
680
|
+
Text(
|
|
681
|
+
'Chat',
|
|
682
|
+
style: GoogleFonts.geist(
|
|
683
|
+
fontSize: 15,
|
|
684
|
+
fontWeight: FontWeight.w600,
|
|
685
|
+
color: _textPrimary,
|
|
686
|
+
),
|
|
687
|
+
),
|
|
688
|
+
const SizedBox(width: 12),
|
|
689
|
+
Expanded(
|
|
690
|
+
child: Text(
|
|
691
|
+
'/ ${controller.activeAgentLabel} / ${controller.modelIndicator}',
|
|
692
|
+
maxLines: 1,
|
|
693
|
+
overflow: TextOverflow.ellipsis,
|
|
694
|
+
style: GoogleFonts.geistMono(fontSize: 11, color: _textMuted),
|
|
695
|
+
),
|
|
696
|
+
),
|
|
697
|
+
const SizedBox(width: 12),
|
|
698
|
+
Row(
|
|
699
|
+
mainAxisSize: MainAxisSize.min,
|
|
700
|
+
children: <Widget>[
|
|
701
|
+
Container(
|
|
702
|
+
width: 7,
|
|
703
|
+
height: 7,
|
|
704
|
+
decoration: BoxDecoration(
|
|
705
|
+
shape: BoxShape.circle,
|
|
706
|
+
color: controller.hasLiveRun ? _success : _accentAlt,
|
|
707
|
+
boxShadow: <BoxShadow>[
|
|
708
|
+
BoxShadow(
|
|
709
|
+
color: (controller.hasLiveRun ? _success : _accentAlt)
|
|
710
|
+
.withValues(alpha: 0.18),
|
|
711
|
+
blurRadius: 0,
|
|
712
|
+
spreadRadius: 3,
|
|
589
713
|
),
|
|
590
714
|
],
|
|
591
715
|
),
|
|
592
716
|
),
|
|
593
|
-
const SizedBox(
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
overflow: TextOverflow.ellipsis,
|
|
601
|
-
style: TextStyle(fontSize: 12, color: _textSecondary),
|
|
602
|
-
),
|
|
603
|
-
),
|
|
604
|
-
const SizedBox(width: 12),
|
|
605
|
-
Flexible(
|
|
606
|
-
child: Text(
|
|
607
|
-
controller.hasLiveRun
|
|
608
|
-
? 'Steering mode'
|
|
609
|
-
: controller.modelIndicator,
|
|
610
|
-
maxLines: 1,
|
|
611
|
-
overflow: TextOverflow.ellipsis,
|
|
612
|
-
textAlign: TextAlign.right,
|
|
613
|
-
style: TextStyle(fontSize: 12, color: _textSecondary),
|
|
614
|
-
),
|
|
615
|
-
),
|
|
616
|
-
],
|
|
717
|
+
const SizedBox(width: 7),
|
|
718
|
+
Text(
|
|
719
|
+
controller.hasLiveRun ? 'live' : 'idle',
|
|
720
|
+
style: GoogleFonts.geistMono(
|
|
721
|
+
fontSize: 12,
|
|
722
|
+
color: _textSecondary,
|
|
723
|
+
),
|
|
617
724
|
),
|
|
618
725
|
],
|
|
619
726
|
),
|
|
727
|
+
],
|
|
728
|
+
),
|
|
729
|
+
);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
class _ChatComposerIconButton extends StatelessWidget {
|
|
734
|
+
const _ChatComposerIconButton({
|
|
735
|
+
required this.tooltip,
|
|
736
|
+
required this.icon,
|
|
737
|
+
required this.onPressed,
|
|
738
|
+
this.color,
|
|
739
|
+
this.backgroundColor,
|
|
740
|
+
});
|
|
741
|
+
|
|
742
|
+
final String tooltip;
|
|
743
|
+
final IconData icon;
|
|
744
|
+
final VoidCallback? onPressed;
|
|
745
|
+
final Color? color;
|
|
746
|
+
final Color? backgroundColor;
|
|
747
|
+
|
|
748
|
+
@override
|
|
749
|
+
Widget build(BuildContext context) {
|
|
750
|
+
final foreground = color ?? _textSecondary;
|
|
751
|
+
return Tooltip(
|
|
752
|
+
message: tooltip,
|
|
753
|
+
child: Material(
|
|
754
|
+
color: Colors.transparent,
|
|
755
|
+
borderRadius: BorderRadius.circular(11),
|
|
756
|
+
child: InkWell(
|
|
757
|
+
borderRadius: BorderRadius.circular(11),
|
|
758
|
+
onTap: onPressed,
|
|
759
|
+
child: Container(
|
|
760
|
+
width: 40,
|
|
761
|
+
height: 40,
|
|
762
|
+
decoration: BoxDecoration(
|
|
763
|
+
color: onPressed == null
|
|
764
|
+
? _bgTertiary.withValues(alpha: 0.52)
|
|
765
|
+
: backgroundColor ?? Colors.transparent,
|
|
766
|
+
borderRadius: BorderRadius.circular(11),
|
|
767
|
+
),
|
|
768
|
+
child: Icon(
|
|
769
|
+
icon,
|
|
770
|
+
size: 19,
|
|
771
|
+
color: onPressed == null ? _textMuted : foreground,
|
|
772
|
+
),
|
|
773
|
+
),
|
|
620
774
|
),
|
|
621
|
-
|
|
775
|
+
),
|
|
622
776
|
);
|
|
623
777
|
}
|
|
624
778
|
}
|
|
@@ -3403,7 +3557,7 @@ class _RunResponseCard extends StatelessWidget {
|
|
|
3403
3557
|
height: 1.6,
|
|
3404
3558
|
),
|
|
3405
3559
|
code: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
|
3406
|
-
fontFamily: GoogleFonts.
|
|
3560
|
+
fontFamily: GoogleFonts.geistMono().fontFamily,
|
|
3407
3561
|
backgroundColor: _bgSecondary,
|
|
3408
3562
|
color: _textPrimary,
|
|
3409
3563
|
),
|
|
@@ -3486,8 +3640,7 @@ class _DeliverableSummaryCard extends StatelessWidget {
|
|
|
3486
3640
|
style: TextStyle(
|
|
3487
3641
|
color: _textSecondary,
|
|
3488
3642
|
fontSize: 12,
|
|
3489
|
-
fontFamily:
|
|
3490
|
-
GoogleFonts.jetBrainsMono().fontFamily,
|
|
3643
|
+
fontFamily: GoogleFonts.geistMono().fontFamily,
|
|
3491
3644
|
),
|
|
3492
3645
|
),
|
|
3493
3646
|
],
|
|
@@ -3798,7 +3951,7 @@ class _RunDetailBlock extends StatelessWidget {
|
|
|
3798
3951
|
fontSize: 12.5,
|
|
3799
3952
|
color: _textPrimary,
|
|
3800
3953
|
fontFamily: monospace
|
|
3801
|
-
? GoogleFonts.
|
|
3954
|
+
? GoogleFonts.geistMono().fontFamily
|
|
3802
3955
|
: null,
|
|
3803
3956
|
),
|
|
3804
3957
|
),
|