neoagent 2.3.1-beta.63 → 2.3.1-beta.64

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.
@@ -63,6 +63,7 @@ part 'main_account_settings.dart';
63
63
  part 'main_settings.dart';
64
64
  part 'main_operations.dart';
65
65
  part 'main_admin.dart';
66
+ part 'main_unified.dart';
66
67
 
67
68
  Future<void> main() async {
68
69
  await runNeoAgentApp(mode: _appModeFromEnvironment());
@@ -150,16 +150,23 @@ class _PasswordStrengthIndicator extends StatelessWidget {
150
150
  enum AccountSettingsTab { account, security }
151
151
 
152
152
  class AccountSettingsPanel extends StatefulWidget {
153
- const AccountSettingsPanel({super.key, required this.controller});
153
+ const AccountSettingsPanel({
154
+ super.key,
155
+ required this.controller,
156
+ this.embedded = false,
157
+ this.initialTab,
158
+ });
154
159
 
155
160
  final NeoAgentController controller;
161
+ final bool embedded;
162
+ final AccountSettingsTab? initialTab;
156
163
 
157
164
  @override
158
165
  State<AccountSettingsPanel> createState() => _AccountSettingsPanelState();
159
166
  }
160
167
 
161
168
  class _AccountSettingsPanelState extends State<AccountSettingsPanel> {
162
- AccountSettingsTab _selectedTab = AccountSettingsTab.account;
169
+ late AccountSettingsTab _selectedTab;
163
170
  late final TextEditingController _emailController;
164
171
  late final TextEditingController _emailPasswordController;
165
172
  late final TextEditingController _setupPasswordController;
@@ -179,6 +186,7 @@ class _AccountSettingsPanelState extends State<AccountSettingsPanel> {
179
186
  @override
180
187
  void initState() {
181
188
  super.initState();
189
+ _selectedTab = widget.initialTab ?? AccountSettingsTab.account;
182
190
  _emailController = TextEditingController(
183
191
  text: widget.controller.user?['email']?.toString() ?? '',
184
192
  );
@@ -196,6 +204,10 @@ class _AccountSettingsPanelState extends State<AccountSettingsPanel> {
196
204
  @override
197
205
  void didUpdateWidget(covariant AccountSettingsPanel oldWidget) {
198
206
  super.didUpdateWidget(oldWidget);
207
+ if (widget.initialTab != null &&
208
+ oldWidget.initialTab != widget.initialTab) {
209
+ _selectedTab = widget.initialTab!;
210
+ }
199
211
  final email = widget.controller.user?['email']?.toString() ?? '';
200
212
  if (_emailController.text.isEmpty && email.isNotEmpty) {
201
213
  _emailController.text = email;
@@ -291,42 +303,43 @@ class _AccountSettingsPanelState extends State<AccountSettingsPanel> {
291
303
  @override
292
304
  Widget build(BuildContext context) {
293
305
  final compact = MediaQuery.sizeOf(context).width < 860;
306
+ final showTabSwitcher = widget.initialTab == null;
294
307
  return ListView(
295
- padding: _pagePadding(context),
308
+ padding: widget.embedded ? EdgeInsets.zero : _pagePadding(context),
296
309
  children: <Widget>[
297
- _PageTitle(
298
- title: 'Account settings',
299
- subtitle:
300
- 'Manage your account email, two-factor authentication, and active sessions.',
301
- trailing: OutlinedButton.icon(
302
- onPressed: widget.controller.isLoadingAccountSettings
303
- ? null
304
- : widget.controller.refreshAccountSettings,
305
- icon: widget.controller.isLoadingAccountSettings
306
- ? const SizedBox.square(
307
- dimension: 16,
308
- child: CircularProgressIndicator(strokeWidth: 2),
309
- )
310
- : Icon(Icons.refresh),
311
- label: Text('Refresh'),
310
+ if (!widget.embedded)
311
+ _PageTitle(
312
+ title: 'Account settings',
313
+ subtitle:
314
+ 'Manage your account email, two-factor authentication, and active sessions.',
315
+ trailing: _refreshButton(),
316
+ )
317
+ else
318
+ Align(
319
+ alignment: Alignment.centerRight,
320
+ child: Padding(
321
+ padding: const EdgeInsets.only(bottom: 12),
322
+ child: _refreshButton(),
323
+ ),
312
324
  ),
313
- ),
314
325
  if (widget.controller.errorMessage != null) ...<Widget>[
315
326
  _InlineError(message: widget.controller.errorMessage!),
316
327
  const SizedBox(height: 16),
317
328
  ],
318
- if (compact)
329
+ if (showTabSwitcher && compact)
319
330
  _AccountSettingsTabs(
320
331
  selected: _selectedTab,
321
332
  onSelected: (value) => setState(() => _selectedTab = value),
322
333
  )
323
334
  else
324
335
  const SizedBox.shrink(),
325
- if (compact) const SizedBox(height: 16),
336
+ if (showTabSwitcher && compact) const SizedBox(height: 16),
326
337
  Card(
327
338
  child: Padding(
328
339
  padding: const EdgeInsets.all(20),
329
- child: compact
340
+ child: !showTabSwitcher
341
+ ? _buildSelectedPanel()
342
+ : compact
330
343
  ? _buildSelectedPanel()
331
344
  : Row(
332
345
  crossAxisAlignment: CrossAxisAlignment.start,
@@ -359,6 +372,21 @@ class _AccountSettingsPanelState extends State<AccountSettingsPanel> {
359
372
  }
360
373
  }
361
374
 
375
+ Widget _refreshButton() {
376
+ return OutlinedButton.icon(
377
+ onPressed: widget.controller.isLoadingAccountSettings
378
+ ? null
379
+ : widget.controller.refreshAccountSettings,
380
+ icon: widget.controller.isLoadingAccountSettings
381
+ ? const SizedBox.square(
382
+ dimension: 16,
383
+ child: CircularProgressIndicator(strokeWidth: 2),
384
+ )
385
+ : Icon(Icons.refresh),
386
+ label: Text('Refresh'),
387
+ );
388
+ }
389
+
362
390
  Widget _buildAccountPanel() {
363
391
  final controller = widget.controller;
364
392
  final username = controller.user?['username']?.toString() ?? 'Account';
@@ -367,24 +367,38 @@ class AgentsPanel extends StatelessWidget {
367
367
  }
368
368
 
369
369
  class McpPanel extends StatelessWidget {
370
- const McpPanel({super.key, required this.controller});
370
+ const McpPanel({super.key, required this.controller, this.embedded = false});
371
371
 
372
372
  final NeoAgentController controller;
373
+ final bool embedded;
373
374
 
374
375
  @override
375
376
  Widget build(BuildContext context) {
376
377
  return ListView(
377
- padding: _pagePadding(context),
378
+ padding: embedded ? EdgeInsets.zero : _pagePadding(context),
378
379
  children: <Widget>[
379
- _PageTitle(
380
- title: 'MCP',
381
- subtitle: 'Configured MCP servers and live server status.',
382
- trailing: FilledButton.icon(
383
- onPressed: () => _openMcpEditor(context),
384
- icon: Icon(Icons.add),
385
- label: Text('Add Server'),
380
+ if (!embedded)
381
+ _PageTitle(
382
+ title: 'MCP',
383
+ subtitle: 'Configured MCP servers and live server status.',
384
+ trailing: FilledButton.icon(
385
+ onPressed: () => _openMcpEditor(context),
386
+ icon: Icon(Icons.add),
387
+ label: Text('Add Server'),
388
+ ),
389
+ )
390
+ else
391
+ Align(
392
+ alignment: Alignment.centerRight,
393
+ child: Padding(
394
+ padding: const EdgeInsets.only(bottom: 12),
395
+ child: FilledButton.icon(
396
+ onPressed: () => _openMcpEditor(context),
397
+ icon: const Icon(Icons.add),
398
+ label: const Text('Add Server'),
399
+ ),
400
+ ),
386
401
  ),
387
- ),
388
402
  if (controller.mcpServers.isEmpty)
389
403
  const _EmptyCard(
390
404
  title: 'No MCP servers configured',
@@ -1120,10 +1120,11 @@ class _HomeViewState extends State<HomeView> {
1120
1120
  }
1121
1121
 
1122
1122
  SidebarGroup? _sidebarGroupForSection(AppSection section) {
1123
- if (!_mainSections(widget.controller).contains(section)) {
1123
+ final visibleSection = section.canonicalSection;
1124
+ if (!_mainSections(widget.controller).contains(visibleSection)) {
1124
1125
  return null;
1125
1126
  }
1126
- return section.group;
1127
+ return visibleSection.group;
1127
1128
  }
1128
1129
 
1129
1130
  void _handleControllerChanged() {
@@ -2104,19 +2105,19 @@ class _SectionBody extends StatelessWidget {
2104
2105
  case AppSection.messaging:
2105
2106
  return MessagingPanel(controller: controller);
2106
2107
  case AppSection.runs:
2107
- return RunsPanel(controller: controller);
2108
+ return RunsAndLogsPanel(controller: controller);
2108
2109
  case AppSection.settings:
2109
- return SettingsPanel(controller: controller);
2110
+ return SettingsWorkspacePanel(controller: controller);
2110
2111
  case AppSection.accountSettings:
2111
- return AccountSettingsPanel(controller: controller);
2112
+ return SettingsWorkspacePanel(controller: controller);
2112
2113
  case AppSection.logs:
2113
- return LogsPanel(controller: controller);
2114
+ return RunsAndLogsPanel(controller: controller);
2114
2115
  case AppSection.skills:
2115
- return SkillsPanel(controller: controller);
2116
+ return ToolsPanel(controller: controller);
2116
2117
  case AppSection.agents:
2117
2118
  return AgentsPanel(controller: controller);
2118
2119
  case AppSection.integrations:
2119
- return IntegrationsPanel(controller: controller);
2120
+ return ToolsPanel(controller: controller);
2120
2121
  case AppSection.memory:
2121
2122
  return MemoryPanel(controller: controller);
2122
2123
  case AppSection.tasks:
@@ -2124,7 +2125,7 @@ class _SectionBody extends StatelessWidget {
2124
2125
  case AppSection.widgets:
2125
2126
  return WidgetsPanel(controller: controller);
2126
2127
  case AppSection.mcp:
2127
- return McpPanel(controller: controller);
2128
+ return ToolsPanel(controller: controller);
2128
2129
  case AppSection.health:
2129
2130
  return controller.showHealthSection
2130
2131
  ? HealthPanel(controller: controller)