@camstack/addon-pipeline 1.2.107 → 1.2.118

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 (35) hide show
  1. package/dist/{addon-utils-A2S9D7pu.mjs → addon-utils-CgBCF-mE.mjs} +50 -14
  2. package/dist/{addon-utils-Vv2dCqA2.js → addon-utils-DJSN5h8c.js} +51 -15
  3. package/dist/audio-analyzer/index.js +3 -3
  4. package/dist/audio-analyzer/index.mjs +3 -3
  5. package/dist/detection-pipeline/index.js +170 -31
  6. package/dist/detection-pipeline/index.mjs +169 -30
  7. package/dist/{dist-CkXAzTZ2.mjs → dist-B763E61Y.mjs} +152 -26
  8. package/dist/{dist-L-1LMGQs.js → dist-BkO76jAp.js} +152 -26
  9. package/dist/{event-loop-stall-monitor-DwAho7HD.js → event-loop-stall-monitor-28f4R0JN.js} +234 -1
  10. package/dist/{event-loop-stall-monitor-fHkfgmlw.mjs → event-loop-stall-monitor-CYEvvp2Z.mjs} +223 -2
  11. package/dist/{lazy-sharp-DfbyQxET.js → lazy-sharp-BaPl5mRa.js} +1 -1
  12. package/dist/motion-wasm/index.js +2 -2
  13. package/dist/motion-wasm/index.mjs +1 -1
  14. package/dist/pipeline-runner/index.js +915 -107
  15. package/dist/pipeline-runner/index.mjs +914 -106
  16. package/dist/{process-memory-CgrbLo3l.js → process-memory-BCQJFZZg.js} +1 -1
  17. package/dist/{process-memory-DlSOzuHP.mjs → process-memory-CK3FnKyZ.mjs} +1 -1
  18. package/dist/recorder/index.js +446 -77
  19. package/dist/recorder/index.mjs +446 -77
  20. package/dist/session-decode/decode-worker-child.js +62 -34
  21. package/dist/session-decode/decode-worker-child.mjs +61 -33
  22. package/dist/stream-broker/_stub.js +2 -2
  23. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BeL4_jgH.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CxgvfkxP.mjs} +3 -3
  24. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CL6Lgzdj.mjs +26 -0
  25. package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CmHtm5CX.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-BAMyzCWw.mjs} +1 -1
  26. package/dist/stream-broker/{hostInit-BK9nzKAG.mjs → hostInit-CTkpxp3w.mjs} +3 -3
  27. package/dist/stream-broker/index.js +279 -198
  28. package/dist/stream-broker/index.mjs +279 -198
  29. package/dist/stream-broker/remoteEntry.js +1 -1
  30. package/dist/{worker-protocol-bEipQT9l.mjs → worker-protocol-D_2QaXYr.mjs} +6 -3
  31. package/dist/{worker-protocol-GGnzfWu3.js → worker-protocol-owR7WMRP.js} +6 -3
  32. package/package.json +1 -1
  33. package/python/inference_pool.py +4 -1
  34. package/python/test_inference_pool_preprocess.py +87 -16
  35. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DjndFc5V.mjs +0 -26
@@ -9058,6 +9058,15 @@ var LabelDefinitionSchema = object({
9058
9058
  description: string().optional(),
9059
9059
  icon: string().optional()
9060
9060
  });
