@camstack/addon-post-analysis 1.1.27 → 1.1.29

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.
@@ -4286,6 +4286,14 @@ function object(shape, params) {
4286
4286
  ...normalizeParams(params)
4287
4287
  });
4288
4288
  }
4289
+ function looseObject(shape, params) {
4290
+ return new ZodObject({
4291
+ type: "object",
4292
+ shape,
4293
+ catchall: unknown(),
4294
+ ...normalizeParams(params)
4295
+ });
4296
+ }
4289
4297
  var ZodUnion = /*@__PURE__*/ $constructor("ZodUnion", (inst, def) => {
4290
4298
  $ZodUnion.init(inst, def);
4291
4299
  ZodType.init(inst, def);
@@ -4627,7 +4635,7 @@ function _instanceof(cls, params = {}) {
4627
4635
  return inst;
4628
4636
  }
4629
4637
  //#endregion
4630
- //#region ../types/dist/sleep-Baang_XW.mjs
4638
+ //#region ../types/dist/sleep-_sv7WKkq.mjs
4631
4639
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4632
4640
  EventCategory["SystemBoot"] = "system.boot";
4633
4641
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -5037,10 +5045,51 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5037
5045
  EventCategory["EnrichmentEmbeddingStored"] = "enrichment.embedding.stored";
5038
5046
  EventCategory["EnrichmentSceneStateChanged"] = "enrichment.scene.state-changed";
5039
5047
  EventCategory["EnrichmentActivitySummary"] = "enrichment.activity.summary";
5048
+ /**
5049
+ * Unified track-lifecycle event: ONE category carrying `phase:
5050
+ * 'start' | 'update' | 'end'` with a rich, typed
5051
+ * `PipelineAnalyticsTrackLifecyclePayload`. Supersedes the thin
5052
+ * `PipelineAnalyticsTrackStarted` / `PipelineAnalyticsTrackEnded`
5053
+ * pair — a consumer subscribes once and branches on `phase`.
5054
+ */
5055
+ EventCategory["PipelineAnalyticsTrackLifecycle"] = "pipeline-analytics.track-lifecycle";
5056
+ /**
5057
+ * @deprecated Superseded by {@link PipelineAnalyticsTrackLifecycle}
5058
+ * (`phase:'start'`). Kept as a soft alias — no known subscribers.
5059
+ */
5040
5060
  EventCategory["PipelineAnalyticsTrackStarted"] = "pipeline-analytics.track-started";
5061
+ /**
5062
+ * @deprecated Superseded by {@link PipelineAnalyticsTrackLifecycle}
5063
+ * (`phase:'end'`). Kept as a soft alias — no known subscribers.
5064
+ */
5041
5065
  EventCategory["PipelineAnalyticsTrackEnded"] = "pipeline-analytics.track-ended";
5042
5066
  EventCategory["PipelineAnalyticsDetectionEvent"] = "pipeline-analytics.detection-event";
5043
5067
  EventCategory["PipelineAnalyticsFrameTracked"] = "pipeline-analytics.frame-tracked";
5068
+ /**
5069
+ * Fired by `addon-post-analysis` when a parked (stationary) object appears
5070
+ * (a track was promoted to a stationary-registry entry) or departs (the
5071
+ * object moved / was removed). Telemetry (D8): lossy, drives a UI refresh of
5072
+ * the dedicated "Stationary" section — never the live event feed. Payload:
5073
+ * `{ deviceId, entryId, className, phase:'appeared'|'departed', timestamp }`.
5074
+ */
5075
+ EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
5076
+ /**
5077
+ * Fired by `addon-post-analysis` whenever a gallery face row changes:
5078
+ * `kind:'buffered'` a new detected face was persisted, `'assigned'` /
5079
+ * `'unassigned'` its identity link changed, `'deleted'` the row was
5080
+ * removed. Telemetry semantics (D8): a lost event only delays a refresh,
5081
+ * never a correctness issue. Payload `PipelineAnalyticsFaceGalleryChangedPayload`.
5082
+ */
5083
+ EventCategory["PipelineAnalyticsFaceGalleryChanged"] = "pipeline-analytics.face-gallery-changed";
5084
+ /**
5085
+ * Fired by `addon-post-analysis` whenever a gallery plate row changes:
5086
+ * `kind:'buffered'` a new read was persisted (`PlateRecognizer.onTrackEnd`),
5087
+ * `'assigned'` / `'unassigned'` its vehicle link changed
5088
+ * (`PlateGalleryProvider`), `'deleted'` the row was removed. Telemetry
5089
+ * semantics (D8): a lost event only delays a refresh, never a correctness
5090
+ * issue. Payload `PipelineAnalyticsPlateGalleryChangedPayload`.
5091
+ */
5092
+ EventCategory["PipelineAnalyticsPlateGalleryChanged"] = "pipeline-analytics.plate-gallery-changed";
5044
5093
  EventCategory["FrigateLiveEvent"] = "frigate.live-event";
5045
5094
  EventCategory["CameraStreamsProfileSlotsChanged"] = "camera-streams.onProfileSlotsChanged";
5046
5095
  /**
@@ -6358,11 +6407,6 @@ var ProfileRtspEntrySchema = object({
6358
6407
  codec: string().optional(),
6359
6408
  resolution: CamStreamResolutionSchema.optional()
6360
6409
  });
6361
- /** Narrow an unknown value to a plain `Record<string, unknown>` or return null. */
6362
- function asJsonObject(value) {
6363
- if (value === null || typeof value !== "object" || Array.isArray(value)) return null;
6364
- return { ...value };
6365
- }
6366
6410
  var DeviceType = /* @__PURE__ */ function(DeviceType) {
6367
6411
  DeviceType["Camera"] = "camera";
6368
6412
  DeviceType["Hub"] = "hub";
@@ -6886,7 +6930,8 @@ var MODEL_FORMATS = [
6886
6930
  "coreml",
6887
6931
  "openvino",
6888
6932
  "tflite",
6889
- "pt"
6933
+ "pt",
6934
+ "gguf"
6890
6935
  ];
6891
6936
  /**
6892
6937
  * Multi-file format payload.
@@ -6930,7 +6975,8 @@ var ModelFormatsSchema = object({
6930
6975
  coreml: ModelFormatEntrySchema.optional(),
6931
6976
  openvino: ModelFormatEntrySchema.optional(),
6932
6977
  tflite: ModelFormatEntrySchema.optional(),
6933
- pt: ModelFormatEntrySchema.optional()
6978
+ pt: ModelFormatEntrySchema.optional(),
6979
+ gguf: ModelFormatEntrySchema.optional()
6934
6980
  });
6935
6981
  /**
6936
6982
  * Variant-selector grouping axes. Shared by the full `ModelCatalogEntry` and by
@@ -6971,6 +7017,15 @@ var ModelCatalogEntrySchema = object({
6971
7017
  width: number(),
6972
7018
  height: number()
6973
7019
  }),
7020
+ /**
7021
+ * Channel count of the model input tensor. Omit ⇒ 3 (RGB), the default for
7022
+ * every detector / classifier / embedder. Set to 1 for a grayscale CTC text
7023
+ * recognizer (EasyOCR VGG plate-OCR: input `[N,1,H,W]`) so the preprocess
7024
+ * feeds a single-channel, EasyOCR-normalized tensor instead of the default
7025
+ * 3-channel RGB one. Threaded through `PoolModelConfig.inputChannels` to the
7026
+ * Python inference pool.
7027
+ */
7028
+ inputChannels: number().int().positive().optional(),
6974
7029
  labels: array(LabelDefinitionSchema).readonly(),
6975
7030
  inputLayout: _enum(["nchw", "nhwc"]).optional(),
6976
7031
  inputNormalization: _enum([
@@ -6980,6 +7035,16 @@ var ModelCatalogEntrySchema = object({
6980
7035
  ]).optional(),
6981
7036
  preprocessMode: _enum(["letterbox", "resize"]).optional(),
6982
7037
  /**
7038
+ * Per-MODEL postprocessor override. Absent ⇒ the step's own
7039
+ * `StepDefinition.postprocessor` applies (the normal case — every model in a
7040
+ * step shares its decode). Set it when a step hosts models with DIFFERENT raw
7041
+ * output layouts under one slot: e.g. object-detection is `'yolo'` by default,
7042
+ * but a Coral SSD MobileNet build emits the `TFLite_Detection_PostProcess`
7043
+ * 4-tensor layout and needs `'ssd'`. Threaded into `PoolModelConfig.postprocessor`
7044
+ * by the engine factory (`modelEntry.postprocessor ?? def.postprocessor`).
7045
+ */
7046
+ postprocessor: custom().optional(),
7047
+ /**
6983
7048
  * When true, the executor produces a landmark-aligned crop (similarity warp
6984
7049
  * onto the canonical template) before this step runs, instead of a plain
6985
7050
  * axis-aligned bbox crop. Required for face-recognition embedders (ArcFace):
@@ -10520,7 +10585,8 @@ var ModelFormatSchema$1 = _enum([
10520
10585
  "coreml",
10521
10586
  "openvino",
10522
10587
  "tflite",
10523
- "pt"
10588
+ "pt",
10589
+ "gguf"
10524
10590
  ]);
10525
10591
  var PipelineSlotSchema = _enum([
10526
10592
  "detector",
@@ -10614,7 +10680,8 @@ var EngineProvisioningSchema = object({
10614
10680
  runtimeId: _enum([
10615
10681
  "onnx",
10616
10682
  "openvino",
10617
- "coreml"
10683
+ "coreml",
10684
+ "edgetpu"
10618
10685
  ]).nullable(),
10619
10686
  device: string().nullable(),
10620
10687
  state: _enum([
@@ -11826,6 +11893,140 @@ DeviceType.Camera, method(object({ deviceId: number() }), PtzAutotrackStatusSche
11826
11893
  deviceId: number(),
11827
11894
  status: PtzAutotrackStatusSchema
11828
11895
  });
11896
+ /**
11897
+ * scene-monitor — device-scoped reference-region state cap. An operator marks
11898
+ * a rect ROI on a camera frame and names one or more states; the engine
11899
+ * (pipeline-analytics, designated post-processing node) reports which state is
11900
+ * active on an ongoing basis. Two operator-selectable check modes share every-
11901
+ * thing except the comparator: `similarity` (CLIP cosine at the same ROI coords
11902
+ * vs condition-tagged references) and `llm` (vision-LLM judgment over the crop).
11903
+ *
11904
+ * D14 device-config archetype (`deviceConfig.ui.kind:'widget'`) — the framework
11905
+ * derives the device-detail contribution; the provider carries NO hand-written
11906
+ * settings-contribution methods. `status.kind:'push'` — the engine pushes on
11907
+ * every hysteresis flip / availability change; consumers never poll.
11908
+ */
11909
+ /** Extensible condition tag. Seeded 'day' | 'night'; open by design so more can
11910
+ * be added without a wire break (matching falls back to any-condition refs). */
11911
+ var SceneConditionSchema = string();
11912
+ /** One captured reference — condition-tagged, model-version-gated. `embedding`
11913
+ * is `number[]` (Float32Array does NOT survive MsgPack/UDS). */
11914
+ var SceneReferenceSchema = object({
11915
+ embedding: array(number()),
11916
+ modelId: string(),
11917
+ condition: SceneConditionSchema,
11918
+ capturedAt: number(),
11919
+ thumbnailMediaId: string().optional()
11920
+ });
11921
+ var SceneMonitorStateSchema = object({
11922
+ id: string(),
11923
+ label: string(),
11924
+ references: array(SceneReferenceSchema),
11925
+ textPrompts: array(string()).optional(),
11926
+ referenceCount: number(),
11927
+ currentlyMatched: boolean()
11928
+ });
11929
+ /** Per-mode comparator params in a discriminated union so an `llm` scene never
11930
+ * carries similarity knobs and vice-versa. */
11931
+ var SceneCheckSchema = discriminatedUnion("mode", [object({
11932
+ mode: literal("similarity"),
11933
+ threshold: number().min(0).max(1),
11934
+ hysteresisCount: number().int().positive()
11935
+ }), object({
11936
+ mode: literal("llm"),
11937
+ prompt: string(),
11938
+ profileId: string().optional(),
11939
+ hysteresisCount: number().int().positive()
11940
+ })]);
11941
+ var SceneMonitorSchema = object({
11942
+ id: string(),
11943
+ label: string(),
11944
+ roi: MaskRectShapeSchema,
11945
+ enabled: boolean(),
11946
+ triggerMode: _enum([
11947
+ "periodic",
11948
+ "on-motion",
11949
+ "both"
11950
+ ]),
11951
+ checkIntervalSec: number().optional(),
11952
+ check: SceneCheckSchema,
11953
+ states: array(SceneMonitorStateSchema),
11954
+ currentStateId: string().nullable(),
11955
+ lastCheckedAt: number().nullable(),
11956
+ lastConfidence: number().nullable(),
11957
+ currentCondition: SceneConditionSchema.nullable(),
11958
+ availability: _enum(["ok", "unavailable"]),
11959
+ unavailableReason: string().nullable()
11960
+ });
11961
+ var SceneMonitorStatusSchema = object({
11962
+ monitors: array(SceneMonitorSchema),
11963
+ lastFetchedAt: number()
11964
+ });
11965
+ DeviceType.Camera, method(object({ deviceId: number() }), SceneMonitorStatusSchema), method(object({
11966
+ deviceId: number(),
11967
+ label: string(),
11968
+ roi: MaskRectShapeSchema,
11969
+ check: SceneCheckSchema,
11970
+ triggerMode: _enum([
11971
+ "periodic",
11972
+ "on-motion",
11973
+ "both"
11974
+ ]).optional(),
11975
+ checkIntervalSec: number().optional()
11976
+ }), SceneMonitorSchema, {
11977
+ kind: "mutation",
11978
+ auth: "admin"
11979
+ }), method(object({
11980
+ deviceId: number(),
11981
+ monitorId: string(),
11982
+ patch: object({
11983
+ label: string().optional(),
11984
+ roi: MaskRectShapeSchema.optional(),
11985
+ enabled: boolean().optional(),
11986
+ triggerMode: _enum([
11987
+ "periodic",
11988
+ "on-motion",
11989
+ "both"
11990
+ ]).optional(),
11991
+ checkIntervalSec: number().optional(),
11992
+ check: SceneCheckSchema.optional()
11993
+ })
11994
+ }), _void(), {
11995
+ kind: "mutation",
11996
+ auth: "admin"
11997
+ }), method(object({
11998
+ deviceId: number(),
11999
+ monitorId: string()
12000
+ }), _void(), {
12001
+ kind: "mutation",
12002
+ auth: "admin"
12003
+ }), method(object({
12004
+ deviceId: number(),
12005
+ monitorId: string(),
12006
+ stateId: string().optional(),
12007
+ label: string().optional(),
12008
+ condition: SceneConditionSchema.optional()
12009
+ }), object({
12010
+ stateId: string(),
12011
+ referenceCount: number()
12012
+ }), {
12013
+ kind: "mutation",
12014
+ auth: "admin"
12015
+ }), method(object({
12016
+ deviceId: number(),
12017
+ monitorId: string(),
12018
+ stateId: string(),
12019
+ index: number()
12020
+ }), _void(), {
12021
+ kind: "mutation",
12022
+ auth: "admin"
12023
+ }), method(object({
12024
+ deviceId: number(),
12025
+ monitorId: string()
12026
+ }), _void(), {
12027
+ kind: "mutation",
12028
+ auth: "admin"
12029
+ });
11829
12030
  object({
11830
12031
  /** Whether the script is currently executing. */
11831
12032
  isRunning: boolean(),
@@ -12233,6 +12434,36 @@ var ZoneScopeBreakdownSchema = PerScopeBreakdownSchema.extend({
12233
12434
  * with the per-track detail panel and live overlay. */
12234
12435
  trackIds: array(string()).readonly()
12235
12436
  });
12437
+ /**
12438
+ * A parked ("stationary") object surfaced alongside occupancy — an object that
12439
+ * settled and stopped moving. It is NO LONGER a tracked object (the tracker was
12440
+ * told to forget it so it stops re-spawning tracks/events), but it IS still
12441
+ * physically present, so it keeps counting toward `frame` occupancy and is
12442
+ * listed here so the UI can show it in a dedicated "Stationary" section instead
12443
+ * of flooding the live event feed.
12444
+ */
12445
+ var StationaryObjectSchema = object({
12446
+ id: string(),
12447
+ className: string(),
12448
+ bbox: object({
12449
+ x: number(),
12450
+ y: number(),
12451
+ w: number(),
12452
+ h: number()
12453
+ }),
12454
+ frameWidth: number().int().nonnegative(),
12455
+ frameHeight: number().int().nonnegative(),
12456
+ /** When the source track was first seen. */
12457
+ firstSeenAt: number().int(),
12458
+ /** When the object was recognised as parked (promotion time). */
12459
+ becameStationaryAt: number().int(),
12460
+ /** Last frame a detection confirmed the object is still there. */
12461
+ lastConfirmedAt: number().int(),
12462
+ /** Enrichment label carried from the source track (identity / plate). */
12463
+ label: string().optional(),
12464
+ /** Native-resolution key-frame media key for the parked object's best image. */
12465
+ keyFrameMediaKey: string().optional()
12466
+ });
12236
12467
  var CameraOccupancySnapshotSchema = object({
12237
12468
  /** Frame timestamp of the inference result that produced this snapshot. */
12238
12469
  ts: number().int(),
@@ -12241,10 +12472,15 @@ var CameraOccupancySnapshotSchema = object({
12241
12472
  frameHeight: number().int().nonnegative(),
12242
12473
  /** Per-zone breakdown — one entry per defined zone (user + onboard). */
12243
12474
  zones: array(ZoneScopeBreakdownSchema).readonly(),
12244
- /** Frame-wide aggregate (everywhere, regardless of zone membership). */
12475
+ /** Frame-wide aggregate (everywhere, regardless of zone membership).
12476
+ * INCLUDES currently-confirmed stationary objects (they are still present). */
12245
12477
  frame: PerScopeBreakdownSchema,
12246
12478
  /** Detections that landed outside every zone. Empty when no zones defined. */
12247
- unzoned: PerScopeBreakdownSchema
12479
+ unzoned: PerScopeBreakdownSchema,
12480
+ /** Parked objects on this camera (additive — absent on legacy snapshots).
12481
+ * Surfaced separately so the UI shows them in a dedicated section rather
12482
+ * than as repeated tracks/events. */
12483
+ stationaryObjects: array(StationaryObjectSchema).readonly().optional()
12248
12484
  });
12249
12485
  /**
12250
12486
  * Time-series resolution. The history methods return one bucket per
@@ -12902,7 +13138,12 @@ var NotificationRuleConditionsSchema = object({
12902
13138
  clipDescription: object({
12903
13139
  text: string().min(1),
12904
13140
  minSimilarity: number().min(0).max(1)
12905
- }).optional()
13141
+ }).optional(),
13142
+ /** Match events whose recognized-entity label (face identity name or plate
13143
+ * vehicle name, propagated onto `event.data.label`) is one of these values.
13144
+ * Empty/absent → unaffected (back-compat). Enables "notify me when <named
13145
+ * vehicle/person> is seen". */
13146
+ labels: array(string()).readonly().optional()
12906
13147
  });
12907
13148
  var NotificationRuleTemplateSchema = object({
12908
13149
  title: string(),
@@ -13160,11 +13401,19 @@ method(object({
13160
13401
  * login page needs NO change.
13161
13402
  *
13162
13403
  * - `widget` — a Module-Federation widget the login page mounts (via
13163
- * `loadRemoteBundle`) for an in-page ceremony. Covers the passkey
13164
- * login ceremony, which must run `@simplewebauthn/browser` INSIDE the
13165
- * addon bundle. The referenced widget also declares `preAuth: true` in
13166
- * its `addon-widgets-source` catalog entry. `auth.listLoginMethods`
13167
- * stamps a public `bundleUrl` from `addonId` + `bundle`.
13404
+ * `loadRemoteBundle`) for an in-page ceremony. `auth.listLoginMethods`
13405
+ * stamps a public `bundleUrl` from `addonId` + `bundle`. Generic
13406
+ * mechanism kept for future use; no shipped addon uses it on the login
13407
+ * page (the passkey ceremony below runs natively in the shell instead).
13408
+ *
13409
+ * - `passkey` — a declarative WebAuthn ceremony the shell renders
13410
+ * natively (`@simplewebauthn/browser` lives in `addon-admin-ui`, not in
13411
+ * a remotely-loaded bundle). Carries the addon's effective `rpId` /
13412
+ * `origin` (from its `resolveRpID()` / `resolveOrigin()`) so the shell
13413
+ * can gate visibility (IP-literal origin, hostname/rpId mismatch) WITHOUT
13414
+ * fetching any remote code pre-auth. Contribution stays unconditional —
13415
+ * enrollment state is never leaked pre-auth; visibility is a shell
13416
+ * decision.
13168
13417
  *
13169
13418
  * Every contribution carries a `stage`:
13170
13419
  * - `primary` — shown on the first credentials screen (OIDC /
@@ -13178,30 +13427,45 @@ method(object({
13178
13427
  */
13179
13428
  /** When a login method renders in the two-phase login flow. */
13180
13429
  var LoginStageEnum = _enum(["primary", "second-factor"]);
13181
- /** One login-method contribution — redirect button OR pre-auth widget. */
13182
- var LoginMethodContributionSchema = discriminatedUnion("kind", [object({
13183
- kind: literal("redirect"),
13184
- /** Stable id within the login-method set (e.g. `auth-oidc/google`). */
13185
- id: string(),
13186
- /** Operator-facing button label. */
13187
- label: string(),
13188
- /** lucide-react icon name. */
13189
- icon: string().optional(),
13190
- /** Addon-owned HTTP route the button navigates to (GET). */
13191
- startUrl: string(),
13192
- stage: LoginStageEnum
13193
- }), object({
13194
- kind: literal("widget"),
13195
- /** Stable id within the login-method set (e.g. `auth-webauthn/passkey-login`). */
13196
- id: string(),
13197
- /** Owning addon id drives the public bundle URL + the MF namespace. */
13198
- addonId: string(),
13199
- /** Bundle filename inside the addon's dist dir (`remoteEntry.js`). */
13200
- bundle: string(),
13201
- /** MF remote descriptor `{ remoteName, exposedModule, componentKey }`. */
13202
- remote: WidgetRemoteSchema,
13203
- stage: LoginStageEnum
13204
- })]);
13430
+ /** One login-method contribution — redirect button, pre-auth widget, or native passkey ceremony. */
13431
+ var LoginMethodContributionSchema = discriminatedUnion("kind", [
13432
+ object({
13433
+ kind: literal("redirect"),
13434
+ /** Stable id within the login-method set (e.g. `auth-oidc/google`). */
13435
+ id: string(),
13436
+ /** Operator-facing button label. */
13437
+ label: string(),
13438
+ /** lucide-react icon name. */
13439
+ icon: string().optional(),
13440
+ /** Addon-owned HTTP route the button navigates to (GET). */
13441
+ startUrl: string(),
13442
+ stage: LoginStageEnum
13443
+ }),
13444
+ object({
13445
+ kind: literal("widget"),
13446
+ /** Stable id within the login-method set (e.g. `auth-webauthn/passkey-login`). */
13447
+ id: string(),
13448
+ /** Owning addon id — drives the public bundle URL + the MF namespace. */
13449
+ addonId: string(),
13450
+ /** Bundle filename inside the addon's dist dir (`remoteEntry.js`). */
13451
+ bundle: string(),
13452
+ /** MF remote descriptor — `{ remoteName, exposedModule, componentKey }`. */
13453
+ remote: WidgetRemoteSchema,
13454
+ stage: LoginStageEnum
13455
+ }),
13456
+ object({
13457
+ kind: literal("passkey"),
13458
+ /** Stable id within the login-method set (e.g. `auth-webauthn/passkey-direct-login`). */
13459
+ id: string(),
13460
+ /** Operator-facing button label. */
13461
+ label: string(),
13462
+ stage: LoginStageEnum,
13463
+ /** Effective WebAuthn RP ID (`resolveRpID()`) — the shell gates visibility on it. */
13464
+ rpId: string(),
13465
+ /** Effective expected origin (`resolveOrigin()`), null when unconfigured. */
13466
+ origin: string().nullable()
13467
+ })
13468
+ ]);
13205
13469
  method(_void(), array(LoginMethodContributionSchema).readonly());
13206
13470
  /**
13207
13471
  * Orchestrator-side destination metadata. The orchestrator computes
@@ -15039,14 +15303,14 @@ var TargetKindCapsSchema = object({
15039
15303
  * the union is large and not meant for runtime validation here; the exported
15040
15304
  * `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
15041
15305
  */
15042
- var ConfigSchemaPassthrough = unknown();
15306
+ var ConfigSchemaPassthrough$1 = unknown();
15043
15307
  var TargetKindSchema = object({
15044
15308
  kind: string(),
15045
15309
  label: string(),
15046
15310
  icon: string(),
15047
15311
  /** Stamped by each provider so the concat-fanned catalog stays routable. */
15048
15312
  addonId: string(),
15049
- configSchema: ConfigSchemaPassthrough,
15313
+ configSchema: ConfigSchemaPassthrough$1,
15050
15314
  supportsDiscovery: boolean(),
15051
15315
  caps: TargetKindCapsSchema
15052
15316
  });
@@ -15099,6 +15363,298 @@ method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSche
15099
15363
  enabled: boolean()
15100
15364
  }), _void(), { kind: "mutation" });
15101
15365
  /**
15366
+ * Shared LLM generate contracts — imported by BOTH `llm.cap.ts` (consumer
15367
+ * surface) and `llm-runtime.cap.ts` (node-side managed executor) so the two
15368
+ * caps stay wire-compatible without a circular cap→cap import.
15369
+ *
15370
+ * Errors are a discriminated-union RESULT, never thrown: the shape survives
15371
+ * every transport tier structurally, and failed calls still write usage rows.
15372
+ * Token counts only in v1 — no costUsd (operator decision, 2026-07-15).
15373
+ */
15374
+ var LlmUsageSchema = object({
15375
+ inputTokens: number(),
15376
+ outputTokens: number()
15377
+ });
15378
+ var LlmErrorCodeSchema = _enum([
15379
+ "timeout",
15380
+ "rate-limited",
15381
+ "auth",
15382
+ "refusal",
15383
+ "bad-request",
15384
+ "unavailable",
15385
+ "no-profile",
15386
+ "budget-exceeded",
15387
+ "adapter-error"
15388
+ ]);
15389
+ var LlmGenerateResultSchema = discriminatedUnion("ok", [object({
15390
+ ok: literal(true),
15391
+ text: string(),
15392
+ model: string(),
15393
+ usage: LlmUsageSchema,
15394
+ truncated: boolean(),
15395
+ latencyMs: number()
15396
+ }), object({
15397
+ ok: literal(false),
15398
+ code: LlmErrorCodeSchema,
15399
+ message: string(),
15400
+ retryAfterMs: number().optional()
15401
+ })]);
15402
+ /**
15403
+ * `Uint8Array` is the sanctioned binary convention — superjson + the UDS
15404
+ * MsgPack channel round-trip typed arrays (embedding-encoder.cap.ts:29,
15405
+ * notification-output.cap.ts:27-31 precedents).
15406
+ */
15407
+ var LlmImageSchema = object({
15408
+ bytes: _instanceof(Uint8Array),
15409
+ mimeType: string()
15410
+ });
15411
+ var LlmGenerateBaseInputSchema = object({
15412
+ /** Collection routing (the notification-output posture). */
15413
+ addonId: string().optional(),
15414
+ /** Explicit profile; else the resolution chain (spec §3). */
15415
+ profileId: string().optional(),
15416
+ /** MANDATORY usage tag: 'ai-summary', 'notifier-rules', 'adhoc-ui', … */
15417
+ consumer: string(),
15418
+ system: string().optional(),
15419
+ /** v1: single-turn. `messages[]` is a v2 additive field. */
15420
+ prompt: string(),
15421
+ /** Structured output — adapter-mapped (response_format / forced tool / responseSchema). */
15422
+ jsonSchema: record(string(), unknown()).optional(),
15423
+ /** Per-call override of the profile default. */
15424
+ maxTokens: number().int().positive().optional(),
15425
+ temperature: number().optional()
15426
+ });
15427
+ /**
15428
+ * `llm-runtime` — node-side managed llama.cpp executor (spec §4). Registered
15429
+ * on EVERY node where `addon-ai` is installed; the hub `llm` provider reaches
15430
+ * a specific node's runtime with `nodePin(profile.runtime.nodeId)` — normal
15431
+ * cap routing, zero bespoke plumbing. `internal: true`: the operator reaches
15432
+ * this only through the `llm` cap's methods.
15433
+ *
15434
+ * One running llama-server child per node in v1 (models are RAM-heavy).
15435
+ * Resource ceiling = llama-server flags + idleStopMinutes ONLY (no RSS
15436
+ * watchdog — operator decision #3).
15437
+ */
15438
+ var ManagedModelRefSchema = discriminatedUnion("kind", [
15439
+ object({
15440
+ kind: literal("catalog"),
15441
+ catalogId: string()
15442
+ }),
15443
+ object({
15444
+ kind: literal("url"),
15445
+ url: string(),
15446
+ sha256: string().optional()
15447
+ }),
15448
+ object({
15449
+ kind: literal("path"),
15450
+ path: string()
15451
+ })
15452
+ ]);
15453
+ var ManagedRuntimeConfigSchema = object({
15454
+ /** WHERE the runtime lives — hub or any agent. */
15455
+ nodeId: string(),
15456
+ /** Closed for v1; 'ollama' is a v2 candidate. */
15457
+ engine: _enum(["llama-cpp"]),
15458
+ model: ManagedModelRefSchema,
15459
+ contextSize: number().int().default(4096),
15460
+ /** 0 = CPU-only. */
15461
+ gpuLayers: number().int().default(0),
15462
+ /** Default: cpus-2, clamped ≥1 (resolved node-side). */
15463
+ threads: number().int().optional(),
15464
+ /** Concurrent slots. */
15465
+ parallel: number().int().default(1),
15466
+ /** Else lazy: first generate boots it. */
15467
+ autoStart: boolean().default(false),
15468
+ /** 0 = never; frees RAM after quiet periods. */
15469
+ idleStopMinutes: number().int().default(30)
15470
+ });
15471
+ var LlmRuntimeStatusSchema = object({
15472
+ /** Status is ALWAYS node-qualified. */
15473
+ nodeId: string(),
15474
+ state: _enum([
15475
+ "stopped",
15476
+ "downloading",
15477
+ "starting",
15478
+ "ready",
15479
+ "crashed",
15480
+ "failed"
15481
+ ]),
15482
+ pid: number().optional(),
15483
+ port: number().optional(),
15484
+ modelPath: string().optional(),
15485
+ modelId: string().optional(),
15486
+ downloadProgress: number().min(0).max(1).optional(),
15487
+ lastError: string().optional(),
15488
+ crashesInWindow: number(),
15489
+ /** Child RSS (sampled best-effort). */
15490
+ memoryBytes: number().optional(),
15491
+ vramBytes: number().optional()
15492
+ });
15493
+ var LlmNodeModelSchema = object({
15494
+ file: string(),
15495
+ sizeBytes: number(),
15496
+ catalogId: string().optional(),
15497
+ installedAt: number().optional()
15498
+ });
15499
+ var LlmRuntimeDiskUsageSchema = object({
15500
+ nodeId: string(),
15501
+ modelsBytes: number(),
15502
+ freeBytes: number().optional()
15503
+ });
15504
+ method(LlmGenerateBaseInputSchema.extend({
15505
+ images: array(LlmImageSchema).optional(),
15506
+ runtime: ManagedRuntimeConfigSchema,
15507
+ /** The managed profile's timeout, threaded by the hub provider. */
15508
+ timeoutMs: number().int().positive().optional()
15509
+ }), LlmGenerateResultSchema, { kind: "mutation" }), method(object({ runtime: ManagedRuntimeConfigSchema }), LlmRuntimeStatusSchema, {
15510
+ kind: "mutation",
15511
+ auth: "admin"
15512
+ }), method(object({}), _void(), {
15513
+ kind: "mutation",
15514
+ auth: "admin"
15515
+ }), method(object({}), LlmRuntimeStatusSchema), method(object({ model: ManagedModelRefSchema }), _void(), {
15516
+ kind: "mutation",
15517
+ auth: "admin"
15518
+ }), method(object({ file: string() }), _void(), {
15519
+ kind: "mutation",
15520
+ auth: "admin"
15521
+ }), method(object({}), array(LlmNodeModelSchema)), method(object({}), LlmRuntimeDiskUsageSchema);
15522
+ /**
15523
+ * `llm` — consumer-facing LLM surface (spec §1-§3). Collection-mode: array
15524
+ * methods concat-fan across providers; single-row methods route to ONE
15525
+ * provider by the `addonId` in the call input (the notification-output
15526
+ * posture, notification-output.cap.ts:215-250). Provided by `addon-ai`
15527
+ * (hub-placed); the cap stays open for future providers.
15528
+ *
15529
+ * Profiles are ROWS (data), not addons: one row = one usable model endpoint.
15530
+ * `apiKey` is a password field — providers REDACT it on read and merge on
15531
+ * write; a stored key NEVER round-trips to a client.
15532
+ */
15533
+ var LlmProfileKindSchema = _enum([
15534
+ "openai-compatible",
15535
+ "openai",
15536
+ "anthropic",
15537
+ "google",
15538
+ "managed-local"
15539
+ ]);
15540
+ var LlmProfileSchema = object({
15541
+ id: string(),
15542
+ name: string(),
15543
+ kind: LlmProfileKindSchema,
15544
+ /** Stamped by the provider — keeps the fanned catalog routable. */
15545
+ addonId: string(),
15546
+ enabled: boolean(),
15547
+ /** Vendor model id, or the managed runtime's loaded model. */
15548
+ model: string(),
15549
+ /** Required for openai-compatible; override for cloud kinds. */
15550
+ baseUrl: string().optional(),
15551
+ /** ConfigUISchema type:'password' — never round-trips (spec §5). */
15552
+ apiKey: string().optional(),
15553
+ supportsVision: boolean(),
15554
+ temperature: number().min(0).max(2).optional(),
15555
+ maxTokens: number().int().positive().optional(),
15556
+ timeoutMs: number().int().positive().default(6e4),
15557
+ extraHeaders: record(string(), string()).optional(),
15558
+ /** kind === 'managed-local' only (spec §4). */
15559
+ runtime: ManagedRuntimeConfigSchema.optional()
15560
+ });
15561
+ /** ConfigUISchema tree passed through untyped on the wire (the
15562
+ * notification-output `ConfigSchemaPassthrough` precedent at
15563
+ * notification-output.cap.ts:151); the exported TS type re-tightens it. */
15564
+ var ConfigSchemaPassthrough = unknown();
15565
+ var LlmProfileKindDescriptorSchema = object({
15566
+ kind: LlmProfileKindSchema,
15567
+ label: string(),
15568
+ icon: string(),
15569
+ /** Stamped by each provider so the concat-fanned catalog stays routable. */
15570
+ addonId: string(),
15571
+ configSchema: ConfigSchemaPassthrough
15572
+ });
15573
+ var LlmDefaultSelectorSchema = union([object({ consumer: string() }), object({ purpose: _enum(["text", "vision"]) })]);
15574
+ var LlmDefaultSchema = object({
15575
+ selector: LlmDefaultSelectorSchema,
15576
+ profileId: string()
15577
+ });
15578
+ /** Server-side rollup row — getUsage never dumps raw call rows (spec §6). */
15579
+ var LlmUsageRollupSchema = object({
15580
+ day: string(),
15581
+ consumer: string(),
15582
+ profileId: string(),
15583
+ calls: number(),
15584
+ okCalls: number(),
15585
+ errorCalls: number(),
15586
+ inputTokens: number(),
15587
+ outputTokens: number(),
15588
+ avgLatencyMs: number()
15589
+ });
15590
+ /** LLM-facing view over the reused ModelCatalogEntry mechanism (spec §4.2). */
15591
+ var ManagedModelCatalogEntrySchema = object({
15592
+ id: string(),
15593
+ label: string(),
15594
+ family: string(),
15595
+ purpose: _enum(["text", "vision"]),
15596
+ url: string(),
15597
+ sha256: string(),
15598
+ sizeBytes: number(),
15599
+ quantization: string(),
15600
+ /** Load-time guidance shown in the picker. */
15601
+ minRamBytes: number(),
15602
+ contextSizeDefault: number().int(),
15603
+ /** Vision models: companion projector file. */
15604
+ mmprojUrl: string().optional()
15605
+ });
15606
+ var LlmRuntimeNodeSchema = object({
15607
+ nodeId: string(),
15608
+ reachable: boolean(),
15609
+ status: LlmRuntimeStatusSchema.optional(),
15610
+ disk: LlmRuntimeDiskUsageSchema.optional(),
15611
+ error: string().optional()
15612
+ });
15613
+ var GenerateVisionInputSchema = LlmGenerateBaseInputSchema.extend({ images: array(LlmImageSchema).min(1) });
15614
+ var ProfileRefInputSchema = object({
15615
+ addonId: string(),
15616
+ profileId: string()
15617
+ });
15618
+ method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, { kind: "mutation" }), method(GenerateVisionInputSchema, LlmGenerateResultSchema, { kind: "mutation" }), method(object({}), array(LlmProfileKindDescriptorSchema)), method(object({}), array(LlmProfileSchema)), method(object({ profile: LlmProfileSchema }), LlmProfileSchema, {
15619
+ kind: "mutation",
15620
+ auth: "admin"
15621
+ }), method(ProfileRefInputSchema, _void(), {
15622
+ kind: "mutation",
15623
+ auth: "admin"
15624
+ }), method(ProfileRefInputSchema, LlmGenerateResultSchema, {
15625
+ kind: "mutation",
15626
+ auth: "admin"
15627
+ }), method(ProfileRefInputSchema, array(string())), method(object({}), array(LlmDefaultSchema)), method(object({
15628
+ selector: LlmDefaultSelectorSchema,
15629
+ profileId: string().nullable()
15630
+ }), _void(), {
15631
+ kind: "mutation",
15632
+ auth: "admin"
15633
+ }), method(object({
15634
+ since: number().optional(),
15635
+ until: number().optional(),
15636
+ consumer: string().optional(),
15637
+ profileId: string().optional()
15638
+ }), array(LlmUsageRollupSchema)), method(object({}), array(ManagedModelCatalogEntrySchema)), method(object({}), array(LlmRuntimeNodeSchema)), method(object({ nodeId: string() }), array(LlmNodeModelSchema)), method(object({
15639
+ nodeId: string(),
15640
+ model: ManagedModelRefSchema
15641
+ }), _void(), {
15642
+ kind: "mutation",
15643
+ auth: "admin"
15644
+ }), method(object({
15645
+ nodeId: string(),
15646
+ file: string()
15647
+ }), _void(), {
15648
+ kind: "mutation",
15649
+ auth: "admin"
15650
+ }), method(ProfileRefInputSchema, LlmRuntimeStatusSchema), method(ProfileRefInputSchema, LlmRuntimeStatusSchema, {
15651
+ kind: "mutation",
15652
+ auth: "admin"
15653
+ }), method(ProfileRefInputSchema, _void(), {
15654
+ kind: "mutation",
15655
+ auth: "admin"
15656
+ });
15657
+ /**
15102
15658
  * Zod schemas for persisted record types.
15103
15659
  *
15104
15660
  * These schemas serve as the single source of truth for types that are
@@ -15300,6 +15856,22 @@ var TrackSnapshotSchema = object({
15300
15856
  /** MediaStore key; resolve via `getTrackMedia({ trackId })`. */
15301
15857
  mediaKey: string()
15302
15858
  });
15859
+ /**
15860
+ * One audio-classification label heard on the track's camera while the
15861
+ * track was alive, aggregated per label. An "episode" is one persisted
15862
+ * audio event (the confident-classification path: score ≥ the device's
15863
+ * `classificationMinScore`, class-change-or-heartbeat coalesced) — NOT
15864
+ * one 32 ms inference chunk, so counts stay human-scaled.
15865
+ */
15866
+ var TrackAudioLabelSchema = object({
15867
+ label: string(),
15868
+ /** Highest classification score observed across the label's episodes. */
15869
+ peakScore: number(),
15870
+ /** Number of coalesced audio-event episodes carrying this label. */
15871
+ count: number(),
15872
+ firstAt: number(),
15873
+ lastAt: number()
15874
+ });
15303
15875
  var TrackSchema = object({
15304
15876
  trackId: string(),
15305
15877
  deviceId: number(),
@@ -15314,6 +15886,10 @@ var TrackSchema = object({
15314
15886
  snapshots: array(TrackSnapshotSchema).readonly(),
15315
15887
  /** Deduplicated zones the track has entered at least once. */
15316
15888
  zonesVisited: array(string()).readonly(),
15889
+ /** Deduplicated set of detector classes observed for this track over its
15890
+ * life (a track may be reclassified, e.g. person→vehicle). Absent on
15891
+ * legacy rows written before class accumulation shipped. */
15892
+ classes: array(string()).readonly().optional(),
15317
15893
  /** Cumulative normalized distance travelled (0..1 units = full frame width). */
15318
15894
  totalDistance: number(),
15319
15895
  state: TrackStateSchema,
@@ -15327,7 +15903,11 @@ var TrackSchema = object({
15327
15903
  bestEventId: string().optional(),
15328
15904
  /** Tag of the importance sub-signal that dominated the score
15329
15905
  * (identity|dwell|proximity|class|confidence|travel|zone). */
15330
- importanceReason: string().optional()
15906
+ importanceReason: string().optional(),
15907
+ /** Audio-classification labels heard on the camera during the track's
15908
+ * life (score ≥ device `classificationMinScore`), aggregated per label.
15909
+ * Absent on legacy rows / tracks with no confident audio. */
15910
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional()
15331
15911
  });
15332
15912
  var BaseEventFields = {
15333
15913
  id: string(),
@@ -15475,7 +16055,7 @@ var KeyEventSchema = object({
15475
16055
  /** Track lifetime in ms (lastSeen - firstSeen). */
15476
16056
  windowMs: number().optional()
15477
16057
  });
15478
- var TrackedDetectionSchema = object({
16058
+ object({
15479
16059
  trackId: string(),
15480
16060
  className: string(),
15481
16061
  confidence: number(),
@@ -15483,6 +16063,23 @@ var TrackedDetectionSchema = object({
15483
16063
  zones: array(string()).readonly(),
15484
16064
  state: TrackStateSchema
15485
16065
  });
16066
+ var OverlayDetectionSchema = looseObject({
16067
+ id: string(),
16068
+ kind: _enum(["first-level", "detail"]),
16069
+ macroClass: string(),
16070
+ score: number(),
16071
+ bbox: object({
16072
+ x: number(),
16073
+ y: number(),
16074
+ width: number(),
16075
+ height: number()
16076
+ }),
16077
+ labels: array(looseObject({
16078
+ label: string(),
16079
+ score: number()
16080
+ })).readonly(),
16081
+ parentId: string().optional()
16082
+ });
15486
16083
  var ScoredObjectEventSchema = ObjectEventSchema.extend({ score: number() });
15487
16084
  var SearchObjectEventsInput = object({
15488
16085
  text: string(),
@@ -15493,6 +16090,20 @@ var SearchObjectEventsInput = object({
15493
16090
  limit: number().default(50),
15494
16091
  minScore: number().min(0).max(1).default(.2)
15495
16092
  });
16093
+ var TrackCascadeCountsSchema = object({
16094
+ /** Persisted track roots deleted (authoritative). */
16095
+ tracks: number().int(),
16096
+ /** Object events removed with their tracks (best-effort; see note above). */
16097
+ events: number().int(),
16098
+ /** Track/face/plate-owned media removed (best-effort). Never identity media. */
16099
+ media: number().int(),
16100
+ /** Unassigned (non-enrolled) face reads removed (best-effort). */
16101
+ faces: number().int(),
16102
+ /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
16103
+ plates: number().int(),
16104
+ /** Per-track CLIP search vectors removed (best-effort). */
16105
+ embeddings: number().int()
16106
+ });
15496
16107
  var pipelineAnalyticsCapability = {
15497
16108
  name: "pipeline-analytics",
15498
16109
  scope: "device",
@@ -15546,12 +16157,14 @@ var pipelineAnalyticsCapability = {
15546
16157
  audio: number().int()
15547
16158
  })).readonly()),
15548
16159
  /**
15549
- * Delete all events (motion + object + audio) for the given device
15550
- * that are older than `cutoffMs` (exclusive), and delete their
15551
- * thumbnails in lockstep. Returns per-kind deleted counts.
15552
- *
15553
- * Called by Phase B3 recorder orchestration to keep event history
15554
- * aligned with available footage.
16160
+ * @deprecated Prefer `pruneTracksBefore` the track is the ROOT of the
16161
+ * analytics model and retention must cascade from it (design §5.1). This
16162
+ * event-only prune leaves orphaned tracks/faces/plates/embeddings behind.
16163
+ * Retained as a compat shim for the Phase-B3 recorder orchestration caller,
16164
+ * which prunes events to keep history aligned with available footage and
16165
+ * reads the per-kind counts. Delete all events (motion + object + audio)
16166
+ * for the given device older than `cutoffMs` (exclusive) + their thumbnails
16167
+ * in lockstep; returns per-kind deleted counts.
15555
16168
  */
15556
16169
  pruneEventsBefore: method(object({
15557
16170
  deviceId: number(),
@@ -15564,6 +16177,55 @@ var pipelineAnalyticsCapability = {
15564
16177
  kind: "mutation",
15565
16178
  auth: "admin"
15566
16179
  }),
16180
+ /**
16181
+ * Track-centric retention entry point (design §5.1). Selects every
16182
+ * persisted track for the device whose `lastSeen < cutoffMs` (paged) and
16183
+ * runs the extensible whole-track deletion cascade (design §3): object
16184
+ * events + their media, track/face/plate-owned media, unassigned face
16185
+ * reads, per-track CLIP embeddings, then the track root LAST. ENROLLED
16186
+ * (assigned) faces/plates and `ownerKind:'identity'` media are exempt —
16187
+ * the durable matching gallery always persists. Fires the per-track
16188
+ * live-state cleanup so a pruned track can't linger in dispatch/overlay
16189
+ * state. Returns per-family deleted counts (`tracks` authoritative).
16190
+ *
16191
+ * Replaces `pruneEventsBefore` as the correct time-based retention prune.
16192
+ */
16193
+ pruneTracksBefore: method(object({
16194
+ deviceId: number(),
16195
+ cutoffMs: number()
16196
+ }), TrackCascadeCountsSchema, {
16197
+ kind: "mutation",
16198
+ auth: "admin"
16199
+ }),
16200
+ /**
16201
+ * Operator "clean slate" for a device (design §5.3): prune EVERY track for
16202
+ * the device via the same cascade as `pruneTracksBefore` with `cutoffMs =
16203
+ * now`. One call per device — no client-side track enumeration. Enrolled
16204
+ * gallery + identity media are exempt (design §4). Returns per-family
16205
+ * deleted counts.
16206
+ */
16207
+ wipeAllAnalytics: method(object({ deviceId: number() }), TrackCascadeCountsSchema, {
16208
+ kind: "mutation",
16209
+ auth: "admin"
16210
+ }),
16211
+ /**
16212
+ * Delete whole tracks (object events) by id for the given device,
16213
+ * cascading their media in lockstep. Returns the number of tracks
16214
+ * actually deleted plus the ids that could not be removed.
16215
+ *
16216
+ * Operator-driven from the DI Events page (batch delete). Routes through
16217
+ * the same widened track-deletion cascade (design §5.2).
16218
+ */
16219
+ deleteTracks: method(object({
16220
+ deviceId: number(),
16221
+ trackIds: array(string()).min(1)
16222
+ }), object({
16223
+ deleted: number().int(),
16224
+ failed: array(string()).readonly()
16225
+ }), {
16226
+ kind: "mutation",
16227
+ auth: "admin"
16228
+ }),
15567
16229
  getEventMedia: method(object({
15568
16230
  eventId: string(),
15569
16231
  kind: MediaFileKindEnum.optional()
@@ -15581,17 +16243,19 @@ var pipelineAnalyticsCapability = {
15581
16243
  },
15582
16244
  events: {
15583
16245
  /**
15584
- * Enriched frame emitted after refinement. Carries lightweight
15585
- * tracked-detection metadata (track id, class, zones, state) so
15586
- * downstream consumers (stream overlays, notifications) can
15587
- * annotate without querying full Track state.
16246
+ * Enriched frame emitted after refinement the live-overlay source of
16247
+ * truth (two-plane re-injection). Carries the frame's detections in the
16248
+ * `ObjectDetection` wire shape: first-level roots (with track info +
16249
+ * enrichment labels) plus synthesized `kind:'detail'` face/plate entries
16250
+ * re-projected from per-track detail state, so stream overlays render
16251
+ * boxes + recognized names without querying full Track state.
15588
16252
  */
15589
16253
  onFrameTracked: { data: object({
15590
16254
  deviceId: number(),
15591
16255
  timestamp: number(),
15592
16256
  frameWidth: number(),
15593
16257
  frameHeight: number(),
15594
- detections: array(TrackedDetectionSchema).readonly()
16258
+ detections: array(OverlayDetectionSchema).readonly()
15595
16259
  }) },
15596
16260
  /** Track entered active state (first-seen). */
15597
16261
  onTrackStarted: { data: object({
@@ -18404,6 +19068,24 @@ DeviceType.Camera, method(object({
18404
19068
  deviceId: number(),
18405
19069
  status: OsdStatusSchema
18406
19070
  });
19071
+ var VehicleSchema = object({
19072
+ id: string(),
19073
+ name: string(),
19074
+ sampleCount: number().int().nonnegative(),
19075
+ coverMediaKey: string().optional(),
19076
+ /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaKey`. */
19077
+ coverBase64: string().optional()
19078
+ });
19079
+ var VehicleSampleInfoSchema = object({
19080
+ id: string(),
19081
+ /** The plate text this sample enrolled (self-labeling — no embedding). */
19082
+ text: string(),
19083
+ /** OCR confidence of the enrolled read (0..1). */
19084
+ score: number(),
19085
+ addedAt: number().int(),
19086
+ deviceId: number().int().optional(),
19087
+ base64: string().optional()
19088
+ });
18407
19089
  var PlateInfoSchema = object({
18408
19090
  plateId: string(),
18409
19091
  deviceId: number().int(),
@@ -18415,6 +19097,16 @@ var PlateInfoSchema = object({
18415
19097
  score: number(),
18416
19098
  /** True when the text was manually corrected (exempt from retention). */
18417
19099
  corrected: boolean(),
19100
+ /** Recognized vehicle id when a matcher lookup named this read (SQL NULL → absent). */
19101
+ recognizedVehicleId: string().optional(),
19102
+ /** Resolved vehicle name for `recognizedVehicleId` (UI convenience). */
19103
+ vehicleName: string().optional(),
19104
+ /** True once the read was assigned to a vehicle (enrolled as a sample). */
19105
+ assigned: boolean(),
19106
+ /** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
19107
+ plateBbox: BoundingBoxSchema.optional(),
19108
+ /** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
19109
+ keyFrameMediaKey: string().optional(),
18418
19110
  base64: string().optional()
18419
19111
  });
18420
19112
  var MediaFileLiteSchema = object({
@@ -18476,6 +19168,58 @@ var plateGalleryCapability = {
18476
19168
  deletePlate: method(object({ plateId: string() }), _void(), {
18477
19169
  kind: "mutation",
18478
19170
  auth: "admin"
19171
+ }),
19172
+ listVehicles: method(_void(), array(VehicleSchema).readonly()),
19173
+ createVehicle: method(object({ name: string().min(1) }), VehicleSchema, {
19174
+ kind: "mutation",
19175
+ auth: "admin"
19176
+ }),
19177
+ renameVehicle: method(object({
19178
+ id: string(),
19179
+ name: string().min(1)
19180
+ }), _void(), {
19181
+ kind: "mutation",
19182
+ auth: "admin"
19183
+ }),
19184
+ deleteVehicle: method(object({ id: string() }), _void(), {
19185
+ kind: "mutation",
19186
+ auth: "admin"
19187
+ }),
19188
+ listVehicleSamples: method(object({ vehicleId: string() }), array(VehicleSampleInfoSchema).readonly()),
19189
+ removeVehicleSample: method(object({
19190
+ vehicleId: string(),
19191
+ sampleId: string()
19192
+ }), _void(), {
19193
+ kind: "mutation",
19194
+ auth: "admin"
19195
+ }),
19196
+ assignPlate: method(object({
19197
+ plateId: string(),
19198
+ vehicleId: string()
19199
+ }), _void(), {
19200
+ kind: "mutation",
19201
+ auth: "admin"
19202
+ }),
19203
+ unassignPlate: method(object({ plateId: string() }), _void(), {
19204
+ kind: "mutation",
19205
+ auth: "admin"
19206
+ }),
19207
+ assignPlates: method(object({
19208
+ plateIds: array(string()).min(1),
19209
+ vehicleId: string()
19210
+ }), object({
19211
+ assigned: number().int(),
19212
+ failed: array(string()).readonly()
19213
+ }), {
19214
+ kind: "mutation",
19215
+ auth: "admin"
19216
+ }),
19217
+ unassignPlates: method(object({ plateIds: array(string()).min(1) }), object({
19218
+ unassigned: number().int(),
19219
+ failed: array(string()).readonly()
19220
+ }), {
19221
+ kind: "mutation",
19222
+ auth: "admin"
18479
19223
  })
18480
19224
  }
18481
19225
  };
@@ -18556,6 +19300,10 @@ var GpuInfoSchema = object({
18556
19300
  memoryMB: number().optional()
18557
19301
  });
18558
19302
  var NpuInfoSchema = object({ type: _enum(["apple-ane", "intel-npu"]) });
19303
+ var CoralInfoSchema = object({
19304
+ type: literal("coral-edgetpu"),
19305
+ bus: string().optional()
19306
+ });
18559
19307
  var HardwareInfoSchema = object({
18560
19308
  platform: HardwarePlatformSchema,
18561
19309
  arch: HardwareArchSchema,
@@ -18564,7 +19312,8 @@ var HardwareInfoSchema = object({
18564
19312
  totalRAM_MB: number(),
18565
19313
  availableRAM_MB: number(),
18566
19314
  gpu: GpuInfoSchema.nullable(),
18567
- npu: NpuInfoSchema.nullable()
19315
+ npu: NpuInfoSchema.nullable(),
19316
+ coral: CoralInfoSchema.nullable().optional()
18568
19317
  });
18569
19318
  var PlatformScoreSchema = object({
18570
19319
  runtime: _enum(["node", "python"]),
@@ -21023,6 +21772,168 @@ Object.freeze({
21023
21772
  addonId: null,
21024
21773
  access: "create"
21025
21774
  },
21775
+ "llm.deleteModel": {
21776
+ capName: "llm",
21777
+ capScope: "system",
21778
+ addonId: null,
21779
+ access: "delete"
21780
+ },
21781
+ "llm.deleteProfile": {
21782
+ capName: "llm",
21783
+ capScope: "system",
21784
+ addonId: null,
21785
+ access: "delete"
21786
+ },
21787
+ "llm.generate": {
21788
+ capName: "llm",
21789
+ capScope: "system",
21790
+ addonId: null,
21791
+ access: "create"
21792
+ },
21793
+ "llm.generateVision": {
21794
+ capName: "llm",
21795
+ capScope: "system",
21796
+ addonId: null,
21797
+ access: "create"
21798
+ },
21799
+ "llm.getDefaults": {
21800
+ capName: "llm",
21801
+ capScope: "system",
21802
+ addonId: null,
21803
+ access: "view"
21804
+ },
21805
+ "llm.getRuntimeStatus": {
21806
+ capName: "llm",
21807
+ capScope: "system",
21808
+ addonId: null,
21809
+ access: "view"
21810
+ },
21811
+ "llm.getUsage": {
21812
+ capName: "llm",
21813
+ capScope: "system",
21814
+ addonId: null,
21815
+ access: "view"
21816
+ },
21817
+ "llm.installModel": {
21818
+ capName: "llm",
21819
+ capScope: "system",
21820
+ addonId: null,
21821
+ access: "create"
21822
+ },
21823
+ "llm.listModelCatalog": {
21824
+ capName: "llm",
21825
+ capScope: "system",
21826
+ addonId: null,
21827
+ access: "view"
21828
+ },
21829
+ "llm.listModels": {
21830
+ capName: "llm",
21831
+ capScope: "system",
21832
+ addonId: null,
21833
+ access: "view"
21834
+ },
21835
+ "llm.listNodeModels": {
21836
+ capName: "llm",
21837
+ capScope: "system",
21838
+ addonId: null,
21839
+ access: "view"
21840
+ },
21841
+ "llm.listProfileKinds": {
21842
+ capName: "llm",
21843
+ capScope: "system",
21844
+ addonId: null,
21845
+ access: "view"
21846
+ },
21847
+ "llm.listProfiles": {
21848
+ capName: "llm",
21849
+ capScope: "system",
21850
+ addonId: null,
21851
+ access: "view"
21852
+ },
21853
+ "llm.listRuntimeNodes": {
21854
+ capName: "llm",
21855
+ capScope: "system",
21856
+ addonId: null,
21857
+ access: "view"
21858
+ },
21859
+ "llm.setDefault": {
21860
+ capName: "llm",
21861
+ capScope: "system",
21862
+ addonId: null,
21863
+ access: "create"
21864
+ },
21865
+ "llm.startRuntime": {
21866
+ capName: "llm",
21867
+ capScope: "system",
21868
+ addonId: null,
21869
+ access: "create"
21870
+ },
21871
+ "llm.stopRuntime": {
21872
+ capName: "llm",
21873
+ capScope: "system",
21874
+ addonId: null,
21875
+ access: "create"
21876
+ },
21877
+ "llm.testProfile": {
21878
+ capName: "llm",
21879
+ capScope: "system",
21880
+ addonId: null,
21881
+ access: "create"
21882
+ },
21883
+ "llm.upsertProfile": {
21884
+ capName: "llm",
21885
+ capScope: "system",
21886
+ addonId: null,
21887
+ access: "create"
21888
+ },
21889
+ "llmRuntime.complete": {
21890
+ capName: "llm-runtime",
21891
+ capScope: "system",
21892
+ addonId: null,
21893
+ access: "create"
21894
+ },
21895
+ "llmRuntime.deleteModel": {
21896
+ capName: "llm-runtime",
21897
+ capScope: "system",
21898
+ addonId: null,
21899
+ access: "delete"
21900
+ },
21901
+ "llmRuntime.ensureStarted": {
21902
+ capName: "llm-runtime",
21903
+ capScope: "system",
21904
+ addonId: null,
21905
+ access: "create"
21906
+ },
21907
+ "llmRuntime.getDiskUsage": {
21908
+ capName: "llm-runtime",
21909
+ capScope: "system",
21910
+ addonId: null,
21911
+ access: "view"
21912
+ },
21913
+ "llmRuntime.installModel": {
21914
+ capName: "llm-runtime",
21915
+ capScope: "system",
21916
+ addonId: null,
21917
+ access: "create"
21918
+ },
21919
+ "llmRuntime.listLocalModels": {
21920
+ capName: "llm-runtime",
21921
+ capScope: "system",
21922
+ addonId: null,
21923
+ access: "view"
21924
+ },
21925
+ "llmRuntime.status": {
21926
+ capName: "llm-runtime",
21927
+ capScope: "system",
21928
+ addonId: null,
21929
+ access: "view"
21930
+ },
21931
+ "llmRuntime.stop": {
21932
+ capName: "llm-runtime",
21933
+ capScope: "system",
21934
+ addonId: null,
21935
+ access: "create"
21936
+ },
21026
21937
  "localNetwork.getAllowedAddresses": {
21027
21938
  capName: "local-network",
21028
21939
  capScope: "system",
@@ -21653,6 +22564,12 @@ Object.freeze({
21653
22564
  addonId: null,
21654
22565
  access: "delete"
21655
22566
  },
22567
+ "pipelineAnalytics.deleteTracks": {
22568
+ capName: "pipeline-analytics",
22569
+ capScope: "device",
22570
+ addonId: null,
22571
+ access: "delete"
22572
+ },
21656
22573
  "pipelineAnalytics.getActiveTracks": {
21657
22574
  capName: "pipeline-analytics",
21658
22575
  capScope: "device",
@@ -21719,12 +22636,24 @@ Object.freeze({
21719
22636
  addonId: null,
21720
22637
  access: "create"
21721
22638
  },
22639
+ "pipelineAnalytics.pruneTracksBefore": {
22640
+ capName: "pipeline-analytics",
22641
+ capScope: "device",
22642
+ addonId: null,
22643
+ access: "create"
22644
+ },
21722
22645
  "pipelineAnalytics.searchObjectEvents": {
21723
22646
  capName: "pipeline-analytics",
21724
22647
  capScope: "device",
21725
22648
  addonId: null,
21726
22649
  access: "view"
21727
22650
  },
22651
+ "pipelineAnalytics.wipeAllAnalytics": {
22652
+ capName: "pipeline-analytics",
22653
+ capScope: "device",
22654
+ addonId: null,
22655
+ access: "delete"
22656
+ },
21728
22657
  "pipelineExecutor.cacheFrameInPool": {
21729
22658
  capName: "pipeline-executor",
21730
22659
  capScope: "system",
@@ -22229,18 +23158,42 @@ Object.freeze({
22229
23158
  addonId: null,
22230
23159
  access: "create"
22231
23160
  },
23161
+ "plateGallery.assignPlate": {
23162
+ capName: "plate-gallery",
23163
+ capScope: "system",
23164
+ addonId: null,
23165
+ access: "create"
23166
+ },
23167
+ "plateGallery.assignPlates": {
23168
+ capName: "plate-gallery",
23169
+ capScope: "system",
23170
+ addonId: null,
23171
+ access: "create"
23172
+ },
22232
23173
  "plateGallery.correctPlateText": {
22233
23174
  capName: "plate-gallery",
22234
23175
  capScope: "system",
22235
23176
  addonId: null,
22236
23177
  access: "create"
22237
23178
  },
23179
+ "plateGallery.createVehicle": {
23180
+ capName: "plate-gallery",
23181
+ capScope: "system",
23182
+ addonId: null,
23183
+ access: "create"
23184
+ },
22238
23185
  "plateGallery.deletePlate": {
22239
23186
  capName: "plate-gallery",
22240
23187
  capScope: "system",
22241
23188
  addonId: null,
22242
23189
  access: "delete"
22243
23190
  },
23191
+ "plateGallery.deleteVehicle": {
23192
+ capName: "plate-gallery",
23193
+ capScope: "system",
23194
+ addonId: null,
23195
+ access: "delete"
23196
+ },
22244
23197
  "plateGallery.getPlateByTrack": {
22245
23198
  capName: "plate-gallery",
22246
23199
  capScope: "system",
@@ -22259,6 +23212,30 @@ Object.freeze({
22259
23212
  addonId: null,
22260
23213
  access: "view"
22261
23214
  },
23215
+ "plateGallery.listVehicles": {
23216
+ capName: "plate-gallery",
23217
+ capScope: "system",
23218
+ addonId: null,
23219
+ access: "view"
23220
+ },
23221
+ "plateGallery.listVehicleSamples": {
23222
+ capName: "plate-gallery",
23223
+ capScope: "system",
23224
+ addonId: null,
23225
+ access: "view"
23226
+ },
23227
+ "plateGallery.removeVehicleSample": {
23228
+ capName: "plate-gallery",
23229
+ capScope: "system",
23230
+ addonId: null,
23231
+ access: "delete"
23232
+ },
23233
+ "plateGallery.renameVehicle": {
23234
+ capName: "plate-gallery",
23235
+ capScope: "system",
23236
+ addonId: null,
23237
+ access: "create"
23238
+ },
22262
23239
  "plateGallery.searchPlates": {
22263
23240
  capName: "plate-gallery",
22264
23241
  capScope: "system",
@@ -22271,6 +23248,18 @@ Object.freeze({
22271
23248
  addonId: null,
22272
23249
  access: "view"
22273
23250
  },
23251
+ "plateGallery.unassignPlate": {
23252
+ capName: "plate-gallery",
23253
+ capScope: "system",
23254
+ addonId: null,
23255
+ access: "create"
23256
+ },
23257
+ "plateGallery.unassignPlates": {
23258
+ capName: "plate-gallery",
23259
+ capScope: "system",
23260
+ addonId: null,
23261
+ access: "create"
23262
+ },
22274
23263
  "platformProbe.getCapabilities": {
22275
23264
  capName: "platform-probe",
22276
23265
  capScope: "system",
@@ -22463,6 +23452,48 @@ Object.freeze({
22463
23452
  addonId: null,
22464
23453
  access: "create"
22465
23454
  },
23455
+ "sceneMonitor.captureReference": {
23456
+ capName: "scene-monitor",
23457
+ capScope: "device",
23458
+ addonId: null,
23459
+ access: "create"
23460
+ },
23461
+ "sceneMonitor.createScene": {
23462
+ capName: "scene-monitor",
23463
+ capScope: "device",
23464
+ addonId: null,
23465
+ access: "create"
23466
+ },
23467
+ "sceneMonitor.deleteReference": {
23468
+ capName: "scene-monitor",
23469
+ capScope: "device",
23470
+ addonId: null,
23471
+ access: "delete"
23472
+ },
23473
+ "sceneMonitor.deleteScene": {
23474
+ capName: "scene-monitor",
23475
+ capScope: "device",
23476
+ addonId: null,
23477
+ access: "delete"
23478
+ },
23479
+ "sceneMonitor.listScenes": {
23480
+ capName: "scene-monitor",
23481
+ capScope: "device",
23482
+ addonId: null,
23483
+ access: "view"
23484
+ },
23485
+ "sceneMonitor.recheckNow": {
23486
+ capName: "scene-monitor",
23487
+ capScope: "device",
23488
+ addonId: null,
23489
+ access: "create"
23490
+ },
23491
+ "sceneMonitor.updateScene": {
23492
+ capName: "scene-monitor",
23493
+ capScope: "device",
23494
+ addonId: null,
23495
+ access: "create"
23496
+ },
22466
23497
  "scriptRunner.run": {
22467
23498
  capName: "script-runner",
22468
23499
  capScope: "device",
@@ -23547,6 +24578,7 @@ Object.freeze({
23547
24578
  Object.freeze({
23548
24579
  "broker": "broker",
23549
24580
  "device-export": "device-export",
24581
+ "llm": "ai",
23550
24582
  "mesh-network": "mesh",
23551
24583
  "mqtt-broker": "broker",
23552
24584
  "network-access": "ingress",
@@ -23579,4 +24611,4 @@ object({
23579
24611
  schemaVersion: literal(1)
23580
24612
  });
23581
24613
  //#endregion
23582
- export { number as C, tuple as E, boolean as S, string as T, asJsonObject as _, embeddingEncoderCapability as a, _enum as b, nodePin as c, videoclipsCapability as d, zoneAnalyticsCapability as f, EventCategory as g, DeviceType as h, cosineSimilarity as i, pipelineAnalyticsCapability as l, BaseAddon as m, addonWidgetsSourceCapability as n, faceGalleryCapability as o, errMsg as p, audioMetricsCapability as r, hfModelUrl as s, EVENT_PAD_MS as t, plateGalleryCapability as u, createEvent as v, object as w, array as x, hydrateSchema as y };
24614
+ export { string as S, createEvent as _, embeddingEncoderCapability as a, number as b, nodePin as c, videoclipsCapability as d, zoneAnalyticsCapability as f, EventCategory as g, DeviceType as h, cosineSimilarity as i, pipelineAnalyticsCapability as l, BaseAddon as m, addonWidgetsSourceCapability as n, faceGalleryCapability as o, errMsg as p, audioMetricsCapability as r, hfModelUrl as s, EVENT_PAD_MS as t, plateGalleryCapability as u, hydrateSchema as v, object as x, boolean as y };