@trillboards/edge-sdk 0.2.4 → 0.2.7
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.
- package/README.md +4 -3
- package/deploy/docker/Dockerfile.cloud-sense +117 -0
- package/deploy/docker/Dockerfile.cpu +30 -21
- package/deploy/docker/Dockerfile.cuda +30 -21
- package/deploy/docker/Dockerfile.openvino +30 -20
- package/deploy/docker/README.md +9 -5
- package/deploy/docker/connector-entrypoint.sh +122 -0
- package/deploy/helm/README.md +1 -1
- package/deploy/k8s/daemonset.yaml +1 -1
- package/deploy/macos/README.md +161 -0
- package/deploy/macos/TrillboardsSetupApp.m +603 -0
- package/deploy/macos/build-macos-pkg.sh +588 -0
- package/deploy/macos/com.trillboards.edge.plist +62 -0
- package/deploy/macos/com.trillboards.litertlm.plist +45 -0
- package/deploy/macos/pair.command +519 -0
- package/deploy/macos/scripts/ensure-litertlm.sh +62 -0
- package/deploy/macos/scripts/postinstall +153 -0
- package/deploy/macos/scripts/setup-litertlm.sh +272 -0
- package/deploy/macos/test-install-pair.sh +383 -0
- package/deploy/macos/test-setup-litertlm-reinstall.sh +109 -0
- package/deploy/systemd/install.sh +25 -15
- package/deploy/systemd/trillboards-edge.service +4 -1
- package/deploy/windows/README.md +70 -0
- package/deploy/windows/build-windows.ps1 +225 -0
- package/deploy/windows/bundle-windows-installer.ps1 +153 -0
- package/deploy/windows/check-feeds.js +26 -0
- package/deploy/windows/e2e/fixtures/person.jpg +0 -0
- package/deploy/windows/e2e/test-local-sense.ps1 +185 -0
- package/deploy/windows/install-service.ps1 +6 -1
- package/deploy/windows/install-update.ps1 +101 -0
- package/deploy/windows/installer.nsi +138 -0
- package/deploy/windows/register-litertlm-task.ps1 +42 -0
- package/deploy/windows/register-task.ps1 +44 -0
- package/deploy/windows/run-connector.ps1 +69 -0
- package/deploy/windows/setup-litertlm.ps1 +361 -0
- package/deploy/windows/stop-existing.ps1 +72 -0
- package/deploy/windows/trillboards-edge-task.vbs +25 -0
- package/deploy/windows/trillboards-edge.cmd +33 -0
- package/deploy/windows/trillboards-pair.cmd +276 -0
- package/deploy/windows/trillboards-setup.ps1 +456 -0
- package/deploy/windows/trillboards-setup.vbs +13 -0
- package/dist/AudienceAnalyzeClient.d.ts +136 -0
- package/dist/AudienceAnalyzeClient.d.ts.map +1 -0
- package/dist/AudienceAnalyzeClient.js +246 -0
- package/dist/AudienceAnalyzeClient.js.map +1 -0
- package/dist/ChannelProber.d.ts +150 -0
- package/dist/ChannelProber.d.ts.map +1 -0
- package/dist/ChannelProber.js +887 -0
- package/dist/ChannelProber.js.map +1 -0
- package/dist/CloudEscalationPolicy.d.ts +143 -0
- package/dist/CloudEscalationPolicy.d.ts.map +1 -0
- package/dist/CloudEscalationPolicy.js +137 -0
- package/dist/CloudEscalationPolicy.js.map +1 -0
- package/dist/CloudSensingManager.d.ts +557 -0
- package/dist/CloudSensingManager.d.ts.map +1 -0
- package/dist/CloudSensingManager.js +1267 -0
- package/dist/CloudSensingManager.js.map +1 -0
- package/dist/DiscoveryReportClient.d.ts +66 -0
- package/dist/DiscoveryReportClient.d.ts.map +1 -0
- package/dist/DiscoveryReportClient.js +85 -0
- package/dist/DiscoveryReportClient.js.map +1 -0
- package/dist/EdgeAgent.d.ts +12 -2
- package/dist/EdgeAgent.d.ts.map +1 -1
- package/dist/EdgeAgent.js +55 -13
- package/dist/EdgeAgent.js.map +1 -1
- package/dist/LiteRtVlmProvider.d.ts +193 -0
- package/dist/LiteRtVlmProvider.d.ts.map +1 -0
- package/dist/LiteRtVlmProvider.js +436 -0
- package/dist/LiteRtVlmProvider.js.map +1 -0
- package/dist/MosaicSource.d.ts +108 -0
- package/dist/MosaicSource.d.ts.map +1 -0
- package/dist/MosaicSource.js +274 -0
- package/dist/MosaicSource.js.map +1 -0
- package/dist/OnvifClient.d.ts +83 -0
- package/dist/OnvifClient.d.ts.map +1 -0
- package/dist/OnvifClient.js +209 -0
- package/dist/OnvifClient.js.map +1 -0
- package/dist/PairClient.d.ts +106 -0
- package/dist/PairClient.d.ts.map +1 -0
- package/dist/PairClient.js +186 -0
- package/dist/PairClient.js.map +1 -0
- package/dist/RecorderAddressRecovery.d.ts +53 -0
- package/dist/RecorderAddressRecovery.d.ts.map +1 -0
- package/dist/RecorderAddressRecovery.js +359 -0
- package/dist/RecorderAddressRecovery.js.map +1 -0
- package/dist/SceneChangeDetector.d.ts +291 -0
- package/dist/SceneChangeDetector.d.ts.map +1 -0
- package/dist/SceneChangeDetector.js +682 -0
- package/dist/SceneChangeDetector.js.map +1 -0
- package/dist/SensingProfileClient.d.ts +59 -0
- package/dist/SensingProfileClient.d.ts.map +1 -0
- package/dist/SensingProfileClient.js +78 -0
- package/dist/SensingProfileClient.js.map +1 -0
- package/dist/SetupSessionClient.d.ts +114 -0
- package/dist/SetupSessionClient.d.ts.map +1 -0
- package/dist/SetupSessionClient.js +95 -0
- package/dist/SetupSessionClient.js.map +1 -0
- package/dist/VlmAdmissionGate.d.ts +126 -0
- package/dist/VlmAdmissionGate.d.ts.map +1 -0
- package/dist/VlmAdmissionGate.js +166 -0
- package/dist/VlmAdmissionGate.js.map +1 -0
- package/dist/autoSense.d.ts +266 -0
- package/dist/autoSense.d.ts.map +1 -0
- package/dist/autoSense.js +606 -0
- package/dist/autoSense.js.map +1 -0
- package/dist/cli.d.ts +27 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +526 -27
- package/dist/cli.js.map +1 -1
- package/dist/combinedSense.d.ts +128 -0
- package/dist/combinedSense.d.ts.map +1 -0
- package/dist/combinedSense.js +261 -0
- package/dist/combinedSense.js.map +1 -0
- package/dist/config.d.ts +351 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +99 -2
- package/dist/config.js.map +1 -1
- package/dist/connectorCadence.d.ts +135 -0
- package/dist/connectorCadence.d.ts.map +1 -0
- package/dist/connectorCadence.js +151 -0
- package/dist/connectorCadence.js.map +1 -0
- package/dist/dataDir.d.ts +33 -0
- package/dist/dataDir.d.ts.map +1 -0
- package/dist/dataDir.js +76 -0
- package/dist/dataDir.js.map +1 -0
- package/dist/deployedCadence.d.ts +167 -0
- package/dist/deployedCadence.d.ts.map +1 -0
- package/dist/deployedCadence.js +209 -0
- package/dist/deployedCadence.js.map +1 -0
- package/dist/deployedCadenceSource.d.ts +48 -0
- package/dist/deployedCadenceSource.d.ts.map +1 -0
- package/dist/deployedCadenceSource.js +74 -0
- package/dist/deployedCadenceSource.js.map +1 -0
- package/dist/diagnose.d.ts +1 -1
- package/dist/diagnose.d.ts.map +1 -1
- package/dist/diagnose.js +15 -13
- package/dist/diagnose.js.map +1 -1
- package/dist/discovery.d.ts +131 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +499 -0
- package/dist/discovery.js.map +1 -0
- package/dist/gemmaModelOta.d.ts +118 -0
- package/dist/gemmaModelOta.d.ts.map +1 -0
- package/dist/gemmaModelOta.js +291 -0
- package/dist/gemmaModelOta.js.map +1 -0
- package/dist/index.d.ts +16 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +40 -1
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +25 -87
- package/dist/init.js.map +1 -1
- package/dist/keepAwake.d.ts +33 -0
- package/dist/keepAwake.d.ts.map +1 -0
- package/dist/keepAwake.js +54 -0
- package/dist/keepAwake.js.map +1 -0
- package/dist/legacyRecorderProfile.d.ts +20 -0
- package/dist/legacyRecorderProfile.d.ts.map +1 -0
- package/dist/legacyRecorderProfile.js +27 -0
- package/dist/legacyRecorderProfile.js.map +1 -0
- package/dist/localInferenceSchema.d.ts +132 -0
- package/dist/localInferenceSchema.d.ts.map +1 -0
- package/dist/localInferenceSchema.js +274 -0
- package/dist/localInferenceSchema.js.map +1 -0
- package/dist/localSenseE2eHarness.d.ts +101 -0
- package/dist/localSenseE2eHarness.d.ts.map +1 -0
- package/dist/localSenseE2eHarness.js +279 -0
- package/dist/localSenseE2eHarness.js.map +1 -0
- package/dist/localSensing.d.ts +284 -0
- package/dist/localSensing.d.ts.map +1 -0
- package/dist/localSensing.js +512 -0
- package/dist/localSensing.js.map +1 -0
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +3 -1
- package/dist/mcp-server.js.map +1 -1
- package/dist/modelIntegrity.d.ts +80 -0
- package/dist/modelIntegrity.d.ts.map +1 -0
- package/dist/modelIntegrity.js +194 -0
- package/dist/modelIntegrity.js.map +1 -0
- package/dist/pairVerify.d.ts +100 -0
- package/dist/pairVerify.d.ts.map +1 -0
- package/dist/pairVerify.js +296 -0
- package/dist/pairVerify.js.map +1 -0
- package/dist/qrScanner.d.ts +33 -0
- package/dist/qrScanner.d.ts.map +1 -0
- package/dist/qrScanner.js +103 -0
- package/dist/qrScanner.js.map +1 -0
- package/dist/runtimePaths.d.ts +10 -0
- package/dist/runtimePaths.d.ts.map +1 -0
- package/dist/runtimePaths.js +79 -0
- package/dist/runtimePaths.js.map +1 -0
- package/dist/sensingRunMode.d.ts +86 -0
- package/dist/sensingRunMode.d.ts.map +1 -0
- package/dist/sensingRunMode.js +346 -0
- package/dist/sensingRunMode.js.map +1 -0
- package/dist/setupMode.d.ts +98 -0
- package/dist/setupMode.d.ts.map +1 -0
- package/dist/setupMode.js +828 -0
- package/dist/setupMode.js.map +1 -0
- package/dist/setupProgress.d.ts +31 -0
- package/dist/setupProgress.d.ts.map +1 -0
- package/dist/setupProgress.js +173 -0
- package/dist/setupProgress.js.map +1 -0
- package/package.json +13 -4
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* VlmAdmissionGate — the connector's port of the Android
|
|
4
|
+
* `VlmFrameAdmissionGate` (agent-core `inference/vlm/VlmFrameAdmissionGate.kt`).
|
|
5
|
+
*
|
|
6
|
+
* WHY THIS EXISTS. `litert-lm serve` is a SINGLE-CONVERSATION server: it
|
|
7
|
+
* processes one chat completion at a time. `CloudSensingManager` fans out one
|
|
8
|
+
* independent timer loop per feed, and those loops free-run — at 16 cameras on
|
|
9
|
+
* the 30 s cadence that is ~32 inference requests/minute arriving at a server
|
|
10
|
+
* that sustains 2–10/minute. Without a gate the surplus does not queue
|
|
11
|
+
* politely: the requests pile onto one serve instance, frames age against the
|
|
12
|
+
* provider's 120 s HTTP timeout, and every timeout burns up to 3 retry
|
|
13
|
+
* attempts (`LiteRtVlmProvider` maxAttempts). The machine spends its whole
|
|
14
|
+
* budget re-asking about frames that are already minutes stale.
|
|
15
|
+
*
|
|
16
|
+
* THE ANDROID SEMANTICS, MIRRORED (not reinvented):
|
|
17
|
+
* - a bounded number of in-flight slots (ONE, sized to the serve's real
|
|
18
|
+
* concurrency; `maxInFlight` exists so a genuinely concurrent backend can
|
|
19
|
+
* be sized up, never guessed up);
|
|
20
|
+
* - `minIntervalMs` — a global pacing floor between admissions;
|
|
21
|
+
* - stale recovery at `maxInFlightMs` — a slot whose holder vanished (a
|
|
22
|
+
* crashed provider, a socket that never resolved) is reclaimed rather than
|
|
23
|
+
* wedging sensing forever on an unattended 24/7 connector;
|
|
24
|
+
* - DROP, never queue. A stale frame is worthless: by the time a queued frame
|
|
25
|
+
* reached the model the scene has moved on. The caller is told "no" and
|
|
26
|
+
* tries again on its next tick.
|
|
27
|
+
*
|
|
28
|
+
* WHAT DIFFERS FROM ANDROID, AND WHY. Android has exactly one camera, so its
|
|
29
|
+
* gate is a bare boolean. The connector has N feeds sharing ONE serve, so
|
|
30
|
+
* admission must be attributable: every acquire/deny is counted per feed, which
|
|
31
|
+
* is what makes "camera 12 is being starved" observable instead of invisible.
|
|
32
|
+
* Acquire returns a TICKET rather than a bare boolean so a late release from a
|
|
33
|
+
* call whose slot was already reclaimed as stale cannot free somebody else's
|
|
34
|
+
* slot.
|
|
35
|
+
*
|
|
36
|
+
* THREADING. Node is single-threaded and `tryAcquire`/`release` never await, so
|
|
37
|
+
* the whole body is one critical section by construction — the Kotlin
|
|
38
|
+
* `@Synchronized` has no counterpart to write.
|
|
39
|
+
*/
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.VlmAdmissionGate = void 0;
|
|
42
|
+
const DEFAULT_MAX_IN_FLIGHT = 1;
|
|
43
|
+
const DEFAULT_MAX_IN_FLIGHT_MS = 180000;
|
|
44
|
+
class VlmAdmissionGate {
|
|
45
|
+
constructor(options = {}) {
|
|
46
|
+
this.inFlight = new Set();
|
|
47
|
+
this.nextAllowedAtMs = 0;
|
|
48
|
+
this.admitted = 0;
|
|
49
|
+
this.droppedInFlight = 0;
|
|
50
|
+
this.droppedMinInterval = 0;
|
|
51
|
+
this.staleReclaimed = 0;
|
|
52
|
+
this.lateReleases = 0;
|
|
53
|
+
this.perFeed = new Map();
|
|
54
|
+
this.maxInFlight = Math.max(1, Math.trunc(options.maxInFlight ?? DEFAULT_MAX_IN_FLIGHT));
|
|
55
|
+
this.minIntervalMs = Math.max(0, Math.trunc(options.minIntervalMs ?? 0));
|
|
56
|
+
this.maxInFlightMs = Math.max(0, Math.trunc(options.maxInFlightMs ?? DEFAULT_MAX_IN_FLIGHT_MS));
|
|
57
|
+
this.now = options.now ?? Date.now;
|
|
58
|
+
}
|
|
59
|
+
/** Slots this gate will ever hand out at once. */
|
|
60
|
+
getMaxInFlight() {
|
|
61
|
+
return this.maxInFlight;
|
|
62
|
+
}
|
|
63
|
+
/** Slots currently held (after reclaiming any stale ones). */
|
|
64
|
+
getInFlight(nowMs) {
|
|
65
|
+
this.reclaimStale(nowMs ?? this.now());
|
|
66
|
+
return this.inFlight.size;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Try to take a slot for `name`. Returns a ticket on admission, `null` on a
|
|
70
|
+
* DROP — the caller must abandon this frame, not hold it. Never blocks.
|
|
71
|
+
*/
|
|
72
|
+
tryAcquire(name, nowMs) {
|
|
73
|
+
const now = nowMs ?? this.now();
|
|
74
|
+
this.reclaimStale(now);
|
|
75
|
+
const feed = this.feedStats(name);
|
|
76
|
+
if (this.inFlight.size >= this.maxInFlight) {
|
|
77
|
+
this.droppedInFlight++;
|
|
78
|
+
feed.dropped++;
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
if (now < this.nextAllowedAtMs) {
|
|
82
|
+
this.droppedMinInterval++;
|
|
83
|
+
feed.dropped++;
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
const ticket = { name, acquiredAtMs: now };
|
|
87
|
+
this.inFlight.add(ticket);
|
|
88
|
+
this.nextAllowedAtMs = now + this.minIntervalMs;
|
|
89
|
+
this.admitted++;
|
|
90
|
+
feed.admitted++;
|
|
91
|
+
feed.lastAdmittedAtMs = now;
|
|
92
|
+
return ticket;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Give a slot back. Idempotent, and a no-op for a ticket already reclaimed as
|
|
96
|
+
* stale (counted as a late release so the reclaim threshold stays auditable).
|
|
97
|
+
*/
|
|
98
|
+
release(ticket) {
|
|
99
|
+
if (!ticket)
|
|
100
|
+
return;
|
|
101
|
+
if (!this.inFlight.delete(ticket)) {
|
|
102
|
+
this.lateReleases++;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/** Age (ms) of the oldest held slot, or null when idle. */
|
|
106
|
+
oldestInFlightAgeMs(nowMs) {
|
|
107
|
+
const now = nowMs ?? this.now();
|
|
108
|
+
let oldest = null;
|
|
109
|
+
for (const t of this.inFlight) {
|
|
110
|
+
const age = Math.max(0, now - t.acquiredAtMs);
|
|
111
|
+
if (oldest === null || age > oldest)
|
|
112
|
+
oldest = age;
|
|
113
|
+
}
|
|
114
|
+
return oldest;
|
|
115
|
+
}
|
|
116
|
+
/** Drop every slot and counter (a stop()/start() cycle starts clean). */
|
|
117
|
+
reset() {
|
|
118
|
+
this.inFlight.clear();
|
|
119
|
+
this.nextAllowedAtMs = 0;
|
|
120
|
+
this.admitted = 0;
|
|
121
|
+
this.droppedInFlight = 0;
|
|
122
|
+
this.droppedMinInterval = 0;
|
|
123
|
+
this.staleReclaimed = 0;
|
|
124
|
+
this.lateReleases = 0;
|
|
125
|
+
this.perFeed.clear();
|
|
126
|
+
}
|
|
127
|
+
getStats(nowMs) {
|
|
128
|
+
this.reclaimStale(nowMs ?? this.now());
|
|
129
|
+
return {
|
|
130
|
+
maxInFlight: this.maxInFlight,
|
|
131
|
+
inFlight: this.inFlight.size,
|
|
132
|
+
admitted: this.admitted,
|
|
133
|
+
droppedInFlight: this.droppedInFlight,
|
|
134
|
+
droppedMinInterval: this.droppedMinInterval,
|
|
135
|
+
staleReclaimed: this.staleReclaimed,
|
|
136
|
+
lateReleases: this.lateReleases,
|
|
137
|
+
perFeed: [...this.perFeed.values()].map((f) => ({ ...f })),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
// ─── Private ────────────────────────────────────────────────────────────────
|
|
141
|
+
feedStats(name) {
|
|
142
|
+
let feed = this.perFeed.get(name);
|
|
143
|
+
if (!feed) {
|
|
144
|
+
feed = { name, admitted: 0, dropped: 0, lastAdmittedAtMs: null };
|
|
145
|
+
this.perFeed.set(name, feed);
|
|
146
|
+
}
|
|
147
|
+
return feed;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Free slots whose holder has exceeded `maxInFlightMs` — the Kotlin gate's
|
|
151
|
+
* stale branch. A wedged slot on a 24/7 unattended connector is indefinite
|
|
152
|
+
* blindness, so the gate self-heals rather than waiting for a restart.
|
|
153
|
+
*/
|
|
154
|
+
reclaimStale(nowMs) {
|
|
155
|
+
if (this.maxInFlightMs <= 0 || this.inFlight.size === 0)
|
|
156
|
+
return;
|
|
157
|
+
for (const t of this.inFlight) {
|
|
158
|
+
if (nowMs - t.acquiredAtMs > this.maxInFlightMs) {
|
|
159
|
+
this.inFlight.delete(t);
|
|
160
|
+
this.staleReclaimed++;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
exports.VlmAdmissionGate = VlmAdmissionGate;
|
|
166
|
+
//# sourceMappingURL=VlmAdmissionGate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VlmAdmissionGate.js","sourceRoot":"","sources":["../src/VlmAdmissionGate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { type EdgeAgentConfig } from './config';
|
|
2
|
+
import { type SensingManager } from './sensingRunMode';
|
|
3
|
+
import { type GemmaModelOtaHandle } from './gemmaModelOta';
|
|
4
|
+
/** The outcome of a LiteRT-LM health probe (consumed by the mode selector). */
|
|
5
|
+
export interface LiteRtHealthResult {
|
|
6
|
+
/** True iff litert-lm answered the readiness check with a usable response. */
|
|
7
|
+
ok: boolean;
|
|
8
|
+
/** Human-readable reason (logged so support can diagnose a fallback). */
|
|
9
|
+
reason: string;
|
|
10
|
+
/** Round-trip latency of the probe in ms (best-effort; present on success). */
|
|
11
|
+
latencyMs?: number;
|
|
12
|
+
/** HTTP status the probe observed, when it got a response at all. */
|
|
13
|
+
statusCode?: number;
|
|
14
|
+
}
|
|
15
|
+
/** Minimal injectable HTTP GET — lets tests stub litert-lm entirely (no network). */
|
|
16
|
+
export interface HttpGetter {
|
|
17
|
+
(url: string, options: {
|
|
18
|
+
timeoutMs: number;
|
|
19
|
+
}): Promise<{
|
|
20
|
+
statusCode: number;
|
|
21
|
+
body: string;
|
|
22
|
+
}>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Probe `litert-lm serve` for reachability + readiness via `GET {base}/v1/models`
|
|
26
|
+
* (the OpenAI-compatible model list — cheap, present on a healthy serve, and a
|
|
27
|
+
* de-facto health endpoint). A 2xx with a parseable model list THAT INCLUDES THE
|
|
28
|
+
* MODEL the local-sense path will actually use is "healthy"; anything else
|
|
29
|
+
* (connection refused, timeout, non-2xx, empty/garbage body, OR a serve hosting
|
|
30
|
+
* a DIFFERENT model than configured) is "unhealthy" so the caller degrades to
|
|
31
|
+
* cloud.
|
|
32
|
+
*
|
|
33
|
+
* Why match the model (not just "non-empty list"): the local path posts inference
|
|
34
|
+
* to `config.localSensing.model` (default gemma-4-E2B-it.litertlm). A serve that
|
|
35
|
+
* is up but hosting a DIFFERENT model id would make auto-sense pick local and
|
|
36
|
+
* then fail EVERY frame — exactly the hard-fail this entrypoint exists to avoid.
|
|
37
|
+
* So we require the expected model to be present. (`expectedModel` omitted → fall
|
|
38
|
+
* back to "any non-empty list", e.g. for a pure reachability check.)
|
|
39
|
+
*
|
|
40
|
+
* Built-in http/https only (no extra dependency → survives bundling into the
|
|
41
|
+
* self-contained connector; trivially mockable in tests). Never throws.
|
|
42
|
+
*/
|
|
43
|
+
export declare function probeLiteRtLmHealth(baseUrl?: string, opts?: {
|
|
44
|
+
timeoutMs?: number;
|
|
45
|
+
httpGetter?: HttpGetter;
|
|
46
|
+
expectedModel?: string;
|
|
47
|
+
}): Promise<LiteRtHealthResult>;
|
|
48
|
+
/** A timer handle the supervisor sets for its re-probe loop (injectable in tests). */
|
|
49
|
+
export type AutoSenseTimerHandle = ReturnType<typeof setTimeout>;
|
|
50
|
+
/** Which sensing path the supervisor is currently running. */
|
|
51
|
+
export type SensingMode = 'local' | 'cloud';
|
|
52
|
+
export type AutoSenseState = SensingMode | 'waiting';
|
|
53
|
+
/**
|
|
54
|
+
* Everything the AutoSenseSupervisor needs, all injectable so the supervisor can
|
|
55
|
+
* be unit-tested with a fake probe + fake managers. `runAutoSense` builds this
|
|
56
|
+
* from config + the real probe/managers/timers.
|
|
57
|
+
*/
|
|
58
|
+
export interface AutoSenseSupervisorDeps {
|
|
59
|
+
/** Probe litert-lm, already bound to the resolved base URL / timeout / model. */
|
|
60
|
+
probe: () => Promise<LiteRtHealthResult>;
|
|
61
|
+
/** Build (NOT start) the local-sensing manager. `null` ⇒ no feeds (fatal). */
|
|
62
|
+
buildLocalManager: () => SensingManager | null;
|
|
63
|
+
/** Build (NOT start) the cloud-sensing manager. `null` ⇒ no feeds (fatal). */
|
|
64
|
+
buildCloudManager: () => SensingManager | null;
|
|
65
|
+
/** Log sink (tests capture it). */
|
|
66
|
+
log: (msg: string) => void;
|
|
67
|
+
/** Sleep between startup re-probes (tests inject a no-op). */
|
|
68
|
+
sleep: (ms: number) => Promise<void>;
|
|
69
|
+
/** Arm the steady-state re-probe timer (tests inject a controllable fake). */
|
|
70
|
+
setTimer: (cb: () => void, ms: number) => AutoSenseTimerHandle;
|
|
71
|
+
/** Clear the re-probe timer (tests assert this on shutdown). */
|
|
72
|
+
clearTimer: (handle: AutoSenseTimerHandle) => void;
|
|
73
|
+
/** Called when the chosen mode has NO feeds (fatal config error; default exits 1). */
|
|
74
|
+
onNoFeeds: () => void;
|
|
75
|
+
/** Called after LOCAL sensing starts. Used to defer model OTA until initial provisioning is complete. */
|
|
76
|
+
onLocalActivated?: () => void;
|
|
77
|
+
/** Bounded startup re-probe attempts before committing to the initial mode. */
|
|
78
|
+
startupAttempts: number;
|
|
79
|
+
/** Delay (ms) between startup re-probes. */
|
|
80
|
+
startupBackoffMs: number;
|
|
81
|
+
/** Steady-state re-probe interval (ms), already floored. */
|
|
82
|
+
recheckIntervalMs: number;
|
|
83
|
+
/** Consecutive unhealthy re-probes required before a LOCAL→CLOUD fallback. */
|
|
84
|
+
unhealthyChecksBeforeFallback: number;
|
|
85
|
+
/** Cloud inference is opt-in because continuous CCTV cloud load is expensive. */
|
|
86
|
+
allowCloudFallback: boolean;
|
|
87
|
+
/** For the initial "probing…" log line. */
|
|
88
|
+
litertLmBaseUrl: string;
|
|
89
|
+
expectedModel: string;
|
|
90
|
+
probeTimeoutMs: number;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The `auto-sense` SUPERVISOR. Instead of probing once and then blocking forever
|
|
94
|
+
* on a single manager (the old behavior — mode FIXED for the whole process run,
|
|
95
|
+
* "restart to re-probe"), it OWNS the sensing lifecycle so the connector always
|
|
96
|
+
* prefers on-device Gemma and switches automatically with NO restart:
|
|
97
|
+
*
|
|
98
|
+
* - startInitial(): bounded startup re-probe → start the chosen path's REAL
|
|
99
|
+
* manager directly when litert-lm is healthy; otherwise wait locally unless
|
|
100
|
+
* cloud fallback was explicitly enabled.
|
|
101
|
+
* - beginRechecks(): a steady-state background re-probe loop on recheckIntervalMs.
|
|
102
|
+
* - recheck(): one tick — AUTO-UPGRADE cloud→local the instant local is ready
|
|
103
|
+
* (fixes the fresh-install race with zero restart). Explicit cloud-fallback
|
|
104
|
+
* installs may also recover local→cloud after K unhealthy probes.
|
|
105
|
+
* - shutdown(): stop the active manager + clear the timer (SIGINT/SIGTERM).
|
|
106
|
+
*
|
|
107
|
+
* At most ONE switch per tick; a re-entrancy guard + the K-debounce mean a
|
|
108
|
+
* flapping health signal can never rapidly toggle managers.
|
|
109
|
+
*/
|
|
110
|
+
export declare class AutoSenseSupervisor {
|
|
111
|
+
private readonly deps;
|
|
112
|
+
private mode;
|
|
113
|
+
private active;
|
|
114
|
+
private localManager;
|
|
115
|
+
private cloudManager;
|
|
116
|
+
private consecutiveUnhealthy;
|
|
117
|
+
/**
|
|
118
|
+
* Completed local analyses as of the previous re-probe. `null` = no baseline
|
|
119
|
+
* yet (not on local, or the manager cannot report it), which reads as "no
|
|
120
|
+
* positive evidence" and leaves the pre-existing behaviour in place.
|
|
121
|
+
*/
|
|
122
|
+
private analysesAtLastRecheck;
|
|
123
|
+
private timer;
|
|
124
|
+
private switching;
|
|
125
|
+
private stopped;
|
|
126
|
+
constructor(deps: AutoSenseSupervisorDeps);
|
|
127
|
+
/** The active mode (null until startInitial). For tests/observability. */
|
|
128
|
+
get currentMode(): AutoSenseState | null;
|
|
129
|
+
private getManager;
|
|
130
|
+
/**
|
|
131
|
+
* Initial probe (bounded startup re-probe loop for the fresh-install warmup
|
|
132
|
+
* race) → start the chosen path's manager directly. Returns false (after
|
|
133
|
+
* onNoFeeds) when the chosen mode has no feeds configured.
|
|
134
|
+
*/
|
|
135
|
+
startInitial(): Promise<boolean>;
|
|
136
|
+
/** Build + start a mode's manager and make it active. False ⇒ no feeds. */
|
|
137
|
+
private activate;
|
|
138
|
+
/** Start the steady-state background re-probe loop. */
|
|
139
|
+
beginRechecks(): void;
|
|
140
|
+
private scheduleNextRecheck;
|
|
141
|
+
/**
|
|
142
|
+
* How many ON-DEVICE inferences have completed this run. `null` when the
|
|
143
|
+
* manager cannot report it (a test fake, a not-yet-built manager) — which
|
|
144
|
+
* reads as "no positive evidence", i.e. today's behaviour.
|
|
145
|
+
*/
|
|
146
|
+
private localInferencesCompleted;
|
|
147
|
+
/**
|
|
148
|
+
* One background re-probe tick.
|
|
149
|
+
* - While WAITING: a healthy probe starts local sensing immediately.
|
|
150
|
+
* - On CLOUD: any healthy probe → AUTO-UPGRADE to local immediately (running
|
|
151
|
+
* on cloud while local is ready is pure waste; the K-debounce on the return
|
|
152
|
+
* path bounds any toggling, so this is safe on the first healthy probe).
|
|
153
|
+
* - On LOCAL: a healthy probe resets the debounce; an unhealthy probe
|
|
154
|
+
* increments it, and only after K CONSECUTIVE unhealthy probes do we
|
|
155
|
+
* AUTO-RECOVER to cloud only when explicit fallback is enabled.
|
|
156
|
+
* At most one switch per tick; re-entrancy guarded.
|
|
157
|
+
*
|
|
158
|
+
* ── Why an unanswered probe is not, by itself, a verdict ───────────────────
|
|
159
|
+
*
|
|
160
|
+
* `litert-lm serve` builds on `http.server.HTTPServer` — the SERIAL one, not
|
|
161
|
+
* `ThreadingHTTPServer`. One request is handled at a time, so for the whole
|
|
162
|
+
* duration of a generation the accept loop is blocked and `GET /v1/models`
|
|
163
|
+
* cannot be answered by anybody. The readiness probe therefore competes with
|
|
164
|
+
* the very work whose viability it is meant to certify: measured against the
|
|
165
|
+
* real serve, 4 of 5 probes issued during ONE 11.8 s inference timed out at
|
|
166
|
+
* the shipped 2 000 ms, while an idle serve answered the same request in
|
|
167
|
+
* 2.6 ms.
|
|
168
|
+
*
|
|
169
|
+
* A 16-camera connector keeps that single slot busy essentially all the time,
|
|
170
|
+
* so an UNANSWERED probe was near-certain and two consecutive ones demoted the
|
|
171
|
+
* whole install: measured 3 mode switches in the first 6 minutes of a
|
|
172
|
+
* 16-camera run, each one stopping and restarting all 16 loops and moving
|
|
173
|
+
* every feed onto the metered cloud path. The connector's own success at
|
|
174
|
+
* local inference was the thing that made local inference look dead.
|
|
175
|
+
*
|
|
176
|
+
* The evidence that settles it is not the ping, it is the WORK: an ON-DEVICE
|
|
177
|
+
* inference that COMPLETED since the previous re-probe proves the runtime is
|
|
178
|
+
* alive, and proves it more directly than any side-channel could. So an
|
|
179
|
+
* unanswered probe is inconclusive only while local inferences are still
|
|
180
|
+
* landing; the moment they stop landing the same probe counts, and K of them
|
|
181
|
+
* demote exactly as before.
|
|
182
|
+
*
|
|
183
|
+
* It has to be `localInferences` and not the total analysis count. With
|
|
184
|
+
* `cloudFallbackOnError` on, a frame the local provider THREW on is answered
|
|
185
|
+
* by the cloud and still lands as an analysis — so a dead runtime would keep
|
|
186
|
+
* advancing the total forever and this rule would mask it permanently, which
|
|
187
|
+
* is strictly worse than the defect it replaces.
|
|
188
|
+
*
|
|
189
|
+
* Deliberately NOT keyed on "we have a request in flight": a serve that
|
|
190
|
+
* ACCEPTS and never answers holds our permit for the provider's whole timeout,
|
|
191
|
+
* so in-flight work is compatible with a runtime that is doing nothing. Only
|
|
192
|
+
* completion is proof. An ANSWERED probe stays conclusive either way — a
|
|
193
|
+
* non-2xx or a wrong model list is a real verdict, and a serve that answers
|
|
194
|
+
* has an opinion.
|
|
195
|
+
*/
|
|
196
|
+
recheck(): Promise<void>;
|
|
197
|
+
/** Stop the active manager, start the target — old.stop() BEFORE new.start(). */
|
|
198
|
+
private switchTo;
|
|
199
|
+
/** SIGINT/SIGTERM: stop the active manager + clear the re-probe timer. Idempotent. */
|
|
200
|
+
shutdown(): Promise<void>;
|
|
201
|
+
}
|
|
202
|
+
/** Injection points for runAutoSense (default to the real probe/managers/timers). */
|
|
203
|
+
export interface AutoSenseDeps {
|
|
204
|
+
/**
|
|
205
|
+
* Probe used to decide local-vs-cloud. Defaults to probeLiteRtLmHealth.
|
|
206
|
+
* Receives the resolved base URL, per-probe timeout, and the model the local
|
|
207
|
+
* path will run (so the probe can require it before declaring local usable).
|
|
208
|
+
*/
|
|
209
|
+
probe?: (baseUrl: string, timeoutMs: number, expectedModel: string) => Promise<LiteRtHealthResult>;
|
|
210
|
+
/** Loads the connector config. Defaults to loadConfig. */
|
|
211
|
+
loadConfig?: (configPath: string) => EdgeAgentConfig;
|
|
212
|
+
/** Build (NOT start) the local manager. Defaults to buildLocalSensingManager(config). */
|
|
213
|
+
buildLocalManager?: () => SensingManager | null;
|
|
214
|
+
/** Build (NOT start) the cloud manager. Defaults to buildCloudSensingManager(config). */
|
|
215
|
+
buildCloudManager?: () => SensingManager | null;
|
|
216
|
+
/** Log sink (tests capture it). Defaults to console.log. */
|
|
217
|
+
log?: (msg: string) => void;
|
|
218
|
+
/** Sleep between startup re-probes (tests inject a no-op). Defaults to setTimeout. */
|
|
219
|
+
sleep?: (ms: number) => Promise<void>;
|
|
220
|
+
/** Arm the re-probe timer. Defaults to setTimeout. */
|
|
221
|
+
setTimer?: (cb: () => void, ms: number) => AutoSenseTimerHandle;
|
|
222
|
+
/** Clear the re-probe timer. Defaults to clearTimeout. */
|
|
223
|
+
clearTimer?: (handle: AutoSenseTimerHandle) => void;
|
|
224
|
+
/** Fatal no-feeds handler. Defaults to process.exit(1). */
|
|
225
|
+
onNoFeeds?: () => void;
|
|
226
|
+
/** Register the shutdown handler. Defaults to SIGINT/SIGTERM listeners. */
|
|
227
|
+
registerShutdown?: (handler: () => void | Promise<void>) => void;
|
|
228
|
+
/** Block until shutdown (production never resolves; tests inject a resolved waiter). */
|
|
229
|
+
waitForShutdown?: () => Promise<void>;
|
|
230
|
+
/**
|
|
231
|
+
* Start the on-device VLM (Gemma) OTA watcher. Defaults to startGemmaModelOta.
|
|
232
|
+
* Returns a handle whose stop() runs on shutdown (or null when disabled). It
|
|
233
|
+
* starts only after LOCAL sensing activates, so first-time provisioning owns
|
|
234
|
+
* the initial model download and OTA cannot race it.
|
|
235
|
+
*/
|
|
236
|
+
startModelOta?: (config: EdgeAgentConfig) => GemmaModelOtaHandle | null;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* `auto-sense` entrypoint: resolve probe + manager inputs from config, then run
|
|
240
|
+
* the AutoSenseSupervisor (probe → start the chosen REAL manager → keep
|
|
241
|
+
* re-probing → auto-upgrade/auto-recover with NO restart). Blocks until
|
|
242
|
+
* SIGINT/SIGTERM (the supervisor's re-probe timer keeps the event loop alive).
|
|
243
|
+
*
|
|
244
|
+
* The probe target is the operator's configured `localSensing.litertLmBaseUrl`
|
|
245
|
+
* (default http://localhost:9379) so a non-standard serve host is honored, and
|
|
246
|
+
* the probe requires the configured `localSensing.model` to be present so we
|
|
247
|
+
* never pick local against a serve hosting the wrong model.
|
|
248
|
+
*
|
|
249
|
+
* Config is REQUIRED to build the sensing managers, so it's loaded up front and a
|
|
250
|
+
* genuine config error propagates to main() (prints + exits 1) — the same net
|
|
251
|
+
* result as before, where the chosen run mode re-loaded the config and reported it.
|
|
252
|
+
*
|
|
253
|
+
* The explicit `local-sense` / `cloud-sense` entrypoints stay non-switching; only
|
|
254
|
+
* `auto-sense` is supervised.
|
|
255
|
+
*/
|
|
256
|
+
export declare function runAutoSense(args: string[], deps?: AutoSenseDeps): Promise<void>;
|
|
257
|
+
/**
|
|
258
|
+
* Default transport using Node's built-in http/https. No third-party deps so it
|
|
259
|
+
* survives bundling into the self-contained connector. Mirrors the framing
|
|
260
|
+
* tolerance of LiteRtVlmProvider's poster: litert-lm serve emits non-strict HTTP
|
|
261
|
+
* framing (bare LF on the status line) that Node's strict parser rejects, and
|
|
262
|
+
* the connector talks to a LOCAL, trusted serve, so we tolerate it here too —
|
|
263
|
+
* otherwise a healthy serve would look "unreachable" and we'd wrongly pick cloud.
|
|
264
|
+
*/
|
|
265
|
+
export declare const defaultHttpGetter: HttpGetter;
|
|
266
|
+
//# sourceMappingURL=autoSense.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autoSense.d.ts","sourceRoot":"","sources":["../src/autoSense.ts"],"names":[],"mappings":"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"}
|