@camstack/ui-library 1.1.27 → 1.1.28

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/index.cjs CHANGED
@@ -3748,37 +3748,41 @@ function mirror(input) {
3748
3748
  });
3749
3749
  continue;
3750
3750
  }
3751
- const srcModel = findModel(targetAddon, srcCfg.modelId);
3752
- const canUseSource = srcModel !== null && Boolean(srcModel.formats[target.engine.format]);
3753
3751
  let chosenModelId;
3754
3752
  let outcome;
3755
- if (canUseSource) {
3756
- chosenModelId = srcCfg.modelId;
3753
+ if (srcCfg.modelId === void 0) {
3754
+ chosenModelId = void 0;
3757
3755
  outcome = "exact";
3758
3756
  } else {
3759
- const fallback = firstModelFor(targetAddon, target.engine.format);
3760
- if (!fallback) {
3761
- out.push({
3762
- addonId,
3763
- outcome: "skip",
3764
- modelId: null,
3765
- reason: "no compatible model for target format",
3766
- patch: null
3767
- });
3768
- continue;
3757
+ const srcModel = findModel(targetAddon, srcCfg.modelId);
3758
+ if (srcModel !== null && Boolean(srcModel.formats[target.engine.format])) {
3759
+ chosenModelId = srcCfg.modelId;
3760
+ outcome = "exact";
3761
+ } else {
3762
+ const fallback = firstModelFor(targetAddon, target.engine.format);
3763
+ if (!fallback) {
3764
+ out.push({
3765
+ addonId,
3766
+ outcome: "skip",
3767
+ modelId: null,
3768
+ reason: "no compatible model for target format",
3769
+ patch: null
3770
+ });
3771
+ continue;
3772
+ }
3773
+ chosenModelId = fallback.id;
3774
+ outcome = "mapped";
3769
3775
  }
3770
- chosenModelId = fallback.id;
3771
- outcome = "mapped";
3772
3776
  }
3773
3777
  const patch = {
3774
3778
  enabled: srcCfg.enabled,
3775
- modelId: chosenModelId,
3779
+ ...chosenModelId ? { modelId: chosenModelId } : {},
3776
3780
  settings: dropModelSpecific(srcCfg.settings, targetAddon)
3777
3781
  };
3778
3782
  out.push({
3779
3783
  addonId,
3780
3784
  outcome,
3781
- modelId: chosenModelId,
3785
+ modelId: chosenModelId ?? null,
3782
3786
  patch
3783
3787
  });
3784
3788
  }
@@ -13268,10 +13272,11 @@ function modelsForStep(schema) {
13268
13272
  name: m.name
13269
13273
  }));
13270
13274
  }
13271
- function PipelineStep({ step, schema, allSchemas: _allSchemas, depth: _depth = 0, onChange, onDelete: _onDelete, readOnly = false, toggleMode = "simple", overrideState = null, onOverrideChange, inheritedEnabled, hideModelAndSettings = false }) {
13275
+ function PipelineStep({ step, schema, allSchemas: _allSchemas, depth: _depth = 0, onChange, onDelete: _onDelete, readOnly = false, toggleMode = "simple", overrideState = null, onOverrideChange, inheritedEnabled, hideModelAndSettings = false, allowAutoModel = false }) {
13272
13276
  const [expanded, setExpanded] = (0, react$1.useState)(false);
13273
13277
  const models = modelsForStep(schema);
13274
- if (models.length > 0 && !models.some((m) => m.id === step.modelId) && !readOnly) {
13278
+ const isAutoSentinel = allowAutoModel && step.modelId === "";
13279
+ if (models.length > 0 && !isAutoSentinel && !models.some((m) => m.id === step.modelId) && !readOnly) {
13275
13280
  const fallback = (schema?.defaultModelId ? models.find((m) => m.id === schema.defaultModelId) : null) ?? models[0];
13276
13281
  if (fallback && fallback.id !== step.modelId) queueMicrotask(() => onChange({
13277
13282
  ...step,
@@ -13356,59 +13361,28 @@ function PipelineStep({ step, schema, allSchemas: _allSchemas, depth: _depth = 0
13356
13361
  children: "Model and detection settings are managed per agent — open the Pipeline page for this camera's agent to edit them."
13357
13362
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13358
13363
  className: "space-y-3",
13359
- children: [
13360
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfigSelect, {
13361
- label: "Model",
13362
- value: step.modelId,
13363
- disabled: readOnly,
13364
- options: models.map((m) => ({
13365
- value: m.id,
13366
- label: m.name
13367
- })),
13368
- onChange: (v) => onChange({
13369
- ...step,
13370
- modelId: v
13371
- })
13372
- }),
13373
- step.slot === "audio-classifier" && step.engine && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfigSelect, {
13374
- label: "Runtime",
13375
- value: `${step.engine.runtime}/${step.engine.backend}`,
13376
- disabled: readOnly,
13377
- options: [
13378
- {
13379
- value: "node/cpu",
13380
- label: "Node.js — ONNX CPU"
13381
- },
13382
- {
13383
- value: "node/coreml",
13384
- label: "Node.js — Apple SoundAnalysis (macOS)"
13385
- },
13386
- {
13387
- value: "python/cpu",
13388
- label: "Python — ONNX CPU"
13389
- }
13390
- ],
13391
- onChange: (v) => {
13392
- const [runtime, backend] = v.split("/");
13393
- const format = backend === "coreml" ? "coreml" : "onnx";
13394
- onChange({
13395
- ...step,
13396
- engine: {
13397
- runtime,
13398
- backend,
13399
- format
13400
- }
13401
- });
13402
- }
13403
- }),
13404
- schema?.configSchema?.map((field) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfigSchemaField, {
13405
- field,
13406
- allFields: schema.configSchema ?? [],
13407
- step,
13408
- disabled: readOnly,
13409
- onChange
13410
- }, field.key))
13411
- ]
13364
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfigSelect, {
13365
+ label: "Model",
13366
+ value: step.modelId,
13367
+ disabled: readOnly,
13368
+ options: [...allowAutoModel ? [{
13369
+ value: "",
13370
+ label: "Auto (node default)"
13371
+ }] : [], ...models.map((m) => ({
13372
+ value: m.id,
13373
+ label: m.name
13374
+ }))],
13375
+ onChange: (v) => onChange({
13376
+ ...step,
13377
+ modelId: v
13378
+ })
13379
+ }), schema?.configSchema?.map((field) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfigSchemaField, {
13380
+ field,
13381
+ allFields: schema.configSchema ?? [],
13382
+ step,
13383
+ disabled: readOnly,
13384
+ onChange
13385
+ }, field.key))]
13412
13386
  })
13413
13387
  });
