@camstack/types 1.2.103 → 1.2.105

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/addon.js CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_event_category = require("./event-category-EY0GNjV9.js");
3
- const require_sleep = require("./sleep-CizGYrCD.js");
3
+ const require_sleep = require("./sleep-CUuoW-kk.js");
4
4
  const require_err_msg = require("./err-msg-COpsHMw2.js");
5
5
  //#region src/generated/cap-input-defaults.ts
6
6
  /**
package/dist/addon.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as EventCategory } from "./event-category-CIa_iT6b.mjs";
2
- import { B as ReadinessRegistry, E as adminUiCapability, L as nodePin, R as readNodePin, St as emitReadiness, T as DeviceType, V as ReadinessTimeoutError, W as scopeKey, _t as DisposerChain, a as asJsonObject, b as deviceOpsCapability, d as BOOT_RECOVERY_BACKOFF_MS, f as DEVICE_SCOPED_CAPS, gt as DATAPLANE_SECRET_HEADER, h as createEventBusSliceSource, j as expandCapMethods, m as createDeviceProxy, p as isDeviceScopedCap, s as asString, t as sleep, u as parseJsonUnknown, vt as BaseAddon, x as viewerUiCapability, yt as normalizeAddonInitResult } from "./sleep-Cs9MWLcT.mjs";
2
+ import { B as ReadinessRegistry, E as adminUiCapability, L as nodePin, R as readNodePin, St as emitReadiness, T as DeviceType, V as ReadinessTimeoutError, W as scopeKey, _t as DisposerChain, a as asJsonObject, b as deviceOpsCapability, d as BOOT_RECOVERY_BACKOFF_MS, f as DEVICE_SCOPED_CAPS, gt as DATAPLANE_SECRET_HEADER, h as createEventBusSliceSource, j as expandCapMethods, m as createDeviceProxy, p as isDeviceScopedCap, s as asString, t as sleep, u as parseJsonUnknown, vt as BaseAddon, x as viewerUiCapability, yt as normalizeAddonInitResult } from "./sleep-BLxqGLY0.mjs";
3
3
  import { t as errMsg } from "./err-msg-IQTHeDzc.mjs";
4
4
  //#region src/generated/cap-input-defaults.ts
5
5
  /**
@@ -114,6 +114,41 @@ export declare const LinkedDeviceSchema: z.ZodObject<{
114
114
  producesTrackedEvents: z.ZodOptional<z.ZodBoolean>;
115
115
  }, z.core.$strip>;
116
116
  export type LinkedDevice = z.infer<typeof LinkedDeviceSchema>;
117
+ /** One camera's resolved linked set, tagged with the camera it belongs to.
118
+ * The batch answer needs the tag; the single-device answer already has it
119
+ * from the input, which is why `getLinkedDevices` keeps the untagged shape. */
120
+ export declare const LinkedDevicesForDeviceSchema: z.ZodObject<{
121
+ deviceId: z.ZodNumber;
122
+ mode: z.ZodEnum<{
123
+ manual: "manual";
124
+ auto: "auto";
125
+ }>;
126
+ devices: z.ZodArray<z.ZodObject<{
127
+ deviceId: z.ZodNumber;
128
+ name: z.ZodString;
129
+ location: z.ZodNullable<z.ZodString>;
130
+ features: z.ZodArray<z.ZodString>;
131
+ producesTrackedEvents: z.ZodOptional<z.ZodBoolean>;
132
+ }, z.core.$strip>>;
133
+ }, z.core.$strip>;
134
+ export type LinkedDevicesForDevice = z.infer<typeof LinkedDevicesForDeviceSchema>;
135
+ /** One device's binding map — the shape `getBindings`, `getBindingsBatch` and
136
+ * `getAllBindings` all answer in. Declared once: three copies of the same
137
+ * object literal is exactly how the three drift apart. */
138
+ export declare const DeviceBindingsForDeviceSchema: z.ZodObject<{
139
+ deviceId: z.ZodNumber;
140
+ entries: z.ZodArray<z.ZodObject<{
141
+ capName: z.ZodString;
142
+ kind: z.ZodEnum<{
143
+ native: "native";
144
+ wrapped: "wrapped";
145
+ }>;
146
+ providerAddonId: z.ZodString;
147
+ providerNodeId: z.ZodString;
148
+ nativeAddonId: z.ZodString;
149
+ }, z.core.$strip>>;
150
+ }, z.core.$strip>;
151
+ export type DeviceBindingsForDevice = z.infer<typeof DeviceBindingsForDeviceSchema>;
117
152
  export { StreamSourceEntrySchema };
118
153
  export declare const SavedDeviceRowSchema: z.ZodObject<{
119
154
  id: z.ZodNumber;
@@ -504,6 +539,7 @@ export declare const deviceManagerCapability: {
504
539
  slim: "slim";
505
540
  }>>;
506
541
  isCamera: z.ZodOptional<z.ZodBoolean>;
542
+ deviceIds: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
507
543
  }, z.core.$strip>, z.ZodArray<z.ZodObject<{
508
544
  id: z.ZodNumber;
509
545
  stableId: z.ZodString;
@@ -663,6 +699,38 @@ export declare const deviceManagerCapability: {
663
699
  producesTrackedEvents: z.ZodOptional<z.ZodBoolean>;
664
700
  }, z.core.$strip>>;
665
701
  }, z.core.$strip>, import("./capability-definition.js").CapabilityMethodKind>;
702
+ /**
703
+ * `getLinkedDevices` for MANY cameras, in one call.
704
+ *
705
+ * Not a convenience wrapper — a cost fix. Resolving one camera's linked set
706
+ * needs the whole fleet as candidates (children ∪ same-location), so the
707
+ * single-device path runs a full `listAll` per call. Asked per camera that
708
+ * is N full-fleet sweeps of device-manager's event loop, and they do not
709
+ * overlap: measured on the live hub 2026-08-25, 30 concurrent
710
+ * `getLinkedDevices` took 4110 ms wall (median 4060 ms each) to return
711
+ * 7260 bytes in total. The batch takes ONE sweep and one settings read per
712
+ * camera.
713
+ *
714
+ * A device id that resolves to nothing still gets a row (`devices: []`) —
715
+ * a caller that asked for thirty and got twenty-eight cannot tell which two
716
+ * are missing, or that any are.
717
+ */
718
+ readonly getLinkedDevicesBatch: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
719
+ deviceIds: z.ZodArray<z.ZodNumber>;
720
+ }, z.core.$strip>, z.ZodArray<z.ZodObject<{
721
+ deviceId: z.ZodNumber;
722
+ mode: z.ZodEnum<{
723
+ manual: "manual";
724
+ auto: "auto";
725
+ }>;
726
+ devices: z.ZodArray<z.ZodObject<{
727
+ deviceId: z.ZodNumber;
728
+ name: z.ZodString;
729
+ location: z.ZodNullable<z.ZodString>;
730
+ features: z.ZodArray<z.ZodString>;
731
+ producesTrackedEvents: z.ZodOptional<z.ZodBoolean>;
732
+ }, z.core.$strip>>;
733
+ }, z.core.$strip>>, import("./capability-definition.js").CapabilityMethodKind>;
666
734
  /** Get stream sources for a camera device. */
667
735
  readonly getStreamSources: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
668
736
  deviceId: z.ZodNumber;
@@ -779,6 +847,35 @@ export declare const deviceManagerCapability: {
779
847
  nativeAddonId: z.ZodString;
780
848
  }, z.core.$strip>>;
781
849
  }, z.core.$strip>, import("./capability-definition.js").CapabilityMethodKind>;
