@camstack/ui-library 1.2.259 → 1.2.260

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
@@ -3885,6 +3885,19 @@ var Phone = createLucideIcon("phone", [["path", {
3885
3885
  * This source code is licensed under the ISC license.
3886
3886
  * See the LICENSE file in the root directory of this source tree.
3887
3887
  */
3888
+ var Pin = createLucideIcon("pin", [["path", {
3889
+ d: "M12 17v5",
3890
+ key: "bb1du9"
3891
+ }], ["path", {
3892
+ d: "M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z",
3893
+ key: "1nkz8b"
3894
+ }]]);
3895
+ /**
3896
+ * @license lucide-react v0.576.0 - ISC
3897
+ *
3898
+ * This source code is licensed under the ISC license.
3899
+ * See the LICENSE file in the root directory of this source tree.
3900
+ */
3888
3901
  var Pipette = createLucideIcon("pipette", [
3889
3902
  ["path", {
3890
3903
  d: "m12 9-8.414 8.414A2 2 0 0 0 3 18.828v1.344a2 2 0 0 1-.586 1.414A2 2 0 0 1 3.828 21h1.344a2 2 0 0 0 1.414-.586L15 12",
@@ -12366,6 +12379,10 @@ var usePipelineAnalyticsGetTrainingExportSummary = trpc.pipelineAnalytics.getTra
12366
12379
  var usePipelineAnalyticsGetTrainingExportUrl = trpc.pipelineAnalytics.getTrainingExportUrl.useQuery;
12367
12380
  /** Generated alias around `trpc.pipelineAnalytics.listRetrainStaging.useQuery`. */
12368
12381
  var usePipelineAnalyticsListRetrainStaging = trpc.pipelineAnalytics.listRetrainStaging.useQuery;
12382
+ /** Generated alias around `trpc.pipelineAnalytics.listRetrainCorpusPage.useQuery`. */
12383
+ var usePipelineAnalyticsListRetrainCorpusPage = trpc.pipelineAnalytics.listRetrainCorpusPage.useQuery;
12384
+ /** Generated alias around `trpc.pipelineAnalytics.getRetrainCorpusKpi.useQuery`. */
12385
+ var usePipelineAnalyticsGetRetrainCorpusKpi = trpc.pipelineAnalytics.getRetrainCorpusKpi.useQuery;
12369
12386
  /** Generated alias around `trpc.pipelineAnalytics.listRetrainFrames.useQuery`. */
12370
12387
  var usePipelineAnalyticsListRetrainFrames = trpc.pipelineAnalytics.listRetrainFrames.useQuery;
12371
12388
  /** Generated alias around `trpc.pipelineAnalytics.selectRetrainFrames.useMutation`. */
@@ -12392,16 +12409,6 @@ var usePipelineAnalyticsSetRetrainFrameComplete = trpc.pipelineAnalytics.setRetr
12392
12409
  var usePipelineAnalyticsWriteRetrainArchive = trpc.pipelineAnalytics.writeRetrainArchive.useMutation;
12393
12410
  /** Generated alias around `trpc.pipelineAnalytics.offerRetrainArchive.useMutation`. */
12394
12411
  var usePipelineAnalyticsOfferRetrainArchive = trpc.pipelineAnalytics.offerRetrainArchive.useMutation;
12395
- /** Generated alias around `trpc.pipelineAnalytics.previewRetrainDataset.useQuery`. */
12396
- var usePipelineAnalyticsPreviewRetrainDataset = trpc.pipelineAnalytics.previewRetrainDataset.useQuery;
12397
- /** Generated alias around `trpc.pipelineAnalytics.createRetrainDatasetVersion.useMutation`. */
12398
- var usePipelineAnalyticsCreateRetrainDatasetVersion = trpc.pipelineAnalytics.createRetrainDatasetVersion.useMutation;
12399
- /** Generated alias around `trpc.pipelineAnalytics.listRetrainDatasetVersions.useQuery`. */
12400
- var usePipelineAnalyticsListRetrainDatasetVersions = trpc.pipelineAnalytics.listRetrainDatasetVersions.useQuery;
12401
- /** Generated alias around `trpc.pipelineAnalytics.deleteRetrainDatasetVersion.useMutation`. */
12402
- var usePipelineAnalyticsDeleteRetrainDatasetVersion = trpc.pipelineAnalytics.deleteRetrainDatasetVersion.useMutation;
12403
- /** Generated alias around `trpc.pipelineAnalytics.verifyRetrainDatasetVersion.useQuery`. */
12404
- var usePipelineAnalyticsVerifyRetrainDatasetVersion = trpc.pipelineAnalytics.verifyRetrainDatasetVersion.useQuery;
12405
12412
  /** Generated alias around `trpc.pipelineAnalytics.listRetrainAssistProfiles.useQuery`. */
12406
12413
  var usePipelineAnalyticsListRetrainAssistProfiles = trpc.pipelineAnalytics.listRetrainAssistProfiles.useQuery;
12407
12414
  /** Generated alias around `trpc.pipelineAnalytics.proposeRetrainAnnotationsWithLlm.useMutation`. */
@@ -12410,6 +12417,8 @@ var usePipelineAnalyticsProposeRetrainAnnotationsWithLlm = trpc.pipelineAnalytic
12410
12417
  var usePipelineAnalyticsCreateRetrainCollection = trpc.pipelineAnalytics.createRetrainCollection.useMutation;
12411
12418
  /** Generated alias around `trpc.pipelineAnalytics.listRetrainCollections.useQuery`. */
12412
12419
  var usePipelineAnalyticsListRetrainCollections = trpc.pipelineAnalytics.listRetrainCollections.useQuery;
12420
+ /** Generated alias around `trpc.pipelineAnalytics.resolveRetrainTrainingCorpus.useQuery`. */
12421
+ var usePipelineAnalyticsResolveRetrainTrainingCorpus = trpc.pipelineAnalytics.resolveRetrainTrainingCorpus.useQuery;
12413
12422
  /** Generated alias around `trpc.pipelineAnalytics.renameRetrainCollection.useMutation`. */
12414
12423
  var usePipelineAnalyticsRenameRetrainCollection = trpc.pipelineAnalytics.renameRetrainCollection.useMutation;
12415
12424
  /** Generated alias around `trpc.pipelineAnalytics.deleteRetrainCollection.useMutation`. */
@@ -13176,22 +13185,14 @@ var useTerminalSessionWriteInput = trpc.terminalSession.writeInput.useMutation;
13176
13185
  var useTerminalSessionClose = trpc.terminalSession.close.useMutation;
13177
13186
  /** Generated alias around `trpc.toast.onToast.useSubscription`. */
13178
13187
  var useToastOnToast = trpc.toast.onToast.useSubscription;
13179
- /** Generated alias around `trpc.training.putDatasetVersion.useMutation`. */
13180
- var useTrainingPutDatasetVersion = trpc.training.putDatasetVersion.useMutation;
13181
- /** Generated alias around `trpc.training.getDatasetVersion.useQuery`. */
13182
- var useTrainingGetDatasetVersion = trpc.training.getDatasetVersion.useQuery;
13183
- /** Generated alias around `trpc.training.listDatasetVersions.useQuery`. */
13184
- var useTrainingListDatasetVersions = trpc.training.listDatasetVersions.useQuery;
13185
- /** Generated alias around `trpc.training.findDatasetVersionIdByName.useQuery`. */
13186
- var useTrainingFindDatasetVersionIdByName = trpc.training.findDatasetVersionIdByName.useQuery;
13187
- /** Generated alias around `trpc.training.removeDatasetVersion.useMutation`. */
13188
- var useTrainingRemoveDatasetVersion = trpc.training.removeDatasetVersion.useMutation;
13189
13188
  /** Generated alias around `trpc.training.listBaseModels.useQuery`. */
13190
13189
  var useTrainingListBaseModels = trpc.training.listBaseModels.useQuery;
13191
13190
  /** Generated alias around `trpc.training.planJob.useQuery`. */
13192
13191
  var useTrainingPlanJob = trpc.training.planJob.useQuery;
13193
13192
  /** Generated alias around `trpc.training.startJob.useMutation`. */
13194
13193
  var useTrainingStartJob = trpc.training.startJob.useMutation;
13194
+ /** Generated alias around `trpc.training.startJobBatch.useMutation`. */
13195
+ var useTrainingStartJobBatch = trpc.training.startJobBatch.useMutation;
13195
13196
  /** Generated alias around `trpc.training.listJobs.useQuery`. */
13196
13197
  var useTrainingListJobs = trpc.training.listJobs.useQuery;
13197
13198
  /** Generated alias around `trpc.training.getJob.useQuery`. */
@@ -25747,7 +25748,7 @@ function DialogTrigger({ children, ...props }) {
25747
25748
  * whenever they are asymmetric (they are: ~59px top vs ~34px bottom). Every
25748
25749
  * term collapses to the previous `100dvh - 2rem` where the insets are 0.
25749
25750
  */
25750
- var contentVariants = cva("fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 m-0 w-[calc(100vw-2rem)] bg-background-elevated text-foreground border border-border rounded-lg p-4 backdrop:bg-black/50 backdrop:backdrop-blur-sm max-h-[calc(100dvh-2rem-2*max(env(safe-area-inset-top),env(safe-area-inset-bottom)))] [&:not([open])]:hidden", {
25751
+ var contentVariants = cva("relative fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 m-0 w-[calc(100vw-2rem)] bg-background-elevated text-foreground border border-border rounded-lg p-4 backdrop:bg-black/50 backdrop:backdrop-blur-sm max-h-[calc(100dvh-2rem-2*max(env(safe-area-inset-top),env(safe-area-inset-bottom)))] [&:not([open])]:hidden", {
25751
25752
  variants: {
25752
25753
  width: {
25753
25754
  sm: "max-w-sm",
@@ -25826,7 +25827,7 @@ var DialogContent = (0, react$1.forwardRef)(({ className, width, placement, scro
25826
25827
  if (open && !el.open) el.showModal();
25827
25828
  if (!open && el.open) el.close();
25828
25829
  }, [open, dialogRef]);
25829
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dialog", {
25830
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dialog", {
25830
25831
  ref: dialogRef,
25831
25832
  id: contentId,
25832
25833
  className: cn(contentVariants({
@@ -25836,7 +25837,15 @@ var DialogContent = (0, react$1.forwardRef)(({ className, width, placement, scro
25836
25837
  }), className),
25837
25838
  onClose: () => setOpen(false),
25838
25839
  ...props,
25839
- children
25840
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconButton, {
25841
+ type: "button",
25842
+ variant: "ghost",
25843
+ size: "sm",
25844
+ icon: X,
25845
+ "aria-label": "Close",
25846
+ className: "absolute right-4 top-4 z-10 shrink-0",
25847
+ onClick: () => setOpen(false)
25848
+ }), children]
25840
25849
  });
25841
25850
  });
25842
25851
  DialogContent.displayName = "DialogContent";
@@ -25845,7 +25854,7 @@ DialogContent.displayName = "DialogContent";
25845
25854
  * ground, or a long form squeezes its own title to nothing. */
25846
25855
  function DialogHeader({ className, ...props }) {
25847
25856
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
25848
- className: cn("flex flex-col gap-1 mb-3 shrink-0", className),
25857
+ className: cn("flex flex-col gap-1 mb-3 shrink-0 pr-10", className),
25849
25858
  ...props
25850
25859
  });
25851
25860
  }
@@ -31824,6 +31833,7 @@ function Popover({ children, open: controlledOpen, onOpenChange }) {
31824
31833
  const open = controlledOpen ?? uncontrolledOpen;
31825
31834
  const triggerId = (0, react$1.useId)();
31826
31835
  const contentId = (0, react$1.useId)();
31836
+ const triggerRef = (0, react$1.useRef)(null);
31827
31837
  const setOpen = (0, react$1.useCallback)((next) => {
31828
31838
  onOpenChange?.(next);
31829
31839
  if (controlledOpen === void 0) setUncontrolledOpen(next);
@@ -31833,7 +31843,8 @@ function Popover({ children, open: controlledOpen, onOpenChange }) {
31833
31843
  open,
31834
31844
  setOpen,
31835
31845
  triggerId,
31836
- contentId
31846
+ contentId,
31847
+ triggerRef
31837
31848
  },
31838
31849
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
31839
31850
  className: "relative inline-block",
@@ -31842,9 +31853,10 @@ function Popover({ children, open: controlledOpen, onOpenChange }) {
31842
31853
  });
31843
31854
  }
31844
31855
  function PopoverTrigger({ children, ...props }) {
31845
- const { open, setOpen, triggerId, contentId } = usePopoverContext();
31856
+ const { open, setOpen, triggerId, contentId, triggerRef } = usePopoverContext();
31846
31857
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
31847
31858
  type: "button",
31859
+ ref: triggerRef,
31848
31860
  id: triggerId,
31849
31861
  "aria-haspopup": "dialog",
31850
31862
  "aria-expanded": open,
@@ -31854,15 +31866,46 @@ function PopoverTrigger({ children, ...props }) {
31854
31866
  children
31855
31867
  });
31856
31868
  }
31857
- function PopoverContent({ className, children, ...props }) {
31858
- const { open, setOpen, contentId, triggerId } = usePopoverContext();
31869
+ function PopoverContent({ className, children, align = "start", offset = 4, ...props }) {
31870
+ const { open, setOpen, contentId, triggerId, triggerRef } = usePopoverContext();
31859
31871
  const isMobile = useIsMobile();
31860
31872
  const ref = (0, react$1.useRef)(null);
31873
+ const [coords, setCoords] = (0, react$1.useState)(null);
31874
+ (0, react$1.useLayoutEffect)(() => {
31875
+ if (!open || isMobile) {
31876
+ setCoords(null);
31877
+ return;
31878
+ }
31879
+ const compute = () => {
31880
+ const trigger = triggerRef.current;
31881
+ if (!trigger) return;
31882
+ const rect = trigger.getBoundingClientRect();
31883
+ const left = align === "end" ? rect.right : rect.left;
31884
+ setCoords({
31885
+ top: rect.bottom + offset,
31886
+ left,
31887
+ minWidth: rect.width
31888
+ });
31889
+ };
31890
+ compute();
31891
+ window.addEventListener("resize", compute);
31892
+ window.addEventListener("scroll", compute, true);
31893
+ return () => {
31894
+ window.removeEventListener("resize", compute);
31895
+ window.removeEventListener("scroll", compute, true);
31896
+ };
31897
+ }, [
31898
+ open,
31899
+ isMobile,
31900
+ align,
31901
+ offset,
31902
+ triggerRef
31903
+ ]);
31861
31904
  (0, react$1.useEffect)(() => {
31862
31905
  if (!open || isMobile) return;
31863
31906
  const handler = (e) => {
31864
31907
  const el = ref.current;
31865
- const trigger = document.getElementById(triggerId);
31908
+ const trigger = triggerRef.current;
31866
31909
  if (el && !el.contains(e.target) && !trigger?.contains(e.target)) setOpen(false);
31867
31910
  };
31868
31911
  const escHandler = (e) => {
@@ -31877,7 +31920,7 @@ function PopoverContent({ className, children, ...props }) {
31877
31920
  }, [
31878
31921
  open,
31879
31922
  setOpen,
31880
- triggerId,
31923
+ triggerRef,
31881
31924
  isMobile
31882
31925
  ]);
31883
31926
  if (!open) return null;
@@ -31886,15 +31929,22 @@ function PopoverContent({ className, children, ...props }) {
31886
31929
  onClose: () => setOpen(false),
31887
31930
  children
31888
31931
  });
31889
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
31932
+ if (!coords || typeof document === "undefined") return null;
31933
+ return (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
31890
31934
  ref,
31891
31935
  id: contentId,
31892
31936
  role: "dialog",
31893
31937
  "aria-labelledby": triggerId,
31894
- className: cn("absolute left-0 top-full z-50 mt-1 bg-background-elevated border border-border rounded-lg shadow-lg p-3", className),
31938
+ style: {
31939
+ position: "fixed",
31940
+ top: coords.top,
31941
+ ...align === "end" ? { right: window.innerWidth - coords.left } : { left: coords.left },
31942
+ minWidth: coords.minWidth
31943
+ },
31944
+ className: cn("z-50 bg-background-elevated border border-border rounded-lg shadow-lg p-3", className),
31895
31945
  ...props,
31896
31946
  children
31897
- });
31947
+ }), document.body);
31898
31948
  }
31899
31949
  //#endregion
31900
31950
  //#region src/primitives/tabs.tsx
@@ -32702,6 +32752,90 @@ function NetworkLinkBadge({ status, className }) {
32702
32752
  });
32703
32753
  }
32704
32754
  //#endregion
32755
+ //#region src/composites/node-color.ts
32756
+ /** Full class strings so Tailwind v4 JIT retains every node palette utility. */
32757
+ var NODE_BG_CLASS = {
32758
+ "node-a": "bg-node-a",
32759
+ "node-b": "bg-node-b",
32760
+ "node-c": "bg-node-c",
32761
+ "node-d": "bg-node-d",
32762
+ "node-e": "bg-node-e",
32763
+ "node-f": "bg-node-f",
32764
+ "node-g": "bg-node-g",
32765
+ "node-h": "bg-node-h"
32766
+ };
32767
+ var NODE_TEXT_CLASS = {
32768
+ "node-a": "text-node-a",
32769
+ "node-b": "text-node-b",
32770
+ "node-c": "text-node-c",
32771
+ "node-d": "text-node-d",
32772
+ "node-e": "text-node-e",
32773
+ "node-f": "text-node-f",
32774
+ "node-g": "text-node-g",
32775
+ "node-h": "text-node-h"
32776
+ };
32777
+ function nodeColorClass(id) {
32778
+ return NODE_BG_CLASS[id];
32779
+ }
32780
+ function nodeTextColorClass(id) {
32781
+ return NODE_TEXT_CLASS[id];
32782
+ }
32783
+ //#endregion
32784
+ //#region src/composites/role-node-pill.tsx
32785
+ /** Full class strings so Tailwind v4 JIT retains node palette opacity utilities. */
32786
+ var NODE_BG_SOFT_CLASS = {
32787
+ "node-a": "bg-node-a/12",
32788
+ "node-b": "bg-node-b/12",
32789
+ "node-c": "bg-node-c/12",
32790
+ "node-d": "bg-node-d/12",
32791
+ "node-e": "bg-node-e/12",
32792
+ "node-f": "bg-node-f/12",
32793
+ "node-g": "bg-node-g/12",
32794
+ "node-h": "bg-node-h/12"
32795
+ };
32796
+ var NODE_BG_EMPHASIZED_CLASS = {
32797
+ "node-a": "bg-node-a/22",
32798
+ "node-b": "bg-node-b/22",
32799
+ "node-c": "bg-node-c/22",
32800
+ "node-d": "bg-node-d/22",
32801
+ "node-e": "bg-node-e/22",
32802
+ "node-f": "bg-node-f/22",
32803
+ "node-g": "bg-node-g/22",
32804
+ "node-h": "bg-node-h/22"
32805
+ };
32806
+ var NODE_RING_CLASS = {
32807
+ "node-a": "ring-node-a/45",
32808
+ "node-b": "ring-node-b/45",
32809
+ "node-c": "ring-node-c/45",
32810
+ "node-d": "ring-node-d/45",
32811
+ "node-e": "ring-node-e/45",
32812
+ "node-f": "ring-node-f/45",
32813
+ "node-g": "ring-node-g/45",
32814
+ "node-h": "ring-node-h/45"
32815
+ };
32816
+ function RoleNodePill({ roleLabel, nodeName, colorId, emphasized = false, pinned = false }) {
32817
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
32818
+ "data-testid": "role-node-pill",
32819
+ title: pinned ? `${roleLabel} pinned on ${nodeName}` : `${roleLabel} on ${nodeName}`,
32820
+ className: cn("inline-flex max-w-full items-center gap-1 rounded-full px-2 py-0.5 text-[10px] leading-tight ring-1 ring-inset", emphasized ? cn("role-node-pill-emphasized font-semibold ring-2", NODE_BG_EMPHASIZED_CLASS[colorId], NODE_RING_CLASS[colorId], nodeTextColorClass(colorId)) : cn("font-medium text-foreground-muted ring-border/60", NODE_BG_SOFT_CLASS[colorId])),
32821
+ children: [
32822
+ pinned && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pin, {
32823
+ className: "h-2.5 w-2.5 shrink-0 opacity-80",
32824
+ "aria-label": "pinned"
32825
+ }),
32826
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
32827
+ className: "shrink-0",
32828
+ children: roleLabel
32829
+ }),
32830
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
32831
+ className: cn("min-w-0 truncate", emphasized ? nodeTextColorClass(colorId) : "text-foreground-subtle"),
32832
+ children: nodeName
32833
+ }),
32834
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: cn("h-1.5 w-1.5 shrink-0 rounded-full", nodeColorClass(colorId)) })
32835
+ ]
32836
+ });
32837
+ }
32838
+ //#endregion
32705
32839
  //#region src/composites/breadcrumb.tsx