13414
13388
  }
@@ -13607,7 +13581,181 @@ function ThreeStateButton({ label, active, variant, subtext, onClick }) {
13607
13581
  });
13608
13582
  }
13609
13583
  //#endregion
13584
+ //#region src/composites/grouped-model-selector.tsx
13585
+ /**
13586
+ * GroupedModelSelector — the shared Family → Tier → Variant model picker.
13587
+ *
13588
+ * The catalog is a FLAT list of models (ids like `yolo26s`, `yolo26s-int8`);
13589
+ * this folds it into a `family → tier → variant` tree (see
13590
+ * `buildModelVariantGroups` in `@camstack/types`) so the operator picks
13591
+ * "YOLO26 → Small → Int8" instead of scanning a flat dropdown of every
13592
+ * size×quantization. The selected value stays the flat model id.
13593
+ *
13594
+ * Parameterised on the minimal `ModelVariantSource` shape so BOTH the config-UI
13595
+ * catalog (`ModelCatalogEntry`) and the pipeline/device steppers
13596
+ * (`PipelineModelOption`) drive the same component. Legacy / ungrouped models
13597
+ * never appear here (the grouping helpers skip them).
13598
+ */
13599
+ function Chip({ active, onClick, disabled, children, title }) {
13600
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
13601
+ type: "button",
13602
+ onClick,
13603
+ disabled,
13604
+ title,
13605
+ className: cn("rounded-full px-3 py-1 text-[11px] font-medium border transition-colors", active ? "border-primary bg-primary/10 text-primary" : "border-border bg-background text-foreground-subtle hover:text-foreground hover:border-foreground-subtle/40", disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"),
13606
+ children
13607
+ });
13608
+ }
13609
+ function GroupedModelSelector({ catalog, value, onChange, disabled }) {
13610
+ const families = (0, _camstack_types.buildModelVariantGroups)(catalog);
13611
+ const current = (0, _camstack_types.describeModelVariant)(catalog, value);
13612
+ const activeFamily = families.find((f) => f.family === current?.family)?.family ?? families[0]?.family ?? "";
13613
+ const family = families.find((f) => f.family === activeFamily) ?? families[0];
13614
+ if (!family) return null;
13615
+ const activeTier = family.tiers.find((t) => t.tier === current?.tier)?.tier ?? family.tiers[0]?.tier ?? "";
13616
+ const tier = family.tiers.find((t) => t.tier === activeTier) ?? family.tiers[0];
13617
+ if (!tier) return null;
13618
+ const selectTier = (tierId) => {
13619
+ const t = family.tiers.find((x) => x.tier === tierId);
13620
+ if (!t) return;
13621
+ const want = {
13622
+ precision: current?.precision,
13623
+ optimization: current?.optimization
13624
+ };
13625
+ onChange((t.options.find((o) => o.precision === (want.precision ?? "fp32") && o.optimization === (want.optimization ?? "standard")) ?? t.options[0]).modelId);
13626
+ };
13627
+ const selectVariant = (opt) => {
13628
+ const id = (0, _camstack_types.resolveVariantModelId)(catalog, {
13629
+ family: family.family,
13630
+ tier: tier.tier,
13631
+ precision: opt.precision,
13632
+ optimization: opt.optimization
13633
+ });
13634
+ if (id) onChange(id);
13635
+ };
13636
+ const selectedOption = tier.options.find((o) => o.modelId === value) ?? null;
13637
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13638
+ className: "space-y-3",
13639
+ children: [
13640
+ families.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
13641
+ className: "text-[10px] uppercase tracking-wide text-foreground-subtle mb-1.5",
13642
+ children: "Family"
13643
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
13644
+ className: "flex flex-wrap gap-1.5",
13645
+ children: families.map((f) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Chip, {
13646
+ active: f.family === family.family,
13647
+ disabled,
13648
+ onClick: () => onChange(f.tiers[0]?.baseModelId ?? ""),
13649
+ children: f.label
13650
+ }, f.family))
13651
+ })] }),
13652
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
13653
+ className: "text-[10px] uppercase tracking-wide text-foreground-subtle mb-1.5",
13654
+ children: [family.label, " — size"]
13655
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
13656
+ className: "grid grid-cols-2 gap-1.5 sm:grid-cols-4",
13657
+ children: family.tiers.map((t) => {
13658
+ const active = t.tier === tier.tier;
13659
+ const base = t.options.find((o) => o.modelId === t.baseModelId) ?? t.options[0];
13660
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
13661
+ type: "button",
13662
+ disabled,
13663
+ onClick: () => selectTier(t.tier),
13664
+ className: cn("rounded-lg border px-2 py-2 text-left transition-all", active ? "border-primary bg-primary/5 ring-1 ring-primary/30" : "border-border bg-background hover:border-foreground-subtle/40", disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"),
13665
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13666
+ className: "flex items-center gap-1",
13667
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
13668
+ className: "text-xs font-semibold text-foreground",
13669
+ children: t.label
13670
+ }), active && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Check, { className: "h-3 w-3 text-primary" })]
13671
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
13672
+ className: "text-[10px] text-foreground-subtle",
13673
+ children: [
13674
+ "~",
13675
+ base?.sizeMB ?? 0,
13676
+ " MB"
13677
+ ]
13678
+ })]
13679
+ }, t.tier);
13680
+ })
13681
+ })] }),
13682
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
13683
+ className: "text-[10px] uppercase tracking-wide text-foreground-subtle mb-1.5",
13684
+ children: "Variant"
13685
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
13686
+ className: "flex flex-wrap gap-1.5",
13687
+ children: tier.options.map((opt) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Chip, {
13688
+ active: opt.modelId === value,
13689
+ disabled,
13690
+ title: `${opt.formats.join(", ")} · ~${opt.sizeMB} MB`,
13691
+ onClick: () => selectVariant(opt),
13692
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
13693
+ className: "inline-flex items-center gap-1",
13694
+ children: [opt.optimization === "fast" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Zap, { className: "h-3 w-3" }), opt.label]
13695
+ })
13696
+ }, opt.modelId))
13697
+ })] }),
13698
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13699
+ className: "flex items-center gap-2 text-[10px] text-foreground-subtle pt-0.5",
13700
+ children: [
13701
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Cpu, { className: "h-3 w-3" }),
13702
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
13703
+ className: "font-mono",
13704
+ children: value || "—"
13705
+ }),
13706
+ selectedOption && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
13707
+ "· ",
13708
+ selectedOption.formats.join(", "),
13709
+ " · ~",
13710
+ selectedOption.sizeMB,
13711
+ " MB"
13712
+ ] })
13713
+ ]
13714
+ })
13715
+ ]
13716
+ });
13717
+ }
13718
+ //#endregion
13610
13719
  //#region src/composites/agent-step-editor.tsx
