stella-coder 5.3.1 → 5.3.3

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 (52) hide show
  1. package/COMMANDS.md +47 -0
  2. package/install-av.bat +17 -0
  3. package/install-stella-pkg.bat +21 -0
  4. package/oneline-av.ps1 +7 -0
  5. package/oneline-stella.ps1 +2 -0
  6. package/package.json +1 -1
  7. package/releases/stella-antivirus/database.mjs +871 -0
  8. package/releases/stella-antivirus/index.mjs +8 -0
  9. package/releases/stella-antivirus/install-av.bat +12 -0
  10. package/releases/stella-antivirus/scanner.mjs +591 -0
  11. package/releases/stella-antivirus/ui.mjs +570 -0
  12. package/releases/stella-antivirus.zip +0 -0
  13. package/releases/stella-coder/README.md +67 -0
  14. package/releases/stella-coder/adb.mjs +200 -0
  15. package/releases/stella-coder/autonomous-agent.mjs +550 -0
  16. package/releases/stella-coder/banner.mjs +46 -0
  17. package/releases/stella-coder/browser-control.mjs +274 -0
  18. package/releases/stella-coder/build.mjs +151 -0
  19. package/releases/stella-coder/charts.mjs +411 -0
  20. package/releases/stella-coder/coding-brain.mjs +753 -0
  21. package/releases/stella-coder/game-engine.mjs +708 -0
  22. package/releases/stella-coder/gdrive-backup.mjs +338 -0
  23. package/releases/stella-coder/git-api.mjs +407 -0
  24. package/releases/stella-coder/gmail.mjs +415 -0
  25. package/releases/stella-coder/home-assistant.mjs +168 -0
  26. package/releases/stella-coder/index.mjs +5810 -0
  27. package/releases/stella-coder/install-stella.bat +12 -0
  28. package/releases/stella-coder/markdown.mjs +100 -0
  29. package/releases/stella-coder/mcp.mjs +296 -0
  30. package/releases/stella-coder/package.json +67 -0
  31. package/releases/stella-coder/presentations.mjs +1106 -0
  32. package/releases/stella-coder/protect.mjs +182 -0
  33. package/releases/stella-coder/screen-monitor.mjs +334 -0
  34. package/releases/stella-coder/sea-config.json +5 -0
  35. package/releases/stella-coder/security.mjs +237 -0
  36. package/releases/stella-coder/subagents.mjs +142 -0
  37. package/releases/stella-coder/telegram-bot.mjs +824 -0
  38. package/releases/stella-coder/tg-server.mjs +116 -0
  39. package/releases/stella-coder/theme.mjs +91 -0
  40. package/releases/stella-coder/tools.mjs +3143 -0
  41. package/releases/stella-coder/web-parser.mjs +229 -0
  42. package/releases/stella-coder/yandex-maps.mjs +426 -0
  43. package/releases/stella-coder.zip +0 -0
  44. package/run-antivirus.bat +4 -0
  45. package/setup-antivirus.bat +64 -0
  46. package/setup-full.bat +65 -0
  47. package/setup-full.ps1 +84 -0
  48. package/setup-stella.bat +46 -0
  49. package/stella-cli/index.mjs +12 -2
  50. package/stella-cli/protect.mjs +182 -0
  51. package/stella.bat +3 -0
  52. package/tests/test-modules.mjs +101 -0
