@camstack/addon-model-studio 1.1.293 → 1.1.295

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 (20) hide show
  1. package/THIRD_PARTY_MODELS.md +2 -2
  2. package/dist/{MotionZonesSettings-DrHyXG0G.mjs → MotionZonesSettings-DOhuE4t6.mjs} +2 -2
  3. package/dist/{PrivacyMaskSettings-CuqGSOYk.mjs → PrivacyMaskSettings-BtQIysUm.mjs} +4 -4
  4. package/dist/{SceneMonitorEditor-_wt-7NOB.mjs → SceneMonitorEditor-B4cEP3UH.mjs} +3 -3
  5. package/dist/_stub.js +155 -155
  6. package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-D1kg1qk9.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-DNRDIeO2.mjs} +4 -4
  7. package/dist/_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CDZyIXC0.mjs +26 -0
  8. package/dist/{hostInit-CqUjCpJe.mjs → hostInit-DLBoEjee.mjs} +3 -3
  9. package/dist/model-studio.addon.js +2257 -261
  10. package/dist/model-studio.addon.mjs +2256 -260
  11. package/dist/{player-overlays-IswZiT1v.mjs → player-overlays-BVHDRE8f.mjs} +1 -1
  12. package/dist/remoteEntry.js +1 -1
  13. package/dist/{responsive-BRDOoNTu.mjs → responsive-CI-NtcQi.mjs} +1 -1
  14. package/dist/{scene-monitor-copy-BLrlOdpo.mjs → scene-monitor-copy-CvzuJJ8Z.mjs} +1 -1
  15. package/dist/{square-CqxajgGh.mjs → square-CsljmL2M.mjs} +1 -1
  16. package/dist/{trash-2-B67pP3l-.mjs → trash-2-DwX9K1LA.mjs} +1 -1
  17. package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-DeT4IssS.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-Bu2vRo0B.mjs} +1 -1
  18. package/package.json +1 -1
  19. package/python/__tests__/test_calibration.py +3 -3
  20. package/dist/_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BPZnyWUq.mjs +0 -26
@@ -32,12 +32,12 @@ let node_path = require("node:path");
32
32
  node_path = __toESM(node_path);
33
33
  let _camstack_system_addon_utils = require("@camstack/system/addon-utils");
34
34
  let node_fs_promises = require("node:fs/promises");
