@camstack/addon-pipeline 1.2.118 → 1.2.120
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/{addon-utils-DJSN5h8c.js → addon-utils-MH-YN_oH.js} +1 -1
- package/dist/audio-analyzer/index.js +3 -3
- package/dist/audio-analyzer/index.mjs +2 -2
- package/dist/detection-pipeline/index.js +171 -167
- package/dist/detection-pipeline/index.mjs +169 -165
- package/dist/{dist-B763E61Y.mjs → dist-CmqBKO-v.mjs} +100 -4
- package/dist/{dist-BkO76jAp.js → dist-CvpyuIHg.js} +105 -3
- package/dist/{event-loop-stall-monitor-28f4R0JN.js → event-loop-stall-monitor-BOHxP7W6.js} +1 -1
- package/dist/{event-loop-stall-monitor-CYEvvp2Z.mjs → event-loop-stall-monitor-kh4gmJ-6.mjs} +1 -1
- package/dist/{lazy-sharp-BaPl5mRa.js → lazy-sharp-BzJLgOw9.js} +1 -1
- package/dist/motion-wasm/index.js +2 -2
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/pipeline-runner/index.js +12 -14
- package/dist/pipeline-runner/index.mjs +11 -13
- package/dist/{process-memory-CK3FnKyZ.mjs → process-memory-C2vefk7-.mjs} +1 -1
- package/dist/{process-memory-BCQJFZZg.js → process-memory-U6kkHBR7.js} +1 -1
- package/dist/recorder/index.js +2 -2
- package/dist/recorder/index.mjs +1 -1
- package/dist/segment-demux-js-CTgNaQTI.js +7310 -0
- package/dist/segment-demux-js-xjK1LW_t.mjs +7288 -0
- package/dist/session-decode/decode-worker-child.js +2 -2
- package/dist/session-decode/decode-worker-child.mjs +1 -1
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CxgvfkxP.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BdP-MWLF.mjs} +2 -2
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Cs8bmrWP.mjs +26 -0
- package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-BAMyzCWw.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-D-NFPV_g.mjs} +1 -1
- package/dist/stream-broker/demux-worker-child.js +46 -0
- package/dist/stream-broker/demux-worker-child.mjs +47 -0
- package/dist/stream-broker/{hostInit-CTkpxp3w.mjs → hostInit-zKdlTmuo.mjs} +2 -2
- package/dist/stream-broker/index.js +381 -7405
- package/dist/stream-broker/index.mjs +382 -7403
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/dist/{worker-protocol-D_2QaXYr.mjs → worker-protocol-CElzXfEW.mjs} +1 -1
- package/dist/{worker-protocol-owR7WMRP.js → worker-protocol-DGYGCx9K.js} +1 -1
- package/package.json +1 -1
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CL6Lgzdj.mjs +0 -26
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { n as __require } from "../chunk-DnnnRqeS.mjs";
|
|
2
|
-
import { $ as
|
|
3
|
-
import { a as ALL_PIPELINE_STEPS, c as getDefaultModelForFormatFromDef, d as resolveModelForFormat, f as landmarkPrecisionVerdict, l as getStep, n as startEventLoopStallMonitor, o as ALL_STEPS, r as localFrameRegistry, s as getDefaultModelForFormat, u as getStepDefinition } from "../event-loop-stall-monitor-
|
|
2
|
+
import { $ as pickClusterStepModels, D as YAMNET_TO_MACRO, Dt as hydrateSchema, Et as createEvent, Ft as sleep, G as evaluateZoneRules, Gt as string, I as defaultDeviceFor$1, Kt as union, Lt as array, Mt as parseJsonUnknown, St as BaseAddon, Ut as object, V as detectionPipelineCapability, W as enumerateInferenceDevices, Z as overlayClusterStepSettings, c as DEFAULT_CLUSTER_STEP_MODELS, dt as runtimeDevices$1, et as pickClusterStepSettings, gt as errMsg, jt as nodePin, l as DEFAULT_CLUSTER_STEP_SETTINGS, lt as resolvePoolMemoryPolicy, mt as supportedRuntimes$1, p as DEVICE_BACKEND_TO_FORMAT, q as inferModelProvider, qt as EventCategory, rt as pipelineExecutorCapability, st as resolveClusterStepModelId, t as APPLE_SA_TO_MACRO, x as PoolMemoryWatchdog } from "../dist-CmqBKO-v.mjs";
|
|
3
|
+
import { a as ALL_PIPELINE_STEPS, c as getDefaultModelForFormatFromDef, d as resolveModelForFormat, f as landmarkPrecisionVerdict, l as getStep, n as startEventLoopStallMonitor, o as ALL_STEPS, r as localFrameRegistry, s as getDefaultModelForFormat, u as getStepDefinition } from "../event-loop-stall-monitor-kh4gmJ-6.mjs";
|
|
4
4
|
import { t as getSharp } from "../lazy-sharp-6oymT_yf.mjs";
|
|
5
|
-
import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-
|
|
5
|
+
import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-C2vefk7-.mjs";
|
|
6
6
|
import { a as ensureModel, o as isModelDownloaded, r as deleteModelFromDisk } from "../addon-utils-CgBCF-mE.mjs";
|
|
7
7
|
import sharp from "sharp";
|
|
8
8
|
import { spawn } from "node:child_process";
|
|
@@ -249,6 +249,113 @@ function normalizeEngineNodeId(rawNodeId) {
|
|
|
249
249
|
return raw.includes("/") ? raw.split("/")[0] ?? "hub" : raw;
|
|
250
250
|
}
|
|
251
251
|
//#endregion
|
|
252
|
+
//#region src/shared/cluster-model-source.ts
|
|
253
|
+
/**
|
|
254
|
+
* Where the runner gets the ONE cluster model choice per cluster-scoped step.
|
|
255
|
+
*
|
|
256
|
+
* The sibling of `crop-convention-source.ts`, and deliberately built the same
|
|
257
|
+
* way, because it answers the neighbouring half of the same question: the crop
|
|
258
|
+
* convention decides WHAT pixels the encoder sees, this decides WHICH encoder
|
|
259
|
+
* sees them. Both are cluster-wide, both are read by the runner from the
|
|
260
|
+
* `pipeline-orchestrator` global settings over the hub-routed `addon-settings`
|
|
261
|
+
* cap, both pass NO `nodeId`.
|
|
262
|
+
*
|
|
263
|
+
* ## Deliberately NOT node-scoped, and not on the attach config
|
|
264
|
+
*
|
|
265
|
+
* With a `nodeId` the settings cap would project that node's scoped value and
|
|
266
|
+
* two nodes could embed into one index with two encoders — the original defect,
|
|
267
|
+
* relocated to the transport. And the attach config is the wrong carrier for
|
|
268
|
+
* the same reason it was wrong for the crop: eleven builders construct a
|
|
269
|
+
* `RunnerCameraConfig`, a cluster-wide constant threaded through eleven
|
|
270
|
+
* builders eventually reaches ten of them, and the cameras attached by the
|
|
271
|
+
* forgotten one quietly write a foreign feature space into the shared index.
|
|
272
|
+
*
|
|
273
|
+
* ## Why the failure mode keeps the last value
|
|
274
|
+
*
|
|
275
|
+
* A failed read must never revert to the registry default MID-PASS: that would
|
|
276
|
+
* silently change what every remaining vector of that dispatch means, which is
|
|
277
|
+
* the exact class of harm the scope exists to prevent. So a failure keeps the
|
|
278
|
+
* last known row and says so, loudly, once per failure.
|
|
279
|
+
*/
|
|
280
|
+
/**
|
|
281
|
+
* The addon whose GLOBAL settings own the cluster row. Same owner as the crop
|
|
282
|
+
* convention and the native-frame lease: hub-resident and neutral between the
|
|
283
|
+
* addons that read it (post-analysis pins it for a re-embed pass, the runner
|
|
284
|
+
* enforces it live — neither should own a value the other depends on).
|
|
285
|
+
*/
|
|
286
|
+
var CLUSTER_MODEL_OWNER_ADDON_ID = "pipeline-orchestrator";
|
|
287
|
+
/** TTL-cached read of the cluster model row. */
|
|
288
|
+
var ClusterModelSource = class {
|
|
289
|
+
models = DEFAULT_CLUSTER_STEP_MODELS;
|
|
290
|
+
settings = DEFAULT_CLUSTER_STEP_SETTINGS;
|
|
291
|
+
lastReadAtMs = Number.NEGATIVE_INFINITY;
|
|
292
|
+
inFlight = null;
|
|
293
|
+
logger;
|
|
294
|
+
now;
|
|
295
|
+
ttlMs;
|
|
296
|
+
constructor(options) {
|
|
297
|
+
this.logger = options.logger;
|
|
298
|
+
this.now = options.now ?? (() => Date.now());
|
|
299
|
+
this.ttlMs = options.ttlMs ?? 6e4;
|
|
300
|
+
}
|
|
301
|
+
/** The row in force right now — the registry defaults until a read lands. */
|
|
302
|
+
current() {
|
|
303
|
+
return this.models;
|
|
304
|
+
}
|
|
305
|
+
/** Cluster-scoped step knobs in force right now (admission floors, …). */
|
|
306
|
+
currentSettings() {
|
|
307
|
+
return this.settings;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Re-read if the cached row has expired. Concurrent callers share one
|
|
311
|
+
* in-flight read; a failure keeps the LAST KNOWN row.
|
|
312
|
+
*/
|
|
313
|
+
async refresh(api) {
|
|
314
|
+
if (api === void 0) return this.models;
|
|
315
|
+
if (this.now() - this.lastReadAtMs < this.ttlMs) return this.models;
|
|
316
|
+
this.inFlight ??= this.read(api).finally(() => {
|
|
317
|
+
this.inFlight = null;
|
|
318
|
+
});
|
|
319
|
+
await this.inFlight;
|
|
320
|
+
return this.models;
|
|
321
|
+
}
|
|
322
|
+
async read(api) {
|
|
323
|
+
try {
|
|
324
|
+
const view = await api.addonSettings.getGlobalSettings.query({ addonId: CLUSTER_MODEL_OWNER_ADDON_ID });
|
|
325
|
+
const next = pickClusterStepModels(view);
|
|
326
|
+
const nextSettings = pickClusterStepSettings(view);
|
|
327
|
+
this.lastReadAtMs = this.now();
|
|
328
|
+
const changed = Object.keys(next).filter((stepId) => next[stepId] !== this.models[stepId]);
|
|
329
|
+
const settingsChanged = Object.keys(nextSettings).some((stepId) => {
|
|
330
|
+
const from = this.settings[stepId] ?? {};
|
|
331
|
+
const to = nextSettings[stepId] ?? {};
|
|
332
|
+
return [...new Set([...Object.keys(from), ...Object.keys(to)])].some((key) => from[key] !== to[key]);
|
|
333
|
+
});
|
|
334
|
+
if (changed.length > 0) {
|
|
335
|
+
this.logger.info("cluster step model changed — vectors already stored by the previous model need a re-embed pass", { meta: { changed: changed.map((stepId) => ({
|
|
336
|
+
stepId,
|
|
337
|
+
from: this.models[stepId],
|
|
338
|
+
to: next[stepId]
|
|
339
|
+
})) } });
|
|
340
|
+
this.models = next;
|
|
341
|
+
}
|
|
342
|
+
if (settingsChanged) {
|
|
343
|
+
this.logger.info("cluster step settings changed", { meta: {
|
|
344
|
+
from: { ...this.settings },
|
|
345
|
+
to: { ...nextSettings }
|
|
346
|
+
} });
|
|
347
|
+
this.settings = nextSettings;
|
|
348
|
+
}
|
|
349
|
+
} catch (err) {
|
|
350
|
+
this.logger.warn("cluster step model read failed — keeping the last known row", { meta: {
|
|
351
|
+
owner: CLUSTER_MODEL_OWNER_ADDON_ID,
|
|
352
|
+
inUse: { ...this.models },
|
|
353
|
+
error: err instanceof Error ? err.message : String(err)
|
|
354
|
+
} });
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
//#endregion
|
|
252
359
|
//#region src/detection-pipeline/default-detection-model.ts
|
|
253
360
|
/** The object-detection step id — the only slot this resolver applies to. */
|
|
254
361
|
var OBJECT_DETECTION_STEP_ID = "object-detection";
|
|
@@ -2594,6 +2701,59 @@ var EngineProvisioner = class {
|
|
|
2594
2701
|
}
|
|
2595
2702
|
};
|
|
2596
2703
|
//#endregion
|
|
2704
|
+
//#region src/session-decode/frame-view-payload.ts
|
|
2705
|
+
var FRAME_VIEW_PAYLOAD_POLICY = "jpeg";
|
|
2706
|
+
//#endregion
|
|
2707
|
+
//#region src/detection-pipeline/root-frame-view.ts
|
|
2708
|
+
/** Resolve the pre-padding content requested from the decode worker for one root. */
|
|
2709
|
+
function resolveRootFrameViewSpec(model, source, crop, format = FRAME_VIEW_PAYLOAD_POLICY) {
|
|
2710
|
+
const sourceWidth = crop?.width ?? source.width;
|
|
2711
|
+
const sourceHeight = crop?.height ?? source.height;
|
|
2712
|
+
if (model.preprocessMode !== "letterbox") return {
|
|
2713
|
+
...crop ? { crop } : {},
|
|
2714
|
+
content: {
|
|
2715
|
+
width: model.inputSize.width,
|
|
2716
|
+
height: model.inputSize.height
|
|
2717
|
+
},
|
|
2718
|
+
fit: "stretch",
|
|
2719
|
+
format
|
|
2720
|
+
};
|
|
2721
|
+
const scale = Math.min(model.inputSize.width / sourceWidth, model.inputSize.height / sourceHeight);
|
|
2722
|
+
return {
|
|
2723
|
+
...crop ? { crop } : {},
|
|
2724
|
+
content: {
|
|
2725
|
+
width: Math.max(1, Math.round(sourceWidth * scale)),
|
|
2726
|
+
height: Math.max(1, Math.round(sourceHeight * scale))
|
|
2727
|
+
},
|
|
2728
|
+
fit: "contain",
|
|
2729
|
+
format
|
|
2730
|
+
};
|
|
2731
|
+
}
|
|
2732
|
+
//#endregion
|
|
2733
|
+
//#region src/detection-pipeline/frame-ref-view-provider.ts
|
|
2734
|
+
var LocalFrameRefMissError = class extends Error {
|
|
2735
|
+
reason;
|
|
2736
|
+
constructor(reason) {
|
|
2737
|
+
super(`local frameRef miss: ${reason}`);
|
|
2738
|
+
this.reason = reason;
|
|
2739
|
+
this.name = "LocalFrameRefMissError";
|
|
2740
|
+
}
|
|
2741
|
+
};
|
|
2742
|
+
/** Bind one registry lease for all heterogeneous roots of a pipeline invocation. */
|
|
2743
|
+
function createRootFrameViewResolver(registry, ref) {
|
|
2744
|
+
const lease = registry.acquire(ref);
|
|
2745
|
+
if (!lease) throw new LocalFrameRefMissError(ref.registryId === registry.registryId ? "stale-ref" : "foreign-registry");
|
|
2746
|
+
const resolve = async (root, crop) => {
|
|
2747
|
+
const model = root.definition.models.find((candidate) => candidate.id === root.modelId);
|
|
2748
|
+
if (!model) throw new Error(`frame view model not found: ${root.modelId}`);
|
|
2749
|
+
const spec = resolveRootFrameViewSpec(model, ref, crop);
|
|
2750
|
+
const result = await lease.resolve(spec);
|
|
2751
|
+
if (result.kind === "miss") throw new LocalFrameRefMissError(result.reason);
|
|
2752
|
+
return result;
|
|
2753
|
+
};
|
|
2754
|
+
return Object.assign(resolve, { release: (reason) => lease.release(reason) });
|
|
2755
|
+
}
|
|
2756
|
+
//#endregion
|
|
2597
2757
|
//#region src/detection-pipeline/pipeline/crop-utils.ts
|
|
2598
2758
|
/**
|
|
2599
2759
|
* Crop utilities — ROI extraction and bbox coordinate transforms.
|
|
@@ -5179,59 +5339,6 @@ function capitalize(s) {
|
|
|
5179
5339
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
5180
5340
|
}
|
|
5181
5341
|
//#endregion
|
|
5182
|
-
//#region src/session-decode/frame-view-payload.ts
|
|
5183
|
-
var FRAME_VIEW_PAYLOAD_POLICY = "jpeg";
|
|
5184
|
-
//#endregion
|
|
5185
|
-
//#region src/detection-pipeline/root-frame-view.ts
|
|
5186
|
-
/** Resolve the pre-padding content requested from the decode worker for one root. */
|
|
5187
|
-
function resolveRootFrameViewSpec(model, source, crop, format = FRAME_VIEW_PAYLOAD_POLICY) {
|
|
5188
|
-
const sourceWidth = crop?.width ?? source.width;
|
|
5189
|
-
const sourceHeight = crop?.height ?? source.height;
|
|
5190
|
-
if (model.preprocessMode !== "letterbox") return {
|
|
5191
|
-
...crop ? { crop } : {},
|
|
5192
|
-
content: {
|
|
5193
|
-
width: model.inputSize.width,
|
|
5194
|
-
height: model.inputSize.height
|
|
5195
|
-
},
|
|
5196
|
-
fit: "stretch",
|
|
5197
|
-
format
|
|
5198
|
-
};
|
|
5199
|
-
const scale = Math.min(model.inputSize.width / sourceWidth, model.inputSize.height / sourceHeight);
|
|
5200
|
-
return {
|
|
5201
|
-
...crop ? { crop } : {},
|
|
5202
|
-
content: {
|
|
5203
|
-
width: Math.max(1, Math.round(sourceWidth * scale)),
|
|
5204
|
-
height: Math.max(1, Math.round(sourceHeight * scale))
|
|
5205
|
-
},
|
|
5206
|
-
fit: "contain",
|
|
5207
|
-
format
|
|
5208
|
-
};
|
|
5209
|
-
}
|
|
5210
|
-
//#endregion
|
|
5211
|
-
//#region src/detection-pipeline/frame-ref-view-provider.ts
|
|
5212
|
-
var LocalFrameRefMissError = class extends Error {
|
|
5213
|
-
reason;
|
|
5214
|
-
constructor(reason) {
|
|
5215
|
-
super(`local frameRef miss: ${reason}`);
|
|
5216
|
-
this.reason = reason;
|
|
5217
|
-
this.name = "LocalFrameRefMissError";
|
|
5218
|
-
}
|
|
5219
|
-
};
|
|
5220
|
-
/** Bind one registry lease for all heterogeneous roots of a pipeline invocation. */
|
|
5221
|
-
function createRootFrameViewResolver(registry, ref) {
|
|
5222
|
-
const lease = registry.acquire(ref);
|
|
5223
|
-
if (!lease) throw new LocalFrameRefMissError(ref.registryId === registry.registryId ? "stale-ref" : "foreign-registry");
|
|
5224
|
-
const resolve = async (root, crop) => {
|
|
5225
|
-
const model = root.definition.models.find((candidate) => candidate.id === root.modelId);
|
|
5226
|
-
if (!model) throw new Error(`frame view model not found: ${root.modelId}`);
|
|
5227
|
-
const spec = resolveRootFrameViewSpec(model, ref, crop);
|
|
5228
|
-
const result = await lease.resolve(spec);
|
|
5229
|
-
if (result.kind === "miss") throw new LocalFrameRefMissError(result.reason);
|
|
5230
|
-
return result;
|
|
5231
|
-
};
|
|
5232
|
-
return Object.assign(resolve, { release: (reason) => lease.release(reason) });
|
|
5233
|
-
}
|
|
5234
|
-
//#endregion
|
|
5235
5342
|
//#region src/detection-pipeline/pipeline/native-crop-compose.ts
|
|
5236
5343
|
/** Clamp `v` into `[lo, hi]`. */
|
|
5237
5344
|
function clamp(v, lo, hi) {
|
|
@@ -5360,7 +5467,10 @@ function mergeCustomModels(staticModels, customModels) {
|
|
|
5360
5467
|
for (const m of customModels) {
|
|
5361
5468
|
if (seen.has(m.id)) continue;
|
|
5362
5469
|
seen.add(m.id);
|
|
5363
|
-
merged.push(
|
|
5470
|
+
merged.push({
|
|
5471
|
+
...m,
|
|
5472
|
+
provider: inferModelProvider(m)
|
|
5473
|
+
});
|
|
5364
5474
|
}
|
|
5365
5475
|
return merged;
|
|
5366
5476
|
}
|
|
@@ -5659,113 +5769,6 @@ function applyZoneRuleGate(result, zones, rules) {
|
|
|
5659
5769
|
};
|
|
5660
5770
|
}
|
|
5661
5771
|
//#endregion
|
|
5662
|
-
//#region src/shared/cluster-model-source.ts
|
|
5663
|
-
/**
|
|
5664
|
-
* Where the runner gets the ONE cluster model choice per cluster-scoped step.
|
|
5665
|
-
*
|
|
5666
|
-
* The sibling of `crop-convention-source.ts`, and deliberately built the same
|
|
5667
|
-
* way, because it answers the neighbouring half of the same question: the crop
|
|
5668
|
-
* convention decides WHAT pixels the encoder sees, this decides WHICH encoder
|
|
5669
|
-
* sees them. Both are cluster-wide, both are read by the runner from the
|
|
5670
|
-
* `pipeline-orchestrator` global settings over the hub-routed `addon-settings`
|
|
5671
|
-
* cap, both pass NO `nodeId`.
|
|
5672
|
-
*
|
|
5673
|
-
* ## Deliberately NOT node-scoped, and not on the attach config
|
|
5674
|
-
*
|
|
5675
|
-
* With a `nodeId` the settings cap would project that node's scoped value and
|
|
5676
|
-
* two nodes could embed into one index with two encoders — the original defect,
|
|
5677
|
-
* relocated to the transport. And the attach config is the wrong carrier for
|
|
5678
|
-
* the same reason it was wrong for the crop: eleven builders construct a
|
|
5679
|
-
* `RunnerCameraConfig`, a cluster-wide constant threaded through eleven
|
|
5680
|
-
* builders eventually reaches ten of them, and the cameras attached by the
|
|
5681
|
-
* forgotten one quietly write a foreign feature space into the shared index.
|
|
5682
|
-
*
|
|
5683
|
-
* ## Why the failure mode keeps the last value
|
|
5684
|
-
*
|
|
5685
|
-
* A failed read must never revert to the registry default MID-PASS: that would
|
|
5686
|
-
* silently change what every remaining vector of that dispatch means, which is
|
|
5687
|
-
* the exact class of harm the scope exists to prevent. So a failure keeps the
|
|
5688
|
-
* last known row and says so, loudly, once per failure.
|
|
5689
|
-
*/
|
|
5690
|
-
/**
|
|
5691
|
-
* The addon whose GLOBAL settings own the cluster row. Same owner as the crop
|
|
5692
|
-
* convention and the native-frame lease: hub-resident and neutral between the
|
|
5693
|
-
* addons that read it (post-analysis pins it for a re-embed pass, the runner
|
|
5694
|
-
* enforces it live — neither should own a value the other depends on).
|
|
5695
|
-
*/
|
|
5696
|
-
var CLUSTER_MODEL_OWNER_ADDON_ID = "pipeline-orchestrator";
|
|
5697
|
-
/** TTL-cached read of the cluster model row. */
|
|
5698
|
-
var ClusterModelSource = class {
|
|
5699
|
-
models = DEFAULT_CLUSTER_STEP_MODELS;
|
|
5700
|
-
settings = DEFAULT_CLUSTER_STEP_SETTINGS;
|
|
5701
|
-
lastReadAtMs = Number.NEGATIVE_INFINITY;
|
|
5702
|
-
inFlight = null;
|
|
5703
|
-
logger;
|
|
5704
|
-
now;
|
|
5705
|
-
ttlMs;
|
|
5706
|
-
constructor(options) {
|
|
5707
|
-
this.logger = options.logger;
|
|
5708
|
-
this.now = options.now ?? (() => Date.now());
|
|
5709
|
-
this.ttlMs = options.ttlMs ?? 6e4;
|
|
5710
|
-
}
|
|
5711
|
-
/** The row in force right now — the registry defaults until a read lands. */
|
|
5712
|
-
current() {
|
|
5713
|
-
return this.models;
|
|
5714
|
-
}
|
|
5715
|
-
/** Cluster-scoped step knobs in force right now (admission floors, …). */
|
|
5716
|
-
currentSettings() {
|
|
5717
|
-
return this.settings;
|
|
5718
|
-
}
|
|
5719
|
-
/**
|
|
5720
|
-
* Re-read if the cached row has expired. Concurrent callers share one
|
|
5721
|
-
* in-flight read; a failure keeps the LAST KNOWN row.
|
|
5722
|
-
*/
|
|
5723
|
-
async refresh(api) {
|
|
5724
|
-
if (api === void 0) return this.models;
|
|
5725
|
-
if (this.now() - this.lastReadAtMs < this.ttlMs) return this.models;
|
|
5726
|
-
this.inFlight ??= this.read(api).finally(() => {
|
|
5727
|
-
this.inFlight = null;
|
|
5728
|
-
});
|
|
5729
|
-
await this.inFlight;
|
|
5730
|
-
return this.models;
|
|
5731
|
-
}
|
|
5732
|
-
async read(api) {
|
|
5733
|
-
try {
|
|
5734
|
-
const view = await api.addonSettings.getGlobalSettings.query({ addonId: CLUSTER_MODEL_OWNER_ADDON_ID });
|
|
5735
|
-
const next = pickClusterStepModels(view);
|
|
5736
|
-
const nextSettings = pickClusterStepSettings(view);
|
|
5737
|
-
this.lastReadAtMs = this.now();
|
|
5738
|
-
const changed = Object.keys(next).filter((stepId) => next[stepId] !== this.models[stepId]);
|
|
5739
|
-
const settingsChanged = Object.keys(nextSettings).some((stepId) => {
|
|
5740
|
-
const from = this.settings[stepId] ?? {};
|
|
5741
|
-
const to = nextSettings[stepId] ?? {};
|
|
5742
|
-
return [...new Set([...Object.keys(from), ...Object.keys(to)])].some((key) => from[key] !== to[key]);
|
|
5743
|
-
});
|
|
5744
|
-
if (changed.length > 0) {
|
|
5745
|
-
this.logger.info("cluster step model changed — vectors already stored by the previous model need a re-embed pass", { meta: { changed: changed.map((stepId) => ({
|
|
5746
|
-
stepId,
|
|
5747
|
-
from: this.models[stepId],
|
|
5748
|
-
to: next[stepId]
|
|
5749
|
-
})) } });
|
|
5750
|
-
this.models = next;
|
|
5751
|
-
}
|
|
5752
|
-
if (settingsChanged) {
|
|
5753
|
-
this.logger.info("cluster step settings changed", { meta: {
|
|
5754
|
-
from: { ...this.settings },
|
|
5755
|
-
to: { ...nextSettings }
|
|
5756
|
-
} });
|
|
5757
|
-
this.settings = nextSettings;
|
|
5758
|
-
}
|
|
5759
|
-
} catch (err) {
|
|
5760
|
-
this.logger.warn("cluster step model read failed — keeping the last known row", { meta: {
|
|
5761
|
-
owner: CLUSTER_MODEL_OWNER_ADDON_ID,
|
|
5762
|
-
inUse: { ...this.models },
|
|
5763
|
-
error: err instanceof Error ? err.message : String(err)
|
|
5764
|
-
} });
|
|
5765
|
-
}
|
|
5766
|
-
}
|
|
5767
|
-
};
|
|
5768
|
-
//#endregion
|
|
5769
5772
|
//#region src/detection-pipeline/provider.ts
|
|
5770
5773
|
/**
|
|
5771
5774
|
* DetectionPipelineProvider — implements IPipelineExecutorProvider.
|
|
@@ -8756,7 +8759,8 @@ function buildSchemaSlots(formats, modelsDir, customByStep) {
|
|
|
8756
8759
|
sizeMB: entry.sizeMB
|
|
8757
8760
|
}])),
|
|
8758
8761
|
...m.group ? { group: m.group } : {},
|
|
8759
|
-
...m.legacy !== void 0 ? { legacy: m.legacy } : {}
|
|
8762
|
+
...m.legacy !== void 0 ? { legacy: m.legacy } : {},
|
|
8763
|
+
provider: m.provider ?? "camstack"
|
|
8760
8764
|
})),
|
|
8761
8765
|
defaultModelId: step.defaultModelId,
|
|
8762
8766
|
...step.defaultModelIdByFormat ? { defaultModelIdByFormat: { ...step.defaultModelIdByFormat } } : {},
|
|
@@ -9150,6 +9150,25 @@ var ModelVariantGroupSchema = object({
|
|
|
9150
9150
|
*/
|
|
9151
9151
|
resolution: number().int().positive().optional()
|
|
9152
9152
|
});
|
|
9153
|
+
var ModelProviderIdSchema = _enum([
|
|
9154
|
+
"camstack",
|
|
9155
|
+
"frigate",
|
|
9156
|
+
"scrypted",
|
|
9157
|
+
"custom"
|
|
9158
|
+
]);
|
|
9159
|
+
/**
|
|
9160
|
+
* Resolve a catalog entry's picker provider. An explicit stamp always wins;
|
|
9161
|
+
* otherwise Frigate/Scrypted are recognised from id prefix or description.
|
|
9162
|
+
* Unstamped BYO registry rows fall through to `custom`. Family `yolov9` is
|
|
9163
|
+
* NOT a Scrypted signal — CamStack ships that family too.
|
|
9164
|
+
*/
|
|
9165
|
+
function inferModelProvider(entry) {
|
|
9166
|
+
if (entry.provider !== void 0) return entry.provider;
|
|
9167
|
+
const haystack = `${entry.id} ${entry.description ?? ""}`;
|
|
9168
|
+
if (/scrypted/i.test(haystack)) return "scrypted";
|
|
9169
|
+
if (/frigate/i.test(haystack)) return "frigate";
|
|
9170
|
+
return "custom";
|
|
9171
|
+
}
|
|
9153
9172
|
var ModelCatalogEntrySchema = object({
|
|
9154
9173
|
id: string(),
|
|
9155
9174
|
name: string(),
|
|
@@ -9247,6 +9266,12 @@ var ModelCatalogEntrySchema = object({
|
|
|
9247
9266
|
*/
|
|
9248
9267
|
group: ModelVariantGroupSchema.optional(),
|
|
9249
9268
|
/**
|
|
9269
|
+
* Catalog source for the pipeline stepper's provider-first picker. Absent on
|
|
9270
|
+
* built-in CamStack entries (treated as `camstack`) and on registry rows
|
|
9271
|
+
* persisted before this field existed (`inferModelProvider` fills those).
|
|
9272
|
+
*/
|
|
9273
|
+
provider: ModelProviderIdSchema.optional(),
|
|
9274
|
+
/**
|
|
9250
9275
|
* Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
|
|
9251
9276
|
* applies (Frigate / COCO public catalog). Set on a custom model whose raw
|
|
9252
9277
|
* labels already ARE the CamStack macros (Scrypted identity map).
|
|
@@ -18637,6 +18662,46 @@ var RecentTracksPageSchema = object({
|
|
|
18637
18662
|
/** Cursor for the next page, or null when this page is the last. */
|
|
18638
18663
|
nextCursor: string().nullable()
|
|
18639
18664
|
});
|
|
18665
|
+
var LIST_GROUPS_DEFAULT_LIMIT = 40;
|
|
18666
|
+
var LIST_GROUPS_MAX_LIMIT = 100;
|
|
18667
|
+
var AnalyticsGroupRecordSchema = object({
|
|
18668
|
+
id: string(),
|
|
18669
|
+
deviceId: number().int(),
|
|
18670
|
+
openedAt: number().int(),
|
|
18671
|
+
closedAt: number().int(),
|
|
18672
|
+
timestamp: number().int(),
|
|
18673
|
+
memberCount: number().int(),
|
|
18674
|
+
memberTrackIds: array(string()).readonly(),
|
|
18675
|
+
className: string(),
|
|
18676
|
+
classes: array(string()).readonly(),
|
|
18677
|
+
/** Relative event-media path, or null when the group has no picture yet. */
|
|
18678
|
+
mediaUrl: string().nullable(),
|
|
18679
|
+
singleton: boolean()
|
|
18680
|
+
});
|
|
18681
|
+
var AnalyticsGroupMemberSchema = object({
|
|
18682
|
+
trackId: string(),
|
|
18683
|
+
deviceId: number().int(),
|
|
18684
|
+
className: string(),
|
|
18685
|
+
firstSeen: number().int(),
|
|
18686
|
+
lastSeen: number().int(),
|
|
18687
|
+
mediaUrl: string().nullable()
|
|
18688
|
+
});
|
|
18689
|
+
var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
|
|
18690
|
+
var ListGroupsQueryInput = object({
|
|
18691
|
+
/** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
|
|
18692
|
+
deviceIds: array(number()),
|
|
18693
|
+
/** Window lower bound on `closedAt` (inclusive). */
|
|
18694
|
+
since: number().optional(),
|
|
18695
|
+
/** Window upper bound on `openedAt` (inclusive). */
|
|
18696
|
+
until: number().optional(),
|
|
18697
|
+
limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
|
|
18698
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
18699
|
+
cursor: string().optional()
|
|
18700
|
+
});
|
|
18701
|
+
var ListGroupsPageSchema = object({
|
|
18702
|
+
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
18703
|
+
nextCursor: string().nullable()
|
|
18704
|
+
});
|
|
18640
18705
|
var KeyEventQueryInput = object({
|
|
18641
18706
|
deviceId: number(),
|
|
18642
18707
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -18860,7 +18925,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
18860
18925
|
* stationary registry). Default false: the timeline lists passages,
|
|
18861
18926
|
* not parking records (operator decision, 2026-08-15). */
|
|
18862
18927
|
includeStationary: boolean().optional()
|
|
18863
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(
|
|
18928
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
|
|
18929
|
+
deviceId: number(),
|
|
18930
|
+
groupId: string().min(1)
|
|
18931
|
+
}), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
18864
18932
|
kind: "mutation",
|
|
18865
18933
|
auth: "admin"
|
|
18866
18934
|
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
|
|
@@ -19170,7 +19238,8 @@ var PipelineModelOptionSchema = object({
|
|
|
19170
19238
|
sizeMB: number()
|
|
19171
19239
|
})),
|
|
19172
19240
|
group: ModelVariantGroupSchema.optional(),
|
|
19173
|
-
legacy: boolean().optional()
|
|
19241
|
+
legacy: boolean().optional(),
|
|
19242
|
+
provider: ModelProviderIdSchema.optional()
|
|
19174
19243
|
});
|
|
19175
19244
|
var ConfigFieldBridge = custom();
|
|
19176
19245
|
var PipelineAddonSchemaSchema = object({
|
|
@@ -26210,7 +26279,12 @@ var PlateInfoSchema = object({
|
|
|
26210
26279
|
plateBbox: BoundingBoxSchema.optional(),
|
|
26211
26280
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
26212
26281
|
keyFrameMediaKey: string().optional(),
|
|
26213
|
-
base64: string().optional()
|
|
26282
|
+
base64: string().optional(),
|
|
26283
|
+
/**
|
|
26284
|
+
* Same crop as a data-plane URL. `getPlateByTrack` returns this and
|
|
26285
|
+
* never inlines JPEG; `listPlates` still inlines for the admin-ui.
|
|
26286
|
+
*/
|
|
26287
|
+
cropUrl: string().optional()
|
|
26214
26288
|
});
|
|
26215
26289
|
var MediaFileLiteSchema = object({
|
|
26216
26290
|
key: string(),
|
|
@@ -31852,6 +31926,12 @@ Object.freeze({
|
|
|
31852
31926
|
addonId: null,
|
|
31853
31927
|
access: "view"
|
|
31854
31928
|
},
|
|
31929
|
+
"pipelineAnalytics.getGroup": {
|
|
31930
|
+
capName: "pipeline-analytics",
|
|
31931
|
+
capScope: "device",
|
|
31932
|
+
addonId: null,
|
|
31933
|
+
access: "view"
|
|
31934
|
+
},
|
|
31855
31935
|
"pipelineAnalytics.getKeyEvents": {
|
|
31856
31936
|
capName: "pipeline-analytics",
|
|
31857
31937
|
capScope: "device",
|
|
@@ -31936,6 +32016,12 @@ Object.freeze({
|
|
|
31936
32016
|
addonId: null,
|
|
31937
32017
|
access: "view"
|
|
31938
32018
|
},
|
|
32019
|
+
"pipelineAnalytics.listGroups": {
|
|
32020
|
+
capName: "pipeline-analytics",
|
|
32021
|
+
capScope: "device",
|
|
32022
|
+
addonId: null,
|
|
32023
|
+
access: "view"
|
|
32024
|
+
},
|
|
31939
32025
|
"pipelineAnalytics.listOpsLog": {
|
|
31940
32026
|
capName: "pipeline-analytics",
|
|
31941
32027
|
capScope: "device",
|
|
@@ -35355,6 +35441,11 @@ Object.freeze({
|
|
|
35355
35441
|
form: "single",
|
|
35356
35442
|
optional: false
|
|
35357
35443
|
}],
|
|
35444
|
+
"pipelineAnalytics.getGroup": [{
|
|
35445
|
+
name: "deviceId",
|
|
35446
|
+
form: "single",
|
|
35447
|
+
optional: false
|
|
35448
|
+
}],
|
|
35358
35449
|
"pipelineAnalytics.getKeyEvents": [{
|
|
35359
35450
|
name: "deviceId",
|
|
35360
35451
|
form: "single",
|
|
@@ -35410,6 +35501,11 @@ Object.freeze({
|
|
|
35410
35501
|
form: "array",
|
|
35411
35502
|
optional: false
|
|
35412
35503
|
}],
|
|
35504
|
+
"pipelineAnalytics.listGroups": [{
|
|
35505
|
+
name: "deviceIds",
|
|
35506
|
+
form: "array",
|
|
35507
|
+
optional: false
|
|
35508
|
+
}],
|
|
35413
35509
|
"pipelineAnalytics.listOpsLog": [{
|
|
35414
35510
|
name: "deviceId",
|
|
35415
35511
|
form: "single",
|
|
@@ -37702,4 +37798,4 @@ function enumerateInferenceDevices(hw) {
|
|
|
37702
37798
|
return out;
|
|
37703
37799
|
}
|
|
37704
37800
|
//#endregion
|
|
37705
|
-
export {
|
|
37801
|
+
export { pickClusterStepModels as $, audioAnalyzerCapability as A, makeSourceBrokerId as At, deriveRecordingMode as B, lazy as Bt, RATE_CONTROL_TIGHT as C, CAM_PROFILE_ORDER as Ct, YAMNET_TO_MACRO as D, hydrateSchema as Dt, RingBuffer as E, createEvent as Et, customAction as F, sleep as Ft, evaluateZoneRules as G, string as Gt, egressTranscodeSharingKey as H, number as Ht, defaultDeviceFor as I, _enum as It, mapAudioLabelToMacro as J, hfModelUrl as K, union as Kt, defineCustomActions as L, array as Lt, batteryCapability as M, parseJsonUnknown as Mt, cameraStreamsCapability as N, parseProfileBrokerId as Nt, addonWidgetsSourceCapability as O, isEvent as Ot, createHwAccelCache as P, selectAssignedProfileSlots as Pt, parseProcStatus as Q, deriveBatteryPresence as R, boolean as Rt, RATE_CONTROL_RELAXED as S, BaseAddon as St, RecordingConfigSchema as T, DeviceType as Tt, egressTransportFromRequest as U, object as Ut, detectionPipelineCapability as V, literal as Vt, enumerateInferenceDevices as W, record as Wt, motionDetectionCapability as X, maskUrlCredentials as Y, overlayClusterStepSettings as Z, HF_BASE_URL as _, AUDIO_PRESETS as _t, COCO_80_LABELS as a, recordingCapability as at, OpsLogEntrySchema as b, invocationFromEncodeProfile as bt, DEFAULT_CLUSTER_STEP_MODELS as c, resolveEgressDecodeHwAccel as ct, DEFAULT_EVENTS_BAND_BUFFER_SEC as d, runtimeDevices as dt, pickClusterStepSettings as et, DEFAULT_NATIVE_LEASE_SETTINGS as f, storageEvictableCapability as ft, ExportRecordSchema as g, errMsg as gt, EncodeProfileSchema as h, webrtcSessionCapability as ht, BatteryStatusSchema as i, pipelineRunnerCapability as it, audioKindId as j, nodePin as jt, audioAnalysisCapability as k, makeProfileBrokerId as kt, DEFAULT_CLUSTER_STEP_SETTINGS as l, resolvePoolMemoryPolicy as lt, EVENT_PAD_MS as m, supportedRuntimes as mt, AUDIO_BACKEND_CHOICES as n, pickNativeLeaseOverride as nt, COCO_TO_MACRO as o, recordingExportCapability as ot, DEVICE_BACKEND_TO_FORMAT as p, streamBrokerCapability as pt, inferModelProvider as q, EventCategory as qt, AUDIO_MACRO_LABELS as r, pipelineExecutorCapability as rt, DEFAULT_AUDIO_ANALYZER_CONFIG as s, resolveClusterStepModelId as st, APPLE_SA_TO_MACRO as t, pickDetailCropConvention as tt, DEFAULT_DETAIL_CROP_CONVENTION as u, resolveRecordingProfiles as ut, NativeLeaseAdmissionSchema as v, Fmp4BoxSplitter as vt, RECORDING_EXPORT_MAX_READ_BYTES as w, DeviceFeature as wt, PoolMemoryWatchdog as x, isSoftwareDecode as xt, NativeLeaseSettingsSchema as y, buildFfmpegArgs as yt, deriveDetailCropRect as z, discriminatedUnion as zt };
|