neoagent 3.0.1-beta.3 → 3.0.1-beta.30

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.
Files changed (126) hide show
  1. package/.env.example +19 -8
  2. package/README.md +20 -3
  3. package/docs/automation.md +17 -0
  4. package/docs/benchmarking.md +102 -0
  5. package/docs/billing.md +229 -0
  6. package/docs/configuration.md +22 -0
  7. package/docs/getting-started.md +10 -8
  8. package/docs/index.md +1 -0
  9. package/docs/operations.md +1 -1
  10. package/flutter_app/lib/main.dart +5 -1
  11. package/flutter_app/lib/main_account_settings.dart +138 -0
  12. package/flutter_app/lib/main_app_shell.dart +331 -0
  13. package/flutter_app/lib/main_billing.dart +1465 -0
  14. package/flutter_app/lib/main_chat.dart +1612 -214
  15. package/flutter_app/lib/main_controller.dart +396 -26
  16. package/flutter_app/lib/main_devices.dart +293 -207
  17. package/flutter_app/lib/main_install.dart +1147 -0
  18. package/flutter_app/lib/main_models.dart +90 -0
  19. package/flutter_app/lib/main_navigation.dart +25 -1
  20. package/flutter_app/lib/main_operations.dart +134 -9
  21. package/flutter_app/lib/main_settings.dart +510 -300
  22. package/flutter_app/lib/main_shared.dart +2 -0
  23. package/flutter_app/lib/main_timeline.dart +1257 -0
  24. package/flutter_app/lib/src/backend_client.dart +147 -19
  25. package/flutter_app/lib/src/desktop_companion_actions.dart +132 -21
  26. package/flutter_app/lib/src/desktop_companion_io.dart +65 -1
  27. package/flutter_app/lib/src/desktop_companion_stub.dart +12 -0
  28. package/flutter_app/lib/src/desktop_ocr_bridge.dart +2 -0
  29. package/flutter_app/lib/src/desktop_ocr_bridge_io.dart +125 -0
  30. package/flutter_app/lib/src/desktop_ocr_bridge_stub.dart +30 -0
  31. package/flutter_app/lib/src/desktop_passive_history.dart +332 -0
  32. package/flutter_app/lib/src/recording_bridge_io.dart +80 -72
  33. package/flutter_app/lib/src/recording_bridge_web.dart +127 -114
  34. package/flutter_app/lib/src/recording_chunk_queue.dart +149 -0
  35. package/flutter_app/lib/src/recording_chunk_queue_io.dart +182 -0
  36. package/flutter_app/lib/src/recording_payloads.dart +9 -0
  37. package/flutter_app/macos/Runner/AppDelegate.swift +25 -0
  38. package/flutter_app/windows/runner/flutter_window.cpp +75 -0
  39. package/landing/index.html +5 -5
  40. package/lib/manager.js +184 -66
  41. package/lib/schema_migrations.js +84 -0
  42. package/package.json +10 -4
  43. package/server/admin/access.js +12 -7
  44. package/server/admin/admin.css +78 -0
  45. package/server/admin/admin.js +441 -23
  46. package/server/admin/billing.js +415 -0
  47. package/server/admin/index.html +116 -13
  48. package/server/admin/users.js +15 -15
  49. package/server/db/database.js +134 -31
  50. package/server/db/sessions_db.js +8 -0
  51. package/server/http/middleware.js +4 -4
  52. package/server/http/routes.js +10 -0
  53. package/server/http/static.js +4 -2
  54. package/server/middleware/requireBilling.js +12 -0
  55. package/server/public/.last_build_id +1 -1
  56. package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
  57. package/server/public/canvaskit/wimp.js.symbols +8475 -8467
  58. package/server/public/canvaskit/wimp.wasm +0 -0
  59. package/server/public/flutter_bootstrap.js +2 -2
  60. package/server/public/main.dart.js +90992 -86181
  61. package/server/routes/account.js +53 -0
  62. package/server/routes/admin.js +472 -63
  63. package/server/routes/agents.js +203 -21
  64. package/server/routes/billing.js +127 -0
  65. package/server/routes/billing_webhook.js +43 -0
  66. package/server/routes/browser.js +8 -1
  67. package/server/routes/memory.js +1 -4
  68. package/server/routes/recordings.js +96 -6
  69. package/server/routes/screenHistory.js +140 -2
  70. package/server/routes/settings.js +1 -2
  71. package/server/routes/skills.js +1 -1
  72. package/server/routes/timeline.js +43 -0
  73. package/server/routes/triggers.js +2 -2
  74. package/server/services/account/erasure.js +263 -0
  75. package/server/services/account/sessions.js +1 -9
  76. package/server/services/ai/loop/agent_engine_core.js +50 -1
  77. package/server/services/ai/loop/blank_recovery.js +36 -0
  78. package/server/services/ai/loop/completion_judge.js +42 -0
  79. package/server/services/ai/loop/conversation_loop.js +289 -38
  80. package/server/services/ai/loop/progress_monitor.js +6 -6
  81. package/server/services/ai/loopPolicy.js +37 -44
  82. package/server/services/ai/messagingFallback.js +25 -1
  83. package/server/services/ai/models.js +18 -0
  84. package/server/services/ai/preModelCompaction.js +25 -5
  85. package/server/services/ai/rate_limits.js +52 -5
  86. package/server/services/ai/systemPrompt.js +23 -5
  87. package/server/services/ai/taskAnalysis.js +2 -0
  88. package/server/services/ai/toolEvidence.js +15 -0
  89. package/server/services/ai/toolResult.js +40 -0
  90. package/server/services/ai/tools.js +237 -22
  91. package/server/services/android/controller.js +6 -2
  92. package/server/services/billing/billing_email.js +106 -0
  93. package/server/services/billing/config.js +17 -0
  94. package/server/services/billing/plans.js +121 -0
  95. package/server/services/billing/stripe_client.js +21 -0
  96. package/server/services/billing/subscriptions.js +462 -0
  97. package/server/services/billing/trial_guard.js +111 -0
  98. package/server/services/browser/anti_detection.js +192 -0
  99. package/server/services/browser/contentExtractor.js +629 -0
  100. package/server/services/browser/controller.js +181 -59
  101. package/server/services/desktop/auth.js +3 -0
  102. package/server/services/desktop/gateway.js +7 -4
  103. package/server/services/desktop/registry.js +50 -2
  104. package/server/services/integrations/google/calendar.js +30 -2
  105. package/server/services/integrations/secrets.js +7 -4
  106. package/server/services/manager.js +23 -42
  107. package/server/services/messaging/automation.js +1 -1
  108. package/server/services/messaging/telnyx.js +12 -11
  109. package/server/services/messaging/whatsapp.js +1 -1
  110. package/server/services/recordings/manager.js +73 -34
  111. package/server/services/runtime/backends/local-vm.js +40 -22
  112. package/server/services/runtime/docker-vm-manager.js +157 -266
  113. package/server/services/runtime/guest_bootstrap.js +17 -5
  114. package/server/services/runtime/guest_image.js +188 -0
  115. package/server/services/runtime/manager.js +0 -1
  116. package/server/services/runtime/validation.js +3 -8
  117. package/server/services/social_video/service.js +60 -10
  118. package/server/services/tasks/runtime.js +221 -19
  119. package/server/services/tasks/schedule_utils.js +5 -5
  120. package/server/services/timeline/service.js +558 -0
  121. package/server/services/voice/runtimeManager.js +19 -10
  122. package/server/services/wearable/gateway.js +8 -5
  123. package/server/services/websocket.js +26 -8
  124. package/server/services/workspace/manager.js +37 -3
  125. package/server/services/desktop/screenRecorder.js +0 -292
  126. package/server/services/desktop/screen_recorder_support.js +0 -46
