@camstack/addon-post-analysis 1.2.92 → 1.2.93
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/dist/{dist-VnaTfwAL.mjs → dist-3QRyOemL.mjs} +321 -3
- package/dist/{dist-BfrtqGyh.js → dist-DYoWeRRt.js} +338 -2
- package/dist/embedding-encoder/index.js +171 -4
- package/dist/embedding-encoder/index.mjs +171 -4
- package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-BIDGLXRs.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-C4-ljPpt.mjs} +3 -3
- package/dist/pipeline-analytics/{hostInit-CpWvyhen.mjs → hostInit-BoUejl7E.mjs} +3 -3
- package/dist/pipeline-analytics/index.js +32 -1
- package/dist/pipeline-analytics/index.mjs +32 -1
- package/dist/pipeline-analytics/remoteEntry.js +1 -1
- package/package.json +3 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region ../types/dist/event-category-
|
|
1
|
+
//#region ../types/dist/event-category-XfKNtfCc.mjs
|
|
2
2
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
3
3
|
EventCategory["SystemBoot"] = "system.boot";
|
|
4
4
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -37,6 +37,22 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
37
37
|
EventCategory["AddonInstalled"] = "addon.installed";
|
|
38
38
|
EventCategory["AddonUninstalled"] = "addon.uninstalled";
|
|
39
39
|
EventCategory["AddonCrashed"] = "addon.crashed";
|
|
40
|
+
/**
|
|
41
|
+
* A RUNNER the D6 crash circuit-breaker gave up on — terminal.
|
|
42
|
+
*
|
|
43
|
+
* `AddonCrashed` is the routine, self-healing fact ("it crashed; it is being
|
|
44
|
+
* respawned"); this is the one that never resolves itself. Emitted exactly
|
|
45
|
+
* once per trip, by `process-service.ts`, carrying the node, the runner, the
|
|
46
|
+
* addons it hosted and the crash count that tripped the breaker.
|
|
47
|
+
*
|
|
48
|
+
* It exists because a runner marked terminally `failed` used to be SILENT:
|
|
49
|
+
* on 2026-08-18 the `recorder` runner died of three unhandled ffmpeg spawn
|
|
50
|
+
* errors, the breaker stopped respawning it (correctly), `/health` kept
|
|
51
|
+
* returning 200, and fleet-wide recording was gone for 3h15 before the
|
|
52
|
+
* operator's phone told him. The Notification Center's system-event intake
|
|
53
|
+
* consumes this category and maps it to the `addon-crash-loop` kind.
|
|
54
|
+
*/
|
|
55
|
+
EventCategory["AddonRunnerFailed"] = "addon.runner-failed";
|
|
40
56
|
EventCategory["AddonError"] = "addon.error";
|
|
41
57
|
EventCategory["AddonPageReady"] = "addon.page-ready";
|
|
42
58
|
EventCategory["AddonWidgetReady"] = "addon.widget-ready";
|
|
@@ -14814,6 +14830,7 @@ var NcSystemEventKindSchema = _enum([
|
|
|
14814
14830
|
"node-offline",
|
|
14815
14831
|
"node-inference-unavailable",
|
|
14816
14832
|
"detection-blind",
|
|
14833
|
+
"addon-crash-loop",
|
|
14817
14834
|
"addon-update-available",
|
|
14818
14835
|
"server-update-available",
|
|
14819
14836
|
"alarm-triggered",
|
|
@@ -15939,6 +15956,10 @@ var NC_CONDITION_CATALOG = [
|
|
|
15939
15956
|
value: "detection-blind",
|
|
15940
15957
|
label: "Camera detecting nothing"
|
|
15941
15958
|
},
|
|
15959
|
+
{
|
|
15960
|
+
value: "addon-crash-loop",
|
|
15961
|
+
label: "Addon stopped after repeated crashes"
|
|
15962
|
+
},
|
|
15942
15963
|
{
|
|
15943
15964
|
value: "addon-update-available",
|
|
15944
15965
|
label: "Addon update available"
|
|
@@ -38537,7 +38558,7 @@ function systemEventFilterApplies(kind, filter) {
|
|
|
38537
38558
|
switch (filter) {
|
|
38538
38559
|
case "deviceIds": return kind.startsWith("device-") || kind.startsWith("stream-") || kind === "detection-blind" || kind === "alarm-triggered" || kind === "export-completed";
|
|
38539
38560
|
case "deviceTypes": return kind.startsWith("device-") || kind === "detection-blind";
|
|
38540
|
-
case "nodeIds": return kind.startsWith("node-") || kind === "addon-update-available" || kind === "addon-updated" || kind === "server-update-available" || kind === "server-updated";
|
|
38561
|
+
case "nodeIds": return kind.startsWith("node-") || kind === "addon-crash-loop" || kind === "addon-update-available" || kind === "addon-updated" || kind === "server-update-available" || kind === "server-updated";
|
|
38541
38562
|
case "packageNames": return kind.endsWith("update-available") || kind === "addon-updated" || kind === "server-updated";
|
|
38542
38563
|
}
|
|
38543
38564
|
}
|
|
@@ -38994,6 +39015,303 @@ function cosineSimilarity(a, b) {
|
|
|
38994
39015
|
function hfModelUrl(repo, path) {
|
|
38995
39016
|
return `https://huggingface.co/${repo}/resolve/main/${path}`;
|
|
38996
39017
|
}
|
|
39018
|
+
var MB = 1024 * 1024;
|
|
39019
|
+
var DEFAULT_POOL_MEMORY_POLICY = {
|
|
39020
|
+
sampleIntervalMs: 6e4,
|
|
39021
|
+
baselineSettleSamples: 5,
|
|
39022
|
+
baselineSampleCount: 3,
|
|
39023
|
+
restartMultiple: 4,
|
|
39024
|
+
floorBytes: 1024 * MB,
|
|
39025
|
+
ceilingBytes: 3072 * MB,
|
|
39026
|
+
cooldownMs: 30 * 6e4,
|
|
39027
|
+
maxRestartsPerWindow: 6,
|
|
39028
|
+
restartWindowMs: 1440 * 6e4
|
|
39029
|
+
};
|
|
39030
|
+
/**
|
|
39031
|
+
* Resolve the policy from env overrides (`CAMSTACK_POOL_MEM_*`). Garbage or
|
|
39032
|
+
* absent values keep the default — an operator typo must never disable the
|
|
39033
|
+
* bound or set it to zero.
|
|
39034
|
+
*/
|
|
39035
|
+
function resolvePoolMemoryPolicy(env) {
|
|
39036
|
+
const num = (key, fallback, min) => {
|
|
39037
|
+
const raw = env[key];
|
|
39038
|
+
if (raw === void 0) return fallback;
|
|
39039
|
+
const parsed = Number(raw);
|
|
39040
|
+
return Number.isFinite(parsed) && parsed >= min ? parsed : fallback;
|
|
39041
|
+
};
|
|
39042
|
+
const d = DEFAULT_POOL_MEMORY_POLICY;
|
|
39043
|
+
return {
|
|
39044
|
+
sampleIntervalMs: num("CAMSTACK_POOL_MEM_INTERVAL_MS", d.sampleIntervalMs, 5e3),
|
|
39045
|
+
baselineSettleSamples: d.baselineSettleSamples,
|
|
39046
|
+
baselineSampleCount: d.baselineSampleCount,
|
|
39047
|
+
restartMultiple: num("CAMSTACK_POOL_MEM_MULTIPLE", d.restartMultiple, 1.5),
|
|
39048
|
+
floorBytes: num("CAMSTACK_POOL_MEM_FLOOR_MB", d.floorBytes / MB, 128) * MB,
|
|
39049
|
+
ceilingBytes: num("CAMSTACK_POOL_MEM_CEILING_MB", d.ceilingBytes / MB, 256) * MB,
|
|
39050
|
+
cooldownMs: num("CAMSTACK_POOL_MEM_COOLDOWN_MS", d.cooldownMs, 6e4),
|
|
39051
|
+
maxRestartsPerWindow: num("CAMSTACK_POOL_MEM_MAX_RESTARTS", d.maxRestartsPerWindow, 1),
|
|
39052
|
+
restartWindowMs: num("CAMSTACK_POOL_MEM_RESTART_WINDOW_MS", d.restartWindowMs, 6e4)
|
|
39053
|
+
};
|
|
39054
|
+
}
|
|
39055
|
+
/** Parse the fields this watchdog needs out of `/proc/<pid>/status` text.
|
|
39056
|
+
* Returns null when VmRSS is missing (dead pid, kernel thread, bad read). */
|
|
39057
|
+
function parseProcStatus(text) {
|
|
39058
|
+
const kb = (label) => {
|
|
39059
|
+
const match = text.match(new RegExp(`^${label}:\\s+(\\d+)\\s*kB`, "m"));
|
|
39060
|
+
return match ? Number(match[1]) * 1024 : null;
|
|
39061
|
+
};
|
|
39062
|
+
const rssBytes = kb("VmRSS");
|
|
39063
|
+
if (rssBytes === null) return null;
|
|
39064
|
+
const threadsMatch = text.match(/^Threads:\s+(\d+)/m);
|
|
39065
|
+
return {
|
|
39066
|
+
rssBytes,
|
|
39067
|
+
vmBytes: kb("VmSize") ?? 0,
|
|
39068
|
+
hwmBytes: kb("VmHWM") ?? 0,
|
|
39069
|
+
swapBytes: kb("VmSwap") ?? 0,
|
|
39070
|
+
threads: threadsMatch ? Number(threadsMatch[1]) : 0
|
|
39071
|
+
};
|
|
39072
|
+
}
|
|
39073
|
+
function initialPoolMemoryState() {
|
|
39074
|
+
return {
|
|
39075
|
+
settleSeen: 0,
|
|
39076
|
+
baselineWindow: [],
|
|
39077
|
+
baselineBytes: null,
|
|
39078
|
+
restartsAt: [],
|
|
39079
|
+
lastRestartAt: null
|
|
39080
|
+
};
|
|
39081
|
+
}
|
|
39082
|
+
function median(values) {
|
|
39083
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
39084
|
+
return sorted[Math.floor(sorted.length / 2)];
|
|
39085
|
+
}
|
|
39086
|
+
function advanceBaseline(state, rssBytes, policy) {
|
|
39087
|
+
if (state.baselineBytes !== null) return state;
|
|
39088
|
+
if (state.settleSeen < policy.baselineSettleSamples) return {
|
|
39089
|
+
...state,
|
|
39090
|
+
settleSeen: state.settleSeen + 1
|
|
39091
|
+
};
|
|
39092
|
+
const window = [...state.baselineWindow, rssBytes];
|
|
39093
|
+
if (window.length < policy.baselineSampleCount) return {
|
|
39094
|
+
...state,
|
|
39095
|
+
baselineWindow: window
|
|
39096
|
+
};
|
|
39097
|
+
return {
|
|
39098
|
+
...state,
|
|
39099
|
+
baselineWindow: window,
|
|
39100
|
+
baselineBytes: median(window)
|
|
39101
|
+
};
|
|
39102
|
+
}
|
|
39103
|
+
/** The one place a pool's restart threshold is computed. */
|
|
39104
|
+
function poolMemoryThreshold(baselineBytes, policy) {
|
|
39105
|
+
if (baselineBytes === null) return policy.ceilingBytes;
|
|
39106
|
+
return Math.min(policy.ceilingBytes, Math.max(policy.floorBytes, policy.restartMultiple * baselineBytes));
|
|
39107
|
+
}
|
|
39108
|
+
function pruneRestarts(restartsAt, nowMs, policy) {
|
|
39109
|
+
return restartsAt.filter((t) => nowMs - t < policy.restartWindowMs);
|
|
39110
|
+
}
|
|
39111
|
+
/**
|
|
39112
|
+
* Evaluate one RSS sample. Pure: returns the successor state plus the verdict.
|
|
39113
|
+
* The caller performs (and logs) the restart, then commits it via
|
|
39114
|
+
* {@link commitWatchdogRestart}.
|
|
39115
|
+
*/
|
|
39116
|
+
function evaluatePoolMemory(state, rssBytes, nowMs, policy) {
|
|
39117
|
+
const next = advanceBaseline(state, rssBytes, policy);
|
|
39118
|
+
const thresholdBytes = poolMemoryThreshold(next.baselineBytes, policy);
|
|
39119
|
+
if (rssBytes <= thresholdBytes) return {
|
|
39120
|
+
state: next,
|
|
39121
|
+
action: next.baselineBytes === null ? "baseline-pending" : "ok",
|
|
39122
|
+
baselineBytes: next.baselineBytes,
|
|
39123
|
+
thresholdBytes
|
|
39124
|
+
};
|
|
39125
|
+
const inWindow = pruneRestarts(next.restartsAt, nowMs, policy);
|
|
39126
|
+
const pruned = {
|
|
39127
|
+
...next,
|
|
39128
|
+
restartsAt: inWindow
|
|
39129
|
+
};
|
|
39130
|
+
if (inWindow.length >= policy.maxRestartsPerWindow) return {
|
|
39131
|
+
state: pruned,
|
|
39132
|
+
action: "exhausted",
|
|
39133
|
+
baselineBytes: next.baselineBytes,
|
|
39134
|
+
thresholdBytes
|
|
39135
|
+
};
|
|
39136
|
+
if (pruned.lastRestartAt !== null && nowMs - pruned.lastRestartAt < policy.cooldownMs) return {
|
|
39137
|
+
state: pruned,
|
|
39138
|
+
action: "cooldown",
|
|
39139
|
+
baselineBytes: next.baselineBytes,
|
|
39140
|
+
thresholdBytes
|
|
39141
|
+
};
|
|
39142
|
+
return {
|
|
39143
|
+
state: pruned,
|
|
39144
|
+
action: "restart",
|
|
39145
|
+
baselineBytes: next.baselineBytes,
|
|
39146
|
+
thresholdBytes
|
|
39147
|
+
};
|
|
39148
|
+
}
|
|
39149
|
+
/** Record a performed watchdog restart: budget consumed, baseline reset —
|
|
39150
|
+
* the recreated pool is a NEW process and gets a fresh settle window. */
|
|
39151
|
+
function commitWatchdogRestart(state, nowMs) {
|
|
39152
|
+
return {
|
|
39153
|
+
...initialPoolMemoryState(),
|
|
39154
|
+
restartsAt: [...state.restartsAt, nowMs],
|
|
39155
|
+
lastRestartAt: nowMs
|
|
39156
|
+
};
|
|
39157
|
+
}
|
|
39158
|
+
/** Reset baseline tracking (pool process replaced OUTSIDE the watchdog —
|
|
39159
|
+
* kernel OOM kill + respawn, idle-reaper eviction, tuning respawn). The
|
|
39160
|
+
* restart budget is kept: it bounds the WATCHDOG, not the pool. */
|
|
39161
|
+
function resetPoolBaseline(state) {
|
|
39162
|
+
return {
|
|
39163
|
+
...initialPoolMemoryState(),
|
|
39164
|
+
restartsAt: state.restartsAt,
|
|
39165
|
+
lastRestartAt: state.lastRestartAt
|
|
39166
|
+
};
|
|
39167
|
+
}
|
|
39168
|
+
/**
|
|
39169
|
+
* Pick ONE pool to restart this sweep — the worst overage ratio. Restarting
|
|
39170
|
+
* several pools at once (e.g. after a model rollout grew every baseline)
|
|
39171
|
+
* would take detection down on every camera simultaneously; one per sweep
|
|
39172
|
+
* means the survivors keep serving while the worst offender reloads, and the
|
|
39173
|
+
* next sweep (one interval later) takes the next one.
|
|
39174
|
+
*/
|
|
39175
|
+
function pickRestartCandidate(candidates) {
|
|
39176
|
+
if (candidates.length === 0) return null;
|
|
39177
|
+
let worst = candidates[0];
|
|
39178
|
+
for (const c of candidates) if (c.rssBytes / c.thresholdBytes > worst.rssBytes / worst.thresholdBytes) worst = c;
|
|
39179
|
+
return worst.key;
|
|
39180
|
+
}
|
|
39181
|
+
var PoolMemoryWatchdog = class {
|
|
39182
|
+
pools = /* @__PURE__ */ new Map();
|
|
39183
|
+
timer = null;
|
|
39184
|
+
sweeping = false;
|
|
39185
|
+
stopped = false;
|
|
39186
|
+
opts;
|
|
39187
|
+
now;
|
|
39188
|
+
setTimer;
|
|
39189
|
+
clearTimer;
|
|
39190
|
+
constructor(opts) {
|
|
39191
|
+
this.opts = opts;
|
|
39192
|
+
this.now = opts.now ?? (() => Date.now());
|
|
39193
|
+
this.setTimer = opts.setTimer ?? ((fn, ms) => setTimeout(fn, ms));
|
|
39194
|
+
this.clearTimer = opts.clearTimer ?? ((t) => clearTimeout(t));
|
|
39195
|
+
}
|
|
39196
|
+
start() {
|
|
39197
|
+
if (this.timer || this.stopped) return;
|
|
39198
|
+
this.arm();
|
|
39199
|
+
}
|
|
39200
|
+
stop() {
|
|
39201
|
+
this.stopped = true;
|
|
39202
|
+
if (this.timer) {
|
|
39203
|
+
this.clearTimer(this.timer);
|
|
39204
|
+
this.timer = null;
|
|
39205
|
+
}
|
|
39206
|
+
}
|
|
39207
|
+
arm() {
|
|
39208
|
+
const timer = this.setTimer(() => {
|
|
39209
|
+
this.sweep().finally(() => {
|
|
39210
|
+
if (!this.stopped) this.arm();
|
|
39211
|
+
});
|
|
39212
|
+
}, this.opts.policy.sampleIntervalMs);
|
|
39213
|
+
if (typeof timer.unref === "function") timer.unref();
|
|
39214
|
+
this.timer = timer;
|
|
39215
|
+
}
|
|
39216
|
+
/** One sweep: sample → log every pool → restart at most one. Public so the
|
|
39217
|
+
* loop is testable without fake global timers. */
|
|
39218
|
+
async sweep() {
|
|
39219
|
+
if (this.sweeping) return;
|
|
39220
|
+
this.sweeping = true;
|
|
39221
|
+
try {
|
|
39222
|
+
await this.doSweep();
|
|
39223
|
+
} catch (err) {
|
|
39224
|
+
this.opts.log.warn("pool memory sweep failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
39225
|
+
} finally {
|
|
39226
|
+
this.sweeping = false;
|
|
39227
|
+
}
|
|
39228
|
+
}
|
|
39229
|
+
async doSweep() {
|
|
39230
|
+
const nowMs = this.now();
|
|
39231
|
+
const samples = await this.opts.sample();
|
|
39232
|
+
const candidates = [];
|
|
39233
|
+
const verdictByKey = /* @__PURE__ */ new Map();
|
|
39234
|
+
for (const t of samples) {
|
|
39235
|
+
const tracked = this.pools.get(t.key);
|
|
39236
|
+
let state = tracked?.state ?? initialPoolMemoryState();
|
|
39237
|
+
if (tracked && tracked.pids.length > 0 && !samePids(tracked.pids, t.pids)) {
|
|
39238
|
+
this.opts.log.warn("pool process changed outside the watchdog — re-baselining", { meta: {
|
|
39239
|
+
poolKey: t.key,
|
|
39240
|
+
previousPids: tracked.pids,
|
|
39241
|
+
pids: t.pids
|
|
39242
|
+
} });
|
|
39243
|
+
state = resetPoolBaseline(state);
|
|
39244
|
+
}
|
|
39245
|
+
const verdict = evaluatePoolMemory(state, t.rssBytes, nowMs, this.opts.policy);
|
|
39246
|
+
this.pools.set(t.key, {
|
|
39247
|
+
state: verdict.state,
|
|
39248
|
+
pids: t.pids
|
|
39249
|
+
});
|
|
39250
|
+
verdictByKey.set(t.key, verdict);
|
|
39251
|
+
this.opts.log.info("pool memory", { meta: {
|
|
39252
|
+
poolKey: t.key,
|
|
39253
|
+
pids: t.pids,
|
|
39254
|
+
rssMb: Math.round(t.rssBytes / MB),
|
|
39255
|
+
baselineMb: verdict.baselineBytes === null ? null : Math.round(verdict.baselineBytes / MB),
|
|
39256
|
+
thresholdMb: Math.round(verdict.thresholdBytes / MB),
|
|
39257
|
+
action: verdict.action,
|
|
39258
|
+
...t.meta
|
|
39259
|
+
} });
|
|
39260
|
+
if (verdict.action === "restart") candidates.push({
|
|
39261
|
+
key: t.key,
|
|
39262
|
+
rssBytes: t.rssBytes,
|
|
39263
|
+
thresholdBytes: verdict.thresholdBytes
|
|
39264
|
+
});
|
|
39265
|
+
else if (verdict.action === "cooldown") this.opts.log.warn("pool over memory threshold but inside restart cooldown", { meta: {
|
|
39266
|
+
poolKey: t.key,
|
|
39267
|
+
rssMb: Math.round(t.rssBytes / MB),
|
|
39268
|
+
thresholdMb: Math.round(verdict.thresholdBytes / MB),
|
|
39269
|
+
cooldownMs: this.opts.policy.cooldownMs
|
|
39270
|
+
} });
|
|
39271
|
+
else if (verdict.action === "exhausted") this.opts.log.error("pool memory watchdog gave up — restart budget exhausted, pool leaks faster than restarts can pay for; needs a heap profile (py-spy / tracemalloc)", { meta: {
|
|
39272
|
+
poolKey: t.key,
|
|
39273
|
+
rssMb: Math.round(t.rssBytes / MB),
|
|
39274
|
+
thresholdMb: Math.round(verdict.thresholdBytes / MB),
|
|
39275
|
+
maxRestartsPerWindow: this.opts.policy.maxRestartsPerWindow,
|
|
39276
|
+
restartWindowMs: this.opts.policy.restartWindowMs
|
|
39277
|
+
} });
|
|
39278
|
+
}
|
|
39279
|
+
for (const key of [...this.pools.keys()]) if (!samples.some((t) => t.key === key)) this.pools.delete(key);
|
|
39280
|
+
const pickedKey = pickRestartCandidate(candidates);
|
|
39281
|
+
if (pickedKey === null) return;
|
|
39282
|
+
const picked = candidates.find((c) => c.key === pickedKey);
|
|
39283
|
+
const verdict = verdictByKey.get(pickedKey);
|
|
39284
|
+
const tracked = this.pools.get(pickedKey);
|
|
39285
|
+
const restartsInWindow = tracked.state.restartsAt.length + 1;
|
|
39286
|
+
this.opts.log.warn("pool memory watchdog restarting pool — RSS over threshold", { meta: {
|
|
39287
|
+
poolKey: pickedKey,
|
|
39288
|
+
pids: tracked.pids,
|
|
39289
|
+
rssMb: Math.round(picked.rssBytes / MB),
|
|
39290
|
+
thresholdMb: Math.round(picked.thresholdBytes / MB),
|
|
39291
|
+
baselineMb: verdict.baselineBytes === null ? null : Math.round(verdict.baselineBytes / MB),
|
|
39292
|
+
restartsInWindow,
|
|
39293
|
+
deferredCandidates: candidates.filter((c) => c.key !== pickedKey).map((c) => c.key)
|
|
39294
|
+
} });
|
|
39295
|
+
try {
|
|
39296
|
+
await this.opts.restart(pickedKey);
|
|
39297
|
+
this.pools.set(pickedKey, {
|
|
39298
|
+
state: commitWatchdogRestart(tracked.state, this.now()),
|
|
39299
|
+
pids: []
|
|
39300
|
+
});
|
|
39301
|
+
} catch (err) {
|
|
39302
|
+
this.opts.log.error("pool memory watchdog restart failed", { meta: {
|
|
39303
|
+
poolKey: pickedKey,
|
|
39304
|
+
error: err instanceof Error ? err.message : String(err)
|
|
39305
|
+
} });
|
|
39306
|
+
}
|
|
39307
|
+
}
|
|
39308
|
+
};
|
|
39309
|
+
function samePids(a, b) {
|
|
39310
|
+
if (a.length !== b.length) return false;
|
|
39311
|
+
const sortedA = [...a].sort((x, y) => x - y);
|
|
39312
|
+
const sortedB = [...b].sort((x, y) => x - y);
|
|
39313
|
+
return sortedA.every((v, i) => v === sortedB[i]);
|
|
39314
|
+
}
|
|
38997
39315
|
/**
|
|
38998
39316
|
* Vector wire codec — base64 of little-endian Float32.
|
|
38999
39317
|
*
|
|
@@ -39023,4 +39341,4 @@ function vectorDimFromBase64(encoded) {
|
|
|
39023
39341
|
return Math.floor(Buffer.from(encoded, "base64").byteLength / 4);
|
|
39024
39342
|
}
|
|
39025
39343
|
//#endregion
|
|
39026
|
-
export {
|
|
39344
|
+
export { encodeVectorBase64 as $, RetrainStatusSchema as A, literal as At, TrackSourceSchema as B, NcSnoozeSchema as C, isDeviceScopedCap as Ct, OpsLogEntrySchema as D, array as Dt, NcTaxonomySchema as E, _enum as Et, SceneMonitorSchema as F, string as Ft, audioMetricsCapability as G, addonWidgetsSourceCapability as H, TIMELAPSE_DENSE_FLOOR_SEC as I, unknown as It, cosineSimilarity as J, audioModeOf as K, TimelapseRuleInputSchema as L, EventCategory as Lt, SCENE_DEFAULT_ANCHOR_THRESHOLD as M, object as Mt, SCENE_DEFAULT_UNCOVERED_POLICY as N, partialRecord as Nt, PoolMemoryWatchdog as O, boolean as Ot, SCENE_DIVERGED as P, record as Pt, embeddingEncoderCapability as Q, TimelapseRulePatchSchema as R, NcSnoozeInputSchema as S, hydrateSchema as St, NcSystemEventKindSchema as T, sleep as Tt, alarmPanelCapability as U, VISIT_MERGE_GAP_MS as V, assertTimelapseCadences as W, defineCustomActions as X, customAction as Y, deriveRecordingMode as Z, NcRuleInputSchema as _, zoneAnalyticsCapability as _t, DETECTION_PIPELINE_CAP_NAME as a, notificationRulesCapability as at, NcRuleTargetSchema as b, DeviceType as bt, EVENT_PAD_MS as c, plateGalleryCapability as ct, NC_ALARM_SYSTEM_EVENT_KINDS as d, resolvePoolMemoryPolicy as dt, faceGalleryCapability as et, NC_CONDITION_CATALOG as f, sceneMonitorCapability as ft, NcConditionDescriptorSchema as g, videoclipsCapability as gt, NC_TAXONOMY as h, vectorDimFromBase64 as ht, DETECTION_MACRO_CLASSES as i, kebabToCamel as it, SCENE_CONFIRM_DEFAULT_TIMEOUT_MS as j, number as jt, RECORDING_EXPORT_MAX_READ_BYTES as k, discriminatedUnion as kt, LabelAttributionSchema as l, readDeviceStateFrom as lt, NC_SNOOZE_MAX_MINUTES as m, systemEventFilterApplies as mt, DEFAULT_EVENT_COLOR as n, isDetectionMacroClass as nt, DeclaredDevices as o, parseProcStatus as ot, NC_DEFAULT_SNOOZE_MINUTES as p, subKindsOf as pt, buildEventKindDescriptor as q, DEFAULT_TIMELAPSE_PREVIEW_TEXT as r, isScheduleActive as rt, EVENT_KIND_BY_CAP as s, pipelineAnalyticsCapability as st, BaseDevice as t, hfModelUrl as tt, MACRO_LABELS as u, readTimelapseGeneratedAt as ut, NcRulePatchSchema as v, errMsg as vt, NcSnoozeSuppressedSchema as w, nodePin as wt, NcScheduleSchema as x, createEvent as xt, NcRuleSchema as y, BaseAddon as yt, TimelapseRuleSchema as z };
|