850
+ /**
851
+ * `getBindings` for a NAMED set of devices, in one call.
852
+ *
853
+ * Between `getBindings` (one device) and `getAllBindings` (all 988) there
854
+ * was nothing, so a caller that needs seventy-five either pays
855
+ * seventy-five round-trips or drags the whole fleet across. Measured on
856
+ * the live hub 2026-08-25: 75 concurrent `getBindings` = 1211 ms / 118 KB,
857
+ * `getAllBindings({})` = 511 ms / 679 KB. Neither is the right answer to
858
+ * "these seventy-five".
859
+ *
860
+ * Same resolver, same routing rules, same per-device shape as
861
+ * `getBindings`; ids are deduped and a device with no bindings answers
862
+ * `entries: []` rather than dropping out.
863
+ */
864
+ readonly getBindingsBatch: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
865
+ deviceIds: z.ZodArray<z.ZodNumber>;
866
+ }, z.core.$strip>, z.ZodArray<z.ZodObject<{
867
+ deviceId: z.ZodNumber;
868
+ entries: z.ZodArray<z.ZodObject<{
869
+ capName: z.ZodString;
870
+ kind: z.ZodEnum<{
871
+ native: "native";
872
+ wrapped: "wrapped";
873
+ }>;
874
+ providerAddonId: z.ZodString;
875
+ providerNodeId: z.ZodString;
876
+ nativeAddonId: z.ZodString;
877
+ }, z.core.$strip>>;
878
+ }, z.core.$strip>>, import("./capability-definition.js").CapabilityMethodKind>;
782
879
  /**
783
880
  * Return the binding map for every device known to the hub. Used by
784
881
  * `SystemManager` warm-boot: a single round-trip resolves the
@@ -55,6 +55,7 @@ export declare const plateGalleryCapability: {
55
55
  readonly listPlates: import("./capability-definition.js").CapabilityMethodSchema<z.ZodOptional<z.ZodObject<{
56
56
  deviceId: z.ZodOptional<z.ZodNumber>;
57
57
  limit: z.ZodOptional<z.ZodNumber>;
58
+ includeCrops: z.ZodOptional<z.ZodBoolean>;
58
59
  }, z.core.$strip>>, z.ZodReadonly<z.ZodArray<z.ZodObject<{
59
60
  plateId: z.ZodString;
60
61
  deviceId: z.ZodNumber;
@@ -114,6 +115,7 @@ export declare const plateGalleryCapability: {
114
115
  text: z.ZodString;
115
116
  maxDistance: z.ZodOptional<z.ZodNumber>;
116
117
  limit: z.ZodOptional<z.ZodNumber>;
118
+ includeCrops: z.ZodOptional<z.ZodBoolean>;
117
119
  }, z.core.$strip>, z.ZodReadonly<z.ZodArray<z.ZodObject<{
118
120
  plateId: z.ZodString;
119
121
  deviceId: z.ZodNumber;
@@ -2219,6 +2219,13 @@ export type AppRouter = TrpcCoreRouter<{
2219
2219
  output: z.infer<typeof deviceManagerCapability.methods.getLinkedDevices.output>;
2220
2220
  meta: object;
2221
2221
  }>;
2222
+ getLinkedDevicesBatch: TRPCQueryProcedure<{
2223
+ input: {
2224
+ [x: string]: unknown;
2225
+ } & z.input<typeof deviceManagerCapability.methods.getLinkedDevicesBatch.input>;
2226
+ output: z.infer<typeof deviceManagerCapability.methods.getLinkedDevicesBatch.output>;
2227
+ meta: object;
2228
+ }>;
2222
2229
  getStreamSources: TRPCQueryProcedure<{
2223
2230
  input: {
2224
2231
  [x: string]: unknown;
@@ -2303,6 +2310,13 @@ export type AppRouter = TrpcCoreRouter<{
2303
2310
  output: z.infer<typeof deviceManagerCapability.methods.getBindings.output>;
2304
2311
  meta: object;
2305
2312
  }>;
2313
+ getBindingsBatch: TRPCQueryProcedure<{
2314
+ input: {
2315
+ [x: string]: unknown;
2316
+ } & z.input<typeof deviceManagerCapability.methods.getBindingsBatch.input>;
2317
+ output: z.infer<typeof deviceManagerCapability.methods.getBindingsBatch.output>;
2318
+ meta: object;
2319
+ }>;
2306
2320
  getAllBindings: TRPCQueryProcedure<{
2307
2321
  input: {
2308
2322
  [x: string]: unknown;
@@ -271,7 +271,7 @@ export interface DeviceProxy {
271
271
  readonly cameraPipelineConfig: Pick<InferDeviceProxyCap<typeof cameraPipelineConfigCapability>, 'getDeviceSettingsContribution' | 'getDeviceLiveContribution' | 'applyDeviceSettingsPatch'>;
272
272
  readonly deviceAdoption: Pick<InferDeviceProxyCap<typeof deviceAdoptionCapability>, 'getStatus'>;
273
273
  readonly deviceExport: Pick<InferDeviceProxyCap<typeof deviceExportCapability>, 'getDeviceSettingsContribution' | 'getDeviceLiveContribution' | 'applyDeviceSettingsPatch'>;
274
- readonly deviceManager: Pick<InferDeviceProxyCap<typeof deviceManagerCapability>, 'loadConfig' | 'loadRuntimeState' | 'loadMeta' | 'setName' | 'setLocation' | 'setType' | 'setIntegrationId' | 'setLinkDeviceId' | 'setPrimaryChildEntityId' | 'setChildLayout' | 'setDisplay' | 'getWireableFields' | 'setRole' | 'applyInitialMeta' | 'setMetadata' | 'setDisabled' | 'getDevice' | 'getLinkedDevices' | 'getStreamSources' | 'getConfigSchema' | 'getSettingsSchema' | 'updateConfig' | 'enable' | 'disable' | 'remove' | 'getStreamProfileMap' | 'setStreamProfileMap' | 'probeStreams' | 'getBindings' | 'getAllBindings' | 'setWrapperActive' | 'getDeviceSettingsAggregate' | 'getDeviceLiveInfoAggregate' | 'getDeviceAggregate' | 'runDeviceAction' | 'updateDeviceField' | 'updateDeviceFieldsBatch' | 'testField' | 'getDeviceStatusAggregate' | 'getDeviceSettingsContribution' | 'getDeviceLiveContribution' | 'applyDeviceSettingsPatch'>;
274
+ readonly deviceManager: Pick<InferDeviceProxyCap<typeof deviceManagerCapability>, 'loadConfig' | 'loadRuntimeState' | 'loadMeta' | 'setName' | 'setLocation' | 'setType' | 'setIntegrationId' | 'setLinkDeviceId' | 'setPrimaryChildEntityId' | 'setChildLayout' | 'setDisplay' | 'getWireableFields' | 'setRole' | 'applyInitialMeta' | 'setMetadata' | 'setDisabled' | 'getDevice' | 'getLinkedDevices' | 'getStreamSources' | 'getConfigSchema' | 'getSettingsSchema' | 'updateConfig' | 'enable' | 'disable' | 'remove' | 'getStreamProfileMap' | 'setStreamProfileMap' | 'probeStreams' | 'getBindings' | 'setWrapperActive' | 'getDeviceSettingsAggregate' | 'getDeviceLiveInfoAggregate' | 'getDeviceAggregate' | 'runDeviceAction' | 'updateDeviceField' | 'updateDeviceFieldsBatch' | 'testField' | 'getDeviceStatusAggregate' | 'getDeviceSettingsContribution' | 'getDeviceLiveContribution' | 'applyDeviceSettingsPatch'>;
275
275
  readonly deviceState: Pick<InferDeviceProxyCap<typeof deviceStateCapability>, 'getSnapshot' | 'getCapSlice' | 'setCapSlice'>;
276
276
  readonly faceGallery: Pick<InferDeviceProxyCap<typeof faceGalleryCapability>, 'listRecentFaces' | 'getFaceByTrack'>;
277
277
  readonly networkQuality: Pick<InferDeviceProxyCap<typeof networkQualityCapability>, 'getDeviceStats' | 'reportClientStats'>;
@@ -6,7 +6,7 @@
6
6
  * scope+access check inside `protectedProcedure` (see
7
7
  * `server/backend/src/api/trpc/trpc.middleware.ts`).
8
8
  *
9
- * Coverage: 953 method paths across 123 capabilities.
9
+ * Coverage: 955 method paths across 123 capabilities.
10
10
  */
