neoagent 2.1.18-beta.35 → 2.1.18-beta.37

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/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  <p align="center"><strong>Your agent. Your server. Your rules.</strong></p>
4
4
 
5
5
  <p align="center">
6
- <a href="https://nodejs.org"><img src="https://img.shields.io/badge/Node.js-18+-5fa04e?style=flat-square&logo=node.js&logoColor=white" alt="Node.js"></a>
6
+ <a href="https://nodejs.org"><img src="https://img.shields.io/badge/Node.js-20+-5fa04e?style=flat-square&logo=node.js&logoColor=white" alt="Node.js"></a>
7
7
  <a href="https://sqlite.org"><img src="https://img.shields.io/badge/SQLite-WAL-003b57?style=flat-square&logo=sqlite&logoColor=white" alt="SQLite"></a>
8
8
  <a href="https://flutter.dev"><img src="https://img.shields.io/badge/Flutter-web%20%2B%20android-02569B?style=flat-square&logo=flutter&logoColor=white" alt="Flutter"></a>
9
9
  <a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-a855f7?style=flat-square" alt="License"></a>
@@ -4,7 +4,7 @@ NeoAgent installs as a Node CLI and runs a self-hosted server with a bundled Flu
4
4
 
5
5
  ## Requirements
6
6
 
7
- - Node.js 18 or newer.
7
+ - Node.js 20 or newer.
8
8
  - A reachable server URL if you want OAuth callbacks, mobile access, or messaging webhooks.
9
9
  - At least one hosted AI provider API key, unless you only use local Ollama.
10
10
  - Android Studio or a Flutter Android toolchain if you build the Android client yourself.
package/docs/index.md CHANGED
@@ -1,47 +1,14 @@
1
1
  ---
2
- layout: home
2
+ slug: /
3
+ title: NeoAgent
4
+ sidebar_label: Overview
5
+ ---
3
6
 
4
- hero:
5
- name: NeoAgent
6
- text: Self-hosted proactive AI agent
7
- tagline: Run your own server, keep credentials server-side, and operate browser, Android, recordings, schedules, integrations, memory, MCP, and messaging from one Flutter UI.
8
- actions:
9
- - theme: brand
10
- text: Get Started
11
- link: /getting-started
12
- - theme: alt
13
- text: Capabilities
14
- link: /capabilities
15
- - theme: alt
16
- text: Why NeoAgent
17
- link: /why-neoagent
7
+ # NeoAgent
18
8
 
19
- features:
20
- - title: Android Control
21
- details: Let the AI operate a server-attached Android emulator or device with screenshots, UI dumps, app launch, intents, taps, typing, swipes, APK installs, and ADB shell.
22
- link: /capabilities#android-control
23
- linkText: Android Control
24
- - title: Recordings
25
- details: Capture web, Android, and wearable audio as sessions with transcripts, searchable segments, playback, retry, cleanup, and AI-generated insights.
26
- link: /capabilities#recordings
27
- linkText: Recordings
28
- - title: Proactive Automation
29
- details: Create recurring tasks and one-time runs that can use browser, files, CLI, memory, MCP, integrations, subagents, health summaries, and messaging delivery.
30
- link: /automation
31
- linkText: Automation
32
- - title: Official Integrations
33
- details: Use OAuth-backed Google Workspace, Microsoft 365, Notion, Slack, and Figma tools instead of brittle browser automation where possible.
34
- link: /integrations
35
- linkText: Integrations
36
- - title: Server-Side Secrets
37
- details: Keep AI provider keys, OAuth client secrets, Telnyx tokens, runtime settings, and deployment controls on the NeoAgent server.
38
- link: /configuration
39
- linkText: Configuration
40
- - title: Recovery Path
41
- details: Operate self-hosted installs with status, logs, release channels, update, fix, runtime paths, and the remote-server log caveat.
42
- link: /operations
43
- linkText: Operations
44
- ---
9
+ NeoAgent is a self-hosted proactive AI agent with a bundled Flutter client for web and Android. It runs on your server, keeps credentials server-side, and gives you an operator UI for chat, runs, logs, scheduler tasks, skills, integrations, MCP, memory, Android control, recordings, Health Connect data, wearables, and settings.
10
+
11
+ It is designed for people who want a focused personal automation server rather than a broad gateway platform. NeoAgent can run scheduled tasks, control a browser, operate a server-attached Android emulator or device, manage files, remember long-term context, connect to hosted AI providers or local Ollama, search recordings, read synced health summaries, and send results through Telegram, Discord, WhatsApp, or Telnyx Voice.
45
12
 
