@camstack/system 1.2.364 → 1.2.366

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 (72) hide show
  1. package/dist/addon-runner.js +1 -1
  2. package/dist/addon-runner.mjs +1 -1
  3. package/dist/addon-utils.d.ts +1 -1
  4. package/dist/addon-utils.js +3 -1
  5. package/dist/addon-utils.mjs +2 -2
  6. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  7. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  8. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  9. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  10. package/dist/builtins/alerts/alerts.addon.js +1 -1
  11. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  12. package/dist/builtins/autotrack/index.js +1 -1
  13. package/dist/builtins/autotrack/index.mjs +1 -1
  14. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  15. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  16. package/dist/builtins/calendars/calendars.addon.js +1 -1
  17. package/dist/builtins/calendars/calendars.addon.mjs +1 -1
  18. package/dist/builtins/camera-grid/index.js +1 -1
  19. package/dist/builtins/camera-grid/index.mjs +1 -1
  20. package/dist/builtins/composer/composer.addon.js +2 -2
  21. package/dist/builtins/composer/composer.addon.mjs +2 -2
  22. package/dist/builtins/console-logging/index.js +1 -1
  23. package/dist/builtins/console-logging/index.mjs +1 -1
  24. package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
  25. package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
  26. package/dist/builtins/device-manager/device-manager.addon.js +2 -2
  27. package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
  28. package/dist/builtins/hub-forwarder/index.js +1 -1
  29. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  30. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  31. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  32. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  33. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  34. package/dist/builtins/local-network/local-network.addon.js +1 -1
  35. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  36. package/dist/builtins/loki-logging/index.js +1 -1
  37. package/dist/builtins/loki-logging/index.mjs +1 -1
  38. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  39. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  40. package/dist/builtins/platform-probe/index.js +1 -1
  41. package/dist/builtins/platform-probe/index.mjs +1 -1
  42. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  43. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  44. package/dist/builtins/snapshot/index.js +1 -1
  45. package/dist/builtins/snapshot/index.mjs +1 -1
  46. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  47. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  48. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
  49. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
  50. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  51. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  52. package/dist/builtins/system-config/system-config.addon.js +1 -1
  53. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  54. package/dist/builtins/winston-logging/index.js +1 -1
  55. package/dist/builtins/winston-logging/index.mjs +1 -1
  56. package/dist/{child-cap-dispatch-B79ITdeA.js → child-cap-dispatch-D9uoEW2A.js} +1 -1
  57. package/dist/{child-cap-dispatch-CtBHqm2J.mjs → child-cap-dispatch-tHbRfy_7.mjs} +1 -1
  58. package/dist/{composition-sources-CNVBIV_9.js → composition-sources-AHfMboGi.js} +1 -1
  59. package/dist/{composition-sources-Dj84elbu.mjs → composition-sources-GjJ1QxMC.mjs} +1 -1
  60. package/dist/{dist-C-IdBSWx.mjs → dist-BUfYKaXx.mjs} +321 -14
  61. package/dist/{dist-DiScyAO6.js → dist-ub3muPSW.js} +338 -13
  62. package/dist/download/hosted-model-revisions.d.ts +10 -0
  63. package/dist/download/model-download-service.d.ts +8 -14
  64. package/dist/download/model-downloader.d.ts +44 -2
  65. package/dist/{event-loop-stall-monitor-NFG6boF5.mjs → event-loop-stall-monitor-CPI1xIcd.mjs} +300 -126
  66. package/dist/{event-loop-stall-monitor-CuTt1wq7.js → event-loop-stall-monitor-j0DRBkuI.js} +317 -125
  67. package/dist/index.d.ts +2 -2
  68. package/dist/index.js +6 -3
  69. package/dist/index.mjs +4 -4
  70. package/dist/{retired-settings-keys-CJpnYIp1.js → retired-settings-keys-DNCxYHe1.js} +1 -1
  71. package/dist/{retired-settings-keys-DIzyi9Jf.mjs → retired-settings-keys-Du41eTrH.mjs} +1 -1
  72. package/package.json +1 -1
@@ -1,4 +1,5 @@
1
1
  const require_chunk = require("./chunk-Cek0wNdY.js");
2
+ const require_dist = require("./dist-ub3muPSW.js");
2
3
  let node_crypto = require("node:crypto");
3
4
  let node_path = require("node:path");
4
5
  node_path = require_chunk.__toESM(node_path);
@@ -8,6 +9,153 @@ let node_util = require("node:util");
8
9
  let node_http = require("node:http");
9
10
  let node_zlib = require("node:zlib");
10
11
  let node_perf_hooks = require("node:perf_hooks");