32706
32840
  /**
32707
32841
  * Breadcrumb navigation component.
@@ -37639,6 +37773,141 @@ function HubSessionTestCard({ trpc, serverUrl, deviceId, cameraField, runMs = HU
37639
37773
  });
37640
37774
  }
37641
37775
  //#endregion
37776
+ //#region src/composites/training/root-detector-placements.ts
37777
+ /**
37778
+ * Pure mapper: per-node inference devices → placements of each effective root
37779
+ * detector model. Training's base-model picker lists every `node · device`
37780
+ * where a trainable base is the cluster's object-detection root.
37781
+ *
37782
+ * Mirrors Model Studio's `acceleratorsRunningModel` decision (effective model
37783
+ * via {@link resolveEffectiveStepModel}) but aggregates across nodes and does
37784
+ * not gate on on-disk currency — "in use" here means the root the node would
37785
+ * run. ui-library must not import addon-model-studio; a sync guard can later
37786
+ * hold the two pure paths equal.
37787
+ */
37788
+ /** Root detection step — the only step whose models are trainable bases. */
37789
+ var ROOT_DETECTOR_STEP_ID = "object-detection";
37790
+ function comparePlacement(a, b) {
37791
+ const byNode = a.nodeId.localeCompare(b.nodeId);
37792
+ if (byNode !== 0) return byNode;
37793
+ const byLabel = a.label.localeCompare(b.label);
37794
+ if (byLabel !== 0) return byLabel;
37795
+ return a.deviceKey.localeCompare(b.deviceKey);
37796
+ }
37797
+ /**
37798
+ * For each modelId that is the effective root on at least one enabled device,
37799
+ * the full list of placements (sorted by node, then device label).
37800
+ */
37801
+ function mapRootDetectorPlacements(nodes, stepId = ROOT_DETECTOR_STEP_ID) {
37802
+ const buckets = /* @__PURE__ */ new Map();
37803
+ for (const node of nodes) for (const device of node.devices) {
37804
+ if (!device.enabled) continue;
37805
+ if (!stepHasModelForFormat(node.catalog.models, device.format)) continue;
37806
+ const effective = resolveEffectiveStepModel({
37807
+ catalog: node.catalog,
37808
+ device,
37809
+ base: device.steps?.[stepId]?.modelId
37810
+ });
37811
+ if (effective === void 0) continue;
37812
+ const list = buckets.get(effective) ?? [];
37813
+ list.push({
37814
+ nodeId: node.nodeId,
37815
+ deviceKey: device.key,
37816
+ label: acceleratorShortLabel(device)
37817
+ });
37818
+ buckets.set(effective, list);
37819
+ }
37820
+ const out = /* @__PURE__ */ new Map();
37821
+ for (const [modelId, list] of buckets) out.set(modelId, [...list].toSorted(comparePlacement));
37822
+ return out;
37823
+ }
37824
+ /** Model ids that appear as an effective root somewhere in the cluster. */
37825
+ function clusterRootModelIds(placements) {
37826
+ return [...placements.keys()].toSorted((a, b) => a.localeCompare(b));
37827
+ }
37828
+ /**
37829
+ * Intersection of listed trainable models and cluster root detectors — the
37830
+ * Select-all-roots action. Order follows `trainableModelIds`.
37831
+ */
37832
+ function defaultSelectClusterRoots(trainableModelIds, clusterRootIds) {
37833
+ const roots = new Set(clusterRootIds);
37834
+ return trainableModelIds.filter((id) => roots.has(id));
37835
+ }
37836
+ //#endregion
37837
+ //#region src/composites/training/TrainingBaseModelPicker.tsx
37838
+ var EMPTY_PLACEMENTS = "Not in use on any node";
37839
+ function placementLine(placement) {
37840
+ return `${placement.nodeId} · ${placement.label}`;
37841
+ }
37842
+ function toggleModel(selected, modelId, checked) {
37843
+ if (checked) {
37844
+ if (selected.includes(modelId)) return selected;
37845
+ return [...selected, modelId];
37846
+ }
37847
+ return selected.filter((id) => id !== modelId);
37848
+ }
37849
+ /**
37850
+ * Multi-select of trainable base models with full multi-placement listing and
37851
+ * Select-all-roots / Clear over cluster root detectors.
37852
+ */
37853
+ function TrainingBaseModelPicker({ models, clusterRootModelIds, value, onChange, disabled = false }) {
37854
+ const selected = new Set(value);
37855
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
37856
+ className: "space-y-2",
37857
+ "data-testid": "training-base-model-picker",
37858
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
37859
+ className: "flex flex-wrap items-center gap-1.5",
37860
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
37861
+ type: "button",
37862
+ variant: "secondary",
37863
+ size: "sm",
37864
+ disabled,
37865
+ onClick: () => onChange(defaultSelectClusterRoots(models.map((m) => m.modelId), clusterRootModelIds)),
37866
+ children: "Select all roots"
37867
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
37868
+ type: "button",
37869
+ variant: "ghost",
37870
+ size: "sm",
37871
+ disabled: disabled || value.length === 0,
37872
+ onClick: () => onChange([]),
37873
+ children: "Clear"
37874
+ })]
37875
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
37876
+ className: "divide-y divide-border-subtle rounded-md border border-border bg-surface",
37877
+ children: models.map((model) => {
37878
+ const checked = selected.has(model.modelId);
37879
+ const label = model.recommended ? `${model.label} (recommended)` : model.label;
37880
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
37881
+ className: "px-2 py-2 sm:px-3",
37882
+ "data-testid": `training-base-model-${model.modelId}`,
37883
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
37884
+ className: "flex min-w-0 cursor-pointer items-start gap-2",
37885
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Checkbox, {
37886
+ className: "mt-0.5",
37887
+ checked,
37888
+ disabled,
37889
+ "aria-label": model.label,
37890
+ onChange: (event) => onChange(toggleModel(value, model.modelId, event.target.checked))
37891
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
37892
+ className: "min-w-0 flex-1 space-y-1",
37893
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
37894
+ className: "block text-sm text-foreground",
37895
+ children: label
37896
+ }), model.placements.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
37897
+ className: cn(TEXT_HINT, "block"),
37898
+ children: EMPTY_PLACEMENTS
37899
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
37900
+ className: cn(TEXT_HINT, "flex flex-wrap gap-x-2 gap-y-0.5"),
37901
+ children: model.placements.map((p) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: placementLine(p) }, `${p.nodeId}:${p.deviceKey}`))
37902
+ })]
37903
+ })]
37904
+ })
37905
+ }, model.modelId);
37906
+ })
37907
+ })]
37908
+ });
37909
+ }
37910
+ //#endregion
37642
37911
  //#region src/composites/cap-settings/scene-monitor-copy.ts