13720
+ /**
13721
+ * Shared model picker for the step editor — renders the grouped
13722
+ * Family→Tier→Variant selector when the step's models declare variant groups
13723
+ * (yolo26 …), else a flat `<select>` (face / plate / classifier catalogs and
13724
+ * custom models). Same component both the agent-default and per-device-override
13725
+ * modes use, so the picker looks identical across the pipeline stepper, the
13726
+ * device stepper and the cluster matrix.
13727
+ */
13728
+ function ModelPicker({ models, value, onChange, disabled }) {
13729
+ const hasGroups = (0, react$1.useMemo)(() => (0, _camstack_types.buildModelVariantGroups)(models).length > 0, [models]);
13730
+ const ungrouped = (0, react$1.useMemo)(() => models.filter((m) => m.group === void 0), [models]);
13731
+ const flatSelect = (opts, selectPlaceholder) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
13732
+ disabled,
13733
+ className: "w-full bg-surface border border-border rounded px-2 py-1 text-xs disabled:opacity-50",
13734
+ value: opts.some((m) => m.id === value) ? value : "",
13735
+ onChange: (e) => onChange(e.target.value),
13736
+ children: [selectPlaceholder !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
13737
+ value: "",
13738
+ disabled: true,
13739
+ children: selectPlaceholder
13740
+ }), opts.map((m) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
13741
+ value: m.id,
13742
+ children: m.name
13743
+ }, m.id))]
13744
+ });
13745
+ if (!hasGroups) return flatSelect(models);
13746
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13747
+ className: "space-y-3",
13748
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(GroupedModelSelector, {
13749
+ catalog: models,
13750
+ value,
13751
+ onChange,
13752
+ disabled
13753
+ }), ungrouped.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
13754
+ className: "text-[10px] uppercase tracking-widest text-foreground-subtle mb-1",
13755
+ children: "Other models"
13756
+ }), flatSelect(ungrouped, "— custom / ungrouped model —")] })]
13757
+ });
13758
+ }
13611
13759
  function buildDisplayStep(addon, cfg) {
13612
13760
  return {
13613
13761
  addonId: addon.id,
@@ -13616,7 +13764,7 @@ function buildDisplayStep(addon, cfg) {
13616
13764
  inputClasses: [...addon.inputClasses],
13617
13765
  outputClasses: [...addon.outputClasses],
13618
13766
  enabled: cfg.enabled,
13619
- modelId: cfg.modelId,
13767
+ modelId: cfg.modelId ?? addon.defaultModelId,
13620
13768
  children: [],
13621
13769
  settings: { ...cfg.settings }
13622
13770
  };
@@ -13654,14 +13802,10 @@ function AgentModeEditor({ addon, agentDefault, modelsForFormat, onChangeAgentCo
13654
13802
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
13655
13803
  className: "text-[10px] uppercase tracking-widest text-foreground-subtle mb-1",
13656
13804
  children: "Model"
13657
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
13658
- className: "w-full bg-surface border border-border rounded px-2 py-1 text-xs",
13659
- value: agentDefault.modelId,
13660
- onChange: (e) => update({ modelId: e.target.value }),
13661
- children: modelsForFormat.map((m) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
13662
- value: m.id,
13663
- children: m.name
13664
- }, m.id))
13805
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelPicker, {
13806
+ models: modelsForFormat,
13807
+ value: agentDefault.modelId ?? "",
13808
+ onChange: (modelId) => update({ modelId })
13665
13809
  })] }),