35
- //#region src/scrypted/scrypted-yolo-manifest-data.json
36
- var scrypted_yolo_manifest_data_default = /*#__PURE__*/ JSON.parse("[{\"id\":\"scrypted-yolov9t-relu-coreml\",\"label\":\"Scrypted YOLOv9T ReLU CoreML\",\"family\":\"yolov9t\",\"variant\":\"relu\",\"format\":\"coreml\",\"precision\":\"fp16\",\"files\":[{\"relativePath\":\"coreml/scrypted_yolov9t_relu/scrypted_yolov9t_relu.mlpackage/Manifest.json\",\"size\":617,\"sha256\":\"0a8733949d77e3204dba6418e81a11a8cc177015711457ce2c171266f23382d6\"},{\"relativePath\":\"coreml/scrypted_yolov9t_relu/scrypted_yolov9t_relu.mlpackage/Data/com.apple.CoreML/model.mlmodel\",\"size\":322229,\"sha256\":\"f5a62f196f1e72a84efa1637119dffb6501621af9cf6f867bc76b4b59c9242a0\"},{\"relativePath\":\"coreml/scrypted_yolov9t_relu/scrypted_yolov9t_relu.mlpackage/Data/com.apple.CoreML/weights/weight.bin\",\"size\":3797160,\"sha256\":\"b994419b8b68cfd6b89c3c6f3fe6b37458c86cc1d87fcca3df5034476a99dd38\"}],\"sizeMB\":4.12},{\"id\":\"scrypted-yolov9t-relu-onnx\",\"label\":\"Scrypted YOLOv9T ReLU ONNX\",\"family\":\"yolov9t\",\"variant\":\"relu\",\"format\":\"onnx\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"onnx/scrypted_yolov9t_relu/scrypted_yolov9t_relu.onnx\",\"size\":8499266,\"sha256\":\"3f11ea2071b27c285b58c16636a44d6a0a27bdd1ca8b64112dfadabd39cfea47\"}],\"sizeMB\":8.5},{\"id\":\"scrypted-yolov9t-relu-test-coreml\",\"label\":\"Scrypted YOLOv9T ReLU test CoreML\",\"family\":\"yolov9t\",\"variant\":\"relu_test\",\"format\":\"coreml\",\"precision\":\"fp16\",\"files\":[{\"relativePath\":\"coreml/scrypted_yolov9t_relu_test/scrypted_yolov9t_relu_test.mlpackage/Manifest.json\",\"size\":617,\"sha256\":\"a5e0128b643f1a66f3e07d4b332f9ccbca97ccab75651c794f0b9f1fb41c8491\"},{\"relativePath\":\"coreml/scrypted_yolov9t_relu_test/scrypted_yolov9t_relu_test.mlpackage/Data/com.apple.CoreML/model.mlmodel\",\"size\":322229,\"sha256\":\"79f4f647f2a0c79db3b560c84251b48c7ba7cbe9c1fecc9674d1a603a389dfa3\"},{\"relativePath\":\"coreml/scrypted_yolov9t_relu_test/scrypted_yolov9t_relu_test.mlpackage/Data/com.apple.CoreML/weights/weight.bin\",\"size\":3797160,\"sha256\":\"72efc9dc6af9241b5e5ee7de24a4f55741f6425d0e279d797f0f223e3d355f84\"}],\"sizeMB\":4.12},{\"id\":\"scrypted-yolov9t-relu-test-onnx\",\"label\":\"Scrypted YOLOv9T ReLU test ONNX\",\"family\":\"yolov9t\",\"variant\":\"relu_test\",\"format\":\"onnx\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"onnx/scrypted_yolov9t_relu_test/scrypted_yolov9t_relu_test.onnx\",\"size\":8499266,\"sha256\":\"d20aa0e6923a3af7f5e84e3a6d28fb00e8ecd592e3225f986f93bd34b634e2f8\"}],\"sizeMB\":8.5},{\"id\":\"scrypted-yolov9s-relu-coreml\",\"label\":\"Scrypted YOLOv9S ReLU CoreML\",\"family\":\"yolov9s\",\"variant\":\"relu\",\"format\":\"coreml\",\"precision\":\"fp16\",\"files\":[{\"relativePath\":\"coreml/scrypted_yolov9s_relu/scrypted_yolov9s_relu.mlpackage/Manifest.json\",\"size\":617,\"sha256\":\"3bcdb820b82f1e89266f2d11bae1604d3ee4ca6d11dc5bd5c57055ff4157e9f3\"},{\"relativePath\":\"coreml/scrypted_yolov9s_relu/scrypted_yolov9s_relu.mlpackage/Data/com.apple.CoreML/model.mlmodel\",\"size\":322664,\"sha256\":\"9a9c3c9cbca406ec2f0418ec867ed6b878ec6d02c16636d30e0bbd83d2ff7c40\"},{\"relativePath\":\"coreml/scrypted_yolov9s_relu/scrypted_yolov9s_relu.mlpackage/Data/com.apple.CoreML/weights/weight.bin\",\"size\":14190120,\"sha256\":\"fd51eda58a993997268f6a2e424b536ba173207ad7974ab8bee2a8ff76d52dab\"}],\"sizeMB\":14.51},{\"id\":\"scrypted-yolov9s-relu-onnx\",\"label\":\"Scrypted YOLOv9S ReLU ONNX\",\"family\":\"yolov9s\",\"variant\":\"relu\",\"format\":\"onnx\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"onnx/scrypted_yolov9s_relu/scrypted_yolov9s_relu.onnx\",\"size\":29287339,\"sha256\":\"ca0b5bd98d5f59eb2029c6cb5129d53af59873f62a317a028beda463bbb96399\"}],\"sizeMB\":29.29},{\"id\":\"scrypted-yolov9s-relu-test-coreml\",\"label\":\"Scrypted YOLOv9S ReLU test CoreML\",\"family\":\"yolov9s\",\"variant\":\"relu_test\",\"format\":\"coreml\",\"precision\":\"fp16\",\"files\":[{\"relativePath\":\"coreml/scrypted_yolov9s_relu_test/scrypted_yolov9s_relu_test.mlpackage/Manifest.json\",\"size\":617,\"sha256\":\"e2d24de0ce7e8573f19572029765e55abc714f36a85175ad7fcb95c001a76653\"},{\"relativePath\":\"coreml/scrypted_yolov9s_relu_test/scrypted_yolov9s_relu_test.mlpackage/Data/com.apple.CoreML/model.mlmodel\",\"size\":322664,\"sha256\":\"186b147cdfd15c5ed7a381ec3a426a22cee0b5c52d56f14efd26da06357f5cb0\"},{\"relativePath\":\"coreml/scrypted_yolov9s_relu_test/scrypted_yolov9s_relu_test.mlpackage/Data/com.apple.CoreML/weights/weight.bin\",\"size\":14190120,\"sha256\":\"e50651924c2cbffd56008a8953569e66c3de69f21807fcf7d825390ce30f21f8\"}],\"sizeMB\":14.51},{\"id\":\"scrypted-yolov9s-relu-test-onnx\",\"label\":\"Scrypted YOLOv9S ReLU test ONNX\",\"family\":\"yolov9s\",\"variant\":\"relu_test\",\"format\":\"onnx\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"onnx/scrypted_yolov9s_relu_test/scrypted_yolov9s_relu_test.onnx\",\"size\":29287339,\"sha256\":\"115ddb83333762a0f2599421335678696454a5c3571ade5df9bac8e9cb5fb4cf\"}],\"sizeMB\":29.29},{\"id\":\"scrypted-yolov9m-relu-coreml\",\"label\":\"Scrypted YOLOv9M ReLU CoreML\",\"family\":\"yolov9m\",\"variant\":\"relu\",\"format\":\"coreml\",\"precision\":\"fp16\",\"files\":[{\"relativePath\":\"coreml/scrypted_yolov9m_relu/scrypted_yolov9m_relu.mlpackage/Manifest.json\",\"size\":617,\"sha256\":\"c548c6e1ff768b2b01bd71e230aa712a1635ae2baa30e0369557a42fc531ecbf\"},{\"relativePath\":\"coreml/scrypted_yolov9m_relu/scrypted_yolov9m_relu.mlpackage/Data/com.apple.CoreML/model.mlmodel\",\"size\":247061,\"sha256\":\"1c40e02fc2a2559cb906ea6cd9da9c730d4a78f5019290cbb38d2fcaae379fe7\"},{\"relativePath\":\"coreml/scrypted_yolov9m_relu/scrypted_yolov9m_relu.mlpackage/Data/com.apple.CoreML/weights/weight.bin\",\"size\":39880616,\"sha256\":\"4cf938e5bfcc3ee1644813e4eb4702a7de450cc0581df94c719cf43d0ed2e408\"}],\"sizeMB\":40.13},{\"id\":\"scrypted-yolov9m-relu-onnx\",\"label\":\"Scrypted YOLOv9M ReLU ONNX\",\"family\":\"yolov9m\",\"variant\":\"relu\",\"format\":\"onnx\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"onnx/scrypted_yolov9m_relu/scrypted_yolov9m_relu.onnx\",\"size\":80380404,\"sha256\":\"e7a81fb33224a0105d2a0a594c3fa43c398c361de623f1d14156ae826e7312d5\"}],\"sizeMB\":80.38},{\"id\":\"scrypted-yolov9m-relu-test-coreml\",\"label\":\"Scrypted YOLOv9M ReLU test CoreML\",\"family\":\"yolov9m\",\"variant\":\"relu_test\",\"format\":\"coreml\",\"precision\":\"fp16\",\"files\":[{\"relativePath\":\"coreml/scrypted_yolov9m_relu_test/scrypted_yolov9m_relu_test.mlpackage/Manifest.json\",\"size\":617,\"sha256\":\"8e2684b286d02b4bdf9db1027c84cb89bf8e4830cfb58269f3ec457c5a010650\"},{\"relativePath\":\"coreml/scrypted_yolov9m_relu_test/scrypted_yolov9m_relu_test.mlpackage/Data/com.apple.CoreML/model.mlmodel\",\"size\":247061,\"sha256\":\"53d5946e74b13b15c5f8616081c9f15e8a95a5df3d5b45b830fc5a7f49561c16\"},{\"relativePath\":\"coreml/scrypted_yolov9m_relu_test/scrypted_yolov9m_relu_test.mlpackage/Data/com.apple.CoreML/weights/weight.bin\",\"size\":39880616,\"sha256\":\"69774bf0032c37707601b8cdc1e1820dbd9f8288eb5d6f3879618a5d34ff5199\"}],\"sizeMB\":40.13},{\"id\":\"scrypted-yolov9m-relu-test-onnx\",\"label\":\"Scrypted YOLOv9M ReLU test ONNX\",\"family\":\"yolov9m\",\"variant\":\"relu_test\",\"format\":\"onnx\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"onnx/scrypted_yolov9m_relu_test/scrypted_yolov9m_relu_test.onnx\",\"size\":80380404,\"sha256\":\"8bb054f099295909ec518e2a6598d63db24d3f90edc8105a0f016903f2a205a2\"}],\"sizeMB\":80.38},{\"id\":\"scrypted-yolov9c-relu-coreml\",\"label\":\"Scrypted YOLOv9C ReLU CoreML\",\"family\":\"yolov9c\",\"variant\":\"relu\",\"format\":\"coreml\",\"precision\":\"fp16\",\"files\":[{\"relativePath\":\"coreml/scrypted_yolov9c_relu/scrypted_yolov9c_relu.mlpackage/Manifest.json\",\"size\":617,\"sha256\":\"813a306ebd69cabfd31f00434f5a961feeca7d237833f3e11805dcf4ad120ba9\"},{\"relativePath\":\"coreml/scrypted_yolov9c_relu/scrypted_yolov9c_relu.mlpackage/Data/com.apple.CoreML/model.mlmodel\",\"size\":263210,\"sha256\":\"862f082619075e470738306b0ff0a37ae70a7d08e684ca6a6dfa1971d404e0c3\"},{\"relativePath\":\"coreml/scrypted_yolov9c_relu/scrypted_yolov9c_relu.mlpackage/Data/com.apple.CoreML/weights/weight.bin\",\"size\":50489960,\"sha256\":\"ed89747e58943758e2a87221d1d404f6a4466cbc039c3c6f96e327cadc403d27\"}],\"sizeMB\":50.75},{\"id\":\"scrypted-yolov9c-relu-onnx\",\"label\":\"Scrypted YOLOv9C ReLU ONNX\",\"family\":\"yolov9c\",\"variant\":\"relu\",\"format\":\"onnx\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"onnx/scrypted_yolov9c_relu/scrypted_yolov9c_relu.onnx\",\"size\":101631962,\"sha256\":\"b9372c4428daf4cd944c114b1e80d1a9ff0487d743e53a77216a051cfbef7116\"}],\"sizeMB\":101.63},{\"id\":\"scrypted-yolov9c-relu-test-coreml\",\"label\":\"Scrypted YOLOv9C ReLU test CoreML\",\"family\":\"yolov9c\",\"variant\":\"relu_test\",\"format\":\"coreml\",\"precision\":\"fp16\",\"files\":[{\"relativePath\":\"coreml/scrypted_yolov9c_relu_test/scrypted_yolov9c_relu_test.mlpackage/Manifest.json\",\"size\":617,\"sha256\":\"966ef82a93cb0ccf1036a8c9729c065fd372fa9590a97d0945e581cc674f7ad2\"},{\"relativePath\":\"coreml/scrypted_yolov9c_relu_test/scrypted_yolov9c_relu_test.mlpackage/Data/com.apple.CoreML/model.mlmodel\",\"size\":263210,\"sha256\":\"08718ecd3e9552d21a702bd8df60911cad0eec7b2ae382466809550f14634711\"},{\"relativePath\":\"coreml/scrypted_yolov9c_relu_test/scrypted_yolov9c_relu_test.mlpackage/Data/com.apple.CoreML/weights/weight.bin\",\"size\":50489960,\"sha256\":\"fe5936b9430ab4c87f30b148220131d6ec998b2377223d033e2fa2a00e60aada\"}],\"sizeMB\":50.75},{\"id\":\"scrypted-yolov9c-relu-test-onnx\",\"label\":\"Scrypted YOLOv9C ReLU test ONNX\",\"family\":\"yolov9c\",\"variant\":\"relu_test\",\"format\":\"onnx\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"onnx/scrypted_yolov9c_relu_test/scrypted_yolov9c_relu_test.onnx\",\"size\":101631962,\"sha256\":\"2f4e2031e8efb4cbc871594338b2e875d78ab4af3ee0258d253273b1aac84742\"}],\"sizeMB\":101.63},{\"id\":\"scrypted-yolov9t-relu-openvino-fp32\",\"label\":\"Scrypted YOLOv9T ReLU OpenVINO FP32\",\"family\":\"yolov9t\",\"variant\":\"relu\",\"format\":\"openvino\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9t_relu/best-converted.xml\",\"size\":628222,\"sha256\":\"01b5a9d02a0f281e1aaf4860e1b0ed3a7f16b9d78975be8ff985ae0ee283d877\"},{\"relativePath\":\"openvino/scrypted_yolov9t_relu/best-converted.bin\",\"size\":7542204,\"sha256\":\"4fe9ce8dbdf94514fdd450cbfc907f257153e4898a0c1489a44e4912d8e32cc7\"}],\"sizeMB\":8.17},{\"id\":\"scrypted-yolov9s-relu-openvino-fp32\",\"label\":\"Scrypted YOLOv9S ReLU OpenVINO FP32\",\"family\":\"yolov9s\",\"variant\":\"relu\",\"format\":\"openvino\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9s_relu/best-converted.xml\",\"size\":629249,\"sha256\":\"5b4a229bf7229425698b63bd065a403e440a6151a6ddff0034867659cc4a480d\"},{\"relativePath\":\"openvino/scrypted_yolov9s_relu/best-converted.bin\",\"size\":28329724,\"sha256\":\"c030bd219208ea94082578c81f383d4ef9ec45d7150eec1c2c2ff2569cf49b35\"}],\"sizeMB\":28.96},{\"id\":\"scrypted-yolov9m-relu-openvino-fp32\",\"label\":\"Scrypted YOLOv9M ReLU OpenVINO FP32\",\"family\":\"yolov9m\",\"variant\":\"relu\",\"format\":\"openvino\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9m_relu/best-converted.xml\",\"size\":485439,\"sha256\":\"c66f9f1965bf70fd3635d4dfc3cb94c72c06b344c256713237d77706725b9a0c\"},{\"relativePath\":\"openvino/scrypted_yolov9m_relu/best-converted.bin\",\"size\":79717372,\"sha256\":\"dfc2d8952bbca9ad0e116168e3fd5c754e601c327d78c4f4d0d4cae12f0e1d2a\"}],\"sizeMB\":80.2},{\"id\":\"scrypted-yolov9c-relu-openvino-fp32\",\"label\":\"Scrypted YOLOv9C ReLU OpenVINO FP32\",\"family\":\"yolov9c\",\"variant\":\"relu\",\"format\":\"openvino\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9c_relu/best-converted.xml\",\"size\":535047,\"sha256\":\"836c1e998ebf76108ff64d554fdfa07aa72c42624f1a5448701bb409f27b8d68\"},{\"relativePath\":\"openvino/scrypted_yolov9c_relu/best-converted.bin\",\"size\":100942972,\"sha256\":\"11a1b330ac9843b349927977b3c7c7f17bb42af73a7ff102969132f27ab81814\"}],\"sizeMB\":101.48},{\"id\":\"scrypted-yolov9t-relu-openvino-int8\",\"label\":\"Scrypted YOLOv9T ReLU OpenVINO INT8\",\"family\":\"yolov9t\",\"variant\":\"relu\",\"format\":\"openvino\",\"precision\":\"int8\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9t_relu_int8/best-converted.xml\",\"size\":1380379,\"sha256\":\"e5a76bf88ac69fc0ebc50c04b61ff91550dd9c2349af1f6d7e4cac949c640cec\"},{\"relativePath\":\"openvino/scrypted_yolov9t_relu_int8/best-converted.bin\",\"size\":1954956,\"sha256\":\"98fb5b6826d7c6697a585f69ba96754873772d9d61fbed8335aab761e8248659\"}],\"sizeMB\":3.34},{\"id\":\"scrypted-yolov9t-relu-test-openvino-int8\",\"label\":\"Scrypted YOLOv9T ReLU test OpenVINO INT8\",\"family\":\"yolov9t\",\"variant\":\"relu_test\",\"format\":\"openvino\",\"precision\":\"int8\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9t_relu_test_int8/best-converted.xml\",\"size\":1380383,\"sha256\":\"9e4119284e923e08c9929e78fd31e2552e602a552ac538ae99bf34a50dd4d172\"},{\"relativePath\":\"openvino/scrypted_yolov9t_relu_test_int8/best-converted.bin\",\"size\":1954960,\"sha256\":\"efe5b0a2fd2f5ddef5923eeb9e592a7ef14719061bb7605c86e05b35c2c58ea9\"}],\"sizeMB\":3.34},{\"id\":\"scrypted-yolov9s-relu-openvino-int8\",\"label\":\"Scrypted YOLOv9S ReLU OpenVINO INT8\",\"family\":\"yolov9s\",\"variant\":\"relu\",\"format\":\"openvino\",\"precision\":\"int8\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9s_relu_int8/best-converted.xml\",\"size\":1382088,\"sha256\":\"4e6c24cf24afbab21462f7e1a15bd05b1cbbe5915046000e03c2435d8110bbbf\"},{\"relativePath\":\"openvino/scrypted_yolov9s_relu_int8/best-converted.bin\",\"size\":7197308,\"sha256\":\"23fd3d666a938c41db232d9c6239baec1134716cfb4ed4ddd3d602dd20eb8ac0\"}],\"sizeMB\":8.58},{\"id\":\"scrypted-yolov9s-relu-test-openvino-int8\",\"label\":\"Scrypted YOLOv9S ReLU test OpenVINO INT8\",\"family\":\"yolov9s\",\"variant\":\"relu_test\",\"format\":\"openvino\",\"precision\":\"int8\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9s_relu_test_int8/best-converted.xml\",\"size\":1382092,\"sha256\":\"49865bfeafe7576afce089ba6f5c3e25a9192c8b514eb96265c90fe877795641\"},{\"relativePath\":\"openvino/scrypted_yolov9s_relu_test_int8/best-converted.bin\",\"size\":7197312,\"sha256\":\"78e9d36e6b74754db2b624ea3ec0b3ff57ed6dfed59a4f2225e1a271054597de\"}],\"sizeMB\":8.58},{\"id\":\"scrypted-yolov9m-relu-openvino-int8\",\"label\":\"Scrypted YOLOv9M ReLU OpenVINO INT8\",\"family\":\"yolov9m\",\"variant\":\"relu\",\"format\":\"openvino\",\"precision\":\"int8\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9m_relu_int8/best-converted.xml\",\"size\":1024595,\"sha256\":\"1242ab8d8c73b2e80c5dd541177ade6e102a2684114b059136acb4cad6efb034\"},{\"relativePath\":\"openvino/scrypted_yolov9m_relu_int8/best-converted.bin\",\"size\":20090516,\"sha256\":\"da8e44af8bee66478e6f359e9504bfb13ab4b76f4bd8a2f1b10cfbc22febcf6e\"}],\"sizeMB\":21.12},{\"id\":\"scrypted-yolov9m-relu-test-openvino-int8\",\"label\":\"Scrypted YOLOv9M ReLU test OpenVINO INT8\",\"family\":\"yolov9m\",\"variant\":\"relu_test\",\"format\":\"openvino\",\"precision\":\"int8\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9m_relu_test_int8/best-converted.xml\",\"size\":1024601,\"sha256\":\"24395ae5fdbb321304c865372cd2b905cdc55abb7610520f3963702e2371decb\"},{\"relativePath\":\"openvino/scrypted_yolov9m_relu_test_int8/best-converted.bin\",\"size\":20090520,\"sha256\":\"4360fe0312067f92c49f180c7b8a10271f14d58b8909aa9b96b13af4ab9289aa\"}],\"sizeMB\":21.12},{\"id\":\"scrypted-yolov9c-relu-openvino-int8\",\"label\":\"Scrypted YOLOv9C ReLU OpenVINO INT8\",\"family\":\"yolov9c\",\"variant\":\"relu\",\"format\":\"openvino\",\"precision\":\"int8\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9c_relu_int8/best-converted.xml\",\"size\":1092695,\"sha256\":\"a45c62940120c4301d8fff9fb3b275c29e3618f403ea68a785f2f3220cefec7a\"},{\"relativePath\":\"openvino/scrypted_yolov9c_relu_int8/best-converted.bin\",\"size\":25428280,\"sha256\":\"0643403a56178c3ed1e066c7884458d8ea6780115d662bdc38d10754d7a11c79\"}],\"sizeMB\":26.52},{\"id\":\"scrypted-yolov9c-relu-test-openvino-int8\",\"label\":\"Scrypted YOLOv9C ReLU test OpenVINO INT8\",\"family\":\"yolov9c\",\"variant\":\"relu_test\",\"format\":\"openvino\",\"precision\":\"int8\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9c_relu_test_int8/best-converted.xml\",\"size\":1092695,\"sha256\":\"a8a1899848ebd060af2326d3c8d3c09ea83354f0bedff6cce6fa08b284ea5519\"},{\"relativePath\":\"openvino/scrypted_yolov9c_relu_test_int8/best-converted.bin\",\"size\":25428280,\"sha256\":\"2eb6bb3d0a03a9b239b6f623f9e7bced62eea61fbe4d8ff89c1b3e2e2b7978a2\"}],\"sizeMB\":26.52},{\"id\":\"scrypted-yolov9s-relu-sep-320-tflite-float16\",\"label\":\"Scrypted YOLOv9s ReLU sep 320 TFLite float16\",\"family\":\"yolov9s\",\"variant\":\"relu\",\"format\":\"tflite\",\"precision\":\"float16\",\"files\":[{\"relativePath\":\"tflite/scrypted_yolov9s_relu_sep_320/best_float16.tflite\",\"size\":14482836,\"sha256\":\"04889db3b81af361c361e41ffa99327330d37b71d680a2f889e6cdf1e94c0d8c\"}],\"sizeMB\":14.48},{\"id\":\"scrypted-yolov9s-relu-sep-320-tflite-float32\",\"label\":\"Scrypted YOLOv9s ReLU sep 320 TFLite float32\",\"family\":\"yolov9s\",\"variant\":\"relu\",\"format\":\"tflite\",\"precision\":\"float32\",\"files\":[{\"relativePath\":\"tflite/scrypted_yolov9s_relu_sep_320/best_float32.tflite\",\"size\":28777068,\"sha256\":\"f5d7d08fc1d8f2262633d2df4391638e0481740331aaa1837880a47c33001a96\"}],\"sizeMB\":28.78},{\"id\":\"scrypted-yolov9s-relu-sep-320-tflite-int8\",\"label\":\"Scrypted YOLOv9s ReLU sep 320 TFLite int8\",\"family\":\"yolov9s\",\"variant\":\"relu\",\"format\":\"tflite\",\"precision\":\"int8\",\"files\":[{\"relativePath\":\"tflite/scrypted_yolov9s_relu_sep_320/best_int8.tflite\",\"size\":7325616,\"sha256\":\"1e9866b16fe80931383bf3c94dc629fe93a37ba3dc1465ea019eb0a50bd428df\"}],\"sizeMB\":7.33},{\"id\":\"scrypted-yolov9s-relu-sep-320-tflite-integer_quant\",\"label\":\"Scrypted YOLOv9s ReLU sep 320 TFLite integer_quant\",\"family\":\"yolov9s\",\"variant\":\"relu\",\"format\":\"tflite\",\"precision\":\"integer_quant\",\"files\":[{\"relativePath\":\"tflite/scrypted_yolov9s_relu_sep_320/best_integer_quant.tflite\",\"size\":7342552,\"sha256\":\"bc1c902e9a9865637ee2403f70c6bf5c29c695d9163e58ad658feb29bb097ebc\"}],\"sizeMB\":7.34},{\"id\":\"scrypted-yolov9s-relu-sep-320-tflite-full_integer_quant\",\"label\":\"Scrypted YOLOv9s ReLU sep 320 TFLite full_integer_quant\",\"family\":\"yolov9s\",\"variant\":\"relu\",\"format\":\"tflite\",\"precision\":\"full_integer_quant\",\"files\":[{\"relativePath\":\"tflite/scrypted_yolov9s_relu_sep_320/best_full_integer_quant.tflite\",\"size\":7341704,\"sha256\":\"483ce38dbe33ee5a35f40a82f56c77629a44fa5d95efd8ade9fa97e4d2a261fd\"}],\"sizeMB\":7.34},{\"id\":\"scrypted-yolov9s-relu-sep-320-tflite-edgetpu\",\"label\":\"Scrypted YOLOv9s ReLU sep 320 TFLite edgetpu\",\"family\":\"yolov9s\",\"variant\":\"relu\",\"format\":\"tflite\",\"precision\":\"edgetpu\",\"files\":[{\"relativePath\":\"tflite/scrypted_yolov9s_relu_sep_320/best_full_integer_quant_edgetpu.tflite\",\"size\":8164480,\"sha256\":\"e1e6b074a3b9fdf19a171baf615553ad375a046aa7de2a3fef9a1950175fab22\"}],\"sizeMB\":8.16}]");
35
+ //#region src/plugin-catalog/plugin-catalog-yolo-manifest-data.json
36
+ var plugin_catalog_yolo_manifest_data_default = /*#__PURE__*/ JSON.parse("[{\"id\":\"scrypted-yolov9t-relu-coreml\",\"label\":\"plugin catalog YOLOv9T ReLU CoreML\",\"family\":\"yolov9t\",\"variant\":\"relu\",\"format\":\"coreml\",\"precision\":\"fp16\",\"files\":[{\"relativePath\":\"coreml/scrypted_yolov9t_relu/scrypted_yolov9t_relu.mlpackage/Manifest.json\",\"size\":617,\"sha256\":\"0a8733949d77e3204dba6418e81a11a8cc177015711457ce2c171266f23382d6\"},{\"relativePath\":\"coreml/scrypted_yolov9t_relu/scrypted_yolov9t_relu.mlpackage/Data/com.apple.CoreML/model.mlmodel\",\"size\":322229,\"sha256\":\"f5a62f196f1e72a84efa1637119dffb6501621af9cf6f867bc76b4b59c9242a0\"},{\"relativePath\":\"coreml/scrypted_yolov9t_relu/scrypted_yolov9t_relu.mlpackage/Data/com.apple.CoreML/weights/weight.bin\",\"size\":3797160,\"sha256\":\"b994419b8b68cfd6b89c3c6f3fe6b37458c86cc1d87fcca3df5034476a99dd38\"}],\"sizeMB\":4.12},{\"id\":\"scrypted-yolov9t-relu-onnx\",\"label\":\"plugin catalog YOLOv9T ReLU ONNX\",\"family\":\"yolov9t\",\"variant\":\"relu\",\"format\":\"onnx\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"onnx/scrypted_yolov9t_relu/scrypted_yolov9t_relu.onnx\",\"size\":8499266,\"sha256\":\"3f11ea2071b27c285b58c16636a44d6a0a27bdd1ca8b64112dfadabd39cfea47\"}],\"sizeMB\":8.5},{\"id\":\"scrypted-yolov9t-relu-test-coreml\",\"label\":\"plugin catalog YOLOv9T ReLU test CoreML\",\"family\":\"yolov9t\",\"variant\":\"relu_test\",\"format\":\"coreml\",\"precision\":\"fp16\",\"files\":[{\"relativePath\":\"coreml/scrypted_yolov9t_relu_test/scrypted_yolov9t_relu_test.mlpackage/Manifest.json\",\"size\":617,\"sha256\":\"a5e0128b643f1a66f3e07d4b332f9ccbca97ccab75651c794f0b9f1fb41c8491\"},{\"relativePath\":\"coreml/scrypted_yolov9t_relu_test/scrypted_yolov9t_relu_test.mlpackage/Data/com.apple.CoreML/model.mlmodel\",\"size\":322229,\"sha256\":\"79f4f647f2a0c79db3b560c84251b48c7ba7cbe9c1fecc9674d1a603a389dfa3\"},{\"relativePath\":\"coreml/scrypted_yolov9t_relu_test/scrypted_yolov9t_relu_test.mlpackage/Data/com.apple.CoreML/weights/weight.bin\",\"size\":3797160,\"sha256\":\"72efc9dc6af9241b5e5ee7de24a4f55741f6425d0e279d797f0f223e3d355f84\"}],\"sizeMB\":4.12},{\"id\":\"scrypted-yolov9t-relu-test-onnx\",\"label\":\"plugin catalog YOLOv9T ReLU test ONNX\",\"family\":\"yolov9t\",\"variant\":\"relu_test\",\"format\":\"onnx\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"onnx/scrypted_yolov9t_relu_test/scrypted_yolov9t_relu_test.onnx\",\"size\":8499266,\"sha256\":\"d20aa0e6923a3af7f5e84e3a6d28fb00e8ecd592e3225f986f93bd34b634e2f8\"}],\"sizeMB\":8.5},{\"id\":\"scrypted-yolov9s-relu-coreml\",\"label\":\"plugin catalog YOLOv9S ReLU CoreML\",\"family\":\"yolov9s\",\"variant\":\"relu\",\"format\":\"coreml\",\"precision\":\"fp16\",\"files\":[{\"relativePath\":\"coreml/scrypted_yolov9s_relu/scrypted_yolov9s_relu.mlpackage/Manifest.json\",\"size\":617,\"sha256\":\"3bcdb820b82f1e89266f2d11bae1604d3ee4ca6d11dc5bd5c57055ff4157e9f3\"},{\"relativePath\":\"coreml/scrypted_yolov9s_relu/scrypted_yolov9s_relu.mlpackage/Data/com.apple.CoreML/model.mlmodel\",\"size\":322664,\"sha256\":\"9a9c3c9cbca406ec2f0418ec867ed6b878ec6d02c16636d30e0bbd83d2ff7c40\"},{\"relativePath\":\"coreml/scrypted_yolov9s_relu/scrypted_yolov9s_relu.mlpackage/Data/com.apple.CoreML/weights/weight.bin\",\"size\":14190120,\"sha256\":\"fd51eda58a993997268f6a2e424b536ba173207ad7974ab8bee2a8ff76d52dab\"}],\"sizeMB\":14.51},{\"id\":\"scrypted-yolov9s-relu-onnx\",\"label\":\"plugin catalog YOLOv9S ReLU ONNX\",\"family\":\"yolov9s\",\"variant\":\"relu\",\"format\":\"onnx\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"onnx/scrypted_yolov9s_relu/scrypted_yolov9s_relu.onnx\",\"size\":29287339,\"sha256\":\"ca0b5bd98d5f59eb2029c6cb5129d53af59873f62a317a028beda463bbb96399\"}],\"sizeMB\":29.29},{\"id\":\"scrypted-yolov9s-relu-test-coreml\",\"label\":\"plugin catalog YOLOv9S ReLU test CoreML\",\"family\":\"yolov9s\",\"variant\":\"relu_test\",\"format\":\"coreml\",\"precision\":\"fp16\",\"files\":[{\"relativePath\":\"coreml/scrypted_yolov9s_relu_test/scrypted_yolov9s_relu_test.mlpackage/Manifest.json\",\"size\":617,\"sha256\":\"e2d24de0ce7e8573f19572029765e55abc714f36a85175ad7fcb95c001a76653\"},{\"relativePath\":\"coreml/scrypted_yolov9s_relu_test/scrypted_yolov9s_relu_test.mlpackage/Data/com.apple.CoreML/model.mlmodel\",\"size\":322664,\"sha256\":\"186b147cdfd15c5ed7a381ec3a426a22cee0b5c52d56f14efd26da06357f5cb0\"},{\"relativePath\":\"coreml/scrypted_yolov9s_relu_test/scrypted_yolov9s_relu_test.mlpackage/Data/com.apple.CoreML/weights/weight.bin\",\"size\":14190120,\"sha256\":\"e50651924c2cbffd56008a8953569e66c3de69f21807fcf7d825390ce30f21f8\"}],\"sizeMB\":14.51},{\"id\":\"scrypted-yolov9s-relu-test-onnx\",\"label\":\"plugin catalog YOLOv9S ReLU test ONNX\",\"family\":\"yolov9s\",\"variant\":\"relu_test\",\"format\":\"onnx\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"onnx/scrypted_yolov9s_relu_test/scrypted_yolov9s_relu_test.onnx\",\"size\":29287339,\"sha256\":\"115ddb83333762a0f2599421335678696454a5c3571ade5df9bac8e9cb5fb4cf\"}],\"sizeMB\":29.29},{\"id\":\"scrypted-yolov9m-relu-coreml\",\"label\":\"plugin catalog YOLOv9M ReLU CoreML\",\"family\":\"yolov9m\",\"variant\":\"relu\",\"format\":\"coreml\",\"precision\":\"fp16\",\"files\":[{\"relativePath\":\"coreml/scrypted_yolov9m_relu/scrypted_yolov9m_relu.mlpackage/Manifest.json\",\"size\":617,\"sha256\":\"c548c6e1ff768b2b01bd71e230aa712a1635ae2baa30e0369557a42fc531ecbf\"},{\"relativePath\":\"coreml/scrypted_yolov9m_relu/scrypted_yolov9m_relu.mlpackage/Data/com.apple.CoreML/model.mlmodel\",\"size\":247061,\"sha256\":\"1c40e02fc2a2559cb906ea6cd9da9c730d4a78f5019290cbb38d2fcaae379fe7\"},{\"relativePath\":\"coreml/scrypted_yolov9m_relu/scrypted_yolov9m_relu.mlpackage/Data/com.apple.CoreML/weights/weight.bin\",\"size\":39880616,\"sha256\":\"4cf938e5bfcc3ee1644813e4eb4702a7de450cc0581df94c719cf43d0ed2e408\"}],\"sizeMB\":40.13},{\"id\":\"scrypted-yolov9m-relu-onnx\",\"label\":\"plugin catalog YOLOv9M ReLU ONNX\",\"family\":\"yolov9m\",\"variant\":\"relu\",\"format\":\"onnx\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"onnx/scrypted_yolov9m_relu/scrypted_yolov9m_relu.onnx\",\"size\":80380404,\"sha256\":\"e7a81fb33224a0105d2a0a594c3fa43c398c361de623f1d14156ae826e7312d5\"}],\"sizeMB\":80.38},{\"id\":\"scrypted-yolov9m-relu-test-coreml\",\"label\":\"plugin catalog YOLOv9M ReLU test CoreML\",\"family\":\"yolov9m\",\"variant\":\"relu_test\",\"format\":\"coreml\",\"precision\":\"fp16\",\"files\":[{\"relativePath\":\"coreml/scrypted_yolov9m_relu_test/scrypted_yolov9m_relu_test.mlpackage/Manifest.json\",\"size\":617,\"sha256\":\"8e2684b286d02b4bdf9db1027c84cb89bf8e4830cfb58269f3ec457c5a010650\"},{\"relativePath\":\"coreml/scrypted_yolov9m_relu_test/scrypted_yolov9m_relu_test.mlpackage/Data/com.apple.CoreML/model.mlmodel\",\"size\":247061,\"sha256\":\"53d5946e74b13b15c5f8616081c9f15e8a95a5df3d5b45b830fc5a7f49561c16\"},{\"relativePath\":\"coreml/scrypted_yolov9m_relu_test/scrypted_yolov9m_relu_test.mlpackage/Data/com.apple.CoreML/weights/weight.bin\",\"size\":39880616,\"sha256\":\"69774bf0032c37707601b8cdc1e1820dbd9f8288eb5d6f3879618a5d34ff5199\"}],\"sizeMB\":40.13},{\"id\":\"scrypted-yolov9m-relu-test-onnx\",\"label\":\"plugin catalog YOLOv9M ReLU test ONNX\",\"family\":\"yolov9m\",\"variant\":\"relu_test\",\"format\":\"onnx\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"onnx/scrypted_yolov9m_relu_test/scrypted_yolov9m_relu_test.onnx\",\"size\":80380404,\"sha256\":\"8bb054f099295909ec518e2a6598d63db24d3f90edc8105a0f016903f2a205a2\"}],\"sizeMB\":80.38},{\"id\":\"scrypted-yolov9c-relu-coreml\",\"label\":\"plugin catalog YOLOv9C ReLU CoreML\",\"family\":\"yolov9c\",\"variant\":\"relu\",\"format\":\"coreml\",\"precision\":\"fp16\",\"files\":[{\"relativePath\":\"coreml/scrypted_yolov9c_relu/scrypted_yolov9c_relu.mlpackage/Manifest.json\",\"size\":617,\"sha256\":\"813a306ebd69cabfd31f00434f5a961feeca7d237833f3e11805dcf4ad120ba9\"},{\"relativePath\":\"coreml/scrypted_yolov9c_relu/scrypted_yolov9c_relu.mlpackage/Data/com.apple.CoreML/model.mlmodel\",\"size\":263210,\"sha256\":\"862f082619075e470738306b0ff0a37ae70a7d08e684ca6a6dfa1971d404e0c3\"},{\"relativePath\":\"coreml/scrypted_yolov9c_relu/scrypted_yolov9c_relu.mlpackage/Data/com.apple.CoreML/weights/weight.bin\",\"size\":50489960,\"sha256\":\"ed89747e58943758e2a87221d1d404f6a4466cbc039c3c6f96e327cadc403d27\"}],\"sizeMB\":50.75},{\"id\":\"scrypted-yolov9c-relu-onnx\",\"label\":\"plugin catalog YOLOv9C ReLU ONNX\",\"family\":\"yolov9c\",\"variant\":\"relu\",\"format\":\"onnx\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"onnx/scrypted_yolov9c_relu/scrypted_yolov9c_relu.onnx\",\"size\":101631962,\"sha256\":\"b9372c4428daf4cd944c114b1e80d1a9ff0487d743e53a77216a051cfbef7116\"}],\"sizeMB\":101.63},{\"id\":\"scrypted-yolov9c-relu-test-coreml\",\"label\":\"plugin catalog YOLOv9C ReLU test CoreML\",\"family\":\"yolov9c\",\"variant\":\"relu_test\",\"format\":\"coreml\",\"precision\":\"fp16\",\"files\":[{\"relativePath\":\"coreml/scrypted_yolov9c_relu_test/scrypted_yolov9c_relu_test.mlpackage/Manifest.json\",\"size\":617,\"sha256\":\"966ef82a93cb0ccf1036a8c9729c065fd372fa9590a97d0945e581cc674f7ad2\"},{\"relativePath\":\"coreml/scrypted_yolov9c_relu_test/scrypted_yolov9c_relu_test.mlpackage/Data/com.apple.CoreML/model.mlmodel\",\"size\":263210,\"sha256\":\"08718ecd3e9552d21a702bd8df60911cad0eec7b2ae382466809550f14634711\"},{\"relativePath\":\"coreml/scrypted_yolov9c_relu_test/scrypted_yolov9c_relu_test.mlpackage/Data/com.apple.CoreML/weights/weight.bin\",\"size\":50489960,\"sha256\":\"fe5936b9430ab4c87f30b148220131d6ec998b2377223d033e2fa2a00e60aada\"}],\"sizeMB\":50.75},{\"id\":\"scrypted-yolov9c-relu-test-onnx\",\"label\":\"plugin catalog YOLOv9C ReLU test ONNX\",\"family\":\"yolov9c\",\"variant\":\"relu_test\",\"format\":\"onnx\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"onnx/scrypted_yolov9c_relu_test/scrypted_yolov9c_relu_test.onnx\",\"size\":101631962,\"sha256\":\"2f4e2031e8efb4cbc871594338b2e875d78ab4af3ee0258d253273b1aac84742\"}],\"sizeMB\":101.63},{\"id\":\"scrypted-yolov9t-relu-openvino-fp32\",\"label\":\"plugin catalog YOLOv9T ReLU OpenVINO FP32\",\"family\":\"yolov9t\",\"variant\":\"relu\",\"format\":\"openvino\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9t_relu/best-converted.xml\",\"size\":628222,\"sha256\":\"01b5a9d02a0f281e1aaf4860e1b0ed3a7f16b9d78975be8ff985ae0ee283d877\"},{\"relativePath\":\"openvino/scrypted_yolov9t_relu/best-converted.bin\",\"size\":7542204,\"sha256\":\"4fe9ce8dbdf94514fdd450cbfc907f257153e4898a0c1489a44e4912d8e32cc7\"}],\"sizeMB\":8.17},{\"id\":\"scrypted-yolov9s-relu-openvino-fp32\",\"label\":\"plugin catalog YOLOv9S ReLU OpenVINO FP32\",\"family\":\"yolov9s\",\"variant\":\"relu\",\"format\":\"openvino\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9s_relu/best-converted.xml\",\"size\":629249,\"sha256\":\"5b4a229bf7229425698b63bd065a403e440a6151a6ddff0034867659cc4a480d\"},{\"relativePath\":\"openvino/scrypted_yolov9s_relu/best-converted.bin\",\"size\":28329724,\"sha256\":\"c030bd219208ea94082578c81f383d4ef9ec45d7150eec1c2c2ff2569cf49b35\"}],\"sizeMB\":28.96},{\"id\":\"scrypted-yolov9m-relu-openvino-fp32\",\"label\":\"plugin catalog YOLOv9M ReLU OpenVINO FP32\",\"family\":\"yolov9m\",\"variant\":\"relu\",\"format\":\"openvino\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9m_relu/best-converted.xml\",\"size\":485439,\"sha256\":\"c66f9f1965bf70fd3635d4dfc3cb94c72c06b344c256713237d77706725b9a0c\"},{\"relativePath\":\"openvino/scrypted_yolov9m_relu/best-converted.bin\",\"size\":79717372,\"sha256\":\"dfc2d8952bbca9ad0e116168e3fd5c754e601c327d78c4f4d0d4cae12f0e1d2a\"}],\"sizeMB\":80.2},{\"id\":\"scrypted-yolov9c-relu-openvino-fp32\",\"label\":\"plugin catalog YOLOv9C ReLU OpenVINO FP32\",\"family\":\"yolov9c\",\"variant\":\"relu\",\"format\":\"openvino\",\"precision\":\"fp32\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9c_relu/best-converted.xml\",\"size\":535047,\"sha256\":\"836c1e998ebf76108ff64d554fdfa07aa72c42624f1a5448701bb409f27b8d68\"},{\"relativePath\":\"openvino/scrypted_yolov9c_relu/best-converted.bin\",\"size\":100942972,\"sha256\":\"11a1b330ac9843b349927977b3c7c7f17bb42af73a7ff102969132f27ab81814\"}],\"sizeMB\":101.48},{\"id\":\"scrypted-yolov9t-relu-openvino-int8\",\"label\":\"plugin catalog YOLOv9T ReLU OpenVINO INT8\",\"family\":\"yolov9t\",\"variant\":\"relu\",\"format\":\"openvino\",\"precision\":\"int8\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9t_relu_int8/best-converted.xml\",\"size\":1380379,\"sha256\":\"e5a76bf88ac69fc0ebc50c04b61ff91550dd9c2349af1f6d7e4cac949c640cec\"},{\"relativePath\":\"openvino/scrypted_yolov9t_relu_int8/best-converted.bin\",\"size\":1954956,\"sha256\":\"98fb5b6826d7c6697a585f69ba96754873772d9d61fbed8335aab761e8248659\"}],\"sizeMB\":3.34},{\"id\":\"scrypted-yolov9t-relu-test-openvino-int8\",\"label\":\"plugin catalog YOLOv9T ReLU test OpenVINO INT8\",\"family\":\"yolov9t\",\"variant\":\"relu_test\",\"format\":\"openvino\",\"precision\":\"int8\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9t_relu_test_int8/best-converted.xml\",\"size\":1380383,\"sha256\":\"9e4119284e923e08c9929e78fd31e2552e602a552ac538ae99bf34a50dd4d172\"},{\"relativePath\":\"openvino/scrypted_yolov9t_relu_test_int8/best-converted.bin\",\"size\":1954960,\"sha256\":\"efe5b0a2fd2f5ddef5923eeb9e592a7ef14719061bb7605c86e05b35c2c58ea9\"}],\"sizeMB\":3.34},{\"id\":\"scrypted-yolov9s-relu-openvino-int8\",\"label\":\"plugin catalog YOLOv9S ReLU OpenVINO INT8\",\"family\":\"yolov9s\",\"variant\":\"relu\",\"format\":\"openvino\",\"precision\":\"int8\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9s_relu_int8/best-converted.xml\",\"size\":1382088,\"sha256\":\"4e6c24cf24afbab21462f7e1a15bd05b1cbbe5915046000e03c2435d8110bbbf\"},{\"relativePath\":\"openvino/scrypted_yolov9s_relu_int8/best-converted.bin\",\"size\":7197308,\"sha256\":\"23fd3d666a938c41db232d9c6239baec1134716cfb4ed4ddd3d602dd20eb8ac0\"}],\"sizeMB\":8.58},{\"id\":\"scrypted-yolov9s-relu-test-openvino-int8\",\"label\":\"plugin catalog YOLOv9S ReLU test OpenVINO INT8\",\"family\":\"yolov9s\",\"variant\":\"relu_test\",\"format\":\"openvino\",\"precision\":\"int8\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9s_relu_test_int8/best-converted.xml\",\"size\":1382092,\"sha256\":\"49865bfeafe7576afce089ba6f5c3e25a9192c8b514eb96265c90fe877795641\"},{\"relativePath\":\"openvino/scrypted_yolov9s_relu_test_int8/best-converted.bin\",\"size\":7197312,\"sha256\":\"78e9d36e6b74754db2b624ea3ec0b3ff57ed6dfed59a4f2225e1a271054597de\"}],\"sizeMB\":8.58},{\"id\":\"scrypted-yolov9m-relu-openvino-int8\",\"label\":\"plugin catalog YOLOv9M ReLU OpenVINO INT8\",\"family\":\"yolov9m\",\"variant\":\"relu\",\"format\":\"openvino\",\"precision\":\"int8\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9m_relu_int8/best-converted.xml\",\"size\":1024595,\"sha256\":\"1242ab8d8c73b2e80c5dd541177ade6e102a2684114b059136acb4cad6efb034\"},{\"relativePath\":\"openvino/scrypted_yolov9m_relu_int8/best-converted.bin\",\"size\":20090516,\"sha256\":\"da8e44af8bee66478e6f359e9504bfb13ab4b76f4bd8a2f1b10cfbc22febcf6e\"}],\"sizeMB\":21.12},{\"id\":\"scrypted-yolov9m-relu-test-openvino-int8\",\"label\":\"plugin catalog YOLOv9M ReLU test OpenVINO INT8\",\"family\":\"yolov9m\",\"variant\":\"relu_test\",\"format\":\"openvino\",\"precision\":\"int8\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9m_relu_test_int8/best-converted.xml\",\"size\":1024601,\"sha256\":\"24395ae5fdbb321304c865372cd2b905cdc55abb7610520f3963702e2371decb\"},{\"relativePath\":\"openvino/scrypted_yolov9m_relu_test_int8/best-converted.bin\",\"size\":20090520,\"sha256\":\"4360fe0312067f92c49f180c7b8a10271f14d58b8909aa9b96b13af4ab9289aa\"}],\"sizeMB\":21.12},{\"id\":\"scrypted-yolov9c-relu-openvino-int8\",\"label\":\"plugin catalog YOLOv9C ReLU OpenVINO INT8\",\"family\":\"yolov9c\",\"variant\":\"relu\",\"format\":\"openvino\",\"precision\":\"int8\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9c_relu_int8/best-converted.xml\",\"size\":1092695,\"sha256\":\"a45c62940120c4301d8fff9fb3b275c29e3618f403ea68a785f2f3220cefec7a\"},{\"relativePath\":\"openvino/scrypted_yolov9c_relu_int8/best-converted.bin\",\"size\":25428280,\"sha256\":\"0643403a56178c3ed1e066c7884458d8ea6780115d662bdc38d10754d7a11c79\"}],\"sizeMB\":26.52},{\"id\":\"scrypted-yolov9c-relu-test-openvino-int8\",\"label\":\"plugin catalog YOLOv9C ReLU test OpenVINO INT8\",\"family\":\"yolov9c\",\"variant\":\"relu_test\",\"format\":\"openvino\",\"precision\":\"int8\",\"files\":[{\"relativePath\":\"openvino/scrypted_yolov9c_relu_test_int8/best-converted.xml\",\"size\":1092695,\"sha256\":\"a8a1899848ebd060af2326d3c8d3c09ea83354f0bedff6cce6fa08b284ea5519\"},{\"relativePath\":\"openvino/scrypted_yolov9c_relu_test_int8/best-converted.bin\",\"size\":25428280,\"sha256\":\"2eb6bb3d0a03a9b239b6f623f9e7bced62eea61fbe4d8ff89c1b3e2e2b7978a2\"}],\"sizeMB\":26.52},{\"id\":\"scrypted-yolov9s-relu-sep-320-tflite-float16\",\"label\":\"plugin catalog YOLOv9s ReLU sep 320 TFLite float16\",\"family\":\"yolov9s\",\"variant\":\"relu\",\"format\":\"tflite\",\"precision\":\"float16\",\"files\":[{\"relativePath\":\"tflite/scrypted_yolov9s_relu_sep_320/best_float16.tflite\",\"size\":14482836,\"sha256\":\"04889db3b81af361c361e41ffa99327330d37b71d680a2f889e6cdf1e94c0d8c\"}],\"sizeMB\":14.48},{\"id\":\"scrypted-yolov9s-relu-sep-320-tflite-float32\",\"label\":\"plugin catalog YOLOv9s ReLU sep 320 TFLite float32\",\"family\":\"yolov9s\",\"variant\":\"relu\",\"format\":\"tflite\",\"precision\":\"float32\",\"files\":[{\"relativePath\":\"tflite/scrypted_yolov9s_relu_sep_320/best_float32.tflite\",\"size\":28777068,\"sha256\":\"f5d7d08fc1d8f2262633d2df4391638e0481740331aaa1837880a47c33001a96\"}],\"sizeMB\":28.78},{\"id\":\"scrypted-yolov9s-relu-sep-320-tflite-int8\",\"label\":\"plugin catalog YOLOv9s ReLU sep 320 TFLite int8\",\"family\":\"yolov9s\",\"variant\":\"relu\",\"format\":\"tflite\",\"precision\":\"int8\",\"files\":[{\"relativePath\":\"tflite/scrypted_yolov9s_relu_sep_320/best_int8.tflite\",\"size\":7325616,\"sha256\":\"1e9866b16fe80931383bf3c94dc629fe93a37ba3dc1465ea019eb0a50bd428df\"}],\"sizeMB\":7.33},{\"id\":\"scrypted-yolov9s-relu-sep-320-tflite-integer_quant\",\"label\":\"plugin catalog YOLOv9s ReLU sep 320 TFLite integer_quant\",\"family\":\"yolov9s\",\"variant\":\"relu\",\"format\":\"tflite\",\"precision\":\"integer_quant\",\"files\":[{\"relativePath\":\"tflite/scrypted_yolov9s_relu_sep_320/best_integer_quant.tflite\",\"size\":7342552,\"sha256\":\"bc1c902e9a9865637ee2403f70c6bf5c29c695d9163e58ad658feb29bb097ebc\"}],\"sizeMB\":7.34},{\"id\":\"scrypted-yolov9s-relu-sep-320-tflite-full_integer_quant\",\"label\":\"plugin catalog YOLOv9s ReLU sep 320 TFLite full_integer_quant\",\"family\":\"yolov9s\",\"variant\":\"relu\",\"format\":\"tflite\",\"precision\":\"full_integer_quant\",\"files\":[{\"relativePath\":\"tflite/scrypted_yolov9s_relu_sep_320/best_full_integer_quant.tflite\",\"size\":7341704,\"sha256\":\"483ce38dbe33ee5a35f40a82f56c77629a44fa5d95efd8ade9fa97e4d2a261fd\"}],\"sizeMB\":7.34},{\"id\":\"scrypted-yolov9s-relu-sep-320-tflite-edgetpu\",\"label\":\"plugin catalog YOLOv9s ReLU sep 320 TFLite edgetpu\",\"family\":\"yolov9s\",\"variant\":\"relu\",\"format\":\"tflite\",\"precision\":\"edgetpu\",\"files\":[{\"relativePath\":\"tflite/scrypted_yolov9s_relu_sep_320/best_full_integer_quant_edgetpu.tflite\",\"size\":8164480,\"sha256\":\"e1e6b074a3b9fdf19a171baf615553ad375a046aa7de2a3fef9a1950175fab22\"}],\"sizeMB\":8.16}]");
37
37
  //#endregion