37643
37912
  /** The lighting variants an operator is OFFERED. The resolver can also report
37644
37913
  * `night`, `dawn` and `dusk`; those are shown when present but never demanded,
@@ -57627,7 +57896,8 @@ function KebabMenu({ items, header, triggerClassName, title = "More actions" })
57627
57896
  className: cn("inline-flex items-center justify-center rounded-lg p-2", "text-foreground-subtle hover:text-foreground hover:bg-surface-hover", "border border-transparent transition-colors", triggerClassName),
57628
57897
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EllipsisVertical, { className: "h-4 w-4" })
57629
57898
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(PopoverContent, {
57630
- className: "left-auto right-0 mt-1 min-w-[200px] p-1",
57899
+ align: "end",
57900
+ className: "min-w-[200px] p-1",
57631
57901
  children: [header && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
57632
57902
  className: "px-2 py-1 text-[10px] uppercase tracking-wider text-foreground-subtle",
57633
57903
  children: header
@@ -58116,6 +58386,208 @@ function ProviderBadge({ provider, showLabel = true, className }) {
58116
58386
  });
58117
58387
  }
58118
58388
  //#endregion
58389
+ //#region src/composites/provider-entries/AddProviderEntryDialog.tsx
58390
+ /**
58391
+ * AddProviderEntryDialog — create one credential entry for a provider type.
58392
+ *
58393
+ * The host supplies the creatable types (`describeTypes`); the dialog never
58394
+ * invents them. Submit hands `{ typeId, name }` to `onCreate` — credentials
58395
+ * and settings live on the entry body after create (Task 11).
58396
+ */
58397
+ function AddProviderEntryDialog({ open, onOpenChange, types, onCreate, submitting = false, title = "Add provider entry", description = "Pick a provider type and name this credential set." }) {
58398
+ const typeFieldId = (0, react$1.useId)();
58399
+ const nameFieldId = (0, react$1.useId)();
58400
+ const [typeId, setTypeId] = (0, react$1.useState)("");
58401
+ const [name, setName] = (0, react$1.useState)("");
58402
+ (0, react$1.useEffect)(() => {
58403
+ if (!open) return;
58404
+ setTypeId(types[0]?.typeId ?? "");
58405
+ setName("");
58406
+ }, [open, types]);
58407
+ const canSubmit = typeId !== "" && name.trim().length > 0 && !submitting && types.length > 0;
58408
+ const handleSubmit = () => {
58409
+ if (!canSubmit) return;
58410
+ onCreate({
58411
+ typeId,
58412
+ name: name.trim()
58413
+ });
58414
+ };
58415
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Dialog, {
58416
+ open,
58417
+ onOpenChange: (next) => !submitting && onOpenChange(next),
58418
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(DialogContent, {
58419
+ width: "sm",
58420
+ placement: "sheet-on-mobile",
58421
+ scroll: "body",
58422
+ children: [
58423
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DialogTitle, { children: title }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DialogDescription, { children: description })] }),
58424
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DialogBody, {
58425
+ className: "space-y-3",
58426
+ children: types.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
58427
+ className: "text-xs text-foreground-subtle",
58428
+ children: "No provider types are available yet. Install a training provider addon first."
58429
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
58430
+ className: "space-y-1",
58431
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Label, {
58432
+ htmlFor: typeFieldId,
58433
+ children: "Provider type"
58434
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
58435
+ className: "flex items-center gap-2",
58436
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TypeIcon, { url: types.find((t) => t.typeId === typeId)?.iconUrl ?? null }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Select, {
58437
+ id: typeFieldId,
58438
+ "aria-label": "Provider type",
58439
+ className: "flex-1",
58440
+ value: typeId,
58441
+ onChange: (event) => setTypeId(event.target.value),
58442
+ options: types.map((t) => ({
58443
+ value: t.typeId,
58444
+ label: t.label
58445
+ })),
58446
+ disabled: submitting
58447
+ })]
58448
+ })]
58449
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
58450
+ className: "space-y-1",
58451
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Label, {
58452
+ htmlFor: nameFieldId,
58453
+ children: "Name"
58454
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Input, {
58455
+ id: nameFieldId,
58456
+ "aria-label": "Name",
58457
+ value: name,
58458
+ onChange: (event) => setName(event.target.value),
58459
+ placeholder: "Production",
58460
+ disabled: submitting,
58461
+ onKeyDown: (event) => {
58462
+ if (event.key === "Enter") {
58463
+ event.preventDefault();
58464
+ handleSubmit();
58465
+ }
58466
+ }
58467
+ })]
58468
+ })] })
58469
+ }),
58470
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(DialogFooter, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
58471
+ type: "button",
58472
+ variant: "ghost",
58473
+ size: "sm",
58474
+ disabled: submitting,
58475
+ onClick: () => onOpenChange(false),
58476
+ children: "Cancel"
58477
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Button, {
58478
+ type: "button",
58479
+ size: "sm",
58480
+ disabled: !canSubmit,
58481
+ onClick: handleSubmit,
58482
+ children: [submitting && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LoaderCircle, {
58483
+ className: "h-3.5 w-3.5 animate-spin",
58484
+ "aria-hidden": true
58485
+ }), "Create"]
58486
+ })] })
58487
+ ]
58488
+ })
58489
+ });
58490
+ }
58491
+ function TypeIcon({ url }) {
58492
+ if (url === null) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
58493
+ className: cn("inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-md", "border border-border bg-surface text-[10px] text-foreground-subtle"),
58494
+ "aria-hidden": true,
58495
+ children: "?"
58496
+ });
58497
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
58498
+ src: url,
58499
+ alt: "",
58500
+ className: "h-7 w-7 shrink-0 rounded-md border border-border bg-surface object-contain p-0.5"
58501
+ });
58502
+ }
58503
+ //#endregion
58504
+ //#region src/composites/provider-entries/ProviderEntryPills.tsx
58505
+ /**
58506
+ * ProviderEntryPills — one pill per credential entry (never a bare type).
58507
+ *
58508
+ * Visual language echoes the admin IntegrationHub strip: icon + name + status
58509
+ * dot, wrapping at every width. Selection is a button callback — the host
58510
+ * owns the URL (`?entry=`). Add is optional; when present it is a dashed
58511
+ * trailing control that opens the host's create dialog.
58512
+ */
58513
+ var PILL_BASE = cn(CHIP_BASE, "min-w-0 max-w-full gap-1.5 py-1 pl-1 pr-2.5 text-xs font-normal", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40");
58514
+ var PILL_CURRENT = cn(CHIP_ACTIVE, "font-medium");
58515
+ var PILL_OTHER = CHIP_INACTIVE;
58516
+ var STATE_DOT = {
58517
+ ok: "bg-success",
58518
+ warning: "bg-warning",
58519
+ error: "bg-danger",
58520
+ unknown: "border border-foreground-subtle bg-transparent"
58521
+ };
58522
+ var STATE_LABEL = {
58523
+ ok: "OK",
58524
+ warning: "Warning",
58525
+ error: "Error",
58526
+ unknown: "Unknown"
58527
+ };
58528
+ function ProviderEntryPills({ label, entries, selectedEntryId, onSelect, onAdd, addLabel = "Add provider" }) {
58529
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("nav", {
58530
+ "aria-label": label,
58531
+ className: "min-w-0",
58532
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
58533
+ className: "flex min-w-0 flex-wrap items-center gap-1.5",
58534
+ children: [entries.map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EntryPill, {
58535
+ entry,
58536
+ current: entry.entryId === selectedEntryId,
58537
+ onSelect
58538
+ }, entry.entryId)), onAdd !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
58539
+ type: "button",
58540
+ onClick: onAdd,
58541
+ className: cn(PILL_BASE, "border-dashed border-border pl-2 text-foreground-subtle", "hover:border-primary/50 hover:text-foreground"),
58542
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Plus, {
58543
+ className: "h-3.5 w-3.5 shrink-0",
58544
+ "aria-hidden": true
58545
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
58546
+ className: "truncate",
58547
+ children: addLabel
58548
+ })]
58549
+ })]
58550
+ })
58551
+ });
58552
+ }
58553
+ function EntryPill({ entry, current, onSelect }) {
58554
+ const quiet = entry.status === "ok";
58555
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
58556
+ type: "button",
58557
+ "aria-current": current ? "true" : void 0,
58558
+ "data-testid": `provider-entry-pill-${entry.entryId}`,
58559
+ onClick: () => onSelect(entry.entryId),
58560
+ className: cn(PILL_BASE, current ? PILL_CURRENT : PILL_OTHER),
58561
+ children: [
58562
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EntryIcon, { url: entry.iconUrl }),
58563
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
58564
+ className: "truncate",
58565
+ children: entry.name
58566
+ }),
58567
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
58568
+ className: cn("h-1.5 w-1.5 shrink-0 rounded-full", STATE_DOT[entry.status]),
58569
+ "aria-hidden": true
58570
+ }),
58571
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
58572
+ className: quiet ? "sr-only" : "shrink-0 text-[10px] font-normal text-foreground-subtle",
58573
+ children: STATE_LABEL[entry.status]
58574
+ })
58575
+ ]
58576
+ });
58577
+ }
58578
+ function EntryIcon({ url }) {
58579
+ if (url === null) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
58580
+ className: "inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-surface text-[9px] text-foreground-subtle",
58581
+ "aria-hidden": true,
58582
+ children: "?"
58583
+ });
58584
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
58585
+ src: url,
58586
+ alt: "",
58587
+ className: "h-5 w-5 shrink-0 rounded-full object-contain"
58588
+ });
58589
+ }
58590
+ //#endregion
58119
58591
  //#region src/composites/response-log.tsx