46
13
  ## Quick Start
47
14
 
@@ -52,7 +19,21 @@ neoagent install
52
19
 
53
20
  Open the server URL, sign in, configure providers and messaging, then create a scheduled task or chat run.
54
21
 
55
- ## Navigation
22
+ ## What NeoAgent Does
23
+
24
+ | Area | Capability |
25
+ |---|---|
26
+ | AI providers | OpenAI, Anthropic, xAI, Google, MiniMax Code, and local Ollama |
27
+ | Operator UI | Chat, live runs, logs, scheduler, skills, integrations, MCP, memory, devices, recordings, health, wearables, settings |
28
+ | Automation | Recurring scheduled tasks, one-time runs, browser control, file access, CLI skills, subagents, and messaging delivery |
29
+ | Android control | AI control of a server-attached Android emulator or device: screenshots, UI dumps, taps, typing, intents, APK installs, and ADB shell |
30
+ | Recordings | Web, Android, and wearable audio sessions with transcript search and AI insights |
31
+ | Integrations | Google Workspace, Notion, Microsoft 365, Slack, Figma, and remote MCP servers |
32
+ | Messaging | Telegram, Discord, WhatsApp text/media, and Telnyx Voice calls |
33
+ | Outputs | Artifacts, Grok image generation, vision analysis, markdown tables, and Mermaid graphs |
34
+ | Recovery | `neoagent status`, `neoagent logs`, `neoagent update`, release channels, and `neoagent fix` |
35
+
36
+ ## Main Paths
56
37
 
57
38
  | Need | Start here |
58
39
  |---|---|
@@ -10,6 +10,9 @@ const flowDescriptionEl = document.querySelector('#flowDescription');
10
10
  const primaryActionEl = document.querySelector('#primaryAction');
11
11
  const secondaryActionEl = document.querySelector('#secondaryAction');
12
12
  const openAppEl = document.querySelector('#openApp');
13
+ const disconnectEl = document.querySelector('#disconnect');
14
+ const checkUpdateEl = document.querySelector('#checkUpdate');
15
+ const downloadEl = document.querySelector('#download');
13
16
 