11
11
  import type { CapabilityMethodAccess } from '../capabilities/capability-definition.js';
12
12
  export interface MethodAccessRecord {
@@ -6,8 +6,8 @@
6
6
  * system-scope cap that takes a deviceId was previously never device-filtered
7
7
  * — see the generator header).
8
8
  *
9
- * Coverage: 339 methods carry a device reference, of which
10
- * 124 are on SYSTEM-scope caps.
9
+ * Coverage: 342 methods carry a device reference, of which
10
+ * 127 are on SYSTEM-scope caps.
11
11
  *
12
12
  * Top-level fields, number arrays, and one-level arrays of objects carrying
13
13
  * a numeric device field (targets[].deviceId) are all mapped; the matcher
@@ -68,7 +68,7 @@ export interface SystemProxy {
68
68
  readonly decoder: Pick<InferProvider<typeof decoderCapability>, 'supportsCodec' | 'getInfo' | 'createSession' | 'destroySession' | 'pushPacket' | 'openStream' | 'pullFrames' | 'pullHandles' | 'getFrame' | 'getShmStats' | 'updateConfig' | 'getStats' | 'listActiveSessions' | 'reprobeHwaccel'>;
69
69
  readonly deviceAdoption: Pick<InferProvider<typeof deviceAdoptionCapability>, 'listCandidateFilters' | 'listCandidates' | 'getCandidate' | 'refresh' | 'adopt' | 'release' | 'resync'>;
70
70
  readonly deviceExport: Pick<InferProvider<typeof deviceExportCapability>, 'getStatus' | 'listSupportedDeviceKinds' | 'listExposedDevices' | 'exposeDevice' | 'unexposeDevice'>;
71
- readonly deviceManager: Pick<InferProvider<typeof deviceManagerCapability>, 'allocateDeviceId' | 'registerDevice' | 'removeDevice' | 'persistConfig' | 'getRoleDisplayDefaults' | 'setRoleDisplayDefaults' | 'listLocations' | 'addLocation' | 'removeLocation' | 'listPersistedByAddon' | 'listAll' | 'getChildren' | 'removeByIntegration' | 'listWrappersForCap' | 'listBindableCapsForDeviceType' | 'discoverDevices' | 'adoptDevice' | 'getCreationSchema' | 'createDevice' | 'testCreationField' | 'adoptionListCandidateFilters' | 'adoptionListCandidates' | 'adoptionRefresh' | 'adoptionAdopt' | 'adoptionRelease' | 'adoptionStartJob' | 'adoptionListJobs' | 'adoptionCancelJob' | 'adoptionResync' | 'discoveryProviders' | 'discoverAllProviders' | 'discoverProvider' | 'providerCreationType' | 'providerDiscoveryParamsSchema' | 'getDeviceStatusAggregateBatch'>;
71
+ readonly deviceManager: Pick<InferProvider<typeof deviceManagerCapability>, 'allocateDeviceId' | 'registerDevice' | 'removeDevice' | 'persistConfig' | 'getRoleDisplayDefaults' | 'setRoleDisplayDefaults' | 'listLocations' | 'addLocation' | 'removeLocation' | 'listPersistedByAddon' | 'listAll' | 'getChildren' | 'getLinkedDevicesBatch' | 'removeByIntegration' | 'getBindingsBatch' | 'getAllBindings' | 'listWrappersForCap' | 'listBindableCapsForDeviceType' | 'discoverDevices' | 'adoptDevice' | 'getCreationSchema' | 'createDevice' | 'testCreationField' | 'adoptionListCandidateFilters' | 'adoptionListCandidates' | 'adoptionRefresh' | 'adoptionAdopt' | 'adoptionRelease' | 'adoptionStartJob' | 'adoptionListJobs' | 'adoptionCancelJob' | 'adoptionResync' | 'discoveryProviders' | 'discoverAllProviders' | 'discoverProvider' | 'providerCreationType' | 'providerDiscoveryParamsSchema' | 'getDeviceStatusAggregateBatch'>;
72
72
  readonly deviceProvider: Pick<InferProvider<typeof deviceProviderCapability>, 'start' | 'stop' | 'getStatus' | 'getDevices' | 'supportsDiscovery' | 'discoverDevices' | 'getDiscoveryParamsSchema' | 'getManualCreationType' | 'adoptDiscoveredDevice' | 'supportsManualCreation' | 'getChildCreationSchema' | 'createDevice' | 'testCreationField'>;
73
73
  readonly deviceState: Pick<InferProvider<typeof deviceStateCapability>, 'getAllSnapshots'>;
74
74
  readonly faceGallery: Pick<InferProvider<typeof faceGalleryCapability>, 'listIdentities' | 'createIdentity' | 'renameIdentity' | 'deleteIdentity' | 'listIdentitySamples' | 'removeSample' | 'getFaceMedia' | 'assignFace' | 'unassignFace' | 'deleteFace' | 'assignFaces' | 'unassignFaces' | 'suggestFaceClusters'>;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_event_category = require("./event-category-EY0GNjV9.js");
3
- const require_sleep = require("./sleep-CizGYrCD.js");
3
+ const require_sleep = require("./sleep-CUuoW-kk.js");
4
4
  const require_canonical_hash = require("./canonical-hash-DNV8S5ET.js");
5
5
  const require_enums = require("./enums.js");
6
6
  const require_err_msg = require("./err-msg-COpsHMw2.js");
@@ -8598,6 +8598,27 @@ var LinkedDeviceSchema = zod.z.object({
8598
8598
  features: zod.z.array(zod.z.string()),
8599
8599
  producesTrackedEvents: zod.z.boolean().optional()
8600
8600
  });
8601
+ /** One camera's resolved linked set, tagged with the camera it belongs to.
8602
+ * The batch answer needs the tag; the single-device answer already has it
8603
+ * from the input, which is why `getLinkedDevices` keeps the untagged shape. */
8604
+ var LinkedDevicesForDeviceSchema = zod.z.object({
8605
+ deviceId: zod.z.number(),
8606
+ mode: LinkedDevicesModeSchema,
8607
+ devices: zod.z.array(LinkedDeviceSchema)
8608
+ });
8609
+ /** One device's binding map — the shape `getBindings`, `getBindingsBatch` and
8610
+ * `getAllBindings` all answer in. Declared once: three copies of the same
8611
+ * object literal is exactly how the three drift apart. */
8612
+ var DeviceBindingsForDeviceSchema = zod.z.object({
8613
+ deviceId: zod.z.number(),
8614
+ entries: zod.z.array(zod.z.object({
8615
+ capName: zod.z.string(),
8616
+ kind: zod.z.enum(["native", "wrapped"]),
8617
+ providerAddonId: zod.z.string(),
8618
+ providerNodeId: zod.z.string(),
8619
+ nativeAddonId: zod.z.string()
8620
+ }))
8621
+ });
8601
8622
  var SavedDeviceRowSchema = zod.z.object({
8602
8623
  /** Numeric id reserved at allocateDeviceId time. */
8603
8624
  id: zod.z.number(),
@@ -8960,7 +8981,21 @@ var deviceManagerCapability = {
8960
8981
  projection: zod.z.enum(["full", "slim"]).optional(),
8961
8982
  /** Return only camera devices. Filtering server-side instead of
8962
8983
  * shipping 293 rows to find 12. */
8963
- isCamera: zod.z.boolean().optional()
8984
+ isCamera: zod.z.boolean().optional(),
8985
+ /**
8986
+ * Return only these device ids. For the caller that already KNOWS the
8987
+ * handful it wants and needs a field the id-bearing answer does not
8988
+ * carry — the viewer's linked-devices panel joins `type` and `online`
8989
+ * onto ~8 linked ids and, unfiltered, dragged the fleet across to do
8990
+ * it: 433 KB slim / 958 KB full for 967 devices, on a query that
8991
+ * refetches on the reconcile interval, on a phone.
8992
+ *
8993
+ * Safe to send at a hub that predates it: Zod STRIPS unknown input
8994
+ * keys rather than rejecting them (verified against the live hub
8995
+ * 2026-08-25 — 967 rows came back), so an old hub answers exactly what
8996
+ * it answers today and the caller filters as it already does.
8997
+ */
8998
+ deviceIds: zod.z.array(zod.z.number()).optional()
8964
8999
  }), zod.z.array(DeviceInfoSchema)),
8965
9000
  /** Get a single device by numeric deviceId. */
8966
9001
  getDevice: require_sleep.method(zod.z.object({ deviceId: zod.z.number() }), DeviceInfoSchema.nullable()),
@@ -8979,6 +9014,23 @@ var deviceManagerCapability = {
8979
9014
  mode: LinkedDevicesModeSchema,
8980
9015
  devices: zod.z.array(LinkedDeviceSchema)
8981
9016
  })),
