neoagent 2.4.1-beta.9 → 2.4.1
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 +33 -3
- package/LICENSE +111 -56
- package/README.md +8 -3
- package/docs/configuration.md +8 -0
- package/docs/getting-started.md +9 -3
- package/docs/index.md +4 -0
- package/extensions/chrome-browser/background.mjs +36 -4
- package/extensions/chrome-browser/icons/icon128.png +0 -0
- package/extensions/chrome-browser/icons/icon16.png +0 -0
- package/extensions/chrome-browser/icons/icon48.png +0 -0
- package/extensions/chrome-browser/icons/logo.svg +39 -8
- package/extensions/chrome-browser/manifest.json +3 -3
- package/extensions/chrome-browser/popup.html +5 -1
- package/extensions/chrome-browser/popup.js +13 -0
- package/flutter_app/android/app/src/main/AndroidManifest.xml +2 -1
- package/flutter_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/flutter_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/flutter_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/flutter_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/flutter_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- package/flutter_app/assets/branding/app_icon_1024.png +0 -0
- package/flutter_app/assets/branding/app_icon_128.png +0 -0
- package/flutter_app/assets/branding/app_icon_192.png +0 -0
- package/flutter_app/assets/branding/app_icon_256.png +0 -0
- package/flutter_app/assets/branding/app_icon_32.png +0 -0
- package/flutter_app/assets/branding/app_icon_512.png +0 -0
- package/flutter_app/assets/branding/app_icon_64.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_1024.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_128.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_192.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_256.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_32.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_512.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_64.png +0 -0
- package/flutter_app/assets/branding/onboarding_intro.mp4 +0 -0
- 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/features/location/location_service.dart +3 -0
- package/flutter_app/lib/features/onboarding/onboarding_chrome.dart +391 -382
- package/flutter_app/lib/features/onboarding/onboarding_companion_step.dart +743 -0
- package/flutter_app/lib/features/onboarding/onboarding_messaging_step.dart +18 -16
- package/flutter_app/lib/features/onboarding/onboarding_model_step.dart +19 -18
- package/flutter_app/lib/features/onboarding/onboarding_shell.dart +8 -1
- package/flutter_app/lib/features/onboarding/onboarding_video_step.dart +16 -13
- package/flutter_app/lib/features/onboarding/onboarding_welcome_step.dart +17 -13
- package/flutter_app/lib/main.dart +2 -0
- package/flutter_app/lib/main_account_settings.dart +10 -34
- package/flutter_app/lib/main_admin.dart +14 -1
- package/flutter_app/lib/main_app_shell.dart +377 -340
- package/flutter_app/lib/main_chat.dart +707 -227
- package/flutter_app/lib/main_controller.dart +197 -42
- package/flutter_app/lib/main_devices.dart +436 -4
- package/flutter_app/lib/main_integrations.dart +255 -6
- package/flutter_app/lib/main_launcher.dart +1 -1
- package/flutter_app/lib/main_model_picker.dart +685 -0
- package/flutter_app/lib/main_models.dart +212 -0
- package/flutter_app/lib/main_navigation.dart +1 -9
- package/flutter_app/lib/main_operations.dart +1417 -614
- package/flutter_app/lib/main_settings.dart +673 -871
- package/flutter_app/lib/main_shared.dart +971 -443
- package/flutter_app/lib/main_spacing.dart +4 -4
- package/flutter_app/lib/main_theme.dart +22 -14
- package/flutter_app/lib/main_unified.dart +5 -72
- package/flutter_app/lib/src/android_apk_drop_zone.dart +24 -0
- package/flutter_app/lib/src/android_apk_drop_zone_stub.dart +13 -0
- package/flutter_app/lib/src/android_apk_drop_zone_web.dart +219 -0
- package/flutter_app/lib/src/backend_client.dart +46 -0
- package/flutter_app/lib/src/desktop_companion_actions.dart +30 -7
- package/flutter_app/lib/src/desktop_companion_io.dart +71 -1
- package/flutter_app/lib/src/security/password_strength.dart +84 -0
- package/flutter_app/lib/src/stream_renderer.dart +42 -3
- package/flutter_app/lib/src/theme/palette.dart +76 -34
- package/flutter_app/linux/runner/resources/app_icon.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png +0 -0
- package/flutter_app/pubspec.lock +2 -2
- package/flutter_app/pubspec.yaml +7 -1
- package/flutter_app/tool/branding_source/neoagent-icon-1024.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-128.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-16.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-180.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-192.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-256.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-32.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-48.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-512.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-64.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon.svg +43 -0
- package/flutter_app/tool/generate_desktop_branding.py +154 -152
- package/flutter_app/web/favicon.png +0 -0
- package/flutter_app/web/favicon.svg +40 -9
- package/flutter_app/web/favicon_light.svg +43 -0
- package/flutter_app/web/icons/Icon-192-light.png +0 -0
- package/flutter_app/web/icons/Icon-192.png +0 -0
- package/flutter_app/web/icons/Icon-512-light.png +0 -0
- package/flutter_app/web/icons/Icon-512.png +0 -0
- package/flutter_app/web/icons/Icon-maskable-192-light.png +0 -0
- package/flutter_app/web/icons/Icon-maskable-192.png +0 -0
- package/flutter_app/web/icons/Icon-maskable-512-light.png +0 -0
- package/flutter_app/web/icons/Icon-maskable-512.png +0 -0
- package/flutter_app/windows/runner/main.cpp +7 -1
- package/flutter_app/windows/runner/resources/app_icon.ico +0 -0
- package/lib/manager.js +445 -83
- package/package.json +17 -3
- package/runtime/paths.js +3 -1
- package/server/admin/access.js +198 -0
- package/server/admin/admin.css +268 -0
- package/server/admin/admin.js +348 -0
- package/server/admin/analytics.js +128 -0
- package/server/admin/index.html +1015 -0
- package/server/admin/login.html +290 -0
- package/server/admin/logo.svg +43 -0
- package/server/admin/sql.js +134 -0
- package/server/admin/users.js +147 -0
- package/server/config/origins.js +3 -1
- package/server/db/database.js +92 -0
- package/server/db/ftsQuery.js +27 -0
- package/server/http/routes.js +1 -0
- package/server/http/static.js +23 -6
- package/server/index.js +1 -1
- package/server/middleware/adminAuth.js +48 -0
- package/server/middleware/auth.js +1 -40
- package/server/public/.last_build_id +1 -1
- package/server/public/app_icon.png +0 -0
- package/server/public/assets/AssetManifest.bin +1 -1
- package/server/public/assets/AssetManifest.bin.json +1 -1
- package/server/public/assets/assets/branding/app_icon_1024.png +0 -0
- package/server/public/assets/assets/branding/app_icon_256.png +0 -0
- package/server/public/assets/assets/branding/app_icon_512.png +0 -0
- package/server/public/assets/assets/branding/app_icon_light_1024.png +0 -0
- package/server/public/assets/assets/branding/app_icon_light_256.png +0 -0
- package/server/public/assets/assets/branding/app_icon_light_512.png +0 -0
- package/server/public/assets/assets/branding/onboarding_intro.mp4 +0 -0
- 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/assets/fonts/MaterialIcons-Regular.otf +0 -0
- package/server/public/assets/web/icons/Icon-192.png +0 -0
- package/server/public/favicon.png +0 -0
- package/server/public/favicon.svg +40 -9
- package/server/public/favicon_light.svg +43 -0
- package/server/public/flutter_bootstrap.js +2 -2
- package/server/public/icons/Icon-192-light.png +0 -0
- package/server/public/icons/Icon-192.png +0 -0
- package/server/public/icons/Icon-512-light.png +0 -0
- package/server/public/icons/Icon-512.png +0 -0
- package/server/public/icons/Icon-maskable-192-light.png +0 -0
- package/server/public/icons/Icon-maskable-192.png +0 -0
- package/server/public/icons/Icon-maskable-512-light.png +0 -0
- package/server/public/icons/Icon-maskable-512.png +0 -0
- package/server/public/main.dart.js +88537 -85936
- package/server/routes/admin.js +632 -0
- package/server/routes/agent_profiles.js +3 -0
- package/server/routes/agents.js +1 -1
- package/server/routes/auth.js +3 -1
- package/server/routes/mcp.js +29 -13
- package/server/routes/memory.js +23 -1
- package/server/routes/messaging.js +2 -0
- package/server/routes/screenHistory.js +14 -8
- package/server/routes/settings.js +10 -2
- package/server/routes/stream.js +1 -1
- package/server/routes/triggers.js +4 -4
- package/server/routes/voice_assistant.js +36 -1
- package/server/routes/workspace.js +86 -0
- package/server/services/account/admin_two_factor.js +132 -0
- package/server/services/account/password_policy.js +6 -1
- package/server/services/ai/completion.js +44 -0
- package/server/services/ai/engine.js +321 -500
- package/server/services/ai/imageAnalysis.js +9 -5
- package/server/services/ai/logFormat.js +46 -0
- package/server/services/ai/loopPolicy.js +11 -0
- package/server/services/ai/messagingFallback.js +228 -0
- package/server/services/ai/models.js +194 -55
- package/server/services/ai/providerRetry.js +169 -0
- package/server/services/ai/providers/anthropic.js +15 -4
- package/server/services/ai/providers/google.js +38 -11
- package/server/services/ai/providers/grok.js +19 -68
- package/server/services/ai/providers/grokOauth.js +141 -0
- package/server/services/ai/providers/nvidia.js +154 -0
- package/server/services/ai/providers/ollama.js +76 -39
- package/server/services/ai/providers/openai.js +20 -31
- package/server/services/ai/providers/openaiCodex.js +6 -2
- package/server/services/ai/providers/openaiCompatible.js +70 -0
- package/server/services/ai/providers/openrouter.js +162 -0
- package/server/services/ai/settings.js +30 -0
- package/server/services/ai/systemPrompt.js +51 -29
- package/server/services/ai/taskAnalysis.js +60 -1
- package/server/services/ai/toolEvidence.js +207 -0
- package/server/services/ai/toolSelector.js +8 -1
- package/server/services/ai/tools.js +78 -13
- package/server/services/browser/extension/registry.js +94 -9
- package/server/services/desktop/registry.js +104 -1
- package/server/services/desktop/screenRecorder.js +208 -98
- package/server/services/desktop/screen_recorder_support.js +46 -0
- package/server/services/integrations/google/provider.js +13 -0
- package/server/services/integrations/home_assistant/constants.js +88 -0
- package/server/services/integrations/home_assistant/network.js +207 -0
- package/server/services/integrations/home_assistant/provider.js +249 -0
- package/server/services/integrations/home_assistant/snapshot.js +98 -0
- package/server/services/integrations/home_assistant/tools.js +101 -0
- package/server/services/integrations/manager.js +5 -0
- package/server/services/integrations/registry.js +2 -0
- package/server/services/integrations/trello/provider.js +8 -2
- package/server/services/manager.js +51 -53
- package/server/services/mcp/client.js +208 -268
- package/server/services/mcp/client_support.js +172 -0
- package/server/services/mcp/recovery.js +116 -0
- package/server/services/mcp/tool_operations.js +123 -0
- package/server/services/memory/ingestion.js +185 -370
- package/server/services/memory/ingestion_coverage.js +129 -0
- package/server/services/memory/ingestion_documents.js +123 -0
- package/server/services/memory/ingestion_support.js +171 -0
- package/server/services/memory/intelligence.js +181 -0
- package/server/services/memory/manager.js +476 -32
- package/server/services/messaging/automation.js +71 -134
- package/server/services/messaging/formatting_guides.js +26 -1
- package/server/services/messaging/inbound_queue.js +111 -0
- package/server/services/messaging/manager.js +25 -8
- package/server/services/messaging/typing_keepalive.js +110 -0
- package/server/services/streaming/android-stream.js +293 -40
- package/server/services/tasks/integration_runtime.js +4 -1
- package/server/services/tasks/runtime.js +415 -56
- package/server/services/tasks/task_repository.js +48 -6
- package/server/services/websocket.js +8 -2
- package/server/services/widgets/service.js +17 -1
- package/server/services/workspace/manager.js +116 -0
- package/server/utils/logger.js +44 -6
- package/server/utils/security.js +3 -0
- package/server/utils/version.js +29 -19
- package/server/services/memory/openhuman_uplift.test.js +0 -98
|
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|
|
2
2
|
import 'package:flutter_animate/flutter_animate.dart';
|
|
3
3
|
|
|
4
4
|
import '../../main.dart';
|
|
5
|
+
import '../../src/theme/palette.dart';
|
|
5
6
|
import 'onboarding_chrome.dart';
|
|
6
7
|
|
|
7
8
|
class OnboardingMessagingStep extends StatefulWidget {
|
|
@@ -29,7 +30,6 @@ class _OnboardingMessagingStepState extends State<OnboardingMessagingStep> {
|
|
|
29
30
|
: messagingPlatforms;
|
|
30
31
|
final width = MediaQuery.sizeOf(context).width;
|
|
31
32
|
final useGrid = width >= 700;
|
|
32
|
-
final columns = width >= 1050 ? 3 : (useGrid ? 2 : 1);
|
|
33
33
|
|
|
34
34
|
return OnboardingScaffold(
|
|
35
35
|
step: 2,
|
|
@@ -79,11 +79,11 @@ class _OnboardingMessagingStepState extends State<OnboardingMessagingStep> {
|
|
|
79
79
|
),
|
|
80
80
|
child: useGrid
|
|
81
81
|
? GridView.builder(
|
|
82
|
-
gridDelegate:
|
|
83
|
-
|
|
82
|
+
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
|
|
83
|
+
maxCrossAxisExtent: 360,
|
|
84
84
|
crossAxisSpacing: 14,
|
|
85
85
|
mainAxisSpacing: 14,
|
|
86
|
-
|
|
86
|
+
mainAxisExtent: 160,
|
|
87
87
|
),
|
|
88
88
|
itemCount: platforms.length,
|
|
89
89
|
itemBuilder: (context, index) {
|
|
@@ -133,6 +133,7 @@ class _MessagingPlatformCard extends StatelessWidget {
|
|
|
133
133
|
|
|
134
134
|
@override
|
|
135
135
|
Widget build(BuildContext context) {
|
|
136
|
+
final p = paletteOf(context);
|
|
136
137
|
final iconSize = compact ? 24.0 : 30.0;
|
|
137
138
|
final shellSize = compact ? 48.0 : 58.0;
|
|
138
139
|
return OnboardingOptionCard(
|
|
@@ -172,10 +173,10 @@ class _MessagingPlatformCard extends StatelessWidget {
|
|
|
172
173
|
platform.label,
|
|
173
174
|
maxLines: 1,
|
|
174
175
|
overflow: TextOverflow.ellipsis,
|
|
175
|
-
style:
|
|
176
|
-
color:
|
|
177
|
-
fontSize:
|
|
178
|
-
fontWeight: FontWeight.
|
|
176
|
+
style: TextStyle(
|
|
177
|
+
color: p.textPrimary,
|
|
178
|
+
fontSize: 16,
|
|
179
|
+
fontWeight: FontWeight.w700,
|
|
179
180
|
),
|
|
180
181
|
),
|
|
181
182
|
const SizedBox(height: 4),
|
|
@@ -184,9 +185,9 @@ class _MessagingPlatformCard extends StatelessWidget {
|
|
|
184
185
|
maxLines: 2,
|
|
185
186
|
overflow: TextOverflow.ellipsis,
|
|
186
187
|
style: TextStyle(
|
|
187
|
-
color:
|
|
188
|
+
color: p.textMuted,
|
|
188
189
|
fontSize: 13,
|
|
189
|
-
height: 1.
|
|
190
|
+
height: 1.4,
|
|
190
191
|
),
|
|
191
192
|
),
|
|
192
193
|
],
|
|
@@ -213,17 +214,17 @@ class _MessagingPlatformCard extends StatelessWidget {
|
|
|
213
214
|
children: <Widget>[
|
|
214
215
|
Text(
|
|
215
216
|
platform.label,
|
|
216
|
-
style:
|
|
217
|
-
color:
|
|
218
|
-
fontSize:
|
|
219
|
-
fontWeight: FontWeight.
|
|
217
|
+
style: TextStyle(
|
|
218
|
+
color: p.textPrimary,
|
|
219
|
+
fontSize: 18,
|
|
220
|
+
fontWeight: FontWeight.w700,
|
|
220
221
|
),
|
|
221
222
|
),
|
|
222
223
|
const SizedBox(height: 5),
|
|
223
224
|
Text(
|
|
224
225
|
platform.subtitle,
|
|
225
226
|
style: TextStyle(
|
|
226
|
-
color:
|
|
227
|
+
color: p.textMuted,
|
|
227
228
|
fontSize: 14,
|
|
228
229
|
height: 1.45,
|
|
229
230
|
),
|
|
@@ -255,6 +256,7 @@ class _SelectionIcon extends StatelessWidget {
|
|
|
255
256
|
|
|
256
257
|
@override
|
|
257
258
|
Widget build(BuildContext context) {
|
|
259
|
+
final p = paletteOf(context);
|
|
258
260
|
return AnimatedSwitcher(
|
|
259
261
|
duration: const Duration(milliseconds: 220),
|
|
260
262
|
child: selected
|
|
@@ -267,7 +269,7 @@ class _SelectionIcon extends StatelessWidget {
|
|
|
267
269
|
: Icon(
|
|
268
270
|
Icons.add_circle_outline_rounded,
|
|
269
271
|
key: ValueKey<String>('idle-$id'),
|
|
270
|
-
color:
|
|
272
|
+
color: p.textMuted.withValues(alpha: 0.5),
|
|
271
273
|
size: 28,
|
|
272
274
|
),
|
|
273
275
|
);
|
|
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|
|
2
2
|
import 'package:flutter_animate/flutter_animate.dart';
|
|
3
3
|
|
|
4
4
|
import '../../main.dart';
|
|
5
|
+
import '../../src/theme/palette.dart';
|
|
5
6
|
import 'onboarding_chrome.dart';
|
|
6
7
|
|
|
7
8
|
class OnboardingModelStep extends StatefulWidget {
|
|
@@ -76,14 +77,13 @@ class _OnboardingModelStepState extends State<OnboardingModelStep> {
|
|
|
76
77
|
Widget build(BuildContext context) {
|
|
77
78
|
final width = MediaQuery.sizeOf(context).width;
|
|
78
79
|
final useGrid = width >= 720;
|
|
79
|
-
final columns = width >= 1150 ? 3 : (useGrid ? 2 : 1);
|
|
80
80
|
|
|
81
81
|
return OnboardingScaffold(
|
|
82
82
|
step: 3,
|
|
83
83
|
totalSteps: 4,
|
|
84
84
|
eyebrow: 'INTELLIGENCE',
|
|
85
85
|
title: 'Choose your\ndefault model.',
|
|
86
|
-
description: 'Pick the model
|
|
86
|
+
description: 'Pick the model NeoAgent should use by default.',
|
|
87
87
|
footer: Row(
|
|
88
88
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
89
89
|
children: <Widget>[
|
|
@@ -100,7 +100,7 @@ class _OnboardingModelStepState extends State<OnboardingModelStep> {
|
|
|
100
100
|
'No available models found.\nYou can configure providers later in Settings.',
|
|
101
101
|
textAlign: TextAlign.center,
|
|
102
102
|
style: TextStyle(
|
|
103
|
-
color:
|
|
103
|
+
color: paletteOf(context).textMuted,
|
|
104
104
|
fontSize: 16,
|
|
105
105
|
height: 1.5,
|
|
106
106
|
),
|
|
@@ -108,11 +108,11 @@ class _OnboardingModelStepState extends State<OnboardingModelStep> {
|
|
|
108
108
|
)
|
|
109
109
|
: useGrid
|
|
110
110
|
? GridView.builder(
|
|
111
|
-
gridDelegate:
|
|
112
|
-
|
|
111
|
+
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
|
|
112
|
+
maxCrossAxisExtent: 380,
|
|
113
113
|
crossAxisSpacing: 14,
|
|
114
114
|
mainAxisSpacing: 14,
|
|
115
|
-
|
|
115
|
+
mainAxisExtent: 214,
|
|
116
116
|
),
|
|
117
117
|
itemCount: _models.length,
|
|
118
118
|
itemBuilder: (context, index) {
|
|
@@ -193,6 +193,7 @@ class _ModelChoiceCard extends StatelessWidget {
|
|
|
193
193
|
|
|
194
194
|
@override
|
|
195
195
|
Widget build(BuildContext context) {
|
|
196
|
+
final p = paletteOf(context);
|
|
196
197
|
final shellSize = compact ? 48.0 : 58.0;
|
|
197
198
|
final iconSize = compact ? 24.0 : 30.0;
|
|
198
199
|
final titleSize = compact ? 17.0 : 20.0;
|
|
@@ -231,7 +232,7 @@ class _ModelChoiceCard extends StatelessWidget {
|
|
|
231
232
|
: Icon(
|
|
232
233
|
Icons.radio_button_unchecked_rounded,
|
|
233
234
|
key: ValueKey<String>('idle-${model.id}'),
|
|
234
|
-
color:
|
|
235
|
+
color: p.textMuted.withValues(alpha: 0.5),
|
|
235
236
|
size: 28,
|
|
236
237
|
),
|
|
237
238
|
),
|
|
@@ -243,9 +244,9 @@ class _ModelChoiceCard extends StatelessWidget {
|
|
|
243
244
|
maxLines: 1,
|
|
244
245
|
overflow: TextOverflow.ellipsis,
|
|
245
246
|
style: TextStyle(
|
|
246
|
-
color:
|
|
247
|
+
color: p.textPrimary,
|
|
247
248
|
fontSize: titleSize,
|
|
248
|
-
fontWeight: FontWeight.
|
|
249
|
+
fontWeight: FontWeight.w700,
|
|
249
250
|
),
|
|
250
251
|
),
|
|
251
252
|
const SizedBox(height: 6),
|
|
@@ -255,7 +256,7 @@ class _ModelChoiceCard extends StatelessWidget {
|
|
|
255
256
|
vertical: 5,
|
|
256
257
|
),
|
|
257
258
|
decoration: BoxDecoration(
|
|
258
|
-
color:
|
|
259
|
+
color: p.bgSecondary,
|
|
259
260
|
borderRadius: BorderRadius.circular(999),
|
|
260
261
|
),
|
|
261
262
|
child: Text(
|
|
@@ -263,7 +264,7 @@ class _ModelChoiceCard extends StatelessWidget {
|
|
|
263
264
|
maxLines: 1,
|
|
264
265
|
overflow: TextOverflow.ellipsis,
|
|
265
266
|
style: TextStyle(
|
|
266
|
-
color:
|
|
267
|
+
color: p.textMuted,
|
|
267
268
|
fontSize: 11,
|
|
268
269
|
fontWeight: FontWeight.w700,
|
|
269
270
|
),
|
|
@@ -275,7 +276,7 @@ class _ModelChoiceCard extends StatelessWidget {
|
|
|
275
276
|
maxLines: 3,
|
|
276
277
|
overflow: TextOverflow.ellipsis,
|
|
277
278
|
style: TextStyle(
|
|
278
|
-
color:
|
|
279
|
+
color: p.textMuted,
|
|
279
280
|
fontSize: purposeSize,
|
|
280
281
|
height: 1.35,
|
|
281
282
|
),
|
|
@@ -306,9 +307,9 @@ class _ModelChoiceCard extends StatelessWidget {
|
|
|
306
307
|
Text(
|
|
307
308
|
model.label,
|
|
308
309
|
style: TextStyle(
|
|
309
|
-
color:
|
|
310
|
+
color: p.textPrimary,
|
|
310
311
|
fontSize: titleSize,
|
|
311
|
-
fontWeight: FontWeight.
|
|
312
|
+
fontWeight: FontWeight.w700,
|
|
312
313
|
),
|
|
313
314
|
),
|
|
314
315
|
Container(
|
|
@@ -317,13 +318,13 @@ class _ModelChoiceCard extends StatelessWidget {
|
|
|
317
318
|
vertical: 5,
|
|
318
319
|
),
|
|
319
320
|
decoration: BoxDecoration(
|
|
320
|
-
color:
|
|
321
|
+
color: p.bgSecondary,
|
|
321
322
|
borderRadius: BorderRadius.circular(999),
|
|
322
323
|
),
|
|
323
324
|
child: Text(
|
|
324
325
|
model.provider,
|
|
325
326
|
style: TextStyle(
|
|
326
|
-
color:
|
|
327
|
+
color: p.textMuted,
|
|
327
328
|
fontSize: 12,
|
|
328
329
|
fontWeight: FontWeight.w700,
|
|
329
330
|
),
|
|
@@ -335,7 +336,7 @@ class _ModelChoiceCard extends StatelessWidget {
|
|
|
335
336
|
Text(
|
|
336
337
|
model.purpose,
|
|
337
338
|
style: TextStyle(
|
|
338
|
-
color:
|
|
339
|
+
color: p.textMuted,
|
|
339
340
|
fontSize: purposeSize,
|
|
340
341
|
height: 1.45,
|
|
341
342
|
),
|
|
@@ -355,7 +356,7 @@ class _ModelChoiceCard extends StatelessWidget {
|
|
|
355
356
|
: Icon(
|
|
356
357
|
Icons.radio_button_unchecked_rounded,
|
|
357
358
|
key: ValueKey<String>('idle-${model.id}'),
|
|
358
|
-
color:
|
|
359
|
+
color: p.textMuted.withValues(alpha: 0.5),
|
|
359
360
|
size: 28,
|
|
360
361
|
),
|
|
361
362
|
),
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import 'package:flutter/material.dart';
|
|
2
2
|
import '../../main.dart';
|
|
3
|
+
import '../../src/theme/palette.dart';
|
|
3
4
|
import 'onboarding_video_step.dart';
|
|
4
5
|
import 'onboarding_welcome_step.dart';
|
|
6
|
+
import 'onboarding_companion_step.dart';
|
|
5
7
|
import 'onboarding_messaging_step.dart';
|
|
6
8
|
import 'onboarding_model_step.dart';
|
|
7
9
|
|
|
@@ -37,7 +39,7 @@ class _OnboardingShellState extends State<OnboardingShell> {
|
|
|
37
39
|
@override
|
|
38
40
|
Widget build(BuildContext context) {
|
|
39
41
|
return Scaffold(
|
|
40
|
-
backgroundColor:
|
|
42
|
+
backgroundColor: paletteOf(context).bgPrimary,
|
|
41
43
|
body: PageView(
|
|
42
44
|
controller: _pageController,
|
|
43
45
|
physics:
|
|
@@ -45,6 +47,10 @@ class _OnboardingShellState extends State<OnboardingShell> {
|
|
|
45
47
|
children: <Widget>[
|
|
46
48
|
OnboardingVideoStep(onComplete: _nextStep),
|
|
47
49
|
OnboardingWelcomeStep(onNext: _nextStep),
|
|
50
|
+
OnboardingCompanionStep(
|
|
51
|
+
onNext: _nextStep,
|
|
52
|
+
controller: widget.controller,
|
|
53
|
+
),
|
|
48
54
|
OnboardingMessagingStep(
|
|
49
55
|
onNext: _nextStep,
|
|
50
56
|
controller: widget.controller,
|
|
@@ -55,3 +61,4 @@ class _OnboardingShellState extends State<OnboardingShell> {
|
|
|
55
61
|
);
|
|
56
62
|
}
|
|
57
63
|
}
|
|
64
|
+
|
|
@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
|
|
|
5
5
|
import 'package:flutter_animate/flutter_animate.dart';
|
|
6
6
|
import 'package:video_player/video_player.dart';
|
|
7
7
|
|
|
8
|
+
import '../../src/theme/palette.dart';
|
|
8
9
|
import 'onboarding_chrome.dart';
|
|
9
10
|
|
|
10
11
|
class OnboardingVideoStep extends StatefulWidget {
|
|
@@ -75,26 +76,27 @@ class _OnboardingVideoStepState extends State<OnboardingVideoStep> {
|
|
|
75
76
|
final orientation = MediaQuery.orientationOf(context);
|
|
76
77
|
|
|
77
78
|
if (_hasError) {
|
|
79
|
+
final p = paletteOf(context);
|
|
78
80
|
return Scaffold(
|
|
79
|
-
backgroundColor:
|
|
81
|
+
backgroundColor: p.bgPrimary,
|
|
80
82
|
body: Center(
|
|
81
83
|
child: Padding(
|
|
82
84
|
padding: const EdgeInsets.all(32),
|
|
83
85
|
child: Column(
|
|
84
86
|
mainAxisSize: MainAxisSize.min,
|
|
85
87
|
children: <Widget>[
|
|
86
|
-
|
|
88
|
+
Icon(
|
|
87
89
|
Icons.play_circle_outline_rounded,
|
|
88
|
-
color:
|
|
90
|
+
color: p.accent,
|
|
89
91
|
size: 56,
|
|
90
92
|
),
|
|
91
93
|
const SizedBox(height: 18),
|
|
92
|
-
|
|
94
|
+
Text(
|
|
93
95
|
'Continue to setup',
|
|
94
96
|
style: TextStyle(
|
|
95
|
-
color:
|
|
97
|
+
color: p.textPrimary,
|
|
96
98
|
fontSize: 26,
|
|
97
|
-
fontWeight: FontWeight.
|
|
99
|
+
fontWeight: FontWeight.w700,
|
|
98
100
|
),
|
|
99
101
|
),
|
|
100
102
|
const SizedBox(height: 12),
|
|
@@ -102,7 +104,7 @@ class _OnboardingVideoStepState extends State<OnboardingVideoStep> {
|
|
|
102
104
|
'The intro is not available on this device.',
|
|
103
105
|
textAlign: TextAlign.center,
|
|
104
106
|
style: TextStyle(
|
|
105
|
-
color:
|
|
107
|
+
color: p.textMuted,
|
|
106
108
|
fontSize: 15,
|
|
107
109
|
height: 1.5,
|
|
108
110
|
),
|
|
@@ -135,7 +137,7 @@ class _OnboardingVideoStepState extends State<OnboardingVideoStep> {
|
|
|
135
137
|
}
|
|
136
138
|
|
|
137
139
|
return Scaffold(
|
|
138
|
-
backgroundColor: Colors.black,
|
|
140
|
+
backgroundColor: portrait ? paletteOf(context).bgPrimary : Colors.black,
|
|
139
141
|
body: portrait
|
|
140
142
|
? const _RotatePrompt()
|
|
141
143
|
: Stack(
|
|
@@ -183,21 +185,22 @@ class _RotatePrompt extends StatelessWidget {
|
|
|
183
185
|
|
|
184
186
|
@override
|
|
185
187
|
Widget build(BuildContext context) {
|
|
188
|
+
final p = paletteOf(context);
|
|
186
189
|
return Center(
|
|
187
190
|
child: Padding(
|
|
188
191
|
padding: const EdgeInsets.all(32),
|
|
189
192
|
child: Column(
|
|
190
193
|
mainAxisSize: MainAxisSize.min,
|
|
191
194
|
children: <Widget>[
|
|
192
|
-
|
|
195
|
+
Icon(Icons.screen_rotation, color: p.accent, size: 54),
|
|
193
196
|
const SizedBox(height: 18),
|
|
194
|
-
|
|
197
|
+
Text(
|
|
195
198
|
'Rotate to continue',
|
|
196
199
|
textAlign: TextAlign.center,
|
|
197
200
|
style: TextStyle(
|
|
198
|
-
color:
|
|
201
|
+
color: p.textPrimary,
|
|
199
202
|
fontSize: 24,
|
|
200
|
-
fontWeight: FontWeight.
|
|
203
|
+
fontWeight: FontWeight.w700,
|
|
201
204
|
),
|
|
202
205
|
),
|
|
203
206
|
const SizedBox(height: 10),
|
|
@@ -205,7 +208,7 @@ class _RotatePrompt extends StatelessWidget {
|
|
|
205
208
|
'This intro is designed for full-screen landscape playback.',
|
|
206
209
|
textAlign: TextAlign.center,
|
|
207
210
|
style: TextStyle(
|
|
208
|
-
color:
|
|
211
|
+
color: p.textMuted,
|
|
209
212
|
fontSize: 15,
|
|
210
213
|
height: 1.5,
|
|
211
214
|
),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import 'package:flutter/material.dart';
|
|
2
2
|
import 'package:flutter_animate/flutter_animate.dart';
|
|
3
3
|
|
|
4
|
+
import '../../src/theme/palette.dart';
|
|
4
5
|
import 'onboarding_chrome.dart';
|
|
5
6
|
|
|
6
7
|
class OnboardingWelcomeStep extends StatelessWidget {
|
|
@@ -11,10 +12,10 @@ class OnboardingWelcomeStep extends StatelessWidget {
|
|
|
11
12
|
@override
|
|
12
13
|
Widget build(BuildContext context) {
|
|
13
14
|
return OnboardingScaffold(
|
|
14
|
-
step:
|
|
15
|
+
step: 0,
|
|
15
16
|
totalSteps: 4,
|
|
16
17
|
eyebrow: 'WELCOME',
|
|
17
|
-
title: 'Welcome to\
|
|
18
|
+
title: 'Welcome to\nNeoAgent',
|
|
18
19
|
description: 'Your assistant layer for capture, context, and action.',
|
|
19
20
|
footer: Row(
|
|
20
21
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
@@ -29,17 +30,20 @@ class OnboardingWelcomeStep extends StatelessWidget {
|
|
|
29
30
|
.slideY(begin: 0.2),
|
|
30
31
|
],
|
|
31
32
|
),
|
|
32
|
-
child:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
child: Builder(
|
|
34
|
+
builder: (context) {
|
|
35
|
+
final p = paletteOf(context);
|
|
36
|
+
return Align(
|
|
37
|
+
alignment: Alignment.topLeft,
|
|
38
|
+
child: Text(
|
|
39
|
+
'Set up your workspace in a few steps and start using NeoAgent immediately.',
|
|
40
|
+
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
|
|
41
|
+
color: p.textSecondary,
|
|
42
|
+
height: 1.6,
|
|
43
|
+
),
|
|
44
|
+
).animate().fadeIn(duration: 600.ms, delay: 380.ms),
|
|
45
|
+
);
|
|
46
|
+
},
|
|
43
47
|
),
|
|
44
48
|
);
|
|
45
49
|
}
|
|
@@ -39,6 +39,7 @@ import 'src/messaging_access_summary.dart';
|
|
|
39
39
|
import 'src/oauth_launcher.dart';
|
|
40
40
|
import 'src/recording_bridge.dart';
|
|
41
41
|
import 'src/recording_payloads.dart';
|
|
42
|
+
import 'src/security/password_strength.dart';
|
|
42
43
|
import 'src/stream_renderer.dart';
|
|
43
44
|
import 'src/theme/palette.dart';
|
|
44
45
|
import 'src/web_app_update_monitor.dart';
|
|
@@ -65,6 +66,7 @@ part 'main_recordings.dart';
|
|
|
65
66
|
part 'main_chat.dart';
|
|
66
67
|
part 'main_account_settings.dart';
|
|
67
68
|
part 'main_settings.dart';
|
|
69
|
+
part 'main_model_picker.dart';
|
|
68
70
|
part 'main_operations.dart';
|
|
69
71
|
part 'main_admin.dart';
|
|
70
72
|
part 'main_unified.dart';
|
|
@@ -28,38 +28,14 @@ _PasswordStrengthInfo _passwordStrengthInfo({
|
|
|
28
28
|
color: _borderLight,
|
|
29
29
|
);
|
|
30
30
|
}
|
|
31
|
-
final
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
upper,
|
|
38
|
-
digits,
|
|
39
|
-
symbols,
|
|
40
|
-
].where((item) => item).length;
|
|
41
|
-
final normalized = value.toLowerCase();
|
|
42
|
-
final userHints = <String>{
|
|
43
|
-
username.trim().toLowerCase(),
|
|
44
|
-
email.trim().toLowerCase(),
|
|
45
|
-
email.trim().toLowerCase().split('@').first,
|
|
46
|
-
}.where((item) => item.length >= 3);
|
|
47
|
-
final containsUserInfo = userHints.any(normalized.contains);
|
|
48
|
-
final obviousPattern =
|
|
49
|
-
RegExp(r'(.)\1\1').hasMatch(value) ||
|
|
50
|
-
normalized.contains('password') ||
|
|
51
|
-
normalized.contains('1234') ||
|
|
52
|
-
normalized.contains('qwerty');
|
|
53
|
-
|
|
54
|
-
var score = 0;
|
|
55
|
-
if (value.length >= 8) score += 1;
|
|
56
|
-
if (value.length >= 12) score += 1;
|
|
57
|
-
if (variety >= 3) score += 1;
|
|
58
|
-
if (variety == 4 || value.length >= 16) score += 1;
|
|
59
|
-
if (containsUserInfo || obviousPattern) score -= 1;
|
|
60
|
-
score = score.clamp(0, 4);
|
|
31
|
+
final evaluation = evaluatePasswordStrength(
|
|
32
|
+
password: password,
|
|
33
|
+
username: username,
|
|
34
|
+
email: email,
|
|
35
|
+
);
|
|
36
|
+
final score = evaluation.score;
|
|
61
37
|
|
|
62
|
-
if (
|
|
38
|
+
if (!evaluation.hasMinimumLength) {
|
|
63
39
|
return _PasswordStrengthInfo(
|
|
64
40
|
score: 1,
|
|
65
41
|
label: 'Weak',
|
|
@@ -67,7 +43,7 @@ _PasswordStrengthInfo _passwordStrengthInfo({
|
|
|
67
43
|
color: _danger,
|
|
68
44
|
);
|
|
69
45
|
}
|
|
70
|
-
if (containsUserInfo) {
|
|
46
|
+
if (evaluation.containsUserInfo) {
|
|
71
47
|
return _PasswordStrengthInfo(
|
|
72
48
|
score: 2,
|
|
73
49
|
label: 'Fair',
|
|
@@ -75,7 +51,7 @@ _PasswordStrengthInfo _passwordStrengthInfo({
|
|
|
75
51
|
color: _warning,
|
|
76
52
|
);
|
|
77
53
|
}
|
|
78
|
-
if (obviousPattern) {
|
|
54
|
+
if (evaluation.obviousPattern) {
|
|
79
55
|
return _PasswordStrengthInfo(
|
|
80
56
|
score: 2,
|
|
81
57
|
label: 'Fair',
|
|
@@ -1197,7 +1173,7 @@ class _QrLoginScannerDialogState extends State<_QrLoginScannerDialog> {
|
|
|
1197
1173
|
const SizedBox(height: 28),
|
|
1198
1174
|
Text(
|
|
1199
1175
|
'Scan a NeoAgent login QR',
|
|
1200
|
-
style: GoogleFonts.
|
|
1176
|
+
style: GoogleFonts.geist(
|
|
1201
1177
|
fontSize: 28,
|
|
1202
1178
|
fontWeight: FontWeight.w700,
|
|
1203
1179
|
color: Colors.white,
|
|
@@ -429,6 +429,8 @@ class McpPanel extends StatelessWidget {
|
|
|
429
429
|
label: server.status,
|
|
430
430
|
color: server.status == 'running'
|
|
431
431
|
? _success
|
|
432
|
+
: server.hasError
|
|
433
|
+
? _danger
|
|
432
434
|
: _textSecondary,
|
|
433
435
|
),
|
|
434
436
|
],
|
|
@@ -437,7 +439,7 @@ class McpPanel extends StatelessWidget {
|
|
|
437
439
|
Text(
|
|
438
440
|
server.command,
|
|
439
441
|
style: TextStyle(
|
|
440
|
-
fontFamily: GoogleFonts.
|
|
442
|
+
fontFamily: GoogleFonts.geistMono().fontFamily,
|
|
441
443
|
color: _textSecondary,
|
|
442
444
|
),
|
|
443
445
|
),
|
|
@@ -465,6 +467,17 @@ class McpPanel extends StatelessWidget {
|
|
|
465
467
|
),
|
|
466
468
|
],
|
|
467
469
|
),
|
|
470
|
+
if (server.hasError) ...<Widget>[
|
|
471
|
+
const SizedBox(height: 12),
|
|
472
|
+
_InlineError(message: server.error!),
|
|
473
|
+
if (server.retryLabel.isNotEmpty) ...<Widget>[
|
|
474
|
+
const SizedBox(height: 8),
|
|
475
|
+
Text(
|
|
476
|
+
server.retryLabel,
|
|
477
|
+
style: TextStyle(color: _textSecondary),
|
|
478
|
+
),
|
|
479
|
+
],
|
|
480
|
+
],
|
|
468
481
|
const SizedBox(height: 14),
|
|
469
482
|
Wrap(
|
|
470
483
|
spacing: 10,
|