12
+ //#region src/download/hosted-model-revisions.ts
13
+ /**
14
+ * GENERATED by `scripts/check-hosted-model-revisions.ts --write` — DO NOT EDIT.
15
+ *
16
+ * The revision of every artefact on the CamStack model mirror, keyed by its
17
+ * path under `https://huggingface.co/camstack/camstack-models/resolve/main/`: the sha256 (`lfs.oid`)
18
+ * of its weight file (`revisionWeightUrl`). `resolveFormatRevision` reads
19
+ * it for every catalog format hosted there (D743, D744). Regenerate after
20
+ * any upload to the mirror; the script without `--write` says when it is due.
21
+ */
22
+ var HOSTED_MODEL_REVISIONS = {
23
+ "animalClassification/animal-classifier/coreml/animal-classifier.mlpackage": "2194acb46c1a957c2db766cce0c6f7c295aafc8ad1983843dcb8bc95eac42a34",
24
+ "animalClassification/animal-classifier/onnx/animal-classifier.onnx": "2ccd51865c1d2d600ff68235f5e72a434cb89555197a872489a2357f50771768",
25
+ "animalClassification/animal-classifier/openvino/animal-classifier.xml": "30edf890ff200e8b5169e7a28fcebe148b0d6a5dd3eb570d7a4de89acc9bd63c",
26
+ "animalClassification/bird-classifier/coreml/bird-classifier.mlpackage": "09d5acd27abc89a139399b70ff6711094c05ace5edd6d40b67bf816a41d39a22",
27
+ "animalClassification/bird-classifier/onnx/bird-classifier.onnx": "64dd1b966628145219f2424b42b18b76b8dc33a0a9d9ce90b8c057397fa76da2",
28
+ "animalClassification/bird-classifier/openvino/bird-classifier.xml": "bef863425e1774fba8bf8809a4d690466eeaf183e8d9278493a584a436304339",
29
+ "animalClassification/bird-classifier/tflite/bird-classifier_edgetpu.tflite": "f5b37245cfda13909a34264df58784981aef8dde3bc8604e0ee42caeba29229c",
30
+ "audioClassification/yamnet/onnx/camstack-yamnet.onnx": "d7459a0aefffef8c1ccc60c8e0a0f0758a724fc1b55b47194b418029e938ea26",
31
+ "audioClassification/yamnet/openvino/camstack-yamnet.xml": "11d9e8f47f8af09245bf6a519bc9967b1ead9ac8f8e89d985289ac0fb07926b7",
32
+ "clip/siglip2/coreml/camstack-siglip2-b16-224-vision.mlpackage": "6fdf1936f91d40a4b9b4fcaabe5b2dcadfc6d8c0e76ab1cc9e18c38e95d60787",
33
+ "clip/siglip2/onnx/camstack-siglip2-b16-224-text.onnx": "df6ffc0c44a49648f903fbf6c46722de416447d065e63db97bd3f8edd9bfc411",
34
+ "clip/siglip2/openvino/camstack-siglip2-b16-224-text.xml": "a85203c195eccea00c9d31af5f3594733353cc6b3a3c2802b4e32dc0136f8dae",
35
+ "clip/siglip2/openvino/camstack-siglip2-b16-224-vision.xml": "2e190c41cfa980c8a7a24cb13ecdd71ae0a08eb8665c22a27314aec64e78f325",
36
+ "faceDetection/yunet/coreml/camstack-yunet-2023mar.mlpackage": "d6296bc3ae3048bf3815ef7df8ee934fde48018276c0b2278f93ba359556103b",
37
+ "faceDetection/yunet/onnx/camstack-yunet-2023mar.onnx": "55df63fd5a5128903ee2b6dd4315aa82979be9a1d6cf83cc154b74cd4bd2c42f",
38
+ "faceDetection/yunet/openvino/camstack-yunet-2023mar.xml": "c246c87702b346a9d1de7a70ea61b256d06c7db59bd895acb1aadeaba1985dff",
39
+ "faceDetection/yunet/tflite/camstack-yunet-2023mar_edgetpu.tflite": "b7214dafaf18b8a5c55c7ea502c783e6a356043c2900ff9e02515a368285e982",
40
+ "faceRecognition/auraface/coreml/camstack-auraface-r100.mlpackage": "c189aaf7d6758dafb1603b4ea7f7c2161b69639434ddbce800e0cc632b26d7e0",
41
+ "faceRecognition/auraface/onnx/camstack-auraface-r100.onnx": "1c050a0fd76a5770fb94bd35d1ff99648cb31385280d7fba43284b9b6e63277f",
42
+ "faceRecognition/auraface/openvino/camstack-auraface-r100.xml": "e8f53b3a4bc7d13520d561d2610887bffe8438fac71a496ec1cfcce2616734bb",
43
+ "objectDetection/yolo26/coreml/camstack-yolo26l-256.mlpackage": "87968708ab7ee99aac97d1d6644f6b70149b7b2c38b3f2c3c64326c3cc2333e2",
44
+ "objectDetection/yolo26/coreml/camstack-yolo26l-320.mlpackage": "f0a136258aa69978f5647e07ac4019a4f8c8745dc6d6500c8e3a2876d041f9e5",
45
+ "objectDetection/yolo26/coreml/camstack-yolo26l.mlpackage": "b53d9ce65fc0f84dd13e460bf2666362ac6854f645c897dd0e0c6e8691995146",
46
+ "objectDetection/yolo26/coreml/camstack-yolo26m-256.mlpackage": "bf1ac4cb5f2a3749815a36dde6d6e57ce0662a005ccefd435283d4e38c21298d",
47
+ "objectDetection/yolo26/coreml/camstack-yolo26m-320.mlpackage": "4cf582bf1b14fb7abf87f61a1cf198ad2626fedec32873224bc6f2411e6680b7",
48
+ "objectDetection/yolo26/coreml/camstack-yolo26m.mlpackage": "e9a3751fd3c60676ce94fba7d3d9e8cccfcc8711cd55025eb8837ad8b0fe1424",
49
+ "objectDetection/yolo26/coreml/camstack-yolo26n-256.mlpackage": "1c0565e40b4e04194561df09de4c007ccedd4d5d784adf2341f3af7c97f42cb9",
50
+ "objectDetection/yolo26/coreml/camstack-yolo26n-320.mlpackage": "b30bb5ced9c127f0a813c7740c451a1766226dde43e277e01eb9d298d44f17cd",
51
+ "objectDetection/yolo26/coreml/camstack-yolo26n.mlpackage": "1e176157d427b358db9d87613b1a57040d20c7d0b4a7de70e4477e162dd3d4c5",
52
+ "objectDetection/yolo26/coreml/camstack-yolo26s-256.mlpackage": "e4f3ba3ba99d9a068c4e064fd74427b8a2b56c5e1f56f56979886a493068fbd0",
53
+ "objectDetection/yolo26/coreml/camstack-yolo26s-320.mlpackage": "156d8db8d1f2b9d6bc23ce2e123889d6ad79a5ce866dfccc35c0d869df79db64",
54
+ "objectDetection/yolo26/coreml/camstack-yolo26s.mlpackage": "6d760c59e32daea2812258bd6db417ddfc2eb1be6184daef54ba349bd8d0d125",
55
+ "objectDetection/yolo26/coreml/camstack-yolo26x.mlpackage": "62871ed80cd80cf2b742d2a1ac3ff83f534d9f51039febcb966ee173851fcd5d",
56
+ "objectDetection/yolo26/onnx/camstack-yolo26l-256.onnx": "1a5a963e9b76a324e2fa0e111d96b23176e47a5337e12576a755b512f843592b",
57
+ "objectDetection/yolo26/onnx/camstack-yolo26l-320.onnx": "15ee305cb925934dd73d15a398cc76adf8a51ffa430b11da1ba61f3686eb24b3",
58
+ "objectDetection/yolo26/onnx/camstack-yolo26l.onnx": "62e55ec70eb11f19e75c519a10c1632e08d38a9ddb3229450156a6b423780bbc",
59
+ "objectDetection/yolo26/onnx/camstack-yolo26m-256.onnx": "3d2df9b07b06bfafc6487200674ecb899957e56acbf2ea64383ad477cab30072",
60
+ "objectDetection/yolo26/onnx/camstack-yolo26m-320.onnx": "6a4fc7a9a0c61cf2a401407805bb850b49dbe1faf1cf0ae2edc794a8bc61cc51",
61
+ "objectDetection/yolo26/onnx/camstack-yolo26m.onnx": "907982ada658a53736edfcbdde7e9cf0489a54c058da0deea106bcb2794fe6bc",
62
+ "objectDetection/yolo26/onnx/camstack-yolo26n-256.onnx": "352b15664cea1af55f80f96e9b7a0f8338ca2e6b6053bc27152ad82fc689cb58",
63
+ "objectDetection/yolo26/onnx/camstack-yolo26n-320.onnx": "22d8f1c749394509161b9053361dec19be23c3479f0386a50caba418e7e897a7",
64
+ "objectDetection/yolo26/onnx/camstack-yolo26n.onnx": "8f2e6c82ccbc63153c2284546880b1310d832d2b75efea67cb9cda1fa35da968",
65
+ "objectDetection/yolo26/onnx/camstack-yolo26s-256.onnx": "354ff62da4ffd763f1e7b8761c5d070c1d3f3eafc5221a1a52a3f5b8e651471b",
66
+ "objectDetection/yolo26/onnx/camstack-yolo26s-320.onnx": "465069e0eb3d44e45c2de2c57a57c9ff6f1466cda0816d7ca05ce15e388b0ae3",
67
+ "objectDetection/yolo26/onnx/camstack-yolo26s.onnx": "d2e7ed3e5ef3b7fac18628c63d2bef0d5ae144cb2c239b195eb90ff96437fed5",
68
+ "objectDetection/yolo26/onnx/camstack-yolo26x.onnx": "6d10ddc274ea5e6597c69471a3e122eee7a4cb2a831c9449b30b0e69f4349133",
69
+ "objectDetection/yolo26/openvino/camstack-yolo26l-256-int8.xml": "d59a9920857a48d27bda14b1cbe3ef1390e1032c37a822cbc567f2a03d1f5e2f",
70
+ "objectDetection/yolo26/openvino/camstack-yolo26l-256.xml": "0c78828d4abe9858bb7ff543ee656adb874c11a76cbacbdcca7777d356be2ee3",
71
+ "objectDetection/yolo26/openvino/camstack-yolo26l-320-int8.xml": "9c441c07c7c2d47982b44a2f2d22af0d77ffd466f7279b843c9bbe21cd07a5d8",
72
+ "objectDetection/yolo26/openvino/camstack-yolo26l-320.xml": "0c78828d4abe9858bb7ff543ee656adb874c11a76cbacbdcca7777d356be2ee3",
73
+ "objectDetection/yolo26/openvino/camstack-yolo26l-fp16.xml": "653a3bf71753672f56a2c8dae65195c8c99029abb3d3d7a42e25860a2071df39",
74
+ "objectDetection/yolo26/openvino/camstack-yolo26l-int8.xml": "9e2c1de16b3533c0f8d2ed58e385515bbcb6ab40231bdace5b922795b88127be",
75
+ "objectDetection/yolo26/openvino/camstack-yolo26l.xml": "653a3bf71753672f56a2c8dae65195c8c99029abb3d3d7a42e25860a2071df39",
76
+ "objectDetection/yolo26/openvino/camstack-yolo26m-256-int8.xml": "01c747e08fbac6fedfc874924a267ba3d5597823b8d91c1c39f5db765047cfd8",
77
+ "objectDetection/yolo26/openvino/camstack-yolo26m-256.xml": "c5a4c729eceaec91f6af5077fa34b6f5cc17bc2130d07dc13ed883966e15902e",
78
+ "objectDetection/yolo26/openvino/camstack-yolo26m-320-int8.xml": "2b6be63ad9012c85976223ed46c63b80208479544f13221575f62c4b5a815314",
79
+ "objectDetection/yolo26/openvino/camstack-yolo26m-320.xml": "c5a4c729eceaec91f6af5077fa34b6f5cc17bc2130d07dc13ed883966e15902e",
80
+ "objectDetection/yolo26/openvino/camstack-yolo26m-fp16.xml": "4990e60c17e6e1158dca28750e7a50c3a6c72cac4fd1bbac73bba52ac3647c39",
81
+ "objectDetection/yolo26/openvino/camstack-yolo26m-int8.xml": "7cf3df0dd16d58468ad6ac185ec5f38ac6e20a49069f049007b6c0607586a6f7",
82
+ "objectDetection/yolo26/openvino/camstack-yolo26m.xml": "4990e60c17e6e1158dca28750e7a50c3a6c72cac4fd1bbac73bba52ac3647c39",
83
+ "objectDetection/yolo26/openvino/camstack-yolo26n-256-int8.xml": "acf0ed987bbd43bd819c9f061582c0ba17aa4a3f6bf55f0c8c7049486742f745",
84
+ "objectDetection/yolo26/openvino/camstack-yolo26n-256.xml": "caf498d56ba2288a54734b4d2c73737f77261d1410357f25998e00655c661736",
85
+ "objectDetection/yolo26/openvino/camstack-yolo26n-320-int8.xml": "639e4d54a0d5c6a17d02859a9b46c0ff4d404fbe0582e48ed3df4b8364867316",
86
+ "objectDetection/yolo26/openvino/camstack-yolo26n-320.xml": "caf498d56ba2288a54734b4d2c73737f77261d1410357f25998e00655c661736",
87
+ "objectDetection/yolo26/openvino/camstack-yolo26n-fp16.xml": "77f9da9a6330b130d21e7d9d2338b8f82f3541491c24566b80b4ff2852559b2d",
88
+ "objectDetection/yolo26/openvino/camstack-yolo26n-int8.xml": "92068cd26433694188cf383e3a7c3cc49a36de58387a8012de9c3768080781f3",
89
+ "objectDetection/yolo26/openvino/camstack-yolo26n.xml": "77f9da9a6330b130d21e7d9d2338b8f82f3541491c24566b80b4ff2852559b2d",
90
+ "objectDetection/yolo26/openvino/camstack-yolo26s-256-int8.xml": "483ca9622c3bb398c414cb3ae412bcab26aeb807c91f4d84dcd42356ce54c885",
91
+ "objectDetection/yolo26/openvino/camstack-yolo26s-256.xml": "8e4c513ffe7d571ed1e9545a990a43f6683a8bde04bdc580fdfd8c62e4e3193f",
92
+ "objectDetection/yolo26/openvino/camstack-yolo26s-320-int8.xml": "c02030199cda5083e41599c7aa9dd64d03597e033f03b61c62194de49719de65",
93
+ "objectDetection/yolo26/openvino/camstack-yolo26s-320.xml": "8e4c513ffe7d571ed1e9545a990a43f6683a8bde04bdc580fdfd8c62e4e3193f",
94
+ "objectDetection/yolo26/openvino/camstack-yolo26s-fp16.xml": "bb9355b5e559d646256ad80e4fc2f965c1c1f4905da3c014b7f15bb3d48d9d34",
95
+ "objectDetection/yolo26/openvino/camstack-yolo26s-int8.xml": "863bbfa6f45b617d5600ceb5488a2dc3c0d573b658e761a5c269b86f3f6cca77",
96
+ "objectDetection/yolo26/openvino/camstack-yolo26s.xml": "bb9355b5e559d646256ad80e4fc2f965c1c1f4905da3c014b7f15bb3d48d9d34",
97
+ "objectDetection/yolo26/openvino/camstack-yolo26x-fp16.xml": "053f64a4dc9c3b81d0b6c1a567c0d0b403eeb33a6771170712c4de1c09fc6f15",
98
+ "objectDetection/yolo26/openvino/camstack-yolo26x-int8.xml": "c1f374e058de562d3a848b93d6b39dd9ccb772e2f34f4c0dec4e0bb7787cfd2f",
99
+ "objectDetection/yolo26/openvino/camstack-yolo26x.xml": "053f64a4dc9c3b81d0b6c1a567c0d0b403eeb33a6771170712c4de1c09fc6f15",
100
+ "objectDetection/yolov9/coreml/camstack-yolov9c-320.mlpackage": "7999f25b805f92c732a450625021cda97b7185f8c9f98be28be82be1529fe171",
101
+ "objectDetection/yolov9/coreml/camstack-yolov9c-640.mlpackage": "9889ababc524db385a4305ebc1a42ada4dddc8028198d040fbba77c504228932",
102
+ "objectDetection/yolov9/coreml/camstack-yolov9m-320.mlpackage": "e0e0298051c71c79390f1a05f71a2bb882af52c096c70d69674afb84077f6de4",
103
+ "objectDetection/yolov9/coreml/camstack-yolov9m-640.mlpackage": "4c56eef689435b427c53e92e918be386781024c9b77492f9e486dcdd8ea3570c",
104
+ "objectDetection/yolov9/coreml/camstack-yolov9s-320.mlpackage": "6408badb44161268a337f87586ad82f40e4e315a58be460a648407cc38097675",
105
+ "objectDetection/yolov9/coreml/camstack-yolov9s-640.mlpackage": "9f68b8d418b0832e9788f115e2dfabc6ff54fbe5244815adafa0bd9f98204755",
106
+ "objectDetection/yolov9/coreml/camstack-yolov9t-320.mlpackage": "531aa2d14e7e321f2c90219b966cc3781781d0304c7bed7e6c3b75adaa2ada86",
107
+ "objectDetection/yolov9/coreml/camstack-yolov9t-640.mlpackage": "53dfec9857b3c9922fcbd5e9f88f34ed79de26d9bbcf0d705a1c7a4e5ac93398",
108
+ "objectDetection/yolov9/onnx/camstack-yolov9c-320.onnx": "41b48ef6b39f76340c9a2d40182eddf46ab311b68efbdf637148358f27f1f351",
109
+ "objectDetection/yolov9/onnx/camstack-yolov9c-640.onnx": "4b89e489c4f724ae6c7f271350c9bfd4c800c535e1699f2d6b2d7714293bb695",
110
+ "objectDetection/yolov9/onnx/camstack-yolov9m-320.onnx": "602acf6a2189ad713e5aa0393a3b47c04c8303d6907762f66424f168c3e1e55b",
111
+ "objectDetection/yolov9/onnx/camstack-yolov9m-640.onnx": "d0e69881f62ad156ccbe8699611ae2bd4e569431a9c020b3b6a681efdcd1cfea",
112
+ "objectDetection/yolov9/onnx/camstack-yolov9s-320.onnx": "e06ee6345026ab95f90f5f367b01164654376725fa8e263067ebb9f3417f89c3",
113
+ "objectDetection/yolov9/onnx/camstack-yolov9s-640.onnx": "9113734de682b6b9147b8ed331684d4dc65ddc58d33dd95a00d507c88e82b5c4",
114
+ "objectDetection/yolov9/onnx/camstack-yolov9t-320.onnx": "6c0b0a302a5aaabaf17749a3bda15588a0b196d6f16363198b678c68d2aa5d17",
115
+ "objectDetection/yolov9/onnx/camstack-yolov9t-640.onnx": "fd025ab7bf4d81d506a0561917813431dabe3d673aea4182ff61d7e5c803c2c8",
116
+ "objectDetection/yolov9/openvino/camstack-yolov9c-320-fp16.xml": "3bacbbd621df5570d25dc28b4371cd46847f252743a5246481efffbbc63b5c31",
117
+ "objectDetection/yolov9/openvino/camstack-yolov9c-320-int8.xml": "7614b514c12e03a35a697ed884abd26db1ed8b4ebb5288f8b9e7daf8335909ea",
118
+ "objectDetection/yolov9/openvino/camstack-yolov9c-640-fp16.xml": "702060a1904f8de7eb68b72ad5024976767ba546c3dc941f8b7c2e5d1a236d0d",
119
+ "objectDetection/yolov9/openvino/camstack-yolov9c-640-int8.xml": "3bda3338e0280108a32b6ae638637cd9a2b2a563b8c8ec328165372ee9d55bd9",
120
+ "objectDetection/yolov9/openvino/camstack-yolov9m-320-fp16.xml": "d381e5981e08bad4b8333bba3db48b4c0885883eb1bd524c71e69e2d8b745eaf",
121
+ "objectDetection/yolov9/openvino/camstack-yolov9m-320-int8.xml": "59e5274ed17b2acb57c9ba6999e2e92ea6f05e153fc11e6f8f19bd4973d36a74",
122
+ "objectDetection/yolov9/openvino/camstack-yolov9m-640-fp16.xml": "a64e8867a406c448e65fecea16932d759d85249427c6b43770387904d980d6aa",
123
+ "objectDetection/yolov9/openvino/camstack-yolov9m-640-int8.xml": "b229989cc83ad3c82a3c7f09a25c522eb25416a9d5ce9f1b58225ef4668694b5",
124
+ "objectDetection/yolov9/openvino/camstack-yolov9s-320-fp16.xml": "d07a908f4e44d3b482fad99fd280e1eff7f12546848b3acdfd478407a12fbaf6",
125
+ "objectDetection/yolov9/openvino/camstack-yolov9s-320-int8.xml": "c8c58877a7a3b969ecfced15244c027eb9b9295a82cae54b71197a1a0dbb31f8",
126
+ "objectDetection/yolov9/openvino/camstack-yolov9s-640-fp16.xml": "19448578cde92005a143b8de9655e767032e608cea496e154273ed05a97bed1f",
127
+ "objectDetection/yolov9/openvino/camstack-yolov9s-640-int8.xml": "7ea8b3d6bc98f15b2eada4e62cdcc35c211a181cbddf51251a11e97bee994fdd",
128
+ "objectDetection/yolov9/openvino/camstack-yolov9t-320-fp16.xml": "2f4dc7d06d49af8008fb3da0cdc04a35fdfbc5fafbb2f069822edd826fcc49de",
129
+ "objectDetection/yolov9/openvino/camstack-yolov9t-320-int8.xml": "4b3964c53d2617502aea7bc07fd5fe24da82b27896abe12fd87956b2765babf6",
130
+ "objectDetection/yolov9/openvino/camstack-yolov9t-640-fp16.xml": "d4dd2278941ccb210d0763d822353f6d951c6a4f4f5a1604d7e3536ce6ffb954",
131
+ "objectDetection/yolov9/openvino/camstack-yolov9t-640-int8.xml": "75e45bcf26fe37489d66ae306c3b7c08742b3f2af3c84cd5e41d0520aaef91bf",
132
+ "packageDetection/rfdetr-package/coreml/camstack-rfdetr-package.mlpackage": "73e42f03d66011a311bd83a0a3d1890e7eb1b9b2ba2b5688552a5d4fd60e0e72",
133
+ "packageDetection/rfdetr-package/onnx/camstack-rfdetr-package.onnx": "5af96c6b5936f179e317c9e3915b7c7f74ea3625355f97f6a071c3cd5af2475c",
134
+ "packageDetection/rfdetr-package/openvino/camstack-rfdetr-package.xml": "e2cb5bbccb7809d5c7e691a957bc5e008084119bdf29e2c95d6b6b0791e3061a",
135
+ "plateDetection/yolox-tiny-plate/coreml/camstack-yolox-tiny-plate.mlpackage": "a26ae8fe32e458f7396d56bed83b1243e6067f435b08cd6da134273b9151447d",
136
+ "plateDetection/yolox-tiny-plate/onnx/camstack-yolox-tiny-plate.onnx": "f57b5618eafe91bab19bbdcd9af9b0671dbdba30d76a6e0a3a86b0db24bb1ae6",
137
+ "plateDetection/yolox-tiny-plate/openvino/camstack-yolox-tiny-plate.xml": "83b808eb8fcda6f852477e2dbcdd5cad29ab6a8a58e90017714f167c6a345c27",
138
+ "plateDetection/yolox-tiny-plate/tflite/camstack-yolox-tiny-plate_edgetpu.tflite": "0e091263e9c93063f9da822387860a9cd21c0a554e714de276140921487b8e4d",
139
+ "plateRecognition/cct-s-v2-global/coreml/camstack-cct-s-v2-global.mlpackage": "31b9aba671d98ebd847f43a9e2555f7664c70ad11c3e42fdc0add528463fd3ee",
140
+ "plateRecognition/cct-s-v2-global/onnx/camstack-cct-s-v2-global.onnx": "79c3c00f906857e63453bc16cef6b4a0d34821dff685328eff565fd2da559d21",
141
+ "plateRecognition/cct-s-v2-global/openvino/camstack-cct-s-v2-global.xml": "7357db8b5f1c71a8af9376f2e35435bd0c0361f5193b7e02787f513514ecb8ab",
142
+ "segmentation/yolo26-seg/coreml/camstack-yolo26m-seg.mlpackage": "77ac5c932948df6c6d30f232b40302ccbdfc00f97f7fa78a90dbfb7cdb97608f",
143
+ "segmentation/yolo26-seg/coreml/camstack-yolo26n-seg.mlpackage": "81863a6503294d06063a3320de0a45d543d62b9a3d11009c8d54f5d626abd2a0",
144
+ "segmentation/yolo26-seg/coreml/camstack-yolo26s-seg.mlpackage": "47ee5d620a141bffd594afaf84c4362de2ccf74e036b71ec55ae53428ffbdde8",
145
+ "segmentation/yolo26-seg/onnx/camstack-yolo26m-seg.onnx": "c419fdc8cb8e65c8707586f461d59910487392a5b01711cac674559275df1f7b",
146
+ "segmentation/yolo26-seg/onnx/camstack-yolo26n-seg.onnx": "9f2480a359c8a44541b931d44c4a47898122a5b16ce78d8e5611351b1d4531b8",
147
+ "segmentation/yolo26-seg/onnx/camstack-yolo26s-seg.onnx": "88454cc2f5c2ebaf197536568ffb2ae146a48a85c5c053fd8c9f72f117262313",
148
+ "segmentation/yolo26-seg/openvino/camstack-yolo26m-seg.xml": "08eea0ff1ff6b66a03eb255b9a9ce6952908c92c4684347672d666731148b28f",
149
+ "segmentation/yolo26-seg/openvino/camstack-yolo26n-seg.xml": "d592be6c57fb6f0fc00277327b2421d7ec91fbc0da050bd97fab227df1158c5e",
150
+ "segmentation/yolo26-seg/openvino/camstack-yolo26s-seg.xml": "c4508b20dbfe644220850cfc294e99c9fc396bd61443fcc8db8801a4388e9d99",
151
+ "segmentationRefiner/u2netp/coreml/camstack-u2netp.mlpackage": "67a1172b99e8b34493482b0095bcfe9960d423315a9bfe619b149ea7ba187e05",
152
+ "segmentationRefiner/u2netp/onnx/camstack-u2netp.onnx": "309c8469258dda742793dce0ebea8e6dd393174f89934733ecc8b14c76f4ddd8",
153
+ "segmentationRefiner/u2netp/openvino/camstack-u2netp.xml": "d060dec1fd64855daef223f635cb280f174415785318d4dc78af0d86de025397",
154
+ "vehicleClassification/vehicle-type-v1/coreml/vehicle-type-v1.mlpackage": "26cf66168010daa0a1d33a2fc12305e0e7465c977840861b4bf470c8cae8a7b8",
155
+ "vehicleClassification/vehicle-type-v1/onnx/vehicle-type-v1.onnx": "5153b77de54286bcfefddfdfec9e3c1101b10c30bc33e9181cf8c04e0156818f",
156
+ "vehicleClassification/vehicle-type-v1/openvino/vehicle-type-v1.xml": "bf352f4a602d5e6ef5b6df5140972ef68e79076be397a90c10f1efdda59f4a1e"
157
+ };
158
+ //#endregion
11
159
  //#region src/download/model-downloader.ts