9061
+ var ClassMapDefinitionSchema = object({
9062
+ mapping: record(string(), _enum([
9063
+ "person",
9064
+ "vehicle",
9065
+ "animal",
9066
+ "package"
9067
+ ])),
9068
+ preserveOriginal: boolean()
9069
+ });
9061
9070
  var MODEL_FORMATS = [
9062
9071
  "onnx",
9063
9072
  "coreml",
@@ -9236,7 +9245,13 @@ var ModelCatalogEntrySchema = object({
9236
9245
  * `id` stays the source of truth for resolution/download/persistence; grouping
9237
9246
  * is a presentation overlay resolved back to an `id`.
9238
9247
  */
9239
- group: ModelVariantGroupSchema.optional()
9248
+ group: ModelVariantGroupSchema.optional(),
9249
+ /**
9250
+ * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
9251
+ * applies (Frigate / COCO public catalog). Set on a custom model whose raw
9252
+ * labels already ARE the CamStack macros (Scrypted identity map).
9253
+ */
9254
+ classMap: ClassMapDefinitionSchema.optional()
9240
9255
  });
9241
9256
  var ConvertTargetSchema = discriminatedUnion("format", [object({
9242
9257
  format: literal("openvino"),
@@ -9265,7 +9280,8 @@ var ModelConvertMetadataSchema = object({
9265
9280
  "ocr",
9266
9281
  "segmentation"
9267
9282
  ]),
9268
- faceAlignment: boolean().optional()
9283
+ faceAlignment: boolean().optional(),
9284
+ classMap: ClassMapDefinitionSchema.optional()
9269
9285
  });
9270
9286
  var ConvertResultSchema = object({
9271
9287
  entry: ModelCatalogEntrySchema,
@@ -16197,12 +16213,15 @@ var NcOccupancyConditionSchema = object({
16197
16213
  * there is no second switch that can disagree with the first and every rule
16198
16214
  * authored before the decision migrates for free (`audioModeOf`):
16199
16215
  *
16200
- * - **LABEL mode — `labels` present.** The rule fires on the FIRST frame the
16201
- * classifier labels with one of them. No window, no percentage:
16202
- * `hitPercent` and `samplingSeconds` are ignored, and the rule's own
16203
- * `throttle` cooldown is the only brake. The per-label confidence floor is
16204
- * the analyzer's (`classificationMinScore`, per device) a label only
16205
- * reaches this condition if the classifier was already confident enough.
16216
+ * - **LABEL mode — `labels` present.** The rule fires when `confirmHits`
16217
+ * labelled frames land inside `confirmWindowSec` (default 2 in 5 s).
16218
+ * `hitPercent` and `samplingSeconds` are still ignored a percentage of
16219
+ * frames is the wrong question for a classifier that labels 1–3 frames
16220
+ * per episode. The count window is the brake that drops a single-frame
16221
+ * false positive; the rule's own `throttle` cooldown is the other. The
16222
+ * per-label confidence floor is the analyzer's (`classificationMinScore`,
16223
+ * per device) — a label only reaches this condition if the classifier was
16224
+ * already confident enough. `confirmHits: 1` restores first-frame fire.
16206
16225
  * - **LEVEL mode — `dbThreshold` present, no labels.** The sampling window IS
16207
16226
  * the condition: at least `hitPercent`% of the samples over
16208
16227
  * `samplingSeconds` must be at or above `dbThreshold` dBFS (see
@@ -16229,14 +16248,22 @@ var NcOccupancyConditionSchema = object({
16229
16248
  * an operator who typed `dog` mean the same thing.
16230
16249
  */
16231
16250
  var NcAudioConditionSchema = object({
16232
- /** LABEL MODE: audio macro labels. Present ⇒ fires on the first labelled frame. */
16251
+ /** LABEL MODE: audio macro labels. Present ⇒ count-in-window confirm. */
16233
16252
  labels: array(string().min(1)).min(1).optional(),
16234
16253
  /** LEVEL MODE: floor in dBFS (negative-going, `0` = full scale). */
16235
16254
  dbThreshold: number().min(-96).max(0).optional(),
16236
16255
  /** LEVEL MODE ONLY: percentage of the window's samples that must be hits (1–100). */
16237
16256
  hitPercent: number().int().min(1).max(100).default(60),
16238
16257
  /** LEVEL MODE ONLY: length of the sampling window in seconds. */
16239
- samplingSeconds: number().int().min(1).max(300).default(10)
16258
+ samplingSeconds: number().int().min(1).max(300).default(10),
16259
+ /**
16260
+ * LABEL MODE: how many labelled frames must land inside
16261
+ * {@link NcAudioConditionSchema.shape.confirmWindowSec} before dispatch.
16262
+ * Absent ⇒ 2 (the matcher default). `1` is first-frame fire.
16263
+ */
16264
+ confirmHits: number().int().min(1).max(20).optional(),
16265
+ /** LABEL MODE: the window those frames must share, in seconds. Absent ⇒ 5. */
16266
+ confirmWindowSec: number().int().min(1).max(60).optional()
16240
16267
  });
16241
16268
  /**
16242
16269
  * Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
@@ -18685,7 +18712,9 @@ var TrackCascadeCountsSchema = object({
18685
18712
  /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
18686
18713
  plates: number().int(),
18687
18714
  /** Per-track CLIP search vectors removed (best-effort). */
18688
- embeddings: number().int()
18715
+ embeddings: number().int(),
18716
+ /** Group membership + group rows removed with their last member (best-effort). */
18717
+ groups: number().int()
18689
18718
  });
18690
18719
  /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
18691
18720
  var DiskReconcileCountsSchema = object({
@@ -19049,6 +19078,33 @@ var NativeCropRefSchema = object({
19049
19078
  h: number()
19050
19079
  })
19051
19080
  });
19081
+ object({
19082
+ crop: object({
19083
+ left: number(),
19084
+ top: number(),
19085
+ width: number().positive(),
19086
+ height: number().positive()
19087
+ }).optional(),
19088
+ content: object({
19089
+ width: number().int().positive(),
19090
+ height: number().int().positive()
19091
+ }),
19092
+ fit: _enum(["stretch", "contain"]),
19093
+ format: _enum([
19094
+ "rgb",
19095
+ "gray",
19096
+ "jpeg"
19097
+ ])
19098
+ });
19099
+ var FrameRefSchema = object({
19100
+ registryId: string().min(1),
19101
+ id: string().min(1),
19102
+ width: number().int().positive(),
19103
+ height: number().int().positive(),
19104
+ format: _enum(["rgb", "gray"]),
19105
+ timestamp: number(),
19106
+ capturedAt: number().optional()
19107
+ });
19052
19108
  var ModelFormatSchema$1 = _enum([
19053
19109
  "onnx",
19054
19110
  "coreml",
@@ -19369,7 +19425,7 @@ var pipelineExecutorCapability = {
19369
19425
  * legacy call shape used by existing benchmark code; once all
19370
19426
  * callers pass it explicitly we make it required.
19371
19427
  *
19372
- * Exactly one of `frame`, `frameHandle`, `imageBase64`,
19428
+ * Exactly one of `frame`, `frameRef`, `frameHandle`, `imageBase64`,
19373
19429
  * `referenceImage` must be provided:
19374
19430
  * - `frame`: runtime dispatch path (runner → decoded broker frame).
19375
19431
  * Carries the raw buffer, dimensions, and format; the executor
@@ -19391,6 +19447,12 @@ var pipelineExecutorCapability = {
19391
19447
  steps: array(PipelineStepInputSchema).min(1),
19392
19448
  frame: FrameInputSchema.optional(),
19393
19449
  /**
19450
+ * Process-local lazy frame. Valid only when caller and provider resolve
19451
+ * in the same execution-group process; split/cross-node callers use
19452
+ * `frame`/`image` inline compatibility instead.
19453
+ */
19454
+ frameRef: FrameRefSchema.optional(),
19455
+ /**
19394
19456
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
19395
19457
  * the decoded pixels live in. One more member of the one-of
19396
19458
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -19700,7 +19762,10 @@ var NativeCropResultSchema = object({
19700
19762
  * Which source served this crop, so a quality-sensitive consumer (the native
19701
19763
  * `keyFrame`) can reject a degraded fallback:
19702
19764
  * - `native` — cut from the decode worker's retained NATIVE surface (the
19703
- * quality path).
19765
+ * quality path). A subject-tile serve is also native-resolution and stays
19766
+ * `native` here: the public enum cannot name `tile` without a breaking cap
19767
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
19768
+ * internal crop result (`nativeHits` vs `tileHits`).
19704
19769
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
19705
19770
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
19706
19771
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -20191,12 +20256,41 @@ var RunnerLocalLoadSchema = object({
20191
20256
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
20192
20257
  * working unchanged when they switch to reading from the runner cap.
20193
20258
  */
20259
+ var FrameLazyCountersSchema = object({
20260
+ framesDecoded: number(),
20261
+ framesAdmitted: number(),
20262
+ framesDroppedPixelFree: number(),
20263
+ viewsMaterialized: number(),
20264
+ viewsSkipped: number(),
20265
+ workerToRunnerBytes: number(),
20266
+ runnerToPoolRawBytes: number(),
20267
+ runnerToPoolJpegBytes: number(),
20268
+ onDemandFullFrameRequests: number(),
20269
+ onDemandCropRequests: number(),
20270
+ nativeHits: number(),
20271
+ nativeMisses: number(),
20272
+ tileHits: number(),
20273
+ tileMisses: number(),
20274
+ fallbackHits: number(),
20275
+ fallbackMisses: number(),
20276
+ retainedWritesAvoided: number(),
20277
+ residentRefs: number(),
20278
+ residentBytes: number(),
20279
+ releases: number(),
20280
+ evictions: number(),
20281
+ staleMisses: number()
20282
+ });
20283
+ var FrameLazyMetricsSchema = object({
20284
+ node: FrameLazyCountersSchema,
20285
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
20286
+ });
20194
20287
  var RunnerLocalMetricsSchema = object({
20195
20288
  nodeId: string(),
20196
20289
  activeCameras: number(),
20197
20290
  throttledCameras: number(),
20198
20291
  avgInferenceTimeMs: number(),
20199
- queueDepth: number()
20292
+ queueDepth: number(),
20293
+ frameLazy: FrameLazyMetricsSchema.optional()
20200
20294
  });
20201
20295
  /**
20202
20296
  * Pipeline Runner capability — runtime detection workhorse.
@@ -21653,6 +21747,9 @@ method(_void(), ProviderInfoSchema), method(object({ config: record(string(), un
21653
21747
  location: StorageLocationSchema,
21654
21748
  relativePath: string()
21655
21749
  }), _void(), { kind: "mutation" }), method(object({ location: StorageLocationSchema }), number().nullable()), method(BeginUploadInputSchema, BeginUploadResultSchema, { kind: "mutation" }), method(WriteChunkInputSchema, _void(), { kind: "mutation" }), method(FinalizeUploadInputSchema, _void(), { kind: "mutation" }), method(AbortUploadInputSchema, _void(), { kind: "mutation" }), method(BeginDownloadInputSchema, BeginDownloadResultSchema, { kind: "mutation" }), method(ReadChunkInputSchema, _instanceof(Uint8Array)), method(EndDownloadInputSchema, _void(), { kind: "mutation" });
21750
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
21751
+ var ProfileSettingsSchemaBridge = unknown().nullable();
21752
+ var ProfileSettingsBagSchema = record(string(), unknown());
21656
21753
  /**
21657
21754
  * A live terminal session hosted by the provider addon. Output and input do
21658
21755
  * NOT flow through the capability — they use the addon data plane
@@ -21687,7 +21784,9 @@ var TerminalProfileInfoSchema = object({
21687
21784
  executable: string().optional(),
21688
21785
  args: array(string()).readonly().optional(),
21689
21786
  cwd: string().optional(),
21690
- environment: array(string()).readonly().optional()
21787
+ environment: array(string()).readonly().optional(),
21788
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
21789
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
21691
21790
  });
21692
21791
  /**
21693
21792
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -21704,7 +21803,8 @@ var TerminalInstanceInfoSchema = object({
21704
21803
  executable: string(),
21705
21804
  args: array(string()).readonly(),
21706
21805
  cwd: string(),
21707
- environment: array(string()).readonly()
21806
+ environment: array(string()).readonly(),
21807
+ profileSettings: ProfileSettingsBagSchema
21708
21808
  });
21709
21809
  var TerminalLegacyCameraSchema = object({
21710
21810
  stableId: string(),
@@ -21738,7 +21838,8 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
21738
21838
  executable: string().max(1024).optional(),
21739
21839
  args: array(string().max(2048)).max(64).optional(),
21740
21840
  cwd: string().max(1024).optional(),
21741
- environment: array(string().max(4096)).max(64).optional()
21841
+ environment: array(string().max(4096)).max(64).optional(),
21842
+ profileSettings: ProfileSettingsBagSchema.optional()
21742
21843
  }), TerminalInstanceInfoSchema, {
21743
21844
  kind: "mutation",
21744
21845
  auth: "admin"
@@ -21748,7 +21849,8 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
21748
21849
  executable: string().max(1024).optional(),
21749
21850
  args: array(string().max(2048)).max(64).optional(),
21750
21851
  cwd: string().max(1024).optional(),
21751
- environment: array(string().max(4096)).max(64).optional()
21852
+ environment: array(string().max(4096)).max(64).optional(),
21853
+ profileSettings: ProfileSettingsBagSchema.optional()
21752
21854
  }), TerminalInstanceInfoSchema, {
21753
21855
  kind: "mutation",
21754
21856
  auth: "admin"
@@ -24703,10 +24805,10 @@ DeviceType.LawnMower, method(object({ deviceId: number().int().nonnegative() }),
24703
24805
  *
24704
24806
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
24705
24807
  * to receive an ordered list of candidate base URLs it should race
24706
- * on connect — LAN IPv4 first (lowest latency when on same network),
24707
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
24708
- * race them with short timeouts and stick with the winner for the
24709
- * session.
24808
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
24809
+ * when on the same network), then public hostname (if a tunnel is
24810
+ * up). The SDK can race them with short timeouts and stick with the
24811
+ * winner for the session.
24710
24812
  *
24711
24813
  * Why hub-only: agents are not directly addressable by the operator's
24712
24814
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -24861,6 +24963,17 @@ var NotificationEndpointSchema = object({
24861
24963
  /** What the ranking currently resolves to (null when nothing is reachable). */
24862
24964
  resolved: string().nullable()
24863
24965
  });
24966
+ /**
24967
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
24968
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
24969
+ * currently expands to, so the UI can show the effective set either way.
24970
+ */
24971
+ var ViewerEndpointsSchema = object({
24972
+ /** The operator's explicit race set, or empty for AUTO. */
24973
+ baseUrls: array(string()).readonly(),
24974
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
24975
+ resolved: array(string()).readonly()
24976
+ });
24864
24977
  var AllowedAddressesSchema = object({
24865
24978
  /**
24866
24979
  * Allowlist of interface addresses operators have explicitly opted
@@ -24892,17 +25005,18 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
24892
25005
  */
24893
25006
  port: number().int().min(1).max(65535).optional(),
24894
25007
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
24895
- * candidate. Default `true`. */
25008
+ * candidate. Default `false` — loopback is not a client route. */
24896
25009
  includeLoopback: boolean().optional(),
24897
- /** Skip IPv6 entries. Some legacy clients can't parse them.
24898
- * Default `false`. */
25010
+ /** Skip IPv6 entries. Default `false` the palette includes stable
25011
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
25012
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
24899
25013
  ipv4Only: boolean().optional(),
24900
25014
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
24901
25015
  * Pass `'https'` when the caller is itself loaded over HTTPS
24902
25016
  * to avoid mixed-content blocks in the browser. The public
24903
25017
  * tunnel always emits `https://` regardless. */
24904
25018
  scheme: _enum(["http", "https"]).optional()
24905
- }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
25019
+ }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
24906
25020
  kind: "mutation",
24907
25021
  auth: "admin"
24908
25022
  }), method(object({
@@ -30886,6 +31000,12 @@ Object.freeze({
30886
31000
  addonId: null,
30887
31001
  access: "view"
30888
31002
  },
31003
+ "localNetwork.getViewerEndpoints": {
31004
+ capName: "local-network",
31005
+ capScope: "system",
31006
+ addonId: null,
31007
+ access: "view"
31008
+ },
30889
31009
  "localNetwork.list": {
30890
31010
  capName: "local-network",
30891
31011
  capScope: "system",
@@ -30922,6 +31042,12 @@ Object.freeze({
30922
31042
  addonId: null,
30923
31043
  access: "create"
30924
31044
  },
31045
+ "localNetwork.setViewerEndpoints": {
31046
+ capName: "local-network",
31047
+ capScope: "system",
31048
+ addonId: null,
31049
+ access: "create"
31050
+ },
30925
31051
  "localNetwork.uploadCertificate": {
30926
31052
  capName: "local-network",
30927
31053
  capScope: "system",
@@ -9081,6 +9081,15 @@ var LabelDefinitionSchema = object({
9081
9081
  description: string().optional(),
9082
9082
  icon: string().optional()
9083
9083
  });
9084
+ var ClassMapDefinitionSchema = object({
9085
+ mapping: record(string(), _enum([
9086
+ "person",
9087
+ "vehicle",
9088
+ "animal",
9089
+ "package"
9090
+ ])),
9091
+ preserveOriginal: boolean()
9092
+ });
9084
9093
  var MODEL_FORMATS = [
9085
9094
  "onnx",
9086
9095
  "coreml",
@@ -9259,7 +9268,13 @@ var ModelCatalogEntrySchema = object({
9259
9268
  * `id` stays the source of truth for resolution/download/persistence; grouping
9260
9269
  * is a presentation overlay resolved back to an `id`.
9261
9270
  */
9262
- group: ModelVariantGroupSchema.optional()
9271
+ group: ModelVariantGroupSchema.optional(),
9272
+ /**
9273
+ * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
9274
+ * applies (Frigate / COCO public catalog). Set on a custom model whose raw
9275
+ * labels already ARE the CamStack macros (Scrypted identity map).
9276
+ */
9277
+ classMap: ClassMapDefinitionSchema.optional()
9263
9278
  });
9264
9279
  var ConvertTargetSchema = discriminatedUnion("format", [object({
9265
9280
  format: literal("openvino"),
@@ -9288,7 +9303,8 @@ var ModelConvertMetadataSchema = object({
9288
9303
  "ocr",
9289
9304
  "segmentation"
9290
9305
  ]),
9291
- faceAlignment: boolean().optional()
9306
+ faceAlignment: boolean().optional(),
9307
+ classMap: ClassMapDefinitionSchema.optional()
9292
9308
  });
9293
9309
  var ConvertResultSchema = object({
9294
9310
  entry: ModelCatalogEntrySchema,
@@ -16220,12 +16236,15 @@ var NcOccupancyConditionSchema = object({
16220
16236
  * there is no second switch that can disagree with the first and every rule
16221
16237
  * authored before the decision migrates for free (`audioModeOf`):
16222
16238
  *
16223
- * - **LABEL mode — `labels` present.** The rule fires on the FIRST frame the
16224
- * classifier labels with one of them. No window, no percentage:
16225
- * `hitPercent` and `samplingSeconds` are ignored, and the rule's own
16226
- * `throttle` cooldown is the only brake. The per-label confidence floor is
16227
- * the analyzer's (`classificationMinScore`, per device) a label only
16228
- * reaches this condition if the classifier was already confident enough.
16239
+ * - **LABEL mode — `labels` present.** The rule fires when `confirmHits`
16240
+ * labelled frames land inside `confirmWindowSec` (default 2 in 5 s).
16241
+ * `hitPercent` and `samplingSeconds` are still ignored a percentage of
16242
+ * frames is the wrong question for a classifier that labels 1–3 frames
16243
+ * per episode. The count window is the brake that drops a single-frame
16244
+ * false positive; the rule's own `throttle` cooldown is the other. The
16245
+ * per-label confidence floor is the analyzer's (`classificationMinScore`,
16246
+ * per device) — a label only reaches this condition if the classifier was
16247
+ * already confident enough. `confirmHits: 1` restores first-frame fire.
16229
16248
  * - **LEVEL mode — `dbThreshold` present, no labels.** The sampling window IS
16230
16249
  * the condition: at least `hitPercent`% of the samples over
16231
16250
  * `samplingSeconds` must be at or above `dbThreshold` dBFS (see
@@ -16252,14 +16271,22 @@ var NcOccupancyConditionSchema = object({
16252
16271
  * an operator who typed `dog` mean the same thing.
16253
16272
  */
16254
16273
  var NcAudioConditionSchema = object({
16255
- /** LABEL MODE: audio macro labels. Present ⇒ fires on the first labelled frame. */
16274
+ /** LABEL MODE: audio macro labels. Present ⇒ count-in-window confirm. */
16256
16275
  labels: array(string().min(1)).min(1).optional(),
16257
16276
  /** LEVEL MODE: floor in dBFS (negative-going, `0` = full scale). */
16258
16277
  dbThreshold: number().min(-96).max(0).optional(),
16259
16278
  /** LEVEL MODE ONLY: percentage of the window's samples that must be hits (1–100). */
16260
16279
  hitPercent: number().int().min(1).max(100).default(60),
16261
16280
  /** LEVEL MODE ONLY: length of the sampling window in seconds. */
16262
- samplingSeconds: number().int().min(1).max(300).default(10)
16281
+ samplingSeconds: number().int().min(1).max(300).default(10),
16282
+ /**
16283
+ * LABEL MODE: how many labelled frames must land inside
16284
+ * {@link NcAudioConditionSchema.shape.confirmWindowSec} before dispatch.
16285
+ * Absent ⇒ 2 (the matcher default). `1` is first-frame fire.
16286
+ */
16287
+ confirmHits: number().int().min(1).max(20).optional(),
16288
+ /** LABEL MODE: the window those frames must share, in seconds. Absent ⇒ 5. */
16289
+ confirmWindowSec: number().int().min(1).max(60).optional()
16263
16290
  });
16264
16291
  /**
16265
16292
  * Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
@@ -18708,7 +18735,9 @@ var TrackCascadeCountsSchema = object({
18708
18735
  /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
18709
18736
  plates: number().int(),
18710
18737
  /** Per-track CLIP search vectors removed (best-effort). */
18711
- embeddings: number().int()
18738
+ embeddings: number().int(),
18739
+ /** Group membership + group rows removed with their last member (best-effort). */
18740
+ groups: number().int()
18712
18741
  });
18713
18742
  /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
18714
18743
  var DiskReconcileCountsSchema = object({
@@ -19072,6 +19101,33 @@ var NativeCropRefSchema = object({
19072
19101
  h: number()
19073
19102
  })
19074
19103
  });
19104
+ object({
19105
+ crop: object({
19106
+ left: number(),
19107
+ top: number(),
19108
+ width: number().positive(),
19109
+ height: number().positive()
19110
+ }).optional(),
19111
+ content: object({
19112
+ width: number().int().positive(),
19113
+ height: number().int().positive()
19114
+ }),
19115
+ fit: _enum(["stretch", "contain"]),
19116
+ format: _enum([
19117
+ "rgb",
19118
+ "gray",
19119
+ "jpeg"
19120
+ ])
19121
+ });
19122
+ var FrameRefSchema = object({
19123
+ registryId: string().min(1),
19124
+ id: string().min(1),
19125
+ width: number().int().positive(),
19126
+ height: number().int().positive(),
19127
+ format: _enum(["rgb", "gray"]),
19128
+ timestamp: number(),
19129
+ capturedAt: number().optional()
19130
+ });
19075
19131
  var ModelFormatSchema$1 = _enum([
19076
19132
  "onnx",
19077
19133
  "coreml",
@@ -19392,7 +19448,7 @@ var pipelineExecutorCapability = {
19392
19448
  * legacy call shape used by existing benchmark code; once all
19393
19449
  * callers pass it explicitly we make it required.
19394
19450
  *
19395
- * Exactly one of `frame`, `frameHandle`, `imageBase64`,
19451
+ * Exactly one of `frame`, `frameRef`, `frameHandle`, `imageBase64`,
19396
19452
  * `referenceImage` must be provided:
19397
19453
  * - `frame`: runtime dispatch path (runner → decoded broker frame).
19398
19454
  * Carries the raw buffer, dimensions, and format; the executor
@@ -19414,6 +19470,12 @@ var pipelineExecutorCapability = {
19414
19470
  steps: array(PipelineStepInputSchema).min(1),
19415
19471
  frame: FrameInputSchema.optional(),
19416
19472
  /**
19473
+ * Process-local lazy frame. Valid only when caller and provider resolve
19474
+ * in the same execution-group process; split/cross-node callers use
19475
+ * `frame`/`image` inline compatibility instead.
19476
+ */
19477
+ frameRef: FrameRefSchema.optional(),
19478
+ /**
19417
19479
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
19418
19480
  * the decoded pixels live in. One more member of the one-of
19419
19481
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -19723,7 +19785,10 @@ var NativeCropResultSchema = object({
19723
19785
  * Which source served this crop, so a quality-sensitive consumer (the native
19724
19786
  * `keyFrame`) can reject a degraded fallback:
19725
19787
  * - `native` — cut from the decode worker's retained NATIVE surface (the
19726
- * quality path).
19788
+ * quality path). A subject-tile serve is also native-resolution and stays
19789
+ * `native` here: the public enum cannot name `tile` without a breaking cap
19790
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
19791
+ * internal crop result (`nativeHits` vs `tileHits`).
19727
19792
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
19728
19793
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
19729
19794
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -20214,12 +20279,41 @@ var RunnerLocalLoadSchema = object({
20214
20279
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
20215
20280
  * working unchanged when they switch to reading from the runner cap.
20216
20281
  */
20282
+ var FrameLazyCountersSchema = object({
20283
+ framesDecoded: number(),
20284
+ framesAdmitted: number(),
20285
+ framesDroppedPixelFree: number(),
20286
+ viewsMaterialized: number(),
20287
+ viewsSkipped: number(),
20288
+ workerToRunnerBytes: number(),
20289
+ runnerToPoolRawBytes: number(),
20290
+ runnerToPoolJpegBytes: number(),
20291
+ onDemandFullFrameRequests: number(),
20292
+ onDemandCropRequests: number(),
20293
+ nativeHits: number(),
20294
+ nativeMisses: number(),
20295
+ tileHits: number(),
20296
+ tileMisses: number(),
20297
+ fallbackHits: number(),
20298
+ fallbackMisses: number(),
20299
+ retainedWritesAvoided: number(),
20300
+ residentRefs: number(),
20301
+ residentBytes: number(),
20302
+ releases: number(),
20303
+ evictions: number(),
20304
+ staleMisses: number()
20305
+ });
20306
+ var FrameLazyMetricsSchema = object({
20307
+ node: FrameLazyCountersSchema,
20308
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
20309
+ });
20217
20310
  var RunnerLocalMetricsSchema = object({
20218
20311
  nodeId: string(),
20219
20312
  activeCameras: number(),
20220
20313
  throttledCameras: number(),
20221
20314
  avgInferenceTimeMs: number(),
20222
- queueDepth: number()
20315
+ queueDepth: number(),
20316
+ frameLazy: FrameLazyMetricsSchema.optional()
20223
20317
  });
20224
20318
  /**
20225
20319
  * Pipeline Runner capability — runtime detection workhorse.
@@ -21676,6 +21770,9 @@ method(_void(), ProviderInfoSchema), method(object({ config: record(string(), un
21676
21770
  location: StorageLocationSchema,
21677
21771
  relativePath: string()
21678
21772
  }), _void(), { kind: "mutation" }), method(object({ location: StorageLocationSchema }), number().nullable()), method(BeginUploadInputSchema, BeginUploadResultSchema, { kind: "mutation" }), method(WriteChunkInputSchema, _void(), { kind: "mutation" }), method(FinalizeUploadInputSchema, _void(), { kind: "mutation" }), method(AbortUploadInputSchema, _void(), { kind: "mutation" }), method(BeginDownloadInputSchema, BeginDownloadResultSchema, { kind: "mutation" }), method(ReadChunkInputSchema, _instanceof(Uint8Array)), method(EndDownloadInputSchema, _void(), { kind: "mutation" });
21773
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
21774
+ var ProfileSettingsSchemaBridge = unknown().nullable();
21775
+ var ProfileSettingsBagSchema = record(string(), unknown());
21679
21776
  /**
21680
21777
  * A live terminal session hosted by the provider addon. Output and input do
21681
21778
  * NOT flow through the capability — they use the addon data plane
@@ -21710,7 +21807,9 @@ var TerminalProfileInfoSchema = object({
21710
21807
  executable: string().optional(),
21711
21808
  args: array(string()).readonly().optional(),
21712
21809
  cwd: string().optional(),
21713
- environment: array(string()).readonly().optional()
21810
+ environment: array(string()).readonly().optional(),
21811
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
21812
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
21714
21813
  });
21715
21814
  /**
21716
21815
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -21727,7 +21826,8 @@ var TerminalInstanceInfoSchema = object({
21727
21826
  executable: string(),
21728
21827
  args: array(string()).readonly(),
21729
21828
  cwd: string(),
21730
- environment: array(string()).readonly()
21829
+ environment: array(string()).readonly(),
21830
+ profileSettings: ProfileSettingsBagSchema
21731
21831
  });
21732
21832
  var TerminalLegacyCameraSchema = object({
21733
21833
  stableId: string(),
@@ -21761,7 +21861,8 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
21761
21861
  executable: string().max(1024).optional(),
21762
21862
  args: array(string().max(2048)).max(64).optional(),
21763
21863
  cwd: string().max(1024).optional(),
21764
- environment: array(string().max(4096)).max(64).optional()
21864
+ environment: array(string().max(4096)).max(64).optional(),
21865
+ profileSettings: ProfileSettingsBagSchema.optional()
21765
21866
  }), TerminalInstanceInfoSchema, {
21766
21867
  kind: "mutation",
21767
21868
  auth: "admin"
@@ -21771,7 +21872,8 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
21771
21872
  executable: string().max(1024).optional(),
21772
21873
  args: array(string().max(2048)).max(64).optional(),
21773
21874
  cwd: string().max(1024).optional(),
21774
- environment: array(string().max(4096)).max(64).optional()
21875
+ environment: array(string().max(4096)).max(64).optional(),
21876
+ profileSettings: ProfileSettingsBagSchema.optional()
21775
21877
  }), TerminalInstanceInfoSchema, {
21776
21878
  kind: "mutation",
21777
21879
  auth: "admin"
@@ -24726,10 +24828,10 @@ DeviceType.LawnMower, method(object({ deviceId: number().int().nonnegative() }),
24726
24828
  *
24727
24829
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
24728
24830
  * to receive an ordered list of candidate base URLs it should race
24729
- * on connect — LAN IPv4 first (lowest latency when on same network),
24730
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
24731
- * race them with short timeouts and stick with the winner for the
24732
- * session.
24831
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
24832
+ * when on the same network), then public hostname (if a tunnel is
24833
+ * up). The SDK can race them with short timeouts and stick with the
24834
+ * winner for the session.
24733
24835
  *
24734
24836
  * Why hub-only: agents are not directly addressable by the operator's
24735
24837
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -24884,6 +24986,17 @@ var NotificationEndpointSchema = object({
24884
24986
  /** What the ranking currently resolves to (null when nothing is reachable). */
24885
24987
  resolved: string().nullable()
24886
24988
  });
24989
+ /**
24990
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
24991
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
24992
+ * currently expands to, so the UI can show the effective set either way.
24993
+ */
24994
+ var ViewerEndpointsSchema = object({
24995
+ /** The operator's explicit race set, or empty for AUTO. */
24996
+ baseUrls: array(string()).readonly(),
24997
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
24998
+ resolved: array(string()).readonly()
24999
+ });
24887
25000
  var AllowedAddressesSchema = object({
24888
25001
  /**
24889
25002
  * Allowlist of interface addresses operators have explicitly opted
@@ -24915,17 +25028,18 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
24915
25028
  */
24916
25029
  port: number().int().min(1).max(65535).optional(),
24917
25030
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
24918
- * candidate. Default `true`. */
25031
+ * candidate. Default `false` — loopback is not a client route. */
24919
25032
  includeLoopback: boolean().optional(),
24920
- /** Skip IPv6 entries. Some legacy clients can't parse them.
24921
- * Default `false`. */
25033
+ /** Skip IPv6 entries. Default `false` the palette includes stable
25034
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
25035
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
24922
25036
  ipv4Only: boolean().optional(),
24923
25037
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
24924
25038
  * Pass `'https'` when the caller is itself loaded over HTTPS
24925
25039
  * to avoid mixed-content blocks in the browser. The public
24926
25040
  * tunnel always emits `https://` regardless. */
24927
25041
  scheme: _enum(["http", "https"]).optional()
24928
- }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
25042
+ }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
24929
25043
  kind: "mutation",
24930
25044
  auth: "admin"
24931
25045
  }), method(object({
@@ -30909,6 +31023,12 @@ Object.freeze({
30909
31023
  addonId: null,
30910
31024
  access: "view"
30911
31025
  },
31026
+ "localNetwork.getViewerEndpoints": {
31027
+ capName: "local-network",
31028
+ capScope: "system",
31029
+ addonId: null,
31030
+ access: "view"
31031
+ },
30912
31032
  "localNetwork.list": {
30913
31033
  capName: "local-network",
30914
31034
  capScope: "system",
@@ -30945,6 +31065,12 @@ Object.freeze({
30945
31065
  addonId: null,
30946
31066
  access: "create"
30947
31067
  },
31068
+ "localNetwork.setViewerEndpoints": {
31069
+ capName: "local-network",
31070
+ capScope: "system",
31071
+ addonId: null,
31072
+ access: "create"
31073
+ },
30948
31074
  "localNetwork.uploadCertificate": {
30949
31075
  capName: "local-network",
30950
31076
  capScope: "system",