package/.env.example CHANGED
@@ -253,17 +253,28 @@ OLLAMA_URL=http://localhost:11434
253
253
  # Connected integration memory refresh cadence in milliseconds.
254
254
  NEOAGENT_MEMORY_INGESTION_INTERVAL_MS=600000
255
255
 
256
- # Local screen OCR capture. This captures the backend host's macOS desktop,
257
- # so enable it only when that host is the configured user's desktop.
258
- NEOAGENT_SCREEN_RECORDER_ENABLED=false
259
- # Existing NeoAgent user ID that owns all captured screen history. Required when enabled.
260
- NEOAGENT_SCREEN_RECORDER_USER_ID=
261
- NEOAGENT_SCREEN_RECORDER_INTERVAL_MS=10000
262
- NEOAGENT_SCREEN_RECORDER_RETENTION_DAYS=7
263
-
264
256
  ########################################
265
257
  # Messaging and voice integrations
266
258
  ########################################
267
259
 
268
260
  MESHTASTIC_ENABLED=true
269
261
  TELNYX_WEBHOOK_TOKEN=
262
+
263
+ ########################################
264
+ # Stripe billing (optional)
265
+ ########################################
266
+
267
+ # Set to true or 1 to enable the billing system. When disabled (default),
268
+ # no billing routes are exposed and no payment UI is shown anywhere.
269
+ # NEOAGENT_BILLING_ENABLED=false
270
+
271
+ # Stripe API keys — required when billing is enabled.
272
+ # Use test keys (sk_test_...) during development; live keys in production.
273
+ # STRIPE_SECRET_KEY=sk_test_...
274
+ # STRIPE_PUBLISHABLE_KEY=pk_test_...
275
+
276
+ # Webhook signing secret from your Stripe dashboard (Developers > Webhooks).
277
+ # STRIPE_WEBHOOK_SECRET=whsec_...
278
+
279
+ # Length of free trial periods in days (default: 14).
280
+ # BILLING_TRIAL_DAYS=14
package/README.md CHANGED
@@ -18,6 +18,12 @@
18
18
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-AGPL--3.0-a855f7?style=flat-square" alt="AGPL-3.0 license"></a>
19
19
  </p>