9017
+ /**
9018
+ * `getLinkedDevices` for MANY cameras, in one call.
9019
+ *
9020
+ * Not a convenience wrapper — a cost fix. Resolving one camera's linked set
9021
+ * needs the whole fleet as candidates (children ∪ same-location), so the
9022
+ * single-device path runs a full `listAll` per call. Asked per camera that
9023
+ * is N full-fleet sweeps of device-manager's event loop, and they do not
9024
+ * overlap: measured on the live hub 2026-08-25, 30 concurrent
9025
+ * `getLinkedDevices` took 4110 ms wall (median 4060 ms each) to return
9026
+ * 7260 bytes in total. The batch takes ONE sweep and one settings read per
9027
+ * camera.
9028
+ *
9029
+ * A device id that resolves to nothing still gets a row (`devices: []`) —
9030
+ * a caller that asked for thirty and got twenty-eight cannot tell which two
9031
+ * are missing, or that any are.
9032
+ */
9033
+ getLinkedDevicesBatch: require_sleep.method(zod.z.object({ deviceIds: zod.z.array(zod.z.number()) }), zod.z.array(LinkedDevicesForDeviceSchema)),
8982
9034
  /** Get stream sources for a camera device. */
8983
9035
  getStreamSources: require_sleep.method(zod.z.object({ deviceId: zod.z.number() }), zod.z.array(require_sleep.StreamSourceEntrySchema)),
8984
9036
  /** Get config entries (key + value + description) for a device. */
@@ -9036,16 +9088,22 @@ var deviceManagerCapability = {
9036
9088
  * currently-active provider (native or wrapper) + the underlying native
9037
9089
  * addon id, so consumers can decide routing without re-running discovery.
9038
9090
  */
9039
- getBindings: require_sleep.method(zod.z.object({ deviceId: zod.z.number() }), zod.z.object({
9040
- deviceId: zod.z.number(),
9041
- entries: zod.z.array(zod.z.object({
9042
- capName: zod.z.string(),
9043
- kind: zod.z.enum(["native", "wrapped"]),
9044
- providerAddonId: zod.z.string(),
9045
- providerNodeId: zod.z.string(),
9046
- nativeAddonId: zod.z.string()
9047
- }))
9048
- })),
9091
+ getBindings: require_sleep.method(zod.z.object({ deviceId: zod.z.number() }), DeviceBindingsForDeviceSchema),
9092
+ /**
9093
+ * `getBindings` for a NAMED set of devices, in one call.
9094
+ *
9095
+ * Between `getBindings` (one device) and `getAllBindings` (all 988) there
9096
+ * was nothing, so a caller that needs seventy-five either pays
9097
+ * seventy-five round-trips or drags the whole fleet across. Measured on
9098
+ * the live hub 2026-08-25: 75 concurrent `getBindings` = 1211 ms / 118 KB,
9099
+ * `getAllBindings({})` = 511 ms / 679 KB. Neither is the right answer to
9100
+ * "these seventy-five".
9101
+ *
9102
+ * Same resolver, same routing rules, same per-device shape as
9103
+ * `getBindings`; ids are deduped and a device with no bindings answers
9104
+ * `entries: []` rather than dropping out.
9105
+ */
9106
+ getBindingsBatch: require_sleep.method(zod.z.object({ deviceIds: zod.z.array(zod.z.number()) }), zod.z.array(DeviceBindingsForDeviceSchema)),
9049
9107
  /**
9050
9108
  * Return the binding map for every device known to the hub. Used by
9051
9109
  * `SystemManager` warm-boot: a single round-trip resolves the
@@ -9054,16 +9112,7 @@ var deviceManagerCapability = {
9054
9112
  * device add/remove) — clients invalidate via the
9055
9113
  * `capability.binding-changed` event.
9056
9114
  */
9057
- getAllBindings: require_sleep.method(zod.z.object({}), zod.z.array(zod.z.object({
9058
- deviceId: zod.z.number(),
9059
- entries: zod.z.array(zod.z.object({
9060
- capName: zod.z.string(),
9061
- kind: zod.z.enum(["native", "wrapped"]),
9062
- providerAddonId: zod.z.string(),
9063
- providerNodeId: zod.z.string(),
9064
- nativeAddonId: zod.z.string()
9065
- }))
9066
- }))),
9115
+ getAllBindings: require_sleep.method(zod.z.object({}), zod.z.array(DeviceBindingsForDeviceSchema)),
9067
9116
  /**
9068
9117
  * Activate (or deactivate) a wrapper addon for a (device, cap) pair.
9069
9118
  * Persists the binding via ctx.settings. active=false clears the wrapper
@@ -26912,8 +26961,10 @@ var PlateInfoSchema = zod.z.object({
26912
26961
  keyFrameMediaKey: zod.z.string().optional(),
26913
26962
  base64: zod.z.string().optional(),
26914
26963
  /**
26915
- * Same crop as a data-plane URL. `getPlateByTrack` returns this and
26916
- * never inlines JPEG; `listPlates` still inlines for the admin-ui.
26964
+ * Same crop as a data-plane URL, always present when the plate has a stored
26965
+ * crop. `getPlateByTrack` returns this and never inlines JPEG; `listPlates`
26966
+ * and `searchPlates` inline the crop only when their `includeCrops` input is
26967
+ * left at its `true` default.
26917
26968
  */
26918
26969
  cropUrl: zod.z.string().optional()
26919
26970
  });