58120
58592
  /**
58121
58593
  * Expandable log box showing the raw JSON response from a pipeline run.
@@ -62070,6 +62542,7 @@ var SceneMonitorEditor = (0, react$1.lazy)(() => Promise.resolve().then(() => re
62070
62542
  /** Lazy-wrapped `PrivacyMaskSettings` — code-split off the main bundle. */
62071
62543
  var PrivacyMaskSettings = (0, react$1.lazy)(() => Promise.resolve().then(() => require("./PrivacyMaskSettings-BqjXsXZR.cjs")).then((m) => ({ default: m.PrivacyMaskSettings })));
62072
62544
  //#endregion
62545
+ exports.AddProviderEntryDialog = AddProviderEntryDialog;
62073
62546
  exports.AddonGlobalSettingsForm = AddonGlobalSettingsForm;
62074
62547
  exports.AdminLinkQuickAction = AdminLinkQuickAction;
62075
62548
  exports.AgentStepEditor = AgentStepEditor;
@@ -62261,6 +62734,7 @@ exports.MobileDrawer = MobileDrawer;
62261
62734
  exports.ModelPicker = ModelPicker;
62262
62735
  exports.MotionZonesSettings = MotionZonesSettings;
62263
62736
  exports.NAVIGATION_DRIVE_INTERVAL_MS = NAVIGATION_DRIVE_INTERVAL_MS;