13666
13810
  (addon.configSchema?.length ?? 0) > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13667
13811
  className: "pt-2 border-t border-border/50 space-y-3",
@@ -13752,15 +13896,11 @@ function DeviceModeEditor({ addon, agentDefault, agentNodeId, currentPatch, mode
13752
13896
  children: "Override"
13753
13897
  })]
13754
13898
  }),
13755
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
13899
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelPicker, {
13900
+ models: modelsForFormat,
13756
13901
  disabled: !modelOverridden,
13757
- className: "w-full bg-surface border border-border rounded px-2 py-1 text-xs disabled:opacity-50",
13758
- value: modelOverridden ? currentPatch?.modelId ?? agentDefault.modelId : agentDefault.modelId,
13759
- onChange: (e) => setModel(e.target.value),
13760
- children: modelsForFormat.map((m) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
13761
- value: m.id,
13762
- children: m.name
13763
- }, m.id))
13902
+ value: (modelOverridden ? currentPatch?.modelId ?? agentDefault.modelId : agentDefault.modelId) ?? "",
13903
+ onChange: (modelId) => setModel(modelId)
13764
13904
  }),
13765
13905
  !modelOverridden && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13766
13906
  className: "text-[10px] text-foreground-subtle mt-1",
@@ -13940,17 +14080,33 @@ function QuickToggle({ enabled, onChange, disabled }) {
13940
14080
  function renderCellContent(state) {
13941
14081
  if (state.kind === "enabled") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
13942
14082
  className: "flex min-w-0 items-center gap-1",
13943
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "h-1.5 w-1.5 rounded-full bg-emerald-500 shrink-0" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
13944
- className: "font-mono text-foreground truncate",
13945
- children: state.modelId
13946
- })]
14083
+ title: state.overridden ? "override" : void 0,
14084
+ children: [
14085
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: cn("h-1.5 w-1.5 rounded-full shrink-0", state.overridden ? "bg-amber-500" : "bg-emerald-500") }),
14086
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
14087
+ className: "font-mono text-foreground truncate",
14088
+ children: state.modelId
14089
+ }),
14090
+ state.overridden && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
14091
+ className: "ml-auto shrink-0 text-[8px] font-semibold uppercase text-amber-500",
14092
+ children: "ovr"
14093
+ })
14094
+ ]
13947
14095
  });
13948
14096
  if (state.kind === "disabled") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
13949
14097
  className: "flex min-w-0 items-center gap-1 text-foreground-subtle",
13950
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "h-1.5 w-1.5 rounded-full border border-foreground-subtle/60 shrink-0" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
13951
- className: "truncate",
13952
- children: "off"
13953
- })]
14098
+ title: state.overridden ? "override" : void 0,
14099
+ children: [
14100
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: cn("h-1.5 w-1.5 rounded-full shrink-0", state.overridden ? "bg-amber-500" : "border border-foreground-subtle/60") }),
14101
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
14102
+ className: "truncate",
14103
+ children: "off"
14104
+ }),
14105
+ state.overridden && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
14106
+ className: "ml-auto shrink-0 text-[8px] font-semibold uppercase text-amber-500",
14107
+ children: "ovr"
14108
+ })
14109
+ ]
13954
14110
  });
13955
14111
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
13956
14112
  className: "flex min-w-0 items-center gap-1 text-foreground-subtle/70",
@@ -15597,6 +15753,22 @@ function usePTZ(trpc, deviceId, hookOptions) {
15597
15753
  refreshPresets,
15598
15754
  wrap
15599
15755
  ]),
