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.
- package/flutter_app/lib/main.dart +1 -0
- package/flutter_app/lib/main_account_settings.dart +50 -22
- package/flutter_app/lib/main_admin.dart +24 -10
- package/flutter_app/lib/main_app_shell.dart +10 -9
- package/flutter_app/lib/main_chat.dart +433 -309
- package/flutter_app/lib/main_controller.dart +2 -1
- package/flutter_app/lib/main_integrations.dart +15 -7
- package/flutter_app/lib/main_models.dart +116 -7
- package/flutter_app/lib/main_navigation.dart +27 -18
- package/flutter_app/lib/main_operations.dart +162 -91
- package/flutter_app/lib/main_settings.dart +268 -71
- package/flutter_app/lib/main_shared.dart +4 -6
- package/flutter_app/lib/main_unified.dart +388 -0
- package/package.json +1 -1
- package/server/db/database.js +52 -0
- package/server/public/.last_build_id +1 -1
- package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/public/main.dart.js +77499 -76627
- package/server/routes/agents.js +2 -1
- package/server/routes/memory.js +75 -3
- package/server/routes/widgets.js +4 -4
- package/server/services/ai/engine.js +86 -0
- package/server/services/ai/runEvents.js +100 -0
- package/server/services/memory/manager.js +242 -26
- package/server/services/websocket.js +3 -1
- package/server/services/widgets/focus_widget.js +126 -0
- package/server/services/widgets/service.js +130 -2
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
part of 'main.dart';
|
|
2
2
|
|
|
3
3
|
class SettingsPanel extends StatefulWidget {
|
|
4
|
-
const SettingsPanel({
|
|
4
|
+
const SettingsPanel({
|
|
5
|
+
super.key,
|
|
6
|
+
required this.controller,
|
|
7
|
+
this.embedded = false,
|
|
8
|
+
});
|
|
5
9
|
|
|
6
10
|
final NeoAgentController controller;
|
|
11
|
+
final bool embedded;
|
|
7
12
|
|
|
8
13
|
@override
|
|
9
14
|
State<SettingsPanel> createState() => _SettingsPanelState();
|
|
@@ -69,7 +74,99 @@ const Map<String, List<String>> _voiceLiveVoicesByProvider =
|
|
|
69
74
|
],
|
|
70
75
|
};
|
|
71
76
|
|
|
77
|
+
class _SettingsSection {
|
|
78
|
+
const _SettingsSection(
|
|
79
|
+
this.title,
|
|
80
|
+
this.keywords, {
|
|
81
|
+
this.requiresDesktop = false,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
final String title;
|
|
85
|
+
final List<String> keywords;
|
|
86
|
+
final bool requiresDesktop;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const _overviewSettingsSection = _SettingsSection('overview', <String>[
|
|
90
|
+
'overview',
|
|
91
|
+
'summary',
|
|
92
|
+
'onboarding',
|
|
93
|
+
'platform',
|
|
94
|
+
'providers',
|
|
95
|
+
]);
|
|
96
|
+
|
|
97
|
+
const _workspaceSettingsSection = _SettingsSection('workspace', <String>[
|
|
98
|
+
'workspace',
|
|
99
|
+
'browser',
|
|
100
|
+
'extension',
|
|
101
|
+
'headless',
|
|
102
|
+
'routing',
|
|
103
|
+
]);
|
|
104
|
+
|
|
105
|
+
const _modelsSettingsSection = _SettingsSection('models', <String>[
|
|
106
|
+
'models',
|
|
107
|
+
'providers',
|
|
108
|
+
'routing',
|
|
109
|
+
'fallback',
|
|
110
|
+
'chat',
|
|
111
|
+
'sub-agent',
|
|
112
|
+
'subagent',
|
|
113
|
+
'smart selector',
|
|
114
|
+
]);
|
|
115
|
+
|
|
116
|
+
const _voiceRecordingSettingsSection = _SettingsSection(
|
|
117
|
+
'voice recording',
|
|
118
|
+
<String>[
|
|
119
|
+
'voice',
|
|
120
|
+
'recording',
|
|
121
|
+
'transcription',
|
|
122
|
+
'summary',
|
|
123
|
+
'speech',
|
|
124
|
+
'tts',
|
|
125
|
+
'stt',
|
|
126
|
+
'live',
|
|
127
|
+
],
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
const _desktopSettingsSection = _SettingsSection('desktop', <String>[
|
|
131
|
+
'desktop',
|
|
132
|
+
'permissions',
|
|
133
|
+
'capture',
|
|
134
|
+
'companion',
|
|
135
|
+
'screen recording',
|
|
136
|
+
'accessibility',
|
|
137
|
+
'input',
|
|
138
|
+
], requiresDesktop: true);
|
|
139
|
+
|
|
140
|
+
const _updatesSettingsSection = _SettingsSection('updates', <String>[
|
|
141
|
+
'updates',
|
|
142
|
+
'release',
|
|
143
|
+
'channel',
|
|
144
|
+
'version',
|
|
145
|
+
'self update',
|
|
146
|
+
'upgrade',
|
|
147
|
+
]);
|
|
148
|
+
|
|
149
|
+
const _diagnosticsSettingsSection = _SettingsSection('diagnostics', <String>[
|
|
150
|
+
'diagnostics',
|
|
151
|
+
'logs',
|
|
152
|
+
'token',
|
|
153
|
+
'usage',
|
|
154
|
+
'debug',
|
|
155
|
+
'health',
|
|
156
|
+
]);
|
|
157
|
+
|
|
158
|
+
const List<_SettingsSection> _settingsSearchSections = <_SettingsSection>[
|
|
159
|
+
_overviewSettingsSection,
|
|
160
|
+
_workspaceSettingsSection,
|
|
161
|
+
_modelsSettingsSection,
|
|
162
|
+
_voiceRecordingSettingsSection,
|
|
163
|
+
_desktopSettingsSection,
|
|
164
|
+
_updatesSettingsSection,
|
|
165
|
+
_diagnosticsSettingsSection,
|
|
166
|
+
];
|
|
167
|
+
|
|
72
168
|
class _SettingsPanelState extends State<SettingsPanel> {
|
|
169
|
+
late final TextEditingController _searchController;
|
|
73
170
|
late bool _headlessBrowser;
|
|
74
171
|
late String _browserBackend;
|
|
75
172
|
late bool _smarterSelector;
|
|
@@ -91,11 +188,13 @@ class _SettingsPanelState extends State<SettingsPanel> {
|
|
|
91
188
|
@override
|
|
92
189
|
void initState() {
|
|
93
190
|
super.initState();
|
|
191
|
+
_searchController = TextEditingController();
|
|
94
192
|
_hydrate();
|
|
95
193
|
}
|
|
96
194
|
|
|
97
195
|
@override
|
|
98
196
|
void dispose() {
|
|
197
|
+
_searchController.dispose();
|
|
99
198
|
for (final controller in _providerBaseUrlControllers.values) {
|
|
100
199
|
controller.dispose();
|
|
101
200
|
}
|
|
@@ -186,6 +285,7 @@ class _SettingsPanelState extends State<SettingsPanel> {
|
|
|
186
285
|
@override
|
|
187
286
|
Widget build(BuildContext context) {
|
|
188
287
|
final controller = widget.controller;
|
|
288
|
+
final searchQuery = _searchController.text.trim().toLowerCase();
|
|
189
289
|
final availableModels = controller.supportedModels
|
|
190
290
|
.where((model) => model.available)
|
|
191
291
|
.toList();
|
|
@@ -215,93 +315,190 @@ class _SettingsPanelState extends State<SettingsPanel> {
|
|
|
215
315
|
final enabledSmartModels = _enabledModels
|
|
216
316
|
.where((id) => routingModels.any((model) => model.id == id))
|
|
217
317
|
.length;
|
|
318
|
+
final visibleSearchSections = _settingsSearchSections
|
|
319
|
+
.where((section) => !section.requiresDesktop || _supportsDesktopShell)
|
|
320
|
+
.toSet();
|
|
218
321
|
|
|
219
322
|
return ListView(
|
|
220
|
-
padding: _pagePadding(context),
|
|
323
|
+
padding: widget.embedded ? EdgeInsets.zero : _pagePadding(context),
|
|
221
324
|
children: <Widget>[
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
defaultChatModel: _defaultChatModel,
|
|
237
|
-
defaultSubagentModel: _defaultSubagentModel,
|
|
238
|
-
defaultRecordingTranscriptionProvider: 'deepgram',
|
|
239
|
-
defaultRecordingTranscriptionModel:
|
|
240
|
-
_defaultRecordingTranscriptionModel,
|
|
241
|
-
defaultRecordingSummaryProvider: _providerForSelectedModel(
|
|
242
|
-
_defaultRecordingSummaryModel,
|
|
243
|
-
controller.supportedModels,
|
|
244
|
-
),
|
|
245
|
-
defaultRecordingSummaryModel: _defaultRecordingSummaryModel,
|
|
246
|
-
fallbackModel: _fallbackModel,
|
|
247
|
-
defaultSpeechModel: _defaultSpeechModel,
|
|
248
|
-
voiceSttProvider: controller.voiceSttProvider,
|
|
249
|
-
voiceSttModel: controller.voiceSttModel,
|
|
250
|
-
voiceTtsProvider: controller.voiceTtsProvider,
|
|
251
|
-
voiceTtsModel: controller.voiceTtsModel,
|
|
252
|
-
voiceTtsVoice: controller.voiceTtsVoice,
|
|
253
|
-
voiceRuntimeMode: 'live',
|
|
254
|
-
voiceLiveProvider: _voiceLiveProvider,
|
|
255
|
-
voiceLiveModel: _voiceLiveModel,
|
|
256
|
-
voiceLiveVoice: _voiceLiveVoice,
|
|
257
|
-
aiProviderConfigs: _buildProviderPayload(),
|
|
258
|
-
),
|
|
259
|
-
style: FilledButton.styleFrom(backgroundColor: _accent),
|
|
260
|
-
icon: controller.isSavingSettings
|
|
261
|
-
? const SizedBox.square(
|
|
262
|
-
dimension: 16,
|
|
263
|
-
child: CircularProgressIndicator(
|
|
264
|
-
strokeWidth: 2,
|
|
265
|
-
color: Colors.white,
|
|
266
|
-
),
|
|
267
|
-
)
|
|
268
|
-
: Icon(Icons.save_outlined),
|
|
269
|
-
label: Text('Save'),
|
|
325
|
+
if (!widget.embedded)
|
|
326
|
+
_PageTitle(
|
|
327
|
+
title: 'Settings',
|
|
328
|
+
subtitle:
|
|
329
|
+
'Workspace, models, recording, update, and diagnostics controls.',
|
|
330
|
+
trailing: _settingsSaveButton(controller),
|
|
331
|
+
)
|
|
332
|
+
else
|
|
333
|
+
Align(
|
|
334
|
+
alignment: Alignment.centerRight,
|
|
335
|
+
child: Padding(
|
|
336
|
+
padding: const EdgeInsets.only(bottom: 12),
|
|
337
|
+
child: _settingsSaveButton(controller),
|
|
338
|
+
),
|
|
270
339
|
),
|
|
271
|
-
),
|
|
272
340
|
if (controller.errorMessage != null) ...<Widget>[
|
|
273
341
|
_InlineError(message: controller.errorMessage!),
|
|
274
342
|
const SizedBox(height: 16),
|
|
275
343
|
],
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
344
|
+
TextField(
|
|
345
|
+
controller: _searchController,
|
|
346
|
+
onChanged: (_) => setState(() {}),
|
|
347
|
+
decoration: InputDecoration(
|
|
348
|
+
labelText: 'Search settings',
|
|
349
|
+
hintText: 'Models, browser, voice, updates, diagnostics...',
|
|
350
|
+
prefixIcon: const Icon(Icons.search),
|
|
351
|
+
suffixIcon: searchQuery.isEmpty
|
|
352
|
+
? null
|
|
353
|
+
: IconButton(
|
|
354
|
+
onPressed: () {
|
|
355
|
+
_searchController.clear();
|
|
356
|
+
setState(() {});
|
|
357
|
+
},
|
|
358
|
+
icon: const Icon(Icons.close),
|
|
359
|
+
),
|
|
360
|
+
),
|
|
292
361
|
),
|
|
293
362
|
const SizedBox(height: 16),
|
|
294
|
-
if (
|
|
363
|
+
if (_matchesSettingsSection(
|
|
364
|
+
searchQuery,
|
|
365
|
+
_overviewSettingsSection,
|
|
366
|
+
)) ...<Widget>[
|
|
367
|
+
_buildSettingsOverview(controller, availableModels.length),
|
|
368
|
+
const SizedBox(height: 16),
|
|
369
|
+
],
|
|
370
|
+
if (_matchesSettingsSection(
|
|
371
|
+
searchQuery,
|
|
372
|
+
_workspaceSettingsSection,
|
|
373
|
+
)) ...<Widget>[
|
|
374
|
+
_buildWorkspaceSection(controller),
|
|
375
|
+
const SizedBox(height: 16),
|
|
376
|
+
],
|
|
377
|
+
if (_matchesSettingsSection(
|
|
378
|
+
searchQuery,
|
|
379
|
+
_modelsSettingsSection,
|
|
380
|
+
)) ...<Widget>[
|
|
381
|
+
_buildModelsSection(
|
|
382
|
+
controller: controller,
|
|
383
|
+
modelChoices: modelChoices,
|
|
384
|
+
routingModels: routingModels,
|
|
385
|
+
availableModels: availableModels,
|
|
386
|
+
enabledSmartModels: enabledSmartModels,
|
|
387
|
+
),
|
|
388
|
+
const SizedBox(height: 16),
|
|
389
|
+
],
|
|
390
|
+
if (_matchesSettingsSection(
|
|
391
|
+
searchQuery,
|
|
392
|
+
_voiceRecordingSettingsSection,
|
|
393
|
+
)) ...<Widget>[
|
|
394
|
+
_buildVoiceAndRecordingSection(
|
|
395
|
+
controller: controller,
|
|
396
|
+
modelChoices: modelChoices,
|
|
397
|
+
routingModels: routingModels,
|
|
398
|
+
),
|
|
399
|
+
const SizedBox(height: 16),
|
|
400
|
+
],
|
|
401
|
+
if (visibleSearchSections.contains(_desktopSettingsSection) &&
|
|
402
|
+
_matchesSettingsSection(
|
|
403
|
+
searchQuery,
|
|
404
|
+
_desktopSettingsSection,
|
|
405
|
+
)) ...<Widget>[
|
|
295
406
|
_buildDesktopSection(controller),
|
|
296
407
|
const SizedBox(height: 16),
|
|
297
408
|
],
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
409
|
+
if (_matchesSettingsSection(
|
|
410
|
+
searchQuery,
|
|
411
|
+
_updatesSettingsSection,
|
|
412
|
+
)) ...<Widget>[
|
|
413
|
+
_buildUpdatesSection(controller),
|
|
414
|
+
const SizedBox(height: 16),
|
|
415
|
+
],
|
|
416
|
+
if (_matchesSettingsSection(
|
|
417
|
+
searchQuery,
|
|
418
|
+
_diagnosticsSettingsSection,
|
|
419
|
+
)) ...<Widget>[_buildDiagnosticsSection(controller)],
|
|
420
|
+
if (_noSettingsMatches(searchQuery, visibleSearchSections)) ...<Widget>[
|
|
421
|
+
const _EmptyCard(
|
|
422
|
+
title: 'No matching settings',
|
|
423
|
+
subtitle:
|
|
424
|
+
'Try a broader search like models, browser, voice, or updates.',
|
|
425
|
+
),
|
|
426
|
+
],
|
|
301
427
|
],
|
|
302
428
|
);
|
|
303
429
|
}
|
|
304
430
|
|
|
431
|
+
bool _matchesSettingsSection(String query, _SettingsSection section) {
|
|
432
|
+
if (query.isEmpty) {
|
|
433
|
+
return true;
|
|
434
|
+
}
|
|
435
|
+
final haystack = <String>[
|
|
436
|
+
section.title,
|
|
437
|
+
...section.keywords,
|
|
438
|
+
].join(' ').toLowerCase();
|
|
439
|
+
return haystack.contains(query);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
bool _noSettingsMatches(
|
|
443
|
+
String query,
|
|
444
|
+
Iterable<_SettingsSection> visibleSections,
|
|
445
|
+
) {
|
|
446
|
+
if (query.isEmpty) {
|
|
447
|
+
return false;
|
|
448
|
+
}
|
|
449
|
+
return !visibleSections.any(
|
|
450
|
+
(section) => _matchesSettingsSection(query, section),
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
Widget _settingsSaveButton(NeoAgentController controller) {
|
|
455
|
+
return FilledButton.icon(
|
|
456
|
+
onPressed: controller.isSavingSettings
|
|
457
|
+
? null
|
|
458
|
+
: () => controller.saveSettings(
|
|
459
|
+
headlessBrowser: _headlessBrowser,
|
|
460
|
+
browserBackend: _browserBackend == 'extension'
|
|
461
|
+
? 'extension'
|
|
462
|
+
: controller.cloudBrowserBackend,
|
|
463
|
+
smarterSelector: _smarterSelector,
|
|
464
|
+
enabledModels: _enabledModels.toList(),
|
|
465
|
+
defaultChatModel: _defaultChatModel,
|
|
466
|
+
defaultSubagentModel: _defaultSubagentModel,
|
|
467
|
+
defaultRecordingTranscriptionProvider: 'deepgram',
|
|
468
|
+
defaultRecordingTranscriptionModel:
|
|
469
|
+
_defaultRecordingTranscriptionModel,
|
|
470
|
+
defaultRecordingSummaryProvider: _providerForSelectedModel(
|
|
471
|
+
_defaultRecordingSummaryModel,
|
|
472
|
+
controller.supportedModels,
|
|
473
|
+
),
|
|
474
|
+
defaultRecordingSummaryModel: _defaultRecordingSummaryModel,
|
|
475
|
+
fallbackModel: _fallbackModel,
|
|
476
|
+
defaultSpeechModel: _defaultSpeechModel,
|
|
477
|
+
voiceSttProvider: controller.voiceSttProvider,
|
|
478
|
+
voiceSttModel: controller.voiceSttModel,
|
|
479
|
+
voiceTtsProvider: controller.voiceTtsProvider,
|
|
480
|
+
voiceTtsModel: controller.voiceTtsModel,
|
|
481
|
+
voiceTtsVoice: controller.voiceTtsVoice,
|
|
482
|
+
voiceRuntimeMode: 'live',
|
|
483
|
+
voiceLiveProvider: _voiceLiveProvider,
|
|
484
|
+
voiceLiveModel: _voiceLiveModel,
|
|
485
|
+
voiceLiveVoice: _voiceLiveVoice,
|
|
486
|
+
aiProviderConfigs: _buildProviderPayload(),
|
|
487
|
+
),
|
|
488
|
+
style: FilledButton.styleFrom(backgroundColor: _accent),
|
|
489
|
+
icon: controller.isSavingSettings
|
|
490
|
+
? const SizedBox.square(
|
|
491
|
+
dimension: 16,
|
|
492
|
+
child: CircularProgressIndicator(
|
|
493
|
+
strokeWidth: 2,
|
|
494
|
+
color: Colors.white,
|
|
495
|
+
),
|
|
496
|
+
)
|
|
497
|
+
: Icon(Icons.save_outlined),
|
|
498
|
+
label: Text('Save'),
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
|
|
305
502
|
Widget _buildSettingsOverview(
|
|
306
503
|
NeoAgentController controller,
|
|
307
504
|
int availableModelCount,
|
|
@@ -232,13 +232,10 @@ List<AppSection> _mainSections(NeoAgentController controller) {
|
|
|
232
232
|
AppSection.chat,
|
|
233
233
|
AppSection.recordings,
|
|
234
234
|
AppSection.runs,
|
|
235
|
-
AppSection.logs,
|
|
236
235
|
AppSection.devices,
|
|
237
236
|
AppSection.tasks,
|
|
238
237
|
AppSection.widgets,
|
|
239
|
-
AppSection.skills,
|
|
240
238
|
AppSection.integrations,
|
|
241
|
-
AppSection.mcp,
|
|
242
239
|
AppSection.memory,
|
|
243
240
|
if (controller.showHealthSection) AppSection.health,
|
|
244
241
|
AppSection.settings,
|
|
@@ -256,7 +253,7 @@ List<Widget> _buildSidebarItems(
|
|
|
256
253
|
final widgets = <Widget>[];
|
|
257
254
|
final mainSections = _mainSections(controller);
|
|
258
255
|
final selectedSidebarSection = mainSections.contains(
|
|
259
|
-
controller.selectedSection,
|
|
256
|
+
controller.selectedSection.canonicalSection,
|
|
260
257
|
);
|
|
261
258
|
for (final group in SidebarGroup.values) {
|
|
262
259
|
final sections = mainSections
|
|
@@ -267,7 +264,8 @@ List<Widget> _buildSidebarItems(
|
|
|
267
264
|
}
|
|
268
265
|
|
|
269
266
|
final active =
|
|
270
|
-
selectedSidebarSection &&
|
|
267
|
+
selectedSidebarSection &&
|
|
268
|
+
controller.selectedSection.canonicalSection.group == group;
|
|
271
269
|
final defaultSection = sections.first;
|
|
272
270
|
final hasChildren = sections.length > 1;
|
|
273
271
|
final expanded = expandedGroup == group;
|
|
@@ -299,7 +297,7 @@ List<Widget> _buildSidebarItems(
|
|
|
299
297
|
_SidebarButton(
|
|
300
298
|
label: section.label,
|
|
301
299
|
icon: section.icon,
|
|
302
|
-
active: controller.selectedSection == section,
|
|
300
|
+
active: controller.selectedSection.canonicalSection == section,
|
|
303
301
|
indent: 18,
|
|
304
302
|
iconSize: 16,
|
|
305
303
|
fontSize: 12,
|