62737
+ exports.NODE_COLOR_IDS = _camstack_types.NODE_COLOR_IDS;
62264
62738
  exports.NatResultCard = NatResultCard;
62265
62739
  exports.NavigationPanel = NavigationPanel;
62266
62740
  exports.NetworkLinkBadge = NetworkLinkBadge;
@@ -62288,6 +62762,7 @@ exports.PRIORITY = PRIORITY;
62288
62762
  exports.PTZOverlay = PTZOverlay;
62289
62763
  exports.PageHeader = PageHeader;
62290
62764
  exports.PageSizeSelect = PageSizeSelect;
62765
+ exports.Pagination = Pagination;
62291
62766
  exports.PasswordInput = PasswordInput;
62292
62767
  exports.PhaseIcon = PhaseIcon;
62293
62768
  exports.PipelineBuilder = PipelineBuilder;
@@ -62302,6 +62777,7 @@ exports.PopoverTrigger = PopoverTrigger;
62302
62777
  exports.PrimaryChildPicker = PrimaryChildPicker;
62303
62778
  exports.PrivacyMaskSettings = PrivacyMaskSettings;
62304
62779
  exports.ProviderBadge = ProviderBadge;
62780
+ exports.ProviderEntryPills = ProviderEntryPills;
62305
62781
  exports.PtzPanel = PtzPanel;