15756
+ updatePreset: (0, react$1.useCallback)(async (presetId) => {
15757
+ if (!ptz) return;
15758
+ await wrap(async () => {
15759
+ const existing = presets.find((p) => p.id === presetId);
15760
+ await ptz.savePreset({
15761
+ presetId,
15762
+ name: existing?.name ?? ""
15763
+ });
15764
+ await refreshPresets();
15765
+ });
15766
+ }, [
15767
+ ptz,
15768
+ presets,
15769
+ refreshPresets,
15770
+ wrap
15771
+ ]),
15600
15772
  deletePreset: (0, react$1.useCallback)(async (presetId) => {
15601
15773
  if (!ptz) return;
15602
15774
  await wrap(async () => {
@@ -15691,10 +15863,13 @@ function DPadButton({ direction, icon: Icon, disabled, className, variant, onMov
15691
15863
  });
15692
15864
  }
15693
15865
  function PTZOverlay({ controls, mode = "overlay", showPresets, showZoom = true, showHome = true, className }) {
15694
- const { move, startContinuous, stopContinuous, zoom, goHome, goToPreset, savePreset, deletePreset, presets, options, busy, error } = controls;
15866
+ const { move, startContinuous, stopContinuous, zoom, goHome, goToPreset, savePreset, updatePreset, deletePreset, presets, options, busy, error } = controls;
15695
15867
  const confirm = useConfirm();
15696
15868
  const [presetsOpen, setPresetsOpen] = (0, react$1.useState)(false);
15697
15869
  const [presetName, setPresetName] = (0, react$1.useState)("");
15870
+ const presetTriggerRef = (0, react$1.useRef)(null);
15871
+ const presetMenuRef = (0, react$1.useRef)(null);
15872
+ const [menuPos, setMenuPos] = (0, react$1.useState)(null);
15698
15873
  const isPanel = mode === "panel";
15699
15874
  const zoomVisible = showZoom && (options?.hasZoom ?? true);
15700
15875
  const supportsPresets = options?.supportsPresets ?? presets.length > 0;
@@ -15720,6 +15895,51 @@ function PTZOverlay({ controls, mode = "overlay", showPresets, showZoom = true,
15720
15895
  })) return;
15721
15896
  await deletePreset(presetId);
15722
15897
  }, [confirm, deletePreset]);
15898
+ const handleUpdatePreset = (0, react$1.useCallback)(async (presetId, label) => {
15899
+ if (!await confirm({
15900
+ title: "Update preset",
15901
+ message: `Overwrite preset "${label}" with the camera's current position?`,
15902
+ confirmLabel: "Update"
15903
+ })) return;
15904
+ await updatePreset(presetId);
15905
+ }, [confirm, updatePreset]);
15906
+ (0, react$1.useLayoutEffect)(() => {
15907
+ if (!presetsOpen) {
15908
+ setMenuPos(null);
15909
+ return;
15910
+ }
15911
+ const reposition = () => {
15912
+ const rect = presetTriggerRef.current?.getBoundingClientRect();
15913
+ if (rect) setMenuPos({
15914
+ top: rect.bottom + 4,
15915
+ right: window.innerWidth - rect.right
15916
+ });
15917
+ };
15918
+ reposition();
15919
+ window.addEventListener("resize", reposition);
15920
+ window.addEventListener("scroll", reposition, true);
15921
+ return () => {
15922
+ window.removeEventListener("resize", reposition);
15923
+ window.removeEventListener("scroll", reposition, true);
15924
+ };
15925
+ }, [presetsOpen]);
15926
+ (0, react$1.useEffect)(() => {
15927
+ if (!presetsOpen) return;
15928
+ const onPointerDown = (e) => {
15929
+ const target = e.target;
15930
+ if (presetMenuRef.current?.contains(target) || presetTriggerRef.current?.contains(target)) return;
15931
+ setPresetsOpen(false);
15932
+ };
15933
+ const onKey = (e) => {
15934
+ if (e.key === "Escape") setPresetsOpen(false);
15935
+ };
15936
+ document.addEventListener("mousedown", onPointerDown);
15937
+ document.addEventListener("keydown", onKey);
15938
+ return () => {
15939
+ document.removeEventListener("mousedown", onPointerDown);
15940
+ document.removeEventListener("keydown", onKey);
15941
+ };
15942
+ }, [presetsOpen]);
15723
15943
  const containerClass = isPanel ? "flex flex-col items-stretch gap-2 w-full h-full p-3" : "pointer-events-auto absolute top-3 right-3 z-10 flex flex-col items-end gap-2";
15724
15944
  const rowClass = isPanel ? cn("flex items-center gap-3 rounded-lg p-2", busy && "ring-1 ring-primary/40") : cn("flex items-center gap-2 rounded-lg border border-white/30 bg-zinc-900/90 backdrop-blur-md p-2 shadow-lg shadow-black/40", busy && "ring-1 ring-primary/40");
15725
15945
  const sideButtonSize = isPanel ? "h-9 w-9" : "h-7 w-7";
@@ -15820,14 +16040,22 @@ function PTZOverlay({ controls, mode = "overlay", showPresets, showZoom = true,
15820
16040
  presetsVisible && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
15821
16041
  className: "relative",
15822
16042
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
16043
+ ref: presetTriggerRef,
15823
16044
  type: "button",
15824
16045
  onClick: () => setPresetsOpen((v) => !v),
15825
16046
  disabled: busy,
15826
16047
  className: cn("flex items-center gap-1 rounded px-2 text-[10px] disabled:opacity-40", isPanel ? "h-9 text-foreground hover:bg-surface-hover" : "h-7 text-white hover:bg-white/15"),
15827
16048
  title: "Presets",
15828
16049
  children: ["Presets", /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronDown, { className: cn("h-3 w-3 transition-transform", presetsOpen && "rotate-180") })]
15829
- }), presetsOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
15830
- className: cn("absolute right-0 top-full mt-1 rounded-lg shadow-xl py-1 z-20", presetManagementVisible ? "min-w-[220px]" : "min-w-[140px]", isPanel ? "bg-surface border border-border" : "border border-white/30 bg-zinc-900/95 backdrop-blur-md"),
16050
+ }), presetsOpen && menuPos && (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
16051
+ ref: presetMenuRef,
16052
+ style: {
16053
+ position: "fixed",
16054
+ top: menuPos.top,
16055
+ right: menuPos.right,
16056
+ zIndex: 60
16057
+ },
16058
+ className: cn("rounded-lg shadow-xl py-1", presetManagementVisible ? "min-w-[220px]" : "min-w-[140px]", isPanel ? "bg-surface border border-border" : "border border-white/30 bg-zinc-900/95 backdrop-blur-md"),
15831
16059
  children: [
15832
16060
  presets.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
15833
16061
  className: cn("px-3 py-1.5 text-[10px]", isPanel ? "text-foreground-subtle" : "text-white/60"),
@@ -15844,14 +16072,21 @@ function PTZOverlay({ controls, mode = "overlay", showPresets, showZoom = true,
15844
16072
  disabled: busy,
15845
16073
  className: cn("flex-1 px-3 py-1.5 text-left text-[10px] disabled:opacity-40", isPanel ? "text-foreground" : "text-white"),
15846
16074
  children: p.name || p.id
15847
- }), presetManagementVisible && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
16075
+ }), presetManagementVisible && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
16076
+ type: "button",
16077
+ onClick: () => void handleUpdatePreset(p.id, p.name || p.id),
16078
+ disabled: busy,
16079
+ title: `Overwrite "${p.name || p.id}" with current position`,
16080
+ className: cn("flex h-5 w-5 shrink-0 items-center justify-center rounded", "text-foreground-subtle hover:bg-primary/15 hover:text-primary disabled:opacity-40"),
16081
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Crosshair, { className: "h-3 w-3" })
16082
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
15848
16083
  type: "button",