@@ -26946,7 +26997,25 @@ var plateGalleryCapability = {
26946
26997
  methods: {
26947
26998
  listPlates: require_sleep.method(zod.z.object({
26948
26999
  deviceId: zod.z.number().int().optional(),
26949
- limit: zod.z.number().int().positive().optional()
27000
+ limit: zod.z.number().int().positive().optional(),
27001
+ /**
27002
+ * Inline the base64 crop on every row. Default `true` — the existing
27003
+ * behaviour, kept so no caller breaks.
27004
+ *
27005
+ * Set `false` once the caller renders {@link PlateInfo.cropUrl}.
27006
+ * Measured on the live hub at the 500 rows the Plates view asks for:
27007
+ * 879,403 B and 27.7 s with the crops inline, against a few KiB of
27008
+ * metadata without them — and the browser then caches the images.
27009
+ *
27010
+ * This is the plate twin of `faceGallery.listRecentFaces`'s option;
27011
+ * plates were the one gallery list left without it.
27012
+ *
27013
+ * **This is an INPUT field, so it does not reach the addon until the
27014
+ * next train.** The hub router validates cap inputs against its own
27015
+ * compiled Zod and strips a key it does not know. Until the train
27016
+ * ships, sending `false` is harmless and keeps the crops inline.
27017
+ */
27018
+ includeCrops: zod.z.boolean().optional()
26950
27019
  }).optional(), zod.z.array(PlateInfoSchema).readonly()),
26951
27020
  getPlateByTrack: require_sleep.method(zod.z.object({
26952
27021
  deviceId: zod.z.number().int(),
@@ -26957,7 +27026,9 @@ var plateGalleryCapability = {
26957
27026
  searchPlates: require_sleep.method(zod.z.object({
26958
27027
  text: zod.z.string().min(1),
26959
27028
  maxDistance: zod.z.number().int().min(0).optional(),
26960
- limit: zod.z.number().int().positive().optional()
27029
+ limit: zod.z.number().int().positive().optional(),
27030
+ /** See `listPlates.includeCrops`. Default `true`. */
27031
+ includeCrops: zod.z.boolean().optional()
26961
27032
  }), zod.z.array(PlateInfoSchema).readonly()),
26962
27033
  /** Suggest groups of near-identical reads (same physical plate) for review/merge. */
26963
27034
  suggestPlateClusters: require_sleep.method(zod.z.object({
@@ -36048,6 +36119,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
36048
36119
  addonId: null,
36049
36120
  access: "view"
36050
36121
  },
36122
+ "deviceManager.getBindingsBatch": {
36123
+ capName: "device-manager",
36124
+ capScope: "system",
36125
+ addonId: null,
36126
+ access: "view"
36127
+ },
36051
36128
  "deviceManager.getChildren": {
36052
36129
  capName: "device-manager",
36053
36130
  capScope: "system",
@@ -36108,6 +36185,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
36108
36185
  addonId: null,
36109
36186
  access: "view"
36110
36187
  },
36188
+ "deviceManager.getLinkedDevicesBatch": {
36189
+ capName: "device-manager",
36190
+ capScope: "system",
36191
+ addonId: null,
36192
+ access: "view"
36193
+ },
36111
36194
  "deviceManager.getRoleDisplayDefaults": {
36112
36195
  capName: "device-manager",
36113
36196
  capScope: "system",
@@ -41012,6 +41095,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
41012
41095
  form: "single",
41013
41096
  optional: false
41014
41097
  }],
41098
+ "deviceManager.getBindingsBatch": [{
41099
+ name: "deviceIds",
41100
+ form: "array",
41101
+ optional: false
41102
+ }],
41015
41103
  "deviceManager.getChildren": [{
41016
41104
  name: "parentDeviceId",
41017
41105
  form: "single",
@@ -41057,6 +41145,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
41057
41145
  form: "single",
41058
41146
  optional: false
41059
41147
  }],
41148
+ "deviceManager.getLinkedDevicesBatch": [{
41149
+ name: "deviceIds",
41150
+ form: "array",
41151
+ optional: false
41152
+ }],
41060
41153
  "deviceManager.getSettingsSchema": [{
41061
41154
  name: "deviceId",
41062
41155
  form: "single",
@@ -41077,6 +41170,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
41077
41170
  form: "single",
41078
41171
  optional: false
41079
41172
  }],
41173
+ "deviceManager.listAll": [{
41174
+ name: "deviceIds",
41175
+ form: "array",
41176
+ optional: true
41177
+ }],
41080
41178
  "deviceManager.loadConfig": [{
41081
41179
  name: "deviceId",
41082
41180
  form: "single",
@@ -42467,6 +42565,7 @@ var SYSTEM_SCOPE_DEVICE_METHODS = [
42467
42565
  "deviceManager.disable",
42468
42566
  "deviceManager.enable",
42469
42567
  "deviceManager.getBindings",
42568
+ "deviceManager.getBindingsBatch",
42470
42569
  "deviceManager.getChildren",
42471
42570
  "deviceManager.getConfigSchema",
42472
42571
  "deviceManager.getDevice",
@@ -42476,10 +42575,12 @@ var SYSTEM_SCOPE_DEVICE_METHODS = [
42476
42575
  "deviceManager.getDeviceStatusAggregate",
42477
42576
  "deviceManager.getDeviceStatusAggregateBatch",
42478
42577
  "deviceManager.getLinkedDevices",
42578
+ "deviceManager.getLinkedDevicesBatch",
42479
42579
  "deviceManager.getSettingsSchema",
42480
42580
  "deviceManager.getStreamProfileMap",
42481
42581
  "deviceManager.getStreamSources",
42482
42582
  "deviceManager.getWireableFields",
42583
+ "deviceManager.listAll",
42483
42584
  "deviceManager.loadConfig",
42484
42585
  "deviceManager.loadMeta",
42485
42586
  "deviceManager.loadRuntimeState",
@@ -43202,7 +43303,10 @@ function createSystemProxy(api) {
43202
43303
  listPersistedByAddon: (input) => dispatch("deviceManager", "listPersistedByAddon", "query", input),
43203
43304
  listAll: (input) => dispatch("deviceManager", "listAll", "query", input),
43204
43305
  getChildren: (input) => dispatch("deviceManager", "getChildren", "query", input),
43306
+ getLinkedDevicesBatch: (input) => dispatch("deviceManager", "getLinkedDevicesBatch", "query", input),
43205
43307
  removeByIntegration: (input) => dispatch("deviceManager", "removeByIntegration", "mutation", input),
43308
+ getBindingsBatch: (input) => dispatch("deviceManager", "getBindingsBatch", "query", input),
43309
+ getAllBindings: (input) => dispatch("deviceManager", "getAllBindings", "query", input),
43206
43310
  listWrappersForCap: (input) => dispatch("deviceManager", "listWrappersForCap", "query", input),
43207
43311
  listBindableCapsForDeviceType: (input) => dispatch("deviceManager", "listBindableCapsForDeviceType", "query", input),
43208
43312
  discoverDevices: (input) => dispatch("deviceManager", "discoverDevices", "mutation", input),
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as EventCategory } from "./event-category-CIa_iT6b.mjs";
2
- import { $ as DecodedFrameSchema, A as event, B as ReadinessRegistry, C as DeviceFeature, Ct as isEvent, D as DEFAULT_RUNTIME_STATE_DURABILITY, Dt as collectHydratedFieldValues, E as adminUiCapability, Et as collectHydratedFieldEntries, F as systemMethod, G as BrokerStatsSchema, H as emitDownForOwnedCaps, I as CAP_NODE_PIN_CONTEXT_KEY, J as CamProfileSchema, K as BrokerStatusSchema, L as nodePin, M as isDeviceConfigCap, N as method, O as DEVICE_SETTINGS_CONTRIBUTION_METHODS, Ot as hydrateSchema, P as resolveCapMount, Q as DecodedAudioChunkSchema, R as readNodePin, S as ChargingStatus, St as emitReadiness, T as DeviceType, Tt as WELL_KNOWN_TAB_MAP, U as readinessKey, V as ReadinessTimeoutError, W as scopeKey, X as CamStreamResolutionSchema, Y as CamStreamKindSchema, Z as CameraStreamSchema, _ as createMirrorSource, _t as DisposerChain, a as asJsonObject, at as ProfileSlotStatusSchema, b as deviceOpsCapability, bt as createDurableState, c as parseJsonArray, ct as SubscribeAudioChunksInputSchema, d as BOOT_RECOVERY_BACKOFF_MS, dt as SubscribeFramesResultSchema, et as EncodedPacketSchema, f as DEVICE_SCOPED_CAPS, ft as makeProfileBrokerId, g as createLazyTrpcSource, gt as DATAPLANE_SECRET_HEADER, h as createEventBusSliceSource, ht as selectAssignedProfileSlots, i as asJsonArray, it as ProfileSlotSchema, j as expandCapMethods, k as DEVICE_STATUS_METHOD, kt as resolveHydratedFieldValue, l as parseJsonObject, lt as SubscribeAudioChunksResultSchema, m as createDeviceProxy, mt as parseProfileBrokerId, n as sleepCancellable, nt as FrameHandleSchema, o as asNumber, ot as StreamSourceEntrySchema, p as isDeviceScopedCap, pt as makeSourceBrokerId, q as CAM_PROFILE_ORDER, r as asBoolean, rt as ProfileRtspEntrySchema, s as asString, st as StreamSourceSchema, t as sleep, tt as FrameHandleFormatSchema, u as parseJsonUnknown, ut as SubscribeFramesInputSchema, v as createSliceHandle, vt as BaseAddon, w as DeviceRole, wt as WELL_KNOWN_TABS, x as viewerUiCapability, xt as createEvent, y as RawStateResultSchema, yt as normalizeAddonInitResult, z as toNodeId } from "./sleep-Cs9MWLcT.mjs";
2
+ import { $ as DecodedFrameSchema, A as event, B as ReadinessRegistry, C as DeviceFeature, Ct as isEvent, D as DEFAULT_RUNTIME_STATE_DURABILITY, Dt as collectHydratedFieldValues, E as adminUiCapability, Et as collectHydratedFieldEntries, F as systemMethod, G as BrokerStatsSchema, H as emitDownForOwnedCaps, I as CAP_NODE_PIN_CONTEXT_KEY, J as CamProfileSchema, K as BrokerStatusSchema, L as nodePin, M as isDeviceConfigCap, N as method, O as DEVICE_SETTINGS_CONTRIBUTION_METHODS, Ot as hydrateSchema, P as resolveCapMount, Q as DecodedAudioChunkSchema, R as readNodePin, S as ChargingStatus, St as emitReadiness, T as DeviceType, Tt as WELL_KNOWN_TAB_MAP, U as readinessKey, V as ReadinessTimeoutError, W as scopeKey, X as CamStreamResolutionSchema, Y as CamStreamKindSchema, Z as CameraStreamSchema, _ as createMirrorSource, _t as DisposerChain, a as asJsonObject, at as ProfileSlotStatusSchema, b as deviceOpsCapability, bt as createDurableState, c as parseJsonArray, ct as SubscribeAudioChunksInputSchema, d as BOOT_RECOVERY_BACKOFF_MS, dt as SubscribeFramesResultSchema, et as EncodedPacketSchema, f as DEVICE_SCOPED_CAPS, ft as makeProfileBrokerId, g as createLazyTrpcSource, gt as DATAPLANE_SECRET_HEADER, h as createEventBusSliceSource, ht as selectAssignedProfileSlots, i as asJsonArray, it as ProfileSlotSchema, j as expandCapMethods, k as DEVICE_STATUS_METHOD, kt as resolveHydratedFieldValue, l as parseJsonObject, lt as SubscribeAudioChunksResultSchema, m as createDeviceProxy, mt as parseProfileBrokerId, n as sleepCancellable, nt as FrameHandleSchema, o as asNumber, ot as StreamSourceEntrySchema, p as isDeviceScopedCap, pt as makeSourceBrokerId, q as CAM_PROFILE_ORDER, r as asBoolean, rt as ProfileRtspEntrySchema, s as asString, st as StreamSourceSchema, t as sleep, tt as FrameHandleFormatSchema, u as parseJsonUnknown, ut as SubscribeFramesInputSchema, v as createSliceHandle, vt as BaseAddon, w as DeviceRole, wt as WELL_KNOWN_TABS, x as viewerUiCapability, xt as createEvent, y as RawStateResultSchema, yt as normalizeAddonInitResult, z as toNodeId } from "./sleep-BLxqGLY0.mjs";
3
3
  import { a as buildAudioArgs, c as buildVideoArgs, d as logBannerArgs, f as pickVideoEncoder, i as audioPlanFromEncodeProfile, l as invocationFromEncodeProfile, n as Fmp4BoxSplitter, o as buildFfmpegArgs, r as AUDIO_PRESETS, s as buildInputArgs, t as canonicalHash, u as isSoftwareDecode } from "./canonical-hash-rO1sRmEK.mjs";
4
4
  import { EventSourceType } from "./enums.mjs";
5
5
  import { t as errMsg } from "./err-msg-IQTHeDzc.mjs";
@@ -8597,6 +8597,27 @@ var LinkedDeviceSchema = z.object({
8597
8597
  features: z.array(z.string()),
8598
8598
  producesTrackedEvents: z.boolean().optional()
8599
8599
  });
8600
+ /** One camera's resolved linked set, tagged with the camera it belongs to.
8601
+ * The batch answer needs the tag; the single-device answer already has it
8602
+ * from the input, which is why `getLinkedDevices` keeps the untagged shape. */
8603
+ var LinkedDevicesForDeviceSchema = z.object({
8604
+ deviceId: z.number(),
8605
+ mode: LinkedDevicesModeSchema,
8606
+ devices: z.array(LinkedDeviceSchema)
8607
+ });
8608
+ /** One device's binding map — the shape `getBindings`, `getBindingsBatch` and
8609
+ * `getAllBindings` all answer in. Declared once: three copies of the same
8610
+ * object literal is exactly how the three drift apart. */
8611
+ var DeviceBindingsForDeviceSchema = z.object({
8612
+ deviceId: z.number(),
8613
+ entries: z.array(z.object({
8614
+ capName: z.string(),
8615
+ kind: z.enum(["native", "wrapped"]),
8616
+ providerAddonId: z.string(),
8617
+ providerNodeId: z.string(),
8618
+ nativeAddonId: z.string()
8619
+ }))
8620
+ });
8600
8621
  var SavedDeviceRowSchema = z.object({
8601
8622
  /** Numeric id reserved at allocateDeviceId time. */
8602
8623
  id: z.number(),
@@ -8959,7 +8980,21 @@ var deviceManagerCapability = {
8959
8980
  projection: z.enum(["full", "slim"]).optional(),
8960
8981
  /** Return only camera devices. Filtering server-side instead of
8961
8982
  * shipping 293 rows to find 12. */
8962
- isCamera: z.boolean().optional()
8983
+ isCamera: z.boolean().optional(),
8984
+ /**
8985
+ * Return only these device ids. For the caller that already KNOWS the
8986
+ * handful it wants and needs a field the id-bearing answer does not
8987
+ * carry — the viewer's linked-devices panel joins `type` and `online`
8988
+ * onto ~8 linked ids and, unfiltered, dragged the fleet across to do
8989
+ * it: 433 KB slim / 958 KB full for 967 devices, on a query that
8990
+ * refetches on the reconcile interval, on a phone.
8991
+ *
8992
+ * Safe to send at a hub that predates it: Zod STRIPS unknown input
8993
+ * keys rather than rejecting them (verified against the live hub
8994
+ * 2026-08-25 — 967 rows came back), so an old hub answers exactly what
8995
+ * it answers today and the caller filters as it already does.
8996
+ */
8997
+ deviceIds: z.array(z.number()).optional()
8963
8998
  }), z.array(DeviceInfoSchema)),
8964
8999
  /** Get a single device by numeric deviceId. */
8965
9000
  getDevice: method(z.object({ deviceId: z.number() }), DeviceInfoSchema.nullable()),
@@ -8978,6 +9013,23 @@ var deviceManagerCapability = {
8978
9013
  mode: LinkedDevicesModeSchema,
8979
9014
  devices: z.array(LinkedDeviceSchema)
8980
9015
  })),
9016
+ /**
9017
+ * `getLinkedDevices` for MANY cameras, in one call.
9018
+ *
9019
+ * Not a convenience wrapper — a cost fix. Resolving one camera's linked set
9020
+ * needs the whole fleet as candidates (children ∪ same-location), so the
9021
+ * single-device path runs a full `listAll` per call. Asked per camera that
9022
+ * is N full-fleet sweeps of device-manager's event loop, and they do not
9023
+ * overlap: measured on the live hub 2026-08-25, 30 concurrent
9024
+ * `getLinkedDevices` took 4110 ms wall (median 4060 ms each) to return
9025
+ * 7260 bytes in total. The batch takes ONE sweep and one settings read per
9026
+ * camera.
9027
+ *
9028
+ * A device id that resolves to nothing still gets a row (`devices: []`) —
9029
+ * a caller that asked for thirty and got twenty-eight cannot tell which two
9030
+ * are missing, or that any are.
9031
+ */
9032
+ getLinkedDevicesBatch: method(z.object({ deviceIds: z.array(z.number()) }), z.array(LinkedDevicesForDeviceSchema)),
8981
9033
  /** Get stream sources for a camera device. */
8982
9034
  getStreamSources: method(z.object({ deviceId: z.number() }), z.array(StreamSourceEntrySchema)),
8983
9035
  /** Get config entries (key + value + description) for a device. */
@@ -9035,16 +9087,22 @@ var deviceManagerCapability = {
9035
9087
  * currently-active provider (native or wrapper) + the underlying native
9036
9088
  * addon id, so consumers can decide routing without re-running discovery.
9037
9089
  */
9038
- getBindings: method(z.object({ deviceId: z.number() }), z.object({
9039
- deviceId: z.number(),
9040
- entries: z.array(z.object({
9041
- capName: z.string(),
9042
- kind: z.enum(["native", "wrapped"]),
9043
- providerAddonId: z.string(),
9044
- providerNodeId: z.string(),
9045
- nativeAddonId: z.string()
9046
- }))
9047
- })),
9090
+ getBindings: method(z.object({ deviceId: z.number() }), DeviceBindingsForDeviceSchema),
9091
+ /**
9092
+ * `getBindings` for a NAMED set of devices, in one call.
9093
+ *
9094
+ * Between `getBindings` (one device) and `getAllBindings` (all 988) there
9095
+ * was nothing, so a caller that needs seventy-five either pays
9096
+ * seventy-five round-trips or drags the whole fleet across. Measured on
9097
+ * the live hub 2026-08-25: 75 concurrent `getBindings` = 1211 ms / 118 KB,
9098
+ * `getAllBindings({})` = 511 ms / 679 KB. Neither is the right answer to
9099
+ * "these seventy-five".
9100
+ *
9101
+ * Same resolver, same routing rules, same per-device shape as
9102
+ * `getBindings`; ids are deduped and a device with no bindings answers
9103
+ * `entries: []` rather than dropping out.
9104
+ */
9105
+ getBindingsBatch: method(z.object({ deviceIds: z.array(z.number()) }), z.array(DeviceBindingsForDeviceSchema)),
9048
9106
  /**
9049
9107
  * Return the binding map for every device known to the hub. Used by
9050
9108
  * `SystemManager` warm-boot: a single round-trip resolves the
@@ -9053,16 +9111,7 @@ var deviceManagerCapability = {
9053
9111
  * device add/remove) — clients invalidate via the
9054
9112
  * `capability.binding-changed` event.
9055
9113
  */
9056
- getAllBindings: method(z.object({}), z.array(z.object({
9057
- deviceId: z.number(),
9058
- entries: z.array(z.object({
9059
- capName: z.string(),
9060
- kind: z.enum(["native", "wrapped"]),
9061
- providerAddonId: z.string(),
9062
- providerNodeId: z.string(),
9063
- nativeAddonId: z.string()
9064
- }))
9065
- }))),
9114
+ getAllBindings: method(z.object({}), z.array(DeviceBindingsForDeviceSchema)),
9066
9115
  /**
9067
9116
  * Activate (or deactivate) a wrapper addon for a (device, cap) pair.
9068
9117
  * Persists the binding via ctx.settings. active=false clears the wrapper
@@ -26911,8 +26960,10 @@ var PlateInfoSchema = z.object({
26911
26960
  keyFrameMediaKey: z.string().optional(),
26912
26961
  base64: z.string().optional(),
26913
26962
  /**
26914
- * Same crop as a data-plane URL. `getPlateByTrack` returns this and
26915
- * never inlines JPEG; `listPlates` still inlines for the admin-ui.
26963
+ * Same crop as a data-plane URL, always present when the plate has a stored
26964
+ * crop. `getPlateByTrack` returns this and never inlines JPEG; `listPlates`
26965
+ * and `searchPlates` inline the crop only when their `includeCrops` input is
26966
+ * left at its `true` default.
26916
26967
  */
26917
26968
  cropUrl: z.string().optional()
26918
26969
  });
@@ -26945,7 +26996,25 @@ var plateGalleryCapability = {
26945
26996
  methods: {
26946
26997
  listPlates: method(z.object({
26947
26998
  deviceId: z.number().int().optional(),
26948
- limit: z.number().int().positive().optional()
26999
+ limit: z.number().int().positive().optional(),
27000
+ /**
27001
+ * Inline the base64 crop on every row. Default `true` — the existing
27002
+ * behaviour, kept so no caller breaks.
27003
+ *
27004
+ * Set `false` once the caller renders {@link PlateInfo.cropUrl}.
27005
+ * Measured on the live hub at the 500 rows the Plates view asks for:
27006
+ * 879,403 B and 27.7 s with the crops inline, against a few KiB of
27007
+ * metadata without them — and the browser then caches the images.
27008
+ *
27009
+ * This is the plate twin of `faceGallery.listRecentFaces`'s option;
27010
+ * plates were the one gallery list left without it.
27011
+ *
27012
+ * **This is an INPUT field, so it does not reach the addon until the
27013
+ * next train.** The hub router validates cap inputs against its own
27014
+ * compiled Zod and strips a key it does not know. Until the train
27015
+ * ships, sending `false` is harmless and keeps the crops inline.
27016
+ */
27017
+ includeCrops: z.boolean().optional()
26949
27018
  }).optional(), z.array(PlateInfoSchema).readonly()),
26950
27019
  getPlateByTrack: method(z.object({
26951
27020
  deviceId: z.number().int(),
@@ -26956,7 +27025,9 @@ var plateGalleryCapability = {
26956
27025
  searchPlates: method(z.object({
26957
27026
  text: z.string().min(1),
26958
27027
  maxDistance: z.number().int().min(0).optional(),
26959
- limit: z.number().int().positive().optional()
27028
+ limit: z.number().int().positive().optional(),
27029
+ /** See `listPlates.includeCrops`. Default `true`. */
27030
+ includeCrops: z.boolean().optional()
26960
27031
  }), z.array(PlateInfoSchema).readonly()),
26961
27032
  /** Suggest groups of near-identical reads (same physical plate) for review/merge. */
26962
27033
  suggestPlateClusters: method(z.object({
@@ -36040,6 +36111,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
36040
36111
  addonId: null,
36041
36112
  access: "view"
36042
36113
  },
36114
+ "deviceManager.getBindingsBatch": {
36115
+ capName: "device-manager",
36116
+ capScope: "system",
36117
+ addonId: null,
36118
+ access: "view"
36119
+ },
36043
36120
  "deviceManager.getChildren": {
36044
36121
  capName: "device-manager",
36045
36122
  capScope: "system",
@@ -36100,6 +36177,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
36100
36177
  addonId: null,
36101
36178
  access: "view"
36102
36179
  },
36180
+ "deviceManager.getLinkedDevicesBatch": {
36181
+ capName: "device-manager",
36182
+ capScope: "system",
36183
+ addonId: null,
36184
+ access: "view"
36185
+ },
36103
36186
  "deviceManager.getRoleDisplayDefaults": {
36104
36187
  capName: "device-manager",
36105
36188
  capScope: "system",
@@ -41004,6 +41087,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
41004
41087
  form: "single",
41005
41088
  optional: false
41006
41089
  }],
41090
+ "deviceManager.getBindingsBatch": [{
41091
+ name: "deviceIds",
41092
+ form: "array",
41093
+ optional: false
41094
+ }],
41007
41095
  "deviceManager.getChildren": [{
41008
41096
  name: "parentDeviceId",
41009
41097
  form: "single",
@@ -41049,6 +41137,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
41049
41137
  form: "single",
41050
41138
  optional: false
41051
41139
  }],
41140
+ "deviceManager.getLinkedDevicesBatch": [{
41141
+ name: "deviceIds",
41142
+ form: "array",
41143
+ optional: false
41144
+ }],
41052
41145
  "deviceManager.getSettingsSchema": [{
41053
41146
  name: "deviceId",
41054
41147
  form: "single",
@@ -41069,6 +41162,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
41069
41162
  form: "single",
41070
41163
  optional: false
41071
41164
  }],
41165
+ "deviceManager.listAll": [{
41166
+ name: "deviceIds",
41167
+ form: "array",
41168
+ optional: true
41169
+ }],
41072
41170
  "deviceManager.loadConfig": [{
41073
41171
  name: "deviceId",
41074
41172
  form: "single",
@@ -42459,6 +42557,7 @@ var SYSTEM_SCOPE_DEVICE_METHODS = [
42459
42557
  "deviceManager.disable",
42460
42558
  "deviceManager.enable",
42461
42559
  "deviceManager.getBindings",
42560
+ "deviceManager.getBindingsBatch",
42462
42561
  "deviceManager.getChildren",
42463
42562
  "deviceManager.getConfigSchema",
42464
42563
  "deviceManager.getDevice",
@@ -42468,10 +42567,12 @@ var SYSTEM_SCOPE_DEVICE_METHODS = [
42468
42567
  "deviceManager.getDeviceStatusAggregate",
42469
42568
  "deviceManager.getDeviceStatusAggregateBatch",
42470
42569
  "deviceManager.getLinkedDevices",
42570
+ "deviceManager.getLinkedDevicesBatch",
42471
42571
  "deviceManager.getSettingsSchema",
42472
42572
  "deviceManager.getStreamProfileMap",
42473
42573
  "deviceManager.getStreamSources",
42474
42574
  "deviceManager.getWireableFields",
42575
+ "deviceManager.listAll",
42475
42576
  "deviceManager.loadConfig",
42476
42577
  "deviceManager.loadMeta",
42477
42578
  "deviceManager.loadRuntimeState",
@@ -43194,7 +43295,10 @@ function createSystemProxy(api) {
43194
43295
  listPersistedByAddon: (input) => dispatch("deviceManager", "listPersistedByAddon", "query", input),
43195
43296
  listAll: (input) => dispatch("deviceManager", "listAll", "query", input),
43196
43297
  getChildren: (input) => dispatch("deviceManager", "getChildren", "query", input),
43298
+ getLinkedDevicesBatch: (input) => dispatch("deviceManager", "getLinkedDevicesBatch", "query", input),
43197
43299
  removeByIntegration: (input) => dispatch("deviceManager", "removeByIntegration", "mutation", input),
43300
+ getBindingsBatch: (input) => dispatch("deviceManager", "getBindingsBatch", "query", input),
43301
+ getAllBindings: (input) => dispatch("deviceManager", "getAllBindings", "query", input),
43198
43302
  listWrappersForCap: (input) => dispatch("deviceManager", "listWrappersForCap", "query", input),
43199
43303
  listBindableCapsForDeviceType: (input) => dispatch("deviceManager", "listBindableCapsForDeviceType", "query", input),
43200
43304
  discoverDevices: (input) => dispatch("deviceManager", "discoverDevices", "mutation", input),
@@ -3501,7 +3501,6 @@ function createDeviceProxy(api, binding, opts) {
3501
3501
  setStreamProfileMap: (input) => dispatchSystem("deviceManager", "setStreamProfileMap", "mutation", input),
3502
3502
  probeStreams: (input) => dispatchSystem("deviceManager", "probeStreams", "mutation", input),
3503
3503
  getBindings: (input) => dispatchSystem("deviceManager", "getBindings", "query", input),
3504
- getAllBindings: (input) => dispatchSystem("deviceManager", "getAllBindings", "query", input),
3505
3504
  setWrapperActive: (input) => dispatchSystem("deviceManager", "setWrapperActive", "mutation", input),
3506
3505
  getDeviceSettingsAggregate: (input) => dispatchSystem("deviceManager", "getDeviceSettingsAggregate", "query", input),
3507
3506
  getDeviceLiveInfoAggregate: (input) => dispatchSystem("deviceManager", "getDeviceLiveInfoAggregate", "query", input),
@@ -3501,7 +3501,6 @@ function createDeviceProxy(api, binding, opts) {
3501
3501
  setStreamProfileMap: (input) => dispatchSystem("deviceManager", "setStreamProfileMap", "mutation", input),
3502
3502
  probeStreams: (input) => dispatchSystem("deviceManager", "probeStreams", "mutation", input),
3503
3503
  getBindings: (input) => dispatchSystem("deviceManager", "getBindings", "query", input),
3504
- getAllBindings: (input) => dispatchSystem("deviceManager", "getAllBindings", "query", input),
3505
3504
  setWrapperActive: (input) => dispatchSystem("deviceManager", "setWrapperActive", "mutation", input),
3506
3505
  getDeviceSettingsAggregate: (input) => dispatchSystem("deviceManager", "getDeviceSettingsAggregate", "query", input),
3507
3506
  getDeviceLiveInfoAggregate: (input) => dispatchSystem("deviceManager", "getDeviceLiveInfoAggregate", "query", input),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/types",
3
- "version": "1.2.103",
3
+ "version": "1.2.105",
4
4
  "description": "Shared types, interfaces, and model catalogs for the CamStack detection ecosystem",
5
5
  "keywords": [
6
6
  "camstack",