62306
62782
  exports.QrCode = QrCode;
62307
62783
  exports.RECONNECT_POLICY = RECONNECT_POLICY;
@@ -62309,12 +62785,14 @@ exports.RECORDED_PLAYBACK_MODES = RECORDED_PLAYBACK_MODES;
62309
62785
  exports.RIGHT = RIGHT;
62310
62786
  exports.ROI_AREA_WARN_FRACTION = ROI_AREA_WARN_FRACTION;
62311
62787
  exports.ROLE_DESCRIPTOR = ROLE_DESCRIPTOR;
62788
+ exports.ROOT_DETECTOR_STEP_ID = ROOT_DETECTOR_STEP_ID;
62312
62789
  exports.RadialGauge = RadialGauge;
62313
62790
  exports.RecordedPlaybackProvider = RecordedPlaybackProvider;
62314
62791
  exports.RecordingPanel = RecordingPanel;
62315
62792
  exports.ResponseLog = ResponseLog;
62316
62793
  exports.RoleDisplayDefaultsFromServer = RoleDisplayDefaultsFromServer;
62317
62794
  exports.RoleDisplayDefaultsProvider = RoleDisplayDefaultsProvider;
62795
+ exports.RoleNodePill = RoleNodePill;
62318
62796
  exports.RootModelSourceControl = RootModelSourceControl;