15849
16084
  onClick: () => void handleDeletePreset(p.id, p.name || p.id),
15850
16085
  disabled: busy,
15851
16086
  title: `Delete preset ${p.name || p.id}`,
15852
16087
  className: cn("mr-1 flex h-5 w-5 shrink-0 items-center justify-center rounded", "text-foreground-subtle hover:bg-danger/15 hover:text-danger disabled:opacity-40"),
15853
16088
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(X, { className: "h-3 w-3" })
15854
- })]
16089
+ })] })]
15855
16090
  }, p.id)),
15856
16091
  presetManagementVisible && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
15857
16092
  presets.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: cn("my-1 h-px", isPanel ? "bg-border" : "bg-white/15") }),
@@ -15887,7 +16122,7 @@ function PTZOverlay({ controls, mode = "overlay", showPresets, showZoom = true,
15887
16122
  })
15888
16123
  ] })
15889
16124
  ]
15890
- })]
16125
+ }), document.body)]
15891
16126
  })
15892
16127
  ]
15893
16128
  })]
@@ -17712,6 +17947,8 @@ var usePipelineExecutorGetGlobalSteps = trpc.pipelineExecutor.getGlobalSteps.use
17712
17947
  var usePipelineExecutorGetGlobalPipelineConfig = trpc.pipelineExecutor.getGlobalPipelineConfig.useQuery;
17713
17948
  /** Generated alias around `trpc.pipelineExecutor.getOrchestratorConfigSchema.useQuery`. */
17714
17949
  var usePipelineExecutorGetOrchestratorConfigSchema = trpc.pipelineExecutor.getOrchestratorConfigSchema.useQuery;
17950
+ /** Generated alias around `trpc.pipelineExecutor.validatePipeline.useQuery`. */
17951
+ var usePipelineExecutorValidatePipeline = trpc.pipelineExecutor.validatePipeline.useQuery;
17715
17952
  /** Generated alias around `trpc.pipelineExecutor.listTemplates.useQuery`. */
17716
17953
  var usePipelineExecutorListTemplates = trpc.pipelineExecutor.listTemplates.useQuery;
17717
17954
  /** Generated alias around `trpc.pipelineExecutor.saveTemplate.useMutation`. */
@@ -17782,6 +18019,8 @@ var usePipelineOrchestratorGetCameraMetrics = trpc.pipelineOrchestrator.getCamer
17782
18019
  var usePipelineOrchestratorGetCapabilityBindings = trpc.pipelineOrchestrator.getCapabilityBindings.useQuery;
17783
18020
  /** Generated alias around `trpc.pipelineOrchestrator.setCapabilityBinding.useMutation`. */
17784
18021
  var usePipelineOrchestratorSetCapabilityBinding = trpc.pipelineOrchestrator.setCapabilityBinding.useMutation;
18022
+ /** Generated alias around `trpc.pipelineOrchestrator.getIngestOwner.useQuery`. */
18023
+ var usePipelineOrchestratorGetIngestOwner = trpc.pipelineOrchestrator.getIngestOwner.useQuery;
17785
18024
  /** Generated alias around `trpc.pipelineOrchestrator.assignDecoder.useMutation`. */
17786
18025
  var usePipelineOrchestratorAssignDecoder = trpc.pipelineOrchestrator.assignDecoder.useMutation;
17787
18026
  /** Generated alias around `trpc.pipelineOrchestrator.unassignDecoder.useMutation`. */
@@ -17814,6 +18053,8 @@ var usePipelineOrchestratorSetAgentMaxCameras = trpc.pipelineOrchestrator.setAge
17814
18053
  var usePipelineOrchestratorSetAgentDetectWeight = trpc.pipelineOrchestrator.setAgentDetectWeight.useMutation;
17815
18054
  /** Generated alias around `trpc.pipelineOrchestrator.setAgentCapabilities.useMutation`. */
17816
18055
  var usePipelineOrchestratorSetAgentCapabilities = trpc.pipelineOrchestrator.setAgentCapabilities.useMutation;
18056
+ /** Generated alias around `trpc.pipelineOrchestrator.setAgentReachableHost.useMutation`. */
18057
+ var usePipelineOrchestratorSetAgentReachableHost = trpc.pipelineOrchestrator.setAgentReachableHost.useMutation;
17817
18058
  /** Generated alias around `trpc.pipelineOrchestrator.getCameraSettings.useQuery`. */
17818
18059
  var usePipelineOrchestratorGetCameraSettings = trpc.pipelineOrchestrator.getCameraSettings.useQuery;
17819
18060
  /** Generated alias around `trpc.pipelineOrchestrator.setCameraStepToggle.useMutation`. */
@@ -17988,10 +18229,6 @@ var useSnapshotGetDeviceSettingsContribution = trpc.snapshot.getDeviceSettingsCo
17988
18229
  var useSnapshotGetDeviceLiveContribution = trpc.snapshot.getDeviceLiveContribution.useQuery;
17989
18230
  /** Generated alias around `trpc.snapshot.applyDeviceSettingsPatch.useMutation`. */
17990
18231
  var useSnapshotApplyDeviceSettingsPatch = trpc.snapshot.applyDeviceSettingsPatch.useMutation;
17991
- /** Generated alias around `trpc.snapshotProvider.supportsDevice.useQuery`. */
17992
- var useSnapshotProviderSupportsDevice = trpc.snapshotProvider.supportsDevice.useQuery;
17993
- /** Generated alias around `trpc.snapshotProvider.getSnapshot.useQuery`. */
17994
- var useSnapshotProviderGetSnapshot = trpc.snapshotProvider.getSnapshot.useQuery;
17995
18232
  /** Generated alias around `trpc.storage.resolve.useQuery`. */