20
20
 
21
+ <p align="center">
22
+ <a href="https://github.com/NeoLabs-Systems/NeoAgent/releases/latest"><img alt="Android" src="https://img.shields.io/badge/Android-APK-3ddc84?style=flat-square&logo=android&logoColor=white"></a>
23
+ <a href="https://github.com/NeoLabs-Systems/NeoAgent/releases/latest"><img alt="iOS" src="https://img.shields.io/badge/iOS-coming_soon-lightgrey?style=flat-square&logo=apple&logoColor=white"></a>
24
+ <a href="https://github.com/NeoLabs-Systems/NeoAgent/releases/latest"><img alt="Windows" src="https://img.shields.io/badge/Windows-EXE-0078d4?style=flat-square&logo=windows&logoColor=white"></a>
25
+ </p>
26
+
21
27
  <p align="center">
22
28
  <a href="https://www.producthunt.com/products/neoagent-2?embed=true&utm_source=badge-featured&utm_medium=badge&utm_campaign=badge-neoagent-2" target="_blank" rel="noopener noreferrer"><img alt="NeoAgent - The next-gen self-hosted AI agent that works beyond chat | Product Hunt" width="250" height="54" src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=1171573&theme=light&t=1781447653039"></a>
23
29
  </p>
@@ -28,15 +34,20 @@
28
34
 
29
35
  ## 🚀 Install
30
36
 
31
- NeoAgent supports macOS and Linux hosts. You need Node.js 20 or newer; the
32
- installer handles the rest of the application setup and attempts to install
33
- QEMU for the isolated browser and terminal runtime.
37
+ NeoAgent supports macOS and Linux hosts. You need Node.js 20 or newer and
38
+ Docker for the isolated browser and terminal runtime; the installer handles the
39
+ rest of the application setup and pre-builds the guest runtime image when Docker
40
+ is available.
34
41
 
35
42
  ```bash
36
43
  npm install -g neoagent
37
44
  neoagent install
38
45
  ```
39
46
 
47
+ <p align="center">
48
+ <a href="https://github.com/NeoLabs-Systems/NeoAgent/releases/latest"><img alt="Download macOS app" src="https://img.shields.io/badge/macOS_app-download-black?style=flat-square&logo=apple&logoColor=white"></a>
49
+ </p>
50
+
40
51
  Open `http://localhost:3333`, create the first account, and configure a model.