62319
62797
  exports.RootSuppliedModelNote = RootSuppliedModelNote;
62320
62798
  exports.RotateCcw = RotateCcw;
@@ -62397,6 +62875,7 @@ exports.TimezoneSelector = TimezoneSelector;
62397
62875
  exports.Tooltip = Tooltip;
62398
62876
  exports.TooltipContent = TooltipContent;
62399
62877
  exports.TooltipTrigger = TooltipTrigger;
62878
+ exports.TrainingBaseModelPicker = TrainingBaseModelPicker;
62400
62879
  exports.TrainingCollectionPicker = TrainingCollectionPicker;
62401
62880
  exports.Trash2 = Trash2;
62402
62881
  exports.UnitPicker = UnitPicker;
@@ -62423,6 +62902,7 @@ exports.allDeviceTypeFilterOptions = allDeviceTypeFilterOptions;
62423
62902
  exports.applyFleetQueryDefaults = applyFleetQueryDefaults;
62424
62903
  exports.applyPickerFilters = applyPickerFilters;
62425
62904
  exports.ariaSortForColumn = ariaSortForColumn;
62905
+ exports.assignNodeColorId = _camstack_types.assignNodeColorId;
62426
62906
  exports.badgeFor = badgeFor;
62427
62907
  exports.badgeFor$1 = badgeFor;
62428
62908
  exports.bindsToModel = bindsToModel;
@@ -62436,9 +62916,11 @@ exports.classifyAddressScope = classifyAddressScope;
62436
62916
  exports.classifyCapability = classifyCapability;
62437
62917
  exports.classifySessionVerdict = classifySessionVerdict;
62438
62918
  exports.clearPickerGroup = clearPickerGroup;
62919
+ exports.clusterRootModelIds = clusterRootModelIds;
62439
62920
  exports.cn = cn;
62440
62921
  exports.columnsForContext = columnsForContext;
62441
62922
  exports.compareSrflxMappings = compareSrflxMappings;
62923
+ exports.computePageButtons = computePageButtons;
62442
62924
  exports.containerChildToRef = containerChildToRef;
62443
62925
  exports.countableDevices = countableDevices;
62444
62926
  exports.coverHighlight = coverHighlight;
@@ -62452,6 +62934,7 @@ exports.darkColors = require_theme_index.darkColors$1;
62452
62934
  exports.dataTableFacetGroups = dataTableFacetGroups;
62453
62935
  exports.dataTableFacets = dataTableFacets;
62454
62936
  exports.defaultOfField = defaultOfField;
62937
+ exports.defaultSelectClusterRoots = defaultSelectClusterRoots;
62455
62938
  exports.defaultTheme = require_theme_index.defaultTheme$1;
62456
62939
  exports.deriveDeviceKind = deriveDeviceKind;
62457
62940
  exports.deriveWebrtcDebugStats = deriveWebrtcDebugStats;
@@ -62515,6 +62998,7 @@ exports.lawnMowerActivityMeta = lawnMowerActivityMeta;
62515
62998
  exports.lightColors = require_theme_index.lightColors$1;
62516
62999
  exports.loadRemoteBundle = loadRemoteBundle;
62517
63000
  exports.makeScrubBridge = makeScrubBridge;
63001
+ exports.mapRootDetectorPlacements = mapRootDetectorPlacements;
62518
63002
  exports.metadataEntries = metadataEntries;
62519
63003
  exports.metadataString = metadataString;
62520
63004
  exports.mirror = mirror;
@@ -62525,6 +63009,8 @@ exports.nextReconnectAction = nextReconnectAction;
62525
63009
  exports.nextSort = nextSort;
62526
63010
  exports.nextSortDirection = nextSortDirection;
62527
63011
  exports.nextTableSort = nextTableSort;
63012
+ exports.nodeColorClass = nodeColorClass;
63013
+ exports.nodeTextColorClass = nodeTextColorClass;
62528
63014
  exports.normalizeForSearch = normalizeForSearch;
62529
63015
  exports.offListSelections = offListSelections;
62530
63016
  exports.openTopLayer = openTopLayer;
@@ -63287,10 +63773,8 @@ exports.usePipelineAnalyticsCompleteRetrainTrack = usePipelineAnalyticsCompleteR
63287
63773
  exports.usePipelineAnalyticsCountRelocatableMedia = usePipelineAnalyticsCountRelocatableMedia;
63288
63774
  exports.usePipelineAnalyticsCountUnstampedEventMedia = usePipelineAnalyticsCountUnstampedEventMedia;
63289
63775
  exports.usePipelineAnalyticsCreateRetrainCollection = usePipelineAnalyticsCreateRetrainCollection;
63290
- exports.usePipelineAnalyticsCreateRetrainDatasetVersion = usePipelineAnalyticsCreateRetrainDatasetVersion;
63291
63776
  exports.usePipelineAnalyticsDeleteDeviceEvents = usePipelineAnalyticsDeleteDeviceEvents;
63292
63777
  exports.usePipelineAnalyticsDeleteRetrainCollection = usePipelineAnalyticsDeleteRetrainCollection;
63293
- exports.usePipelineAnalyticsDeleteRetrainDatasetVersion = usePipelineAnalyticsDeleteRetrainDatasetVersion;
63294
63778
  exports.usePipelineAnalyticsDeleteTracks = usePipelineAnalyticsDeleteTracks;
63295
63779
  exports.usePipelineAnalyticsDeselectRetrainFrame = usePipelineAnalyticsDeselectRetrainFrame;
63296
63780
  exports.usePipelineAnalyticsGetActiveTracks = usePipelineAnalyticsGetActiveTracks;
@@ -63308,6 +63792,7 @@ exports.usePipelineAnalyticsGetMediaReclaimStatus = usePipelineAnalyticsGetMedia
63308
63792
  exports.usePipelineAnalyticsGetMotionEvents = usePipelineAnalyticsGetMotionEvents;
63309
63793
  exports.usePipelineAnalyticsGetObjectEmbeddingRebuildStatus = usePipelineAnalyticsGetObjectEmbeddingRebuildStatus;
63310
63794
  exports.usePipelineAnalyticsGetObjectEvents = usePipelineAnalyticsGetObjectEvents;
63795
+ exports.usePipelineAnalyticsGetRetrainCorpusKpi = usePipelineAnalyticsGetRetrainCorpusKpi;
63311
63796
  exports.usePipelineAnalyticsGetRetrainExportUrl = usePipelineAnalyticsGetRetrainExportUrl;