@@ -0,0 +1,182 @@
1
+ #!/usr/bin/env node
2
+ // Stella Coder — Code Protector & Packager
3
+ import fs from "node:fs"
4
+ import path from "node:path"
5
+ import { execSync } from "node:child_process"
6
+ import { fileURLToPath } from "node:url"
7
+
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
9
+ const ROOT = path.resolve(__dirname, "..")
10
+ const RELEASES = path.join(ROOT, "releases")
11
+ const STELLA_PKG = path.join(RELEASES, "stella-coder")
12
+ const AV_PKG = path.join(RELEASES, "stella-antivirus")
13
+
14
+ function cleanDir(dir) {
15
+ if (fs.existsSync(dir)) fs.rmSync(dir, { recursive: true })
16
+ fs.mkdirSync(dir, { recursive: true })
17
+ }
18
+
19
+ function copy(src, dst) {
20
+ if (fs.existsSync(src)) {
21
+ if (fs.statSync(src).isDirectory()) {
22
+ if (!fs.existsSync(dst)) fs.mkdirSync(dst, { recursive: true })
23
+ for (const item of fs.readdirSync(src)) copy(path.join(src, item), path.join(dst, item))
24
+ } else {
25
+ fs.cpSync(src, dst)
26
+ }
27
+ }
28
+ }
29
+
30
+ function stripComments(code) {
31
+ return code
32
+ }
33
+
34
+ function makeReadable(code) {
35
+ return code
36
+ }
37
+
38
+ function addGuard(code) {
39
+ return code
40
+ }
41
+
42
+ console.log("\n ✦ Stella Coder — Protector & Packager\n")
43
+
44
+ // Create release directories
45
+ cleanDir(STELLA_PKG)
46
+ cleanDir(AV_PKG)
47
+
48
+ // 1. Package Stella CLI
49
+ console.log(" [1/3] Packaging Stella CLI...")
50
+ const cliFiles = fs.readdirSync(path.join(ROOT, "stella-cli")).filter(f => f.endsWith(".mjs"))
51
+ for (const f of cliFiles) {
52
+ const src = path.join(ROOT, "stella-cli", f)
53
+ let code = fs.readFileSync(src, "utf8")
54
+ code = addGuard(code)
55
+ code = stripComments(code)
56
+ fs.writeFileSync(path.join(STELLA_PKG, f), code)
57
+ }
58
+ // Copy package.json and README
59
+ copy(path.join(ROOT, "package.json"), path.join(STELLA_PKG, "package.json"))
60
+ copy(path.join(ROOT, "stella-cli", "sea-config.json"), path.join(STELLA_PKG, "sea-config.json"))
61
+ copy(path.join(ROOT, "README.md"), path.join(STELLA_PKG, "README.md"))
62
+
63
+ // Create install-stella.bat
64
+ fs.writeFileSync(path.join(STELLA_PKG, "install-stella.bat"), `@echo off
65
+ chcp 65001 >nul
66
+ echo.
67
+ echo ✦ Stella Coder — Installation
68
+ echo =============================
69
+ echo.
70
+ echo Install: npm i -g stella-coder
71
+ echo Or run: node stella-cli/index.mjs
72
+ echo.
73
+ echo Docs: https://a1x10.github.io/stella/
74
+ echo.
75
+ pause
76
+ `)
77
+
78
+ // 2. Package Antivirus separately
79
+ console.log(" [2/3] Packaging Stella Antivirus...")
80
+ const avFiles = fs.readdirSync(path.join(ROOT, "antimalware")).filter(f => f.endsWith(".mjs"))
81
+ for (const f of avFiles) {
82
+ const src = path.join(ROOT, "antimalware", f)
83
+ let code = fs.readFileSync(src, "utf8")
84
+ code = addGuard(code)
85
+ code = stripComments(code)
86
+ fs.writeFileSync(path.join(AV_PKG, f), code)
87
+ }
88
+ // Copy antimalware/index.mjs as entry point
89
+ copy(path.join(ROOT, "antimalware", "index.mjs"), path.join(AV_PKG, "index.mjs"))
90
+
91
+ // Create standalone install-antivirus.bat
92
+ fs.writeFileSync(path.join(AV_PKG, "install-av.bat"), `@echo off
93
+ chcp 65001 >nul
94
+ echo.
95
+ echo ✦ Stella Antivirus — Installation
96
+ echo =================================
97
+ echo.
98
+ echo Quick run: node index.mjs
99
+ echo.
100
+ echo Scans your system for threats using
101
+ echo signature-based detection + AI analysis.
102
+ echo.
103
+ pause
104
+ `)
105
+
106
+ // 3. Create combined installers for root
107
+ console.log(" [3/3] Creating root installers...")
108
+
109
+ // Stella installer
110
+ fs.writeFileSync(path.join(ROOT, "install-stella-pkg.bat"), `@echo off
111
+ chcp 65001 >nul
112
+ echo.
113
+ echo ✦ Stella Coder v5.3.1 — AI Coding Agent
114
+ echo =========================================
115
+ echo.
116
+ echo [1] npm install -g stella-coder
117
+ call npm install -g stella-coder
118
+ echo.
119
+ echo [2] Verify installation
120
+ call stella --version
121
+ echo.
122
+ if %errorlevel% equ 0 (
123
+ echo ✓ Stella Coder installed!
124
+ echo.
125
+ echo Type "stella" to start
126
+ ) else (
127
+ echo ✗ Try: node %~dp0stella-cli/index.mjs
128
+ )
129
+ echo.
130
+ pause
131
+ `)
132
+
133
+ // Antivirus standalone installer
134
+ fs.writeFileSync(path.join(ROOT, "install-av.bat"), `@echo off
135
+ chcp 65001 >nul
136
+ echo.
137
+ echo ✦ Stella Antivirus — Standalone Scanner
138
+ echo =========================================
139
+ echo.
140
+ echo Quick start:
141
+ echo node "%CD%\\antimalware\\index.mjs"
142
+ echo.
143
+ echo Or add to PATH:
144
+ echo set PATH=%%PATH%%;"%CD%\\antimalware"
145
+ echo stella-antivirus
146
+ echo.
147
+ echo Scans: files, processes, registry, startup
148
+ echo Method: signature database + AI heuristic
149
+ echo.
150
+ pause
151
+ `)
152
+
153
+ // Create shortcuts
154
+ fs.writeFileSync(path.join(ROOT, "run-antivirus.bat"), `@echo off
155
+ chcp 65001 >nul
156
+ node "%~dp0antimalware\\index.mjs"
157
+ pause
158
+ `)
159
+
160
+ console.log(fs.existsSync(path.join(AV_PKG, "index.mjs")) ? " ✓" : " ✗")
161
+ console.log()
162
+
163
+ // Create archive versions for GitHub release
164
+ console.log(" Creating archives for GitHub Release...")
165
+ const zipDir = path.join(ROOT, "releases")
166
+ if (!fs.existsSync(zipDir)) fs.mkdirSync(zipDir, { recursive: true })
167
+
168
+ // ZIP Stella
169
+ try {
170
+ execSync(`powershell -Command "Compress-Archive -Path '${STELLA_PKG}\\*' -DestinationPath '${path.join(zipDir, 'stella-coder.zip')}' -Force"`, { timeout: 15000 })
171
+ console.log(" ✓ stella-coder.zip")
172
+ } catch { console.log(" ✗ stella-coder.zip (use 7zip or manual)") }
173
+
174
+ // ZIP Antivirus
175
+ try {
176
+ execSync(`powershell -Command "Compress-Archive -Path '${AV_PKG}\\*' -DestinationPath '${path.join(zipDir, 'stella-antivirus.zip')}' -Force"`, { timeout: 15000 })
177
+ console.log(" ✓ stella-antivirus.zip")
178
+ } catch { console.log(" ✗ stella-antivirus.zip") }
179
+
180
+ console.log()
181
+ console.log(" ✓ Done! Packages in releases/")
182
+ console.log()
@@ -0,0 +1,334 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync, unlinkSync, statSync } from "fs"
2
+ import { join } from "path"
3
+ import { homedir } from "os"
4
+ import { execSync } from "child_process"
5
+
6
+ const STELLA_DIR = join(homedir(), ".stella")
7
+ const MONITOR_DIR = join(STELLA_DIR, "monitor")
8
+ const HISTORY_FILE = join(MONITOR_DIR, "history.json")
9
+ const ALERTS_FILE = join(MONITOR_DIR, "alerts.json")
10
+ const SCREENSHOTS_DIR = join(MONITOR_DIR, "screenshots")
11
+ const MONITOR_STATE = join(MONITOR_DIR, "state.json")
12
+
13
+ function ensureDir() {
14
+ if (!existsSync(MONITOR_DIR)) mkdirSync(MONITOR_DIR, { recursive: true })
15
+ if (!existsSync(SCREENSHOTS_DIR)) mkdirSync(SCREENSHOTS_DIR, { recursive: true })
16
+ }
17
+
18
+ function loadJSON(file, fallback) {
19
+ try { return JSON.parse(readFileSync(file, "utf-8")) } catch { return fallback }
20
+ }
21
+
22
+ function saveJSON(file, data) {
23
+ ensureDir()
24
+ writeFileSync(file, JSON.stringify(data, null, 2))
25
+ }
26
+
27
+ function captureScreenSync() {
28
+ const ts = Date.now()
29
+ const outPath = join(SCREENSHOTS_DIR, `screen_${ts}.png`)
30
+ const tempPath = join(SCREENSHOTS_DIR, `_temp.png`)
31
+ const psScriptPath = join(SCREENSHOTS_DIR, `_capture.ps1`)
32
+
33
+ // Write PowerShell script to file (avoids escaping issues)
34
+ const psScript = `
35
+ Add-Type -AssemblyName System.Windows.Forms
36
+ Add-Type -AssemblyName System.Drawing
37
+ try {
38
+ $bounds = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds
39
+ $bitmap = New-Object System.Drawing.Bitmap($bounds.Width, $bounds.Height)
40
+ $graphics = [System.Drawing.Graphics]::FromImage($bitmap)
41
+ $graphics.CopyFromScreen($bounds.Location, [System.Drawing.Point]::Empty, $bounds.Size)
42
+ $bitmap.Save("${tempPath.replace(/\\/g, "\\\\")}")
43
+ $graphics.Dispose()
44
+ $bitmap.Dispose()
45
+ Write-Output "OK"
46
+ } catch {
47
+ Write-Output "FAIL:$($_.Exception.Message)"
48
+ }
49
+ `.trim()
50
+
51
+ try {
52
+ writeFileSync(psScriptPath, psScript, "utf-8")
53
+ const result = execSync(`powershell -NoProfile -ExecutionPolicy Bypass -File "${psScriptPath}"`, {
54
+ encoding: "utf-8",
55
+ timeout: 10000,
56
+ stdio: ["pipe", "pipe", "pipe"],
57
+ }).trim()
58
+
59
+ if (result.startsWith("OK") && existsSync(tempPath)) {
60
+ const data = readFileSync(tempPath)
61
+ writeFileSync(outPath, data)
62
+ try { unlinkSync(tempPath) } catch {}
63
+ try { unlinkSync(psScriptPath) } catch {}
64
+ return outPath
65
+ }
66
+ try { unlinkSync(psScriptPath) } catch {}
67
+ return null
68
+ } catch {
69
+ return null
70
+ }
71
+ }
72
+
73
+ function compressImage(imagePath, maxWidth = 800) {
74
+ const compressedPath = imagePath.replace(".png", "_small.png")
75
+ const psScriptPath = join(SCREENSHOTS_DIR, `_compress.ps1`)
76
+
77
+ const psScript = `
78
+ Add-Type -AssemblyName System.Drawing
79
+ try {
80
+ $img = [System.Drawing.Image]::FromFile("${imagePath.replace(/\\/g, "\\\\")}")
81
+ $ratio = ${maxWidth} / $img.Width
82
+ if ($ratio -ge 1) { $ratio = 1 }
83
+ $newW = [int]($img.Width * $ratio)
84
+ $newH = [int]($img.Height * $ratio)
85
+ $bmp = New-Object System.Drawing.Bitmap($newW, $newH)
86
+ $g = [System.Drawing.Graphics]::FromImage($bmp)
87
+ $g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
88
+ $g.DrawImage($img, 0, 0, $newW, $newH)
89
+ $bmp.Save("${compressedPath.replace(/\\/g, "\\\\")}")
90
+ $g.Dispose()
91
+ $bmp.Dispose()
92
+ $img.Dispose()
93
+ Write-Output "OK"
94
+ } catch {
95
+ Write-Output "FAIL"
96
+ }
97
+ `.trim()
98
+
99
+ try {
100
+ writeFileSync(psScriptPath, psScript, "utf-8")
101
+ execSync(`powershell -NoProfile -ExecutionPolicy Bypass -File "${psScriptPath}"`, {
102
+ encoding: "utf-8",
103
+ timeout: 10000,
104
+ stdio: ["pipe", "pipe", "pipe"],
105
+ })
106
+ try { unlinkSync(psScriptPath) } catch {}
107
+ if (existsSync(compressedPath)) {
108
+ return compressedPath
109
+ }
110
+ } catch {}
111
+ return imagePath
112
+ }
113
+
114
+ export class ScreenMonitor {
115
+ constructor() {
116
+ ensureDir()
117
+ this.state = loadJSON(MONITOR_STATE, {
118
+ running: false,
119
+ interval: 2000,
120
+ startedAt: null,
121
+ totalCaptures: 0,
122
+ totalAlerts: 0,
123
+ pid: null,
124
+ })
125
+ this.history = loadJSON(HISTORY_FILE, [])
126
+ this.alerts = loadJSON(ALERTS_FILE, [])
127
+ this.intervalId = null
128
+ }
129
+
130
+ save() {
131
+ saveJSON(MONITOR_STATE, this.state)
132
+ saveJSON(HISTORY_FILE, this.history.slice(-500))
133
+ saveJSON(ALERTS_FILE, this.alerts.slice(-200))
134
+ }
135
+
136
+ async captureAndAnalyze(visionFn) {
137
+ const imagePath = captureScreenSync()
138
+ if (!imagePath) {
139
+ return { success: false, error: "Failed to capture screen" }
140
+ }
141
+
142
+ const stats = statSync(imagePath)
143
+ const sizeKB = Math.round(stats.size / 1024)
144
+
145
+ // Compress for AI analysis
146
+ const compressedPath = compressImage(imagePath, 600)
147
+ let imageBase64
148
+ try {
149
+ imageBase64 = readFileSync(compressedPath).toString("base64")
150
+ } catch {
151
+ imageBase64 = readFileSync(imagePath).toString("base64")
152
+ }
153
+
154
+ const ts = new Date().toISOString()
155
+ const capture = {
156
+ id: Date.now().toString(36),
157
+ timestamp: ts,
158
+ path: imagePath,
159
+ sizeKB,
160
+ analysis: null,
161
+ alerts: [],
162
+ }
163
+
164
+ // Analyze with vision AI
165
+ if (visionFn) {
166
+ try {
167
+ const analysis = await visionFn(imageBase64, this.getRecentContext())
168
+ capture.analysis = analysis
169
+
170
+ // Detect alerts
171
+ const alertKeywords = [
172
+ "error", "crash", "exception", "fatal", "alert", "warning", "failed",
173
+ "ошибка", "краш", "исключение", "фатальная", "предупреждение", "сбой",
174
+ "not responding", "has stopped", "dead", "kill", "terminate",
175
+ "не отвечает", "остановлен", "завершить",
176
+ ]
177
+
178
+ const textLower = (analysis.text || "").toLowerCase()
179
+ const detected = alertKeywords.filter(k => textLower.includes(k))
180
+
181
+ if (detected.length > 0) {
182
+ const alert = {
183
+ id: capture.id,
184
+ timestamp: ts,
185
+ type: detected.join(", "),
186
+ severity: detected.some(k => ["fatal", "crash", "exception", "фатальная", "краш", "исключение"].includes(k)) ? "critical" : "warning",
187
+ description: analysis.text?.slice(0, 500),
188
+ screenshot: imagePath,
189
+ }
190
+ capture.alerts.push(alert)
191
+ this.alerts.push(alert)
192
+ this.state.totalAlerts++
193
+ }
194
+ } catch (err) {
195
+ capture.analysis = { error: err.message }
196
+ }
197
+ }
198
+
199
+ this.history.push(capture)
200
+ this.state.totalCaptures++
201
+ this.save()
202
+
203
+ // Clean old screenshots (keep last 50)
204
+ this.cleanOldScreenshots(50)
205
+
206
+ return { success: true, capture }
207
+ }
208
+
209
+ getRecentContext() {
210
+ const recent = this.history.slice(-5)
211
+ return recent.map(h => ({
212
+ time: h.timestamp,
213
+ analysis: h.analysis?.summary || h.analysis?.text?.slice(0, 200) || "no analysis",
214
+ alerts: h.alerts?.length || 0,
215
+ }))
216
+ }
217
+
218
+ cleanOldScreenshots(keep = 50) {
219
+ try {
220
+ const files = readdirSync(SCREENSHOTS_DIR)
221
+ .filter(f => f.startsWith("screen_") && f.endsWith(".png"))
222
+ .sort()
223
+
224
+ if (files.length > keep) {
225
+ const toDelete = files.slice(0, files.length - keep)
226
+ for (const f of toDelete) {
227
+ try { unlinkSync(join(SCREENSHOTS_DIR, f)) } catch {}
228
+ }
229
+ }
230
+ } catch {}
231
+ }
232
+
233
+ start(intervalMs, visionFn) {
234
+ if (this.state.running) {
235
+ return { success: false, error: "Monitor already running" }
236
+ }
237
+
238
+ this.state.running = true
239
+ this.state.startedAt = new Date().toISOString()
240
+ this.state.interval = intervalMs || 2000
241
+ this.state.pid = process.pid
242
+ this.save()
243
+
244
+ this.intervalId = setInterval(async () => {
245
+ if (!this.state.running) {
246
+ this.stop()
247
+ return
248
+ }
249
+ await this.captureAndAnalyze(visionFn)
250
+ }, this.state.interval)
251
+
252
+ return { success: true, interval: this.state.interval }
253
+ }
254
+
255
+ stop() {
256
+ if (this.intervalId) {
257
+ clearInterval(this.intervalId)
258
+ this.intervalId = null
259
+ }
260
+ this.state.running = false
261
+ this.state.pid = null
262
+ this.save()
263
+ return { success: true }
264
+ }
265
+
266
+ getStatus() {
267
+ const recentAlerts = this.alerts.slice(-10)
268
+ const recentCaptures = this.history.slice(-5)
269
+
270
+ return {
271
+ running: this.state.running,
272
+ startedAt: this.state.startedAt,
273
+ interval: this.state.interval,
274
+ totalCaptures: this.state.totalCaptures,
275
+ totalAlerts: this.state.totalAlerts,
276
+ pid: this.state.pid,
277
+ recentAlerts,
278
+ recentCaptures: recentCaptures.map(c => ({
279
+ time: c.timestamp,
280
+ size: c.sizeKB + "KB",
281
+ summary: c.analysis?.summary || c.analysis?.text?.slice(0, 100) || "analyzing...",
282
+ alertCount: c.alerts?.length || 0,
283
+ })),
284
+ }
285
+ }
286
+
287
+ getAlerts(since) {
288
+ if (since) {
289
+ return this.alerts.filter(a => new Date(a.timestamp) > new Date(since))
290
+ }
291
+ return this.alerts
292
+ }
293
+
294
+ getScreenshotPath() {
295
+ const files = readdirSync(SCREENSHOTS_DIR)
296
+ .filter(f => f.startsWith("screen_") && f.endsWith(".png"))
297
+ .sort()
298
+ return files.length > 0 ? join(SCREENSHOTS_DIR, files[files.length - 1]) : null
299
+ }
300
+
301
+ generateReport() {
302
+ const status = this.getStatus()
303
+ const alertsByType = {}
304
+ for (const a of this.alerts) {
305
+ alertsByType[a.type] = (alertsByType[a.type] || 0) + 1
306
+ }
307
+
308
+ const report = `
309
+ ═══════════════════════════════════════════
310
+ 👁️ SCREEN MONITOR REPORT
311
+ ═══════════════════════════════════════════
312
+
313
+ Status: ${status.running ? "🟢 RUNNING" : "🔴 STOPPED"}
314
+ Started: ${status.startedAt ? new Date(status.startedAt).toLocaleString() : "Never"}
315
+ Interval: every ${status.interval / 1000}s
316
+ Total captures: ${status.totalCaptures}
317
+ Total alerts: ${status.totalAlerts}
318
+
319
+ ${Object.keys(alertsByType).length > 0 ? `
320
+ Alert breakdown:
321
+ ${Object.entries(alertsByType).map(([type, count]) => ` ⚠️ ${type}: ${count}`).join("\n")}
322
+ ` : "No alerts detected."}
323
+
324
+ Recent captures:
325
+ ${status.recentCaptures.map(c => ` [${new Date(c.time).toLocaleTimeString()}] ${c.summary} ${c.alertCount > 0 ? `⚠️ ${c.alertCount} alerts` : "✅"}`).join("\n")}
326
+
327
+ ═══════════════════════════════════════════
328
+ `.trim()
329
+
330
+ return report
331
+ }
332
+ }
333
+
334
+ export default ScreenMonitor
@@ -0,0 +1,5 @@
1
+ {
2
+ "main": "index.mjs",
3
+ "output": "sea-prep.blob",
4
+ "disableExperimentalSEAWarning": true
5
+ }