17996
18233
  var useStorageResolve = trpc.storage.resolve.useQuery;
17997
18234
  /** Generated alias around `trpc.storage.write.useMutation`. */
@@ -30042,10 +30279,11 @@ function PlaceholderStep({ addon, onClick }) {
30042
30279
  })
30043
30280
  });
30044
30281
  }
30045
- function PipelineBuilder({ schema, steps, onChange, templates, selectedTemplateId, onSelectTemplate, onSaveTemplate, onUpdateTemplate, onDeleteTemplate, readOnly = false, excludeAddons = [], hideTemplates = false, showOnlyEnabled = false, showSlotLabels = false, toggleMode = "simple", overrides = {}, onOverrideChange, inheritedEnabledByAddon = {}, hideModelAndSettings = false }) {
30282
+ function PipelineBuilder({ schema, steps, onChange, templates, selectedTemplateId, onSelectTemplate, onSaveTemplate, onUpdateTemplate, onDeleteTemplate, readOnly = false, excludeAddons = [], hideTemplates = false, showOnlyEnabled = false, showSlotLabels = false, toggleMode = "simple", overrides = {}, onOverrideChange, inheritedEnabledByAddon = {}, hideModelAndSettings = false, allowAutoModel = false }) {
30046
30283
  const stepExtraProps = (addonId) => ({
30047
30284
  toggleMode,
30048
30285
  hideModelAndSettings,
30286
+ allowAutoModel,
30049
30287
  ...toggleMode === "threeState" ? {
30050
30288
  overrideState: overrides[addonId] !== void 0 ? overrides[addonId] : null,
30051
30289
  onOverrideChange: onOverrideChange ? (next) => onOverrideChange(addonId, next) : void 0,
@@ -33278,7 +33516,7 @@ function ScheduleBandsEditor({ schedules, onChange }) {
33278
33516
  className: "space-y-2",
33279
33517
  children: [schedules.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
33280
33518
  className: "text-[11px] text-foreground-subtle",
33281
- children: "Sempre (24/7) — aggiungi una fascia per limitare gli orari."
33519
+ children: "Always (24/7) — add a band to restrict hours."
33282
33520
  }) : schedules.map((band, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BandRow, {
33283
33521
  band,
33284
33522
  onChange: (b) => replaceAt(i, b),
@@ -33287,7 +33525,7 @@ function ScheduleBandsEditor({ schedules, onChange }) {
33287
33525
  type: "button",
33288
33526
  onClick: addBand,
33289
33527
  className: "flex items-center gap-1 rounded-md bg-surface-hover px-2 py-1 text-[11px] text-foreground-subtle hover:text-foreground",
33290
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Plus, { className: "h-3 w-3" }), " Aggiungi fascia"]
33528
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Plus, { className: "h-3 w-3" }), " Add band"]
33291
33529
  })]
33292
33530
  });
33293
33531
  }
@@ -33297,18 +33535,18 @@ function BandRow({ band, onChange, onRemove }) {
33297
33535
  children: [
33298
33536
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
33299
33537
  className: "flex-1",
33300
- children: "Sempre"
33538
+ children: "Always"
33301
33539
  }),
33302
33540
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
33303
33541
  type: "button",
33304
33542
  onClick: () => onChange(newBand()),
33305
33543
  className: "text-foreground-subtle hover:text-foreground underline",
33306
- children: "imposta fascia"
33544
+ children: "Set band"
33307
33545
  }),
33308
33546
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
33309
33547
  type: "button",
33310
33548
  onClick: onRemove,
33311
- "aria-label": "Rimuovi fascia",
33549
+ "aria-label": "Remove band",
33312
33550
  className: "text-foreground-subtle hover:text-red-500",
33313
33551
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Trash2, { className: "h-3.5 w-3.5" })
33314
33552
  })
@@ -33353,7 +33591,7 @@ function BandRow({ band, onChange, onRemove }) {
33353
33591
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
33354
33592
  type: "button",
33355
33593
  onClick: onRemove,
33356
- "aria-label": "Rimuovi fascia",
33594
+ "aria-label": "Remove band",
33357
33595
  className: "text-foreground-subtle hover:text-red-500",
33358
33596
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Trash2, { className: "h-3.5 w-3.5" })
33359
33597
  })
@@ -33369,7 +33607,7 @@ function BandRow({ band, onChange, onRemove }) {
33369
33607
  }, d.value);
33370
33608
  }), days.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
33371
33609
  className: "self-center text-[10px] text-foreground-subtle",
33372
- children: "tutti i giorni"
33610
+ children: "every day"
33373
33611
  }) : null]
33374
33612
  })]
33375
33613
  });
@@ -33415,7 +33653,7 @@ function RecordingSettings({ initial, saving, onSave }) {
33415
33653
  });
33416
33654
  const numOrUndef = (v) => v === "" ? void 0 : Number(v);
33417
33655
  const toggleProfile = (p) => {
33418
- const cur = common.profiles ?? [];
33656
+ const cur = common.profiles ?? [...PROFILES];
33419
33657
  const next = cur.includes(p) ? cur.filter((x) => x !== p) : [...cur, p];
33420
33658
  setCommon({
33421
33659
  ...common,
@@ -33593,7 +33831,7 @@ function RecordingSettings({ initial, saving, onSave }) {
33593
33831
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
33594
33832
  type: "button",
33595
33833
  onClick: () => toggleProfile(p),
33596
- className: `rounded px-2 py-1 ${(common.profiles ?? []).includes(p) ? "bg-primary text-primary-foreground" : "bg-surface-hover text-foreground-subtle"}`,
33834
+ className: `rounded px-2 py-1 ${common.profiles == null || common.profiles.includes(p) ? "bg-primary text-primary-foreground" : "bg-surface-hover text-foreground-subtle"}`,
33597
33835
  children: p
33598
33836
  }, p);
33599
33837
  })]