63312
63797
  exports.usePipelineAnalyticsGetRetrainFrameImage = usePipelineAnalyticsGetRetrainFrameImage;
63313
63798
  exports.usePipelineAnalyticsGetSensorEvents = usePipelineAnalyticsGetSensorEvents;
@@ -63328,7 +63813,7 @@ exports.usePipelineAnalyticsListRetrainAnnotations = usePipelineAnalyticsListRet
63328
63813
  exports.usePipelineAnalyticsListRetrainAssistProfiles = usePipelineAnalyticsListRetrainAssistProfiles;
63329
63814
  exports.usePipelineAnalyticsListRetrainCollectionFrames = usePipelineAnalyticsListRetrainCollectionFrames;
63330
63815
  exports.usePipelineAnalyticsListRetrainCollections = usePipelineAnalyticsListRetrainCollections;
63331
- exports.usePipelineAnalyticsListRetrainDatasetVersions = usePipelineAnalyticsListRetrainDatasetVersions;
63816
+ exports.usePipelineAnalyticsListRetrainCorpusPage = usePipelineAnalyticsListRetrainCorpusPage;
63332
63817
  exports.usePipelineAnalyticsListRetrainFrames = usePipelineAnalyticsListRetrainFrames;
63333
63818
  exports.usePipelineAnalyticsListRetrainStaging = usePipelineAnalyticsListRetrainStaging;
63334
63819
  exports.usePipelineAnalyticsListTrackMedia = usePipelineAnalyticsListTrackMedia;
@@ -63337,7 +63822,6 @@ exports.usePipelineAnalyticsListTracks = usePipelineAnalyticsListTracks;
63337
63822
  exports.usePipelineAnalyticsOfferRetrainArchive = usePipelineAnalyticsOfferRetrainArchive;
63338
63823
  exports.usePipelineAnalyticsOwnersWithMedia = usePipelineAnalyticsOwnersWithMedia;
63339
63824
  exports.usePipelineAnalyticsPauseForStorageMigration = usePipelineAnalyticsPauseForStorageMigration;
63340
- exports.usePipelineAnalyticsPreviewRetrainDataset = usePipelineAnalyticsPreviewRetrainDataset;
63341
63825
  exports.usePipelineAnalyticsProposeRetrainAnnotations = usePipelineAnalyticsProposeRetrainAnnotations;
63342
63826
  exports.usePipelineAnalyticsProposeRetrainAnnotationsWithLlm = usePipelineAnalyticsProposeRetrainAnnotationsWithLlm;
63343
63827
  exports.usePipelineAnalyticsPruneEvents = usePipelineAnalyticsPruneEvents;
@@ -63351,6 +63835,7 @@ exports.usePipelineAnalyticsRefreshStorageLocationsForMigration = usePipelineAna
63351
63835
  exports.usePipelineAnalyticsRelocateMedia = usePipelineAnalyticsRelocateMedia;
63352
63836
  exports.usePipelineAnalyticsRemoveRetrainFrameFromCollection = usePipelineAnalyticsRemoveRetrainFrameFromCollection;
63353
63837
  exports.usePipelineAnalyticsRenameRetrainCollection = usePipelineAnalyticsRenameRetrainCollection;
63838
+ exports.usePipelineAnalyticsResolveRetrainTrainingCorpus = usePipelineAnalyticsResolveRetrainTrainingCorpus;
63354
63839
  exports.usePipelineAnalyticsRestageRetrainTrack = usePipelineAnalyticsRestageRetrainTrack;
63355
63840
  exports.usePipelineAnalyticsResumeForStorageMigration = usePipelineAnalyticsResumeForStorageMigration;
63356
63841
  exports.usePipelineAnalyticsSaveRetrainAnnotations = usePipelineAnalyticsSaveRetrainAnnotations;
@@ -63361,7 +63846,6 @@ exports.usePipelineAnalyticsSetTrackFlags = usePipelineAnalyticsSetTrackFlags;
63361
63846
  exports.usePipelineAnalyticsSetTrackPurity = usePipelineAnalyticsSetTrackPurity;
63362
63847
  exports.usePipelineAnalyticsSetTrackRelation = usePipelineAnalyticsSetTrackRelation;
63363
63848
  exports.usePipelineAnalyticsStartStorageMigrationMove = usePipelineAnalyticsStartStorageMigrationMove;
63364
- exports.usePipelineAnalyticsVerifyRetrainDatasetVersion = usePipelineAnalyticsVerifyRetrainDatasetVersion;
63365
63849
  exports.usePipelineAnalyticsWipeAllAnalytics = usePipelineAnalyticsWipeAllAnalytics;
63366
63850
  exports.usePipelineAnalyticsWipeObjectEmbeddings = usePipelineAnalyticsWipeObjectEmbeddings;
63367
63851
  exports.usePipelineAnalyticsWriteRetrainArchive = usePipelineAnalyticsWriteRetrainArchive;
@@ -63749,19 +64233,15 @@ exports.useToastOnToast = useToastOnToast;
63749
64233
  exports.useTrainingCanaryResult = useTrainingCanaryResult;
63750
64234
  exports.useTrainingCancelJob = useTrainingCancelJob;
63751
64235
  exports.useTrainingDiscardResult = useTrainingDiscardResult;
63752
- exports.useTrainingFindDatasetVersionIdByName = useTrainingFindDatasetVersionIdByName;
63753
- exports.useTrainingGetDatasetVersion = useTrainingGetDatasetVersion;
63754
64236
  exports.useTrainingGetJob = useTrainingGetJob;
63755
64237
  exports.useTrainingGetJobResult = useTrainingGetJobResult;
63756
64238
  exports.useTrainingListBaseModels = useTrainingListBaseModels;
63757
- exports.useTrainingListDatasetVersions = useTrainingListDatasetVersions;
63758
64239
  exports.useTrainingListJobs = useTrainingListJobs;
63759
64240
  exports.useTrainingPlanJob = useTrainingPlanJob;
63760
- exports.useTrainingPutDatasetVersion = useTrainingPutDatasetVersion;
63761
64241
  exports.useTrainingRegisterResult = useTrainingRegisterResult;
63762
- exports.useTrainingRemoveDatasetVersion = useTrainingRemoveDatasetVersion;
63763
64242
  exports.useTrainingRollbackCanary = useTrainingRollbackCanary;
63764
64243
  exports.useTrainingStartJob = useTrainingStartJob;
64244
+ exports.useTrainingStartJobBatch = useTrainingStartJobBatch;
63765
64245
  exports.useTurnProviderGetTurnServers = useTurnProviderGetTurnServers;
63766
64246
  exports.useUpdateGetStatus = useUpdateGetStatus;
63767
64247
  exports.useUpdateInstallUpdate = useUpdateInstallUpdate;