neoagent 2.4.1-beta.26 → 2.4.1-beta.27
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/tray_icon_light_template.png +0 -0
- package/flutter_app/assets/branding/tray_icon_template.png +0 -0
- package/flutter_app/lib/main_chat.dart +37 -3
- package/flutter_app/lib/main_controller.dart +45 -9
- package/flutter_app/tool/generate_desktop_branding.py +12 -4
- package/package.json +1 -1
- package/server/public/.last_build_id +1 -1
- package/server/public/assets/assets/branding/tray_icon_light_template.png +0 -0
- package/server/public/assets/assets/branding/tray_icon_template.png +0 -0
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/public/main.dart.js +53913 -53872
- package/server/routes/messaging.js +2 -0
- package/server/services/messaging/manager.js +4 -3
|
Binary file
|
|
Binary file
|
|
@@ -1893,9 +1893,17 @@ class _MessagingCard extends StatelessWidget {
|
|
|
1893
1893
|
Widget build(BuildContext context) {
|
|
1894
1894
|
final connected = status?.isConnected ?? false;
|
|
1895
1895
|
final configured = status != null && status!.status != 'not_configured';
|
|
1896
|
+
final disabled = status?.status == 'disabled';
|
|
1897
|
+
final canDisconnect = configured && !connected && !disabled;
|
|
1898
|
+
final isDisconnecting = controller.isMessagingPlatformBusy(
|
|
1899
|
+
platform.id,
|
|
1900
|
+
'disconnect',
|
|
1901
|
+
);
|
|
1896
1902
|
final accent = platform.accent;
|
|
1897
1903
|
final actionLabel = connected
|
|
1898
1904
|
? 'Connected'
|
|
1905
|
+
: disabled
|
|
1906
|
+
? 'Disabled'
|
|
1899
1907
|
: configured
|
|
1900
1908
|
? 'Reconnect'
|
|
1901
1909
|
: 'Connect';
|
|
@@ -1960,11 +1968,15 @@ class _MessagingCard extends StatelessWidget {
|
|
|
1960
1968
|
_StatusPill(
|
|
1961
1969
|
label: connected
|
|
1962
1970
|
? 'Live'
|
|
1971
|
+
: disabled
|
|
1972
|
+
? 'Disabled'
|
|
1963
1973
|
: configured
|
|
1964
1974
|
? 'Ready'
|
|
1965
1975
|
: 'Setup',
|
|
1966
1976
|
color: connected
|
|
1967
1977
|
? _success
|
|
1978
|
+
: disabled
|
|
1979
|
+
? _textMuted
|
|
1968
1980
|
: configured
|
|
1969
1981
|
? _warning
|
|
1970
1982
|
: _textMuted,
|
|
@@ -2005,15 +2017,24 @@ class _MessagingCard extends StatelessWidget {
|
|
|
2005
2017
|
Expanded(
|
|
2006
2018
|
child: connected
|
|
2007
2019
|
? OutlinedButton.icon(
|
|
2008
|
-
onPressed: onDisconnect,
|
|
2009
|
-
icon:
|
|
2020
|
+
onPressed: isDisconnecting ? null : onDisconnect,
|
|
2021
|
+
icon: isDisconnecting
|
|
2022
|
+
? SizedBox.square(
|
|
2023
|
+
dimension: 18,
|
|
2024
|
+
child: CircularProgressIndicator(
|
|
2025
|
+
strokeWidth: 2,
|
|
2026
|
+
),
|
|
2027
|
+
)
|
|
2028
|
+
: Icon(Icons.link_off_rounded, size: 18),
|
|
2010
2029
|
label: Text(
|
|
2011
2030
|
'Disconnect',
|
|
2012
2031
|
overflow: TextOverflow.ellipsis,
|
|
2013
2032
|
),
|
|
2014
2033
|
)
|
|
2015
2034
|
: FilledButton.icon(
|
|
2016
|
-
onPressed:
|
|
2035
|
+
onPressed: disabled || isDisconnecting
|
|
2036
|
+
? null
|
|
2037
|
+
: onConnect,
|
|
2017
2038
|
icon: Icon(Icons.power_settings_new_rounded, size: 18),
|
|
2018
2039
|
label: Text(
|
|
2019
2040
|
actionLabel,
|
|
@@ -2022,6 +2043,19 @@ class _MessagingCard extends StatelessWidget {
|
|
|
2022
2043
|
style: FilledButton.styleFrom(backgroundColor: accent),
|
|
2023
2044
|
),
|
|
2024
2045
|
),
|
|
2046
|
+
if (canDisconnect) ...[
|
|
2047
|
+
const SizedBox(width: 8),
|
|
2048
|
+
IconButton.outlined(
|
|
2049
|
+
tooltip: 'Disconnect platform',
|
|
2050
|
+
onPressed: isDisconnecting ? null : onDisconnect,
|
|
2051
|
+
icon: isDisconnecting
|
|
2052
|
+
? SizedBox.square(
|
|
2053
|
+
dimension: 18,
|
|
2054
|
+
child: CircularProgressIndicator(strokeWidth: 2),
|
|
2055
|
+
)
|
|
2056
|
+
: Icon(Icons.link_off_rounded),
|
|
2057
|
+
),
|
|
2058
|
+
],
|
|
2025
2059
|
const SizedBox(width: 8),
|
|
2026
2060
|
IconButton.outlined(
|
|
2027
2061
|
tooltip: 'Access policy',
|
|
@@ -63,6 +63,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
63
63
|
final Set<String> _backgroundRunIds = <String>{};
|
|
64
64
|
final Set<String> _voiceRunIds = <String>{};
|
|
65
65
|
final Set<String> _busyOfficialIntegrationKeys = <String>{};
|
|
66
|
+
final Set<String> _busyMessagingPlatformKeys = <String>{};
|
|
66
67
|
final Map<String, DateTime> _manualRunCooldowns = <String, DateTime>{};
|
|
67
68
|
static const Duration _manualRunCooldownDuration = Duration(seconds: 10);
|
|
68
69
|
static const Duration _homeWidgetSyncCooldown = Duration(seconds: 5);
|
|
@@ -70,6 +71,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
70
71
|
int _authCycle = 0;
|
|
71
72
|
bool _isPollingQrLogin = false;
|
|
72
73
|
bool _socketHasConnectedOnce = false;
|
|
74
|
+
bool _onboardingManuallyReopened = false;
|
|
73
75
|
List<LogEntry> _serverLogs = const <LogEntry>[];
|
|
74
76
|
List<LogEntry> _clientLogs = const <LogEntry>[];
|
|
75
77
|
|
|
@@ -236,6 +238,8 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
236
238
|
|
|
237
239
|
bool isOfficialIntegrationBusy(String key) =>
|
|
238
240
|
_busyOfficialIntegrationKeys.contains(key);
|
|
241
|
+
bool isMessagingPlatformBusy(String platform, String action) =>
|
|
242
|
+
_busyMessagingPlatformKeys.contains('$platform:$action');
|
|
239
243
|
|
|
240
244
|
String get chatComposerHint => hasLiveRun
|
|
241
245
|
? 'Send a steering update or next-up note for the current run...'
|
|
@@ -812,6 +816,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
812
816
|
status['user'] as Map<String, dynamic>,
|
|
813
817
|
);
|
|
814
818
|
isAuthenticated = true;
|
|
819
|
+
_syncOnboardingFromAccount();
|
|
815
820
|
}
|
|
816
821
|
if (isAuthenticated) {
|
|
817
822
|
unawaited(refresh());
|
|
@@ -1350,9 +1355,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
1350
1355
|
pendingTwoFactorUsername = '';
|
|
1351
1356
|
password = '';
|
|
1352
1357
|
|
|
1353
|
-
|
|
1354
|
-
user?['hasCompletedOnboarding'] == true;
|
|
1355
|
-
showOnboarding = isRegistration || !backendCompletedOnboarding;
|
|
1358
|
+
_syncOnboardingFromAccount();
|
|
1356
1359
|
|
|
1357
1360
|
_clearQrLoginChallenge();
|
|
1358
1361
|
await _persistCredentials();
|
|
@@ -1596,6 +1599,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
1596
1599
|
}
|
|
1597
1600
|
|
|
1598
1601
|
Future<void> dismissOnboarding() async {
|
|
1602
|
+
_onboardingManuallyReopened = false;
|
|
1599
1603
|
showOnboarding = false;
|
|
1600
1604
|
notifyListeners();
|
|
1601
1605
|
try {
|
|
@@ -1612,10 +1616,23 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
1612
1616
|
}
|
|
1613
1617
|
|
|
1614
1618
|
void reopenOnboarding() {
|
|
1619
|
+
_onboardingManuallyReopened = true;
|
|
1615
1620
|
showOnboarding = true;
|
|
1616
1621
|
notifyListeners();
|
|
1617
1622
|
}
|
|
1618
1623
|
|
|
1624
|
+
void _syncOnboardingFromAccount() {
|
|
1625
|
+
final hasCompletedOnboarding = user?['hasCompletedOnboarding'] == true;
|
|
1626
|
+
if (hasCompletedOnboarding) {
|
|
1627
|
+
if (!_onboardingManuallyReopened) {
|
|
1628
|
+
showOnboarding = false;
|
|
1629
|
+
}
|
|
1630
|
+
return;
|
|
1631
|
+
}
|
|
1632
|
+
_onboardingManuallyReopened = false;
|
|
1633
|
+
showOnboarding = true;
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1619
1636
|
void _clearAuthenticatedState() {
|
|
1620
1637
|
_disconnectSocket();
|
|
1621
1638
|
_updatePollTimer?.cancel();
|
|
@@ -1623,6 +1640,8 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
1623
1640
|
_clearQrLoginChallenge();
|
|
1624
1641
|
isAuthenticated = false;
|
|
1625
1642
|
isRefreshing = false;
|
|
1643
|
+
_onboardingManuallyReopened = false;
|
|
1644
|
+
_busyMessagingPlatformKeys.clear();
|
|
1626
1645
|
isAwaitingTwoFactor = false;
|
|
1627
1646
|
pendingTwoFactorUsername = '';
|
|
1628
1647
|
errorMessage = null;
|
|
@@ -2080,6 +2099,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
2080
2099
|
user = Map<String, dynamic>.from(
|
|
2081
2100
|
authStatus['user'] as Map<String, dynamic>,
|
|
2082
2101
|
);
|
|
2102
|
+
_syncOnboardingFromAccount();
|
|
2083
2103
|
|
|
2084
2104
|
final profilesResponse = await _backendClient.fetchAgentProfiles(
|
|
2085
2105
|
backendUrl,
|
|
@@ -5499,12 +5519,28 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
5499
5519
|
}
|
|
5500
5520
|
|
|
5501
5521
|
Future<void> disconnectMessagingPlatform(String platform) async {
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5522
|
+
final busyKey = '$platform:disconnect';
|
|
5523
|
+
if (_busyMessagingPlatformKeys.contains(busyKey)) {
|
|
5524
|
+
return;
|
|
5525
|
+
}
|
|
5526
|
+
|
|
5527
|
+
_busyMessagingPlatformKeys.add(busyKey);
|
|
5528
|
+
errorMessage = null;
|
|
5529
|
+
notifyListeners();
|
|
5530
|
+
|
|
5531
|
+
try {
|
|
5532
|
+
await _backendClient.disconnectMessagingPlatform(
|
|
5533
|
+
backendUrl,
|
|
5534
|
+
platform: platform,
|
|
5535
|
+
agentId: _scopedAgentId,
|
|
5536
|
+
);
|
|
5537
|
+
await refreshMessaging();
|
|
5538
|
+
} catch (error) {
|
|
5539
|
+
errorMessage = _friendlyErrorMessage(error);
|
|
5540
|
+
} finally {
|
|
5541
|
+
_busyMessagingPlatformKeys.remove(busyKey);
|
|
5542
|
+
notifyListeners();
|
|
5543
|
+
}
|
|
5508
5544
|
}
|
|
5509
5545
|
|
|
5510
5546
|
Future<void> logoutMessagingPlatform(String platform) async {
|
|
@@ -28,6 +28,7 @@ SOURCE_PNG_SIZES = (16, 32, 48, 64, 128, 180, 192, 256, 512, 1024)
|
|
|
28
28
|
TRANSPARENT = (0, 0, 0, 0)
|
|
29
29
|
WHITE = (255, 255, 255, 255)
|
|
30
30
|
BLACK = (0, 0, 0, 255)
|
|
31
|
+
TRAY_TEMPLATE_SIZE = 256
|
|
31
32
|
|
|
32
33
|
|
|
33
34
|
def ensure_dirs() -> None:
|
|
@@ -141,7 +142,8 @@ def make_tray_template(
|
|
|
141
142
|
)
|
|
142
143
|
|
|
143
144
|
# Keep the symbol optically centered inside the menu-bar bounds.
|
|
144
|
-
|
|
145
|
+
vertical_offset = round(size * 0.03125)
|
|
146
|
+
return img.crop((0, vertical_offset, size, size + vertical_offset))
|
|
145
147
|
|
|
146
148
|
|
|
147
149
|
def main() -> None:
|
|
@@ -151,8 +153,14 @@ def main() -> None:
|
|
|
151
153
|
save_icon(BRANDING_DIR / f"app_icon_{size}.png", size)
|
|
152
154
|
save_icon(BRANDING_DIR / f"app_icon_light_{size}.png", size)
|
|
153
155
|
|
|
154
|
-
make_tray_template(
|
|
155
|
-
|
|
156
|
+
make_tray_template(TRAY_TEMPLATE_SIZE).save(
|
|
157
|
+
BRANDING_DIR / "tray_icon_template.png",
|
|
158
|
+
format="PNG",
|
|
159
|
+
)
|
|
160
|
+
make_tray_template(TRAY_TEMPLATE_SIZE, WHITE).save(
|
|
161
|
+
BRANDING_DIR / "tray_icon_light_template.png",
|
|
162
|
+
format="PNG",
|
|
163
|
+
)
|
|
156
164
|
|
|
157
165
|
for size in (16, 32, 64, 128, 256, 512, 1024):
|
|
158
166
|
save_icon(MAC_ICON_DIR / f"app_icon_{size}.png", size)
|
|
@@ -192,7 +200,7 @@ def main() -> None:
|
|
|
192
200
|
save_icon(STATIC_IMG_DIR / "app_icon.png", 512)
|
|
193
201
|
save_icon(STATIC_IMG_DIR / "app_icon_light.png", 512)
|
|
194
202
|
save_icon(SERVER_PUBLIC_DIR / "assets" / "assets" / "branding" / "app_icon_256.png", 256)
|
|
195
|
-
make_tray_template(
|
|
203
|
+
make_tray_template(TRAY_TEMPLATE_SIZE).save(
|
|
196
204
|
SERVER_PUBLIC_DIR / "assets" / "assets" / "branding" / "tray_icon_template.png",
|
|
197
205
|
format="PNG",
|
|
198
206
|
)
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
77eaad1940c3818c9ff1374401de40eb
|
|
Binary file
|
|
Binary file
|
|
@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"c416acfeb8126e097f758c664aaa3da929e27d
|
|
|
37
37
|
|
|
38
38
|
_flutter.loader.load({
|
|
39
39
|
serviceWorkerSettings: {
|
|
40
|
-
serviceWorkerVersion: "
|
|
40
|
+
serviceWorkerVersion: "1085140529" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
|
|
41
41
|
}
|
|
42
42
|
});
|