14
17
  const STATUS_LABELS = {
15
18
  connected: 'Connected',
@@ -186,68 +189,38 @@ async function refresh() {
186
189
  updateFlow();
187
190
  }
188
191
 
189
- primaryActionEl.addEventListener('click', async () => {
190
- try {
191
- setMessage('');
192
- await runAction(primaryActionEl.dataset.action);
193
- } catch (error) {
194
- setMessage(error.message, 'error');
195
- }
196
- });
197
-
198
- secondaryActionEl.addEventListener('click', async () => {
199
- try {
200
- setMessage('');
201
- await runAction(secondaryActionEl.dataset.action);
202
- } catch (error) {
203
- setMessage(error.message, 'error');
204
- }
205
- });
206
-
207
- openAppEl.addEventListener('click', async () => {
208
- try {
209
- setMessage('');
210
- await runAction('openApp');
211
- } catch (error) {
212
- setMessage(error.message, 'error');
213
- }
214
- });
192
+ function bindAsyncClick(element, handler) {
193
+ element.addEventListener('click', async () => {
194
+ try {
195
+ setMessage('');
196
+ await handler();
197
+ } catch (error) {
198
+ setMessage(error.message, 'error');
199
+ }
200
+ });
201
+ }
215
202
 
216
203
  serverUrlEl.addEventListener('input', updateFlow);
217
204
 
218
- document.querySelector('#disconnect').addEventListener('click', async () => {
219
- try {
220
- setMessage('');
221
- await send('disconnect');
222
- await refresh();
223
- setMessage('Disconnected.', 'success');
224
- } catch (error) {
225
- setMessage(error.message, 'error');
226
- }
205
+ bindAsyncClick(primaryActionEl, () => runAction(primaryActionEl.dataset.action));
206
+ bindAsyncClick(secondaryActionEl, () => runAction(secondaryActionEl.dataset.action));
207
+ bindAsyncClick(openAppEl, () => runAction('openApp'));
208
+ bindAsyncClick(disconnectEl, async () => {
209
+ await send('disconnect');
210
+ await refresh();
211
+ setMessage('Disconnected.', 'success');
227
212
  });
228
-
229
- document.querySelector('#checkUpdate').addEventListener('click', async () => {
230
- try {
231
- setMessage('');
232
- const result = await send('checkForUpdates', { serverUrl: effectiveServerUrl() });
233
- setMessage(
234
- result.updateAvailable
235
- ? `Update available: ${result.currentVersion} -> ${result.latestVersion}.`
236
- : `Current version ${result.currentVersion} is up to date.`,
237
- result.updateAvailable ? '' : 'success',
238
- );
239
- } catch (error) {
240
- setMessage(error.message, 'error');
241
- }
213
+ bindAsyncClick(checkUpdateEl, async () => {
214
+ const result = await send('checkForUpdates', { serverUrl: effectiveServerUrl() });
215
+ setMessage(
216
+ result.updateAvailable
217
+ ? `Update available: ${result.currentVersion} -> ${result.latestVersion}.`
218
+ : `Current version ${result.currentVersion} is up to date.`,
219
+ result.updateAvailable ? '' : 'success',
220
+ );
242
221
  });
243
-
244
- document.querySelector('#download').addEventListener('click', async () => {
245
- try {
246
- setMessage('');
247
- await send('openDownload', { serverUrl: effectiveServerUrl() });
248
- } catch (error) {
249
- setMessage(error.message, 'error');
250
- }
222
+ bindAsyncClick(downloadEl, async () => {
223
+ await send('openDownload', { serverUrl: effectiveServerUrl() });
251
224
  });
252
225
 
253
226
  chrome.runtime.onMessage.addListener((message) => {
package/package.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "name": "neoagent",
3
- "version": "2.1.18-beta.35",
3
+ "version": "2.1.18-beta.37",
4
4
  "description": "Proactive personal AI agent with no limits",
5
5
  "license": "MIT",
6
6
  "main": "server/index.js",
7
+ "engines": {
8
+ "node": ">=20"
9
+ },
7
10
  "bin": {
8
11
  "neoagent": "bin/neoagent.js"
9
12
  },
@@ -28,9 +31,9 @@
28
31
  "dev:stack": "./dev/stack.sh",
29
32
  "dev:build": "./dev/build.sh",
30
33
  "dev:test": "./dev/test.sh",
31
- "docs:dev": "vitepress dev docs",
32
- "docs:build": "vitepress build docs",
33
- "docs:preview": "vitepress preview docs",
34
+ "docs:dev": "docusaurus start",
35
+ "docs:build": "docusaurus build",
36
+ "docs:preview": "docusaurus serve build",
34
37
  "flutter:run:web": "cd flutter_app && flutter run -d chrome",
35
38
  "flutter:build:web": "cd flutter_app && flutter build web --output ../server/public --dart-define=NEOAGENT_BACKEND_URL=${NEOAGENT_BACKEND_URL:-}",
36
39
  "manage": "node bin/neoagent.js",
@@ -83,6 +86,9 @@
83
86
  "undici": "^6.24.0"
84
87
  },
85
88
  "devDependencies": {
86
- "vitepress": "1.6.4"
89
+ "@docusaurus/core": "3.8.1",
90
+ "@docusaurus/preset-classic": "3.8.1",
91
+ "react": "18.3.1",
92
+ "react-dom": "18.3.1"
87
93
  }
88
94
  }
@@ -0,0 +1,99 @@
1
+ ---
2
+ name: Catbox & Litterbox File Uploader
3
+ description: Upload local files to Catbox for permanent sharing or Litterbox for temporary sharing. Use when you need a public link for logs, screenshots, archives, media, or other local artifacts.
4
+ version: 1.0.0
5
+ author: Microck
6
+ upstream: https://github.com/Microck/opendots-microck/tree/main/skills/catbox-upload-skill
7
+ ---
8
+
9
+ # Catbox & Litterbox File Uploader
10
+
11
+ Use this skill when the user wants a direct public URL for a local file.
12
+
13
+ - Prefer `litterbox` for temporary sharing of logs, builds, screenshots, and one-off artifacts.
14
+ - Prefer `catbox` for permanent hosting.
15
+ - Return the final URL plainly, and for `litterbox` also mention the selected expiry window.
16
+
17
+ ## Command
18
+
19
+ Run the bundled uploader script:
20
+
21
+ ```bash
22
+ bash ~/.neoagent/agent-data/skills/productivity-catbox-upload-skill/scripts/upload.sh /path/to/file
23
+ ```
24
+
25
+ ## Arguments
26
+
27
+ - `file_path` (required): local file to upload
28
+ - `--service litterbox|catbox` (optional): defaults to `litterbox`
29
+ - `--time 1h|12h|24h|72h` (optional): only used for `litterbox`, defaults to `24h`
30
+ - `--userhash HASH` (optional): Catbox account hash for uploads tied to a Catbox account
31
+
32
+ ## Examples
33
+
34
+ Temporary upload with the default 24-hour expiry:
35
+
36
+ ```bash
37
+ bash ~/.neoagent/agent-data/skills/productivity-catbox-upload-skill/scripts/upload.sh ./logs/server.log
38
+ ```
39
+
40
+ Temporary upload that expires after 1 hour:
41
+
42
+ ```bash
43
+ bash ~/.neoagent/agent-data/skills/productivity-catbox-upload-skill/scripts/upload.sh ./build/output.zip --time 1h
44
+ ```
45
+
46
+ Permanent upload to Catbox:
47
+
48
+ ```bash
49
+ bash ~/.neoagent/agent-data/skills/productivity-catbox-upload-skill/scripts/upload.sh ./artifacts/screenshot.png --service catbox
50
+ ```
51
+
52
+ Permanent upload associated with a Catbox account:
53
+
54
+ ```bash
55
+ bash ~/.neoagent/agent-data/skills/productivity-catbox-upload-skill/scripts/upload.sh ./artifacts/screenshot.png --service catbox --userhash YOUR_HASH
56
+ ```
57
+
58
+ ## Expected Output
59
+
60
+ The script prints exactly one URL on success, for example:
61
+
62
+ ```text
63
+ https://litterbox.catbox.moe/abc123.png
64
+ ```
65
+
66
+ or:
67
+
68
+ ```text
69
+ https://files.catbox.moe/abc123.png
70
+ ```
71
+
72
+ ## Presenting Results
73
+
74
+ When the upload succeeds:
75
+
76
+ - show the returned URL clearly
77
+ - mention whether it is temporary or permanent
78
+ - if using `litterbox`, include the expiration window
79
+
80
+ Example response:
81
+
82
+ ```text
83
+ File uploaded successfully.
84
+
85
+ Link: https://litterbox.catbox.moe/abc123.png
86
+ Expires in: 24 hours
87
+ ```
88
+
89
+ ## Limits
90
+
91
+ - `litterbox`: up to 1 GB, temporary, supports `1h`, `12h`, `24h`, and `72h`
92
+ - `catbox`: up to 200 MB, permanent
93
+
94
+ ## Troubleshooting
95
+
96
+ - If the file does not exist or is unreadable, verify the path first.
97
+ - If the upload fails, surface the exact error from the script.
98
+ - If `curl` is missing, install it before retrying.
99
+ - If Catbox rejects the file, the file may exceed the service limit or violate Catbox content rules.
@@ -0,0 +1,155 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ usage() {
5
+ cat >&2 <<'EOF'
6
+ Usage: upload.sh <file_path> [--service litterbox|catbox] [--time 1h|12h|24h|72h] [--userhash HASH]
7
+
8
+ Options:
9
+ --service Upload target. Defaults to litterbox.
10
+ --time Litterbox retention window. Defaults to 24h.
11
+ --userhash Optional Catbox account hash for uploads associated with an account.
12
+ -h, --help Show this help text.
13
+
14
+ Limits:
15
+ litterbox: 1 GB
16
+ catbox: 200 MB
17
+ EOF
18
+ }
19
+
20
+ fail() {
21
+ printf 'Error: %s\n' "$1" >&2
22
+ exit 1
23
+ }
24
+
25
+ require_value() {
26
+ local option="$1"
27
+ local value="${2-}"
28
+ [[ -n "$value" ]] || fail "$option requires a value"
29
+ }
30
+
31
+ SERVICE="litterbox"
32
+ TIME="24h"
33
+ USERHASH=""
34
+ FILE_PATH=""
35
+
36
+ while [[ $# -gt 0 ]]; do
37
+ case "$1" in
38
+ --service)
39
+ require_value "$1" "${2-}"
40
+ SERVICE="$2"
41
+ shift 2
42
+ ;;
43
+ --time)
44
+ require_value "$1" "${2-}"
45
+ TIME="$2"
46
+ shift 2
47
+ ;;
48
+ --userhash)
49
+ require_value "$1" "${2-}"
50
+ USERHASH="$2"
51
+ shift 2
52
+ ;;
53
+ -h|--help)
54
+ usage
55
+ exit 0
56
+ ;;
57
+ --)
58
+ shift
59
+ break
60
+ ;;
61
+ -*)
62
+ usage
63
+ fail "unknown option: $1"
64
+ ;;
65
+ *)
66
+ [[ -z "$FILE_PATH" ]] || fail "only one file path is supported"
67
+ FILE_PATH="$1"
68
+ shift
69
+ ;;
70
+ esac
71
+ done
72
+
73
+ if [[ $# -gt 0 ]]; then
74
+ [[ -z "$FILE_PATH" ]] || fail "only one file path is supported"
75
+ FILE_PATH="$1"
76
+ shift
77
+ fi
78
+
79
+ [[ $# -eq 0 ]] || fail "only one file path is supported"
80
+
81
+ [[ -n "$FILE_PATH" ]] || {
82
+ usage
83
+ fail "file path is required"
84
+ }
85
+
86
+ command -v curl >/dev/null 2>&1 || fail "curl is not installed"
87
+ [[ -f "$FILE_PATH" ]] || fail "file not found: $FILE_PATH"
88
+ [[ -r "$FILE_PATH" ]] || fail "file is not readable: $FILE_PATH"
89
+
90
+ case "$SERVICE" in
91
+ litterbox|catbox)
92
+ ;;
93
+ *)
94
+ fail "service must be either 'litterbox' or 'catbox'"
95
+ ;;
96
+ esac
97
+
98
+ case "$TIME" in
99
+ 1h|12h|24h|72h)
100
+ ;;
101
+ *)
102
+ fail "time must be one of: 1h, 12h, 24h, 72h"
103
+ ;;
104
+ esac
105
+
106
+ FILE_SIZE_BYTES="$(wc -c < "$FILE_PATH" | tr -d '[:space:]')"
107
+ LITTERBOX_LIMIT_BYTES=1073741824
108
+ CATBOX_LIMIT_BYTES=209715200
109
+
110
+ if [[ "$SERVICE" == "litterbox" ]] && (( FILE_SIZE_BYTES > LITTERBOX_LIMIT_BYTES )); then
111
+ fail "litterbox uploads are limited to 1 GB"
112
+ fi
113
+
114
+ if [[ "$SERVICE" == "catbox" ]] && (( FILE_SIZE_BYTES > CATBOX_LIMIT_BYTES )); then
115
+ fail "catbox uploads are limited to 200 MB"
116
+ fi
117
+
118
+ CURL_FILE_PATH="${FILE_PATH//;/\\;}"
119
+
120
+ if [[ "$SERVICE" == "litterbox" ]]; then
121
+ ENDPOINT="https://litterbox.catbox.moe/resources/internals/api.php"
122
+ RESPONSE="$(
123
+ curl --silent --show-error --fail \
124
+ --user-agent 'NeoAgent catbox-upload-skill/1.0' \
125
+ -F 'reqtype=fileupload' \
126
+ -F "time=$TIME" \
127
+ -F "fileToUpload=@$CURL_FILE_PATH" \
128
+ "$ENDPOINT"
129
+ )"
130
+ else
131
+ ENDPOINT="https://catbox.moe/user/api.php"
132
+ if [[ -n "$USERHASH" ]]; then
133
+ RESPONSE="$(
134
+ curl --silent --show-error --fail \
135
+ --user-agent 'NeoAgent catbox-upload-skill/1.0' \
136
+ -F 'reqtype=fileupload' \
137
+ -F "userhash=$USERHASH" \
138
+ -F "fileToUpload=@$CURL_FILE_PATH" \
139
+ "$ENDPOINT"
140
+ )"
141
+ else
142
+ RESPONSE="$(
143
+ curl --silent --show-error --fail \
144
+ --user-agent 'NeoAgent catbox-upload-skill/1.0' \
145
+ -F 'reqtype=fileupload' \
146
+ -F "fileToUpload=@$CURL_FILE_PATH" \
147
+ "$ENDPOINT"
148
+ )"
149
+ fi
150
+ fi
151
+
152
+ RESPONSE="$(printf '%s' "$RESPONSE" | tr -d '\r\n')"
153
+ [[ "$RESPONSE" =~ ^https?:// ]] || fail "upload failed: $RESPONSE"
154
+
155
+ printf '%s\n' "$RESPONSE"
@@ -10,6 +10,7 @@ const { logRequestSummary } = require('../utils/logger');
10
10
  const { getSessionSecret } = require('../services/account/session_secret');
11
11
 
12
12
  const sessionsDb = new Sqlite(`${DATA_DIR}/sessions.db`);
13
+ const LEGACY_SESSION_EXPIRE_FALLBACK = 0;
13
14
 
14
15
  function ensureSessionStoreSchema(db) {
15
16
  const table = db.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'sessions'").get();
@@ -35,11 +36,10 @@ function ensureSessionStoreSchema(db) {
35
36
  db.exec('CREATE TABLE sessions (sid PRIMARY KEY, sess, expire)');
36
37
 
37
38
  if (hasSid && hasSess) {
38
- // TODO: Verify whether better-sqlite3-session-store treats expire=0 as already expired or non-expiring.
39
39
  const expireExpr = expireColumn ? expireColumn : 'NULL';
40
40
  db.exec(`
41
41
  INSERT OR REPLACE INTO sessions (sid, sess, expire)
42
- SELECT sid, sess, COALESCE(${expireExpr}, 0) AS expire
42
+ SELECT sid, sess, COALESCE(${expireExpr}, ${LEGACY_SESSION_EXPIRE_FALLBACK}) AS expire
43
43
  FROM ${legacyTableName}
44
44
  WHERE sid IS NOT NULL
45
45
  `);
@@ -138,6 +138,13 @@ function applyHttpMiddleware(app, { secureCookies, sessionMiddleware, validateOr
138
138
  || path === '/api/browser-extension/pairing/request'
139
139
  || /^\/api\/browser-extension\/pairing\/[^/]+\/claim$/i.test(path);
140
140
  };
141
+ const requestPath = (req) => req.originalUrl || req.url || req.path || '';
142
+ const applyOnlyToRecordingChunk = (handler) => (req, res, next) => (
143
+ isRecordingChunkPath(requestPath(req)) ? handler(req, res, next) : next()
144
+ );
145
+ const skipRecordingChunk = (handler) => (req, res, next) => (
146
+ isRecordingChunkPath(requestPath(req)) ? next() : handler(req, res, next)
147
+ );
141
148
 
142
149
  if (secureCookies) {
143
150
  app.set('trust proxy', 1);
@@ -184,24 +191,9 @@ function applyHttpMiddleware(app, { secureCookies, sessionMiddleware, validateOr
184
191
 
185
192
  next();
186
193
  });
187
- app.use((req, res, next) => {
188
- if (isRecordingChunkPath(req.originalUrl || req.url || req.path)) {
189
- return rawRecordingChunkBody(req, res, next);
190
- }
191
- return next();
192
- });
193
- app.use((req, res, next) => {
194
- if (isRecordingChunkPath(req.originalUrl || req.url || req.path)) {
195
- return next();
196
- }
197
- return jsonBody(req, res, next);
198
- });
199
- app.use((req, res, next) => {
200
- if (isRecordingChunkPath(req.originalUrl || req.url || req.path)) {
201
- return next();
202
- }
203
- return urlencodedBody(req, res, next);
204
- });
194
+ app.use(applyOnlyToRecordingChunk(rawRecordingChunkBody));
195
+ app.use(skipRecordingChunk(jsonBody));
196
+ app.use(skipRecordingChunk(urlencodedBody));
205
197
  app.use(sessionMiddleware);
206
198
  }
207
199
 
@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"425cfb54d01a9472b3e81d9e76fd63a4a44cfb
37
37
 
38
38
  _flutter.loader.load({
39
39
  serviceWorkerSettings: {
40
- serviceWorkerVersion: "1213638891" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
40
+ serviceWorkerVersion: "1235668503" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
41
41
  }
42
42
  });