@camstack/addon-post-analysis 1.2.122 → 1.2.124

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.
@@ -27142,8 +27142,10 @@ var PlateInfoSchema = object({
27142
27142
  keyFrameMediaKey: string().optional(),
27143
27143
  base64: string().optional(),
27144
27144
  /**
27145
- * Same crop as a data-plane URL. `getPlateByTrack` returns this and
27146
- * never inlines JPEG; `listPlates` still inlines for the admin-ui.
27145
+ * Same crop as a data-plane URL, always present when the plate has a stored
27146
+ * crop. `getPlateByTrack` returns this and never inlines JPEG; `listPlates`
27147
+ * and `searchPlates` inline the crop only when their `includeCrops` input is
27148
+ * left at its `true` default.
27147
27149
  */
27148
27150
  cropUrl: string().optional()
27149
27151
  });
@@ -27176,7 +27178,25 @@ var plateGalleryCapability = {
27176
27178
  methods: {
27177
27179
  listPlates: method(object({
27178
27180
  deviceId: number().int().optional(),
27179
- limit: number().int().positive().optional()
27181
+ limit: number().int().positive().optional(),
27182
+ /**
27183
+ * Inline the base64 crop on every row. Default `true` — the existing
27184
+ * behaviour, kept so no caller breaks.
27185
+ *
27186
+ * Set `false` once the caller renders {@link PlateInfo.cropUrl}.
27187
+ * Measured on the live hub at the 500 rows the Plates view asks for:
27188
+ * 879,403 B and 27.7 s with the crops inline, against a few KiB of
27189
+ * metadata without them — and the browser then caches the images.
27190
+ *
27191
+ * This is the plate twin of `faceGallery.listRecentFaces`'s option;
27192
+ * plates were the one gallery list left without it.
27193
+ *
27194
+ * **This is an INPUT field, so it does not reach the addon until the
27195
+ * next train.** The hub router validates cap inputs against its own
27196
+ * compiled Zod and strips a key it does not know. Until the train
27197
+ * ships, sending `false` is harmless and keeps the crops inline.
27198
+ */
27199
+ includeCrops: boolean().optional()
27180
27200
  }).optional(), array(PlateInfoSchema).readonly()),
27181
27201
  getPlateByTrack: method(object({
27182
27202
  deviceId: number().int(),
@@ -27187,7 +27207,9 @@ var plateGalleryCapability = {
27187
27207
  searchPlates: method(object({
27188
27208
  text: string().min(1),
27189
27209
  maxDistance: number().int().min(0).optional(),
27190
- limit: number().int().positive().optional()
27210
+ limit: number().int().positive().optional(),
27211
+ /** See `listPlates.includeCrops`. Default `true`. */
27212
+ includeCrops: boolean().optional()
27191
27213
  }), array(PlateInfoSchema).readonly()),
27192
27214
  /** Suggest groups of near-identical reads (same physical plate) for review/merge. */
27193
27215
  suggestPlateClusters: method(object({
@@ -27173,8 +27173,10 @@ var PlateInfoSchema = object({
27173
27173
  keyFrameMediaKey: string().optional(),
27174
27174
  base64: string().optional(),
27175
27175
  /**
27176
- * Same crop as a data-plane URL. `getPlateByTrack` returns this and
27177
- * never inlines JPEG; `listPlates` still inlines for the admin-ui.
27176
+ * Same crop as a data-plane URL, always present when the plate has a stored
27177
+ * crop. `getPlateByTrack` returns this and never inlines JPEG; `listPlates`
27178
+ * and `searchPlates` inline the crop only when their `includeCrops` input is
27179
+ * left at its `true` default.
27178
27180
  */
27179
27181
  cropUrl: string().optional()
27180
27182
  });
@@ -27207,7 +27209,25 @@ var plateGalleryCapability = {
27207
27209
  methods: {
27208
27210
  listPlates: method(object({
27209
27211
  deviceId: number().int().optional(),
27210
- limit: number().int().positive().optional()
27212
+ limit: number().int().positive().optional(),
27213
+ /**
27214
+ * Inline the base64 crop on every row. Default `true` — the existing
27215
+ * behaviour, kept so no caller breaks.
27216
+ *
27217
+ * Set `false` once the caller renders {@link PlateInfo.cropUrl}.
27218
+ * Measured on the live hub at the 500 rows the Plates view asks for:
27219
+ * 879,403 B and 27.7 s with the crops inline, against a few KiB of
27220
+ * metadata without them — and the browser then caches the images.
27221
+ *
27222
+ * This is the plate twin of `faceGallery.listRecentFaces`'s option;
27223
+ * plates were the one gallery list left without it.
27224
+ *
27225
+ * **This is an INPUT field, so it does not reach the addon until the
27226
+ * next train.** The hub router validates cap inputs against its own
27227
+ * compiled Zod and strips a key it does not know. Until the train
27228
+ * ships, sending `false` is harmless and keeps the crops inline.
27229
+ */
27230
+ includeCrops: boolean().optional()
27211
27231
  }).optional(), array(PlateInfoSchema).readonly()),
27212
27232
  getPlateByTrack: method(object({
27213
27233
  deviceId: number().int(),
@@ -27218,7 +27238,9 @@ var plateGalleryCapability = {
27218
27238
  searchPlates: method(object({
27219
27239
  text: string().min(1),
27220
27240
  maxDistance: number().int().min(0).optional(),
27221
- limit: number().int().positive().optional()
27241
+ limit: number().int().positive().optional(),
27242
+ /** See `listPlates.includeCrops`. Default `true`. */
27243
+ includeCrops: boolean().optional()
27222
27244
  }), array(PlateInfoSchema).readonly()),
27223
27245
  /** Suggest groups of near-identical reads (same physical plate) for review/merge. */
27224
27246
  suggestPlateClusters: method(object({
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-jHCxxZ2_.js");
5
+ const require_dist = require("../dist-DaFae0Kv.js");
6
6
  let node_fs = require("node:fs");
7
7
  let node_fs$1 = require_dist.__toESM(node_fs, 1);
8
8
  node_fs = require_dist.__toESM(node_fs);
@@ -1,4 +1,4 @@
1
- import { M as PoolMemoryWatchdog, at as hfModelUrl, gt as resolvePoolMemoryPolicy, nt as embeddingEncoderCapability, ut as parseProcStatus, wt as BaseAddon } from "../dist-CsMG-R4E.mjs";
1
+ import { M as PoolMemoryWatchdog, at as hfModelUrl, gt as resolvePoolMemoryPolicy, nt as embeddingEncoderCapability, ut as parseProcStatus, wt as BaseAddon } from "../dist-Cplsn5Hc.mjs";
2
2
  import { createRequire } from "node:module";
3
3
  import * as fs from "node:fs";
4
4
  import "node:fs";
@@ -18,7 +18,7 @@ var e = {
18
18
  },
19
19
  "@camstack/types": {
20
20
  name: "@camstack/types",
21
- version: "1.2.104",
21
+ version: "1.2.105",
22
22
  scope: ["default"],
23
23
  loaded: !1,
24
24
  from: "addon_pipeline_analytics_widgets",
@@ -36,7 +36,7 @@ async function r() {
36
36
  }
37
37
  },
38
38
  "@camstack/types": {
39
- version: "1.2.104",
39
+ version: "1.2.105",
40
40
  scope: "default",
41
41
  shareConfig: {
42
42
  singleton: !0,
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-jHCxxZ2_.js");
5
+ const require_dist = require("../dist-DaFae0Kv.js");
6
6
  let node_fs = require("node:fs");
7
7
  node_fs = require_dist.__toESM(node_fs, 1);
8
8
  let node_path = require("node:path");
@@ -25937,6 +25937,11 @@ var embeddingActions = require_dist.defineCustomActions({
25937
25937
  "embedding.reembedFacesStatus": require_dist.customAction(NoInputSchema$1, ReembedFacesStatusSchema)
25938
25938
  });
25939
25939
  //#endregion
25940
+ //#region src/pipeline-analytics/include-crops-default.ts
25941
+ function resolveIncludeCrops(input) {
25942
+ return input?.includeCrops === true;
25943
+ }
25944
+ //#endregion
25940
25945
  //#region src/pipeline-analytics/map-with-concurrency.ts
25941
25946
  /**
25942
25947
  * Apply `mapper` to every item with at most `limit` in flight at once.
@@ -26595,7 +26600,7 @@ var FaceGalleryProvider = class {
26595
26600
  });
26596
26601
  const identities = await this.identityStore.listIdentities();
26597
26602
  const nameMap = new Map(identities.map((i) => [i.id, i.name]));
26598
- const includeCrops = input?.includeCrops ?? true;
26603
+ const includeCrops = resolveIncludeCrops(input);
26599
26604
  return mapWithConcurrency(faces, FACE_CROP_FETCH_CONCURRENCY, async (face) => {
26600
26605
  const base64 = includeCrops ? await this.faceCropBase64(face) : void 0;
26601
26606
  const cropUrl = this.cropUrlFor(face);
@@ -30867,7 +30872,7 @@ var PlateGalleryProvider = class {
30867
30872
  return media.length > 0 ? media[0].base64 : void 0;
30868
30873
  }
30869
30874
  async toPlateInfo(plate, nameMap, opts) {
30870
- const base64 = opts?.includeCrops ?? true ? await this.plateCropBase64(plate) : void 0;
30875
+ const base64 = resolveIncludeCrops(opts) ? await this.plateCropBase64(plate) : void 0;
30871
30876
  const cropUrl = this.cropUrlFor(plate);
30872
30877
  const vehicleName = plate.recognizedVehicleId != null ? nameMap?.get(plate.recognizedVehicleId) : void 0;
30873
30878
  return {
@@ -30891,13 +30896,22 @@ var PlateGalleryProvider = class {
30891
30896
  const vehicles = await this.vehicleStore.listVehicles();
30892
30897
  return new Map(vehicles.map((v) => [v.id, v.name]));
30893
30898
  }
30899
+ /**
30900
+ * `includeCrops` defaults to `true` — the pre-existing behaviour, kept so no
30901
+ * caller loses its images. Pass `false` once the caller renders
30902
+ * {@link PlateInfo.cropUrl}: measured on the live hub at the 500 rows the
30903
+ * Plates view asks for, the inline crops are 879,403 B and 27.7 s, against a
30904
+ * few KiB of metadata without them. This is the plate twin of
30905
+ * `faceGallery.listRecentFaces`'s option, which shipped first.
30906
+ */
30894
30907
  async listPlates(input) {
30895
30908
  const rows = await this.plateStore.listRecentPlates({
30896
30909
  ...input?.deviceId !== void 0 ? { deviceId: input.deviceId } : {},
30897
30910
  ...input?.limit !== void 0 ? { limit: input.limit } : {}
30898
30911
  });
30899
30912
  const nameMap = await this.vehicleNameMap();
30900
- return Promise.all(rows.map((p) => this.toPlateInfo(p, nameMap)));
30913
+ const includeCrops = resolveIncludeCrops(input);
30914
+ return Promise.all(rows.map((p) => this.toPlateInfo(p, nameMap, { includeCrops })));
30901
30915
  }
30902
30916
  async getPlateByTrack(input) {
30903
30917
  const plate = await this.plateStore.get(`plate-${input.trackId}`);
@@ -30922,7 +30936,8 @@ var PlateGalleryProvider = class {
30922
30936
  })).filter((x) => x.dist <= maxDistance).toSorted((a, b) => a.dist - b.dist || b.p.timestamp - a.p.timestamp);
30923
30937
  const limited = input.limit !== void 0 ? scored.slice(0, input.limit) : scored;
30924
30938
  const nameMap = await this.vehicleNameMap();
30925
- return Promise.all(limited.map((x) => this.toPlateInfo(x.p, nameMap)));
30939
+ const includeCrops = input.includeCrops ?? true;
30940
+ return Promise.all(limited.map((x) => this.toPlateInfo(x.p, nameMap, { includeCrops })));
30926
30941
  }
30927
30942
  async suggestPlateClusters(input) {
30928
30943
  const maxDistance = input?.maxDistance ?? 1;
@@ -1,4 +1,4 @@
1
- import { $ as customAction, A as NcTaxonomySchema, At as sleep, B as TIMELAPSE_DENSE_FLOOR_SEC, Bt as string, C as NcRuleSchema, Ct as errMsg, D as NcSnoozeSchema, Dt as hydrateSchema, E as NcSnoozeInputSchema, Et as createEvent, Ft as literal, G as VISIT_MERGE_GAP_MS, H as TimelapseRulePatchSchema, Ht as EventCategory, I as SCENE_DEFAULT_ANCHOR_THRESHOLD, It as number, J as assertTimelapseCadences, K as addonWidgetsSourceCapability, L as SCENE_DEFAULT_UNCOVERED_POLICY, Lt as object, Mt as array, N as RECORDING_EXPORT_MAX_READ_BYTES, Nt as boolean, O as NcSnoozeSuppressedSchema, Ot as isDeviceScopedCap, P as RetrainStatusSchema, Pt as discriminatedUnion, Q as cosineSimilarity$1, R as SCENE_DIVERGED, Rt as partialRecord, S as NcRulePatchSchema, St as zoneAnalyticsCapability, T as NcScheduleSchema, Tt as DeviceType, U as TimelapseRuleSchema, V as TimelapseRuleInputSchema, Vt as unknown, W as TrackSourceSchema, X as audioModeOf, Y as audioMetricsCapability, Z as buildEventKindDescriptor, _ as NC_DEFAULT_SNOOZE_MINUTES, _t as sceneMonitorCapability, a as DEFAULT_EVENT_COLOR, b as NcConditionDescriptorSchema, bt as vectorDimFromBase64, ct as kebabToCamel, d as EVENT_PAD_MS, dt as pickClusterStepModels, et as defineCustomActions, f as FULL_IMAGE_BBOX, ft as pipelineAnalyticsCapability, g as NC_CONDITION_CATALOG, h as NC_ALARM_SYSTEM_EVENT_KINDS, ht as readTimelapseGeneratedAt, i as CLUSTER_MODEL_SCOPED_STEPS, it as faceGalleryCapability, j as OpsLogEntrySchema, jt as _enum, k as NcSystemEventKindSchema, kt as nodePin, l as DeclaredDevices, lt as notificationRulesCapability, m as MACRO_LABELS, mt as readDeviceStateFrom, n as AnalyticsGroupRecordSchema, ot as isDetectionMacroClass, p as LabelAttributionSchema, pt as plateGalleryCapability, q as alarmPanelCapability, r as BaseDevice, rt as encodeVectorBase64, s as DETECTION_MACRO_CLASSES, st as isScheduleActive, t as AnalyticsGroupDetailSchema, tt as deriveRecordingMode, u as EVENT_KIND_BY_CAP, vt as subKindsOf, w as NcRuleTargetSchema, wt as BaseAddon, x as NcRuleInputSchema, xt as videoclipsCapability, y as NC_TAXONOMY, yt as systemEventFilterApplies, z as SceneMonitorSchema, zt as record } from "../dist-CsMG-R4E.mjs";
1
+ import { $ as customAction, A as NcTaxonomySchema, At as sleep, B as TIMELAPSE_DENSE_FLOOR_SEC, Bt as string, C as NcRuleSchema, Ct as errMsg, D as NcSnoozeSchema, Dt as hydrateSchema, E as NcSnoozeInputSchema, Et as createEvent, Ft as literal, G as VISIT_MERGE_GAP_MS, H as TimelapseRulePatchSchema, Ht as EventCategory, I as SCENE_DEFAULT_ANCHOR_THRESHOLD, It as number, J as assertTimelapseCadences, K as addonWidgetsSourceCapability, L as SCENE_DEFAULT_UNCOVERED_POLICY, Lt as object, Mt as array, N as RECORDING_EXPORT_MAX_READ_BYTES, Nt as boolean, O as NcSnoozeSuppressedSchema, Ot as isDeviceScopedCap, P as RetrainStatusSchema, Pt as discriminatedUnion, Q as cosineSimilarity$1, R as SCENE_DIVERGED, Rt as partialRecord, S as NcRulePatchSchema, St as zoneAnalyticsCapability, T as NcScheduleSchema, Tt as DeviceType, U as TimelapseRuleSchema, V as TimelapseRuleInputSchema, Vt as unknown, W as TrackSourceSchema, X as audioModeOf, Y as audioMetricsCapability, Z as buildEventKindDescriptor, _ as NC_DEFAULT_SNOOZE_MINUTES, _t as sceneMonitorCapability, a as DEFAULT_EVENT_COLOR, b as NcConditionDescriptorSchema, bt as vectorDimFromBase64, ct as kebabToCamel, d as EVENT_PAD_MS, dt as pickClusterStepModels, et as defineCustomActions, f as FULL_IMAGE_BBOX, ft as pipelineAnalyticsCapability, g as NC_CONDITION_CATALOG, h as NC_ALARM_SYSTEM_EVENT_KINDS, ht as readTimelapseGeneratedAt, i as CLUSTER_MODEL_SCOPED_STEPS, it as faceGalleryCapability, j as OpsLogEntrySchema, jt as _enum, k as NcSystemEventKindSchema, kt as nodePin, l as DeclaredDevices, lt as notificationRulesCapability, m as MACRO_LABELS, mt as readDeviceStateFrom, n as AnalyticsGroupRecordSchema, ot as isDetectionMacroClass, p as LabelAttributionSchema, pt as plateGalleryCapability, q as alarmPanelCapability, r as BaseDevice, rt as encodeVectorBase64, s as DETECTION_MACRO_CLASSES, st as isScheduleActive, t as AnalyticsGroupDetailSchema, tt as deriveRecordingMode, u as EVENT_KIND_BY_CAP, vt as subKindsOf, w as NcRuleTargetSchema, wt as BaseAddon, x as NcRuleInputSchema, xt as videoclipsCapability, y as NC_TAXONOMY, yt as systemEventFilterApplies, z as SceneMonitorSchema, zt as record } from "../dist-Cplsn5Hc.mjs";
2
2
  import { t as __exportAll } from "../embedding-encoder/index.mjs";
3
3
  import * as fs from "node:fs";
4
4
  import { promises } from "node:fs";
@@ -25915,6 +25915,11 @@ var embeddingActions = defineCustomActions({
25915
25915
  "embedding.reembedFacesStatus": customAction(NoInputSchema$1, ReembedFacesStatusSchema)
25916
25916
  });
25917
25917
  //#endregion
25918
+ //#region src/pipeline-analytics/include-crops-default.ts
25919
+ function resolveIncludeCrops(input) {
25920
+ return input?.includeCrops === true;
25921
+ }
25922
+ //#endregion
25918
25923
  //#region src/pipeline-analytics/map-with-concurrency.ts
25919
25924
  /**
25920
25925
  * Apply `mapper` to every item with at most `limit` in flight at once.
@@ -26573,7 +26578,7 @@ var FaceGalleryProvider = class {
26573
26578
  });
26574
26579
  const identities = await this.identityStore.listIdentities();
26575
26580
  const nameMap = new Map(identities.map((i) => [i.id, i.name]));
26576
- const includeCrops = input?.includeCrops ?? true;
26581
+ const includeCrops = resolveIncludeCrops(input);
26577
26582
  return mapWithConcurrency(faces, FACE_CROP_FETCH_CONCURRENCY, async (face) => {
26578
26583
  const base64 = includeCrops ? await this.faceCropBase64(face) : void 0;
26579
26584
  const cropUrl = this.cropUrlFor(face);
@@ -30843,7 +30848,7 @@ var PlateGalleryProvider = class {
30843
30848
  return media.length > 0 ? media[0].base64 : void 0;
30844
30849
  }
30845
30850
  async toPlateInfo(plate, nameMap, opts) {
30846
- const base64 = opts?.includeCrops ?? true ? await this.plateCropBase64(plate) : void 0;
30851
+ const base64 = resolveIncludeCrops(opts) ? await this.plateCropBase64(plate) : void 0;
30847
30852
  const cropUrl = this.cropUrlFor(plate);
30848
30853
  const vehicleName = plate.recognizedVehicleId != null ? nameMap?.get(plate.recognizedVehicleId) : void 0;
30849
30854
  return {
@@ -30867,13 +30872,22 @@ var PlateGalleryProvider = class {
30867
30872
  const vehicles = await this.vehicleStore.listVehicles();
30868
30873
  return new Map(vehicles.map((v) => [v.id, v.name]));
30869
30874
  }
30875
+ /**
30876
+ * `includeCrops` defaults to `true` — the pre-existing behaviour, kept so no
30877
+ * caller loses its images. Pass `false` once the caller renders
30878
+ * {@link PlateInfo.cropUrl}: measured on the live hub at the 500 rows the
30879
+ * Plates view asks for, the inline crops are 879,403 B and 27.7 s, against a
30880
+ * few KiB of metadata without them. This is the plate twin of
30881
+ * `faceGallery.listRecentFaces`'s option, which shipped first.
30882
+ */
30870
30883
  async listPlates(input) {
30871
30884
  const rows = await this.plateStore.listRecentPlates({
30872
30885
  ...input?.deviceId !== void 0 ? { deviceId: input.deviceId } : {},
30873
30886
  ...input?.limit !== void 0 ? { limit: input.limit } : {}
30874
30887
  });
30875
30888
  const nameMap = await this.vehicleNameMap();
30876
- return Promise.all(rows.map((p) => this.toPlateInfo(p, nameMap)));
30889
+ const includeCrops = resolveIncludeCrops(input);
30890
+ return Promise.all(rows.map((p) => this.toPlateInfo(p, nameMap, { includeCrops })));
30877
30891
  }
30878
30892
  async getPlateByTrack(input) {
30879
30893
  const plate = await this.plateStore.get(`plate-${input.trackId}`);
@@ -30898,7 +30912,8 @@ var PlateGalleryProvider = class {
30898
30912
  })).filter((x) => x.dist <= maxDistance).toSorted((a, b) => a.dist - b.dist || b.p.timestamp - a.p.timestamp);
30899
30913
  const limited = input.limit !== void 0 ? scored.slice(0, input.limit) : scored;
30900
30914
  const nameMap = await this.vehicleNameMap();
30901
- return Promise.all(limited.map((x) => this.toPlateInfo(x.p, nameMap)));
30915
+ const includeCrops = input.includeCrops ?? true;
30916
+ return Promise.all(limited.map((x) => this.toPlateInfo(x.p, nameMap, { includeCrops })));
30902
30917
  }
30903
30918
  async suggestPlateClusters(input) {
30904
30919
  const maxDistance = input?.maxDistance ?? 1;
@@ -30,7 +30,7 @@ async function d(e) {
30
30
  }
31
31
  }
32
32
  async function f() {
33
- return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-u9dpdQPa.mjs")).catch((e) => {
33
+ return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-BlrCc0Y5.mjs")).catch((e) => {
34
34
  throw l = void 0, e;
35
35
  }), l;
36
36
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-post-analysis",
3
- "version": "1.2.122",
3
+ "version": "1.2.124",
4
4
  "description": "Post-Analysis bundle — enrichment, embedding-encoder, pipeline-analytics. Multi-entry npm package shipping addons that consume pipeline output.",
5
5
  "keywords": [
6
6
  "camstack",