Compare commits

..
Author SHA1 Message Date
dependabot[bot]andGitHub 45fadcdd2b Bump ruff in /docker/main in the pip-main-minor-patch group
Bumps the pip-main-minor-patch group in /docker/main with 1 update: [ruff](https://github.com/astral-sh/ruff).


Updates `ruff` from 0.17.3 to 0.17.4
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.17.3...0.17.4)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.17.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: pip-main-minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-11-09 13:46:58 +00:00
14 changed files with 62 additions and 234 deletions
+1 -1
View File
@@ -47,7 +47,7 @@ onnxruntime == 1.31.*
# Embeddings
transformers == 5.22.*
# Generative AI
google-genai == 3.0.*
google-genai == 2.34.*
ollama == 0.6.*
openai == 3.46.*
# push notifications
@@ -80,11 +80,6 @@ cp -r /usr/local/nginx/conf/. /tmp/nginx/conf/
set_worker_processes
# A non-root master ignores `user` and warns on every start
if [[ "$runs_as_root" -eq 0 ]]; then
sed -i '/^user root;$/d' /tmp/nginx/conf/nginx.conf
fi
# TLS certs: user-mounted certs at /etc/letsencrypt/live/frigate (documented
# contract) always win; otherwise fall back to a self-signed cert persisted in
# /config/tls, which stays writable under a read-only root filesystem.
@@ -2,7 +2,7 @@
# file, all other path directives follow --prefix and must stay absolute.
daemon off;
# keeps workers root under FRIGATE_RUN_AS_ROOT; the run script strips it otherwise
# ignored by a non-root master; keeps workers root under FRIGATE_RUN_AS_ROOT
user root;
worker_processes auto;
+1 -23
View File
@@ -683,15 +683,6 @@
"title": "FeaturesSection",
"type": "object"
},
"FfmpegSource": {
"enum": [
"default",
"bundled",
"custom"
],
"title": "FfmpegSource",
"type": "string"
},
"FpsBucket": {
"enum": [
"le_5",
@@ -1026,17 +1017,6 @@
"description": "CPU architecture",
"x-public": true
},
"custom_go2rtc": {
"description": "Whether an executable /config/go2rtc build exists",
"title": "Custom Go2Rtc",
"type": "boolean",
"x-public": true
},
"ffmpeg": {
"$ref": "#/$defs/FfmpegSource",
"description": "Configured global ffmpeg.path: the default build, another bundled version, or a custom path",
"x-public": true
},
"image_variant": {
"$ref": "#/$defs/ImageVariant",
"description": "Published image the install runs",
@@ -1074,9 +1054,7 @@
"install_type",
"arch",
"kernel",
"run_as_root",
"custom_go2rtc",
"ffmpeg"
"run_as_root"
],
"title": "InstallSection",
"type": "object"
+1 -22
View File
@@ -6,15 +6,7 @@ import re
from frigate.analytics.collectors.common import closed
from frigate.analytics.context import ReportContext
from frigate.analytics.schema import (
Arch,
FfmpegSource,
ImageVariant,
InstallSection,
InstallType,
)
from frigate.const import CONFIG_DIR, DEFAULT_FFMPEG_VERSION, INCLUDED_FFMPEG_VERSIONS
from frigate.util.config import is_valid_ffmpeg_path
from frigate.analytics.schema import Arch, ImageVariant, InstallSection, InstallType
from frigate.version import VERSION
KERNEL_PATTERN = re.compile(r"^(\d{1,3})\.(\d{1,3})")
@@ -62,17 +54,6 @@ def kernel(release: str) -> str:
return f"{match.group(1)}.{match.group(2)}" if match else "unknown"
def ffmpeg_source(path: str) -> FfmpegSource:
"""Classify the configured ffmpeg.path, applying resolve_ffmpeg_path's alias fallbacks."""
if path.startswith("/") and is_valid_ffmpeg_path(path):
return FfmpegSource.custom
if path != DEFAULT_FFMPEG_VERSION and path in INCLUDED_FFMPEG_VERSIONS:
return FfmpegSource.bundled
return FfmpegSource.default
def collect(ctx: ReportContext) -> InstallSection:
"""Describe the Frigate version, image, install method, and platform."""
return InstallSection(
@@ -82,6 +63,4 @@ def collect(ctx: ReportContext) -> InstallSection:
arch=arch(platform.machine()),
kernel=kernel(platform.release()),
run_as_root=os.geteuid() == 0,
custom_go2rtc=os.access(os.path.join(CONFIG_DIR, "go2rtc"), os.X_OK),
ffmpeg=ffmpeg_source(ctx.config.ffmpeg.path),
)
-10
View File
@@ -47,12 +47,6 @@ class Arch(StrEnum):
other = "other"
class FfmpegSource(StrEnum):
default = "default"
bundled = "bundled"
custom = "custom"
class GpuVendor(StrEnum):
intel = "intel"
amd = "amd"
@@ -207,10 +201,6 @@ class InstallSection(AnalyticsModel):
"Host kernel as major.minor", pattern=r"^(\d{1,3}\.\d{1,3}|unknown)$"
)
run_as_root: bool = metric("Whether the main process runs as root")
custom_go2rtc: bool = metric("Whether an executable /config/go2rtc build exists")
ffmpeg: FfmpegSource = metric(
"Configured global ffmpeg.path: the default build, another bundled version, or a custom path"
)
class GpuInfo(AnalyticsModel):
@@ -12,7 +12,6 @@ from frigate.analytics.collectors.common import closed, histogram, rate
from frigate.analytics.schema import (
Arch,
DecodeFamily,
FfmpegSource,
GpuVendor,
HardwareKey,
ImageVariant,
@@ -57,36 +56,6 @@ class TestInstallCollector(unittest.TestCase):
self.assertEqual(section.arch, Arch.aarch64)
self.assertEqual(section.kernel, "6.8")
self.assertFalse(section.run_as_root)
self.assertEqual(section.ffmpeg, FfmpegSource.default)
def test_ffmpeg_source_follows_path_resolution(self):
with (
patch.object(install, "DEFAULT_FFMPEG_VERSION", "8.0"),
patch.object(install, "INCLUDED_FFMPEG_VERSIONS", ["8.0", "7.0"]),
):
self.assertEqual(install.ffmpeg_source("default"), FfmpegSource.default)
self.assertEqual(install.ffmpeg_source("8.0"), FfmpegSource.default)
self.assertEqual(install.ffmpeg_source("4.4"), FfmpegSource.default)
self.assertEqual(install.ffmpeg_source("7.0"), FfmpegSource.bundled)
self.assertEqual(
install.ffmpeg_source("/config/custom-ffmpeg"), FfmpegSource.custom
)
self.assertEqual(
install.ffmpeg_source("/config/a b; rm"), FfmpegSource.default
)
def test_custom_go2rtc_needs_an_executable_binary(self):
with tempfile.TemporaryDirectory() as config_dir:
binary = os.path.join(config_dir, "go2rtc")
with patch.object(install, "CONFIG_DIR", config_dir):
self.assertFalse(install.collect(make_context()).custom_go2rtc)
open(binary, "w").close()
self.assertFalse(install.collect(make_context()).custom_go2rtc)
os.chmod(binary, 0o755)
self.assertTrue(install.collect(make_context()).custom_go2rtc)
def test_image_variant_is_dev_when_unset_and_other_when_unknown(self):
self.assertEqual(install.image_variant(None), ImageVariant.dev)
-2
View File
@@ -25,8 +25,6 @@ INSTALL = InstallSection(
arch="x86_64",
kernel="6.8",
run_as_root=False,
custom_go2rtc=False,
ffmpeg="default",
)
-37
View File
@@ -1,6 +1,5 @@
"""Tests for migrating detectors and model into the models list."""
import errno
import logging
import os
import tempfile
@@ -241,42 +240,6 @@ class TestMigrateConfigFile(unittest.TestCase):
with open(self.config_file) as f:
return YAML().load(f)
def test_a_failed_write_leaves_the_original_config(self):
original = "mqtt:\n enabled: false\ncameras: {}\n"
with open(self.config_file, "w") as f:
f.write(original)
with (
patch.object(YAML, "dump", side_effect=RuntimeError),
self.assertRaises(RuntimeError),
):
migrate_frigate_config(self.config_file)
with open(self.config_file) as f:
self.assertEqual(f.read(), original)
def test_a_file_bind_mount_is_written_in_place(self):
with patch(
"frigate.util.config.os.replace",
side_effect=OSError(errno.EBUSY, "Device or resource busy"),
):
migrated = self._migrate("mqtt:\n enabled: false\ncameras: {}\n")
self.assertEqual(migrated["version"], CURRENT_CONFIG_VERSION)
self.assertFalse(os.path.exists(f"{self.config_file}.tmp"))
def test_a_symlinked_config_migrates_its_target(self):
target = os.path.join(self.temp_dir.name, "frigate.yml")
with open(target, "w") as f:
f.write("mqtt:\n enabled: false\ncameras: {}\n")
os.symlink(target, self.config_file)
migrate_frigate_config(self.config_file)
self.assertTrue(os.path.islink(self.config_file))
with open(target) as f:
self.assertEqual(YAML().load(f)["version"], CURRENT_CONFIG_VERSION)
def test_migrates_a_config_already_stamped_with_the_current_version(self):
# 0.19 is unreleased, so a dev config can be current and still use
# the pre-models keys
-30
View File
@@ -321,36 +321,6 @@ class TestLighterANE(unittest.TestCase):
ane.assert_not_called()
class TestTensorRTProvider(unittest.TestCase):
def _trt_options(self, env):
with (
patch.object(
model_util.ort,
"get_available_providers",
return_value=["TensorrtExecutionProvider", "CPUExecutionProvider"],
),
patch.object(model_util.os, "makedirs"),
patch.dict(os.environ, env, clear=False),
):
if "USE_FP16" not in env:
os.environ.pop("USE_FP16", None)
providers, options = model_util.get_ort_providers(device="Tensorrt")
return options[providers.index("TensorrtExecutionProvider")]
def test_fp16_is_disabled_by_default(self):
self.assertFalse(self._trt_options({})["trt_fp16_enable"])
def test_use_fp16_enables_fp16(self):
for value in ("true", "True", "TRUE"):
with self.subTest(value=value):
options = self._trt_options({"USE_FP16": value})
self.assertTrue(options["trt_fp16_enable"])
def test_use_fp16_false_keeps_fp16_disabled(self):
self.assertFalse(self._trt_options({"USE_FP16": "False"})["trt_fp16_enable"])
class TestMIGraphX(unittest.TestCase):
"""AMD's MIGraphX plugin provider, selected through its devices in the ROCm image."""
+18 -33
View File
@@ -1,8 +1,6 @@
"""configuration utils."""
import asyncio
import contextlib
import errno
import ipaddress
import logging
import os
@@ -214,28 +212,6 @@ def find_config_file() -> str:
return config_path
def _write_config(config_file: str, yaml: YAML, config: dict[str, Any]) -> None:
config_file = os.path.realpath(config_file)
st = os.stat(config_file)
tmp_file = f"{config_file}.tmp"
with open(tmp_file, "w") as f:
yaml.dump(config, f)
os.chmod(tmp_file, st.st_mode)
with contextlib.suppress(PermissionError):
os.chown(tmp_file, st.st_uid, st.st_gid)
try:
os.replace(tmp_file, config_file)
except OSError as e:
if e.errno != errno.EBUSY:
raise
# a file bind mount can't be renamed over, so write it in place
shutil.copyfile(tmp_file, config_file)
os.remove(tmp_file)
def migrate_frigate_config(config_file: str):
"""handle migrating the frigate config."""
logger.info("Checking if frigate config needs migration...")
@@ -283,7 +259,8 @@ def migrate_frigate_config(config_file: str):
if previous_version < "0.14":
logger.info(f"Migrating frigate config from {previous_version} to 0.14...")
new_config = migrate_014(new_config)
_write_config(config_file, yaml, new_config)
with open(config_file, "w") as f:
yaml.dump(new_config, f)
previous_version = "0.14"
logger.info("Migrating export file names...")
@@ -300,48 +277,56 @@ def migrate_frigate_config(config_file: str):
if previous_version < "0.15-0":
logger.info(f"Migrating frigate config from {previous_version} to 0.15-0...")
new_config = migrate_015_0(new_config)
_write_config(config_file, yaml, new_config)
with open(config_file, "w") as f:
yaml.dump(new_config, f)
previous_version = "0.15-0"
if previous_version < "0.15-1":
logger.info(f"Migrating frigate config from {previous_version} to 0.15-1...")
new_config = migrate_015_1(new_config)
_write_config(config_file, yaml, new_config)
with open(config_file, "w") as f:
yaml.dump(new_config, f)
previous_version = "0.15-1"
if previous_version < "0.16-0":
logger.info(f"Migrating frigate config from {previous_version} to 0.16-0...")
new_config = migrate_016_0(new_config)
_write_config(config_file, yaml, new_config)
with open(config_file, "w") as f:
yaml.dump(new_config, f)
previous_version = "0.16-0"
if previous_version < "0.17-0":
logger.info(f"Migrating frigate config from {previous_version} to 0.17-0...")
new_config = migrate_017_0(new_config)
_write_config(config_file, yaml, new_config)
with open(config_file, "w") as f:
yaml.dump(new_config, f)
previous_version = "0.17-0"
if previous_version < "0.18-0":
logger.info(f"Migrating frigate config from {previous_version} to 0.18-0...")
new_config = migrate_018_0(new_config)
_write_config(config_file, yaml, new_config)
with open(config_file, "w") as f:
yaml.dump(new_config, f)
previous_version = "0.18-0"
if previous_version < "0.19-0":
logger.info(f"Migrating frigate config from {previous_version} to 0.19-0...")
new_config = migrate_019_0(new_config)
_write_config(config_file, yaml, new_config)
with open(config_file, "w") as f:
yaml.dump(new_config, f)
previous_version = "0.19-0"
if needs_models:
logger.info("Migrating frigate detectors and model to models...")
new_config = migrate_models(new_config)
_write_config(config_file, yaml, new_config)
with open(config_file, "w") as f:
yaml.dump(new_config, f)
if needs_detector_rename:
logger.info("Migrating renamed frigate detectors...")
new_config = rename_hailo_detector(new_config)
_write_config(config_file, yaml, new_config)
with open(config_file, "w") as f:
yaml.dump(new_config, f)
logger.info("Finished frigate config migration...")
+3 -2
View File
@@ -318,6 +318,7 @@ def post_process_yolox(
def get_ort_providers(
force_cpu: bool = False,
device: str | None = "AUTO",
requires_fp16: bool = False,
) -> tuple[list[str], list[dict[str, Any]]]:
if force_cpu:
return (
@@ -356,8 +357,8 @@ def get_ort_providers(
options.append(
{
"device_id": device_id,
"trt_fp16_enable": os.environ.get("USE_FP16", "False").lower()
== "true",
"trt_fp16_enable": requires_fp16
and os.environ.get("USE_FP16", "True") != "False",
"trt_timing_cache_enable": True,
"trt_engine_cache_enable": True,
"trt_timing_cache_path": os.path.join(
+32 -32
View File
@@ -45,15 +45,15 @@
"copy-to-clipboard": "^4.0.2",
"date-fns": "^4.4.0",
"date-fns-tz": "^3.2.0",
"framer-motion": "^14.10.0",
"framer-motion": "^14.9.1",
"hls.js": "^1.7.4",
"i18next": "^26.7.2",
"i18next": "^26.7.1",
"i18next-http-backend": "^4.0.10",
"idb-keyval": "^6.3.0",
"js-yaml": "^5.5.0",
"konva": "^10.9.1",
"lodash": "^4.18.1",
"lucide-react": "^1.70.0",
"lucide-react": "^1.69.0",
"monaco-yaml": "^5.5.1",
"next-themes": "^0.4.6",
"nosleep.js": "^0.12.0",
@@ -65,7 +65,7 @@
"react-dropzone": "^20.1.4",
"react-grid-layout": "^2.3.0",
"react-hook-form": "^7.91.0",
"react-i18next": "^17.1.13",
"react-i18next": "^17.1.12",
"react-icons": "^5.7.0",
"react-konva": "^19.3.2",
"react-markdown": "^10.1.0",
@@ -87,7 +87,7 @@
},
"devDependencies": {
"@eslint/js": "^10.0.1",
"@playwright/test": "^1.65.0",
"@playwright/test": "^1.64.1",
"@types/js-yaml": "^4.0.9",
"@types/lodash": "^4.17.27",
"@types/node": "^26.6.6",
@@ -1714,13 +1714,13 @@
}
},
"node_modules/@playwright/test": {
"version": "1.65.0",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.65.0.tgz",
"integrity": "sha512-iGURLGuKDLakSEl7Pgfv8h7f+XLT+V861Wfhz0zlEl5nyFuKUopdkFBPKqTllTUp06aOwPuH8iuUEb3yp3MpbQ==",
"version": "1.64.1",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.64.1.tgz",
"integrity": "sha512-IaYGml/nSOiZWROfPtuIL7neuu9qDOZ3TNvNljUIrhDMxiGTgPjzj/g9p9RxpS2tSepPDRY+UwAaEeiKtUvIAg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"playwright": "1.65.0"
"playwright": "1.64.1"
},
"bin": {
"playwright": "cli.js"
@@ -5596,12 +5596,12 @@
}
},
"node_modules/framer-motion": {
"version": "14.10.0",
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-14.10.0.tgz",
"integrity": "sha512-e8MjIet+IJKohYxBj8TAk9Mg5cD0HiOX87qde1YTPL67gI2ao074O6yBtQnIcWCk+bTX7XX4litepufLiYPrLg==",
"version": "14.9.1",
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-14.9.1.tgz",
"integrity": "sha512-WDWNT2ixHdmpvGg02BZWI/SWwRYzPiMUf4aIkTBgrxxD8RYFdZO3fCM4pnLMo6j8mUpj0+BuJRHQBChI4v3Anw==",
"license": "MIT",
"dependencies": {
"motion-dom": "14.10.0",
"motion-dom": "14.9.1",
"motion-utils": "14.7.0",
"tslib": "^2.4.0"
},
@@ -6009,9 +6009,9 @@
}
},
"node_modules/i18next": {
"version": "26.7.2",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.7.2.tgz",
"integrity": "sha512-RsOY3BeaCDdkk52NeJSFAXELQ2rQXBO/tOub6L8ue2ICPfR/FRDWDOfEDg4xMPd1SqO5goVYQ6i72qWEUB/PPw==",
"version": "26.7.1",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.7.1.tgz",
"integrity": "sha512-cX+3RRVczel/V2kCMTACckSGSpqgtWYEA6beXNYVms7dOQiHojdPYHD26lT4IKimNeoGWrLvtPgjftbRvmZJVw==",
"funding": [
{
"type": "individual",
@@ -6996,9 +6996,9 @@
}
},
"node_modules/lucide-react": {
"version": "1.70.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.70.0.tgz",
"integrity": "sha512-gCTPPN1MlQUBtUgdsUv+0CAUj+X8hifRUiRBw4E5v7lvDIOIpx0EZezdGQMSimS8pKA6esvullJub4GYr0mCHA==",
"version": "1.69.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.69.0.tgz",
"integrity": "sha512-UTFECm4yEgkgMN0kfLuxWcmlk+4u02Jrqehgk3ZXRx/Ud68OpP7hjkp67bvkBHmIpMaZCIveF1QDYeupO7XmYQ==",
"license": "ISC",
"peerDependencies": {
"@types/react": "*",
@@ -8073,9 +8073,9 @@
}
},
"node_modules/motion-dom": {
"version": "14.10.0",
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-14.10.0.tgz",
"integrity": "sha512-k0LwJZ1R5xCvqrScszO4ywuZP52lRcT3QO0IUovgczom9ZHb0BaRLOX6M2O40q7TrSLvzX/fIHHmDm8TUMt3fg==",
"version": "14.9.1",
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-14.9.1.tgz",
"integrity": "sha512-2eCCGXH2Yv09lM8GHK3TdfChrcvHxzVY19LD9VraoHEaQl5+PuGnTNnmJaBAR+5MdxUVdsLFXygFJjR9RwRSxw==",
"license": "MIT",
"dependencies": {
"motion-utils": "14.7.0"
@@ -8537,13 +8537,13 @@
}
},
"node_modules/playwright": {
"version": "1.65.0",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.65.0.tgz",
"integrity": "sha512-F3AMWcR44qMBt4kq+6Kb6mX7bjGXshktKFOPULd7reED6ZJWevjbNRqysP7q+AATE9kdPEZBibex1BYsvpVoeA==",
"version": "1.64.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.64.1.tgz",
"integrity": "sha512-HCrVhHr5QQuwYoswEUGTb7gGp522yflbv/ST8nF4sFWGuLjQCt17Q/EubpGGSNKYn1tsTCPZxqHhHCfVURu7UA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"playwright-core": "1.65.0"
"playwright-core": "1.64.1"
},
"bin": {
"playwright": "cli.js"
@@ -8553,9 +8553,9 @@
}
},
"node_modules/playwright-core": {
"version": "1.65.0",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.65.0.tgz",
"integrity": "sha512-vNSKgH6YqtN7cdT/L334zo0a+YwkrpicyrHJlWWPIm/Q+Nn2SWInil01oT0mbu96U4GgoRtCYQD9CzJQgju+lA==",
"version": "1.64.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.64.1.tgz",
"integrity": "sha512-BC4s8y6SEVA6Q1rSxZTto8hI1KUI3xXlHGZgvGqP4IqPdI/a6FX9H29IDNz7vKo9l21b6LfYosScPL6M3xxyDQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -9077,9 +9077,9 @@
}
},
"node_modules/react-i18next": {
"version": "17.1.13",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-17.1.13.tgz",
"integrity": "sha512-ZxhOSlyKSKPtbUNPLwYMmE3w3bhoc0jaZJZ6bc7wGOT6cLbrbs//6m01HxCLtFdSjHvFpwFwoPhxxzIlHSs9cw==",
"version": "17.1.12",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-17.1.12.tgz",
"integrity": "sha512-Gf8riCKF/EmqQ8I1g0N5pJOLvJCkAXGAEkzOuRNHc/sBGL3dfE3WZ7+sDLrUo/kw/xdug3g48jo7M+s/SKf0HQ==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.29.7",
+5 -5
View File
@@ -57,15 +57,15 @@
"copy-to-clipboard": "^4.0.2",
"date-fns": "^4.4.0",
"date-fns-tz": "^3.2.0",
"framer-motion": "^14.10.0",
"framer-motion": "^14.9.1",
"hls.js": "^1.7.4",
"i18next": "^26.7.2",
"i18next": "^26.7.1",
"i18next-http-backend": "^4.0.10",
"idb-keyval": "^6.3.0",
"js-yaml": "^5.5.0",
"konva": "^10.9.1",
"lodash": "^4.18.1",
"lucide-react": "^1.70.0",
"lucide-react": "^1.69.0",
"monaco-yaml": "^5.5.1",
"next-themes": "^0.4.6",
"nosleep.js": "^0.12.0",
@@ -77,7 +77,7 @@
"react-dropzone": "^20.1.4",
"react-grid-layout": "^2.3.0",
"react-hook-form": "^7.91.0",
"react-i18next": "^17.1.13",
"react-i18next": "^17.1.12",
"react-icons": "^5.7.0",
"react-konva": "^19.3.2",
"react-markdown": "^10.1.0",
@@ -99,7 +99,7 @@
},
"devDependencies": {
"@eslint/js": "^10.0.1",
"@playwright/test": "^1.65.0",
"@playwright/test": "^1.64.1",
"@types/js-yaml": "^4.0.9",
"@types/lodash": "^4.17.27",
"@types/node": "^26.6.6",