41
52
  Local models can run through [Ollama](https://ollama.com/); hosted providers
42
53
  can be configured in the application.
@@ -51,6 +62,7 @@ service to a network.
51
62
  - **It operates real devices.** The agent can use an isolated browser and shell, control an Android device or emulator over ADB, or work through a paired Chrome extension and desktop companion.
52
63
  - **Automation can start without a message.** Tasks can run on a schedule or from supported Gmail, Outlook, Slack, Teams, personal WhatsApp, and weather events. Android notifications can also start an agent run.
53
64
  - **Agents and users have separate state.** Specialist agents can have their own memory, settings, tools, account assignments, conversations, and task history. Multi-user deployments include administrative account controls and optional email confirmation.
65
+ - **SaaS billing is built in and off by default.** Set `NEOAGENT_BILLING_ENABLED=true` to activate Stripe subscriptions, plan management, free trials, and model access restrictions. When disabled, no payment routes or UI appear anywhere. See [Billing](docs/billing.md).
54
66
  - **The same server has several interfaces.** NeoAgent includes web, Android, desktop, and Android launcher clients, messaging bridges, a Chrome extension, and firmware for a supported ESP32-S3 wearable.
55
67
 
56
68
  ## 🖥️ Interfaces
@@ -79,6 +91,11 @@ changes and rough edges. Review the
79
91
  [security boundaries](docs/security-boundaries.md) before connecting sensitive
80
92
  accounts or giving the agent access to a personal workstation.
81
93
 
94
+ ## 📊 Benchmarks
95
+
96
+ ![NeoAgent benchmark dashboard](static/benchmarks/latest-dashboard.png)
97
+ See [Benchmarking](docs/benchmarking.md) for the reproducibility details and suite coverage.
98
+
82
99
  Start with the [documentation](https://neolabs-systems.github.io/NeoAgent/docs/).
83
100
  Use [GitHub Discussions](https://github.com/NeoLabs-Systems/NeoAgent/discussions)
84
101
  for questions and [GitHub Issues](https://github.com/NeoLabs-Systems/NeoAgent/issues)
@@ -62,6 +62,23 @@ when no reply is needed.
62
62
  Prefer official integrations or MCP tools over browser automation when both
63
63
  can perform the action. Structured tools are easier to restrict and diagnose.
64
64
 
65
+ ## Bot-protected pages
66
+
67
+ The isolated VM browser uses native anti-detection hardening inspired by
68
+ Botasaurus' public anti-detect browser patterns: stable browser profiles,
69
+ common desktop viewport sizes, less mechanical pointer movement, referrer-aware
70
+ navigation, and challenge detection telemetry. NeoAgent does not embed or
71
+ depend on Botasaurus for this path.
72
+
73
+ `browser_navigate` accepts optional `referrerMode` values of `direct`,
74
+ `google`, or `current`. By default it also retries once with a Google referrer
75
+ when a known bot challenge is detected. Browser results can include
76
+ `botDetection` so runs can report that a page is blocked instead of treating the
77
+ challenge page as ordinary content.
78
+
79
+ Browser automation still must comply with the target site's terms and applicable
80
+ law. URL safety checks and the VM device-access restrictions remain in effect.
81
+
65
82
  ## Runs and delivery
66
83
 
67
84
  Open **Runs** to inspect the trigger, tool calls, approvals, output, and error
@@ -0,0 +1,102 @@
1
+ # Benchmarking
2
+
3
+ NeoAgent includes an end-to-end benchmark harness that drives the app through
4
+ its authenticated HTTP surface instead of calling internal engine methods
5
+ directly. The harness configures OpenRouter models, submits benchmark tasks,
6
+ collects run events and usage data, and writes normalized result artifacts.
7
+
8
+ ## Latest dashboard
9
+
10
+ ![Latest benchmark dashboard](/benchmarks/latest-dashboard.png)
11
+
12
+ The generated image is backed by these local outputs:
13
+
14
+ - `benchmark/results/latest-results.json`
15
+ - `benchmark/results/latest-summary.json`
16
+ - `benchmark/results/latest-summary.md`
17
+ - `static/benchmarks/latest-dashboard.png`
18
+
19
+ ## Commands
20
+
21
+ ```bash
22
+ npm run benchmark:setup
23
+ npm run benchmark:run
24
+ npm run benchmark:report
25
+ ```
26
+
27
+ ## Model selection
28
+
29
+ The benchmark harness is OpenRouter-first. Edit the `OPENROUTER_MODEL_IDS`
30
+ variable in `benchmark/config.js` to pin exact model IDs, or leave it empty to
31
+ use the current cheap-tier OpenRouter models discovered at runtime.
32
+
33
+ ## Benchmark coverage
34
+
35
+ - `GAIA`, `BrowseComp`, `WebArena`, `VisualWebArena`, and `SWE-bench` are wired
36
+ as exact public-suite adapters. When their official datasets or external
37
+ runners are not installed, they are reported as blocked instead of being
38
+ approximated.
39
+ - `NeoAgent Representative Tasks` runs first-party agent tasks through
40
+ `/api/agents` and scores them from the persisted run details.
41
+ - `NeoAgent Memory Retrieval` seeds memories over `/api/memory`, recalls them
42
+ through the app routes, and scores retrieval quality with the same metric
43
+ code used by the server evaluation module.
44
+
45
+ ## Reproducibility
46
+
47
+ - Public-suite setup manifests are written under `benchmark/workdir/<suite>/`.
48
+ - The harness uses one benchmark account and persists per-run usage summaries
49
+ through the existing NeoAgent run detail endpoints.
50
+ - Blocked suites are intentional and explicit. The harness never substitutes a
51
+ simplified local task and labels it as a public benchmark result.
52
+
53
+ ## Public benchmark prerequisites
54
+
55
+ ### GAIA
56
+
57
+ - Access to the gated [GAIA dataset](https://huggingface.co/datasets/gaia-benchmark/GAIA).
58
+ - `HF_TOKEN` in the environment.
59
+ - A Python environment with `datasets` installed if you want `benchmark:setup`
60
+ to export a normalized local cache automatically.
61
+ - Either an exact evaluator wired through
62
+ `NEOAGENT_BENCHMARK_GAIA_RUNNER` or a repository-local exact runner added to
63
+ the harness. The current adapter intentionally reports `blocked` until an
64
+ official evaluator path is configured.
65
+
66
+ ### BrowseComp
67
+
68
+ - A checkout of [openai/simple-evals](https://github.com/openai/simple-evals),
69
+ which `benchmark:setup` can clone into `benchmark/workdir/browsecomp/`.
70
+ - Exact BrowseComp case extraction from that repo.
71
+ - An official evaluator command exposed through
72
+ `NEOAGENT_BENCHMARK_BROWSECOMP_RUNNER`.
73
+
74
+ ### WebArena
75
+
76
+ - Docker installed and running.
77
+ - The official [WebArena](https://webarena.dev/) environment and task sites.
78
+ - Browser automation dependencies required by the official runner.
79
+ - An exact runner command exposed through
80
+ `NEOAGENT_BENCHMARK_WEBARENA_RUNNER`.
81
+
82
+ ### VisualWebArena
83
+
84
+ - Docker installed and running.
85
+ - The official VisualWebArena environment.
86
+ - A vision-capable configured benchmark model.
87
+ - An exact runner command exposed through
88
+ `NEOAGENT_BENCHMARK_VISUAL_WEBARENA_RUNNER`.
89
+
90
+ ### SWE-bench
91
+
92
+ - Docker installed and running.
93
+ - A checkout of [SWE-bench](https://github.com/SWE-bench/SWE-bench), which
94
+ `benchmark:setup` can clone into `benchmark/workdir/swebench/`.
95
+ - The official dataset/runtime and enough disk/network budget for repo/image
96
+ setup.
97
+ - An exact runner command exposed through
98
+ `NEOAGENT_BENCHMARK_SWEBENCH_RUNNER`.
99
+
100
+ On this machine, `docker` is currently missing, so exact `WebArena`,
101
+ `VisualWebArena`, and `SWE-bench` execution remain blocked until Docker and the
102
+ official runners are installed.
@@ -0,0 +1,229 @@
1
+ # Billing
2
+
3
+ NeoAgent includes an optional Stripe-based billing system for deployments that
4
+ charge users for access. When disabled — the default — no billing routes are
5
+ exposed, no payment UI is shown, and no payment-related information appears
6
+ anywhere in the application.
7
+
8
+ ## Enable billing
9
+
10
+ Run the interactive setup wizard:
11
+
12
+ ```bash
13
+ neoagent billing setup
14
+ ```
15
+
16
+ The wizard prompts for your Stripe API keys, webhook secret, and trial length,
17
+ then asks whether to enable billing immediately. Use Stripe test keys
18
+ (`sk_test_...`, `pk_test_...`) during development.
19
+
20
+ To check the current configuration at any time:
21
+
22
+ ```bash
23
+ neoagent billing # or: neoagent billing status
24
+ ```
25
+
26
+ To toggle billing without re-running setup:
27
+
28
+ ```bash
29
+ neoagent billing enable # set NEOAGENT_BILLING_ENABLED=true and restart
30
+ neoagent billing disable # set NEOAGENT_BILLING_ENABLED=false and restart
31
+ ```
32
+
33
+ When enabled the admin dashboard will show a **Billing** navigation item and
34
+ the `/api/billing/*` endpoints become active.
35
+
36
+ > **Manual alternative** — you can also set variables directly and restart:
37
+ > ```bash
38
+ > neoagent env set STRIPE_SECRET_KEY sk_live_...
39
+ > neoagent env set STRIPE_PUBLISHABLE_KEY pk_live_...
40
+ > neoagent env set STRIPE_WEBHOOK_SECRET whsec_...
41
+ > neoagent env set NEOAGENT_BILLING_ENABLED true
42
+ > neoagent restart
43
+ > ```
44
+
45
+ ## Subscription plans
46
+
47
+ Plans are managed in **Admin › Billing › Plans**. Each plan controls:
48
+
49
+ | Field | Purpose |
50
+ |---|---|
51
+ | Name | Displayed to users in the settings submenu |
52
+ | Price | Stripe price in cents (0 = free) |
53
+ | Billing interval | `month`, `year`, or blank for one-time or free |
54
+ | Stripe Price ID | The `price_...` ID from your Stripe dashboard |
55
+ | 4h token limit | Per-user 4-hour rolling token budget (blank = server default) |
56
+ | Weekly token limit | Per-user 7-day rolling token budget (blank = server default) |
57
+ | Allowed models | Comma-separated model IDs; blank = all models accessible |
58
+ | Features | Marketing feature strings shown on pricing pages |
59
+
60
+ Token limits are written directly to the user account when a subscription
61
+ becomes active or is updated via webhook. The existing rate-limit enforcement
62
+ in the runtime reads them with no additional configuration.
63
+
64
+ Token limits gate interactive run starts. Background task executions are not
65
+ blocked by the internal token admission check, so scheduled and integration
66
+ tasks can still run while a user is over quota. Their token usage is still
67
+ recorded and included in account and admin usage snapshots.
68
+
69
+ ### Free plan
70
+
71
+ Create a plan with **Price = 0** to serve as the default for new users. If a
72
+ free plan exists when billing is enabled, every new registration is
73
+ automatically placed on it.
74
+
75
+ ### Model restrictions
76
+
77
+ If **Allowed models** is non-empty, users on that plan can only use the listed
78
+ model IDs. Models outside the allowlist remain visible in the UI with an
79
+ unavailable status so users understand what upgrading unlocks.
80
+
81
+ Leave the field blank to allow all configured models on a plan.
82
+
83
+ ## User subscriptions
84
+
85
+ Users manage their subscription in **Settings › Billing** (Flutter client). From
86
+ there they can:
87
+
88
+ - View their current plan, status, and next renewal date
89
+ - Upgrade or downgrade through Stripe Checkout
90
+ - Open the Stripe Customer Portal to update a payment method or download invoices
91
+ - Cancel at the end of the current billing period
92
+
93
+ ### Stripe Checkout
94
+
95
+ When a user selects a paid plan, the server creates a Stripe Checkout session
96
+ and redirects the client to Stripe's hosted payment page. No card data passes
97
+ through NeoAgent.
98
+
99
+ ### Stripe Customer Portal
100
+
101
+ The Customer Portal is a Stripe-hosted page where users can update their
102
+ payment method, view billing history, and cancel. Configure the portal in your
103
+ [Stripe dashboard](https://dashboard.stripe.com/settings/billing/portal) before
104
+ enabling it.
105
+
106
+ ## Free trials
107
+
108
+ Enable free trials in **Admin › Billing › Plans** by configuring a Stripe price
109
+ that supports trials, then setting `BILLING_TRIAL_DAYS` to the desired length
110
+ (default: 14 days).
111
+
112
+ Trials start when a user calls `POST /api/billing/trial` with a plan ID. The
113
+ server runs anti-abuse checks before granting a trial:
114
+
115
+ | Check | Limit |
116
+ |---|---|
117
+ | IP address | 2 trials per IP per 30 days |
118
+ | Email domain | 3 trials per non-common domain per 30 days |
119
+ | Account age | Account must be at least 1 day old |
120
+ | Device fingerprint | 1 trial per device per 90 days (opaque hash from client) |
121
+
122
+ The Flutter client is responsible for generating and sending the device
123
+ fingerprint. The server hashes it with SHA-256 before storage — the raw
124
+ fingerprint is never persisted.
125
+
126
+ ## Webhooks
127
+
128
+ Stripe sends events to `POST /api/billing/webhook`. Register this URL in your
129
+ [Stripe dashboard](https://dashboard.stripe.com/webhooks) under the endpoint
130
+ for your account.
131
+
132
+ Handled events:
133
+
134
+ | Event | Effect |
135
+ |---|---|
136
+ | `customer.subscription.created` | Creates a local subscription row |
137
+ | `customer.subscription.updated` | Syncs status, period dates, and token limits |
138
+ | `customer.subscription.deleted` | Marks subscription canceled |
139
+ | `customer.subscription.trial_will_end` | Sends trial-ending email (fires 3 days before) |
140
+ | `invoice.payment_succeeded` | Records payment; sends renewal email on cycle |
141
+ | `invoice.payment_failed` | Records failure; sends payment-failed email |
142
+
143
+ Events are idempotent — replaying a webhook event produces the same result.
144
+
145
+ **Required events to enable in Stripe:**
146
+
147
+ ```
148
+ customer.subscription.created
149
+ customer.subscription.updated
150
+ customer.subscription.deleted
151
+ customer.subscription.trial_will_end
152
+ invoice.payment_succeeded
153
+ invoice.payment_failed
154
+ ```
155
+
156
+ ### Verifying the webhook locally
157
+
158
+ Use the Stripe CLI to forward events to a local server during development:
159
+
160
+ ```bash
161
+ stripe listen --forward-to http://localhost:3333/api/billing/webhook
162
+ ```
163
+
164
+ ## Email notifications
165
+
166
+ If [service email](configuration.md#service-email) is configured, users receive
167
+ emails at the following billing events:
168
+
169
+ | Event | Email |
170
+ |---|---|
171
+ | Trial started | Confirmation with trial end date |
172
+ | Trial ending soon | Reminder 3 days before end |
173
+ | Subscription activated | Welcome to the paid plan |
174
+ | Subscription renewed | Renewal confirmation |
175
+ | Payment failed | Action required with next retry date |
176
+ | Subscription canceled | Cancellation confirmation |
177
+ | Plan changed | Summary of the new plan |
178
+
179
+ No emails are sent if SMTP is not configured.
180
+
181
+ ## AI context awareness
182
+
183
+ When billing is enabled, each AI request includes the user's subscription in
184
+ the system prompt:
185
+
186
+ ```
187
+ SUBSCRIPTION: User is on the "Pro" plan, status: active.
188
+ ```
189
+
190
+ Agents and workflows can use this context to adapt their behavior — for
191
+ example, acknowledging feature limitations on a free plan or confirming
192
+ capabilities on a paid one.
193
+
194
+ ## Admin controls
195
+
196
+ The **Admin › Billing** page provides:
197
+
198
+ - **Plans**: Create, edit, and deactivate subscription plans
199
+ - **Subscriptions**: Browse all user subscriptions with status filter and
200
+ pagination; override a user's plan without going through Stripe
201
+
202
+ Override a user's plan directly from the subscriptions table using the
203
+ **Override** button. This is useful for comped accounts, support escalations,
204
+ or fixing a webhook gap.
205
+
206
+ ## Configuration reference
207
+
208
+ | Variable | Default | Purpose |
209
+ |---|---|---|
210
+ | `NEOAGENT_BILLING_ENABLED` | `false` | Master on/off switch |
211
+ | `STRIPE_SECRET_KEY` | required | Stripe server-side API key |
212
+ | `STRIPE_PUBLISHABLE_KEY` | required | Stripe client-side key (returned to Flutter) |
213
+ | `STRIPE_WEBHOOK_SECRET` | required | Webhook signing secret from Stripe dashboard |
214
+ | `BILLING_TRIAL_DAYS` | `14` | Free trial length in days |
215
+
216
+ All variables can be set with `neoagent env set` or added to `~/.neoagent/.env`
217
+ directly. Restart the server after any change.
218
+
219
+ ## Security notes
220
+
221
+ - NeoAgent stores only Stripe customer IDs and subscription IDs — no card
222
+ numbers, bank details, or PII beyond what Stripe already holds.
223
+ - Webhook payloads are verified with HMAC-SHA256 using `STRIPE_WEBHOOK_SECRET`
224
+ before any processing. Requests missing the `stripe-signature` header are
225
+ rejected with 400.
226
+ - Trial fingerprints are stored as SHA-256 hashes — the raw IP, email domain,
227
+ and device identifiers are never persisted.
228
+ - All billing routes return 404 when `NEOAGENT_BILLING_ENABLED` is not set,
229
+ regardless of whether Stripe credentials are present.
@@ -97,6 +97,28 @@ reset, email changes, and security notifications.
97
97
  | `NEOAGENT_EMAIL_PUBLIC_URL` | Base URL used in email links |
98
98
  | `NEOAGENT_EMAIL_TOKEN_TTL_HOURS` | Confirmation token lifetime |
99
99
 
100
+ ## Billing
101
+
102
+ Billing is disabled by default. Use the interactive wizard to configure it:
103
+
104
+ ```bash
105
+ neoagent billing setup # guided Stripe key and webhook setup
106
+ neoagent billing # show current status
107
+ neoagent billing enable # activate billing and restart
108
+ neoagent billing disable # deactivate billing and restart
109
+ ```
110
+
111
+ See [Billing](billing.md) for the full setup guide, webhook configuration, and
112
+ plan management.
113
+
114
+ | Variable | Default | Purpose |
115
+ |---|---|---|
116
+ | `NEOAGENT_BILLING_ENABLED` | `false` | Enable the Stripe billing system |
117
+ | `STRIPE_SECRET_KEY` | unset | Stripe server-side API key |
118
+ | `STRIPE_PUBLISHABLE_KEY` | unset | Stripe client-side key (returned to clients) |
119
+ | `STRIPE_WEBHOOK_SECRET` | unset | Webhook signing secret |
120
+ | `BILLING_TRIAL_DAYS` | `14` | Free trial length in days |
121
+
100
122
  ## Isolated runtime
101
123
 
102
124
  | Variable | Purpose |
@@ -9,18 +9,20 @@ remote access to work.
9
9
  - Node.js 20 or newer with npm
10
10
  - A macOS or Linux user account that can install packages
11
11
  - Enough disk and memory for the models and runtime you choose
12
- - QEMU for the isolated browser and terminal runtime
12
+ - Docker for the isolated browser and terminal runtime
13
13
 
14
- The installer attempts to install QEMU with Homebrew, `apt`, `dnf`, or `yum`.
15
- If the host uses another package manager, install QEMU first.
14
+ The isolated browser and CLI run each user's guest agent in a Docker container.
15
+ Install Docker first; the NeoAgent installer detects it and pre-builds the guest
16
+ runtime image (browser and dependencies baked in) so the first browser or CLI
17
+ action is instant. If Docker is missing, the rest of NeoAgent still installs and
18
+ the cloud browser/CLI become available once Docker is running.
16
19
 
17
20
  ```bash
18
- # macOS
19
- brew install qemu
21
+ # macOS — Docker Desktop
22
+ # https://www.docker.com/products/docker-desktop/
20
23
 
21
- # Ubuntu or Debian
22
- sudo apt-get update
23
- sudo apt-get install -y qemu-system qemu-utils
24
+ # Ubuntu or Debian — Docker Engine
25
+ # https://docs.docker.com/engine/install/
24
26
  ```
25
27
 
26
28
  ## Install NeoAgent
package/docs/index.md CHANGED
@@ -45,6 +45,7 @@ Continue with:
45
45
  | [Recordings and health](recordings-and-health.md) | Audio transcription and Health Connect |
46
46
  | [Skills and MCP](skills.md) | Reusable instructions and external tool servers |
47
47
  | [Operations](operations.md) | Updates, backups, logs, and recovery |
48
+ | [Billing](billing.md) | Stripe subscriptions, plans, trials, and webhooks |
48
49
  | [Configuration](configuration.md) | Environment and runtime reference |
49
50
  | [Why NeoAgent](why-neoagent.md) | Factual comparison with OpenClaw and Hermes |
50
51
 
@@ -66,7 +66,7 @@ Protect backups as credentials and personal data.
66
66
  |---|---|
67
67
  | Service does not start | `neoagent status`, then `neoagent logs` |
68
68
  | Chat has no response | Provider connection, selected model, provider quota |
69
- | Browser or shell unavailable | QEMU installation and first runtime boot |
69
+ | Browser or shell unavailable | Docker installed and running, then first runtime boot |
70
70
  | OAuth fails | Reachable HTTPS `PUBLIC_URL` and exact callback URI |
71
71
  | Messaging receives nothing | Channel credentials, webhook, and allowlists |
72
72
  | Task does not run | Enabled state, trigger account, next run, **Runs** |
@@ -1,6 +1,6 @@
1
1
  import 'dart:async';
2
2
  import 'dart:convert';
3
- import 'dart:io' show Platform;
3
+ import 'dart:io' show Directory, File, Platform, Process, ProcessSignal;
4
4
  import 'dart:math' as math;
5
5
  import 'dart:ui' show ImageFilter;
6
6
 
@@ -20,6 +20,7 @@ import 'package:image/image.dart' as img;
20
20
  import 'package:mobile_scanner/mobile_scanner.dart';
21
21
  import 'package:qr_flutter/qr_flutter.dart';
22
22
  import 'package:shared_preferences/shared_preferences.dart';
23
+ import 'package:url_launcher/url_launcher.dart' as url_launcher;
23
24
  import 'package:socket_io_client/socket_io_client.dart' as io;
24
25
  import 'package:audioplayers/audioplayers.dart';
25
26
  import 'package:tray_manager/tray_manager.dart';
@@ -60,6 +61,7 @@ part 'main_models.dart';
60
61
  part 'main_shared.dart';
61
62
  part 'main_voice_assistant.dart';
62
63
  part 'main_navigation.dart';
64
+ part 'main_timeline.dart';
63
65
  part 'main_runtime.dart';
64
66
  part 'main_controller.dart';
65
67
  part 'main_devices.dart';
@@ -71,7 +73,9 @@ part 'main_security.dart';
71
73
  part 'main_model_picker.dart';
72
74
  part 'main_operations.dart';
73
75
  part 'main_admin.dart';
76
+ part 'main_billing.dart';
74
77
  part 'main_unified.dart';
78
+ part 'main_install.dart';
75
79
 
76
80
  Future<void> main() async {
77
81
  await runNeoAgentApp(mode: _appModeFromEnvironment());