@@ -34136,7 +34374,7 @@ function CoverageTrack({ windowFrom, windowTo, spans, playheadMs, onSeek, onScru
34136
34374
  const left = pctForMs(s.startMs, windowFrom, windowTo);
34137
34375
  const right = pctForMs(s.endMs, windowFrom, windowTo);
34138
34376
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
34139
- "data-testid": "coverage-fascia",
34377
+ "data-testid": "coverage-band",
34140
34378
  className: "absolute inset-y-0 bg-gradient-to-b from-primary to-primary/80",
34141
34379
  style: {
34142
34380
  left: `${left}%`,
@@ -45158,6 +45396,7 @@ exports.GRID_GAP = GRID_GAP;
45158
45396
  exports.GRID_PAIRED = GRID_PAIRED;
45159
45397
  exports.GRID_QUICK_STATS = GRID_QUICK_STATS;
45160
45398
  exports.GripTrack = GripTrack;
45399
+ exports.GroupedModelSelector = GroupedModelSelector;
45161
45400
  exports.HOST_WIDGETS = HOST_WIDGETS;
45162
45401
  exports.HlsVideo = HlsVideo;
45163
45402
  exports.HoverZoomImage = HoverZoomImage;
@@ -45894,6 +46133,7 @@ exports.usePipelineExecutorSetVideoPipelineSteps = usePipelineExecutorSetVideoPi
45894
46133
  exports.usePipelineExecutorSpinEngine = usePipelineExecutorSpinEngine;
45895
46134
  exports.usePipelineExecutorUncacheFrame = usePipelineExecutorUncacheFrame;
45896
46135
  exports.usePipelineExecutorUpdateTemplate = usePipelineExecutorUpdateTemplate;
46136
+ exports.usePipelineExecutorValidatePipeline = usePipelineExecutorValidatePipeline;
45897
46137
  exports.usePipelineOrchestratorApplyDeviceSettingsPatch = usePipelineOrchestratorApplyDeviceSettingsPatch;
45898
46138
  exports.usePipelineOrchestratorAssignAudio = usePipelineOrchestratorAssignAudio;
45899
46139
  exports.usePipelineOrchestratorAssignDecoder = usePipelineOrchestratorAssignDecoder;
@@ -45915,6 +46155,7 @@ exports.usePipelineOrchestratorGetDecoderAssignments = usePipelineOrchestratorGe
45915
46155
  exports.usePipelineOrchestratorGetDeviceLiveContribution = usePipelineOrchestratorGetDeviceLiveContribution;
45916
46156
  exports.usePipelineOrchestratorGetDeviceSettingsContribution = usePipelineOrchestratorGetDeviceSettingsContribution;
45917
46157
  exports.usePipelineOrchestratorGetGlobalMetrics = usePipelineOrchestratorGetGlobalMetrics;
46158
+ exports.usePipelineOrchestratorGetIngestOwner = usePipelineOrchestratorGetIngestOwner;
45918
46159
  exports.usePipelineOrchestratorGetPipelineAssignment = usePipelineOrchestratorGetPipelineAssignment;
45919
46160
  exports.usePipelineOrchestratorGetPipelineAssignments = usePipelineOrchestratorGetPipelineAssignments;
45920
46161
  exports.usePipelineOrchestratorListAgentSettings = usePipelineOrchestratorListAgentSettings;
@@ -45927,6 +46168,7 @@ exports.usePipelineOrchestratorSetAgentAddonDefaults = usePipelineOrchestratorSe
45927
46168
  exports.usePipelineOrchestratorSetAgentCapabilities = usePipelineOrchestratorSetAgentCapabilities;
45928
46169
  exports.usePipelineOrchestratorSetAgentDetectWeight = usePipelineOrchestratorSetAgentDetectWeight;
45929
46170
  exports.usePipelineOrchestratorSetAgentMaxCameras = usePipelineOrchestratorSetAgentMaxCameras;
46171
+ exports.usePipelineOrchestratorSetAgentReachableHost = usePipelineOrchestratorSetAgentReachableHost;
45930
46172
  exports.usePipelineOrchestratorSetCameraPipelineForAgent = usePipelineOrchestratorSetCameraPipelineForAgent;
45931
46173
  exports.usePipelineOrchestratorSetCameraStepOverride = usePipelineOrchestratorSetCameraStepOverride;
45932
46174
  exports.usePipelineOrchestratorSetCameraStepToggle = usePipelineOrchestratorSetCameraStepToggle;
@@ -46014,8 +46256,6 @@ exports.useSnapshotGetDeviceSettingsContribution = useSnapshotGetDeviceSettingsC
46014
46256
  exports.useSnapshotGetSnapshot = useSnapshotGetSnapshot;
46015
46257
  exports.useSnapshotGetStatus = useSnapshotGetStatus;
46016
46258
  exports.useSnapshotInvalidateCache = useSnapshotInvalidateCache;
46017
- exports.useSnapshotProviderGetSnapshot = useSnapshotProviderGetSnapshot;
46018
- exports.useSnapshotProviderSupportsDevice = useSnapshotProviderSupportsDevice;
46019
46259
  exports.useStorageAbortUpload = useStorageAbortUpload;
46020
46260
  exports.useStorageBeginDownload = useStorageBeginDownload;
46021
46261
  exports.useStorageBeginUpload = useStorageBeginUpload;