@trillboards/edge-sdk 0.2.3 → 0.2.6

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 (200) hide show
  1. package/README.md +4 -3
  2. package/deploy/docker/Dockerfile.cloud-sense +117 -0
  3. package/deploy/docker/Dockerfile.cpu +30 -21
  4. package/deploy/docker/Dockerfile.cuda +30 -21
  5. package/deploy/docker/Dockerfile.openvino +30 -20
  6. package/deploy/docker/README.md +9 -4
  7. package/deploy/docker/connector-entrypoint.sh +122 -0
  8. package/deploy/helm/README.md +1 -1
  9. package/deploy/k8s/daemonset.yaml +1 -1
  10. package/deploy/macos/README.md +161 -0
  11. package/deploy/macos/TrillboardsSetupApp.m +603 -0
  12. package/deploy/macos/build-macos-pkg.sh +588 -0
  13. package/deploy/macos/com.trillboards.edge.plist +62 -0
  14. package/deploy/macos/com.trillboards.litertlm.plist +45 -0
  15. package/deploy/macos/pair.command +519 -0
  16. package/deploy/macos/scripts/ensure-litertlm.sh +62 -0
  17. package/deploy/macos/scripts/postinstall +153 -0
  18. package/deploy/macos/scripts/setup-litertlm.sh +272 -0
  19. package/deploy/macos/test-install-pair.sh +383 -0
  20. package/deploy/macos/test-setup-litertlm-reinstall.sh +109 -0
  21. package/deploy/systemd/install.sh +25 -15
  22. package/deploy/systemd/trillboards-edge.service +4 -1
  23. package/deploy/windows/README.md +70 -0
  24. package/deploy/windows/build-windows.ps1 +225 -0
  25. package/deploy/windows/bundle-windows-installer.ps1 +153 -0
  26. package/deploy/windows/check-feeds.js +26 -0
  27. package/deploy/windows/e2e/fixtures/person.jpg +0 -0
  28. package/deploy/windows/e2e/test-local-sense.ps1 +185 -0
  29. package/deploy/windows/install-update.ps1 +101 -0
  30. package/deploy/windows/installer.nsi +138 -0
  31. package/deploy/windows/register-litertlm-task.ps1 +42 -0
  32. package/deploy/windows/register-task.ps1 +44 -0
  33. package/deploy/windows/run-connector.ps1 +69 -0
  34. package/deploy/windows/setup-litertlm.ps1 +361 -0
  35. package/deploy/windows/stop-existing.ps1 +72 -0
  36. package/deploy/windows/trillboards-edge-task.vbs +25 -0
  37. package/deploy/windows/trillboards-edge.cmd +33 -0
  38. package/deploy/windows/trillboards-pair.cmd +276 -0
  39. package/deploy/windows/trillboards-setup.ps1 +456 -0
  40. package/deploy/windows/trillboards-setup.vbs +13 -0
  41. package/dist/AudienceAnalyzeClient.d.ts +136 -0
  42. package/dist/AudienceAnalyzeClient.d.ts.map +1 -0
  43. package/dist/AudienceAnalyzeClient.js +246 -0
  44. package/dist/AudienceAnalyzeClient.js.map +1 -0
  45. package/dist/ChannelProber.d.ts +150 -0
  46. package/dist/ChannelProber.d.ts.map +1 -0
  47. package/dist/ChannelProber.js +887 -0
  48. package/dist/ChannelProber.js.map +1 -0
  49. package/dist/CloudEscalationPolicy.d.ts +143 -0
  50. package/dist/CloudEscalationPolicy.d.ts.map +1 -0
  51. package/dist/CloudEscalationPolicy.js +137 -0
  52. package/dist/CloudEscalationPolicy.js.map +1 -0
  53. package/dist/CloudSensingManager.d.ts +533 -0
  54. package/dist/CloudSensingManager.d.ts.map +1 -0
  55. package/dist/CloudSensingManager.js +1254 -0
  56. package/dist/CloudSensingManager.js.map +1 -0
  57. package/dist/DiscoveryReportClient.d.ts +66 -0
  58. package/dist/DiscoveryReportClient.d.ts.map +1 -0
  59. package/dist/DiscoveryReportClient.js +85 -0
  60. package/dist/DiscoveryReportClient.js.map +1 -0
  61. package/dist/EdgeAgent.d.ts +12 -2
  62. package/dist/EdgeAgent.d.ts.map +1 -1
  63. package/dist/EdgeAgent.js +122 -65
  64. package/dist/EdgeAgent.js.map +1 -1
  65. package/dist/LiteRtVlmProvider.d.ts +193 -0
  66. package/dist/LiteRtVlmProvider.d.ts.map +1 -0
  67. package/dist/LiteRtVlmProvider.js +436 -0
  68. package/dist/LiteRtVlmProvider.js.map +1 -0
  69. package/dist/MosaicSource.d.ts +108 -0
  70. package/dist/MosaicSource.d.ts.map +1 -0
  71. package/dist/MosaicSource.js +274 -0
  72. package/dist/MosaicSource.js.map +1 -0
  73. package/dist/OnvifClient.d.ts +83 -0
  74. package/dist/OnvifClient.d.ts.map +1 -0
  75. package/dist/OnvifClient.js +209 -0
  76. package/dist/OnvifClient.js.map +1 -0
  77. package/dist/PairClient.d.ts +106 -0
  78. package/dist/PairClient.d.ts.map +1 -0
  79. package/dist/PairClient.js +186 -0
  80. package/dist/PairClient.js.map +1 -0
  81. package/dist/RecorderAddressRecovery.d.ts +53 -0
  82. package/dist/RecorderAddressRecovery.d.ts.map +1 -0
  83. package/dist/RecorderAddressRecovery.js +359 -0
  84. package/dist/RecorderAddressRecovery.js.map +1 -0
  85. package/dist/SceneChangeDetector.d.ts +291 -0
  86. package/dist/SceneChangeDetector.d.ts.map +1 -0
  87. package/dist/SceneChangeDetector.js +682 -0
  88. package/dist/SceneChangeDetector.js.map +1 -0
  89. package/dist/SensingProfileClient.d.ts +59 -0
  90. package/dist/SensingProfileClient.d.ts.map +1 -0
  91. package/dist/SensingProfileClient.js +78 -0
  92. package/dist/SensingProfileClient.js.map +1 -0
  93. package/dist/SetupSessionClient.d.ts +114 -0
  94. package/dist/SetupSessionClient.d.ts.map +1 -0
  95. package/dist/SetupSessionClient.js +95 -0
  96. package/dist/SetupSessionClient.js.map +1 -0
  97. package/dist/VlmAdmissionGate.d.ts +126 -0
  98. package/dist/VlmAdmissionGate.d.ts.map +1 -0
  99. package/dist/VlmAdmissionGate.js +166 -0
  100. package/dist/VlmAdmissionGate.js.map +1 -0
  101. package/dist/autoSense.d.ts +216 -0
  102. package/dist/autoSense.d.ts.map +1 -0
  103. package/dist/autoSense.js +521 -0
  104. package/dist/autoSense.js.map +1 -0
  105. package/dist/cli.d.ts +27 -1
  106. package/dist/cli.d.ts.map +1 -1
  107. package/dist/cli.js +511 -21
  108. package/dist/cli.js.map +1 -1
  109. package/dist/combinedSense.d.ts +128 -0
  110. package/dist/combinedSense.d.ts.map +1 -0
  111. package/dist/combinedSense.js +261 -0
  112. package/dist/combinedSense.js.map +1 -0
  113. package/dist/config.d.ts +351 -0
  114. package/dist/config.d.ts.map +1 -1
  115. package/dist/config.js +99 -2
  116. package/dist/config.js.map +1 -1
  117. package/dist/connectorCadence.d.ts +135 -0
  118. package/dist/connectorCadence.d.ts.map +1 -0
  119. package/dist/connectorCadence.js +151 -0
  120. package/dist/connectorCadence.js.map +1 -0
  121. package/dist/dataDir.d.ts +33 -0
  122. package/dist/dataDir.d.ts.map +1 -0
  123. package/dist/dataDir.js +76 -0
  124. package/dist/dataDir.js.map +1 -0
  125. package/dist/deployedCadence.d.ts +167 -0
  126. package/dist/deployedCadence.d.ts.map +1 -0
  127. package/dist/deployedCadence.js +209 -0
  128. package/dist/deployedCadence.js.map +1 -0
  129. package/dist/deployedCadenceSource.d.ts +48 -0
  130. package/dist/deployedCadenceSource.d.ts.map +1 -0
  131. package/dist/deployedCadenceSource.js +74 -0
  132. package/dist/deployedCadenceSource.js.map +1 -0
  133. package/dist/diagnose.d.ts +1 -1
  134. package/dist/diagnose.d.ts.map +1 -1
  135. package/dist/diagnose.js +13 -12
  136. package/dist/diagnose.js.map +1 -1
  137. package/dist/discovery.d.ts +131 -0
  138. package/dist/discovery.d.ts.map +1 -0
  139. package/dist/discovery.js +499 -0
  140. package/dist/discovery.js.map +1 -0
  141. package/dist/gemmaModelOta.d.ts +118 -0
  142. package/dist/gemmaModelOta.d.ts.map +1 -0
  143. package/dist/gemmaModelOta.js +291 -0
  144. package/dist/gemmaModelOta.js.map +1 -0
  145. package/dist/index.d.ts +16 -1
  146. package/dist/index.d.ts.map +1 -1
  147. package/dist/index.js +40 -1
  148. package/dist/index.js.map +1 -1
  149. package/dist/init.d.ts.map +1 -1
  150. package/dist/init.js +41 -18
  151. package/dist/init.js.map +1 -1
  152. package/dist/keepAwake.d.ts +33 -0
  153. package/dist/keepAwake.d.ts.map +1 -0
  154. package/dist/keepAwake.js +54 -0
  155. package/dist/keepAwake.js.map +1 -0
  156. package/dist/legacyRecorderProfile.d.ts +20 -0
  157. package/dist/legacyRecorderProfile.d.ts.map +1 -0
  158. package/dist/legacyRecorderProfile.js +27 -0
  159. package/dist/legacyRecorderProfile.js.map +1 -0
  160. package/dist/localInferenceSchema.d.ts +132 -0
  161. package/dist/localInferenceSchema.d.ts.map +1 -0
  162. package/dist/localInferenceSchema.js +274 -0
  163. package/dist/localInferenceSchema.js.map +1 -0
  164. package/dist/localSenseE2eHarness.d.ts +101 -0
  165. package/dist/localSenseE2eHarness.d.ts.map +1 -0
  166. package/dist/localSenseE2eHarness.js +279 -0
  167. package/dist/localSenseE2eHarness.js.map +1 -0
  168. package/dist/localSensing.d.ts +268 -0
  169. package/dist/localSensing.d.ts.map +1 -0
  170. package/dist/localSensing.js +492 -0
  171. package/dist/localSensing.js.map +1 -0
  172. package/dist/modelIntegrity.d.ts +59 -0
  173. package/dist/modelIntegrity.d.ts.map +1 -0
  174. package/dist/modelIntegrity.js +165 -0
  175. package/dist/modelIntegrity.js.map +1 -0
  176. package/dist/pairVerify.d.ts +100 -0
  177. package/dist/pairVerify.d.ts.map +1 -0
  178. package/dist/pairVerify.js +296 -0
  179. package/dist/pairVerify.js.map +1 -0
  180. package/dist/qrScanner.d.ts +33 -0
  181. package/dist/qrScanner.d.ts.map +1 -0
  182. package/dist/qrScanner.js +103 -0
  183. package/dist/qrScanner.js.map +1 -0
  184. package/dist/runtimePaths.d.ts +10 -0
  185. package/dist/runtimePaths.d.ts.map +1 -0
  186. package/dist/runtimePaths.js +79 -0
  187. package/dist/runtimePaths.js.map +1 -0
  188. package/dist/sensingRunMode.d.ts +68 -0
  189. package/dist/sensingRunMode.d.ts.map +1 -0
  190. package/dist/sensingRunMode.js +346 -0
  191. package/dist/sensingRunMode.js.map +1 -0
  192. package/dist/setupMode.d.ts +98 -0
  193. package/dist/setupMode.d.ts.map +1 -0
  194. package/dist/setupMode.js +828 -0
  195. package/dist/setupMode.js.map +1 -0
  196. package/dist/setupProgress.d.ts +31 -0
  197. package/dist/setupProgress.d.ts.map +1 -0
  198. package/dist/setupProgress.js +173 -0
  199. package/dist/setupProgress.js.map +1 -0
  200. package/package.json +13 -4
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.decodeImageToRgba = decodeImageToRgba;
40
+ exports.decodeQrFromImageBuffer = decodeQrFromImageBuffer;
41
+ exports.decodeClaimCodeFromImageFile = decodeClaimCodeFromImageFile;
42
+ const fs = __importStar(require("fs"));
43
+ const jsqr_1 = __importDefault(require("jsqr"));
44
+ const pngjs_1 = require("pngjs");
45
+ const jpeg = __importStar(require("jpeg-js"));
46
+ const PNG_MAGIC = [0x89, 0x50, 0x4e, 0x47]; // "\x89PNG"
47
+ const JPEG_MAGIC = [0xff, 0xd8, 0xff];
48
+ function startsWith(buf, sig) {
49
+ if (buf.length < sig.length)
50
+ return false;
51
+ for (let i = 0; i < sig.length; i += 1) {
52
+ if (buf[i] !== sig[i])
53
+ return false;
54
+ }
55
+ return true;
56
+ }
57
+ /**
58
+ * Decode a PNG or JPEG buffer to RGBA pixels, or null for an unsupported format
59
+ * (sniffed by magic bytes, not file extension, so a mislabeled file still works).
60
+ */
61
+ function decodeImageToRgba(buf) {
62
+ if (startsWith(buf, PNG_MAGIC)) {
63
+ const png = pngjs_1.PNG.sync.read(buf); // always RGBA
64
+ return { data: new Uint8ClampedArray(png.data), width: png.width, height: png.height };
65
+ }
66
+ if (startsWith(buf, JPEG_MAGIC)) {
67
+ const img = jpeg.decode(buf, { useTArray: true, formatAsRGBA: true, maxMemoryUsageInMB: 512 });
68
+ return { data: new Uint8ClampedArray(img.data), width: img.width, height: img.height };
69
+ }
70
+ return null;
71
+ }
72
+ /** Decode the QR payload from an image buffer, or null if unsupported / no QR found. */
73
+ function decodeQrFromImageBuffer(buf) {
74
+ const img = decodeImageToRgba(buf);
75
+ if (!img)
76
+ return null;
77
+ const result = (0, jsqr_1.default)(img.data, img.width, img.height);
78
+ return result && typeof result.data === 'string' ? result.data : null;
79
+ }
80
+ /**
81
+ * Read an image file (a PNG/JPEG screenshot or photo of the portal's claim-code
82
+ * QR) and return the embedded claim code. Throws a clear, owner-facing error for
83
+ * a missing file, an unsupported format, or an image with no QR — so the CLI can
84
+ * print actionable guidance instead of a stack trace.
85
+ */
86
+ async function decodeClaimCodeFromImageFile(filePath) {
87
+ let buf;
88
+ try {
89
+ buf = await fs.promises.readFile(filePath);
90
+ }
91
+ catch {
92
+ throw new Error(`could not read image file: ${filePath}`);
93
+ }
94
+ if (!decodeImageToRgba(buf)) {
95
+ throw new Error(`unsupported image format (save the QR as a PNG or JPEG): ${filePath}`);
96
+ }
97
+ const code = decodeQrFromImageBuffer(buf);
98
+ if (!code || !code.trim()) {
99
+ throw new Error(`no QR code found in image: ${filePath}`);
100
+ }
101
+ return code.trim();
102
+ }
103
+ //# sourceMappingURL=qrScanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qrScanner.js","sourceRoot":"","sources":["../src/qrScanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Resolve the FFmpeg binary for connector run modes.
3
+ *
4
+ * macOS LaunchAgents and Windows scheduled tasks can start with a minimal PATH,
5
+ * so the packaged connector should prefer the FFmpeg shipped beside its bundled
6
+ * Node runtime. Operators can still override with an explicit config/CLI path
7
+ * or TRILLBOARDS_FFMPEG.
8
+ */
9
+ export declare function resolveFfmpegBinaryPath(...configuredPaths: Array<string | null | undefined>): string;
10
+ //# sourceMappingURL=runtimePaths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtimePaths.d.ts","sourceRoot":"","sources":["../src/runtimePaths.ts"],"names":[],"mappings":"AAgBA;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,eAAe,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,GACnD,MAAM,CAmBR"}
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.resolveFfmpegBinaryPath = resolveFfmpegBinaryPath;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const FFMPEG_BINARY = process.platform === 'win32' ? 'ffmpeg.exe' : 'ffmpeg';
40
+ function firstExistingFile(paths) {
41
+ for (const candidate of new Set(paths)) {
42
+ try {
43
+ if (fs.statSync(candidate).isFile())
44
+ return candidate;
45
+ }
46
+ catch {
47
+ // keep looking
48
+ }
49
+ }
50
+ return undefined;
51
+ }
52
+ /**
53
+ * Resolve the FFmpeg binary for connector run modes.
54
+ *
55
+ * macOS LaunchAgents and Windows scheduled tasks can start with a minimal PATH,
56
+ * so the packaged connector should prefer the FFmpeg shipped beside its bundled
57
+ * Node runtime. Operators can still override with an explicit config/CLI path
58
+ * or TRILLBOARDS_FFMPEG.
59
+ */
60
+ function resolveFfmpegBinaryPath(...configuredPaths) {
61
+ for (const configuredPath of configuredPaths) {
62
+ const trimmed = configuredPath?.trim();
63
+ if (trimmed)
64
+ return trimmed;
65
+ }
66
+ const envPath = process.env.TRILLBOARDS_FFMPEG?.trim();
67
+ if (envPath)
68
+ return envPath;
69
+ const bundled = firstExistingFile([
70
+ // Installed connector: edge/bin/node and edge/bin/ffmpeg are siblings.
71
+ path.join(path.dirname(process.execPath), FFMPEG_BINARY),
72
+ // dist/runtimePaths.js in the packaged connector: edge/lib/edge-sdk/dist.
73
+ path.resolve(__dirname, '../../../bin', FFMPEG_BINARY),
74
+ // In-package fallback for future layouts: edge-sdk/dist next to edge-sdk/bin.
75
+ path.resolve(__dirname, '../bin', FFMPEG_BINARY),
76
+ ]);
77
+ return bundled || FFMPEG_BINARY;
78
+ }
79
+ //# sourceMappingURL=runtimePaths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtimePaths.js","sourceRoot":"","sources":["../src/runtimePaths.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,0DAqBC;AA7CD,uCAAyB;AACzB,2CAA6B;AAE7B,MAAM,aAAa,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC;AAE7E,SAAS,iBAAiB,CAAC,KAAe;IACxC,KAAK,MAAM,SAAS,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QACvC,IAAI,CAAC;YACH,IAAI,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE;gBAAE,OAAO,SAAS,CAAC;QACxD,CAAC;QAAC,MAAM,CAAC;YACP,eAAe;QACjB,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,uBAAuB,CACrC,GAAG,eAAiD;IAEpD,KAAK,MAAM,cAAc,IAAI,eAAe,EAAE,CAAC;QAC7C,MAAM,OAAO,GAAG,cAAc,EAAE,IAAI,EAAE,CAAC;QACvC,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;IAC9B,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,EAAE,CAAC;IACvD,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAE5B,MAAM,OAAO,GAAG,iBAAiB,CAAC;QAChC,uEAAuE;QACvE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC;QACxD,0EAA0E;QAC1E,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,cAAc,EAAE,aAAa,CAAC;QACtD,8EAA8E;QAC9E,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,EAAE,aAAa,CAAC;KACjD,CAAC,CAAC;IAEH,OAAO,OAAO,IAAI,aAAa,CAAC;AAClC,CAAC"}
@@ -0,0 +1,68 @@
1
+ import { CloudSensingManager, type ResolvedFeed } from './CloudSensingManager';
2
+ import type { SharedFrameSource } from './MosaicSource';
3
+ import type { EdgeAgentConfig } from './config';
4
+ /**
5
+ * Optional cross-rail mosaic-pull sharing: the combined `sense` entrypoint passes
6
+ * a `sharedSources` registry so the VLM rail attaches to the SAME SharedFrameSource
7
+ * the on-device ONNX zoo rail uses — one RTSP pull per mosaic source feeds both.
8
+ */
9
+ export interface SensingManagerOpts {
10
+ sharedSources?: Map<string, SharedFrameSource>;
11
+ /** Persist DHCP-recovered recorder addresses back to this local config. */
12
+ configPath?: string;
13
+ /** Reuse a caller-owned recovery coordinator across shared sensing rails. */
14
+ streamUrlResolver?: (feed: ResolvedFeed, currentUrl: string, error: Error) => Promise<string | null>;
15
+ }
16
+ /**
17
+ * The lifecycle surface the auto-sense supervisor drives. `CloudSensingManager`
18
+ * already satisfies it: `start()` opens cameras + runs the capture loops;
19
+ * `stop()` clears the loop timers + closes cameras (a clean teardown that a
20
+ * later `start()` resumes from). Narrowed to just these two so the supervisor
21
+ * can hold either a real manager or a test fake.
22
+ */
23
+ export interface SensingManager {
24
+ start(): Promise<void>;
25
+ stop(): Promise<void>;
26
+ }
27
+ /** A console-shaped sink so callers can capture/redirect the build-time logs. */
28
+ export interface SensingIo {
29
+ log: (msg: string) => void;
30
+ warn: (msg: string) => void;
31
+ error: (msg: string) => void;
32
+ }
33
+ /** Default sink: the real console (what the CLI entrypoints use). */
34
+ export declare const consoleIo: SensingIo;
35
+ /**
36
+ * The error logged (and `null` returned) when a build is attempted with no
37
+ * camera feeds configured. Exported so the supervisor + CLI surface the SAME
38
+ * message and so tests can assert on it.
39
+ */
40
+ export declare const NO_FEEDS_MESSAGE: string;
41
+ /**
42
+ * How often the connector prints the one line that answers "why is my
43
+ * 16-camera store only sampling every N seconds?". Long enough not to spam a
44
+ * 24/7 log, short enough that an operator watching an install sees it.
45
+ */
46
+ export declare const SENSING_HEALTH_LOG_INTERVAL_MS: number;
47
+ /**
48
+ * The operator-facing degradation line. A machine that cannot analyze 16
49
+ * cameras every 30 s is not a bug to hide — it is a capacity fact to state, in
50
+ * the terms an operator can act on: how often each camera is actually looked
51
+ * at, how many analyses/minute this machine sustains, and where the rest went.
52
+ */
53
+ export declare function formatSensingHealth(health: ReturnType<CloudSensingManager['getSensingHealth']>): string;
54
+ /**
55
+ * Build (but do NOT start) the thin cloud-sensing manager: RTSP frame → POST
56
+ * /v2/earner/audience-analyze (cloud VLM does the inference). Returns `null`
57
+ * after logging NO_FEEDS_MESSAGE when no feeds are configured — the caller
58
+ * decides how to surface that (the CLI + the supervisor both exit 1).
59
+ */
60
+ export declare function buildCloudSensingManager(config: EdgeAgentConfig, io?: SensingIo, opts?: SensingManagerOpts): CloudSensingManager | null;
61
+ /**
62
+ * Build (but do NOT start) the on-device LOCAL-sensing manager: RTSP frame →
63
+ * LOCAL VLM (LiteRT-LM serving Gemma) → POST the STRUCTURED result as
64
+ * `preAnalyzed` (skips the cloud VLM → no Vertex cost). Returns `null` after
65
+ * logging NO_FEEDS_MESSAGE when no feeds are configured.
66
+ */
67
+ export declare function buildLocalSensingManager(config: EdgeAgentConfig, io?: SensingIo, opts?: SensingManagerOpts): CloudSensingManager | null;
68
+ //# sourceMappingURL=sensingRunMode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sensingRunMode.d.ts","sourceRoot":"","sources":["../src/sensingRunMode.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EAInB,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAMhD;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC/C,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,iBAAiB,CAAC,EAAE,CAClB,IAAI,EAAE,YAAY,EAClB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,KAAK,KACT,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC7B;AA2CD;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,iFAAiF;AACjF,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAED,qEAAqE;AACrE,eAAO,MAAM,SAAS,EAAE,SAIvB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,QAEgD,CAAC;AAE9E;;;;GAIG;AACH,eAAO,MAAM,8BAA8B,QAAgB,CAAC;AA4C5D;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,CAAC,mBAAmB,CAAC,kBAAkB,CAAC,CAAC,GAC1D,MAAM,CAqBR;AAoDD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,eAAe,EACvB,EAAE,GAAE,SAAqB,EACzB,IAAI,CAAC,EAAE,kBAAkB,GACxB,mBAAmB,GAAG,IAAI,CA6D5B;AAqCD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,eAAe,EACvB,EAAE,GAAE,SAAqB,EACzB,IAAI,CAAC,EAAE,kBAAkB,GACxB,mBAAmB,GAAG,IAAI,CAmF5B"}
@@ -0,0 +1,346 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SENSING_HEALTH_LOG_INTERVAL_MS = exports.NO_FEEDS_MESSAGE = exports.consoleIo = void 0;
4
+ exports.formatSensingHealth = formatSensingHealth;
5
+ exports.buildCloudSensingManager = buildCloudSensingManager;
6
+ exports.buildLocalSensingManager = buildLocalSensingManager;
7
+ const CloudSensingManager_1 = require("./CloudSensingManager");
8
+ const localSensing_1 = require("./localSensing");
9
+ const SensingProfileClient_1 = require("./SensingProfileClient");
10
+ const deployedCadenceSource_1 = require("./deployedCadenceSource");
11
+ const RecorderAddressRecovery_1 = require("./RecorderAddressRecovery");
12
+ /**
13
+ * Shared construction of the cloud- and local-sensing managers.
14
+ *
15
+ * Both the explicit `cloud-sense` / `local-sense` CLI entrypoints AND the
16
+ * `auto-sense` supervisor build their managers through here, so there is exactly
17
+ * ONE place that wires an EdgeAgentConfig → a real `CloudSensingManager` (loops +
18
+ * cadence + event logging). The supervisor starts/stops the SAME real managers
19
+ * the explicit modes use — no parallel sensing implementation.
20
+ */
21
+ /**
22
+ * One profile client per feed, so the connector can ask what cadence its
23
+ * operator actually deployed. Each feed's device token binds to its own screen,
24
+ * so this is N clients, not one — the same shape local sensing already uses to
25
+ * fetch each screen's custom fields.
26
+ *
27
+ * Returns undefined when nothing can be asked (no feed carries a device token),
28
+ * which leaves the manager on its constructor cadence exactly as before.
29
+ */
30
+ function cadenceSourceFor(config, feeds, mode) {
31
+ const profileClients = feeds
32
+ .filter((f) => !!f.deviceToken)
33
+ .map((f) => new SensingProfileClient_1.SensingProfileClient({
34
+ apiBaseUrl: config.apiBaseUrl,
35
+ deviceToken: f.deviceToken,
36
+ }));
37
+ return (0, deployedCadenceSource_1.buildDeployedCadenceSource)({
38
+ profileClients,
39
+ mode,
40
+ feedCount: feeds.length,
41
+ monthlyBudgetUsdPerCamera: config.cloudSensing?.monthlyBudgetUsdPerCamera,
42
+ });
43
+ }
44
+ const DEFAULT_LITERT_LM_BASE_URL = 'http://localhost:9379';
45
+ const DEFAULT_LITERT_LM_MODEL = 'gemma-4-E2B-it.litertlm';
46
+ /** Default sink: the real console (what the CLI entrypoints use). */
47
+ exports.consoleIo = {
48
+ log: (m) => console.log(m),
49
+ warn: (m) => console.warn(m),
50
+ error: (m) => console.error(m),
51
+ };
52
+ /**
53
+ * The error logged (and `null` returned) when a build is attempted with no
54
+ * camera feeds configured. Exported so the supervisor + CLI surface the SAME
55
+ * message and so tests can assert on it.
56
+ */
57
+ exports.NO_FEEDS_MESSAGE = 'No camera feeds configured. Set `cameras: [{ name, screenId, deviceToken, rtspUrl }]` ' +
58
+ 'for multi-channel, or `camera.rtspUrl` + `deviceToken` for a single feed.';
59
+ /**
60
+ * How often the connector prints the one line that answers "why is my
61
+ * 16-camera store only sampling every N seconds?". Long enough not to spam a
62
+ * 24/7 log, short enough that an operator watching an install sees it.
63
+ */
64
+ exports.SENSING_HEALTH_LOG_INTERVAL_MS = 5 * 60 * 1000;
65
+ const CADENCE_CLAMP_WORDING = {
66
+ no_request: '',
67
+ operator_request: '',
68
+ cloud_cost_budget: 'cloud spend budget',
69
+ local_inference_budget: 'this machine\'s single inference slot',
70
+ look_interval: 'the connector never looks that often',
71
+ cadence_ceiling: 'a capture loop cannot run a cadence that slow',
72
+ };
73
+ /**
74
+ * The deployed-cadence fragment of the capacity line.
75
+ *
76
+ * `resolveDeployedCadence` exists to make a clamp legible instead of silent, and
77
+ * `getSensingHealth()` duly returns the whole verdict — but this formatter, the
78
+ * ONLY thing in the connector that a human ever reads, dropped it. An operator
79
+ * who set "every 30 seconds" in the portal and is being run at 303 saw a line
80
+ * about analyses/minute and nothing at all about the 10x gap or its reason. A
81
+ * clamp nobody is told about is a silent clamp however carefully the verdict
82
+ * that produced it was modelled.
83
+ *
84
+ * The projected bill rides along whenever the cloud path knows it, clamped or
85
+ * not: "what is this camera costing me" is the other question this number is
86
+ * the only answer to.
87
+ */
88
+ function formatDeployedCadence(cadence) {
89
+ if (!cadence || cadence.intervalMs === null)
90
+ return [];
91
+ const secs = (ms) => `${(ms / 1000).toFixed(0)}s`;
92
+ const parts = [];
93
+ if (cadence.clamped && cadence.requestedMs !== null) {
94
+ parts.push(`deployed ${secs(cadence.requestedMs)} → running ${secs(cadence.intervalMs)} ` +
95
+ `(${CADENCE_CLAMP_WORDING[cadence.reason] || cadence.reason})`);
96
+ }
97
+ else {
98
+ parts.push(`deployed cadence ${secs(cadence.intervalMs)}`);
99
+ }
100
+ if (cadence.estimatedMonthlyUsdPerCamera !== null) {
101
+ parts.push(`~$${cadence.estimatedMonthlyUsdPerCamera.toFixed(0)}/camera/month`);
102
+ }
103
+ return parts;
104
+ }
105
+ /**
106
+ * The operator-facing degradation line. A machine that cannot analyze 16
107
+ * cameras every 30 s is not a bug to hide — it is a capacity fact to state, in
108
+ * the terms an operator can act on: how often each camera is actually looked
109
+ * at, how many analyses/minute this machine sustains, and where the rest went.
110
+ */
111
+ function formatSensingHealth(health) {
112
+ const perCamera = health.effectiveSampleIntervalMs === null
113
+ ? 'no analyses yet'
114
+ : `every ${(health.effectiveSampleIntervalMs / 1000).toFixed(0)}s per camera`;
115
+ const parts = [
116
+ `${health.loops} feed${health.loops === 1 ? '' : 's'}`,
117
+ `sampling ${perCamera}`,
118
+ `sustained ${health.analysesPerMinute.toFixed(1)} analyses/min (cap ${health.maxConcurrentAnalyses} concurrent)`,
119
+ ];
120
+ if (health.motionSkipped > 0)
121
+ parts.push(`${health.motionSkipped} skipped (no change)`);
122
+ if (health.admissionDenied > 0)
123
+ parts.push(`${health.admissionDenied} deferred (model busy)`);
124
+ parts.push(...formatDeployedCadence(health.deployedCadence));
125
+ // Frames that LEFT the premises for cloud confirmation. Printed whenever
126
+ // escalation is on — including at zero — because "how many frames left" is a
127
+ // question an operator must be able to answer from the log, and an absent
128
+ // line reads as "none" whether or not the feature is even running.
129
+ if (health.cloudEscalationEnabled) {
130
+ parts.push(`${health.cloudEscalated} escalated to cloud (confirming alerts)`);
131
+ }
132
+ return `[sensing] ${parts.join(' · ')}`;
133
+ }
134
+ /**
135
+ * Wire the manager's lifecycle events to the IO sink — identical for both modes
136
+ * except the per-frame "analyzed" line (cloud says `analyze →`, local says
137
+ * `local→preAnalyzed →`).
138
+ *
139
+ * The cascade's per-frame outcomes (`motionSkipped`, `admissionDenied`) are
140
+ * deliberately NOT logged per event: on a saturated 16-camera connector they
141
+ * would be tens of thousands of lines a day and would bury the events that
142
+ * need a human. They stay on the EventEmitter for embedders, and reach the
143
+ * operator as counts on the periodic capacity line below.
144
+ */
145
+ function wireSensingLogs(manager, io, analyzedLine) {
146
+ manager.on('analyzed', ({ name, response }) => {
147
+ io.log(analyzedLine(name, response));
148
+ });
149
+ manager.on('reconnecting', ({ name, delayMs }) => {
150
+ io.warn(`[${name}] RTSP down — re-opening (next retry in ${delayMs}ms)…`);
151
+ });
152
+ manager.on('reconnected', ({ name }) => {
153
+ io.log(`[${name}] RTSP reconnected — sensing resumed`);
154
+ });
155
+ manager.on('error', ({ name, error }) => {
156
+ io.error(`[${name}] error: ${error.message}`);
157
+ });
158
+ // Periodic capacity line. `unref()` so it can never hold the process open.
159
+ const timer = setInterval(() => {
160
+ if (!manager.isRunning())
161
+ return;
162
+ io.log(formatSensingHealth(manager.getSensingHealth()));
163
+ }, exports.SENSING_HEALTH_LOG_INTERVAL_MS);
164
+ if (typeof timer.unref === 'function')
165
+ timer.unref();
166
+ }
167
+ /** Print the per-feed startup banner (the lines the CLI used to print inline). */
168
+ function logFeedBanner(io, header, feeds) {
169
+ for (const line of header)
170
+ io.log(line);
171
+ io.log(` Feeds: ${feeds.length}`);
172
+ for (const f of feeds) {
173
+ io.log(` - ${f.name}${f.screenId ? ` (screen ${f.screenId})` : ''}`);
174
+ }
175
+ io.log('');
176
+ }
177
+ /**
178
+ * Build (but do NOT start) the thin cloud-sensing manager: RTSP frame → POST
179
+ * /v2/earner/audience-analyze (cloud VLM does the inference). Returns `null`
180
+ * after logging NO_FEEDS_MESSAGE when no feeds are configured — the caller
181
+ * decides how to surface that (the CLI + the supervisor both exit 1).
182
+ */
183
+ function buildCloudSensingManager(config, io = exports.consoleIo, opts) {
184
+ const feeds = (0, CloudSensingManager_1.resolveFeeds)(config);
185
+ if (feeds.length === 0) {
186
+ io.error(exports.NO_FEEDS_MESSAGE);
187
+ return null;
188
+ }
189
+ logFeedBanner(io, [` API: ${config.apiBaseUrl}`], feeds);
190
+ const addressRecovery = opts?.streamUrlResolver
191
+ ? null
192
+ : new RecorderAddressRecovery_1.RecorderAddressRecovery(config, {
193
+ configPath: opts?.configPath,
194
+ log: (message) => io.warn(message),
195
+ });
196
+ const loops = (0, CloudSensingManager_1.buildSensingLoops)(config, {
197
+ sharedSources: opts?.sharedSources,
198
+ streamUrlResolver: (feed, currentUrl, error) => opts?.streamUrlResolver?.(feed, currentUrl, error) ??
199
+ addressRecovery.recover(feed, currentUrl, error),
200
+ });
201
+ const manager = new CloudSensingManager_1.CloudSensingManager({
202
+ loops,
203
+ periodicIntervalMs: config.cloudSensing?.periodicIntervalMs,
204
+ faceTriggeredIntervalMs: config.cloudSensing?.faceTriggeredIntervalMs,
205
+ jpegQuality: config.cloudSensing?.jpegQuality,
206
+ // The cadence the operator deployed from the portal, re-asked on the profile
207
+ // TTL so it reaches a RUNNING connector. Clamped by the cloud spend budget —
208
+ // see deployedCadence. Before this the cloud path made NO config-bearing
209
+ // server call after start(), so a portal cadence change reached it never.
210
+ cadenceSource: cadenceSourceFor(config, feeds, 'cloud'),
211
+ // Thin mode: no local face detector drives face state, so POST on the
212
+ // periodic cadence (the cloud VLM does the inference). Honor an explicit
213
+ // opt-in to face-gating if the operator wires an edge motion gate.
214
+ skipPostWhenNoFaces: config.cloudSensing?.skipPostWhenNoFaces ?? false,
215
+ width: config.camera?.width,
216
+ height: config.camera?.height,
217
+ // Self-recover from RTSP drops (retry forever, bounded exponential backoff).
218
+ reconnectInitialDelayMs: config.cloudSensing?.reconnectInitialDelayMs,
219
+ reconnectMaxDelayMs: config.cloudSensing?.reconnectMaxDelayMs,
220
+ // Phase multi-camera loops apart so one connector does not stampede an NVR.
221
+ feedStaggerMs: config.cloudSensing?.feedStaggerMs,
222
+ maxFeedStaggerMs: config.cloudSensing?.maxFeedStaggerMs,
223
+ cameraHealthFailureGraceCount: config.cloudSensing?.cameraHealthFailureGraceCount,
224
+ // The cloud VLM is genuinely concurrent, so admission stays wide open
225
+ // unless the operator narrows it — no behavior change for cloud sensing.
226
+ maxConcurrentAnalyses: config.cloudSensing?.maxConcurrentAnalyses,
227
+ maxAnalysisInFlightMs: config.cloudSensing?.maxAnalysisInFlightMs,
228
+ admissionRetryDelayMs: config.cloudSensing?.admissionRetryDelayMs,
229
+ // Motion cascade is OPT-IN here: cloud has no single-instance ceiling to
230
+ // relieve, and looking more often would raise the per-call bill instead of
231
+ // throughput. Local sensing enables it by default (see below).
232
+ motionGate: resolveMotionGateOptions(config, false),
233
+ });
234
+ wireSensingLogs(manager, io, (name, response) => `[${name}] analyze → HTTP ${response.statusCode}${response.ok ? '' : ' (NOT OK)'}`);
235
+ return manager;
236
+ }
237
+ /**
238
+ * Resolve the motion-cascade options for a run mode, or `undefined` when the
239
+ * cascade is off. `enabledByDefault` differs by mode; an explicit
240
+ * `cloudSensing.motionGate.enabled` always wins.
241
+ */
242
+ function resolveMotionGateOptions(config, enabledByDefault) {
243
+ const configured = config.cloudSensing?.motionGate;
244
+ const enabled = configured?.enabled ?? enabledByDefault;
245
+ if (!enabled)
246
+ return undefined;
247
+ return {
248
+ enabled: true,
249
+ ...(configured?.scanIntervalMs !== undefined
250
+ ? { scanIntervalMs: configured.scanIntervalMs }
251
+ : {}),
252
+ ...(configured?.heartbeatIntervalMs !== undefined
253
+ ? { heartbeatIntervalMs: configured.heartbeatIntervalMs }
254
+ : {}),
255
+ ...(configured?.minAnalyzeIntervalMs !== undefined
256
+ ? { minAnalyzeIntervalMs: configured.minAnalyzeIntervalMs }
257
+ : {}),
258
+ ...(configured?.frameHeight !== undefined ? { frameHeight: configured.frameHeight } : {}),
259
+ ...(configured?.threshold !== undefined ? { threshold: configured.threshold } : {}),
260
+ ...(configured?.contourArea !== undefined ? { contourArea: configured.contourArea } : {}),
261
+ ...(configured?.lightningThreshold !== undefined
262
+ ? { lightningThreshold: configured.lightningThreshold }
263
+ : {}),
264
+ ...(configured?.stationaryReanalyzeEvery !== undefined
265
+ ? { stationaryReanalyzeEvery: configured.stationaryReanalyzeEvery }
266
+ : {}),
267
+ };
268
+ }
269
+ /**
270
+ * Build (but do NOT start) the on-device LOCAL-sensing manager: RTSP frame →
271
+ * LOCAL VLM (LiteRT-LM serving Gemma) → POST the STRUCTURED result as
272
+ * `preAnalyzed` (skips the cloud VLM → no Vertex cost). Returns `null` after
273
+ * logging NO_FEEDS_MESSAGE when no feeds are configured.
274
+ */
275
+ function buildLocalSensingManager(config, io = exports.consoleIo, opts) {
276
+ const feeds = (0, CloudSensingManager_1.resolveFeeds)(config);
277
+ if (feeds.length === 0) {
278
+ io.error(exports.NO_FEEDS_MESSAGE);
279
+ return null;
280
+ }
281
+ const litertLm = config.localSensing?.litertLmBaseUrl || DEFAULT_LITERT_LM_BASE_URL;
282
+ const model = config.localSensing?.model || DEFAULT_LITERT_LM_MODEL;
283
+ // The delegate is resolved by LiteRtVlmProvider at first inference (it reads
284
+ // /v1/models and prefers the `,gpu` variant) and logged there — the banner
285
+ // reports the POLICY so a pinned 'cpu' is visible at startup.
286
+ const accelerator = config.localSensing?.accelerator || 'auto';
287
+ // State the egress posture at startup, in both directions. "Nothing leaves
288
+ // your premises" is only true of the on-device path, so an operator must see
289
+ // which one they are running BEFORE the first frame, not discover it in a log
290
+ // line an hour later.
291
+ // isCloudEscalationEnabled is the SAME expression LocalSensingClient enforces
292
+ // (it also honors attachEvidenceFrame:false), so this line can never announce
293
+ // an egress posture the connector is not actually running.
294
+ const escalation = config.localSensing?.cloudEscalation;
295
+ const escalationLine = (0, localSensing_1.isCloudEscalationEnabled)(config.localSensing)
296
+ ? ` Escalation: ON — a flagged frame is sent to the cloud VLM to confirm an alert ` +
297
+ `(max ${escalation?.maxPerHour ?? 12}/hour per camera)`
298
+ : ' Escalation: off — every frame is analyzed on this machine';
299
+ logFeedBanner(io, [
300
+ ` API: ${config.apiBaseUrl}`,
301
+ ` LiteRT-LM: ${litertLm} (model ${model}, accelerator ${accelerator})`,
302
+ escalationLine,
303
+ ], feeds);
304
+ const addressRecovery = opts?.streamUrlResolver
305
+ ? null
306
+ : new RecorderAddressRecovery_1.RecorderAddressRecovery(config, {
307
+ configPath: opts?.configPath,
308
+ log: (message) => io.warn(message),
309
+ });
310
+ const loops = (0, localSensing_1.buildLocalSensingLoops)(config, {
311
+ sharedSources: opts?.sharedSources,
312
+ streamUrlResolver: (feed, currentUrl, error) => opts?.streamUrlResolver?.(feed, currentUrl, error) ??
313
+ addressRecovery.recover(feed, currentUrl, error),
314
+ });
315
+ const manager = new CloudSensingManager_1.CloudSensingManager({
316
+ loops,
317
+ periodicIntervalMs: config.localSensing?.captureIntervalMs ?? config.cloudSensing?.periodicIntervalMs,
318
+ faceTriggeredIntervalMs: config.cloudSensing?.faceTriggeredIntervalMs,
319
+ // Same deployed cadence, clamped instead by the single local inference slot
320
+ // (connectorCadence's measured 7.30 s/frame ceiling) rather than by money.
321
+ cadenceSource: cadenceSourceFor(config, feeds, 'local'),
322
+ // Local inference has no cloud cost → POST every periodic frame.
323
+ skipPostWhenNoFaces: false,
324
+ width: config.camera?.width,
325
+ height: config.camera?.height,
326
+ // Self-recover from RTSP drops (retry forever, bounded exponential backoff).
327
+ reconnectInitialDelayMs: config.cloudSensing?.reconnectInitialDelayMs,
328
+ reconnectMaxDelayMs: config.cloudSensing?.reconnectMaxDelayMs,
329
+ // Same RTSP/NVR friendliness as cloud mode; local VLM only changes analysis.
330
+ feedStaggerMs: config.cloudSensing?.feedStaggerMs,
331
+ maxFeedStaggerMs: config.cloudSensing?.maxFeedStaggerMs,
332
+ cameraHealthFailureGraceCount: config.cloudSensing?.cameraHealthFailureGraceCount,
333
+ // `litert-lm serve` takes ONE conversation at a time. Without this gate N
334
+ // feeds pile onto it, frames age against the provider's 120 s timeout, and
335
+ // each failure burns retries — 16 cameras produce ~17x the work the server
336
+ // can do. One slot, shared by every feed, drop-not-queue.
337
+ maxConcurrentAnalyses: config.cloudSensing?.maxConcurrentAnalyses ?? 1,
338
+ maxAnalysisInFlightMs: config.cloudSensing?.maxAnalysisInFlightMs,
339
+ admissionRetryDelayMs: config.cloudSensing?.admissionRetryDelayMs,
340
+ // …and don't spend that one slot on an empty aisle: the cascade decides.
341
+ motionGate: resolveMotionGateOptions(config, true),
342
+ });
343
+ wireSensingLogs(manager, io, (name, response) => `[${name}] local→preAnalyzed → HTTP ${response.statusCode}${response.ok ? '' : ' (NOT OK)'}`);
344
+ return manager;
345
+ }
346
+ //# sourceMappingURL=sensingRunMode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sensingRunMode.js","sourceRoot":"","sources":["../src/sensingRunMode.ts"],"names":[],"mappings":"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"}