38
38
  //#region src/model-licenses.ts
39
39
  /**
40
- * Scrypted's YOLOv9 ReLU detectors. Checked 2026-09-27 on
40
+ * plugin catalog's YOLOv9 ReLU detectors. Checked 2026-09-27 on
41
41
  * `onnx/scrypted_yolov9t_relu/scrypted_yolov9t_relu.onnx` at the pinned
42
42
  * revision: no licence in the ONNX metadata, and the export's node traces name
43
43
  * `models.yolo.DetectionModel` / `models.common.Conv` from a `yolov9/` checkout
@@ -45,23 +45,23 @@ var scrypted_yolo_manifest_data_default = /*#__PURE__*/ JSON.parse("[{\"id\":\"s
45
45
  * card says `license: mit` at repository level; nothing states terms per model
46
46
  * or names the training data. So: code GPL-3.0, weights UNKNOWN.
47
47
  */
48
- var SCRYPTED_YOLOV9_UNKNOWN = {
48
+ var PLUGIN_CATALOG_YOLOV9_UNKNOWN = {
49
49
  weights: "UNKNOWN",
50
50
  code: "GPL-3.0",
51
51
  data: {
52
- name: "not stated by Scrypted",
52
+ name: "not stated by plugin catalog",
53
53
  terms: "UNKNOWN"
54
54
  },
55
55
  upstream: {
56
- name: "Scrypted plugin-models (repository tagged MIT, no per-model terms)",
56
+ name: "plugin catalog plugin-models (repository tagged MIT, no per-model terms)",
57
57
  url: "https://huggingface.co/scrypted/plugin-models"
58
58
  },
59
59
  url: "https://huggingface.co/scrypted/plugin-models",
60
- attribution: "Scrypted YOLOv9 ReLU detectors, Koushik Dutta (scrypted/plugin-models, repository tagged MIT); trained with the YOLOv9 code of Chien-Yao Wang, I-Hau Yeh, Hong-Yuan Mark Liao, GPL-3.0 (https://github.com/WongKinYiu/yolov9).",
60
+ attribution: "plugin catalog YOLOv9 ReLU detectors, Koushik Dutta (scrypted/plugin-models, repository tagged MIT); trained with the YOLOv9 code of Chien-Yao Wang, I-Hau Yeh, Hong-Yuan Mark Liao, GPL-3.0 (https://github.com/WongKinYiu/yolov9).",
61
61
  modifications: "none: downloaded as published, at a pinned revision",
62
62
  hosting: "third-party"
63
63
  };
64
- /** Frigate's default Coral model: Google's SSDLite MobileDet, Apache-2.0. */
64
+ /** plus catalog's default Coral model: Google's SSDLite MobileDet, Apache-2.0. */
65
65
  var CORAL_MOBILEDET_APACHE = {
66
66
  weights: "Apache-2.0",
67
67
  code: "Apache-2.0",
@@ -79,17 +79,17 @@ var CORAL_MOBILEDET_APACHE = {
79
79
  hosting: "third-party"
80
80
  };
81
81
  //#endregion
82
- //#region src/scrypted/scrypted-yolo-manifest.ts
83
- var SCRYPTED_SHA256_RE = /^[0-9a-f]{64}$/;
84
- var SCRYPTED_HF_HOST = "https://huggingface.co";
85
- var SCRYPTED_HF_REPO = "scrypted/plugin-models";
86
- var SCRYPTED_HF_REVISION = "187402b20a3be0a7fab9bceee21d857ed6ae0064";
87
- var SCRYPTED_YOLO_LABELS = [
82
+ //#region src/plugin-catalog/plugin-catalog-yolo-manifest.ts
83
+ var PLUGIN_CATALOG_SHA256_RE = /^[0-9a-f]{64}$/;
84
+ var PLUGIN_CATALOG_HF_HOST = "https://huggingface.co";
85
+ var PLUGIN_CATALOG_HF_REPO = "scrypted/plugin-models";
86
+ var PLUGIN_CATALOG_HF_REVISION = "187402b20a3be0a7fab9bceee21d857ed6ae0064";
87
+ var PLUGIN_CATALOG_YOLO_LABELS = [
88
88
  "person",
89
89
  "vehicle",
90
90
  "animal"
91
91
  ];
92
- var SCRYPTED_IDENTITY_CLASS_MAP = {
92
+ var PLUGIN_CATALOG_IDENTITY_CLASS_MAP = {
93
93
  mapping: {
94
94
  person: "person",
95
95
  vehicle: "vehicle",
@@ -97,7 +97,7 @@ var SCRYPTED_IDENTITY_CLASS_MAP = {
97
97
  },
98
98
  preserveOriginal: false
99
99
  };
100
- var SCRYPTED_LABEL_DEFS = SCRYPTED_YOLO_LABELS.map((id) => ({
100
+ var PLUGIN_CATALOG_LABEL_DEFS = PLUGIN_CATALOG_YOLO_LABELS.map((id) => ({
101
101
  id,
102
102
  name: id
103
103
  }));
@@ -110,22 +110,22 @@ var INPUT_SIZE = {
110
110
  width: 320,
111
111
  height: 320
112
112
  };
113
- function assertScryptedFileSha256(value, relativePath) {
114
- if (value === void 0 || !SCRYPTED_SHA256_RE.test(value)) throw new Error(`Invalid sha256 for ${relativePath}: expected 64 lowercase hex`);
113
+ function assertPluginCatalogFileSha256(value, relativePath) {
114
+ if (value === void 0 || !PLUGIN_CATALOG_SHA256_RE.test(value)) throw new Error(`Invalid sha256 for ${relativePath}: expected 64 lowercase hex`);
115
115
  return value;
116
116
  }
117
- function assertScryptedRelativePath(value) {
118
- if (value.length === 0 || value.startsWith("/") || value.includes("\\") || value.includes("\0")) throw new Error(`Unsafe Scrypted relative path: ${value}`);
119
- if (value.split("/").some((segment) => segment.length === 0 || segment === "." || segment === "..")) throw new Error(`Unsafe Scrypted relative path: ${value}`);
117
+ function assertPluginCatalogRelativePath(value) {
118
+ if (value.length === 0 || value.startsWith("/") || value.includes("\\") || value.includes("\0")) throw new Error(`Unsafe plugin catalog relative path: ${value}`);
119
+ if (value.split("/").some((segment) => segment.length === 0 || segment === "." || segment === "..")) throw new Error(`Unsafe plugin catalog relative path: ${value}`);
120
120
  return value;
121
121
  }
122
- function buildScryptedResolveUrl(relativePath) {
123
- return `${SCRYPTED_HF_HOST}/${SCRYPTED_HF_REPO}/resolve/${SCRYPTED_HF_REVISION}/${assertScryptedRelativePath(relativePath).split("/").map((segment) => encodeURIComponent(segment)).join("/")}`;
122
+ function buildPluginCatalogResolveUrl(relativePath) {
123
+ return `${PLUGIN_CATALOG_HF_HOST}/${PLUGIN_CATALOG_HF_REPO}/resolve/${PLUGIN_CATALOG_HF_REVISION}/${assertPluginCatalogRelativePath(relativePath).split("/").map((segment) => encodeURIComponent(segment)).join("/")}`;
124
124
  }
125
125
  function packageDirectory(files) {
126
126
  const manifest = files.find((file) => file.relativePath.endsWith("/Manifest.json"));
127
127
  if (!manifest) throw new Error("CoreML entry is missing Manifest.json");
128
- return assertScryptedRelativePath(manifest.relativePath.replace(/\/Manifest\.json$/, ""));
128
+ return assertPluginCatalogRelativePath(manifest.relativePath.replace(/\/Manifest\.json$/, ""));
129
129
  }
130
130
  function buildModel(spec) {
131
131
  const tier = spec.family.slice(-1);
@@ -148,25 +148,25 @@ function buildModel(spec) {
148
148
  if (spec.variant === "relu_test") nameParts.push("(Test)");
149
149
  if (int8) nameParts.push("INT8");
150
150
  const name = nameParts.join(" ");
151
- const description = `${name} — imported from the local Scrypted YOLO catalog.`;
151
+ const description = `${name} — imported from the local plugin catalog YOLO catalog.`;
152
152
  if (spec.format === "coreml") return {
153
153
  id: canonicalId,
154
154
  name,
155
155
  description,
156
156
  formats: { coreml: {
157
- url: buildScryptedResolveUrl(packageDirectory(spec.files)),
157
+ url: buildPluginCatalogResolveUrl(packageDirectory(spec.files)),
158
158
  sizeMB: spec.sizeMB,
159
159
  isDirectory: true,
160
160
  files: [...MLPACKAGE_INNER_FILES],
161
161
  runtimes: ["python"]
162
162
  } },
163
163
  inputSize: INPUT_SIZE,
164
- labels: SCRYPTED_LABEL_DEFS,
164
+ labels: PLUGIN_CATALOG_LABEL_DEFS,
165
165
  preprocessMode: "resize",
166
- classMap: SCRYPTED_IDENTITY_CLASS_MAP,
166
+ classMap: PLUGIN_CATALOG_IDENTITY_CLASS_MAP,
167
167
  group,
168
168
  provider: "scrypted",
169
- license: SCRYPTED_YOLOV9_UNKNOWN
169
+ license: PLUGIN_CATALOG_YOLOV9_UNKNOWN
170
170
  };
171
171
  if (spec.format === "openvino") {
172
172
  const xml = spec.files.find((file) => file.relativePath.endsWith(".xml"));
@@ -178,18 +178,18 @@ function buildModel(spec) {
178
178
  name,
179
179
  description,
180
180
  formats: { openvino: {
181
- url: buildScryptedResolveUrl(xml.relativePath),
181
+ url: buildPluginCatalogResolveUrl(xml.relativePath),
182
182
  sizeMB: spec.sizeMB,
183
183
  files: [binName],
184
184
  runtimes: ["python"]
185
185
  } },
186
186
  inputSize: INPUT_SIZE,
187
- labels: SCRYPTED_LABEL_DEFS,
187
+ labels: PLUGIN_CATALOG_LABEL_DEFS,
188
188
  preprocessMode: "resize",
189
- classMap: SCRYPTED_IDENTITY_CLASS_MAP,
189
+ classMap: PLUGIN_CATALOG_IDENTITY_CLASS_MAP,
190
190
  group,
191
191
  provider: "scrypted",
192
- license: SCRYPTED_YOLOV9_UNKNOWN
192
+ license: PLUGIN_CATALOG_YOLOV9_UNKNOWN
193
193
  };
194
194
  }
195
195
  const main = spec.files[0];
@@ -199,25 +199,25 @@ function buildModel(spec) {
199
199
  name,
200
200
  description,
201
201
  formats: { [spec.format]: {
202
- url: buildScryptedResolveUrl(main.relativePath),
202
+ url: buildPluginCatalogResolveUrl(main.relativePath),
203
203
  sizeMB: spec.sizeMB,
204
204
  runtimes: spec.format === "tflite" ? ["python"] : void 0
205
205
  } },
206
206
  inputSize: INPUT_SIZE,
207
- labels: SCRYPTED_LABEL_DEFS,
207
+ labels: PLUGIN_CATALOG_LABEL_DEFS,
208
208
  preprocessMode: "resize",
209
- classMap: SCRYPTED_IDENTITY_CLASS_MAP,
209
+ classMap: PLUGIN_CATALOG_IDENTITY_CLASS_MAP,
210
210
  group,
211
211
  provider: "scrypted",
212
- license: SCRYPTED_YOLOV9_UNKNOWN,
212
+ license: PLUGIN_CATALOG_YOLOV9_UNKNOWN,
213
213
  ...spec.format === "tflite" ? { postprocessor: "yolo-split-dfl" } : {}
214
214
  };
215
215
  }
216
216
  function freezeEntry(spec) {
217
217
  const files = spec.files.map((file) => Object.freeze({
218
- relativePath: assertScryptedRelativePath(file.relativePath),
218
+ relativePath: assertPluginCatalogRelativePath(file.relativePath),
219
219
  size: file.size,
220
- sha256: assertScryptedFileSha256(file.sha256, file.relativePath)
220
+ sha256: assertPluginCatalogFileSha256(file.sha256, file.relativePath)
221
221
  }));
222
222
  return Object.freeze({
223
223
  id: spec.id,
@@ -234,26 +234,26 @@ function freezeEntry(spec) {
234
234
  })
235
235
  });
236
236
  }
237
- var SCRYPTED_YOLO_MANIFEST = Object.freeze(scrypted_yolo_manifest_data_default.map(freezeEntry));
238
- function getScryptedManifestEntry(manifestId) {
239
- return SCRYPTED_YOLO_MANIFEST.find((entry) => entry.id === manifestId);
237
+ var PLUGIN_CATALOG_YOLO_MANIFEST = Object.freeze(plugin_catalog_yolo_manifest_data_default.map(freezeEntry));
238
+ function getPluginCatalogManifestEntry(manifestId) {
239
+ return PLUGIN_CATALOG_YOLO_MANIFEST.find((entry) => entry.id === manifestId);
240
240
  }
241
241
  //#endregion
242
- //#region src/scrypted/scrypted-tree-drift.ts
242
+ //#region src/plugin-catalog/plugin-catalog-tree-drift.ts
243
243
  /**
244
- * Read-only drift check: compare the local Scrypted YOLO manifest to a
244
+ * Read-only drift check: compare the local plugin catalog YOLO manifest to a
245
245
  * Hugging Face tree. Never mutates the manifest and never auto-imports
246
246
  * remote-only files.
247
247
  */
248
- var SCRYPTED_KNOWN_DRIFT_STATUSES = [
248
+ var PLUGIN_CATALOG_KNOWN_DRIFT_STATUSES = [
249
249
  "ok",
250
250
  "missing",
251
251
  "size-changed",
252
252
  "unavailable"
253
253
  ];
254
254
  /** Fail-closed: a future/unknown status is never treated as `ok`. */
255
- function normalizeScryptedDrift(row) {
256
- if (SCRYPTED_KNOWN_DRIFT_STATUSES.includes(row.status)) return {
255
+ function normalizePluginCatalogDrift(row) {
256
+ if (PLUGIN_CATALOG_KNOWN_DRIFT_STATUSES.includes(row.status)) return {
257
257
  manifestId: row.manifestId,
258
258
  status: row.status,
259
259
  ...row.details !== void 0 ? { details: row.details } : {}
@@ -267,7 +267,7 @@ function normalizeScryptedDrift(row) {
267
267
  function remoteSize(file) {
268
268
  return file.lfs?.size ?? file.size;
269
269
  }
270
- function compareScryptedManifestDrift(manifest, tree) {
270
+ function comparePluginCatalogManifestDrift(manifest, tree) {
271
271
  const byPath = new Map(tree.map((file) => [file.path, file]));
272
272
  return manifest.map((entry) => {
273
273
  const missing = [];
@@ -296,25 +296,25 @@ function compareScryptedManifestDrift(manifest, tree) {
296
296
  };
297
297
  });
298
298
  }
299
- var ScryptedTreeLinkError = class extends Error {
299
+ var PluginCatalogTreeLinkError = class extends Error {
300
300
  constructor(message) {
301
301
  super(message);
302
- this.name = "ScryptedTreeLinkError";
302
+ this.name = "PluginCatalogTreeLinkError";
303
303
  }
304
304
  };
305
- function assertScryptedTreePageUrl(url, revision) {
306
- if (url.protocol !== "https:") throw new ScryptedTreeLinkError(`Refusing non-https tree link: ${url.protocol}`);
307
- if (url.username || url.password) throw new ScryptedTreeLinkError("Refusing tree link with userinfo");
308
- if (url.origin !== `https://huggingface.co`) throw new ScryptedTreeLinkError(`Refusing tree link origin ${url.origin}`);
309
- const expectedPath = `/api/models/${SCRYPTED_HF_REPO}/tree/${revision}`;
310
- if (url.pathname !== expectedPath) throw new ScryptedTreeLinkError(`Refusing tree link path/revision ${url.pathname} (expected ${expectedPath})`);
305
+ function assertPluginCatalogTreePageUrl(url, revision) {
306
+ if (url.protocol !== "https:") throw new PluginCatalogTreeLinkError(`Refusing non-https tree link: ${url.protocol}`);
307
+ if (url.username || url.password) throw new PluginCatalogTreeLinkError("Refusing tree link with userinfo");
308
+ if (url.origin !== `https://huggingface.co`) throw new PluginCatalogTreeLinkError(`Refusing tree link origin ${url.origin}`);
309
+ const expectedPath = `/api/models/${PLUGIN_CATALOG_HF_REPO}/tree/${revision}`;
310
+ if (url.pathname !== expectedPath) throw new PluginCatalogTreeLinkError(`Refusing tree link path/revision ${url.pathname} (expected ${expectedPath})`);
311
311
  }
312
312
  /**
313
313
  * Parse `Link: <...>; rel="next"` and accept only an HTTPS huggingface.co
314
314
  * tree URL for the same repo + revision. Relative hrefs resolve against the
315
315
  * current page URL. Never returns a URL that failed validation.
316
316
  */
317
- function resolveScryptedTreeNextLink(header, currentUrl, revision) {
317
+ function resolvePluginCatalogTreeNextLink(header, currentUrl, revision) {
318
318
  if (!header) return void 0;
319
319
  const match = /<([^>]+)>;\s*rel="next"/.exec(header);
320
320
  if (!match?.[1]) return void 0;
@@ -322,34 +322,34 @@ function resolveScryptedTreeNextLink(header, currentUrl, revision) {
322
322
  try {
323
323
  resolved = new URL(match[1], currentUrl);
324
324
  } catch {
325
- throw new ScryptedTreeLinkError(`Refusing unparsable tree next link: ${match[1]}`);
325
+ throw new PluginCatalogTreeLinkError(`Refusing unparsable tree next link: ${match[1]}`);
326
326
  }
327
- assertScryptedTreePageUrl(resolved, revision);
327
+ assertPluginCatalogTreePageUrl(resolved, revision);
328
328
  return resolved.href;
329
329
  }
330
330
  async function sleep(ms) {
331
331
  if (ms <= 0) return;
332
332
  await new Promise((resolve) => setTimeout(resolve, ms));
333
333
  }
334
- async function fetchScryptedRemoteTree(opts) {
334
+ async function fetchPluginCatalogRemoteTree(opts) {
335
335
  const revision = opts.revision ?? "main";
336
336
  const maxRetries = opts.maxRetries ?? 4;
337
337
  const retryDelayMs = opts.retryDelayMs ?? 200;
338
- let lastError = /* @__PURE__ */ new Error("Scrypted Hugging Face tree unavailable");
338
+ let lastError = /* @__PURE__ */ new Error("plugin catalog Hugging Face tree unavailable");
339
339
  for (let attempt = 0; attempt < maxRetries; attempt++) try {
340
340
  const files = [];
341
- let url = `${SCRYPTED_HF_HOST}/api/models/${SCRYPTED_HF_REPO}/tree/${encodeURIComponent(revision)}?recursive=true&expand=true`;
341
+ let url = `${PLUGIN_CATALOG_HF_HOST}/api/models/${PLUGIN_CATALOG_HF_REPO}/tree/${encodeURIComponent(revision)}?recursive=true&expand=true`;
342
342
  let pages = 0;
343
343
  while (url) {
344
344
  pages += 1;
345
- if (pages > 50) throw new Error("Scrypted Hugging Face tree pagination exceeded the bound");
346
- assertScryptedTreePageUrl(new URL(url), revision);
345
+ if (pages > 50) throw new Error("plugin catalog Hugging Face tree pagination exceeded the bound");
346
+ assertPluginCatalogTreePageUrl(new URL(url), revision);
347
347
  const response = await opts.fetchImpl(url, {
348
348
  redirect: "manual",
349
349
  headers: { "User-Agent": "CamStack/1.0" }
350
350
  });
351
- if (response.status === 301 || response.status === 302 || response.status === 303 || response.status === 307 || response.status === 308) throw new ScryptedTreeLinkError(`Refusing tree API redirect ${response.status} (fail-closed, no follow)`);
352
- if (!response.ok) throw new Error(`HTTP ${response.status} fetching Scrypted Hugging Face tree`);
351
+ if (response.status === 301 || response.status === 302 || response.status === 303 || response.status === 307 || response.status === 308) throw new PluginCatalogTreeLinkError(`Refusing tree API redirect ${response.status} (fail-closed, no follow)`);
352
+ if (!response.ok) throw new Error(`HTTP ${response.status} fetching plugin catalog Hugging Face tree`);
353
353
  const payload = await response.json();
354
354
  for (const entry of payload) {
355
355
  if (entry.type !== "file" || !entry.path) continue;
@@ -359,20 +359,20 @@ async function fetchScryptedRemoteTree(opts) {
359
359
  ...entry.lfs !== void 0 ? { lfs: entry.lfs } : {}
360
360
  });
361
361
  }
362
- url = resolveScryptedTreeNextLink(response.headers.get("link") ?? "", url, revision);
362
+ url = resolvePluginCatalogTreeNextLink(response.headers.get("link") ?? "", url, revision);
363
363
  }
364
364
  return files;
365
365
  } catch (err) {
366
- if (err instanceof ScryptedTreeLinkError) throw err;
366
+ if (err instanceof PluginCatalogTreeLinkError) throw err;
367
367
  lastError = err instanceof Error ? err : new Error(String(err));
368
368
  await sleep(Math.min(retryDelayMs * 2 ** attempt, 3e3));
369
369
  }
370
- throw new Error(`Scrypted Hugging Face tree unavailable: ${lastError.message}`);
370
+ throw new Error(`plugin catalog Hugging Face tree unavailable: ${lastError.message}`);
371
371
  }
372
372
  //#endregion
373
- //#region src/scrypted/scrypted-import.ts
373
+ //#region src/plugin-catalog/plugin-catalog-import.ts
374
374
  /**
375
- * Server-owned Scrypted catalog import. The only client input is `manifestId`.
375
+ * Server-owned plugin catalog catalog import. The only client input is `manifestId`.
376
376
  * Downloads use the pinned host/repo/revision, a bounded staging dir, LFS /
377
377
  * size / checksum checks, and atomic finalize with cleanup on every failure.
378
378
  */
@@ -380,12 +380,12 @@ async function fetchScryptedRemoteTree(opts) {
380
380
  * Library registration descriptor: keeps manifesto remote URLs (HF resolve).
381
381
  * Files land on a node only via Distribute / downloadModel — not hub staging.
382
382
  */
383
- function buildScryptedRegistryDescriptor(entry) {
383
+ function buildPluginCatalogRegistryDescriptor(entry) {
384
384
  return {
385
385
  stepId: "object-detection",
386
386
  entry: {
387
387
  ...entry.model,
388
- classMap: SCRYPTED_IDENTITY_CLASS_MAP,
388
+ classMap: PLUGIN_CATALOG_IDENTITY_CLASS_MAP,
389
389
  formats: { ...entry.model.formats },
390
390
  name: entry.model.name,
391
391
  description: entry.model.description,
@@ -394,7 +394,7 @@ function buildScryptedRegistryDescriptor(entry) {
394
394
  };
395
395
  }
396
396
  //#endregion
397
- //#region ../types/dist/event-category-Ceif8n-v.mjs
397
+ //#region ../types/dist/event-category-DHXxB8t9.mjs
398
398
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
399
399
  EventCategory["SystemBoot"] = "system.boot";
400
400
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -690,7 +690,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
690
690
  * TRANSITION into that state (never per dispatch), and the node is dropped
691
691
  * from the placement candidate set for as long as it holds.
692
692
  *
693
- * This exists because the state was previously invisible: little-unraid
693
+ * This exists because the state was previously invisible: agent-a
694
694
  * absorbed 283k inference errors in a day while still being handed cameras,
695
695
  * and nothing in the system said so.
696
696
  *
@@ -5829,7 +5829,7 @@ var ZodIssueCode = {
5829
5829
  var ZodFirstPartyTypeKind;
5830
5830
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5831
5831
  //#endregion
5832
- //#region ../types/dist/sleep-CYfIZzGv.mjs
5832
+ //#region ../types/dist/sleep-BErAxhul.mjs
5833
5833
  /**
5834
5834
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5835
5835
  * window to float samples (D455).
@@ -8862,6 +8862,1980 @@ method(object({ deviceId: number() }), array(StreamSourceEntrySchema)), method(o
8862
8862
  kind: "mutation",
8863
8863
  auth: "admin"
8864
8864
  }), method(object({ deviceId: number() }), unknown().nullable()), method(object({ deviceId: number() }), RawStateResultSchema.nullable(), { auth: "protected" });
8865
+ Object.freeze({ "doorbell": "lastPressedAt" });
8866
+ /** Every capability name, so addon code can check a name without the schema graph. */
8867
+ var CAP_NAMES = Object.freeze([
8868
+ "accessories",
8869
+ "addon-pages",
8870
+ "addon-pages-source",
8871
+ "addon-routes",
8872
+ "addon-settings",
8873
+ "addon-widgets",
8874
+ "addon-widgets-source",
8875
+ "addons",
8876
+ "admin-ui",
8877
+ "air-quality-sensor",
8878
+ "alarm-panel",
8879
+ "alerts",
8880
+ "ambient-light-sensor",
8881
+ "audio-analysis",
8882
+ "audio-analyzer",
8883
+ "audio-codec",
8884
+ "audio-metrics",
8885
+ "auth-provider",
8886
+ "automation-control",
8887
+ "backup",
8888
+ "battery",
8889
+ "binary",
8890
+ "brightness",
8891
+ "broker",
8892
+ "button",
8893
+ "calendar-source",
8894
+ "calendars",
8895
+ "camera-credentials",
8896
+ "camera-grid-layout",
8897
+ "camera-pipeline-config",
8898
+ "camera-streams",
8899
+ "carbon-monoxide",
8900
+ "climate-control",
8901
+ "color",
8902
+ "composer",
8903
+ "connection-test",
8904
+ "connectivity",
8905
+ "consumables",
8906
+ "contact",
8907
+ "control",
8908
+ "core-blocks",
8909
+ "cover",
8910
+ "custom-model-registry",
8911
+ "data-store-provider",
8912
+ "database-snapshot",
8913
+ "day-night",
8914
+ "decoder",
8915
+ "detection-pipeline",
8916
+ "device-admin-link",
8917
+ "device-adoption",
8918
+ "device-credentials",
8919
+ "device-discovery",
8920
+ "device-export",
8921
+ "device-extension",
8922
+ "device-history",
8923
+ "device-manager",
8924
+ "device-ops",
8925
+ "device-provider",
8926
+ "device-removal-hook",
8927
+ "device-state",
8928
+ "device-status",
8929
+ "dishwasher",
8930
+ "display-palette",
8931
+ "doorbell",
8932
+ "embedding-encoder",
8933
+ "enum-sensor",
8934
+ "event-emitter",
8935
+ "face-gallery",
8936
+ "failure-contribution",
8937
+ "fan-control",
8938
+ "feature-probe",
8939
+ "filesystem-browse",
8940
+ "flood",
8941
+ "gas",
8942
+ "heating-valve",
8943
+ "humidifier",
8944
+ "humidity-sensor",
8945
+ "image",
8946
+ "image-settings",
8947
+ "integrations",
8948
+ "intercom",
8949
+ "keychain",
8950
+ "keychain-admin",
8951
+ "lawn-mower-control",
8952
+ "llm",
8953
+ "llm-runtime",
8954
+ "load-contribution",
8955
+ "local-network",
8956
+ "lock-control",
8957
+ "log-channels",
8958
+ "log-destination",
8959
+ "login-method",
8960
+ "media-player",
8961
+ "mesh-network",
8962
+ "metrics-provider",
8963
+ "model-convert",
8964
+ "model-distributor",
8965
+ "motion",
8966
+ "motion-detection",
8967
+ "motion-trigger",
8968
+ "motion-zones",
8969
+ "mqtt-broker",
8970
+ "native-object-detection",
8971
+ "navigation",
8972
+ "network-access",
8973
+ "network-link",
8974
+ "network-quality",
8975
+ "node-certificates",
8976
+ "nodes",
8977
+ "notification-output",
8978
+ "notification-rules",
8979
+ "notifier",
8980
+ "numeric-sensor",
8981
+ "oauth-integration",
8982
+ "oidc-connections",
8983
+ "osd",
8984
+ "osd-manager",
8985
+ "pet-feeder",
8986
+ "pipeline-analytics",
8987
+ "pipeline-executor",
8988
+ "pipeline-orchestrator",
8989
+ "pipeline-runner",
8990
+ "plate-gallery",
8991
+ "platform-probe",
8992
+ "power-meter",
8993
+ "presence",
8994
+ "pressure-sensor",
8995
+ "privacy-mask",
8996
+ "ptz",
8997
+ "ptz-autotrack",
8998
+ "reboot",
8999
+ "record-entries",
9000
+ "recording",
9001
+ "recording-archive",
9002
+ "recording-export",
9003
+ "recording-onboard",
9004
+ "recording-signal",
9005
+ "records",
9006
+ "running-state",
9007
+ "scene-monitor",
9008
+ "script-runner",
9009
+ "server-management",
9010
+ "settings-store",
9011
+ "smoke",
9012
+ "smtp-provider",
9013
+ "snapshot",
9014
+ "sso-bridge",
9015
+ "storage",
9016
+ "storage-admin",
9017
+ "storage-evictable",
9018
+ "storage-migration",
9019
+ "storage-occupancy",
9020
+ "storage-provider",
9021
+ "stream-broker",
9022
+ "stream-catalog",
9023
+ "stream-params",
9024
+ "stream-signals",
9025
+ "switch",
9026
+ "system",
9027
+ "tamper",
9028
+ "temperature-sensor",
9029
+ "terminal-session",
9030
+ "toast",
9031
+ "training",
9032
+ "training-provider",
9033
+ "turn-provider",
9034
+ "update",
9035
+ "user-management",
9036
+ "user-passkeys",
9037
+ "vacuum-control",
9038
+ "valve",
9039
+ "vector-store",
9040
+ "vibration",
9041
+ "videoclips",
9042
+ "viewer-ui",
9043
+ "water-heater",
9044
+ "weather",
9045
+ "webrtc-session",
9046
+ "zone-analytics",
9047
+ "zone-rules",
9048
+ "zones"
9049
+ ]);
9050
+ Object.freeze({
9051
+ "air-quality-sensor": [
9052
+ {
9053
+ "path": "co2Ppm",
9054
+ "valueType": "number"
9055
+ },
9056
+ {
9057
+ "path": "vocPpb",
9058
+ "valueType": "number"
9059
+ },
9060
+ {
9061
+ "path": "pm25",
9062
+ "valueType": "number"
9063
+ },
9064
+ {
9065
+ "path": "pm10",
9066
+ "valueType": "number"
9067
+ },
9068
+ {
9069
+ "path": "aqi",
9070
+ "valueType": "number"
9071
+ },
9072
+ {
9073
+ "path": "unit",
9074
+ "valueType": "string"
9075
+ },
9076
+ {
9077
+ "path": "precision",
9078
+ "valueType": "number"
9079
+ }
9080
+ ],
9081
+ "alarm-panel": [
9082
+ {
9083
+ "path": "state",
9084
+ "valueType": "enum",
9085
+ "enumValues": [
9086
+ "disarmed",
9087
+ "armed_home",
9088
+ "armed_away",
9089
+ "armed_night",
9090
+ "armed_vacation",
9091
+ "armed_custom_bypass",
9092
+ "arming",
9093
+ "disarming",
9094
+ "pending",
9095
+ "triggered"
9096
+ ]
9097
+ },
9098
+ {
9099
+ "path": "targetMode",
9100
+ "valueType": "enum",
9101
+ "enumValues": [
9102
+ "home",
9103
+ "away",
9104
+ "night",
9105
+ "vacation",
9106
+ "custom_bypass"
9107
+ ]
9108
+ },
9109
+ {
9110
+ "path": "requiresCode",
9111
+ "valueType": "boolean"
9112
+ }
9113
+ ],
9114
+ "ambient-light-sensor": [
9115
+ {
9116
+ "path": "lux",
9117
+ "valueType": "number"
9118
+ },
9119
+ {
9120
+ "path": "unit",
9121
+ "valueType": "string"
9122
+ },
9123
+ {
9124
+ "path": "precision",
9125
+ "valueType": "number"
9126
+ }
9127
+ ],
9128
+ "audio-metrics": [
9129
+ {
9130
+ "path": "ts",
9131
+ "valueType": "number"
9132
+ },
9133
+ {
9134
+ "path": "windowSec",
9135
+ "valueType": "number"
9136
+ },
9137
+ {
9138
+ "path": "level.rms",
9139
+ "valueType": "number"
9140
+ },
9141
+ {
9142
+ "path": "level.dbfs",
9143
+ "valueType": "number"
9144
+ },
9145
+ {
9146
+ "path": "peakDbfs",
9147
+ "valueType": "number"
9148
+ },
9149
+ {
9150
+ "path": "avgDbfs",
9151
+ "valueType": "number"
9152
+ },
9153
+ {
9154
+ "path": "current.className",
9155
+ "valueType": "string"
9156
+ },
9157
+ {
9158
+ "path": "current.score",
9159
+ "valueType": "number"
9160
+ },
9161
+ {
9162
+ "path": "current.timestamp",
9163
+ "valueType": "number"
9164
+ }
9165
+ ],
9166
+ "automation-control": [
9167
+ {
9168
+ "path": "enabled",
9169
+ "valueType": "boolean"
9170
+ },
9171
+ {
9172
+ "path": "isRunning",
9173
+ "valueType": "boolean"
9174
+ },
9175
+ {
9176
+ "path": "lastTriggeredAt",
9177
+ "valueType": "number"
9178
+ },
9179
+ {
9180
+ "path": "lastError",
9181
+ "valueType": "string"
9182
+ }
9183
+ ],
9184
+ "battery": [
9185
+ {
9186
+ "path": "percentage",
9187
+ "valueType": "number"
9188
+ },
9189
+ {
9190
+ "path": "charging",
9191
+ "valueType": "enum",
9192
+ "enumValues": [
9193
+ "dc",
9194
+ "solar",
9195
+ "none",
9196
+ "unknown"
9197
+ ]
9198
+ },
9199
+ {
9200
+ "path": "sleeping",
9201
+ "valueType": "boolean"
9202
+ },
9203
+ {
9204
+ "path": "lastUpdated",
9205
+ "valueType": "number"
9206
+ },
9207
+ {
9208
+ "path": "lastContactAt",
9209
+ "valueType": "number"
9210
+ },
9211
+ {
9212
+ "path": "lastFullRefreshAt",
9213
+ "valueType": "number"
9214
+ },
9215
+ {
9216
+ "path": "binary",
9217
+ "valueType": "boolean"
9218
+ }
9219
+ ],
9220
+ "binary": [{
9221
+ "path": "on",
9222
+ "valueType": "boolean"
9223
+ }],
9224
+ "brightness": [{
9225
+ "path": "percentage",
9226
+ "valueType": "number"
9227
+ }],
9228
+ "broker": [{
9229
+ "path": "brokerCount",
9230
+ "valueType": "number"
9231
+ }, {
9232
+ "path": "connectedCount",
9233
+ "valueType": "number"
9234
+ }],
9235
+ "camera-credentials": [
9236
+ {
9237
+ "path": "host",
9238
+ "valueType": "string"
9239
+ },
9240
+ {
9241
+ "path": "port",
9242
+ "valueType": "number"
9243
+ },
9244
+ {
9245
+ "path": "onvifPort",
9246
+ "valueType": "number"
9247
+ },
9248
+ {
9249
+ "path": "rtspPort",
9250
+ "valueType": "number"
9251
+ },
9252
+ {
9253
+ "path": "https",
9254
+ "valueType": "boolean"
9255
+ },
9256
+ {
9257
+ "path": "hasUsername",
9258
+ "valueType": "boolean"
9259
+ },
9260
+ {
9261
+ "path": "hasPassword",
9262
+ "valueType": "boolean"
9263
+ },
9264
+ {
9265
+ "path": "onvifProfile",
9266
+ "valueType": "string"
9267
+ }
9268
+ ],
9269
+ "camera-streams": [
9270
+ {
9271
+ "path": "online",
9272
+ "valueType": "boolean"
9273
+ },
9274
+ {
9275
+ "path": "slotStatuses.high",
9276
+ "valueType": "enum",
9277
+ "enumValues": [
9278
+ "unassigned",
9279
+ "idle",
9280
+ "connecting",
9281
+ "streaming",
9282
+ "error"
9283
+ ]
9284
+ },
9285
+ {
9286
+ "path": "slotStatuses.mid",
9287
+ "valueType": "enum",
9288
+ "enumValues": [
9289
+ "unassigned",
9290
+ "idle",
9291
+ "connecting",
9292
+ "streaming",
9293
+ "error"
9294
+ ]
9295
+ },
9296
+ {
9297
+ "path": "slotStatuses.low",
9298
+ "valueType": "enum",
9299
+ "enumValues": [
9300
+ "unassigned",
9301
+ "idle",
9302
+ "connecting",
9303
+ "streaming",
9304
+ "error"
9305
+ ]
9306
+ },
9307
+ {
9308
+ "path": "slotErrors.high",
9309
+ "valueType": "string"
9310
+ },
9311
+ {
9312
+ "path": "slotErrors.mid",
9313
+ "valueType": "string"
9314
+ },
9315
+ {
9316
+ "path": "slotErrors.low",
9317
+ "valueType": "string"
9318
+ }
9319
+ ],
9320
+ "carbon-monoxide": [{
9321
+ "path": "detected",
9322
+ "valueType": "boolean"
9323
+ }],
9324
+ "climate-control": [
9325
+ {
9326
+ "path": "mode",
9327
+ "valueType": "enum",
9328
+ "enumValues": [
9329
+ "off",
9330
+ "heat",
9331
+ "cool",
9332
+ "auto",
9333
+ "heat_cool",
9334
+ "fan_only",
9335
+ "dry"
9336
+ ]
9337
+ },
9338
+ {
9339
+ "path": "fanMode",
9340
+ "valueType": "string"
9341
+ },
9342
+ {
9343
+ "path": "preset",
9344
+ "valueType": "string"
9345
+ },
9346
+ {
9347
+ "path": "target",
9348
+ "valueType": "number"
9349
+ },
9350
+ {
9351
+ "path": "targetHigh",
9352
+ "valueType": "number"
9353
+ },
9354
+ {
9355
+ "path": "targetLow",
9356
+ "valueType": "number"
9357
+ },
9358
+ {
9359
+ "path": "targetHumidity",
9360
+ "valueType": "number"
9361
+ },
9362
+ {
9363
+ "path": "currentTemp",
9364
+ "valueType": "number"
9365
+ },
9366
+ {
9367
+ "path": "currentHumidity",
9368
+ "valueType": "number"
9369
+ },
9370
+ {
9371
+ "path": "swingVertical",
9372
+ "valueType": "boolean"
9373
+ },
9374
+ {
9375
+ "path": "swingHorizontal",
9376
+ "valueType": "boolean"
9377
+ },
9378
+ {
9379
+ "path": "minTemp",
9380
+ "valueType": "number"
9381
+ },
9382
+ {
9383
+ "path": "maxTemp",
9384
+ "valueType": "number"
9385
+ },
9386
+ {
9387
+ "path": "tempStep",
9388
+ "valueType": "number"
9389
+ }
9390
+ ],
9391
+ "color": [
9392
+ {
9393
+ "path": "mode",
9394
+ "valueType": "enum",
9395
+ "enumValues": [
9396
+ "rgb",
9397
+ "hsv",
9398
+ "mired"
9399
+ ]
9400
+ },
9401
+ {
9402
+ "path": "rgb.r",
9403
+ "valueType": "number"
9404
+ },
9405
+ {
9406
+ "path": "rgb.g",
9407
+ "valueType": "number"
9408
+ },
9409
+ {
9410
+ "path": "rgb.b",
9411
+ "valueType": "number"
9412
+ },
9413
+ {
9414
+ "path": "hsv.h",
9415
+ "valueType": "number"
9416
+ },
9417
+ {
9418
+ "path": "hsv.s",
9419
+ "valueType": "number"
9420
+ },
9421
+ {
9422
+ "path": "hsv.v",
9423
+ "valueType": "number"
9424
+ },
9425
+ {
9426
+ "path": "mireds",
9427
+ "valueType": "number"
9428
+ }
9429
+ ],
9430
+ "connectivity": [{
9431
+ "path": "connected",
9432
+ "valueType": "boolean"
9433
+ }],
9434
+ "contact": [{
9435
+ "path": "entryOpen",
9436
+ "valueType": "boolean"
9437
+ }],
9438
+ "control": [
9439
+ {
9440
+ "path": "kind",
9441
+ "valueType": "enum",
9442
+ "enumValues": [
9443
+ "numeric",
9444
+ "select",
9445
+ "text",
9446
+ "datetime"
9447
+ ]
9448
+ },
9449
+ {
9450
+ "path": "unit",
9451
+ "valueType": "string"
9452
+ },
9453
+ {
9454
+ "path": "min",
9455
+ "valueType": "number"
9456
+ },
9457
+ {
9458
+ "path": "max",
9459
+ "valueType": "number"
9460
+ },
9461
+ {
9462
+ "path": "step",
9463
+ "valueType": "number"
9464
+ },
9465
+ {
9466
+ "path": "precision",
9467
+ "valueType": "number"
9468
+ },
9469
+ {
9470
+ "path": "format",
9471
+ "valueType": "enum",
9472
+ "enumValues": [
9473
+ "date",
9474
+ "time",
9475
+ "datetime"
9476
+ ]
9477
+ }
9478
+ ],
9479
+ "cover": [
9480
+ {
9481
+ "path": "state",
9482
+ "valueType": "enum",
9483
+ "enumValues": [
9484
+ "open",
9485
+ "opening",
9486
+ "closing",
9487
+ "closed",
9488
+ "stopped"
9489
+ ]
9490
+ },
9491
+ {
9492
+ "path": "position",
9493
+ "valueType": "number"
9494
+ },
9495
+ {
9496
+ "path": "tiltPosition",
9497
+ "valueType": "number"
9498
+ }
9499
+ ],
9500
+ "day-night": [
9501
+ {
9502
+ "path": "mode",
9503
+ "valueType": "enum",
9504
+ "enumValues": [
9505
+ "auto",
9506
+ "day",
9507
+ "night",
9508
+ "schedule"
9509
+ ]
9510
+ },
9511
+ {
9512
+ "path": "sensitivity",
9513
+ "valueType": "number"
9514
+ },
9515
+ {
9516
+ "path": "switchDelaySec",
9517
+ "valueType": "number"
9518
+ }
9519
+ ],
9520
+ "device-adoption": [
9521
+ {
9522
+ "path": "lastDiscoveryAt",
9523
+ "valueType": "number"
9524
+ },
9525
+ {
9526
+ "path": "candidateCount",
9527
+ "valueType": "number"
9528
+ },
9529
+ {
9530
+ "path": "adoptedCount",
9531
+ "valueType": "number"
9532
+ },
9533
+ {
9534
+ "path": "lastError",
9535
+ "valueType": "string"
9536
+ }
9537
+ ],
9538
+ "device-discovery": [{
9539
+ "path": "lastDiscoveryAt",
9540
+ "valueType": "number"
9541
+ }, {
9542
+ "path": "lastError",
9543
+ "valueType": "string"
9544
+ }],
9545
+ "device-export": [
9546
+ {
9547
+ "path": "linkState",
9548
+ "valueType": "enum",
9549
+ "enumValues": [
9550
+ "unlinked",
9551
+ "linked",
9552
+ "error"
9553
+ ]
9554
+ },
9555
+ {
9556
+ "path": "exposedDeviceCount",
9557
+ "valueType": "number"
9558
+ },
9559
+ {
9560
+ "path": "error",
9561
+ "valueType": "string"
9562
+ },
9563
+ {
9564
+ "path": "setup.qr",
9565
+ "valueType": "string"
9566
+ },
9567
+ {
9568
+ "path": "setup.note",
9569
+ "valueType": "string"
9570
+ }
9571
+ ],
9572
+ "device-status": [{
9573
+ "path": "online",
9574
+ "valueType": "boolean"
9575
+ }],
9576
+ "dishwasher": [
9577
+ {
9578
+ "path": "availability",
9579
+ "valueType": "enum",
9580
+ "enumValues": [
9581
+ "available",
9582
+ "offline",
9583
+ "description-missing"
9584
+ ]
9585
+ },
9586
+ {
9587
+ "path": "state",
9588
+ "valueType": "enum",
9589
+ "enumValues": [
9590
+ "idle",
9591
+ "running",
9592
+ "paused",
9593
+ "finished",
9594
+ "error",
9595
+ "unavailable"
9596
+ ]
9597
+ },
9598
+ {
9599
+ "path": "operationState",
9600
+ "valueType": "enum",
9601
+ "enumValues": [
9602
+ "Inactive",
9603
+ "Ready",
9604
+ "DelayedStart",
9605
+ "Run",
9606
+ "Pause",
9607
+ "ActionRequired",
9608
+ "Finished",
9609
+ "Error",
9610
+ "Aborting"
9611
+ ]
9612
+ },
9613
+ {
9614
+ "path": "program",
9615
+ "valueType": "string"
9616
+ },
9617
+ {
9618
+ "path": "selectedProgram",
9619
+ "valueType": "string"
9620
+ },
9621
+ {
9622
+ "path": "remainingSeconds",
9623
+ "valueType": "number"
9624
+ },
9625
+ {
9626
+ "path": "delayedStartSeconds",
9627
+ "valueType": "number"
9628
+ },
9629
+ {
9630
+ "path": "progressPercent",
9631
+ "valueType": "number"
9632
+ },
9633
+ {
9634
+ "path": "doorOpen",
9635
+ "valueType": "boolean"
9636
+ },
9637
+ {
9638
+ "path": "doorLocked",
9639
+ "valueType": "boolean"
9640
+ },
9641
+ {
9642
+ "path": "remoteStartAllowed",
9643
+ "valueType": "boolean"
9644
+ },
9645
+ {
9646
+ "path": "remoteControlActive",
9647
+ "valueType": "boolean"
9648
+ },
9649
+ {
9650
+ "path": "localControlActive",
9651
+ "valueType": "boolean"
9652
+ },
9653
+ {
9654
+ "path": "powerOn",
9655
+ "valueType": "boolean"
9656
+ },
9657
+ {
9658
+ "path": "powerState",
9659
+ "valueType": "string"
9660
+ },
9661
+ {
9662
+ "path": "filterCleaningDue",
9663
+ "valueType": "boolean"
9664
+ },
9665
+ {
9666
+ "path": "machineCareDue",
9667
+ "valueType": "boolean"
9668
+ },
9669
+ {
9670
+ "path": "machineCareRemainingRuns",
9671
+ "valueType": "number"
9672
+ },
9673
+ {
9674
+ "path": "halfLoad",
9675
+ "valueType": "boolean"
9676
+ },
9677
+ {
9678
+ "path": "hygienePlus",
9679
+ "valueType": "boolean"
9680
+ },
9681
+ {
9682
+ "path": "extraDry",
9683
+ "valueType": "boolean"
9684
+ },
9685
+ {
9686
+ "path": "intensiveZone",
9687
+ "valueType": "boolean"
9688
+ },
9689
+ {
9690
+ "path": "varioSpeedPlus",
9691
+ "valueType": "boolean"
9692
+ },
9693
+ {
9694
+ "path": "childLock",
9695
+ "valueType": "boolean"
9696
+ },
9697
+ {
9698
+ "path": "errorCode",
9699
+ "valueType": "number"
9700
+ },
9701
+ {
9702
+ "path": "errorLabel",
9703
+ "valueType": "string"
9704
+ }
9705
+ ],
9706
+ "doorbell": [{
9707
+ "path": "lastPressedAt",
9708
+ "valueType": "number"
9709
+ }, {
9710
+ "path": "pressCountSinceStart",
9711
+ "valueType": "number"
9712
+ }],
9713
+ "enum-sensor": [{
9714
+ "path": "value",
9715
+ "valueType": "string"
9716
+ }, {
9717
+ "path": "format",
9718
+ "valueType": "enum",
9719
+ "enumValues": [
9720
+ "date",
9721
+ "time",
9722
+ "datetime"
9723
+ ]
9724
+ }],
9725
+ "event-emitter": [
9726
+ {
9727
+ "path": "lastEvent.deviceId",
9728
+ "valueType": "number"
9729
+ },
9730
+ {
9731
+ "path": "lastEvent.eventType",
9732
+ "valueType": "string"
9733
+ },
9734
+ {
9735
+ "path": "lastEvent.timestamp",
9736
+ "valueType": "number"
9737
+ },
9738
+ {
9739
+ "path": "lastEvent.seq",
9740
+ "valueType": "number"
9741
+ },
9742
+ {
9743
+ "path": "eventCountSinceStart",
9744
+ "valueType": "number"
9745
+ }
9746
+ ],
9747
+ "fan-control": [
9748
+ {
9749
+ "path": "percentage",
9750
+ "valueType": "number"
9751
+ },
9752
+ {
9753
+ "path": "percentageStep",
9754
+ "valueType": "number"
9755
+ },
9756
+ {
9757
+ "path": "preset",
9758
+ "valueType": "string"
9759
+ },
9760
+ {
9761
+ "path": "direction",
9762
+ "valueType": "enum",
9763
+ "enumValues": ["forward", "reverse"]
9764
+ },
9765
+ {
9766
+ "path": "oscillating",
9767
+ "valueType": "boolean"
9768
+ }
9769
+ ],
9770
+ "feature-probe": [
9771
+ {
9772
+ "path": "deviceType",
9773
+ "valueType": "string"
9774
+ },
9775
+ {
9776
+ "path": "model",
9777
+ "valueType": "string"
9778
+ },
9779
+ {
9780
+ "path": "channelCount",
9781
+ "valueType": "number"
9782
+ },
9783
+ {
9784
+ "path": "lastProbedAt",
9785
+ "valueType": "number"
9786
+ }
9787
+ ],
9788
+ "flood": [{
9789
+ "path": "flooded",
9790
+ "valueType": "boolean"
9791
+ }],
9792
+ "gas": [{
9793
+ "path": "detected",
9794
+ "valueType": "boolean"
9795
+ }],
9796
+ "heating-valve": [{
9797
+ "path": "position",
9798
+ "valueType": "number"
9799
+ }],
9800
+ "humidifier": [
9801
+ {
9802
+ "path": "on",
9803
+ "valueType": "boolean"
9804
+ },
9805
+ {
9806
+ "path": "currentHumidity",
9807
+ "valueType": "number"
9808
+ },
9809
+ {
9810
+ "path": "targetHumidity",
9811
+ "valueType": "number"
9812
+ },
9813
+ {
9814
+ "path": "mode",
9815
+ "valueType": "string"
9816
+ },
9817
+ {
9818
+ "path": "action",
9819
+ "valueType": "string"
9820
+ },
9821
+ {
9822
+ "path": "minHumidity",
9823
+ "valueType": "number"
9824
+ },
9825
+ {
9826
+ "path": "maxHumidity",
9827
+ "valueType": "number"
9828
+ }
9829
+ ],
9830
+ "humidity-sensor": [
9831
+ {
9832
+ "path": "percent",
9833
+ "valueType": "number"
9834
+ },
9835
+ {
9836
+ "path": "unit",
9837
+ "valueType": "string"
9838
+ },
9839
+ {
9840
+ "path": "precision",
9841
+ "valueType": "number"
9842
+ }
9843
+ ],
9844
+ "image": [{
9845
+ "path": "url",
9846
+ "valueType": "string"
9847
+ }, {
9848
+ "path": "lastUpdated",
9849
+ "valueType": "number"
9850
+ }],
9851
+ "image-settings": [
9852
+ {
9853
+ "path": "brightness",
9854
+ "valueType": "number"
9855
+ },
9856
+ {
9857
+ "path": "contrast",
9858
+ "valueType": "number"
9859
+ },
9860
+ {
9861
+ "path": "saturation",
9862
+ "valueType": "number"
9863
+ },
9864
+ {
9865
+ "path": "sharpness",
9866
+ "valueType": "number"
9867
+ },
9868
+ {
9869
+ "path": "mirror",
9870
+ "valueType": "boolean"
9871
+ },
9872
+ {
9873
+ "path": "flip",
9874
+ "valueType": "boolean"
9875
+ },
9876
+ {
9877
+ "path": "rotate",
9878
+ "valueType": "enum",
9879
+ "enumValues": [
9880
+ "0",
9881
+ "90",
9882
+ "180",
9883
+ "270"
9884
+ ]
9885
+ },
9886
+ {
9887
+ "path": "whiteBalance",
9888
+ "valueType": "enum",
9889
+ "enumValues": ["auto", "manual"]
9890
+ },
9891
+ {
9892
+ "path": "warmth",
9893
+ "valueType": "number"
9894
+ },
9895
+ {
9896
+ "path": "exposureMode",
9897
+ "valueType": "enum",
9898
+ "enumValues": ["auto", "manual"]
9899
+ },
9900
+ {
9901
+ "path": "backlightMode",
9902
+ "valueType": "enum",
9903
+ "enumValues": [
9904
+ "off",
9905
+ "blc",
9906
+ "wdr",
9907
+ "hlc"
9908
+ ]
9909
+ }
9910
+ ],
9911
+ "intercom": [
9912
+ {
9913
+ "path": "talking",
9914
+ "valueType": "boolean"
9915
+ },
9916
+ {
9917
+ "path": "lastSessionAt",
9918
+ "valueType": "number"
9919
+ },
9920
+ {
9921
+ "path": "ability.sampleRate",
9922
+ "valueType": "number"
9923
+ },
9924
+ {
9925
+ "path": "ability.duplex",
9926
+ "valueType": "enum",
9927
+ "enumValues": ["half", "full"]
9928
+ },
9929
+ {
9930
+ "path": "ability.maxBacklogMs",
9931
+ "valueType": "number"
9932
+ }
9933
+ ],
9934
+ "lawn-mower-control": [
9935
+ {
9936
+ "path": "activity",
9937
+ "valueType": "enum",
9938
+ "enumValues": [
9939
+ "idle",
9940
+ "mowing",
9941
+ "paused",
9942
+ "docked",
9943
+ "error"
9944
+ ]
9945
+ },
9946
+ {
9947
+ "path": "batteryLevel",
9948
+ "valueType": "number"
9949
+ },
9950
+ {
9951
+ "path": "progressPercent",
9952
+ "valueType": "number"
9953
+ },
9954
+ {
9955
+ "path": "currentCode",
9956
+ "valueType": "number"
9957
+ },
9958
+ {
9959
+ "path": "currentCodeLabel",
9960
+ "valueType": "string"
9961
+ },
9962
+ {
9963
+ "path": "severity",
9964
+ "valueType": "enum",
9965
+ "enumValues": [
9966
+ "info",
9967
+ "warning",
9968
+ "error"
9969
+ ]
9970
+ }
9971
+ ],
9972
+ "lock-control": [{
9973
+ "path": "state",
9974
+ "valueType": "enum",
9975
+ "enumValues": [
9976
+ "locked",
9977
+ "unlocked",
9978
+ "locking",
9979
+ "unlocking",
9980
+ "jammed"
9981
+ ]
9982
+ }],
9983
+ "media-player": [
9984
+ {
9985
+ "path": "state",
9986
+ "valueType": "enum",
9987
+ "enumValues": [
9988
+ "off",
9989
+ "on",
9990
+ "idle",
9991
+ "playing",
9992
+ "paused",
9993
+ "buffering",
9994
+ "standby"
9995
+ ]
9996
+ },
9997
+ {
9998
+ "path": "volumeLevel",
9999
+ "valueType": "number"
10000
+ },
10001
+ {
10002
+ "path": "isMuted",
10003
+ "valueType": "boolean"
10004
+ },
10005
+ {
10006
+ "path": "source",
10007
+ "valueType": "string"
10008
+ },
10009
+ {
10010
+ "path": "currentMedia.type",
10011
+ "valueType": "string"
10012
+ },
10013
+ {
10014
+ "path": "currentMedia.title",
10015
+ "valueType": "string"
10016
+ },
10017
+ {
10018
+ "path": "currentMedia.artist",
10019
+ "valueType": "string"
10020
+ },
10021
+ {
10022
+ "path": "currentMedia.album",
10023
+ "valueType": "string"
10024
+ },
10025
+ {
10026
+ "path": "currentMedia.imageUrl",
10027
+ "valueType": "string"
10028
+ },
10029
+ {
10030
+ "path": "positionMs",
10031
+ "valueType": "number"
10032
+ },
10033
+ {
10034
+ "path": "durationMs",
10035
+ "valueType": "number"
10036
+ },
10037
+ {
10038
+ "path": "shuffle",
10039
+ "valueType": "boolean"
10040
+ },
10041
+ {
10042
+ "path": "repeat",
10043
+ "valueType": "enum",
10044
+ "enumValues": [
10045
+ "off",
10046
+ "all",
10047
+ "one"
10048
+ ]
10049
+ }
10050
+ ],
10051
+ "motion": [
10052
+ {
10053
+ "path": "detected",
10054
+ "valueType": "boolean"
10055
+ },
10056
+ {
10057
+ "path": "lastDetectedAt",
10058
+ "valueType": "number"
10059
+ },
10060
+ {
10061
+ "path": "autoClearAfterMs",
10062
+ "valueType": "number"
10063
+ }
10064
+ ],
10065
+ "motion-trigger": [{
10066
+ "path": "enabled",
10067
+ "valueType": "boolean"
10068
+ }],
10069
+ "motion-zones": [{
10070
+ "path": "enabled",
10071
+ "valueType": "boolean"
10072
+ }, {
10073
+ "path": "sensitivity",
10074
+ "valueType": "number"
10075
+ }],
10076
+ "mqtt-broker": [{
10077
+ "path": "brokerCount",
10078
+ "valueType": "number"
10079
+ }, {
10080
+ "path": "embeddedRunning",
10081
+ "valueType": "boolean"
10082
+ }],
10083
+ "native-object-detection": [{
10084
+ "path": "enabled",
10085
+ "valueType": "boolean"
10086
+ }],
10087
+ "navigation": [
10088
+ {
10089
+ "path": "mode",
10090
+ "valueType": "enum",
10091
+ "enumValues": [
10092
+ "idle",
10093
+ "cleaning",
10094
+ "spot",
10095
+ "following",
10096
+ "goto",
10097
+ "returning",
10098
+ "paused",
10099
+ "unknown"
10100
+ ]
10101
+ },
10102
+ {
10103
+ "path": "following",
10104
+ "valueType": "boolean"
10105
+ },
10106
+ {
10107
+ "path": "flash",
10108
+ "valueType": "boolean"
10109
+ },
10110
+ {
10111
+ "path": "lightMode",
10112
+ "valueType": "enum",
10113
+ "enumValues": ["auto", "manual"]
10114
+ },
10115
+ {
10116
+ "path": "lightLevel",
10117
+ "valueType": "number"
10118
+ }
10119
+ ],
10120
+ "network-link": [
10121
+ {
10122
+ "path": "type",
10123
+ "valueType": "enum",
10124
+ "enumValues": [
10125
+ "wifi",
10126
+ "ethernet",
10127
+ "cellular",
10128
+ "unknown"
10129
+ ]
10130
+ },
10131
+ {
10132
+ "path": "signalPercent",
10133
+ "valueType": "number"
10134
+ },
10135
+ {
10136
+ "path": "rssiDbm",
10137
+ "valueType": "number"
10138
+ },
10139
+ {
10140
+ "path": "ssid",
10141
+ "valueType": "string"
10142
+ },
10143
+ {
10144
+ "path": "lastUpdated",
10145
+ "valueType": "number"
10146
+ }
10147
+ ],
10148
+ "notifier": [
10149
+ {
10150
+ "path": "lastSentAt",
10151
+ "valueType": "number"
10152
+ },
10153
+ {
10154
+ "path": "lastError",
10155
+ "valueType": "string"
10156
+ },
10157
+ {
10158
+ "path": "queueDepth",
10159
+ "valueType": "number"
10160
+ },
10161
+ {
10162
+ "path": "supports.image",
10163
+ "valueType": "boolean"
10164
+ },
10165
+ {
10166
+ "path": "supports.priority",
10167
+ "valueType": "boolean"
10168
+ },
10169
+ {
10170
+ "path": "supports.data",
10171
+ "valueType": "boolean"
10172
+ },
10173
+ {
10174
+ "path": "supports.actions",
10175
+ "valueType": "boolean"
10176
+ },
10177
+ {
10178
+ "path": "supports.recipients",
10179
+ "valueType": "boolean"
10180
+ }
10181
+ ],
10182
+ "numeric-sensor": [
10183
+ {
10184
+ "path": "value",
10185
+ "valueType": "number"
10186
+ },
10187
+ {
10188
+ "path": "unit",
10189
+ "valueType": "string"
10190
+ },
10191
+ {
10192
+ "path": "precision",
10193
+ "valueType": "number"
10194
+ }
10195
+ ],
10196
+ "pet-feeder": [
10197
+ {
10198
+ "path": "foodLevel",
10199
+ "valueType": "number"
10200
+ },
10201
+ {
10202
+ "path": "food1",
10203
+ "valueType": "number"
10204
+ },
10205
+ {
10206
+ "path": "food2",
10207
+ "valueType": "number"
10208
+ },
10209
+ {
10210
+ "path": "lowFood",
10211
+ "valueType": "boolean"
10212
+ },
10213
+ {
10214
+ "path": "batteryPower",
10215
+ "valueType": "number"
10216
+ },
10217
+ {
10218
+ "path": "desiccantLeftDays",
10219
+ "valueType": "number"
10220
+ },
10221
+ {
10222
+ "path": "feeding",
10223
+ "valueType": "boolean"
10224
+ },
10225
+ {
10226
+ "path": "status",
10227
+ "valueType": "enum",
10228
+ "enumValues": [
10229
+ "normal",
10230
+ "offline",
10231
+ "on_batteries"
10232
+ ]
10233
+ },
10234
+ {
10235
+ "path": "error",
10236
+ "valueType": "string"
10237
+ },
10238
+ {
10239
+ "path": "errorCode",
10240
+ "valueType": "number"
10241
+ },
10242
+ {
10243
+ "path": "isDualHopper",
10244
+ "valueType": "boolean"
10245
+ },
10246
+ {
10247
+ "path": "childLock",
10248
+ "valueType": "boolean"
10249
+ },
10250
+ {
10251
+ "path": "indicatorLight",
10252
+ "valueType": "boolean"
10253
+ },
10254
+ {
10255
+ "path": "feedSound",
10256
+ "valueType": "boolean"
10257
+ },
10258
+ {
10259
+ "path": "volume",
10260
+ "valueType": "number"
10261
+ }
10262
+ ],
10263
+ "power-meter": [
10264
+ {
10265
+ "path": "watts",
10266
+ "valueType": "number"
10267
+ },
10268
+ {
10269
+ "path": "kwhTotal",
10270
+ "valueType": "number"
10271
+ },
10272
+ {
10273
+ "path": "volts",
10274
+ "valueType": "number"
10275
+ },
10276
+ {
10277
+ "path": "amps",
10278
+ "valueType": "number"
10279
+ },
10280
+ {
10281
+ "path": "va",
10282
+ "valueType": "number"
10283
+ },
10284
+ {
10285
+ "path": "powerFactor",
10286
+ "valueType": "number"
10287
+ },
10288
+ {
10289
+ "path": "unit",
10290
+ "valueType": "string"
10291
+ },
10292
+ {
10293
+ "path": "precision",
10294
+ "valueType": "number"
10295
+ }
10296
+ ],
10297
+ "presence": [
10298
+ {
10299
+ "path": "state",
10300
+ "valueType": "string"
10301
+ },
10302
+ {
10303
+ "path": "location",
10304
+ "valueType": "string"
10305
+ },
10306
+ {
10307
+ "path": "gps.latitude",
10308
+ "valueType": "number"
10309
+ },
10310
+ {
10311
+ "path": "gps.longitude",
10312
+ "valueType": "number"
10313
+ },
10314
+ {
10315
+ "path": "gps.accuracyMeters",
10316
+ "valueType": "number"
10317
+ },
10318
+ {
10319
+ "path": "batteryPercent",
10320
+ "valueType": "number"
10321
+ }
10322
+ ],
10323
+ "pressure-sensor": [
10324
+ {
10325
+ "path": "hpa",
10326
+ "valueType": "number"
10327
+ },
10328
+ {
10329
+ "path": "unit",
10330
+ "valueType": "string"
10331
+ },
10332
+ {
10333
+ "path": "precision",
10334
+ "valueType": "number"
10335
+ }
10336
+ ],
10337
+ "privacy-mask": [{
10338
+ "path": "enabled",
10339
+ "valueType": "boolean"
10340
+ }, {
10341
+ "path": "audioEnabled",
10342
+ "valueType": "boolean"
10343
+ }],
10344
+ "ptz": [
10345
+ {
10346
+ "path": "pan",
10347
+ "valueType": "number"
10348
+ },
10349
+ {
10350
+ "path": "tilt",
10351
+ "valueType": "number"
10352
+ },
10353
+ {
10354
+ "path": "zoom",
10355
+ "valueType": "number"
10356
+ },
10357
+ {
10358
+ "path": "autofocus",
10359
+ "valueType": "boolean"
10360
+ }
10361
+ ],
10362
+ "ptz-autotrack": [
10363
+ {
10364
+ "path": "enabled",
10365
+ "valueType": "boolean"
10366
+ },
10367
+ {
10368
+ "path": "currentSettings.targetType",
10369
+ "valueType": "string"
10370
+ },
10371
+ {
10372
+ "path": "currentSettings.stopDelaySeconds",
10373
+ "valueType": "number"
10374
+ },
10375
+ {
10376
+ "path": "currentSettings.disappearDelaySeconds",
10377
+ "valueType": "number"
10378
+ }
10379
+ ],
10380
+ "recording-archive": [
10381
+ {
10382
+ "path": "deviceId",
10383
+ "valueType": "number"
10384
+ },
10385
+ {
10386
+ "path": "enabled",
10387
+ "valueType": "boolean"
10388
+ },
10389
+ {
10390
+ "path": "activeMode",
10391
+ "valueType": "enum",
10392
+ "enumValues": [
10393
+ "off",
10394
+ "events",
10395
+ "continuous",
10396
+ "on-device-decision"
10397
+ ]
10398
+ },
10399
+ {
10400
+ "path": "nodeId",
10401
+ "valueType": "string"
10402
+ },
10403
+ {
10404
+ "path": "storageBytes",
10405
+ "valueType": "number"
10406
+ }
10407
+ ],
10408
+ "recording-onboard": [
10409
+ {
10410
+ "path": "primaryTrackId",
10411
+ "valueType": "string"
10412
+ },
10413
+ {
10414
+ "path": "enabled",
10415
+ "valueType": "boolean"
10416
+ },
10417
+ {
10418
+ "path": "overwriteWhenFull",
10419
+ "valueType": "boolean"
10420
+ },
10421
+ {
10422
+ "path": "preRecordSec",
10423
+ "valueType": "number"
10424
+ },
10425
+ {
10426
+ "path": "postRecordSec",
10427
+ "valueType": "number"
10428
+ },
10429
+ {
10430
+ "path": "segmentMinutes",
10431
+ "valueType": "number"
10432
+ },
10433
+ {
10434
+ "path": "unreadableWindows",
10435
+ "valueType": "number"
10436
+ },
10437
+ {
10438
+ "path": "recordingToNowhere",
10439
+ "valueType": "boolean"
10440
+ }
10441
+ ],
10442
+ "recording-signal": [{
10443
+ "path": "active",
10444
+ "valueType": "boolean"
10445
+ }, {
10446
+ "path": "reason",
10447
+ "valueType": "string"
10448
+ }],
10449
+ "running-state": [
10450
+ {
10451
+ "path": "running",
10452
+ "valueType": "boolean"
10453
+ },
10454
+ {
10455
+ "path": "since",
10456
+ "valueType": "number"
10457
+ },
10458
+ {
10459
+ "path": "source",
10460
+ "valueType": "enum",
10461
+ "enumValues": ["native", "assigned"]
10462
+ },
10463
+ {
10464
+ "path": "phase",
10465
+ "valueType": "string"
10466
+ }
10467
+ ],
10468
+ "script-runner": [
10469
+ {
10470
+ "path": "isRunning",
10471
+ "valueType": "boolean"
10472
+ },
10473
+ {
10474
+ "path": "lastRunAt",
10475
+ "valueType": "number"
10476
+ },
10477
+ {
10478
+ "path": "lastRunSuccess",
10479
+ "valueType": "boolean"
10480
+ },
10481
+ {
10482
+ "path": "lastError",
10483
+ "valueType": "string"
10484
+ }
10485
+ ],
10486
+ "smoke": [{
10487
+ "path": "detected",
10488
+ "valueType": "boolean"
10489
+ }],
10490
+ "snapshot": [
10491
+ {
10492
+ "path": "lastCapturedAt",
10493
+ "valueType": "number"
10494
+ },
10495
+ {
10496
+ "path": "cacheAgeMs",
10497
+ "valueType": "number"
10498
+ },
10499
+ {
10500
+ "path": "lastBytes",
10501
+ "valueType": "number"
10502
+ },
10503
+ {
10504
+ "path": "lastStreamId",
10505
+ "valueType": "string"
10506
+ }
10507
+ ],
10508
+ "stream-params": [
10509
+ {
10510
+ "path": "main.width",
10511
+ "valueType": "number"
10512
+ },
10513
+ {
10514
+ "path": "main.height",
10515
+ "valueType": "number"
10516
+ },
10517
+ {
10518
+ "path": "main.codec",
10519
+ "valueType": "enum",
10520
+ "enumValues": ["h264", "h265"]
10521
+ },
10522
+ {
10523
+ "path": "main.framerate",
10524
+ "valueType": "number"
10525
+ },
10526
+ {
10527
+ "path": "main.bitrate",
10528
+ "valueType": "number"
10529
+ },
10530
+ {
10531
+ "path": "main.bitrateMode",
10532
+ "valueType": "enum",
10533
+ "enumValues": ["vbr", "cbr"]
10534
+ },
10535
+ {
10536
+ "path": "main.encoderProfile",
10537
+ "valueType": "enum",
10538
+ "enumValues": [
10539
+ "high",
10540
+ "main",
10541
+ "baseline"
10542
+ ]
10543
+ },
10544
+ {
10545
+ "path": "main.gop",
10546
+ "valueType": "number"
10547
+ },
10548
+ {
10549
+ "path": "main.audio",
10550
+ "valueType": "boolean"
10551
+ },
10552
+ {
10553
+ "path": "sub.width",
10554
+ "valueType": "number"
10555
+ },
10556
+ {
10557
+ "path": "sub.height",
10558
+ "valueType": "number"
10559
+ },
10560
+ {
10561
+ "path": "sub.codec",
10562
+ "valueType": "enum",
10563
+ "enumValues": ["h264", "h265"]
10564
+ },
10565
+ {
10566
+ "path": "sub.framerate",
10567
+ "valueType": "number"
10568
+ },
10569
+ {
10570
+ "path": "sub.bitrate",
10571
+ "valueType": "number"
10572
+ },
10573
+ {
10574
+ "path": "sub.bitrateMode",
10575
+ "valueType": "enum",
10576
+ "enumValues": ["vbr", "cbr"]
10577
+ },
10578
+ {
10579
+ "path": "sub.encoderProfile",
10580
+ "valueType": "enum",
10581
+ "enumValues": [
10582
+ "high",
10583
+ "main",
10584
+ "baseline"
10585
+ ]
10586
+ },
10587
+ {
10588
+ "path": "sub.gop",
10589
+ "valueType": "number"
10590
+ },
10591
+ {
10592
+ "path": "sub.audio",
10593
+ "valueType": "boolean"
10594
+ },
10595
+ {
10596
+ "path": "ext.width",
10597
+ "valueType": "number"
10598
+ },
10599
+ {
10600
+ "path": "ext.height",
10601
+ "valueType": "number"
10602
+ },
10603
+ {
10604
+ "path": "ext.codec",
10605
+ "valueType": "enum",
10606
+ "enumValues": ["h264", "h265"]
10607
+ },
10608
+ {
10609
+ "path": "ext.framerate",
10610
+ "valueType": "number"
10611
+ },
10612
+ {
10613
+ "path": "ext.bitrate",
10614
+ "valueType": "number"
10615
+ },
10616
+ {
10617
+ "path": "ext.bitrateMode",
10618
+ "valueType": "enum",
10619
+ "enumValues": ["vbr", "cbr"]
10620
+ },
10621
+ {
10622
+ "path": "ext.encoderProfile",
10623
+ "valueType": "enum",
10624
+ "enumValues": [
10625
+ "high",
10626
+ "main",
10627
+ "baseline"
10628
+ ]
10629
+ },
10630
+ {
10631
+ "path": "ext.gop",
10632
+ "valueType": "number"
10633
+ },
10634
+ {
10635
+ "path": "ext.audio",
10636
+ "valueType": "boolean"
10637
+ }
10638
+ ],
10639
+ "switch": [{
10640
+ "path": "on",
10641
+ "valueType": "boolean"
10642
+ }],
10643
+ "tamper": [{
10644
+ "path": "tampered",
10645
+ "valueType": "boolean"
10646
+ }],
10647
+ "temperature-sensor": [
10648
+ {
10649
+ "path": "celsius",
10650
+ "valueType": "number"
10651
+ },
10652
+ {
10653
+ "path": "unit",
10654
+ "valueType": "string"
10655
+ },
10656
+ {
10657
+ "path": "precision",
10658
+ "valueType": "number"
10659
+ }
10660
+ ],
10661
+ "update": [
10662
+ {
10663
+ "path": "currentVersion",
10664
+ "valueType": "string"
10665
+ },
10666
+ {
10667
+ "path": "availableVersion",
10668
+ "valueType": "string"
10669
+ },
10670
+ {
10671
+ "path": "updatable",
10672
+ "valueType": "boolean"
10673
+ },
10674
+ {
10675
+ "path": "state",
10676
+ "valueType": "string"
10677
+ },
10678
+ {
10679
+ "path": "inProgress",
10680
+ "valueType": "boolean"
10681
+ }
10682
+ ],
10683
+ "vacuum-control": [
10684
+ {
10685
+ "path": "state",
10686
+ "valueType": "enum",
10687
+ "enumValues": [
10688
+ "idle",
10689
+ "cleaning",
10690
+ "paused",
10691
+ "returning",
10692
+ "docked",
10693
+ "drying",
10694
+ "error"
10695
+ ]
10696
+ },
10697
+ {
10698
+ "path": "batteryLevel",
10699
+ "valueType": "number"
10700
+ },
10701
+ {
10702
+ "path": "fanSpeed",
10703
+ "valueType": "string"
10704
+ },
10705
+ {
10706
+ "path": "progressPercent",
10707
+ "valueType": "number"
10708
+ },
10709
+ {
10710
+ "path": "errorCode",
10711
+ "valueType": "number"
10712
+ },
10713
+ {
10714
+ "path": "errorLabel",
10715
+ "valueType": "string"
10716
+ }
10717
+ ],
10718
+ "valve": [{
10719
+ "path": "state",
10720
+ "valueType": "enum",
10721
+ "enumValues": [
10722
+ "open",
10723
+ "opening",
10724
+ "closing",
10725
+ "closed",
10726
+ "stopped"
10727
+ ]
10728
+ }, {
10729
+ "path": "position",
10730
+ "valueType": "number"
10731
+ }],
10732
+ "vibration": [{
10733
+ "path": "detected",
10734
+ "valueType": "boolean"
10735
+ }],
10736
+ "water-heater": [
10737
+ {
10738
+ "path": "currentTemp",
10739
+ "valueType": "number"
10740
+ },
10741
+ {
10742
+ "path": "targetTemp",
10743
+ "valueType": "number"
10744
+ },
10745
+ {
10746
+ "path": "operationMode",
10747
+ "valueType": "string"
10748
+ },
10749
+ {
10750
+ "path": "away",
10751
+ "valueType": "boolean"
10752
+ },
10753
+ {
10754
+ "path": "minTemp",
10755
+ "valueType": "number"
10756
+ },
10757
+ {
10758
+ "path": "maxTemp",
10759
+ "valueType": "number"
10760
+ }
10761
+ ],
10762
+ "weather": [
10763
+ {
10764
+ "path": "condition",
10765
+ "valueType": "string"
10766
+ },
10767
+ {
10768
+ "path": "temperature",
10769
+ "valueType": "number"
10770
+ },
10771
+ {
10772
+ "path": "temperatureUnit",
10773
+ "valueType": "string"
10774
+ },
10775
+ {
10776
+ "path": "humidity",
10777
+ "valueType": "number"
10778
+ },
10779
+ {
10780
+ "path": "pressure",
10781
+ "valueType": "number"
10782
+ },
10783
+ {
10784
+ "path": "pressureUnit",
10785
+ "valueType": "string"
10786
+ },
10787
+ {
10788
+ "path": "windSpeed",
10789
+ "valueType": "number"
10790
+ },
10791
+ {
10792
+ "path": "windSpeedUnit",
10793
+ "valueType": "string"
10794
+ },
10795
+ {
10796
+ "path": "windBearing",
10797
+ "valueType": "number"
10798
+ }
10799
+ ],
10800
+ "zone-analytics": [
10801
+ {
10802
+ "path": "ts",
10803
+ "valueType": "number"
10804
+ },
10805
+ {
10806
+ "path": "frameWidth",
10807
+ "valueType": "number"
10808
+ },
10809
+ {
10810
+ "path": "frameHeight",
10811
+ "valueType": "number"
10812
+ },
10813
+ {
10814
+ "path": "frame.totalObjects",
10815
+ "valueType": "number"
10816
+ },
10817
+ {
10818
+ "path": "frame.standingObjects",
10819
+ "valueType": "number"
10820
+ },
10821
+ {
10822
+ "path": "frame.transientObjects",
10823
+ "valueType": "number"
10824
+ },
10825
+ {
10826
+ "path": "unzoned.totalObjects",
10827
+ "valueType": "number"
10828
+ },
10829
+ {
10830
+ "path": "unzoned.standingObjects",
10831
+ "valueType": "number"
10832
+ },
10833
+ {
10834
+ "path": "unzoned.transientObjects",
10835
+ "valueType": "number"
10836
+ }
10837
+ ]
10838
+ });
8865
10839
  object({
8866
10840
  code: string().regex(/^[a-z][a-z0-9-]*(\.[a-z0-9-]+)+$/),
8867
10841
  params: record(string(), union([string(), number()])).optional()
@@ -9210,7 +11184,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
9210
11184
  return DeviceRole;
9211
11185
  }({});
9212
11186
  //#endregion
9213
- //#region ../types/dist/composition-BJ8iAZb3.mjs
11187
+ //#region ../types/dist/composition-kEl9mevu.mjs
9214
11188
  /**
9215
11189
  * The ffmpeg build every CamStack node downloads, per platform and arch.
9216
11190
  *
@@ -12425,7 +14399,7 @@ var LogChannelDescriptorSchema = object({
12425
14399
  * `true` is a PROMISE with two halves, and both must hold: the gate is
12426
14400
  * consulted with the numeric device id, AND every line the channel admits
12427
14401
  * carries `tags: { deviceId }` with that same numeric id. The second half is
12428
- * what makes `| json | deviceId="617"` work in Loki — `loki-payload.ts`
14402
+ * what makes `| json | deviceId="102"` work in Loki — `loki-payload.ts`
12429
14403
  * keeps `deviceId` out of the stream labels for cardinality, so the tag in
12430
14404
  * the body is the only way to filter.
12431
14405
  *
@@ -12589,7 +14563,7 @@ function effectFor(stepId, label) {
12589
14563
  * - label kind: a label counts for a step only when the classMap sends it to
12590
14564
  * that step's macro AND it names a vocabulary entry. Every root is judged
12591
14565
  * the same way — a COCO model supplies the animal classifier with the six
12592
- * species COCO names, exactly as a Frigate+ model supplies seven.
14566
+ * species COCO names, exactly as a plus catalog model supplies seven.
12593
14567
  * - crop kind: the labelmap carries one of the step's root labels. Those
12594
14568
  * labels are deliberately left out of the classMap, so they never make a
12595
14569
  * track of their own.
@@ -12738,7 +14712,7 @@ var ModelVariantGroupSchema = object({
12738
14712
  precision: _enum(["fp32", "int8"]).optional(),
12739
14713
  /**
12740
14714
  * Training / latency-variant axis. Omit ⇒ the standard build. `test` marks
12741
- * an alternate training of the same family (Scrypted `relu_test`); chip
14715
+ * an alternate training of the same family (plugin catalog `relu_test`); chip
12742
14716
  * label is "Test".
12743
14717
  */
12744
14718
  optimization: _enum(["standard", "test"]).optional(),
@@ -12759,9 +14733,9 @@ var ModelProviderIdSchema = _enum([
12759
14733
  ]);
12760
14734
  /**
12761
14735
  * Resolve a catalog entry's picker provider. An explicit stamp always wins;
12762
- * otherwise Frigate/Scrypted are recognised from id prefix or description.
14736
+ * otherwise plus catalog/plugin catalog are recognised from id prefix or description.
12763
14737
  * Unstamped BYO registry rows fall through to `custom`. Family `yolov9` is
12764
- * NOT a Scrypted signal — CamStack ships that family too.
14738
+ * NOT a plugin catalog signal — CamStack ships that family too.
12765
14739
  */
12766
14740
  function inferModelProvider(entry) {
12767
14741
  if (entry.provider !== void 0) return entry.provider;
@@ -13003,8 +14977,8 @@ var ModelCatalogEntrySchema = object({
13003
14977
  provider: ModelProviderIdSchema.optional(),
13004
14978
  /**
13005
14979
  * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
13006
- * applies (Frigate / COCO public catalog). Set on a custom model whose raw
13007
- * labels already ARE the CamStack macros (Scrypted identity map).
14980
+ * applies (plus catalog / COCO public catalog). Set on a custom model whose raw
14981
+ * labels already ARE the CamStack macros (plugin catalog identity map).
13008
14982
  */
13009
14983
  classMap: DetectionCatalogClassMapSchema.optional(),
13010
14984
  /**
@@ -15991,7 +17965,7 @@ method(object({
15991
17965
  * `1` is real time and is the ONLY value that allows the copy branch —
15992
17966
  * anything else forces `libx264` over the window. That was priced
15993
17967
  * before it was chosen: a per-event burst measured at 0.23 s and 254 KB
15994
- * on a real 615 720p cut, against 922 KB for the copy it replaces. A
17968
+ * on a real 101 720p cut, against 922 KB for the copy it replaces. A
15995
17969
  * re-encode is capped at 720p (`EVENT_CLIP_ENCODE_MAX_WIDTH`), because
15996
17970
  * once the decode is forced the width stops being free.
15997
17971
  */
@@ -16411,6 +18385,7 @@ var CompositionRunStatusSchema = _enum([
16411
18385
  "starting",
16412
18386
  "running",
16413
18387
  "degraded",
18388
+ "incomplete",
16414
18389
  "failed"
16415
18390
  ]);
16416
18391
  var CompositionFieldStateKindSchema = _enum([
@@ -16624,6 +18599,7 @@ var CoreBlockStatusSchema = _enum([
16624
18599
  "starting",
16625
18600
  "running",
16626
18601
  "degraded",
18602
+ "incomplete",
16627
18603
  "failed"
16628
18604
  ]);
16629
18605
  /** path → TypeScript source for a multi-file block. */
@@ -38575,7 +40551,7 @@ var PRIMARY_CATEGORIES = new Set(ENTRIES.map((e) => e.primaryCategory));
38575
40551
  * `locationKey` is ALWAYS {@link locationIconKey} of the label — never the
38576
40552
  * operator's casing. The registry matches labels trimmed + case-insensitively
38577
40553
  * everywhere (`addLocation`, `removeLocation`, `renameLocation`), and a
38578
- * case-only rename (`cucina` → `Cucina`) is a real edit this repo supports; a
40554
+ * case-only rename (`kitchen` → `Kitchen`) is a real edit this repo supports; a
38579
40555
  * map keyed on the displayed casing would orphan its entry on exactly that
38580
40556
  * edit. Consumers join by keying their own label through `locationIconKey`.
38581
40557
  */
@@ -38600,7 +40576,7 @@ var LocationDescriptionAssignmentSchema = object({
38600
40576
  /**
38601
40577
  * A SITE ZONE — a named part of the property that several locations belong to.
38602
40578
  *
38603
- * "Zona notte" holds every bedroom; "Zona giorno" the living room and the
40579
+ * "Night zone" holds every bedroom; "Zona giorno" the living room and the
38604
40580
  * kitchen. A camera belongs to exactly one location, and a location to at most
38605
40581
  * one zone, so a camera's zone is derived and never stored on the device: the
38606
40582
  * whole point of this entity is that grouping rooms touches no device row.
@@ -38629,7 +40605,7 @@ var LocationDescriptionAssignmentSchema = object({
38629
40605
  * the locations inside it.
38630
40606
  *
38631
40607
  * The LABEL is carried alongside the key because the key is lossy on purpose —
38632
- * a surface must show "Zona notte", not "zona notte". Locations are carried
40608
+ * a surface must show "Night zone", not "night zone". Locations are carried
38633
40609
  * here, rather than left to a second call, because every consumer wants both
38634
40610
  * at once and a viewer that asked twice could render a zone whose membership
38635
40611
  * it has not fetched yet.
@@ -40742,8 +42718,8 @@ var LoadContributionSchema = object({
40742
42718
  "unattributable"
40743
42719
  ]),
40744
42720
  /**
40745
- * What ONE entry is, in the contributor's own words — `615/high`,
40746
- * `617/native`, `cuda:0 shared pool`. Free text because the unit differs per
42721
+ * What ONE entry is, in the contributor's own words — `101/high`,
42722
+ * `102/native`, `cuda:0 shared pool`. Free text because the unit differs per
40747
42723
  * family and inventing a common one would lose the only information that
40748
42724
  * makes two entries for the same camera distinguishable.
40749
42725
  */
@@ -43709,7 +45685,7 @@ var NcConditionsSchema = object({
43709
45685
  * with the list under it is worse than no switch (D62).
43710
45686
  *
43711
45687
  * MEMBERS ARE FACE-GALLERY `Identity.id`s (uuid), not display names. A name is
43712
- * renameable, and a rule authored on "Gianluca" went silently dark the moment
45688
+ * renameable, and a rule authored on "Alice" went silently dark the moment
43713
45689
  * the operator fixed the spelling. The id reaches the record on
43714
45690
  * `LabelAttribution.identityId`; the name is what the editor shows and what
43715
45691
  * `{{label}}` renders.
@@ -44260,7 +46236,7 @@ var NcRulePatchSchema = NcRuleInputSchema.partial().extend({
44260
46236
  * A rule scoped to one camera and one zone silently became a rule that
44261
46237
  * matches EVERY event on EVERY camera, and lost its `media` policy
44262
46238
  * (zoneCrop / gif / clip / frame) and its `priority` at the same time. Seen
44263
- * live on 2026-08-12: a rule scoped to device 617 fired on 590 and 615
46239
+ * live on 2026-08-12: a rule scoped to device 102 fired on 104 and 101
44264
46240
  * within a minute of a two-field patch.
44265
46241
  *
44266
46242
  * So every defaulted field is re-declared here WITHOUT its default. The
@@ -46073,7 +48049,7 @@ var LabelAttributionSchema = object({
46073
48049
  * `Identity.id` or a plate-gallery `Vehicle.id` (both `randomUUID`).
46074
48050
  *
46075
48051
  * The text alone is a DISPLAY NAME, and a display name is renameable: a
46076
- * notification rule authored on "Gianluca" stopped matching the moment the
48052
+ * notification rule authored on "Alice" stopped matching the moment the
46077
48053
  * operator fixed the spelling in the gallery, and nothing said so. The id is
46078
48054
  * the thing that does not move, so it is what a rule matches on
46079
48055
  * (`NcConditions.identities`) and the text is what a human is shown.
@@ -48612,7 +50588,7 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
48612
50588
  /**
48613
50589
  * Root-supplied detections for the tree's ROOT step (D730). Set by
48614
50590
  * `runDetailSubtree` when the camera's root model supplies a crop-kind
48615
- * step (a Frigate+ `license_plate` for `plate-detection`): the step is
50591
+ * step (a plus catalog `license_plate` for `plate-detection`): the step is
48616
50592
  * NOT inferred, these boxes are its output, and its children (the plate
48617
50593
  * reader) run on them through their own crop policy. Boxes are in the
48618
50594
  * PIXELS of the image this call carries. Absent ⇒ the root step runs.
@@ -50245,7 +52221,7 @@ var RunnerCameraConfigSchema = object({
50245
52221
  * detection session that asks for history. What shipped was a last-moment
50246
52222
  * discard — `FrameSlot`'s throttle compares wall clocks, and ~4 s of media
50247
52223
  * arriving inside a few hundred ms of wall clock looks to it like one frame's
50248
- * worth. Device 617, 2026-09-08: a re-run of the SAME model over the stored
52224
+ * worth. Device 102, 2026-09-08: a re-run of the SAME model over the stored
50249
52225
  * recording scored the subject `vehicle 0.5669` — above the 0.50 floor —
50250
52226
  * 1.68 s BEFORE the live track was born, on a frame that was in the pre-roll,
50251
52227
  * was decoded, and was freed.
@@ -52275,7 +54251,7 @@ method(_void(), ProviderInfoSchema, { auth: "admin" }), method(object({ config:
52275
54251
  * The signals a device can emit to WAKE its own stream.
52276
54252
  *
52277
54253
  * A camera whose stream is built on demand sleeps until something asks for it,
52278
- * and "something" cannot be a consumer that is merely attached — a Frigate-style
54254
+ * and "something" cannot be a consumer that is merely attached — a external-catalog
52279
54255
  * puller holds a session open for ever, and treating that as demand would keep
52280
54256
  * a battery camera awake for ever, which is the whole thing the battery is for
52281
54257
  * (D173). So the wake has to come from the CAMERA: an event it noticed by
@@ -52962,7 +54938,7 @@ var ClipSchema = object({
52962
54938
  * {@link MAX_CLIP_EVENT_IDS}. Empty on footage-only clips.
52963
54939
  *
52964
54940
  * Bounded because it is not a payload the surface pages through: one visit on
52965
- * device 615 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
54941
+ * device 101 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
52966
54942
  * camera-day. Read {@link eventCount} for the true total.
52967
54943
  */
52968
54944
  eventIds: array(string()).optional(),
@@ -53107,7 +55083,7 @@ var ClipPlaybackSchema = object({
53107
55083
  * camera has no recordings", which is the defect this whole line of work is
53108
55084
  * about: a battery camera nobody woke (`sleeping`), a camera that could not be
53109
55085
  * reached at all (`unreachable`, also what a provider that THREW reports), a
53110
- * camera whose SD card is not mounted (`no-storage`, measured on 640 —
55086
+ * camera whose SD card is not mounted (`no-storage`, measured on 106 —
53111
55087
  * `HddInfo mount 0`, honestly nothing to list rather than "no clips"), and a
53112
55088
  * camera whose OWN index disagrees with its OWN calendar (`index-empty`,
53113
55089
  * measured on 618: the calendar marks 3–20 September, days 6–20 list zero
@@ -53372,7 +55348,7 @@ DeviceType.Camera, method(object({
53372
55348
  *
53373
55349
  * It was optional, documented as "absent means the device's BOUND
53374
55350
  * provider, which is CamStack on every camera". No code implemented
53375
- * that. Measured on the live hub 2026-09-20 — device 592, bound to
55351
+ * that. Measured on the live hub 2026-09-20 — device 107, bound to
53376
55352
  * `recorder` AND `provider-reolink` — a bare call with `limit: 3`
53377
55353
  * answered SIX rows, three from each source, merged newest-first:
53378
55354
  * `device-collection-dispatch.ts` simply left the fan-out un-narrowed,
@@ -54450,7 +56426,10 @@ object({
54450
56426
  DeviceType.Sensor;
54451
56427
  object({
54452
56428
  /** Current illuminance in lux (lx). */
54453
- lux: number().min(0),
56429
+ lux: number().min(0).meta({
56430
+ unit: "lx",
56431
+ label: "Illuminance"
56432
+ }),
54454
56433
  /** Ms epoch when the slice was last updated. */
54455
56434
  lastFetchedAt: number(),
54456
56435
  /** Live display unit from the upstream source (e.g. HA
@@ -54606,7 +56585,10 @@ var BatteryStatusSchema = object({
54606
56585
  * Consumers must SKIP a null rather than coerce it — `battery-band` already
54607
56586
  * declines to band a non-finite reading, which is the correct shape.
54608
56587
  */
54609
- percentage: number().min(0).max(100).nullable(),
56588
+ percentage: number().min(0).max(100).nullable().meta({
56589
+ unit: "%",
56590
+ label: "Charge"
56591
+ }),
54610
56592
  /**
54611
56593
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
54612
56594
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -54625,13 +56607,13 @@ var BatteryStatusSchema = object({
54625
56607
  "solar",
54626
56608
  "none",
54627
56609
  "unknown"
54628
- ]),
56610
+ ]).meta({ label: "Charging source" }),
54629
56611
  /**
54630
56612
  * True when the camera firmware has gone into low-power mode. Battery
54631
56613
  * providers MUST avoid polling during sleep — reading the battery
54632
56614
  * wakes the camera up and drains charge.
54633
56615
  */
54634
- sleeping: boolean(),
56616
+ sleeping: boolean().meta({ label: "Sleeping" }),
54635
56617
  /** Ms epoch of the last observation. Lets consumers reason about freshness. */
54636
56618
  lastUpdated: number(),
54637
56619
  /**
@@ -54671,7 +56653,7 @@ var BatteryStatusSchema = object({
54671
56653
  * sub-threshold = low). UI MUST render "Normal"/"Low" instead of a
54672
56654
  * misleading exact percentage. Absent/false → genuine 0–100 % reading.
54673
56655
  */
54674
- binary: boolean().optional()
56656
+ binary: boolean().optional().meta({ label: "Binary indicator" })
54675
56657
  });
54676
56658
  DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat;
54677
56659
  method(object({
@@ -54686,7 +56668,7 @@ method(object({
54686
56668
  status: BatteryStatusSchema
54687
56669
  });
54688
56670
  object({
54689
- on: boolean(),
56671
+ on: boolean().meta({ label: "On" }),
54690
56672
  /** Ms epoch of the last transition. 0 if never observed. */
54691
56673
  lastChangedAt: number()
54692
56674
  });
@@ -54944,7 +56926,7 @@ var GridLayoutCellSchema = object({
54944
56926
  *
54945
56927
  * A grid's `high` composes its sources' `high` and its `low` their `low`, so a
54946
56928
  * profile is on offer only when EVERY source can serve it. The refusal NAMES
54947
- * the sources, because "this grid has no low" is not a finding — "615 has no
56929
+ * the sources, because "this grid has no low" is not a finding — "101 has no
54948
56930
  * low" is, and it is the one an operator can act on.
54949
56931
  */
54950
56932
  var GridProfileOfferSchema = object({
@@ -56495,7 +58477,10 @@ DeviceType.Humidifier, method(object({
56495
58477
  });
56496
58478
  object({
56497
58479
  /** Current relative humidity, 0..100. */
56498
- percent: number().min(0).max(100),
58480
+ percent: number().min(0).max(100).meta({
58481
+ unit: "%",
58482
+ label: "Humidity"
58483
+ }),
56499
58484
  /** Ms epoch when the slice was last updated. */
56500
58485
  lastFetchedAt: number(),
56501
58486
  /** Live display unit from the upstream source (e.g. HA
@@ -59272,9 +61257,15 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
59272
61257
  });
59273
61258
  object({
59274
61259
  /** Instantaneous power draw in watts. */
59275
- watts: number().optional(),
61260
+ watts: number().optional().meta({
61261
+ unit: "W",
61262
+ label: "Power"
61263
+ }),
59276
61264
  /** Cumulative energy in kilowatt-hours since the meter was reset. */
59277
- kwhTotal: number().optional(),
61265
+ kwhTotal: number().optional().meta({
61266
+ unit: "kWh",
61267
+ label: "Energy"
61268
+ }),
59278
61269
  /** Voltage in volts. */
59279
61270
  volts: number().optional(),
59280
61271
  /** Current in amperes. */
@@ -59593,9 +61584,9 @@ var PtzOptionsSchema = object({
59593
61584
  * Reolink preset 0, Hikvision preset '1', Dahua preset 1 -- and on this fleet
59594
61585
  * not one of the three cameras honours its own:
59595
61586
  *
59596
- * 592 Videocamera camera Daniel (reolink) preset 0 holds "stanza"
59597
- * 1438 Videocamera dispensa (hikvision) preset 1 holds "Credenza"
59598
- * 3836 Videocamera studio (amcrest) preset 1 holds "Preset1"
61587
+ * 107 Camera camera Carol (reolink) preset 0 holds "stanza"
61588
+ * 1438 Camera dispensa (hikvision) preset 1 holds "Credenza"
61589
+ * 3836 Camera studio (amcrest) preset 1 holds "Preset1"
59599
61590
  *
59600
61591
  * So `goHome` meant "go wherever the operator happened to save in slot 0 or 1",
59601
61592
  * and two of the three swallowed the failure in a bare `catch`. For autotrack
@@ -59742,7 +61733,7 @@ object({
59742
61733
  running: boolean().nullable(),
59743
61734
  /** Epoch ms the current boolean began; null while `running` is null. */
59744
61735
  since: number().nullable(),
59745
- source: RunningStateSourceSchema,
61736
+ source: RunningStateSourceSchema.meta({ label: "Source" }),
59746
61737
  phase: string().nullable(),
59747
61738
  /** null until a reading has been published (D393). */
59748
61739
  lastFetchedAt: number().nullable()
@@ -59795,7 +61786,7 @@ var RecordingAvailabilitySchema = object({
59795
61786
  * would look identical. But the answer used to say nothing about that, so a
59796
61787
  * caller asking "what can I export?" read the single preferred profile as
59797
61788
  * the only one that exists — on this deployment every camera records `high`
59798
- * AND `low`, the low tree holding 14 GB for camera 615 alone, and the export
61789
+ * AND `low`, the low tree holding 14 GB for camera 101 alone, and the export
59799
61790
  * UI could not see it.
59800
61791
  *
59801
61792
  * Cheap: it is the same shallow directory read the profile CHOICE already
@@ -59894,7 +61885,7 @@ var RecordingSourceOptionsSchema = object({
59894
61885
  * `sparse` = gaps are the absence of one, and must be drawn as such.
59895
61886
  *
59896
61887
  * Not an onboard-only concession: measured 2026-09-24, OUR bar covers 98.8 %
59897
- * of 592's day and 1.2 % of 1436's. It is a fact about a (source, camera)
61888
+ * of 107's day and 1.2 % of 1436's. It is a fact about a (source, camera)
59898
61889
  * pair, and ours answers it per camera from `deriveRecordingMode`. */
59899
61890
  coverage: _enum(["continuous", "sparse"]),
59900
61891
  /** Where the playhead may be put.
@@ -59970,7 +61961,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(RecordingSourceS
59970
61961
  * merely discouraged (D554 amended).
59971
61962
  *
59972
61963
  * It was learned the expensive way on `videoclips.listClips`: measured
59973
- * on the live hub 2026-09-20, device 592 bound to `recorder` AND
61964
+ * on the live hub 2026-09-20, device 107 bound to `recorder` AND
59974
61965
  * `provider-reolink`, a bare call with `limit: 3` answered SIX rows,
59975
61966
  * three from each source, merged — `device-collection-dispatch.ts`
59976
61967
  * leaves an unpinned fan-out un-narrowed, so absence buys the union the
@@ -60571,7 +62562,7 @@ var ExportSpeedSchema = number().min(.25).max(32);
60571
62562
  * on a 10 h window holding 29,393 s of footage every range landed late by the
60572
62563
  * gap accumulated before it — up to 6,607 s, well past EOF. Nothing matched,
60573
62564
  * the video was a uniform timelapse, and the log line reported the five ranges
60574
- * that had been ASKED for (2026-08-13, export `57d14363`, camera 615).
62565
+ * that had been ASKED for (2026-08-13, export `57d14363`, camera 101).
60575
62566
  *
60576
62567
  * Relative and not absolute epoch, because an absolute epoch would make every
60577
62568
  * call site responsible for the same subtraction.
@@ -61205,7 +63196,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), RecordingSignalStatusS
61205
63196
  * which put a "Scenes" tab on one camera's detail page. That is the wrong shape
61206
63197
  * for the thing: a scene is a standing question about the property ("is the bin
61207
63198
  * still out"), and the operator's question is "which of my scenes have tripped",
61208
- * across every camera at once — not "what does camera 617 think". Buried one
63199
+ * across every camera at once — not "what does camera 102 think". Buried one
61209
63200
  * camera deep it also could not be found. The surface is now a top-level admin
61210
63201
  * page (`/scenes`, `pages/Scenes.tsx`) that lists every scene on every camera and
61211
63202
  * picks the camera inside the create flow, the same shape Events and Faces have.
@@ -61788,7 +63779,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), StreamParamsOptionsSch
61788
63779
  auth: "admin"
61789
63780
  }), method(object({ deviceId: number() }), unknown().nullable());
61790
63781
  object({
61791
- on: boolean(),
63782
+ on: boolean().meta({ label: "On" }),
61792
63783
  /** Ms epoch of the last state change. Useful for UI "X minutes ago". */
61793
63784
  lastChangedAt: number()
61794
63785
  });
@@ -62351,7 +64342,10 @@ object({
62351
64342
  DeviceType.Sensor;
62352
64343
  object({
62353
64344
  /** Current temperature in Celsius. */
62354
- celsius: number(),
64345
+ celsius: number().meta({
64346
+ unit: "°C",
64347
+ label: "Temperature"
64348
+ }),
62355
64349
  /** Ms epoch when the slice was last updated (push or poll). */
62356
64350
  lastFetchedAt: number(),
62357
64351
  /** Live display unit from the upstream source (e.g. HA
@@ -63499,15 +65493,19 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
63499
65493
  auth: "admin"
63500
65494
  });
63501
65495
  SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
65496
+ DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Camera, DeviceType.Camera, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
65497
+ String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
65498
+ DeviceRole.BinarySensor, DeviceRole.MotionSensor;
65499
+ new Set(CAP_NAMES);
63502
65500
  function isClassMapMacroTarget(value) {
63503
65501
  return CLASS_MAP_MACRO_TARGETS.some((target) => target === value);
63504
65502
  }
63505
65503
  /**
63506
- * Raw Frigate+ label → detection macro. Every label of the documented
63507
- * Frigate+ base set (docs.frigate.video/plus, verified 2026-08-21) is either
63508
- * here or in {@link FRIGATE_PLUS_UNMAPPED_LABELS}, with the reason it is not.
65504
+ * Raw plus catalog label → detection macro. Every label of the documented
65505
+ * plus catalog base set (docs.frigate.video/plus, verified 2026-08-21) is either
65506
+ * here or in {@link PLUS_CATALOG_UNMAPPED_LABELS}, with the reason it is not.
63509
65507
  *
63510
- * Why this exists: a Frigate+ import used to carry NO classMap, so it inherited
65508
+ * Why this exists: a plus catalog import used to carry NO classMap, so it inherited
63511
65509
  * the step's `COCO_TO_MACRO` (`preserveOriginal: false`) and the executor
63512
65510
  * dropped every label COCO does not name — deer, raccoon, fox, squirrel, goat,
63513
65511
  * rabbit, skunk, kangaroo, possum, rodent, school_bus, garbage_truck and even
@@ -63515,7 +65513,7 @@ function isClassMapMacroTarget(value) {
63515
65513
  * label as `originalClass` whenever the map resolves it, so the fine identity
63516
65514
  * survives under the macro.
63517
65515
  */
63518
- var FRIGATE_PLUS_TO_MACRO = {
65516
+ var PLUS_CATALOG_TO_MACRO = {
63519
65517
  person: "person",
63520
65518
  baby: "person",
63521
65519
  car: "vehicle",
@@ -63543,17 +65541,17 @@ var FRIGATE_PLUS_TO_MACRO = {
63543
65541
  package: "package"
63544
65542
  };
63545
65543
  /**
63546
- * The per-model classMap for a Frigate / Frigate+ detector, derived from ITS
63547
- * labelmap: each label resolves through {@link FRIGATE_PLUS_TO_MACRO} first,
63548
- * then `COCO_TO_MACRO` (Frigate's default model ships the COCO-91 labelmap, so
65544
+ * The per-model classMap for a plus catalog / plus catalog detector, derived from ITS
65545
+ * labelmap: each label resolves through {@link PLUS_CATALOG_TO_MACRO} first,
65546
+ * then `COCO_TO_MACRO` (plus catalog's default model ships the COCO-91 labelmap, so
63549
65547
  * a preset import may carry either vocabulary). A label neither knows is left
63550
65548
  * out, and `preserveOriginal: false` drops it in the executor — the same
63551
- * contract as the COCO map, now with the Frigate+ vocabulary in it.
65549
+ * contract as the COCO map, now with the plus catalog vocabulary in it.
63552
65550
  */
63553
- function buildFrigateClassMap(labels) {
65551
+ function buildPlusCatalogClassMap(labels) {
63554
65552
  const mapping = {};
63555
65553
  for (const label of labels) {
63556
- const target = FRIGATE_PLUS_TO_MACRO[label] ?? COCO_TO_MACRO.mapping[label];
65554
+ const target = PLUS_CATALOG_TO_MACRO[label] ?? COCO_TO_MACRO.mapping[label];
63557
65555
  if (target !== void 0 && isClassMapMacroTarget(target)) mapping[label] = target;
63558
65556
  }
63559
65557
  return {
@@ -63562,14 +65560,14 @@ function buildFrigateClassMap(labels) {
63562
65560
  };
63563
65561
  }
63564
65562
  /**
63565
- * Everything a Frigate / Frigate+ entry derives from ITS OWN labelmap: the
65563
+ * Everything a plus catalog / plus catalog entry derives from ITS OWN labelmap: the
63566
65564
  * classMap and the steps it can supply (D730) — label and crop kinds alike.
63567
- * Every Frigate builder spreads this at import, so the two cannot be derived
65565
+ * Every plus catalog builder spreads this at import, so the two cannot be derived
63568
65566
  * from different label lists, and no family is assumed to carry a label it
63569
65567
  * does not list.
63570
65568
  */
63571
- function frigateLabelFields(labels) {
63572
- const classMap = buildFrigateClassMap(labels);
65569
+ function plusCatalogLabelFields(labels) {
65570
+ const classMap = buildPlusCatalogClassMap(labels);
63573
65571
  const supplies = deriveRootSupplies(labels, classMap);
63574
65572
  return supplies.length > 0 ? {
63575
65573
  classMap,
@@ -63577,35 +65575,35 @@ function frigateLabelFields(labels) {
63577
65575
  } : { classMap };
63578
65576
  }
63579
65577
  /**
63580
- * Per-class confidence-floor defaults of an imported stock Frigate detector
65578
+ * Per-class confidence-floor defaults of an imported stock plus catalog detector
63581
65579
  * (D738): its per-detection `min_score` default, 0.5, for every class. Its
63582
65580
  * track-level `threshold` (the median of a track's recent scores) has no
63583
65581
  * counterpart in CamStack's per-detection floors and is not carried.
63584
65582
  */
63585
- var FRIGATE_STOCK_CLASS_FLOORS = Object.freeze({
65583
+ var PLUS_CATALOG_STOCK_CLASS_FLOORS = Object.freeze({
63586
65584
  person: .5,
63587
65585
  vehicle: .5,
63588
65586
  animal: .5
63589
65587
  });
63590
65588
  /**
63591
- * Per-class floor defaults of an imported Frigate+ detector (D738): the
63592
- * documented starting `min_score` values for Frigate+ models, which score
65589
+ * Per-class floor defaults of an imported plus catalog detector (D738): the
65590
+ * documented starting `min_score` values for plus catalog models, which score
63593
65591
  * higher than the stock ones (person 0.65, car 0.65, cat 0.65, dog 0.70). The
63594
65592
  * macro `animal` takes the lower of its classes, so no class is cut above its
63595
65593
  * documented value.
63596
65594
  */
63597
- var FRIGATE_PLUS_CLASS_FLOORS = Object.freeze({
65595
+ var PLUS_CATALOG_CLASS_FLOORS = Object.freeze({
63598
65596
  person: .65,
63599
65597
  vehicle: .65,
63600
65598
  animal: .65
63601
65599
  });
63602
65600
  /**
63603
- * The `defaultClassFloors` an imported Frigate entry carries: the import's
65601
+ * The `defaultClassFloors` an imported plus catalog entry carries: the import's
63604
65602
  * own, when it states them, else the defaults of its kind. A fresh object.
63605
65603
  */
63606
- function frigateDefaultClassFloors(kind, carried) {
65604
+ function plusCatalogDefaultClassFloors(kind, carried) {
63607
65605
  if (carried !== void 0) return { ...carried };
63608
- return { ...kind === "plus" ? FRIGATE_PLUS_CLASS_FLOORS : FRIGATE_STOCK_CLASS_FLOORS };
65606
+ return { ...kind === "plus" ? PLUS_CATALOG_CLASS_FLOORS : PLUS_CATALOG_STOCK_CLASS_FLOORS };
63609
65607
  }
63610
65608
  /**
63611
65609
  * Accessory device helpers — shared across drivers.
@@ -76534,7 +78532,7 @@ var SENSOR_CAP_VOCABULARY = {
76534
78532
  state: [{
76535
78533
  kind: "boolean",
76536
78534
  field: "on",
76537
- label: t("Active", "Attivo"),
78535
+ label: t("On", "Acceso"),
76538
78536
  whenTrue: t("When {device} turns active", "Quando {device} si attiva"),
76539
78537
  whenFalse: t("When {device} turns inactive", "Quando {device} si disattiva"),
76540
78538
  icon: "toggle-right"
@@ -79958,7 +81956,6 @@ Object.freeze({
79958
81956
  "smtp-provider": "email"
79959
81957
  });
79960
81958
  DeviceType.Camera;
79961
- DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Camera, DeviceType.Camera, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
79962
81959
  /**
79963
81960
  * A saved Customize assignment (D936). The schema is the type: callers use
79964
81961
  * `z.infer`, they do not restate the shape.
@@ -80047,7 +82044,6 @@ object({
80047
82044
  ]),
80048
82045
  reason: string().nullable()
80049
82046
  });
80050
- String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
80051
82047
  var G711_SCALE_CORRECTION_DB = {
80052
82048
  PCMU: 20 * Math.log10(4),
80053
82049
  PCMA: 20 * Math.log10(8)
@@ -80420,7 +82416,7 @@ var STATE_SUMMARY_SECTION_VARS = [
80420
82416
  {
80421
82417
  name: "summaryStreams",
80422
82418
  label: "Summary: streams offline",
80423
- example: "Ingresso (high) — since 06:40",
82419
+ example: "Front door (high) — since 06:40",
80424
82420
  kinds: ["stream-offline", "stream-online"]
80425
82421
  },
80426
82422
  {
@@ -80438,13 +82434,13 @@ var STATE_SUMMARY_SECTION_VARS = [
80438
82434
  {
80439
82435
  name: "summaryDetection",
80440
82436
  label: "Summary: cameras detecting nothing",
80441
- example: "Ingresso — since 05:10",
82437
+ example: "Front door — since 05:10",
80442
82438
  kinds: ["detection-blind"]
80443
82439
  },
80444
82440
  {
80445
82441
  name: "summaryNodes",
80446
82442
  label: "Summary: nodes",
80447
- example: "little-unraid — offline since 03:00",
82443
+ example: "agent-a — offline since 03:00",
80448
82444
  kinds: [
80449
82445
  "node-offline",
80450
82446
  "node-online",
@@ -81435,7 +83431,7 @@ function upsertAvailability(map, modelId, nodeId, entry) {
81435
83431
  }
81436
83432
  /**
81437
83433
  * Insert or replace a descriptor keyed by `entry.id`. When the id already
81438
- * exists, **formats are merged** (Scrypted multi-format accumulate) — sibling
83434
+ * exists, **formats are merged** (plugin catalog multi-format accumulate) — sibling
81439
83435
  * formats on the prior entry are never dropped. Returns a new array.
81440
83436
  */
81441
83437
  function upsertCustomModel(list, descriptor, nameOrigin = "source") {
@@ -81608,23 +83604,23 @@ function stripModelIdFromInferenceDevices(devices, modelId) {
81608
83604
  };
81609
83605
  }
81610
83606
  //#endregion
81611
- //#region src/frigate/frigate-import.ts
83607
+ //#region src/plus-catalog/plus-catalog-import.ts
81612
83608
  /**
81613
- * Variant-selector axes for an imported Frigate / Frigate+ detector. Family
83609
+ * Variant-selector axes for an imported plus catalog / plus catalog detector. Family
81614
83610
  * follows the generation (`ssdlite-mobiledet` / `yolonas` / `yolov9`); a
81615
83611
  * single-model import uses tier `default` so the stepper still gets a grouped
81616
- * picker under the Frigate provider.
83612
+ * picker under the plus catalog provider.
81617
83613
  */
81618
- function frigateVariantGroup(type, resolution) {
83614
+ function plusCatalogVariantGroup(type, resolution) {
81619
83615
  return {
81620
83616
  family: type === "mobiledet" ? "ssdlite-mobiledet" : type,
81621
83617
  tier: "default",
81622
83618
  resolution
81623
83619
  };
81624
83620
  }
81625
- var FRIGATE_PUBLIC_CATALOG = [{
83621
+ var PLUS_CATALOG_PUBLIC_CATALOG = [{
81626
83622
  id: "frigate-mobiledet-edgetpu",
81627
- label: "Frigate default — SSDLite MobileDet (EdgeTPU)",
83623
+ label: "plus catalog default — SSDLite MobileDet (EdgeTPU)",
81628
83624
  format: "tflite",
81629
83625
  url: "https://github.com/google-coral/test_data/raw/release-frogfish/ssdlite_mobiledet_coco_qat_postprocess_edgetpu.tflite",
81630
83626
  sizeMB: 5.4,
@@ -81724,21 +83720,21 @@ var FRIGATE_PUBLIC_CATALOG = [{
81724
83720
  "hair brush"
81725
83721
  ],
81726
83722
  license: CORAL_MOBILEDET_APACHE,
81727
- notes: "Frigate's default detection model (the one a stock Frigate + Coral install runs). EdgeTPU-compiled full-integer TFLite, 320×320, TFLite_Detection_PostProcess output → ssd decode. Requires a Coral (tflite format) node."
83723
+ notes: "plus catalog's default detection model (the one a stock plus catalog + Coral install runs). EdgeTPU-compiled full-integer TFLite, 320×320, TFLite_Detection_PostProcess output → ssd decode. Requires a Coral (tflite format) node."
81728
83724
  }];
81729
83725
  /**
81730
83726
  * Build the registrable descriptor for a curated catalog entry. The URL is
81731
83727
  * the PUBLIC one — any node downloads it on demand; no Distribute needed.
81732
83728
  */
81733
- function buildFrigateCatalogDescriptor(catalogId, overrides) {
81734
- const cat = FRIGATE_PUBLIC_CATALOG.find((e) => e.id === catalogId);
81735
- if (!cat) throw new Error(`Unknown Frigate catalog id "${catalogId}" — available: ${FRIGATE_PUBLIC_CATALOG.map((e) => e.id).join(", ")}`);
83729
+ function buildPlusCatalogCatalogDescriptor(catalogId, overrides) {
83730
+ const cat = PLUS_CATALOG_PUBLIC_CATALOG.find((e) => e.id === catalogId);
83731
+ if (!cat) throw new Error(`Unknown plus catalog catalog id "${catalogId}" — available: ${PLUS_CATALOG_PUBLIC_CATALOG.map((e) => e.id).join(", ")}`);
81736
83732
  return {
81737
83733
  stepId: "object-detection",
81738
83734
  entry: {
81739
83735
  id: overrides?.modelId?.trim() || cat.id,
81740
83736
  name: overrides?.name?.trim() || cat.label,
81741
- description: `${cat.notes} Imported from the Frigate public catalog via Model Studio.`,
83737
+ description: `${cat.notes} Imported from the plus catalog public catalog via Model Studio.`,
81742
83738
  formats: { [cat.format]: {
81743
83739
  url: cat.url,
81744
83740
  sizeMB: cat.sizeMB,
@@ -81752,18 +83748,18 @@ function buildFrigateCatalogDescriptor(catalogId, overrides) {
81752
83748
  id: name,
81753
83749
  name
81754
83750
  })),
81755
- ...frigateLabelFields(cat.labels),
81756
- defaultClassFloors: frigateDefaultClassFloors("stock"),
83751
+ ...plusCatalogLabelFields(cat.labels),
83752
+ defaultClassFloors: plusCatalogDefaultClassFloors("stock"),
81757
83753
  preprocessMode: "letterbox",
81758
83754
  provider: "frigate",
81759
83755
  license: cat.license,
81760
- group: frigateVariantGroup("mobiledet", cat.inputSize),
83756
+ group: plusCatalogVariantGroup("mobiledet", cat.inputSize),
81761
83757
  ...cat.postprocessor !== void 0 ? { postprocessor: cat.postprocessor } : {}
81762
83758
  }
81763
83759
  };
81764
83760
  }
81765
83761
  //#endregion
81766
- //#region src/frigate/plus-conversion.ts
83762
+ //#region src/plus-catalog/plus-conversion.ts
81767
83763
  /** Converted formats ADD to the imported entry; identity fields (decode,
81768
83764
  * labels, description, preprocess) stay the import's. */
81769
83765
  function mergeConvertedFormats(base, converted) {
@@ -82206,14 +84202,14 @@ async function moveInto(source, target) {
82206
84202
  }
82207
84203
  }
82208
84204
  //#endregion
82209
- //#region src/frigate/plus-decode.ts
84205
+ //#region src/plus-catalog/plus-decode.ts
82210
84206
  var UnsupportedPlusDecodeError = class extends Error {
82211
84207
  type;
82212
84208
  format;
82213
84209
  detectors;
82214
84210
  constructor(type, format, detectors) {
82215
84211
  const detList = detectors.length > 0 ? detectors.join(", ") : "(none)";
82216
- super(`Frigate+ import refused — no decoder for type "${type}", format "${format}", detectors ${detList}`);
84212
+ super(`plus catalog import refused — no decoder for type "${type}", format "${format}", detectors ${detList}`);
82217
84213
  this.name = "UnsupportedPlusDecodeError";
82218
84214
  this.type = type;
82219
84215
  this.format = format;
@@ -82291,12 +84287,12 @@ function resolvePlusDecode(info, formatOverride) {
82291
84287
  return decode;
82292
84288
  }
82293
84289
  //#endregion
82294
- //#region src/frigate/frigate-plus.ts
84290
+ //#region src/plus-catalog/plus-catalog-api.ts
82295
84291
  /**
82296
- * Frigate+ API client — the REAL api.frigate.video contract, verified against
82297
- * frigate/plus.py (dev branch, 2026-08-21):
84292
+ * plus catalog API client — the REAL api.frigate.video contract, verified against
84293
+ * plus-catalog/plus.py (dev branch, 2026-08-21):
82298
84294
  *
82299
- * - key format: `[uuid]:[40 hex]` (Frigate validates
84295
+ * - key format: `[uuid]:[40 hex]` (plus catalog validates
82300
84296
  * `[a-z0-9]{8}-…-[a-z0-9]{12}:[a-z0-9]{40}`)
82301
84297
  * - GET /v1/auth/token with HTTP basic auth (key split on `:`) →
82302
84298
  * `{ accessToken, expires }`
@@ -82320,19 +84316,19 @@ function isRecord(value) {
82320
84316
  }
82321
84317
  /** Exchange the API key for an access token. The key never appears in errors. */
82322
84318
  async function fetchPlusAccessToken(fetchFn, apiKey) {
82323
- if (!isValidPlusApiKey(apiKey)) throw new Error("Frigate+ API key is malformed — expected the \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:40-hex\" shape shown in your Frigate+ account settings");
84319
+ if (!isValidPlusApiKey(apiKey)) throw new Error("plus catalog API key is malformed — expected the \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:40-hex\" shape shown in your plus catalog account settings");
82324
84320
  const [user, pass] = apiKey.split(":");
82325
84321
  const basic = Buffer.from(`${user}:${pass}`).toString("base64");
82326
84322
  const res = await fetchFn(`${PLUS_API_HOST}/v1/auth/token`, { headers: { authorization: `Basic ${basic}` } });
82327
- if (!res.ok) throw new Error(`Frigate+ authentication failed (HTTP ${res.status}) — check the API key in the Model Studio addon settings`);
84323
+ if (!res.ok) throw new Error(`plus catalog authentication failed (HTTP ${res.status}) — check the API key in the Model Studio addon settings`);
82328
84324
  const body = await res.json();
82329
84325
  const token = isRecord(body) && typeof body.accessToken === "string" ? body.accessToken : null;
82330
- if (token === null) throw new Error("Frigate+ auth response carried no accessToken");
84326
+ if (token === null) throw new Error("plus catalog auth response carried no accessToken");
82331
84327
  return token;
82332
84328
  }
82333
84329
  async function plusGet(fetchFn, token, path) {
82334
84330
  const res = await fetchFn(`${PLUS_API_HOST}/v1/${path}`, { headers: { authorization: `Bearer ${token}` } });
82335
- if (!res.ok) throw new Error(`Frigate+ request "${path}" failed (HTTP ${res.status}): ${await res.text()}`);
84331
+ if (!res.ok) throw new Error(`plus catalog request "${path}" failed (HTTP ${res.status}): ${await res.text()}`);
82336
84332
  return res.json();
82337
84333
  }
82338
84334
  /**
@@ -82380,7 +84376,7 @@ async function listPlusModels(fetchFn, apiKey) {
82380
84376
  return toPlusModelSummaries(await plusGet(fetchFn, await fetchPlusAccessToken(fetchFn, apiKey), "model/list"));
82381
84377
  }
82382
84378
  function toModelInfo(raw, modelId) {
82383
- if (!isRecord(raw)) throw new Error("Frigate+ model info: unexpected response shape");
84379
+ if (!isRecord(raw)) throw new Error("plus catalog model info: unexpected response shape");
82384
84380
  const labelMap = {};
82385
84381
  if (isRecord(raw.labelMap)) {
82386
84382
  for (const [k, v] of Object.entries(raw.labelMap)) if (typeof v === "string") labelMap[k] = v;
@@ -82404,7 +84400,7 @@ async function requestPlusModelDownload(fetchFn, apiKey, plusModelId) {
82404
84400
  const info = toModelInfo(await plusGet(fetchFn, token, `model/${plusModelId}`), plusModelId);
82405
84401
  const signed = await plusGet(fetchFn, token, `model/${plusModelId}/signed_url`);
82406
84402
  const url = isRecord(signed) && typeof signed.url === "string" ? signed.url : null;
82407
- if (url === null) throw new Error("Frigate+ signed_url response carried no url");
84403
+ if (url === null) throw new Error("plus catalog signed_url response carried no url");
82408
84404
  return {
82409
84405
  info,
82410
84406
  downloadUrl: url
@@ -82420,7 +84416,7 @@ function orderedLabels(labelMap) {
82420
84416
  return out;
82421
84417
  }
82422
84418
  /**
82423
- * Build the registrable descriptor for a downloaded Frigate+ model. The
84419
+ * Build the registrable descriptor for a downloaded plus catalog model. The
82424
84420
  * artifact is hub-local (landed by the server-side download), so the URL uses
82425
84421
  * the `camstack-local://` convention (D208) — other nodes get it via
82426
84422
  * Distribute.
@@ -82433,7 +84429,7 @@ function plusInfoToDescriptor(info, opts) {
82433
84429
  entry: {
82434
84430
  id: opts.modelId,
82435
84431
  name: opts.name,
82436
- description: `Frigate+ personal model (${info.type}) — imported via Model Studio`,
84432
+ description: `plus catalog personal model (${info.type}) — imported via Model Studio`,
82437
84433
  formats: { [decode.format]: {
82438
84434
  url: `camstack-local://${opts.modelId}/${opts.filename}`,
82439
84435
  sizeMB: opts.sizeMB,
@@ -82447,11 +84443,11 @@ function plusInfoToDescriptor(info, opts) {
82447
84443
  id: name,
82448
84444
  name
82449
84445
  })),
82450
- ...frigateLabelFields(labels),
82451
- defaultClassFloors: frigateDefaultClassFloors("plus"),
84446
+ ...plusCatalogLabelFields(labels),
84447
+ defaultClassFloors: plusCatalogDefaultClassFloors("plus"),
82452
84448
  preprocessMode: "letterbox",
82453
84449
  provider: "frigate",
82454
- group: frigateVariantGroup(info.type, info.width),
84450
+ group: plusCatalogVariantGroup(info.type, info.width),
82455
84451
  postprocessor: decode.postprocessor
82456
84452
  }
82457
84453
  };
@@ -82569,16 +84565,16 @@ var ModelNodeAvailabilitySchema = preprocess((raw) => {
82569
84565
  }, object({ formats: partialRecord(_enum(MODEL_FORMATS), ModelFormatPresenceSchema) }));
82570
84566
  /** `modelId → nodeId → { formats: { [format]: presence } }`. */
82571
84567
  var ModelAvailabilityMapSchema = record(string(), record(string(), ModelNodeAvailabilitySchema));
82572
- /** Stable Library id for a Frigate+ training (chip id ↔ registry). */
82573
- function frigatePlusRegistryId(plusModelId) {
82574
- return `frigate-plus-${plusModelId}`;
84568
+ /** Stable Library id for a plus catalog training (chip id ↔ registry). */
84569
+ function plusCatalogPlusRegistryId(plusModelId) {
84570
+ return `plus-catalog-${plusModelId}`;
82575
84571
  }
82576
- var ScryptedManifestFileSchema = object({
84572
+ var PluginCatalogManifestFileSchema = object({
82577
84573
  relativePath: string(),
82578
84574
  size: number(),
82579
84575
  sha256: string().regex(/^[0-9a-f]{64}$/)
82580
84576
  });
82581
- var ScryptedManifestEntrySchema = object({
84577
+ var PluginCatalogManifestEntrySchema = object({
82582
84578
  id: string(),
82583
84579
  label: string(),
82584
84580
  family: _enum([
@@ -82599,10 +84595,10 @@ var ScryptedManifestEntrySchema = object({
82599
84595
  width: number(),
82600
84596
  height: number()
82601
84597
  }),
82602
- files: array(ScryptedManifestFileSchema).readonly(),
84598
+ files: array(PluginCatalogManifestFileSchema).readonly(),
82603
84599
  model: ModelCatalogEntrySchema
82604
84600
  });
82605
- var ScryptedCatalogDriftSchema = object({
84601
+ var PluginCatalogCatalogDriftSchema = object({
82606
84602
  manifestId: string(),
82607
84603
  status: _enum([
82608
84604
  "ok",
@@ -82613,12 +84609,12 @@ var ScryptedCatalogDriftSchema = object({
82613
84609
  details: string().optional()
82614
84610
  });
82615
84611
  /**
82616
- * Curated PUBLIC Frigate catalog entry (D214 addendum). Named + exported so
82617
- * the UI's `listFrigateCatalog` result parses against the SAME schema this
82618
- * action's output is declared with (see `modelStudioActions.listFrigateCatalog`
84612
+ * Curated PUBLIC plus catalog catalog entry (D214 addendum). Named + exported so
84613
+ * the UI's `listPlusCatalogCatalog` result parses against the SAME schema this
84614
+ * action's output is declared with (see `modelStudioActions.listPlusCatalogCatalog`
82619
84615
  * below) — one shape, not a hand-duplicated interface on the UI side.
82620
84616
  */
82621
- var FrigateCatalogEntrySchema = object({
84617
+ var PlusCatalogCatalogEntrySchema = object({
82622
84618
  id: string(),
82623
84619
  label: string(),
82624
84620
  format: _enum(MODEL_FORMATS),
@@ -82627,11 +84623,11 @@ var FrigateCatalogEntrySchema = object({
82627
84623
  notes: string()
82628
84624
  });
82629
84625
  /**
82630
- * Frigate+ `/v1/model/list` entry (see `frigate-plus.ts`). `isBaseModel` is
82631
- * the Base/Custom discriminator Frigate's own UI groups on. Named + exported
82632
- * for the same reason as {@link FrigateCatalogEntrySchema}.
84626
+ * plus catalog `/v1/model/list` entry (see `plus-catalog-api.ts`). `isBaseModel` is
84627
+ * the Base/Custom discriminator plus catalog's own UI groups on. Named + exported
84628
+ * for the same reason as {@link PlusCatalogCatalogEntrySchema}.
82633
84629
  */
82634
- var FrigatePlusModelSchema = object({
84630
+ var PlusCatalogModelSchema = object({
82635
84631
  id: string(),
82636
84632
  name: string(),
82637
84633
  type: string(),
@@ -82675,7 +84671,7 @@ var modelStudioActions = defineCustomActions({
82675
84671
  }), { kind: "mutation" }),
82676
84672
  /**
82677
84673
  * Convert missing OpenVINO / CoreML from an already-registered ONNX entry
82678
- * (Frigate+ / Custom per-format Import). Only the requested formats run.
84674
+ * (plus catalog / Custom per-format Import). Only the requested formats run.
82679
84675
  */
82680
84676
  ensureModelFormats: customAction(object({
82681
84677
  modelId: string(),
@@ -82692,7 +84688,7 @@ var modelStudioActions = defineCustomActions({
82692
84688
  clearedPins: number().int().nonnegative()
82693
84689
  }), { kind: "mutation" }),
82694
84690
  /**
82695
- * Rename an IMPORTED registry row (Frigate, Frigate+, Scrypted, uploads,
84691
+ * Rename an IMPORTED registry row (plus catalog, plus catalog, plugin catalog, uploads,
82696
84692
  * conversions) in place. Only `entry.name` changes — never the id, so pins
82697
84693
  * and availability are untouched. An empty name restores the name the model
82698
84694
  * was imported with. CamStack catalog models are refused.
@@ -82744,7 +84740,7 @@ var modelStudioActions = defineCustomActions({
82744
84740
  }), { kind: "mutation" }),
82745
84741
  listAvailability: customAction(_void(), ModelAvailabilityMapSchema),
82746
84742
  /**
82747
- * Chunked model-file upload (Frigate import). One tRPC mutation cannot
84743
+ * Chunked model-file upload (plus catalog import). One tRPC mutation cannot
82748
84744
  * carry a model file (hub HTTP body limit ~1 MB), so the page streams
82749
84745
  * base64 chunks: begin → append× → commit. Commit lands the artifact in the
82750
84746
  * hub's shared modelsDir, where the `camstack-local://` catalog-URL
@@ -82766,12 +84762,12 @@ var modelStudioActions = defineCustomActions({
82766
84762
  }), { kind: "mutation" }),
82767
84763
  abortModelUpload: customAction(object({ uploadId: string() }), object({ ok: literal(true) }), { kind: "mutation" }),
82768
84764
  /**
82769
- * Curated PUBLIC Frigate model catalog (D214 addendum). Import registers the
84765
+ * Curated PUBLIC plus catalog model catalog (D214 addendum). Import registers the
82770
84766
  * descriptor with its public URL (Library only). Optional `targetNodeId`
82771
84767
  * downloads on that node — no hub staging disk.
82772
84768
  */
82773
- listFrigateCatalog: customAction(_void(), array(FrigateCatalogEntrySchema).readonly()),
82774
- importFrigateCatalogModel: customAction(object({
84769
+ listPlusCatalogCatalog: customAction(_void(), array(PlusCatalogCatalogEntrySchema).readonly()),
84770
+ importPlusCatalogCatalogModel: customAction(object({
82775
84771
  catalogId: string(),
82776
84772
  modelId: string().optional(),
82777
84773
  name: string().optional(),
@@ -82782,23 +84778,23 @@ var modelStudioActions = defineCustomActions({
82782
84778
  bytes: number()
82783
84779
  }), { kind: "mutation" }),
82784
84780
  /**
82785
- * Local Scrypted YOLO catalog (Task 7B). Listing is a projection of the
84781
+ * Local plugin catalog YOLO catalog (Task 7B). Listing is a projection of the
82786
84782
  * revision-pinned manifesto plus a read-only HF drift check. Import accepts
82787
84783
  * `manifestId` (+ optional land-on-node) — host/repo/revision/path/labels/
82788
84784
  * checksum stay server-owned.
82789
84785
  */
82790
- listScryptedCatalog: customAction(_void(), object({
82791
- entries: array(ScryptedManifestEntrySchema).readonly(),
82792
- drift: array(ScryptedCatalogDriftSchema).readonly()
84786
+ listPluginCatalogCatalog: customAction(_void(), object({
84787
+ entries: array(PluginCatalogManifestEntrySchema).readonly(),
84788
+ drift: array(PluginCatalogCatalogDriftSchema).readonly()
82793
84789
  })),
82794
- importScryptedCatalogModel: customAction(object({
84790
+ importPluginCatalogCatalogModel: customAction(object({
82795
84791
  manifestId: string(),
82796
84792
  /** Optional display name typed on the import card. */
82797
84793
  name: string().optional(),
82798
84794
  targetNodeId: string().optional()
82799
84795
  }), CustomModelDescriptorSchema, { kind: "mutation" }),
82800
84796
  /**
82801
- * Frigate+ personal models. The API key lives in the addon's SETTINGS
84797
+ * plus catalog personal models. The API key lives in the addon's SETTINGS
82802
84798
  * (password field) and never leaves the hub: list / test / import all run
82803
84799
  * server-side against api.frigate.video. Status deliberately reveals only
82804
84800
  * booleans — never the key.
@@ -82809,18 +84805,18 @@ var modelStudioActions = defineCustomActions({
82809
84805
  * Empty object — `addons.custom` cannot carry zod `void`.
82810
84806
  */
82811
84807
  tfliteSupport: customAction(object({}).optional(), object({ nodes: array(string()).readonly() })),
82812
- frigatePlusStatus: customAction(_void(), object({
84808
+ plusCatalogPlusStatus: customAction(_void(), object({
82813
84809
  configured: boolean(),
82814
84810
  keyFormatValid: boolean()
82815
84811
  })),
82816
- frigatePlusTest: customAction(_void(), object({
84812
+ plusCatalogPlusTest: customAction(_void(), object({
82817
84813
  ok: boolean(),
82818
84814
  error: string().optional()
82819
84815
  }), { kind: "mutation" }),
82820
- frigatePlusListModels: customAction(_void(), array(FrigatePlusModelSchema).readonly()),
82821
- importFrigatePlusModel: customAction(object({
84816
+ plusCatalogPlusListModels: customAction(_void(), array(PlusCatalogModelSchema).readonly()),
84817
+ importPlusCatalogModel: customAction(object({
82822
84818
  plusModelId: string(),
82823
- /** Ignored for identity — registry id is always `frigate-plus-<plusModelId>`. */
84819
+ /** Ignored for identity — registry id is always `plus-catalog-<plusModelId>`. */
82824
84820
  modelId: string().optional(),
82825
84821
  name: string().optional(),
82826
84822
  /**
@@ -82945,7 +84941,7 @@ function spawnRunConvert(jobPath, pythonPath, onProgress, _sessionId) {
82945
84941
  function nameOriginOf(operatorName) {
82946
84942
  return operatorName !== void 0 ? { nameOrigin: "operator" } : {};
82947
84943
  }
82948
- /** Global-fetch adapter for the injected Frigate+ client seam. */
84944
+ /** Global-fetch adapter for the injected plus catalog client seam. */
82949
84945
  var plusFetch = async (url, init) => fetch(url, init);
82950
84946
  var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
82951
84947
  id = "model-studio";
@@ -82971,17 +84967,17 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
82971
84967
  section: "detection"
82972
84968
  }];
82973
84969
  constructor() {
82974
- super({ frigatePlusApiKey: "" });
84970
+ super({ plusCatalogPlusApiKey: "" });
82975
84971
  }
82976
84972
  globalSettingsSchema() {
82977
84973
  return this.schema({ sections: [{
82978
84974
  id: "frigate-plus",
82979
- title: "Frigate+",
82980
- description: "Credentials for importing your personal Frigate+ models. Create an API key in your Frigate+ account (https://plus.frigate.video → Settings → API keys; see docs.frigate.video/integrations/plus). The key is used only server-side against api.frigate.video and is never sent to the browser.",
84975
+ title: "plus catalog",
84976
+ description: "Credentials for importing your personal plus catalog models. Create an API key in your plus catalog account (https://plus.frigate.video → Settings → API keys; see docs.frigate.video/integrations/plus). The key is used only server-side against api.frigate.video and is never sent to the browser.",
82981
84977
  fields: [{
82982
84978
  type: "password",
82983
- key: "frigatePlusApiKey",
82984
- label: "Frigate+ API key",
84979
+ key: "plusCatalogPlusApiKey",
84980
+ label: "plus catalog API key",
82985
84981
  description: "Shape: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:40-hex-chars",
82986
84982
  showToggle: true
82987
84983
  }]
@@ -83091,7 +85087,7 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
83091
85087
  await this.pruneOrphanAvailability_();
83092
85088
  return this.availability_.get();
83093
85089
  },
83094
- listFrigateCatalog: async () => FRIGATE_PUBLIC_CATALOG.map((c) => ({
85090
+ listPlusCatalogCatalog: async () => PLUS_CATALOG_PUBLIC_CATALOG.map((c) => ({
83095
85091
  id: c.id,
83096
85092
  label: c.label,
83097
85093
  format: c.format,
@@ -83099,9 +85095,9 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
83099
85095
  inputSize: c.inputSize,
83100
85096
  notes: c.notes
83101
85097
  })),
83102
- importFrigateCatalogModel: async (input) => this.importFrigateCatalogModel(input),
83103
- listScryptedCatalog: async () => this.listScryptedCatalog(),
83104
- importScryptedCatalogModel: async (input) => this.importScryptedCatalogFromManifest(input),
85098
+ importPlusCatalogCatalogModel: async (input) => this.importPlusCatalogCatalogModel(input),
85099
+ listPluginCatalogCatalog: async () => this.listPluginCatalogCatalog(),
85100
+ importPluginCatalogCatalogModel: async (input) => this.importPluginCatalogCatalogFromManifest(input),
83105
85101
  tfliteSupport: async () => {
83106
85102
  const api = this.ctx.api;
83107
85103
  if (!api) return { nodes: [] };
@@ -83112,16 +85108,16 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
83112
85108
  } catch {}
83113
85109
  return { nodes: supported };
83114
85110
  },
83115
- frigatePlusStatus: async () => {
83116
- const key = this.config.frigatePlusApiKey ?? "";
85111
+ plusCatalogPlusStatus: async () => {
85112
+ const key = this.config.plusCatalogPlusApiKey ?? "";
83117
85113
  return {
83118
85114
  configured: key.length > 0,
83119
85115
  keyFormatValid: isValidPlusApiKey(key)
83120
85116
  };
83121
85117
  },
83122
- frigatePlusTest: async () => {
85118
+ plusCatalogPlusTest: async () => {
83123
85119
  try {
83124
- await fetchPlusAccessToken(plusFetch, this.config.frigatePlusApiKey ?? "");
85120
+ await fetchPlusAccessToken(plusFetch, this.config.plusCatalogPlusApiKey ?? "");
83125
85121
  return { ok: true };
83126
85122
  } catch (err) {
83127
85123
  return {
@@ -83130,8 +85126,8 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
83130
85126
  };
83131
85127
  }
83132
85128
  },
83133
- frigatePlusListModels: async () => listPlusModels(plusFetch, this.config.frigatePlusApiKey ?? ""),
83134
- importFrigatePlusModel: async (input) => this.importFrigatePlusModel(input),
85129
+ plusCatalogPlusListModels: async () => listPlusModels(plusFetch, this.config.plusCatalogPlusApiKey ?? ""),
85130
+ importPlusCatalogModel: async (input) => this.importPlusCatalogModel(input),
83135
85131
  recommendConvertNode: async (input) => {
83136
85132
  const api = this.ctx.api;
83137
85133
  if (!api) throw new Error("recommendConvertNode: ctx.api unavailable");
@@ -83318,7 +85314,7 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
83318
85314
  };
83319
85315
  }
83320
85316
  /** listNodes/hardwareOf deps for `recommendConvertNode` — shared by the
83321
- * convert actions and the Frigate+ auto-conversion. */
85317
+ * convert actions and the plus catalog auto-conversion. */
83322
85318
  recommendDeps() {
83323
85319
  const api = this.ctx.api;
83324
85320
  if (!api) throw new Error("model-studio: ctx.api unavailable");
@@ -83350,21 +85346,21 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
83350
85346
  return hash.digest("hex");
83351
85347
  }
83352
85348
  /**
83353
- * Projection of the local Scrypted YOLO manifesto plus a read-only HF drift
85349
+ * Projection of the local plugin catalog YOLO manifesto plus a read-only HF drift
83354
85350
  * check. Network errors become `unavailable` rows — the manifesto is never
83355
85351
  * mutated and nothing is auto-imported.
83356
85352
  */
83357
- async listScryptedCatalog() {
85353
+ async listPluginCatalogCatalog() {
83358
85354
  try {
83359
85355
  return {
83360
- entries: SCRYPTED_YOLO_MANIFEST,
83361
- drift: compareScryptedManifestDrift(SCRYPTED_YOLO_MANIFEST, await fetchScryptedRemoteTree({ fetchImpl: fetch })).map(normalizeScryptedDrift)
85356
+ entries: PLUGIN_CATALOG_YOLO_MANIFEST,
85357
+ drift: comparePluginCatalogManifestDrift(PLUGIN_CATALOG_YOLO_MANIFEST, await fetchPluginCatalogRemoteTree({ fetchImpl: fetch })).map(normalizePluginCatalogDrift)
83362
85358
  };
83363
85359
  } catch (err) {
83364
85360
  const details = err instanceof Error ? err.message : "Hugging Face tree unavailable";
83365
85361
  return {
83366
- entries: SCRYPTED_YOLO_MANIFEST,
83367
- drift: SCRYPTED_YOLO_MANIFEST.map((entry) => ({
85362
+ entries: PLUGIN_CATALOG_YOLO_MANIFEST,
85363
+ drift: PLUGIN_CATALOG_YOLO_MANIFEST.map((entry) => ({
83368
85364
  manifestId: entry.id,
83369
85365
  status: "unavailable",
83370
85366
  details
@@ -83377,15 +85373,15 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
83377
85373
  * stay server-owned. Artifacts are NOT staged on the hub — optional
83378
85374
  * `targetNodeId` lands the HF URL on that node via download-on-target.
83379
85375
  */
83380
- async importScryptedCatalogFromManifest(input) {
85376
+ async importPluginCatalogCatalogFromManifest(input) {
83381
85377
  const name = optionalImportName(input.name);
83382
- const entry = getScryptedManifestEntry(input.manifestId);
83383
- if (!entry) throw new Error(`importScryptedCatalogModel: unknown manifest id "${input.manifestId}"`);
85378
+ const entry = getPluginCatalogManifestEntry(input.manifestId);
85379
+ if (!entry) throw new Error(`importPluginCatalogCatalogModel: unknown manifest id "${input.manifestId}"`);
83384
85380
  let drift;
83385
85381
  try {
83386
- const tree = await fetchScryptedRemoteTree({ fetchImpl: fetch });
83387
- const row = compareScryptedManifestDrift(SCRYPTED_YOLO_MANIFEST.filter((e) => e.id === input.manifestId), tree)[0];
83388
- drift = normalizeScryptedDrift(row ?? {
85382
+ const tree = await fetchPluginCatalogRemoteTree({ fetchImpl: fetch });
85383
+ const row = comparePluginCatalogManifestDrift(PLUGIN_CATALOG_YOLO_MANIFEST.filter((e) => e.id === input.manifestId), tree)[0];
85384
+ drift = normalizePluginCatalogDrift(row ?? {
83389
85385
  manifestId: input.manifestId,
83390
85386
  status: "missing",
83391
85387
  details: "entry missing from manifesto"
@@ -83397,8 +85393,8 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
83397
85393
  details: err instanceof Error ? err.message : "Hugging Face tree unavailable"
83398
85394
  };
83399
85395
  }
83400
- if (drift.status !== "ok") throw new Error(`importScryptedCatalogModel: entry "${entry.id}" is blocked by drift (${drift.status}${drift.details ? `: ${drift.details}` : ""})`);
83401
- const built = buildScryptedRegistryDescriptor(entry);
85396
+ if (drift.status !== "ok") throw new Error(`importPluginCatalogCatalogModel: entry "${entry.id}" is blocked by drift (${drift.status}${drift.details ? `: ${drift.details}` : ""})`);
85397
+ const built = buildPluginCatalogRegistryDescriptor(entry);
83402
85398
  const descriptor = name !== void 0 ? {
83403
85399
  stepId: built.stepId,
83404
85400
  entry: {
@@ -83412,7 +85408,7 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
83412
85408
  nodeId: input.targetNodeId,
83413
85409
  format: entry.format
83414
85410
  });
83415
- this.ctx.logger.info("Registered Scrypted catalog model", { meta: {
85411
+ this.ctx.logger.info("Registered plugin catalog catalog model", { meta: {
83416
85412
  manifestId: input.manifestId,
83417
85413
  modelId: descriptor.entry.id,
83418
85414
  format: entry.format,
@@ -83421,15 +85417,15 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
83421
85417
  return descriptor;
83422
85418
  }
83423
85419
  /**
83424
- * Register a curated PUBLIC Frigate catalog model into the Library. The
85420
+ * Register a curated PUBLIC plus catalog catalog model into the Library. The
83425
85421
  * entry keeps its public URL — no hub staging. Optional `targetNodeId`
83426
85422
  * downloads on that node (same path as Library → Distribute).
83427
85423
  */
83428
- async importFrigateCatalogModel(input) {
83429
- const cat = FRIGATE_PUBLIC_CATALOG.find((c) => c.id === input.catalogId);
83430
- if (!cat) throw new Error(`importFrigateCatalogModel: unknown catalog id "${input.catalogId}"`);
85424
+ async importPlusCatalogCatalogModel(input) {
85425
+ const cat = PLUS_CATALOG_PUBLIC_CATALOG.find((c) => c.id === input.catalogId);
85426
+ if (!cat) throw new Error(`importPlusCatalogCatalogModel: unknown catalog id "${input.catalogId}"`);
83431
85427
  const name = optionalImportName(input.name);
83432
- const descriptor = buildFrigateCatalogDescriptor(input.catalogId, {
85428
+ const descriptor = buildPlusCatalogCatalogDescriptor(input.catalogId, {
83433
85429
  ...input.modelId !== void 0 ? { modelId: input.modelId } : {},
83434
85430
  ...name !== void 0 ? { name } : {}
83435
85431
  });
@@ -83443,7 +85439,7 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
83443
85439
  });
83444
85440
  bytes = landed.bytes > 0 ? landed.bytes : bytes;
83445
85441
  }
83446
- this.ctx.logger.info("Registered Frigate catalog model", { meta: {
85442
+ this.ctx.logger.info("Registered plus catalog catalog model", { meta: {
83447
85443
  catalogId: input.catalogId,
83448
85444
  modelId: descriptor.entry.id,
83449
85445
  ...input.targetNodeId !== void 0 ? { targetNodeId: input.targetNodeId } : {},
@@ -83456,22 +85452,22 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
83456
85452
  };
83457
85453
  }
83458
85454
  /**
83459
- * Import one of the operator's personal Frigate+ models: resolve metadata +
85455
+ * Import one of the operator's personal plus catalog models: resolve metadata +
83460
85456
  * presigned URL with the SECRET key (server-side only), download into the
83461
85457
  * hub's modelsDir, and register with the model-type-derived characteristics
83462
85458
  * (format, decode, input size, labelmap — nothing hand-typed). The artifact
83463
85459
  * is hub-local: other nodes get it via Models → Distribute.
83464
85460
  */
83465
- async importFrigatePlusModel(input) {
83466
- const modelId = frigatePlusRegistryId(input.plusModelId);
85461
+ async importPlusCatalogModel(input) {
85462
+ const modelId = plusCatalogPlusRegistryId(input.plusModelId);
83467
85463
  const operatorName = optionalImportName(input.name);
83468
- const key = this.config.frigatePlusApiKey ?? "";
85464
+ const key = this.config.plusCatalogPlusApiKey ?? "";
83469
85465
  const { info, downloadUrl } = await requestPlusModelDownload(plusFetch, key, input.plusModelId);
83470
85466
  let decode;
83471
85467
  try {
83472
85468
  decode = resolvePlusDecode(info, input.format);
83473
85469
  } catch (err) {
83474
- if (err instanceof UnsupportedPlusDecodeError) this.ctx.logger.warn("Frigate+ model import refused — no decoder", { meta: {
85470
+ if (err instanceof UnsupportedPlusDecodeError) this.ctx.logger.warn("plus catalog model import refused — no decoder", { meta: {
83475
85471
  plusModelId: input.plusModelId,
83476
85472
  type: err.type,
83477
85473
  format: err.format,
@@ -83486,12 +85482,12 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
83486
85482
  const bytes = (await node_fs.default.promises.stat(destPath)).size;
83487
85483
  if (bytes < 1e4) {
83488
85484
  await node_fs.default.promises.rm(destPath, { force: true });
83489
- throw new Error(`importFrigatePlusModel: downloaded only ${bytes} bytes — the signed URL likely expired or the response was an error page`);
85485
+ throw new Error(`importPlusCatalogModel: downloaded only ${bytes} bytes — the signed URL likely expired or the response was an error page`);
83490
85486
  }
83491
85487
  const sha256 = await ModelStudioAddon.fileSha256(destPath);
83492
85488
  const descriptor = plusInfoToDescriptor(info, {
83493
85489
  modelId,
83494
- name: operatorName ?? `Frigate+ ${info.type} (${input.plusModelId.slice(0, 8)})`,
85490
+ name: operatorName ?? `plus catalog ${info.type} (${input.plusModelId.slice(0, 8)})`,
83495
85491
  filename,
83496
85492
  sizeMB: Number((bytes / 1e6).toFixed(1)),
83497
85493
  ...input.format !== void 0 ? { format: input.format } : {}
@@ -83506,7 +85502,7 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
83506
85502
  bytes,
83507
85503
  at: Date.now()
83508
85504
  }));
83509
- this.ctx.logger.info("Imported Frigate+ model", { meta: {
85505
+ this.ctx.logger.info("Imported plus catalog model", { meta: {
83510
85506
  plusModelId: input.plusModelId,
83511
85507
  modelId,
83512
85508
  type: info.type,
@@ -83517,7 +85513,7 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
83517
85513
  let conversions = [];
83518
85514
  if (decode.format === "onnx" && wanted.length > 0) {
83519
85515
  conversions = (await ensureEngineFormats(descriptor.entry, this.plusConversionDeps(async () => (await requestPlusModelDownload(plusFetch, key, input.plusModelId)).downloadUrl, descriptor.stepId), { targetFormats: wanted })).conversions;
83520
- this.ctx.logger.info("Frigate+ import — engine conversions", { meta: {
85516
+ this.ctx.logger.info("plus catalog import — engine conversions", { meta: {
83521
85517
  modelId,
83522
85518
  outcomes: conversions.map((o) => ({ ...o }))
83523
85519
  } });