12
160
  function isNonEmptyFile(filePath) {
13
161
  return node_fs.existsSync(filePath) && node_fs.statSync(filePath).size > 0;
@@ -212,22 +360,23 @@ async function computeSha256(filePath) {
212
360
  });
213
361
  }
214
362
  /**
215
- * Download every file in a HuggingFace directory bundle (e.g.,
216
- * `.mlpackage` / OpenVINO IR pair) atomically. `knownFiles` lists the
217
- * relative paths inside the directory; the function fetches each from
218
- * `${url}/${file}` and renames the staging directory only on full
219
- * success. Mirrors `ModelDownloadService.downloadDirectory` but
220
- * exposed as a standalone for catalog-less callers.
363
+ * Download every file in a HuggingFace directory bundle (e.g. `.mlpackage`)
364
+ * atomically. `knownFiles` lists the relative paths inside the directory; a
365
+ * bundle that declares none is listed through the Hugging Face tree API. The
366
+ * staging directory replaces `destDir` only when every file arrived, so a
367
+ * bundle already on disk keeps serving until then.
221
368
  */
222
369
  async function downloadDirectory(url, destDir, knownFiles, onProgress) {
223
370
  const match = url.match(/huggingface\.co\/([^/]+\/[^/]+)\/resolve\/main\/(.+)/);
224
371
  if (!match) throw new Error(`Cannot parse HuggingFace URL: ${url}`);
225
372
  const [, repo, dirPath] = match;
226
- const files = (knownFiles ?? []).map((f) => ({
373
+ if (repo === void 0 || dirPath === void 0) throw new Error(`Cannot parse HuggingFace URL: ${url}`);
374
+ const relativePaths = knownFiles !== void 0 && knownFiles.length > 0 ? knownFiles : (await listHfFiles(repo, dirPath)).map((f) => f.substring(dirPath.length + 1));
375
+ if (relativePaths.length === 0) throw new Error(`No files found in HuggingFace directory: ${dirPath}`);
376
+ const files = relativePaths.map((f) => ({
227
377
  relativePath: f,
228
378
  fileUrl: `https://huggingface.co/${repo}/resolve/main/${dirPath}/${f}`
229
379
  }));
230
- if (files.length === 0) throw new Error(`Directory bundle requires explicit \`files\` list (got none for ${url})`);
231
380
  const tmpDir = destDir + ".downloading";
232
381
  node_fs.rmSync(tmpDir, {
233
382
  recursive: true,
@@ -257,6 +406,21 @@ async function downloadDirectory(url, destDir, knownFiles, onProgress) {
257
406
  throw err;
258
407
  }
259
408
  }
409
+ function isHfTreeEntry(value) {
410
+ return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string" && "path" in value && typeof value.path === "string";
411
+ }
412
+ /** Every file path (repo-relative) under `dirPath`, recursively, via the HF tree API. */
413
+ async function listHfFiles(repo, dirPath) {
414
+ const listing = await fetchJson(`https://huggingface.co/api/models/${repo}/tree/main/${dirPath}`);
415
+ if (!Array.isArray(listing)) throw new Error(`Unexpected HuggingFace tree for ${dirPath}`);
416
+ const files = [];
417
+ for (const entry of listing) {
418
+ if (!isHfTreeEntry(entry)) continue;
419
+ if (entry.type === "file") files.push(entry.path);
420
+ else if (entry.type === "directory") files.push(...await listHfFiles(repo, entry.path));
421
+ }
422
+ return files;
423
+ }
260
424
  /**
261
425
  * Where a node records the catalog `revision` of the format it downloaded:
262
426
  * a sibling of the file or bundle, `<name>.revision` (D743). Outside the
@@ -272,23 +436,92 @@ function readRevisionRecord(modelPath) {
272
436
  return null;
273
437
  }
274
438
  }
439
+ /** The CamStack model mirror. Every artefact under it has a generated revision. */
440
+ var HOSTED_MODEL_MIRROR_PREFIX = require_dist.hfModelUrl(require_dist.HF_REPO, "");
441
+ /**
442
+ * The revision a format must be at — the ONE rule every model download path
443
+ * reads (D743, D744). An inline `revision` wins; otherwise a format hosted on
444
+ * the CamStack mirror takes the revision generated for its path from the
445
+ * mirror's LFS metadata (`hosted-model-revisions.ts`); anything else has none.
446
+ */
447
+ function resolveFormatRevision(formatEntry) {
448
+ if (formatEntry.revision !== void 0) return formatEntry.revision;
449
+ if (!formatEntry.url.startsWith(HOSTED_MODEL_MIRROR_PREFIX)) return void 0;
450
+ return HOSTED_MODEL_REVISIONS[formatEntry.url.slice(HOSTED_MODEL_MIRROR_PREFIX.length)];
451
+ }
452
+ /** The member of a Core ML package that holds its weights. */
453
+ var COREML_WEIGHT_MEMBER = "Data/com.apple.CoreML/weights/weight.bin";
454
+ function revisionWeightFile(formatEntry) {
455
+ if (formatEntry.isDirectory) return formatEntry.url.endsWith(".mlpackage") ? {
456
+ in: "bundle",
457
+ member: COREML_WEIGHT_MEMBER
458
+ } : null;
459
+ const weights = siblingFilesFor(formatEntry).find((f) => f.endsWith(".bin"));
460
+ return weights !== void 0 ? {
461
+ in: "sibling",
462
+ name: weights
463
+ } : { in: "main" };
464
+ }
465
+ /** Where the revision's weight file is hosted — what the mirror's `lfs.oid` describes. */
466
+ function revisionWeightUrl(formatEntry) {
467
+ const weights = revisionWeightFile(formatEntry);
468
+ if (weights === null) return null;
469
+ switch (weights.in) {
470
+ case "bundle": return `${formatEntry.url}/${weights.member}`;
471
+ case "sibling": return siblingUrl(formatEntry.url, weights.name);
472
+ case "main": return formatEntry.url;
473
+ }
474
+ }
475
+ function revisionWeightPath(modelsDir, modelPath, formatEntry) {
476
+ const weights = revisionWeightFile(formatEntry);
477
+ if (weights === null) return null;
478
+ switch (weights.in) {
479
+ case "bundle": return node_path.join(modelPath, weights.member);
480
+ case "sibling": return node_path.join(modelsDir, weights.name);
481
+ case "main": return modelPath;
482
+ }
483
+ }
275
484
  /**
276
- * True when the copy at `modelPath` is the one the catalog names. A format
277
- * without a `revision` is current whenever it is present (the behaviour
278
- * before revisions existed); with one, the node's record must match it — no
279
- * record means the copy predates the revision and may hold replaced bytes.
485
+ * True when the copy at `modelPath` is RECORDED at the revision the format
486
+ * must be at. A format without a revision is current whenever it is present
487
+ * (the behaviour before revisions existed); with one, the node's record must
488
+ * match it — no record means the copy has not been proven current yet.
280
489
  */
281
490
  function isCurrentRevision(modelPath, formatEntry) {
282
- return formatEntry.revision === void 0 || readRevisionRecord(modelPath) === formatEntry.revision;
491
+ const revision = resolveFormatRevision(formatEntry);
492
+ return revision === void 0 || readRevisionRecord(modelPath) === revision;
283
493
  }
284
- function writeRevisionRecord(modelPath, formatEntry) {
285
- if (formatEntry.revision === void 0) return;
494
+ function writeRevisionRecord(modelPath, revision) {
495
+ if (revision === void 0) return;
286
496
  const record = revisionRecordPath(modelPath);
287
497
  const tmp = `${record}.tmp`;
288
- node_fs.writeFileSync(tmp, `${formatEntry.revision}\n`);
498
+ node_fs.writeFileSync(tmp, `${revision}\n`);
289
499
  node_fs.renameSync(tmp, record);
290
500
  }
291
501
  /**
502
+ * Prove an unrecorded (or differently recorded) copy current by hashing its
503
+ * weight file: when it IS the revision, record it and skip the download. This
504
+ * is what keeps a new revision from re-downloading every copy that already
505
+ * holds the right bytes — a copy fetched before revisions existed, one that a
506
+ * hub distributed, one fetched before the catalog caught up with the mirror.
507
+ */
508
+ async function adoptByHash(modelsDir, modelPath, formatEntry) {
509
+ const revision = resolveFormatRevision(formatEntry);
510
+ if (revision === void 0) return false;
511
+ const weights = revisionWeightPath(modelsDir, modelPath, formatEntry);
512
+ if (weights === null || !isNonEmptyFile(weights)) return false;
513
+ if (await computeSha256(weights) !== revision) return false;
514
+ writeRevisionRecord(modelPath, revision);
515
+ return true;
516
+ }
517
+ /** True when every file of the format is on disk, whatever revision it holds. */
518
+ function isCompleteCopy(modelsDir, modelPath, formatEntry) {
519
+ if (!node_fs.existsSync(modelPath)) return false;
520
+ if (formatEntry.isDirectory) return node_fs.existsSync(node_path.join(modelPath, "Manifest.json"));
521
+ if (node_fs.statSync(modelPath).size <= 0) return false;
522
+ return siblingFilesFor(formatEntry).every((f) => isNonEmptyFile(node_path.join(modelsDir, f)));
523
+ }
524
+ /**
292
525
  * Replace a single-file format and its siblings that are already on disk.
293
526
  * `downloadFile` keeps an existing file, so every file is fetched to a
294
527
  * `.updating` name first and moved over the old one only when ALL of them
@@ -333,8 +566,8 @@ async function ensureModel(modelsDir, entry, format, onProgress) {
333
566
  recursive: true,
334
567
  force: true
335
568
  });
336
- else if (siblings.some((f) => !isNonEmptyFile(node_path.join(modelsDir, f)))) outdated = !isCurrentRevision(modelPath, formatEntry);
337
- else if (isCurrentRevision(modelPath, formatEntry)) return modelPath;
569
+ else if (siblings.some((f) => !isNonEmptyFile(node_path.join(modelsDir, f)))) outdated = !isCurrentRevision(modelPath, formatEntry) && !await adoptByHash(modelsDir, modelPath, formatEntry);
570
+ else if (isCurrentRevision(modelPath, formatEntry) || await adoptByHash(modelsDir, modelPath, formatEntry)) return modelPath;
338
571
  else outdated = true;
339
572
  node_fs.mkdirSync(modelsDir, { recursive: true });
340
573
  if (formatEntry.isDirectory) await downloadDirectory(formatEntry.url, modelPath, formatEntry.files, onProgress);
@@ -343,9 +576,39 @@ async function ensureModel(modelsDir, entry, format, onProgress) {
343
576
  await downloadFile(formatEntry.url, modelPath, (downloaded, total) => onProgress?.(downloaded, total === 0 ? void 0 : total));
344
577
  for (const sibling of siblings) await downloadFile(siblingUrl(formatEntry.url, sibling), node_path.join(modelsDir, sibling));
345
578
  }
346
- writeRevisionRecord(modelPath, formatEntry);
579
+ writeRevisionRecord(modelPath, resolveFormatRevision(formatEntry));
347
580
  return modelPath;
348
581
  }
582
+ /**
583
+ * Walk `entries` and record the revision of every complete copy on disk that
584
+ * hashes to it, so a node's listing reports present models as downloaded
585
+ * without waiting for something to `ensureModel` them. Offline: it reads
586
+ * files and never fetches. A copy already recorded current is not re-hashed.
587
+ */
588
+ async function adoptModelRevisions(modelsDir, entries) {
589
+ const adopted = [];
590
+ const stale = [];
591
+ const seen = /* @__PURE__ */ new Set();
592
+ for (const entry of entries) for (const format of Object.keys(entry.formats).filter(isModelFormat)) {
593
+ const formatEntry = entry.formats[format];
594
+ if (formatEntry === void 0 || resolveFormatRevision(formatEntry) === void 0) continue;
595
+ const modelPath = getModelFilePath(modelsDir, entry, format);
596
+ if (modelPath === null || seen.has(modelPath)) continue;
597
+ seen.add(modelPath);
598
+ if (!isCompleteCopy(modelsDir, modelPath, formatEntry)) continue;
599
+ if (isCurrentRevision(modelPath, formatEntry)) continue;
600
+ const key = `${entry.id}/${format}`;
601
+ if (await adoptByHash(modelsDir, modelPath, formatEntry)) adopted.push(key);
602
+ else stale.push(key);
603
+ }
604
+ return {
605
+ adopted,
606
+ stale
607
+ };
608
+ }
609
+ function isModelFormat(value) {
610
+ return require_dist.MODEL_FORMATS.some((f) => f === value);
611
+ }
349
612
  /** Compute the on-disk path for a given model + format, even when not yet downloaded. */
350
613
  function getModelFilePath(modelsDir, entry, format) {
351
614
  const formatEntry = entry.formats[format];
@@ -355,8 +618,10 @@ function getModelFilePath(modelsDir, entry, format) {
355
618
  }
356
619
  /**
357
620
  * True iff the model file (or `Manifest.json` for directory bundles) exists and
358
- * is non-empty, and — when the catalog names a `revision` — the node recorded
359
- * that same revision for it (D743).
621
+ * is non-empty, and — when the format has a revision ({@link
622
+ * resolveFormatRevision}) — the node recorded that same revision for it
623
+ * (D743). Synchronous, so it never hashes: a copy not yet proven current
624
+ * answers false until `ensureModel` or {@link adoptModelRevisions} records it.
360
625
  */
361
626
  function isModelDownloaded(modelsDir, entry, format) {
362
627
  const formatEntry = entry.formats[format];
@@ -364,9 +629,7 @@ function isModelDownloaded(modelsDir, entry, format) {
364
629
  const modelPath = getModelFilePath(modelsDir, entry, format);
365
630
  if (!modelPath || !node_fs.existsSync(modelPath)) return false;
366
631
  if (!isCurrentRevision(modelPath, formatEntry)) return false;
367
- if (formatEntry.isDirectory) return node_fs.existsSync(node_path.join(modelPath, "Manifest.json"));
368
- if (node_fs.statSync(modelPath).size <= 0) return false;
369
- return siblingFilesFor(formatEntry).every((f) => isNonEmptyFile(node_path.join(modelsDir, f)));
632
+ return isCompleteCopy(modelsDir, modelPath, formatEntry);
370
633
  }
371
634
  /** Remove the on-disk model file/directory. Returns true if something was deleted. */
372
635
  function deleteModelFromDisk(modelsDir, entry, format) {
@@ -390,11 +653,13 @@ function deleteModelFromDisk(modelsDir, entry, format) {
390
653
  //#endregion
391
654
  //#region src/download/model-download-service.ts
392
655
  /**
393
- * Unified model download service.
656
+ * A catalog-bound face over the shared downloader.
394
657
  *
395
- * Handles downloading model files and extra files (labels, dicts) from a
396
- * catalog of ModelCatalogEntry items. Supports single-file models and
397
- * directory bundles (e.g., .mlpackage for CoreML).
658
+ * Downloading, completeness and the revision contract (D743) are
659
+ * `ensureModel` / `isModelDownloaded`'s — this class only resolves a model id
660
+ * (and a default format) against its catalog and keys progress by model id.
661
+ * It used to carry its own copy of the download loop, which never learnt the
662
+ * revision; one rule now lives in one place.
398
663
  *
399
664
  * Addons use this via `context.models.ensure(modelId, format)`.
400
665
  */
@@ -410,33 +675,16 @@ var ModelDownloadService = class {
410
675
  this.catalog = map;
411
676
  }
412
677
  /**
413
- * Ensure a model (and its extra files) is downloaded.
678
+ * Ensure a model (and its extra files) is downloaded and current.
414
679
  * Returns the local filesystem path to the model file/directory.
415
680
  */
416
681
  async ensure(modelId, format) {
417
682
  const entry = this.catalog.get(modelId);
418
683
  if (!entry) throw new Error(`ModelDownloadService: unknown model "${modelId}"`);
419
684
  const selectedFormat = format ?? this.pickDefaultFormat(entry);
420
- const formatEntry = entry.formats[selectedFormat];
421
- if (!formatEntry) throw new Error(`ModelDownloadService: model "${modelId}" has no ${selectedFormat} format`);
422
- await this.ensureExtraFiles(modelId);
423
- const modelPath = this.modelFilePath(entry, selectedFormat);
424
- const siblings = siblingFilesFor(formatEntry);
425
- if (node_fs.existsSync(modelPath)) {
426
- if (formatEntry.isDirectory) if (!node_fs.existsSync(node_path.join(modelPath, "Manifest.json"))) node_fs.rmSync(modelPath, {
427
- recursive: true,
428
- force: true
429
- });
430
- else return modelPath;
431
- else if (siblings.every((f) => isNonEmptyFile(node_path.join(this.modelsDir, f)))) return modelPath;
432
- }
433
- node_fs.mkdirSync(this.modelsDir, { recursive: true });
434
- if (formatEntry.isDirectory) await this.downloadDirectory(formatEntry.url, modelPath, formatEntry.files, modelId);
435
- else {
436
- await downloadFile(formatEntry.url, modelPath, this.onProgress ? (downloaded, total) => this.onProgress(modelId, downloaded, total) : void 0);
437
- for (const sibling of siblings) await downloadFile(siblingUrl(formatEntry.url, sibling), node_path.join(this.modelsDir, sibling));
438
- }
439
- return modelPath;
685
+ if (!entry.formats[selectedFormat]) throw new Error(`ModelDownloadService: model "${modelId}" has no ${selectedFormat} format`);
686
+ const onProgress = this.onProgress;
687
+ return ensureModel(this.modelsDir, entry, selectedFormat, onProgress ? (downloaded, total) => onProgress(modelId, downloaded, total ?? 0) : void 0);
440
688
  }
441
689
  /**
442
690
  * Ensure extra files for a model are downloaded.
@@ -459,18 +707,11 @@ var ModelDownloadService = class {
459
707
  getModelsDir() {
460
708
  return this.modelsDir;
461
709
  }
462
- /** Check if a model file is already present on disk. */
710
+ /** True when the model is on disk, complete, and at its revision (D743). */
463
711
  isDownloaded(modelId, format) {
464
712
  const entry = this.catalog.get(modelId);
465
713
  if (!entry) return false;
466
- const selectedFormat = format ?? this.pickDefaultFormat(entry);
467
- const formatEntry = entry.formats[selectedFormat];
468
- if (!formatEntry) return false;
469
- const modelPath = this.modelFilePath(entry, selectedFormat);
470
- if (!node_fs.existsSync(modelPath)) return false;
471
- if (formatEntry.isDirectory) return node_fs.existsSync(node_path.join(modelPath, "Manifest.json"));
472
- if (node_fs.statSync(modelPath).size <= 0) return false;
473
- return siblingFilesFor(formatEntry).every((f) => isNonEmptyFile(node_path.join(this.modelsDir, f)));
714
+ return isModelDownloaded(this.modelsDir, entry, format ?? this.pickDefaultFormat(entry));
474
715
  }
475
716
  /** Get the catalog entry for a model by ID. */
476
717
  getEntry(modelId) {
@@ -488,73 +729,6 @@ var ModelDownloadService = class {
488
729
  if (first) return first;
489
730
  throw new Error(`ModelDownloadService: model "${entry.id}" has no formats`);
490
731
  }
491
- modelFilePath(entry, format) {
492
- const formatEntry = entry.formats[format];
493
- if (!formatEntry) throw new Error(`Model ${entry.id} has no ${format} format`);
494
- const urlParts = formatEntry.url.split("/");
495
- const filename = urlParts[urlParts.length - 1] ?? `${entry.id}.${format}`;
496
- return node_path.join(this.modelsDir, filename);
497
- }
498
- /**
499
- * Download a directory bundle (e.g., .mlpackage) from HuggingFace.
500
- * ATOMIC: downloads to temp dir, renames only on complete success.
501
- */
502
- async downloadDirectory(url, destDir, knownFiles, _modelId) {
503
- const match = url.match(/huggingface\.co\/([^/]+\/[^/]+)\/resolve\/main\/(.+)/);
504
- if (!match) throw new Error(`Cannot parse HuggingFace URL: ${url}`);
505
- const [, repo, dirPath] = match;
506
- let filesToDownload;
507
- if (knownFiles && knownFiles.length > 0) filesToDownload = knownFiles.map((f) => ({
508
- relativePath: f,
509
- fileUrl: `https://huggingface.co/${repo}/resolve/main/${dirPath}/${f}`
510
- }));
511
- else {
512
- const hfFiles = await this.listHfFiles(repo, dirPath);
513
- if (hfFiles.length === 0) throw new Error(`No files found in HuggingFace directory: ${dirPath}`);
514
- filesToDownload = hfFiles.map((f) => ({
515
- relativePath: f.path.substring(dirPath.length + 1),
516
- fileUrl: `https://huggingface.co/${repo}/resolve/main/${f.path}`
517
- }));
518
- }
519
- const tmpDir = destDir + ".downloading";
520
- node_fs.rmSync(tmpDir, {
521
- recursive: true,
522
- force: true
523
- });
524
- node_fs.mkdirSync(tmpDir, { recursive: true });
525
- try {
526
- for (const file of filesToDownload) {
527
- const destPath = node_path.join(tmpDir, file.relativePath);
528
- node_fs.mkdirSync(node_path.dirname(destPath), { recursive: true });
529
- await downloadFile(file.fileUrl, destPath);
530
- }
531
- node_fs.rmSync(destDir, {
532
- recursive: true,
533
- force: true
534
- });
535
- node_fs.renameSync(tmpDir, destDir);
536
- } catch (err) {
537
- node_fs.rmSync(tmpDir, {
538
- recursive: true,
539
- force: true
540
- });
541
- throw err;
542
- }
543
- }
544
- /** Recursively list all files in a HuggingFace directory via API. */
545
- async listHfFiles(repo, dirPath) {
546
- const entries = await fetchJson(`https://huggingface.co/api/models/${repo}/tree/main/${dirPath}`);
547
- const files = [];
548
- for (const entry of entries) if (entry.type === "file") files.push({
549
- path: entry.path,
550
- size: entry.size ?? entry.lfs?.size ?? 0
551
- });
552
- else if (entry.type === "directory") {
553
- const subFiles = await this.listHfFiles(repo, entry.path);
554
- files.push(...subFiles);
555
- }
556
- return files;
557
- }
558
732
  };
559
733
  //#endregion
560
734
  //#region src/http/authenticated-file-server.ts
@@ -1228,6 +1402,12 @@ Object.defineProperty(exports, "STALL_TICK_MS", {
1228
1402
  return STALL_TICK_MS;
1229
1403
  }
1230
1404
  });
1405
+ Object.defineProperty(exports, "adoptModelRevisions", {
1406
+ enumerable: true,
1407
+ get: function() {
1408
+ return adoptModelRevisions;
1409
+ }
1410
+ });
1231
1411
  Object.defineProperty(exports, "attributeStall", {
1232
1412
  enumerable: true,
1233
1413
  get: function() {
@@ -1324,6 +1504,18 @@ Object.defineProperty(exports, "resolveFilePath", {
1324
1504
  return resolveFilePath;
1325
1505
  }
1326
1506
  });
1507
+ Object.defineProperty(exports, "resolveFormatRevision", {
1508
+ enumerable: true,
1509
+ get: function() {
1510
+ return resolveFormatRevision;
1511
+ }
1512
+ });
1513
+ Object.defineProperty(exports, "revisionWeightUrl", {
1514
+ enumerable: true,
1515
+ get: function() {
1516
+ return revisionWeightUrl;
1517
+ }
1518
+ });
1327
1519
  Object.defineProperty(exports, "startEventLoopStallMonitor", {
1328
1520
  enumerable: true,
1329
1521
  get: function() {
package/dist/index.d.ts CHANGED
@@ -39,8 +39,8 @@ export { StorageOrchestratorAddon, StorageOrchestratorService, } from './builtin
39
39
  export { SystemConfigAddon } from './builtins/system-config/index.js';
40
40
  export { WinstonDestination, WinstonLoggingAddon } from './builtins/winston-logging/index.js';
41
41
  export { ModelDownloadService } from './download/model-download-service.js';
42
- export type { DownloadProgressCallback } from './download/model-downloader.js';
43
- export { collectModelFiles, deleteModelFromDisk, downloadFile, downloadModel, ensureModel, fetchJson, getModelFilePath, isModelDownloaded, } from './download/model-downloader.js';
42
+ export type { DownloadProgressCallback, ModelRevisionAdoption, RevisionWeightFile, } from './download/model-downloader.js';
43
+ export { adoptModelRevisions, collectModelFiles, deleteModelFromDisk, downloadFile, downloadModel, ensureModel, fetchJson, getModelFilePath, isModelDownloaded, resolveFormatRevision, revisionWeightUrl, } from './download/model-downloader.js';
44
44
  export { EventBus } from './events/event-bus.js';
45
45
  export type { EventFilter, EventSource, SystemEvent, } from './events/system-event-bus.js';
46
46
  export { SystemEventBus } from './events/system-event-bus.js';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("./chunk-Cek0wNdY.js");
3
- const require_dist = require("./dist-DiScyAO6.js");
3
+ const require_dist = require("./dist-ub3muPSW.js");
4
4
  const require_builtins_alerts_alerts_addon = require("./builtins/alerts/alerts.addon.js");
5
5
  require("./builtins/alerts/index.js");
6
6
  const require_builtins_calendars_calendars_addon = require("./builtins/calendars/calendars.addon.js");
@@ -29,9 +29,9 @@ require("./builtins/storage-orchestrator/index.js");
29
29
  const require_builtins_system_config_system_config_addon = require("./builtins/system-config/system-config.addon.js");
30
30
  require("./builtins/system-config/index.js");
31
31
  const require_builtins_winston_logging_index = require("./builtins/winston-logging/index.js");
32
- const require_event_loop_stall_monitor = require("./event-loop-stall-monitor-CuTt1wq7.js");
32
+ const require_event_loop_stall_monitor = require("./event-loop-stall-monitor-j0DRBkuI.js");
33
33
  const require_tls$1 = require("./tls-CCMX7MjX.js");
34
- const require_child_cap_dispatch = require("./child-cap-dispatch-B79ITdeA.js");
34
+ const require_child_cap_dispatch = require("./child-cap-dispatch-D9uoEW2A.js");
35
35
  const require_resource_monitor = require("./resource-monitor-BgWGRxN5.js");
36
36
  const require_custom_action_registry = require("./custom-action-registry-acBY3mHA.js");
37
37
  let zod = require("zod");
@@ -96484,6 +96484,7 @@ exports.__resetCapUsageRegistryForTests = require_child_cap_dispatch.__resetCapU
96484
96484
  exports.__resetLoggingGateForTests = __resetLoggingGateForTests;
96485
96485
  exports.adaptBrokerToCluster = require_child_cap_dispatch.adaptBrokerToCluster;
96486
96486
  exports.addonSettingsCapability = require_dist.addonSettingsCapability;
96487
+ exports.adoptModelRevisions = require_event_loop_stall_monitor.adoptModelRevisions;
96487
96488
  exports.afterWorkerOnlineAnnounce = require_child_cap_dispatch.afterWorkerOnlineAnnounce;
96488
96489
  exports.allFamiliesListenHost = require_tls$1.allFamiliesListenHost;
96489
96490
  exports.answerClaimedGetStatus = require_child_cap_dispatch.answerClaimedGetStatus;
@@ -96720,9 +96721,11 @@ exports.registerLanHttpHandler = require_tls$1.registerLanHttpHandler;
96720
96721
  exports.reissueTlsLeaf = require_tls$1.reissueTlsLeaf;
96721
96722
  exports.reloadHttpsListener = require_tls$1.reloadHttpsListener;
96722
96723
  exports.resolveFilePath = require_event_loop_stall_monitor.resolveFilePath;
96724
+ exports.resolveFormatRevision = require_event_loop_stall_monitor.resolveFormatRevision;
96723
96725
  exports.resolveHwAccel = require_child_cap_dispatch.resolveHwAccel;
96724
96726
  exports.resolveNpmInvocation = require_child_cap_dispatch.resolveNpmInvocation;
96725
96727
  exports.revertToGeneratedCertificate = require_tls$1.revertToGeneratedCertificate;
96728
+ exports.revisionWeightUrl = require_event_loop_stall_monitor.revisionWeightUrl;
96726
96729
  exports.runHubAddonBoot = runHubAddonBoot;
96727
96730
  exports.runNpm = require_child_cap_dispatch.runNpm;
96728
96731
  exports.sampleSocketDirection = require_child_cap_dispatch.sampleSocketDirection;