@camstack/addon-provider-dreame 0.2.26 → 0.2.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.
Files changed (3) hide show
  1. package/dist/addon.js +432 -50
  2. package/dist/addon.mjs +432 -50
  3. package/package.json +1 -1
package/dist/addon.mjs CHANGED
@@ -56306,6 +56306,13 @@ var BaseAddon = class {
56306
56306
  _readinessGeneration = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2, 14);
56307
56307
  /** Capability names this addon registered at init — used to emit matching `down` events on shutdown. */
56308
56308
  _registeredCapNames = [];
56309
+ /**
56310
+ * True only after `readAddonStore` actually answered. Constructor
56311
+ * defaults look like stored config when the store is down — a forked
56312
+ * addon that auto-starts from those defaults (cloudflare-tunnel quick
56313
+ * mode, 2026-08-25) is not "the operator chose this".
56314
+ */
56315
+ settingsStoreReady = false;
56309
56316
  /** Default config values. Provided via constructor. */
56310
56317
  defaults;
56311
56318
  constructor(defaults) {
@@ -56706,7 +56713,9 @@ var BaseAddon = class {
56706
56713
  ];
56707
56714
  let lastErr;
56708
56715
  for (let attempt = 0; attempt <= delaysMs.length; attempt++) try {
56709
- return await settings.readAddonStore() ?? {};
56716
+ const stored = await settings.readAddonStore() ?? {};
56717
+ this.settingsStoreReady = true;
56718
+ return stored;
56710
56719
  } catch (err) {
56711
56720
  lastErr = err;
56712
56721
  const msg = err instanceof Error ? err.message : String(err);
@@ -56714,6 +56723,7 @@ var BaseAddon = class {
56714
56723
  if (attempt === delaysMs.length) break;
56715
56724
  await new Promise((r) => setTimeout(r, delaysMs[attempt]));
56716
56725
  }
56726
+ this.settingsStoreReady = false;
56717
56727
  this._ctx?.logger?.warn?.("readAddonStore: settings-store unavailable after retries — using defaults", { meta: { error: lastErr instanceof Error ? lastErr.message : String(lastErr) } });
56718
56728
  return {};
56719
56729
  }
@@ -58525,6 +58535,15 @@ var LabelDefinitionSchema = object({
58525
58535
  description: string().optional(),
58526
58536
  icon: string().optional()
58527
58537
  });
58538
+ var ClassMapDefinitionSchema = object({
58539
+ mapping: record(string(), _enum([
58540
+ "person",
58541
+ "vehicle",
58542
+ "animal",
58543
+ "package"
58544
+ ])),
58545
+ preserveOriginal: boolean()
58546
+ });
58528
58547
  var MODEL_FORMATS = [
58529
58548
  "onnx",
58530
58549
  "coreml",
@@ -58608,6 +58627,12 @@ var ModelVariantGroupSchema = object({
58608
58627
  */
58609
58628
  resolution: number().int().positive().optional()
58610
58629
  });
58630
+ var ModelProviderIdSchema = _enum([
58631
+ "camstack",
58632
+ "frigate",
58633
+ "scrypted",
58634
+ "custom"
58635
+ ]);
58611
58636
  var ModelCatalogEntrySchema = object({
58612
58637
  id: string(),
58613
58638
  name: string(),
@@ -58703,7 +58728,19 @@ var ModelCatalogEntrySchema = object({
58703
58728
  * `id` stays the source of truth for resolution/download/persistence; grouping
58704
58729
  * is a presentation overlay resolved back to an `id`.
58705
58730
  */
58706
- group: ModelVariantGroupSchema.optional()
58731
+ group: ModelVariantGroupSchema.optional(),
58732
+ /**
58733
+ * Catalog source for the pipeline stepper's provider-first picker. Absent on
58734
+ * built-in CamStack entries (treated as `camstack`) and on registry rows
58735
+ * persisted before this field existed (`inferModelProvider` fills those).
58736
+ */
58737
+ provider: ModelProviderIdSchema.optional(),
58738
+ /**
58739
+ * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
58740
+ * applies (Frigate / COCO public catalog). Set on a custom model whose raw
58741
+ * labels already ARE the CamStack macros (Scrypted identity map).
58742
+ */
58743
+ classMap: ClassMapDefinitionSchema.optional()
58707
58744
  });
58708
58745
  var ConvertTargetSchema = discriminatedUnion("format", [object({
58709
58746
  format: literal("openvino"),
@@ -58732,7 +58769,8 @@ var ModelConvertMetadataSchema = object({
58732
58769
  "ocr",
58733
58770
  "segmentation"
58734
58771
  ]),
58735
- faceAlignment: boolean().optional()
58772
+ faceAlignment: boolean().optional(),
58773
+ classMap: ClassMapDefinitionSchema.optional()
58736
58774
  });
58737
58775
  var ConvertResultSchema = object({
58738
58776
  entry: ModelCatalogEntrySchema,
@@ -62506,6 +62544,27 @@ var LinkedDeviceSchema = object({
62506
62544
  features: array(string()),
62507
62545
  producesTrackedEvents: boolean().optional()
62508
62546
  });
62547
+ /** One camera's resolved linked set, tagged with the camera it belongs to.
62548
+ * The batch answer needs the tag; the single-device answer already has it
62549
+ * from the input, which is why `getLinkedDevices` keeps the untagged shape. */
62550
+ var LinkedDevicesForDeviceSchema = object({
62551
+ deviceId: number(),
62552
+ mode: LinkedDevicesModeSchema,
62553
+ devices: array(LinkedDeviceSchema)
62554
+ });
62555
+ /** One device's binding map — the shape `getBindings`, `getBindingsBatch` and
62556
+ * `getAllBindings` all answer in. Declared once: three copies of the same
62557
+ * object literal is exactly how the three drift apart. */
62558
+ var DeviceBindingsForDeviceSchema = object({
62559
+ deviceId: number(),
62560
+ entries: array(object({
62561
+ capName: string(),
62562
+ kind: _enum(["native", "wrapped"]),
62563
+ providerAddonId: string(),
62564
+ providerNodeId: string(),
62565
+ nativeAddonId: string()
62566
+ }))
62567
+ });
62509
62568
  var SavedDeviceRowSchema = object({
62510
62569
  /** Numeric id reserved at allocateDeviceId time. */
62511
62570
  id: number(),
@@ -62731,11 +62790,25 @@ method(object({
62731
62790
  projection: _enum(["full", "slim"]).optional(),
62732
62791
  /** Return only camera devices. Filtering server-side instead of
62733
62792
  * shipping 293 rows to find 12. */
62734
- isCamera: boolean().optional()
62793
+ isCamera: boolean().optional(),
62794
+ /**
62795
+ * Return only these device ids. For the caller that already KNOWS the
62796
+ * handful it wants and needs a field the id-bearing answer does not
62797
+ * carry — the viewer's linked-devices panel joins `type` and `online`
62798
+ * onto ~8 linked ids and, unfiltered, dragged the fleet across to do
62799
+ * it: 433 KB slim / 958 KB full for 967 devices, on a query that
62800
+ * refetches on the reconcile interval, on a phone.
62801
+ *
62802
+ * Safe to send at a hub that predates it: Zod STRIPS unknown input
62803
+ * keys rather than rejecting them (verified against the live hub
62804
+ * 2026-08-25 — 967 rows came back), so an old hub answers exactly what
62805
+ * it answers today and the caller filters as it already does.
62806
+ */
62807
+ deviceIds: array(number()).optional()
62735
62808
  }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
62736
62809
  mode: LinkedDevicesModeSchema,
62737
62810
  devices: array(LinkedDeviceSchema)
62738
- })), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
62811
+ })), method(object({ deviceIds: array(number()) }), array(LinkedDevicesForDeviceSchema)), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
62739
62812
  deviceId: number(),
62740
62813
  values: record(string(), unknown())
62741
62814
  }), object({ success: literal(true) }), {
@@ -62762,25 +62835,7 @@ method(object({
62762
62835
  }), method(object({ deviceId: number() }), array(StreamProbeResultSchema), {
62763
62836
  kind: "mutation",
62764
62837
  auth: "admin"
62765
- }), method(object({ deviceId: number() }), object({
62766
- deviceId: number(),
62767
- entries: array(object({
62768
- capName: string(),
62769
- kind: _enum(["native", "wrapped"]),
62770
- providerAddonId: string(),
62771
- providerNodeId: string(),
62772
- nativeAddonId: string()
62773
- }))
62774
- })), method(object({}), array(object({
62775
- deviceId: number(),
62776
- entries: array(object({
62777
- capName: string(),
62778
- kind: _enum(["native", "wrapped"]),
62779
- providerAddonId: string(),
62780
- providerNodeId: string(),
62781
- nativeAddonId: string()
62782
- }))
62783
- }))), method(object({
62838
+ }), method(object({ deviceId: number() }), DeviceBindingsForDeviceSchema), method(object({ deviceIds: array(number()) }), array(DeviceBindingsForDeviceSchema)), method(object({}), array(DeviceBindingsForDeviceSchema)), method(object({
62784
62839
  deviceId: number(),
62785
62840
  capName: string(),
62786
62841
  wrapperAddonId: string(),
@@ -65190,12 +65245,15 @@ var NcOccupancyConditionSchema = object({
65190
65245
  * there is no second switch that can disagree with the first and every rule
65191
65246
  * authored before the decision migrates for free (`audioModeOf`):
65192
65247
  *
65193
- * - **LABEL mode — `labels` present.** The rule fires on the FIRST frame the
65194
- * classifier labels with one of them. No window, no percentage:
65195
- * `hitPercent` and `samplingSeconds` are ignored, and the rule's own
65196
- * `throttle` cooldown is the only brake. The per-label confidence floor is
65197
- * the analyzer's (`classificationMinScore`, per device) a label only
65198
- * reaches this condition if the classifier was already confident enough.
65248
+ * - **LABEL mode — `labels` present.** The rule fires when `confirmHits`
65249
+ * labelled frames land inside `confirmWindowSec` (default 2 in 5 s).
65250
+ * `hitPercent` and `samplingSeconds` are still ignored a percentage of
65251
+ * frames is the wrong question for a classifier that labels 1–3 frames
65252
+ * per episode. The count window is the brake that drops a single-frame
65253
+ * false positive; the rule's own `throttle` cooldown is the other. The
65254
+ * per-label confidence floor is the analyzer's (`classificationMinScore`,
65255
+ * per device) — a label only reaches this condition if the classifier was
65256
+ * already confident enough. `confirmHits: 1` restores first-frame fire.
65199
65257
  * - **LEVEL mode — `dbThreshold` present, no labels.** The sampling window IS
65200
65258
  * the condition: at least `hitPercent`% of the samples over
65201
65259
  * `samplingSeconds` must be at or above `dbThreshold` dBFS (see
@@ -65222,14 +65280,22 @@ var NcOccupancyConditionSchema = object({
65222
65280
  * an operator who typed `dog` mean the same thing.
65223
65281
  */
65224
65282
  var NcAudioConditionSchema = object({
65225
- /** LABEL MODE: audio macro labels. Present ⇒ fires on the first labelled frame. */
65283
+ /** LABEL MODE: audio macro labels. Present ⇒ count-in-window confirm. */
65226
65284
  labels: array(string().min(1)).min(1).optional(),
65227
65285
  /** LEVEL MODE: floor in dBFS (negative-going, `0` = full scale). */
65228
65286
  dbThreshold: number().min(-96).max(0).optional(),
65229
65287
  /** LEVEL MODE ONLY: percentage of the window's samples that must be hits (1–100). */
65230
65288
  hitPercent: number().int().min(1).max(100).default(60),
65231
65289
  /** LEVEL MODE ONLY: length of the sampling window in seconds. */
65232
- samplingSeconds: number().int().min(1).max(300).default(10)
65290
+ samplingSeconds: number().int().min(1).max(300).default(10),
65291
+ /**
65292
+ * LABEL MODE: how many labelled frames must land inside
65293
+ * {@link NcAudioConditionSchema.shape.confirmWindowSec} before dispatch.
65294
+ * Absent ⇒ 2 (the matcher default). `1` is first-frame fire.
65295
+ */
65296
+ confirmHits: number().int().min(1).max(20).optional(),
65297
+ /** LABEL MODE: the window those frames must share, in seconds. Absent ⇒ 5. */
65298
+ confirmWindowSec: number().int().min(1).max(60).optional()
65233
65299
  });
65234
65300
  /**
65235
65301
  * Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
@@ -67603,6 +67669,46 @@ var RecentTracksPageSchema = object({
67603
67669
  /** Cursor for the next page, or null when this page is the last. */
67604
67670
  nextCursor: string().nullable()
67605
67671
  });
67672
+ var LIST_GROUPS_DEFAULT_LIMIT = 40;
67673
+ var LIST_GROUPS_MAX_LIMIT = 100;
67674
+ var AnalyticsGroupRecordSchema = object({
67675
+ id: string(),
67676
+ deviceId: number().int(),
67677
+ openedAt: number().int(),
67678
+ closedAt: number().int(),
67679
+ timestamp: number().int(),
67680
+ memberCount: number().int(),
67681
+ memberTrackIds: array(string()).readonly(),
67682
+ className: string(),
67683
+ classes: array(string()).readonly(),
67684
+ /** Relative event-media path, or null when the group has no picture yet. */
67685
+ mediaUrl: string().nullable(),
67686
+ singleton: boolean()
67687
+ });
67688
+ var AnalyticsGroupMemberSchema = object({
67689
+ trackId: string(),
67690
+ deviceId: number().int(),
67691
+ className: string(),
67692
+ firstSeen: number().int(),
67693
+ lastSeen: number().int(),
67694
+ mediaUrl: string().nullable()
67695
+ });
67696
+ var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
67697
+ var ListGroupsQueryInput = object({
67698
+ /** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
67699
+ deviceIds: array(number()),
67700
+ /** Window lower bound on `closedAt` (inclusive). */
67701
+ since: number().optional(),
67702
+ /** Window upper bound on `openedAt` (inclusive). */
67703
+ until: number().optional(),
67704
+ limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
67705
+ /** Opaque continuation cursor from a previous page's `nextCursor`. */
67706
+ cursor: string().optional()
67707
+ });
67708
+ var ListGroupsPageSchema = object({
67709
+ groups: array(AnalyticsGroupRecordSchema).readonly(),
67710
+ nextCursor: string().nullable()
67711
+ });
67606
67712
  var KeyEventQueryInput = object({
67607
67713
  deviceId: number(),
67608
67714
  /** Window lower bound (track firstSeen ≥ since). */
@@ -67678,7 +67784,9 @@ var TrackCascadeCountsSchema = object({
67678
67784
  /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
67679
67785
  plates: number().int(),
67680
67786
  /** Per-track CLIP search vectors removed (best-effort). */
67681
- embeddings: number().int()
67787
+ embeddings: number().int(),
67788
+ /** Group membership + group rows removed with their last member (best-effort). */
67789
+ groups: number().int()
67682
67790
  });
67683
67791
  /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
67684
67792
  var DiskReconcileCountsSchema = object({
@@ -67824,7 +67932,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
67824
67932
  * stationary registry). Default false: the timeline lists passages,
67825
67933
  * not parking records (operator decision, 2026-08-15). */
67826
67934
  includeStationary: boolean().optional()
67827
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
67935
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
67936
+ deviceId: number(),
67937
+ groupId: string().min(1)
67938
+ }), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
67828
67939
  kind: "mutation",
67829
67940
  auth: "admin"
67830
67941
  }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
@@ -68042,6 +68153,33 @@ var NativeCropRefSchema = object({
68042
68153
  h: number()
68043
68154
  })
68044
68155
  });
68156
+ object({
68157
+ crop: object({
68158
+ left: number(),
68159
+ top: number(),
68160
+ width: number().positive(),
68161
+ height: number().positive()
68162
+ }).optional(),
68163
+ content: object({
68164
+ width: number().int().positive(),
68165
+ height: number().int().positive()
68166
+ }),
68167
+ fit: _enum(["stretch", "contain"]),
68168
+ format: _enum([
68169
+ "rgb",
68170
+ "gray",
68171
+ "jpeg"
68172
+ ])
68173
+ });
68174
+ var FrameRefSchema = object({
68175
+ registryId: string().min(1),
68176
+ id: string().min(1),
68177
+ width: number().int().positive(),
68178
+ height: number().int().positive(),
68179
+ format: _enum(["rgb", "gray"]),
68180
+ timestamp: number(),
68181
+ capturedAt: number().optional()
68182
+ });
68045
68183
  var ModelFormatSchema$1 = _enum([
68046
68184
  "onnx",
68047
68185
  "coreml",
@@ -68107,7 +68245,8 @@ var PipelineModelOptionSchema = object({
68107
68245
  sizeMB: number()
68108
68246
  })),
68109
68247
  group: ModelVariantGroupSchema.optional(),
68110
- legacy: boolean().optional()
68248
+ legacy: boolean().optional(),
68249
+ provider: ModelProviderIdSchema.optional()
68111
68250
  });
68112
68251
  var ConfigFieldBridge = custom();
68113
68252
  var PipelineAddonSchemaSchema = object({
@@ -68286,6 +68425,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
68286
68425
  steps: array(PipelineStepInputSchema).min(1),
68287
68426
  frame: FrameInputSchema.optional(),
68288
68427
  /**
68428
+ * Process-local lazy frame. Valid only when caller and provider resolve
68429
+ * in the same execution-group process; split/cross-node callers use
68430
+ * `frame`/`image` inline compatibility instead.
68431
+ */
68432
+ frameRef: FrameRefSchema.optional(),
68433
+ /**
68289
68434
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
68290
68435
  * the decoded pixels live in. One more member of the one-of
68291
68436
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -68581,7 +68726,10 @@ var NativeCropResultSchema = object({
68581
68726
  * Which source served this crop, so a quality-sensitive consumer (the native
68582
68727
  * `keyFrame`) can reject a degraded fallback:
68583
68728
  * - `native` — cut from the decode worker's retained NATIVE surface (the
68584
- * quality path).
68729
+ * quality path). A subject-tile serve is also native-resolution and stays
68730
+ * `native` here: the public enum cannot name `tile` without a breaking cap
68731
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
68732
+ * internal crop result (`nativeHits` vs `tileHits`).
68585
68733
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
68586
68734
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
68587
68735
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -69072,12 +69220,41 @@ var RunnerLocalLoadSchema = object({
69072
69220
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
69073
69221
  * working unchanged when they switch to reading from the runner cap.
69074
69222
  */
69223
+ var FrameLazyCountersSchema = object({
69224
+ framesDecoded: number(),
69225
+ framesAdmitted: number(),
69226
+ framesDroppedPixelFree: number(),
69227
+ viewsMaterialized: number(),
69228
+ viewsSkipped: number(),
69229
+ workerToRunnerBytes: number(),
69230
+ runnerToPoolRawBytes: number(),
69231
+ runnerToPoolJpegBytes: number(),
69232
+ onDemandFullFrameRequests: number(),
69233
+ onDemandCropRequests: number(),
69234
+ nativeHits: number(),
69235
+ nativeMisses: number(),
69236
+ tileHits: number(),
69237
+ tileMisses: number(),
69238
+ fallbackHits: number(),
69239
+ fallbackMisses: number(),
69240
+ retainedWritesAvoided: number(),
69241
+ residentRefs: number(),
69242
+ residentBytes: number(),
69243
+ releases: number(),
69244
+ evictions: number(),
69245
+ staleMisses: number()
69246
+ });
69247
+ var FrameLazyMetricsSchema = object({
69248
+ node: FrameLazyCountersSchema,
69249
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
69250
+ });
69075
69251
  var RunnerLocalMetricsSchema = object({
69076
69252
  nodeId: string(),
69077
69253
  activeCameras: number(),
69078
69254
  throttledCameras: number(),
69079
69255
  avgInferenceTimeMs: number(),
69080
- queueDepth: number()
69256
+ queueDepth: number(),
69257
+ frameLazy: FrameLazyMetricsSchema.optional()
69081
69258
  });
69082
69259
  method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mutation" }), method(object({ deviceId: number() }), object({ success: literal(true) }), { kind: "mutation" }), method(ReportMotionInputSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), RunnerLocalLoadSchema), method(_void(), RunnerLocalMetricsSchema), method(object({ deviceId: number() }), CameraMetricsSchema.nullable()), method(_void(), array(CameraMetricsWithDeviceIdSchema).readonly()), method(_void(), array(number()).readonly()), method(object({
69083
69260
  handle: FrameHandleSchema,
@@ -70377,6 +70554,9 @@ method(_void(), ProviderInfoSchema), method(object({ config: record(string(), un
70377
70554
  location: StorageLocationSchema,
70378
70555
  relativePath: string()
70379
70556
  }), _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" });
70557
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
70558
+ var ProfileSettingsSchemaBridge = unknown().nullable();
70559
+ var ProfileSettingsBagSchema = record(string(), unknown());
70380
70560
  /**
70381
70561
  * A live terminal session hosted by the provider addon. Output and input do
70382
70562
  * NOT flow through the capability — they use the addon data plane
@@ -70406,7 +70586,14 @@ var TerminalSessionInfoSchema = object({
70406
70586
  var TerminalProfileInfoSchema = object({
70407
70587
  profileId: string(),
70408
70588
  label: string(),
70409
- description: string().optional()
70589
+ description: string().optional(),
70590
+ /** Spawn defaults the instance form copies on create. */
70591
+ executable: string().optional(),
70592
+ args: array(string()).readonly().optional(),
70593
+ cwd: string().optional(),
70594
+ environment: array(string()).readonly().optional(),
70595
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
70596
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
70410
70597
  });
70411
70598
  /**
70412
70599
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -70419,7 +70606,12 @@ var TerminalInstanceInfoSchema = object({
70419
70606
  profileId: string(),
70420
70607
  profileLabel: string(),
70421
70608
  name: string(),
70422
- enabled: boolean()
70609
+ enabled: boolean(),
70610
+ executable: string(),
70611
+ args: array(string()).readonly(),
70612
+ cwd: string(),
70613
+ environment: array(string()).readonly(),
70614
+ profileSettings: ProfileSettingsBagSchema
70423
70615
  });
70424
70616
  var TerminalLegacyCameraSchema = object({
70425
70617
  stableId: string(),
@@ -70449,7 +70641,23 @@ var TerminalOutputBatchSchema = object({
70449
70641
  method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }), method(object({
70450
70642
  targetNodeId: string().min(1),
70451
70643
  profileId: string().min(1),
70452
- name: string().trim().min(1).max(160).optional()
70644
+ name: string().trim().min(1).max(160).optional(),
70645
+ executable: string().max(1024).optional(),
70646
+ args: array(string().max(2048)).max(64).optional(),
70647
+ cwd: string().max(1024).optional(),
70648
+ environment: array(string().max(4096)).max(64).optional(),
70649
+ profileSettings: ProfileSettingsBagSchema.optional()
70650
+ }), TerminalInstanceInfoSchema, {
70651
+ kind: "mutation",
70652
+ auth: "admin"
70653
+ }), method(object({
70654
+ instanceId: string().min(1),
70655
+ name: string().trim().min(1).max(160).optional(),
70656
+ executable: string().max(1024).optional(),
70657
+ args: array(string().max(2048)).max(64).optional(),
70658
+ cwd: string().max(1024).optional(),
70659
+ environment: array(string().max(4096)).max(64).optional(),
70660
+ profileSettings: ProfileSettingsBagSchema.optional()
70453
70661
  }), TerminalInstanceInfoSchema, {
70454
70662
  kind: "mutation",
70455
70663
  auth: "admin"
@@ -70471,7 +70679,11 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
70471
70679
  }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
70472
70680
  profileId: string(),
70473
70681
  cols: number().int().positive(),
70474
- rows: number().int().positive()
70682
+ rows: number().int().positive(),
70683
+ executable: string().max(1024).optional(),
70684
+ args: array(string().max(2048)).max(64).optional(),
70685
+ cwd: string().max(1024).optional(),
70686
+ environment: array(string().max(4096)).max(64).optional()
70475
70687
  }), TerminalSessionInfoSchema, {
70476
70688
  kind: "mutation",
70477
70689
  auth: "admin"
@@ -74371,10 +74583,10 @@ var lawnMowerControlCapability = {
74371
74583
  *
74372
74584
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
74373
74585
  * to receive an ordered list of candidate base URLs it should race
74374
- * on connect — LAN IPv4 first (lowest latency when on same network),
74375
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
74376
- * race them with short timeouts and stick with the winner for the
74377
- * session.
74586
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
74587
+ * when on the same network), then public hostname (if a tunnel is
74588
+ * up). The SDK can race them with short timeouts and stick with the
74589
+ * winner for the session.
74378
74590
  *
74379
74591
  * Why hub-only: agents are not directly addressable by the operator's
74380
74592
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -74529,6 +74741,17 @@ var NotificationEndpointSchema = object({
74529
74741
  /** What the ranking currently resolves to (null when nothing is reachable). */
74530
74742
  resolved: string().nullable()
74531
74743
  });
74744
+ /**
74745
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
74746
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
74747
+ * currently expands to, so the UI can show the effective set either way.
74748
+ */
74749
+ var ViewerEndpointsSchema = object({
74750
+ /** The operator's explicit race set, or empty for AUTO. */
74751
+ baseUrls: array(string()).readonly(),
74752
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
74753
+ resolved: array(string()).readonly()
74754
+ });
74532
74755
  var AllowedAddressesSchema = object({
74533
74756
  /**
74534
74757
  * Allowlist of interface addresses operators have explicitly opted
@@ -74537,6 +74760,20 @@ var AllowedAddressesSchema = object({
74537
74760
  * Network Addresses admin page and persisted by the addon.
74538
74761
  */
74539
74762
  addresses: array(string()).readonly() });
74763
+ var TlsStatusSchema = object({
74764
+ mode: _enum([
74765
+ "generated",
74766
+ "uploaded",
74767
+ "disabled"
74768
+ ]),
74769
+ leafFingerprintSha256: string().nullable(),
74770
+ caFingerprintSha256: string().nullable(),
74771
+ validTo: string().nullable(),
74772
+ sans: array(string()),
74773
+ caCertPem: string().nullable(),
74774
+ reissueError: string().nullable(),
74775
+ restartRequired: boolean()
74776
+ });
74540
74777
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
74541
74778
  /**
74542
74779
  * LEGACY HINT — do not send from new code. Kept optional so clients
@@ -74546,17 +74783,31 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
74546
74783
  */
74547
74784
  port: number().int().min(1).max(65535).optional(),
74548
74785
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
74549
- * candidate. Default `true`. */
74786
+ * candidate. Default `false` — loopback is not a client route. */
74550
74787
  includeLoopback: boolean().optional(),
74551
- /** Skip IPv6 entries. Some legacy clients can't parse them.
74552
- * Default `false`. */
74788
+ /** Skip IPv6 entries. Default `false` the palette includes stable
74789
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
74790
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
74553
74791
  ipv4Only: boolean().optional(),
74554
74792
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
74555
74793
  * Pass `'https'` when the caller is itself loaded over HTTPS
74556
74794
  * to avoid mixed-content blocks in the browser. The public
74557
74795
  * tunnel always emits `https://` regardless. */
74558
74796
  scheme: _enum(["http", "https"]).optional()
74559
- }), 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" });
74797
+ }), 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, {
74798
+ kind: "mutation",
74799
+ auth: "admin"
74800
+ }), method(object({
74801
+ certPem: string().min(1),
74802
+ keyPem: string().min(1),
74803
+ caPem: string().optional()
74804
+ }), TlsStatusSchema, {
74805
+ kind: "mutation",
74806
+ auth: "admin"
74807
+ }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
74808
+ kind: "mutation",
74809
+ auth: "admin"
74810
+ });
74560
74811
  var LockControlStatusSchema = object({
74561
74812
  /** Lifecycle state of the lock. `jammed` means the motor reported
74562
74813
  * failure to reach the target — operator intervention required. */
@@ -76117,7 +76368,12 @@ var PlateInfoSchema = object({
76117
76368
  plateBbox: BoundingBoxSchema.optional(),
76118
76369
  /** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
76119
76370
  keyFrameMediaKey: string().optional(),
76120
- base64: string().optional()
76371
+ base64: string().optional(),
76372
+ /**
76373
+ * Same crop as a data-plane URL. `getPlateByTrack` returns this and
76374
+ * never inlines JPEG; `listPlates` still inlines for the admin-ui.
76375
+ */
76376
+ cropUrl: string().optional()
76121
76377
  });
76122
76378
  var MediaFileLiteSchema = object({
76123
76379
  key: string(),
@@ -81641,6 +81897,12 @@ Object.freeze({
81641
81897
  addonId: null,
81642
81898
  access: "view"
81643
81899
  },
81900
+ "deviceManager.getBindingsBatch": {
81901
+ capName: "device-manager",
81902
+ capScope: "system",
81903
+ addonId: null,
81904
+ access: "view"
81905
+ },
81644
81906
  "deviceManager.getChildren": {
81645
81907
  capName: "device-manager",
81646
81908
  capScope: "system",
@@ -81701,6 +81963,12 @@ Object.freeze({
81701
81963
  addonId: null,
81702
81964
  access: "view"
81703
81965
  },
81966
+ "deviceManager.getLinkedDevicesBatch": {
81967
+ capName: "device-manager",
81968
+ capScope: "system",
81969
+ addonId: null,
81970
+ access: "view"
81971
+ },
81704
81972
  "deviceManager.getRoleDisplayDefaults": {
81705
81973
  capName: "device-manager",
81706
81974
  capScope: "system",
@@ -82583,6 +82851,12 @@ Object.freeze({
82583
82851
  addonId: null,
82584
82852
  access: "create"
82585
82853
  },
82854
+ "localNetwork.downloadCa": {
82855
+ capName: "local-network",
82856
+ capScope: "system",
82857
+ addonId: null,
82858
+ access: "view"
82859
+ },
82586
82860
  "localNetwork.getAllowedAddresses": {
82587
82861
  capName: "local-network",
82588
82862
  capScope: "system",
@@ -82607,18 +82881,42 @@ Object.freeze({
82607
82881
  addonId: null,
82608
82882
  access: "view"
82609
82883
  },
82884
+ "localNetwork.getTlsStatus": {
82885
+ capName: "local-network",
82886
+ capScope: "system",
82887
+ addonId: null,
82888
+ access: "view"
82889
+ },
82890
+ "localNetwork.getViewerEndpoints": {
82891
+ capName: "local-network",
82892
+ capScope: "system",
82893
+ addonId: null,
82894
+ access: "view"
82895
+ },
82610
82896
  "localNetwork.list": {
82611
82897
  capName: "local-network",
82612
82898
  capScope: "system",
82613
82899
  addonId: null,
82614
82900
  access: "view"
82615
82901
  },
82902
+ "localNetwork.regenerateCertificate": {
82903
+ capName: "local-network",
82904
+ capScope: "system",
82905
+ addonId: null,
82906
+ access: "create"
82907
+ },
82616
82908
  "localNetwork.resetAllowlistToBestMatch": {
82617
82909
  capName: "local-network",
82618
82910
  capScope: "system",
82619
82911
  addonId: null,
82620
82912
  access: "delete"
82621
82913
  },
82914
+ "localNetwork.revertToGeneratedCertificate": {
82915
+ capName: "local-network",
82916
+ capScope: "system",
82917
+ addonId: null,
82918
+ access: "create"
82919
+ },
82622
82920
  "localNetwork.setAllowedAddresses": {
82623
82921
  capName: "local-network",
82624
82922
  capScope: "system",
@@ -82631,6 +82929,18 @@ Object.freeze({
82631
82929
  addonId: null,
82632
82930
  access: "create"
82633
82931
  },
82932
+ "localNetwork.setViewerEndpoints": {
82933
+ capName: "local-network",
82934
+ capScope: "system",
82935
+ addonId: null,
82936
+ access: "create"
82937
+ },
82938
+ "localNetwork.uploadCertificate": {
82939
+ capName: "local-network",
82940
+ capScope: "system",
82941
+ addonId: null,
82942
+ access: "create"
82943
+ },
82634
82944
  "lockControl.lock": {
82635
82945
  capName: "lock-control",
82636
82946
  capScope: "device",
@@ -83429,6 +83739,12 @@ Object.freeze({
83429
83739
  addonId: null,
83430
83740
  access: "view"
83431
83741
  },
83742
+ "pipelineAnalytics.getGroup": {
83743
+ capName: "pipeline-analytics",
83744
+ capScope: "device",
83745
+ addonId: null,
83746
+ access: "view"
83747
+ },
83432
83748
  "pipelineAnalytics.getKeyEvents": {
83433
83749
  capName: "pipeline-analytics",
83434
83750
  capScope: "device",
@@ -83513,6 +83829,12 @@ Object.freeze({
83513
83829
  addonId: null,
83514
83830
  access: "view"
83515
83831
  },
83832
+ "pipelineAnalytics.listGroups": {
83833
+ capName: "pipeline-analytics",
83834
+ capScope: "device",
83835
+ addonId: null,
83836
+ access: "view"
83837
+ },
83516
83838
  "pipelineAnalytics.listOpsLog": {
83517
83839
  capName: "pipeline-analytics",
83518
83840
  capScope: "device",
@@ -85511,6 +85833,12 @@ Object.freeze({
85511
85833
  addonId: null,
85512
85834
  access: "create"
85513
85835
  },
85836
+ "terminalSession.updateInstance": {
85837
+ capName: "terminal-session",
85838
+ capScope: "system",
85839
+ addonId: null,
85840
+ access: "create"
85841
+ },
85514
85842
  "terminalSession.writeInput": {
85515
85843
  capName: "terminal-session",
85516
85844
  capScope: "system",
@@ -86288,6 +86616,11 @@ Object.freeze({
86288
86616
  form: "single",
86289
86617
  optional: false
86290
86618
  }],
86619
+ "deviceManager.getBindingsBatch": [{
86620
+ name: "deviceIds",
86621
+ form: "array",
86622
+ optional: false
86623
+ }],
86291
86624
  "deviceManager.getChildren": [{
86292
86625
  name: "parentDeviceId",
86293
86626
  form: "single",
@@ -86333,6 +86666,11 @@ Object.freeze({
86333
86666
  form: "single",
86334
86667
  optional: false
86335
86668
  }],
86669
+ "deviceManager.getLinkedDevicesBatch": [{
86670
+ name: "deviceIds",
86671
+ form: "array",
86672
+ optional: false
86673
+ }],
86336
86674
  "deviceManager.getSettingsSchema": [{
86337
86675
  name: "deviceId",
86338
86676
  form: "single",
@@ -86353,6 +86691,11 @@ Object.freeze({
86353
86691
  form: "single",
86354
86692
  optional: false
86355
86693
  }],
86694
+ "deviceManager.listAll": [{
86695
+ name: "deviceIds",
86696
+ form: "array",
86697
+ optional: true
86698
+ }],
86356
86699
  "deviceManager.loadConfig": [{
86357
86700
  name: "deviceId",
86358
86701
  form: "single",
@@ -86926,6 +87269,11 @@ Object.freeze({
86926
87269
  form: "single",
86927
87270
  optional: false
86928
87271
  }],
87272
+ "pipelineAnalytics.getGroup": [{
87273
+ name: "deviceId",
87274
+ form: "single",
87275
+ optional: false
87276
+ }],
86929
87277
  "pipelineAnalytics.getKeyEvents": [{
86930
87278
  name: "deviceId",
86931
87279
  form: "single",
@@ -86981,6 +87329,11 @@ Object.freeze({
86981
87329
  form: "array",
86982
87330
  optional: false
86983
87331
  }],
87332
+ "pipelineAnalytics.listGroups": [{
87333
+ name: "deviceIds",
87334
+ form: "array",
87335
+ optional: false
87336
+ }],
86984
87337
  "pipelineAnalytics.listOpsLog": [{
86985
87338
  name: "deviceId",
86986
87339
  form: "single",
@@ -87998,6 +88351,35 @@ Object.freeze(Object.fromEntries([{
87998
88351
  }]
87999
88352
  }].map((s) => [s.stepId, s.defaultModelId])));
88000
88353
  string().min(1);
88354
+ var CLUSTER_STEP_SETTING_FIELDS = [{
88355
+ stepId: "face-embedding",
88356
+ key: "minLandmarkFaceSize",
88357
+ label: "Min face size for recognition (detection px)",
88358
+ description: "Refuse to embed a face smaller than this IN THE DETECTION FRAME. Applies to every node — the enrolled gallery is one index, and two admission floors would fill it from two policies. 0 disables the gate.",
88359
+ type: "slider",
88360
+ min: 0,
88361
+ max: 64,
88362
+ step: 2,
88363
+ default: 24
88364
+ }];
88365
+ function clusterStepSettingKey(stepId, fieldKey) {
88366
+ return `clusterStepSetting:${stepId}:${fieldKey}`;
88367
+ }
88368
+ var ClusterSettingNumberSchema = number().finite();
88369
+ function readClusterStepSettings(config) {
88370
+ const out = {};
88371
+ for (const field of CLUSTER_STEP_SETTING_FIELDS) {
88372
+ const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
88373
+ const value = parsed.success ? parsed.data : field.default;
88374
+ const existing = out[field.stepId] ?? {};
88375
+ out[field.stepId] = {
88376
+ ...existing,
88377
+ [field.key]: value
88378
+ };
88379
+ }
88380
+ return out;
88381
+ }
88382
+ readClusterStepSettings({});
88001
88383
  object({
88002
88384
  /**
88003
88385
  * Fraction of the box's own size added on EACH side before cutting.