neoagent 2.4.1-beta.8 → 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 +45 -7
- 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 -2
- package/extensions/chrome-browser/popup.html +5 -1
- package/extensions/chrome-browser/popup.js +15 -2
- 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 +3 -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 +338 -46
- package/flutter_app/lib/main_devices.dart +851 -122
- 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 +764 -887
- 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 +79 -0
- package/flutter_app/lib/src/desktop_companion_actions.dart +56 -7
- package/flutter_app/lib/src/desktop_companion_io.dart +77 -1
- package/flutter_app/lib/src/desktop_native_bridge.dart +13 -0
- package/flutter_app/lib/src/security/password_strength.dart +84 -0
- package/flutter_app/lib/src/stream_renderer.dart +205 -35
- 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/AppDelegate.swift +44 -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 +88944 -85720
- 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/browser.js +14 -0
- package/server/routes/browser_extension.js +21 -4
- package/server/routes/desktop.js +10 -0
- 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 +14 -2
- package/server/routes/stream.js +12 -3
- 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 +80 -15
- package/server/services/android/controller.js +36 -1
- package/server/services/browser/controller.js +18 -0
- package/server/services/browser/extension/manifest.js +33 -0
- package/server/services/browser/extension/provider.js +12 -6
- package/server/services/browser/extension/registry.js +229 -18
- package/server/services/desktop/protocol.js +1 -0
- package/server/services/desktop/provider.js +4 -0
- 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 -47
- 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/runtime/manager.js +7 -3
- package/server/services/runtime/settings.js +17 -0
- package/server/services/streaming/android-stream.js +296 -32
- package/server/services/streaming/stream-hub.js +1 -1
- 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
package/.env.example
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
# Core runtime
|
|
3
3
|
########################################
|
|
4
4
|
|
|
5
|
+
# Admin dashboard credentials — set during `neoagent setup`.
|
|
6
|
+
# Access the dashboard at http://localhost:<PORT>/admin
|
|
7
|
+
# Run `neoagent admin` to display these credentials at any time.
|
|
8
|
+
ADMIN_USERNAME=admin
|
|
9
|
+
ADMIN_PASSWORD=
|
|
10
|
+
|
|
11
|
+
# Admin API key for programmatic access to /admin/api/* endpoints.
|
|
12
|
+
# Use: Authorization: Bearer <key>
|
|
13
|
+
# Generate or rotate via the admin dashboard → Access → Generate key.
|
|
14
|
+
# Leave blank to disable API key auth (dashboard session auth still works).
|
|
15
|
+
ADMIN_API_KEY=
|
|
16
|
+
|
|
5
17
|
PORT=3333
|
|
6
18
|
NODE_ENV=production
|
|
7
19
|
# Auto-generated on first start or setup if left blank.
|
|
@@ -111,6 +123,17 @@ GOOGLE_AI_KEY=your-google-ai-key-here
|
|
|
111
123
|
# • MiniMax-M2.7 via the Anthropic-compatible MiniMax endpoint
|
|
112
124
|
MINIMAX_API_KEY=your-minimax-api-key-here
|
|
113
125
|
|
|
126
|
+
# NVIDIA NIM API key — used for:
|
|
127
|
+
# • Free-tier and paid models on NVIDIA's hosted inference (Nemotron, Kimi, Llama 4, DeepSeek, etc.)
|
|
128
|
+
# Get your key at: https://build.nvidia.com
|
|
129
|
+
NVIDIA_API_KEY=your-nvidia-nim-api-key-here
|
|
130
|
+
|
|
131
|
+
# OpenRouter API key — used for:
|
|
132
|
+
# • 300+ models from all major providers through a single API
|
|
133
|
+
# • Includes free-tier models (no credit needed for :free variants)
|
|
134
|
+
# Get your key at: https://openrouter.ai/keys
|
|
135
|
+
OPENROUTER_API_KEY=your-openrouter-api-key-here
|
|
136
|
+
|
|
114
137
|
# GitHub Copilot OAuth token — used for:
|
|
115
138
|
# • Copilot-backed chat/coding models (gpt-5.3, gpt-4.1)
|
|
116
139
|
# Set via: neoagent login github-copilot
|
|
@@ -219,9 +242,16 @@ DEEPGRAM_LANGUAGE=multi
|
|
|
219
242
|
|
|
220
243
|
OLLAMA_URL=http://localhost:11434
|
|
221
244
|
|
|
222
|
-
#
|
|
223
|
-
|
|
224
|
-
|
|
245
|
+
# Connected integration memory refresh cadence in milliseconds.
|
|
246
|
+
NEOAGENT_MEMORY_INGESTION_INTERVAL_MS=600000
|
|
247
|
+
|
|
248
|
+
# Local screen OCR capture. This captures the backend host's macOS desktop,
|
|
249
|
+
# so enable it only when that host is the configured user's desktop.
|
|
250
|
+
NEOAGENT_SCREEN_RECORDER_ENABLED=false
|
|
251
|
+
# Existing NeoAgent user ID that owns all captured screen history. Required when enabled.
|
|
252
|
+
NEOAGENT_SCREEN_RECORDER_USER_ID=
|
|
253
|
+
NEOAGENT_SCREEN_RECORDER_INTERVAL_MS=10000
|
|
254
|
+
NEOAGENT_SCREEN_RECORDER_RETENTION_DAYS=7
|
|
225
255
|
|
|
226
256
|
########################################
|
|
227
257
|
# Messaging and voice integrations
|
package/LICENSE
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
GNU
|
|
2
|
-
Version 3,
|
|
1
|
+
GNU GENERAL PUBLIC LICENSE
|
|
2
|
+
Version 3, 29 June 2007
|
|
3
3
|
|
|
4
4
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
|
5
5
|
Everyone is permitted to copy and distribute verbatim copies
|
|
@@ -7,15 +7,17 @@
|
|
|
7
7
|
|
|
8
8
|
Preamble
|
|
9
9
|
|
|
10
|
-
The GNU
|
|
11
|
-
software and other kinds of works
|
|
12
|
-
cooperation with the community in the case of network server software.
|
|
10
|
+
The GNU General Public License is a free, copyleft license for
|
|
11
|
+
software and other kinds of works.
|
|
13
12
|
|
|
14
13
|
The licenses for most software and other practical works are designed
|
|
15
14
|
to take away your freedom to share and change the works. By contrast,
|
|
16
|
-
|
|
15
|
+
the GNU General Public License is intended to guarantee your freedom to
|
|
17
16
|
share and change all versions of a program--to make sure it remains free
|
|
18
|
-
software for all its users.
|
|
17
|
+
software for all its users. We, the Free Software Foundation, use the
|
|
18
|
+
GNU General Public License for most of our software; it applies also to
|
|
19
|
+
any other work released this way by its authors. You can apply it to
|
|
20
|
+
your programs, too.
|
|
19
21
|
|
|
20
22
|
When we speak of free software, we are referring to freedom, not
|
|
21
23
|
price. Our General Public Licenses are designed to make sure that you
|
|
@@ -24,34 +26,44 @@ them if you wish), that you receive source code or can get it if you
|
|
|
24
26
|
want it, that you can change the software or use pieces of it in new
|
|
25
27
|
free programs, and that you know you can do these things.
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
this
|
|
29
|
+
To protect your rights, we need to prevent others from denying you
|
|
30
|
+
these rights or asking you to surrender the rights. Therefore, you have
|
|
31
|
+
certain responsibilities if you distribute copies of the software, or if
|
|
32
|
+
you modify it: responsibilities to respect the freedom of others.
|
|
33
|
+
|
|
34
|
+
For example, if you distribute copies of such a program, whether
|
|
35
|
+
gratis or for a fee, you must pass on to the recipients the same
|
|
36
|
+
freedoms that you received. You must make sure that they, too, receive
|
|
37
|
+
or can get the source code. And you must show them these terms so they
|
|
38
|
+
know their rights.
|
|
39
|
+
|
|
40
|
+
Developers that use the GNU GPL protect your rights with two steps:
|
|
41
|
+
(1) assert copyright on the software, and (2) offer you this License
|
|
42
|
+
giving you legal permission to copy, distribute and/or modify it.
|
|
43
|
+
|
|
44
|
+
For the developers' and authors' protection, the GPL clearly explains
|
|
45
|
+
that there is no warranty for this free software. For both users' and
|
|
46
|
+
authors' sake, the GPL requires that modified versions be marked as
|
|
47
|
+
changed, so that their problems will not be attributed erroneously to
|
|
48
|
+
authors of previous versions.
|
|
49
|
+
|
|
50
|
+
Some devices are designed to deny users access to install or run
|
|
51
|
+
modified versions of the software inside them, although the manufacturer
|
|
52
|
+
can do so. This is fundamentally incompatible with the aim of
|
|
53
|
+
protecting users' freedom to change the software. The systematic
|
|
54
|
+
pattern of such abuse occurs in the area of products for individuals to
|
|
55
|
+
use, which is precisely where it is most unacceptable. Therefore, we
|
|
56
|
+
have designed this version of the GPL to prohibit the practice for those
|
|
57
|
+
products. If such problems arise substantially in other domains, we
|
|
58
|
+
stand ready to extend this provision to those domains in future versions
|
|
59
|
+
of the GPL, as needed to protect the freedom of users.
|
|
60
|
+
|
|
61
|
+
Finally, every program is threatened constantly by software patents.
|
|
62
|
+
States should not allow patents to restrict development and use of
|
|
63
|
+
software on general-purpose computers, but in those that do, we wish to
|
|
64
|
+
avoid the special danger that patents applied to a free program could
|
|
65
|
+
make it effectively proprietary. To prevent this, the GPL assures that
|
|
66
|
+
patents cannot be used to render the program non-free.
|
|
55
67
|
|
|
56
68
|
The precise terms and conditions for copying, distribution and
|
|
57
69
|
modification follow.
|
|
@@ -60,7 +72,7 @@ modification follow.
|
|
|
60
72
|
|
|
61
73
|
0. Definitions.
|
|
62
74
|
|
|
63
|
-
"This License" refers to version 3 of the GNU
|
|
75
|
+
"This License" refers to version 3 of the GNU General Public License.
|
|
64
76
|
|
|
65
77
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
|
66
78
|
works, such as semiconductor masks.
|
|
@@ -537,45 +549,35 @@ to collect a royalty for further conveying from those to whom you convey
|
|
|
537
549
|
the Program, the only way you could satisfy both those terms and this
|
|
538
550
|
License would be to refrain entirely from conveying the Program.
|
|
539
551
|
|
|
540
|
-
13.
|
|
541
|
-
|
|
542
|
-
Notwithstanding any other provision of this License, if you modify the
|
|
543
|
-
Program, your modified version must prominently offer all users
|
|
544
|
-
interacting with it remotely through a computer network (if your version
|
|
545
|
-
supports such interaction) an opportunity to receive the Corresponding
|
|
546
|
-
Source of your version by providing access to the Corresponding Source
|
|
547
|
-
from a network server at no charge, through some standard or customary
|
|
548
|
-
means of facilitating copying of software. This Corresponding Source
|
|
549
|
-
shall include the Corresponding Source for any work covered by version 3
|
|
550
|
-
of the GNU General Public License that is incorporated pursuant to the
|
|
551
|
-
following paragraph.
|
|
552
|
+
13. Use with the GNU Affero General Public License.
|
|
552
553
|
|
|
553
554
|
Notwithstanding any other provision of this License, you have
|
|
554
555
|
permission to link or combine any covered work with a work licensed
|
|
555
|
-
under version 3 of the GNU General Public License into a single
|
|
556
|
+
under version 3 of the GNU Affero General Public License into a single
|
|
556
557
|
combined work, and to convey the resulting work. The terms of this
|
|
557
558
|
License will continue to apply to the part which is the covered work,
|
|
558
|
-
but the
|
|
559
|
-
|
|
559
|
+
but the special requirements of the GNU Affero General Public License,
|
|
560
|
+
section 13, concerning interaction through a network will apply to the
|
|
561
|
+
combination as such.
|
|
560
562
|
|
|
561
563
|
14. Revised Versions of this License.
|
|
562
564
|
|
|
563
565
|
The Free Software Foundation may publish revised and/or new versions of
|
|
564
|
-
the GNU
|
|
565
|
-
|
|
566
|
+
the GNU General Public License from time to time. Such new versions will
|
|
567
|
+
be similar in spirit to the present version, but may differ in detail to
|
|
566
568
|
address new problems or concerns.
|
|
567
569
|
|
|
568
570
|
Each version is given a distinguishing version number. If the
|
|
569
|
-
Program specifies that a certain numbered version of the GNU
|
|
571
|
+
Program specifies that a certain numbered version of the GNU General
|
|
570
572
|
Public License "or any later version" applies to it, you have the
|
|
571
573
|
option of following the terms and conditions either of that numbered
|
|
572
574
|
version or of any later version published by the Free Software
|
|
573
575
|
Foundation. If the Program does not specify a version number of the
|
|
574
|
-
GNU
|
|
576
|
+
GNU General Public License, you may choose any version ever published
|
|
575
577
|
by the Free Software Foundation.
|
|
576
578
|
|
|
577
579
|
If the Program specifies that a proxy can decide which future
|
|
578
|
-
versions of the GNU
|
|
580
|
+
versions of the GNU General Public License can be used, that proxy's
|
|
579
581
|
public statement of acceptance of a version permanently authorizes you
|
|
580
582
|
to choose that version for the Program.
|
|
581
583
|
|
|
@@ -617,3 +619,56 @@ Program, unless a warranty or assumption of liability accompanies a
|
|
|
617
619
|
copy of the Program in return for a fee.
|
|
618
620
|
|
|
619
621
|
END OF TERMS AND CONDITIONS
|
|
622
|
+
|
|
623
|
+
How to Apply These Terms to Your New Programs
|
|
624
|
+
|
|
625
|
+
If you develop a new program, and you want it to be of the greatest
|
|
626
|
+
possible use to the public, the best way to achieve this is to make it
|
|
627
|
+
free software which everyone can redistribute and change under these terms.
|
|
628
|
+
|
|
629
|
+
To do so, attach the following notices to the program. It is safest
|
|
630
|
+
to attach them to the start of each source file to most effectively
|
|
631
|
+
state the exclusion of warranty; and each file should have at least
|
|
632
|
+
the "copyright" line and a pointer to where the full notice is found.
|
|
633
|
+
|
|
634
|
+
<one line to give the program's name and a brief idea of what it does.>
|
|
635
|
+
Copyright (C) <year> <name of author>
|
|
636
|
+
|
|
637
|
+
This program is free software: you can redistribute it and/or modify
|
|
638
|
+
it under the terms of the GNU General Public License as published by
|
|
639
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
640
|
+
(at your option) any later version.
|
|
641
|
+
|
|
642
|
+
This program is distributed in the hope that it will be useful,
|
|
643
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
644
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
645
|
+
GNU General Public License for more details.
|
|
646
|
+
|
|
647
|
+
You should have received a copy of the GNU General Public License
|
|
648
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
649
|
+
|
|
650
|
+
Also add information on how to contact you by electronic and paper mail.
|
|
651
|
+
|
|
652
|
+
If the program does terminal interaction, make it output a short
|
|
653
|
+
notice like this when it starts in an interactive mode:
|
|
654
|
+
|
|
655
|
+
<program> Copyright (C) <year> <name of author>
|
|
656
|
+
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
|
657
|
+
This is free software, and you are welcome to redistribute it
|
|
658
|
+
under certain conditions; type `show c' for details.
|
|
659
|
+
|
|
660
|
+
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
661
|
+
parts of the General Public License. Of course, your program's commands
|
|
662
|
+
might be different; for a GUI interface, you would use an "about box".
|
|
663
|
+
|
|
664
|
+
You should also get your employer (if you work as a programmer) or school,
|
|
665
|
+
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
|
666
|
+
For more information on this, and how to apply and follow the GNU GPL, see
|
|
667
|
+
<https://www.gnu.org/licenses/>.
|
|
668
|
+
|
|
669
|
+
The GNU General Public License does not permit incorporating your program
|
|
670
|
+
into proprietary programs. If your program is a subroutine library, you
|
|
671
|
+
may consider it more useful to permit linking proprietary applications with
|
|
672
|
+
the library. If this is what you want to do, use the GNU Lesser General
|
|
673
|
+
Public License instead of this License. But first, please read
|
|
674
|
+
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
package/README.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="flutter_app/assets/branding/app_icon_128.png" width="80" alt="NeoAgent">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
1
5
|
<h1 align="center">NeoAgent</h1>
|
|
2
6
|
|
|
3
7
|
<p align="center"><strong>Your agent. Your server. Your rules.</strong></p>
|
|
@@ -27,14 +31,15 @@
|
|
|
27
31
|
|
|
28
32
|
## Install
|
|
29
33
|
|
|
30
|
-
Requires Node.js 20+ and QEMU — see [getting started](docs/getting-started.md) for details.
|
|
31
|
-
|
|
32
34
|
```bash
|
|
33
35
|
npm install -g neoagent
|
|
34
36
|
neoagent install
|
|
35
37
|
```
|
|
36
38
|
|
|
37
|
-
|
|
39
|
+
`neoagent install` runs a preflight, writes a secure default config when setup
|
|
40
|
+
cannot prompt, installs Node dependencies, builds or uses the bundled web
|
|
41
|
+
client, bootstraps supported system tools where possible, and starts the
|
|
42
|
+
service. Available at **http://localhost:3333** when complete.
|
|
38
43
|
|
|
39
44
|
## Manage
|
|
40
45
|
|
package/docs/configuration.md
CHANGED
|
@@ -4,6 +4,12 @@ NeoAgent reads server config from `~/.neoagent/.env`. Run `neoagent setup` to ge
|
|
|
4
4
|
|
|
5
5
|
All AI provider credentials, OAuth client secrets, and deployment settings are server-side only — never sent to the client or exposed in the UI.
|
|
6
6
|
|
|
7
|
+
## Admin Dashboard
|
|
8
|
+
|
|
9
|
+
The admin dashboard at `/admin` provides a web UI for operator tasks including AI provider key management, server logs, and runtime updates. Credentials are generated during `neoagent setup` (or run `neoagent admin` to view them).
|
|
10
|
+
|
|
11
|
+
Navigate to **Providers** in the sidebar to set or rotate API keys without editing `.env` manually — changes take effect immediately without a server restart.
|
|
12
|
+
|
|
7
13
|
## Minimal Config
|
|
8
14
|
|
|
9
15
|
```dotenv
|
|
@@ -40,6 +46,8 @@ At least one key is required unless you only use local Ollama.
|
|
|
40
46
|
| `XAI_BASE_URL` | Optional xAI-compatible base URL override |
|
|
41
47
|
| `GOOGLE_AI_KEY` | Gemini (Google) |
|
|
42
48
|
| `MINIMAX_API_KEY` | MiniMax (including `MiniMax-M2.7`) |
|
|
49
|
+
| `NVIDIA_API_KEY` | NVIDIA NIM (free-tier + paid: Nemotron, Kimi, Llama 4, DeepSeek, etc.) |
|
|
50
|
+
| `OPENROUTER_API_KEY` | OpenRouter — access 300+ models from all providers through one API; free-tier models included |
|
|
43
51
|
| `BRAVE_SEARCH_API_KEY` | Brave Search for the `web_search` tool |
|
|
44
52
|
| `OPENAI_BASE_URL` | Optional OpenAI-compatible base URL override |
|
|
45
53
|
| `ANTHROPIC_BASE_URL` | Optional Anthropic-compatible base URL override |
|
package/docs/getting-started.md
CHANGED
|
@@ -7,12 +7,16 @@ Install takes about 5 minutes. The first VM boot downloads and configures an Ubu
|
|
|
7
7
|
| | |
|
|
8
8
|
|---|---|
|
|
9
9
|
| Node.js | 20 or newer |
|
|
10
|
-
| QEMU | for VM-isolated browser and Android |
|
|
10
|
+
| QEMU | installed automatically when supported; used for VM-isolated browser and Android |
|
|
11
11
|
| AI provider key | Anthropic, OpenAI, Gemini, Grok, MiniMax, or local Ollama |
|
|
12
12
|
|
|
13
13
|
No API key is required if you only use local Ollama.
|
|
14
14
|
|
|
15
|
-
###
|
|
15
|
+
### Optional manual QEMU install
|
|
16
|
+
|
|
17
|
+
`neoagent install` tries to install QEMU on supported macOS and Linux package
|
|
18
|
+
managers. If the machine does not have a supported package manager yet, install
|
|
19
|
+
QEMU manually and rerun `neoagent install`.
|
|
16
20
|
|
|
17
21
|
```bash
|
|
18
22
|
# macOS
|
|
@@ -29,7 +33,9 @@ npm install -g neoagent
|
|
|
29
33
|
neoagent install
|
|
30
34
|
```
|
|
31
35
|
|
|
32
|
-
This runs
|
|
36
|
+
This runs a preflight, creates or updates config, installs dependencies, builds
|
|
37
|
+
or uses the bundled web client, starts the service, and prints any remaining
|
|
38
|
+
machine-specific action items.
|
|
33
39
|
|
|
34
40
|
Open **http://localhost:3333** in your browser when the install finishes.
|
|
35
41
|
|
package/docs/index.md
CHANGED
|
@@ -4,6 +4,10 @@ title: NeoAgent
|
|
|
4
4
|
sidebar_label: Overview
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
<p align="center">
|
|
8
|
+
<img src="/img/app_icon.png" width="72" alt="NeoAgent" />
|
|
9
|
+
</p>
|
|
10
|
+
|
|
7
11
|
# NeoAgent
|
|
8
12
|
|
|
9
13
|
Self-hosted AI agent server. Runs as a system service, keeps all credentials on your machine, and provides a full operator UI for chat, automation, Android device control, recordings, integrations, and memory.
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { createBrowserProtocol } from './protocol.mjs';
|
|
2
2
|
import { DEFAULT_SERVER_URL } from './config.mjs';
|
|
3
3
|
|
|
4
|
-
const STORAGE_KEYS = ['serverUrl', 'configuredServerUrl', 'token', 'pairingId', 'pairingSecret', 'approvalUrl', 'status'];
|
|
4
|
+
const STORAGE_KEYS = ['serverUrl', 'configuredServerUrl', 'token', 'pairingId', 'pairingSecret', 'approvalUrl', 'status', 'extensionName'];
|
|
5
5
|
const protocol = createBrowserProtocol(chrome);
|
|
6
6
|
let socket = null;
|
|
7
7
|
let reconnectTimer = null;
|
|
8
8
|
let suppressSocketClose = false;
|
|
9
9
|
const DEFAULT_FETCH_TIMEOUT_MS = 10000;
|
|
10
10
|
const DEFAULT_WS_CONNECT_TIMEOUT_MS = 10000;
|
|
11
|
+
const KEEPALIVE_ALARM_NAME = 'neoagent-extension-keepalive';
|
|
12
|
+
const KEEPALIVE_ALARM_MINUTES = 1;
|
|
11
13
|
const EXTENSION_PROTOCOL_VERSION = 1;
|
|
12
14
|
|
|
13
15
|
function getStorage(keys = STORAGE_KEYS) {
|
|
@@ -81,6 +83,12 @@ function clearReconnectTimer() {
|
|
|
81
83
|
reconnectTimer = null;
|
|
82
84
|
}
|
|
83
85
|
|
|
86
|
+
function ensureKeepaliveAlarm() {
|
|
87
|
+
chrome.alarms?.create?.(KEEPALIVE_ALARM_NAME, {
|
|
88
|
+
periodInMinutes: KEEPALIVE_ALARM_MINUTES,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
84
92
|
async function handleSocketDisconnected(ws) {
|
|
85
93
|
if (socket !== ws) {
|
|
86
94
|
return;
|
|
@@ -188,10 +196,12 @@ async function handleSocketMessage(raw) {
|
|
|
188
196
|
async function startPairing(serverUrl) {
|
|
189
197
|
const normalized = await resolveServerUrl(serverUrl);
|
|
190
198
|
if (!normalized) throw new Error('NeoAgent server URL required.');
|
|
199
|
+
const { extensionName } = await getStorage(['extensionName']);
|
|
200
|
+
const nameToUse = String(extensionName || 'Chrome Extension').trim() || 'Chrome Extension';
|
|
191
201
|
const response = await fetchWithTimeout(`${normalized}/api/browser-extension/pairing/request`, {
|
|
192
202
|
method: 'POST',
|
|
193
203
|
headers: { 'content-type': 'application/json' },
|
|
194
|
-
body: JSON.stringify({ extensionName:
|
|
204
|
+
body: JSON.stringify({ extensionName: nameToUse }),
|
|
195
205
|
});
|
|
196
206
|
const payload = await response.json().catch(() => ({}));
|
|
197
207
|
if (!response.ok) throw new Error(payload.error || `Pairing failed: ${response.status}`);
|
|
@@ -212,14 +222,15 @@ async function startPairing(serverUrl) {
|
|
|
212
222
|
}
|
|
213
223
|
|
|
214
224
|
async function claimPairing() {
|
|
215
|
-
const { serverUrl, pairingId, pairingSecret } = await getStorage(['serverUrl', 'pairingId', 'pairingSecret']);
|
|
225
|
+
const { serverUrl, pairingId, pairingSecret, extensionName } = await getStorage(['serverUrl', 'pairingId', 'pairingSecret', 'extensionName']);
|
|
216
226
|
if (!serverUrl || !pairingId || !pairingSecret) {
|
|
217
227
|
throw new Error('No pending pairing request.');
|
|
218
228
|
}
|
|
229
|
+
const nameToUse = String(extensionName || 'Chrome Extension').trim() || 'Chrome Extension';
|
|
219
230
|
const response = await fetchWithTimeout(`${serverUrl}/api/browser-extension/pairing/${encodeURIComponent(pairingId)}/claim`, {
|
|
220
231
|
method: 'POST',
|
|
221
232
|
headers: { 'content-type': 'application/json' },
|
|
222
|
-
body: JSON.stringify({ pairingSecret, extensionName:
|
|
233
|
+
body: JSON.stringify({ pairingSecret, extensionName: nameToUse }),
|
|
223
234
|
});
|
|
224
235
|
const payload = await response.json().catch(() => ({}));
|
|
225
236
|
if (!response.ok) throw new Error(payload.error || `Claim failed: ${response.status}`);
|
|
@@ -250,12 +261,18 @@ async function checkForUpdates(preferredServerUrl) {
|
|
|
250
261
|
const response = await fetchWithTimeout(`${serverUrl}/api/browser-extension/latest`);
|
|
251
262
|
const latest = await response.json().catch(() => ({}));
|
|
252
263
|
if (!response.ok) throw new Error(latest.error || `Update check failed: ${response.status}`);
|
|
253
|
-
const
|
|
264
|
+
const manifest = chrome.runtime.getManifest();
|
|
265
|
+
const currentVersion = manifest.version;
|
|
266
|
+
const currentVersionName = manifest.version_name || currentVersion;
|
|
267
|
+
const latestVersion = latest.version || currentVersion;
|
|
268
|
+
const latestVersionName = latest.versionName || latestVersion;
|
|
254
269
|
return {
|
|
255
270
|
currentVersion,
|
|
256
|
-
|
|
271
|
+
currentVersionName,
|
|
272
|
+
latestVersion,
|
|
273
|
+
latestVersionName,
|
|
257
274
|
downloadUrl: latest.downloadUrl || `${serverUrl}/api/browser-extension/download`,
|
|
258
|
-
updateAvailable: compareVersions(
|
|
275
|
+
updateAvailable: compareVersions(latestVersion, currentVersion) > 0,
|
|
259
276
|
};
|
|
260
277
|
}
|
|
261
278
|
|
|
@@ -279,6 +296,9 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
|
|
|
279
296
|
return disconnect();
|
|
280
297
|
case 'checkForUpdates':
|
|
281
298
|
return checkForUpdates(message.serverUrl);
|
|
299
|
+
case 'saveExtensionName':
|
|
300
|
+
await setStorage({ extensionName: message.extensionName });
|
|
301
|
+
return { success: true };
|
|
282
302
|
case 'openDownload':
|
|
283
303
|
return openDownload(message.serverUrl);
|
|
284
304
|
case 'getState':
|
|
@@ -296,4 +316,22 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
|
|
|
296
316
|
return true;
|
|
297
317
|
});
|
|
298
318
|
|
|
319
|
+
chrome.alarms?.onAlarm?.addListener((alarm) => {
|
|
320
|
+
if (alarm?.name !== KEEPALIVE_ALARM_NAME) return;
|
|
321
|
+
connect().catch((error) => {
|
|
322
|
+
console.error('NeoAgent keepalive reconnect failed', error);
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
chrome.runtime.onStartup?.addListener(() => {
|
|
327
|
+
ensureKeepaliveAlarm();
|
|
328
|
+
connect().catch(() => {});
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
chrome.runtime.onInstalled?.addListener(() => {
|
|
332
|
+
ensureKeepaliveAlarm();
|
|
333
|
+
connect().catch(() => {});
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
ensureKeepaliveAlarm();
|
|
299
337
|
connect().catch(() => {});
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,12 +1,43 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 100 100">
|
|
2
2
|
<defs>
|
|
3
|
-
<linearGradient id="
|
|
4
|
-
<stop offset="0%" stop-color="#
|
|
5
|
-
<stop offset="100%" stop-color="#
|
|
3
|
+
<linearGradient id="tile" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
+
<stop offset="0%" stop-color="#705331"></stop>
|
|
5
|
+
<stop offset="100%" stop-color="#22564c"></stop>
|
|
6
6
|
</linearGradient>
|
|
7
|
+
<radialGradient id="shine" cx="26%" cy="14%" r="72%">
|
|
8
|
+
<stop offset="0%" stop-color="#ffffff" stop-opacity="0.22"></stop>
|
|
9
|
+
<stop offset="100%" stop-color="#ffffff" stop-opacity="0"></stop>
|
|
10
|
+
</radialGradient>
|
|
11
|
+
<radialGradient id="core" cx="38%" cy="32%" r="75%">
|
|
12
|
+
<stop offset="0%" stop-color="#fffdf6"></stop>
|
|
13
|
+
<stop offset="48%" stop-color="#eee3cc"></stop>
|
|
14
|
+
<stop offset="100%" stop-color="#b5a888"></stop>
|
|
15
|
+
</radialGradient>
|
|
16
|
+
<radialGradient id="node" cx="36%" cy="30%" r="80%">
|
|
17
|
+
<stop offset="0%" stop-color="#f8dca8"></stop>
|
|
18
|
+
<stop offset="52%" stop-color="#d3a85f"></stop>
|
|
19
|
+
<stop offset="100%" stop-color="#9b6f2f"></stop>
|
|
20
|
+
</radialGradient>
|
|
21
|
+
<linearGradient id="tube" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
22
|
+
<stop offset="0%" stop-color="#fffaf0"></stop>
|
|
23
|
+
<stop offset="52%" stop-color="#efe7d6"></stop>
|
|
24
|
+
<stop offset="100%" stop-color="#cabf9f"></stop>
|
|
25
|
+
</linearGradient>
|
|
26
|
+
<filter id="sh" x="-30%" y="-30%" width="160%" height="160%">
|
|
27
|
+
<feDropShadow dx="0" dy="1.1" stdDeviation="1.1" flood-color="#000000" flood-opacity="0.45"></feDropShadow>
|
|
28
|
+
</filter>
|
|
29
|
+
<clipPath id="tc"><rect x="0" y="0" width="100" height="100" rx="22.5"></rect></clipPath>
|
|
7
30
|
</defs>
|
|
8
|
-
<
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
31
|
+
<g clip-path="url(#tc)">
|
|
32
|
+
<rect x="0" y="0" width="100" height="100" fill="url(#tile)"></rect>
|
|
33
|
+
<rect x="0" y="0" width="100" height="100" fill="url(#shine)"></rect>
|
|
34
|
+
<g fill="none" stroke="url(#tube)" stroke-linecap="round" filter="url(#sh)">
|
|
35
|
+
<circle cx="50" cy="50" r="17" stroke-width="5" stroke-dasharray="78 29" transform="rotate(-35 50 50)" stroke-opacity="0.92"></circle>
|
|
36
|
+
<circle cx="50" cy="50" r="30" stroke-width="5" stroke-dasharray="150 39" transform="rotate(70 50 50)" stroke-opacity="0.8"></circle>
|
|
37
|
+
</g>
|
|
38
|
+
<circle cx="50" cy="50" r="7" fill="url(#core)"></circle>
|
|
39
|
+
<circle cx="50" cy="20" r="5.6" fill="url(#node)"></circle>
|
|
40
|
+
<circle cx="48" cy="18.4" r="1.7" fill="#fff7e6" fill-opacity="0.8"></circle>
|
|
41
|
+
</g>
|
|
42
|
+
<rect x="0.6" y="0.6" width="98.8" height="98.8" rx="22" fill="none" stroke="#ffffff" stroke-opacity="0.16" stroke-width="1.2"></rect>
|
|
12
43
|
</svg>
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest_version": 3,
|
|
3
3
|
"name": "NeoAgent Browser",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "2.4.1.8",
|
|
5
|
+
"version_name": "2.4.1-beta.8",
|
|
5
6
|
"description": "Connect this Chrome browser to NeoAgent for browser automation.",
|
|
6
7
|
"minimum_chrome_version": "118",
|
|
7
|
-
"permissions": ["debugger", "storage", "tabs"],
|
|
8
|
+
"permissions": ["alarms", "debugger", "storage", "tabs"],
|
|
8
9
|
"host_permissions": ["http://*/*", "https://*/*"],
|
|
9
10
|
"icons": {
|
|
10
11
|
"16": "icons/icon16.png",
|
|
@@ -38,7 +38,11 @@
|
|
|
38
38
|
Server URL
|
|
39
39
|
<input id="serverUrl" type="url" placeholder="https://neoagent.example.com">
|
|
40
40
|
</label>
|
|
41
|
-
<
|
|
41
|
+
<label style="margin-top: 8px;">
|
|
42
|
+
Extension Name
|
|
43
|
+
<input id="extensionName" type="text" placeholder="e.g. Work Laptop, Personal Mac" value="Chrome Extension">
|
|
44
|
+
</label>
|
|
45
|
+
<div class="settings-actions" style="margin-top: 12px;">
|
|
42
46
|
<button id="checkUpdate" type="button" class="secondary">Check for update</button>
|
|
43
47
|
<button id="download" type="button" class="secondary">Download latest ZIP</button>
|
|
44
48
|
<button id="disconnect" type="button" class="secondary danger">Disconnect</button>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const statusEl = document.querySelector('#status');
|
|
2
2
|
const statusDotEl = document.querySelector('#statusDot');
|
|
3
3
|
const serverUrlEl = document.querySelector('#serverUrl');
|
|
4
|
+
const extensionNameEl = document.querySelector('#extensionName');
|
|
4
5
|
const serverLabelEl = document.querySelector('#serverLabel');
|
|
5
6
|
const messageEl = document.querySelector('#message');
|
|
6
7
|
const settingsEl = document.querySelector('#settings');
|
|
@@ -214,6 +215,10 @@ async function refresh() {
|
|
|
214
215
|
if (serverUrl && document.activeElement !== serverUrlEl) {
|
|
215
216
|
serverUrlEl.value = serverUrl;
|
|
216
217
|
}
|
|
218
|
+
const extensionName = currentState.extensionName || 'Chrome Extension';
|
|
219
|
+
if (document.activeElement !== extensionNameEl) {
|
|
220
|
+
extensionNameEl.value = extensionName;
|
|
221
|
+
}
|
|
217
222
|
if (!serverUrl) {
|
|
218
223
|
settingsEl.open = true;
|
|
219
224
|
}
|
|
@@ -237,6 +242,14 @@ function bindAsyncClick(element, handler) {
|
|
|
237
242
|
}
|
|
238
243
|
|
|
239
244
|
serverUrlEl.addEventListener('input', updateFlow);
|
|
245
|
+
extensionNameEl.addEventListener('input', async () => {
|
|
246
|
+
const name = String(extensionNameEl.value || '').trim();
|
|
247
|
+
try {
|
|
248
|
+
await send('saveExtensionName', { extensionName: name });
|
|
249
|
+
} catch (err) {
|
|
250
|
+
console.error('Failed to save extension name', err);
|
|
251
|
+
}
|
|
252
|
+
});
|
|
240
253
|
|
|
241
254
|
bindAsyncClick(primaryActionEl, () => runAction(primaryActionEl.dataset.action));
|
|
242
255
|
bindAsyncClick(secondaryActionEl, () => runAction(secondaryActionEl.dataset.action));
|
|
@@ -249,8 +262,8 @@ bindAsyncClick(checkUpdateEl, async () => {
|
|
|
249
262
|
const result = await send('checkForUpdates', { serverUrl: effectiveServerUrl() });
|
|
250
263
|
setMessage(
|
|
251
264
|
result.updateAvailable
|
|
252
|
-
? `Update available: ${result.currentVersion} -> ${result.latestVersion}.`
|
|
253
|
-
: `Current version ${result.currentVersion} is up to date.`,
|
|
265
|
+
? `Update available: ${result.currentVersionName || result.currentVersion} -> ${result.latestVersionName || result.latestVersion}.`
|
|
266
|
+
: `Current version ${result.currentVersionName || result.currentVersion} is up to date.`,
|
|
254
267
|
result.updateAvailable ? '' : 'success',
|
|
255
268
|
);
|
|
256
269
|
});
|
|
@@ -124,7 +124,8 @@
|
|
|
124
124
|
|
|
125
125
|
<service
|
|
126
126
|
android:name=".auto.NeoAgentCarAppService"
|
|
127
|
-
android:exported="true"
|
|
127
|
+
android:exported="true"
|
|
128
|
+
android:permission="android.car.permission.BIND_CAR_APP_SERVICE">
|
|
128
129
|
<intent-filter>
|
|
129
130
|
<action android:name="androidx.car.app.CarAppService" />
|
|
130
131
|
<category android:name="androidx.car.app.category.IOT" />
|
|
Binary file
|
|
Binary file
|