camstack 1.1.26 → 1.1.27

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.
@@ -14522,7 +14522,7 @@ function date4(params) {
14522
14522
  // ../../node_modules/zod/v4/classic/external.js
14523
14523
  config(en_default());
14524
14524
 
14525
- // ../types/dist/sleep-Br7r_3fq.mjs
14525
+ // ../types/dist/sleep-CK899CTS.mjs
14526
14526
  var WELL_KNOWN_TABS = [
14527
14527
  {
14528
14528
  id: "overview",
@@ -18401,7 +18401,10 @@ var doorbellCapability = {
18401
18401
  scope: "device",
18402
18402
  deviceNative: true,
18403
18403
  mode: "singleton",
18404
- deviceTypes: [DeviceType.Button],
18404
+ kind: "wrapper",
18405
+ defaultActive: false,
18406
+ deviceTypes: [DeviceType.Button, DeviceType.Camera],
18407
+ exposesDeviceSettings: true,
18405
18408
  methods: {},
18406
18409
  events: {
18407
18410
  /**
@@ -23740,6 +23743,13 @@ var ConfigEntrySchema2 = external_exports.object({
23740
23743
  value: external_exports.unknown(),
23741
23744
  description: external_exports.string().optional()
23742
23745
  });
23746
+ var DeviceLinkModeSchema = external_exports.enum(["auto", "manual"]);
23747
+ var LinkedDeviceSchema = external_exports.object({
23748
+ deviceId: external_exports.number(),
23749
+ name: external_exports.string(),
23750
+ location: external_exports.string().nullable(),
23751
+ features: external_exports.array(external_exports.string())
23752
+ });
23743
23753
  var SavedDeviceRowSchema = external_exports.object({
23744
23754
  /** Numeric id reserved at allocateDeviceId time. */
23745
23755
  id: external_exports.number(),
@@ -23842,6 +23852,7 @@ var deviceManagerCapability = {
23842
23852
  name: "device-manager",
23843
23853
  scope: "system",
23844
23854
  mode: "singleton",
23855
+ exposesDeviceSettings: true,
23845
23856
  methods: {
23846
23857
  /** Reserve (or re-resolve) a progressive numeric id for `(addonId, stableId)`.
23847
23858
  * Idempotent: returns the existing id if one is already persisted for the
@@ -24092,6 +24103,19 @@ var deviceManagerCapability = {
24092
24103
  getDevice: method(external_exports.object({ deviceId: external_exports.number() }), DeviceInfoSchema.nullable()),
24093
24104
  /** List children of a parent device (by parent numeric id). */
24094
24105
  getChildren: method(external_exports.object({ parentDeviceId: external_exports.number() }), external_exports.array(DeviceInfoSchema)),
24106
+ /**
24107
+ * Resolve the devices LINKED to a camera — the single policy authority
24108
+ * both consumers call (viewer devices panel + pipeline-analytics event
24109
+ * kinds/ingest). Device-tree children are ALWAYS included; mode 'auto'
24110
+ * (default) adds every device sharing the camera's non-null `location`,
24111
+ * mode 'manual' adds the persisted manual list instead. Excludes the
24112
+ * camera itself; deduped. Configuration is standard per-device settings
24113
+ * (see the module docblock) — there are no bespoke link mutations.
24114
+ */
24115
+ getLinkedDevices: method(external_exports.object({ deviceId: external_exports.number() }), external_exports.object({
24116
+ mode: DeviceLinkModeSchema,
24117
+ devices: external_exports.array(LinkedDeviceSchema)
24118
+ })),
24095
24119
  /** Get stream sources for a camera device. */
24096
24120
  getStreamSources: method(external_exports.object({ deviceId: external_exports.number() }), external_exports.array(StreamSourceEntrySchema$1)),
24097
24121
  /** Get config entries (key + value + description) for a device. */
@@ -25544,6 +25568,55 @@ var EventKindSchema = external_exports.enum([
25544
25568
  "object",
25545
25569
  "audio"
25546
25570
  ]);
25571
+ var TrackZoneFilterSchema = external_exports.discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
25572
+ var EventKindIconSchema = external_exports.enum([
25573
+ "motion",
25574
+ "audio",
25575
+ "person",
25576
+ "vehicle",
25577
+ "animal",
25578
+ "door",
25579
+ "pir",
25580
+ "smoke",
25581
+ "water",
25582
+ "button",
25583
+ "generic"
25584
+ ]);
25585
+ var EventKindCategorySchema = external_exports.enum([
25586
+ "motion",
25587
+ "audio",
25588
+ "detection",
25589
+ "sensor",
25590
+ "custom"
25591
+ ]);
25592
+ var EventKindDescriptorSchema = external_exports.object({
25593
+ /** Stable kind id (e.g. 'motion', 'person', 'contact'). */
25594
+ kind: external_exports.string(),
25595
+ label: external_exports.string(),
25596
+ /** Hex color for timeline/legend rendering. */
25597
+ color: external_exports.string(),
25598
+ icon: EventKindIconSchema,
25599
+ category: EventKindCategorySchema,
25600
+ /** Which cap + device contributes this kind. For built-ins the camera
25601
+ * itself; for sensor kinds the LINKED source device. */
25602
+ source: external_exports.object({
25603
+ capName: external_exports.string(),
25604
+ deviceId: external_exports.number()
25605
+ })
25606
+ });
25607
+ var SensorEventSchema = external_exports.object({
25608
+ id: external_exports.string(),
25609
+ /** The CAMERA the event is attributed to (a sensor linked to N cameras
25610
+ * yields N rows, one per camera). */
25611
+ deviceId: external_exports.number(),
25612
+ /** The linked sensor device whose state changed. */
25613
+ sourceDeviceId: external_exports.number(),
25614
+ /** Event kind id — matches an `EventKindDescriptor.kind`. */
25615
+ kind: external_exports.string(),
25616
+ /** Snapshot of the sensor cap's runtime-state slice at the change. */
25617
+ value: external_exports.record(external_exports.string(), external_exports.unknown()).nullable(),
25618
+ timestamp: external_exports.number()
25619
+ });
25547
25620
  var TrackPositionSchema = external_exports.object({
25548
25621
  x: external_exports.number(),
25549
25622
  y: external_exports.number(),
@@ -25556,6 +25629,13 @@ var TrackSnapshotSchema = external_exports.object({
25556
25629
  /** MediaStore key; resolve via `getTrackMedia({ trackId })`. */
25557
25630
  mediaKey: external_exports.string()
25558
25631
  });
25632
+ var TrackEnvelopeSchema = external_exports.object({
25633
+ minX: external_exports.number(),
25634
+ minY: external_exports.number(),
25635
+ maxX: external_exports.number(),
25636
+ maxY: external_exports.number()
25637
+ });
25638
+ var TrackProjectionSchema = external_exports.enum(["full", "slim"]);
25559
25639
  var TrackAudioLabelSchema = external_exports.object({
25560
25640
  label: external_exports.string(),
25561
25641
  /** Highest classification score observed across the label's episodes. */
@@ -25600,7 +25680,11 @@ var TrackSchema = external_exports.object({
25600
25680
  /** Audio-classification labels heard on the camera during the track's
25601
25681
  * life (score ≥ device `classificationMinScore`), aggregated per label.
25602
25682
  * Absent on legacy rows / tracks with no confident audio. */
25603
- audioLabels: external_exports.array(TrackAudioLabelSchema).readonly().optional()
25683
+ audioLabels: external_exports.array(TrackAudioLabelSchema).readonly().optional(),
25684
+ /** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
25685
+ * Populated from the persisted envelope columns on historical reads;
25686
+ * absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
25687
+ envelope: TrackEnvelopeSchema.optional()
25604
25688
  });
25605
25689
  var BaseEventFields = {
25606
25690
  id: external_exports.string(),
@@ -25702,11 +25786,13 @@ var MediaFileSchema = external_exports.object({
25702
25786
  sizeBytes: external_exports.number(),
25703
25787
  timestamp: external_exports.number()
25704
25788
  });
25789
+ var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
25790
+ var MAX_EVENT_QUERY_LIMIT = 5e3;
25705
25791
  var DeviceEventQueryInput = external_exports.object({
25706
25792
  deviceId: external_exports.number(),
25707
25793
  since: external_exports.number().optional(),
25708
25794
  until: external_exports.number().optional(),
25709
- limit: external_exports.number().int().min(1).max(5e3).default(1e3),
25795
+ limit: external_exports.number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
25710
25796
  /** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
25711
25797
  * optional `mediaUrl` (populated by B5). `full` (default) keeps today's
25712
25798
  * exact behaviour. Callers may omit this field — the store defaults to
@@ -25714,6 +25800,27 @@ var DeviceEventQueryInput = external_exports.object({
25714
25800
  projection: external_exports.enum(["full", "slim"]).optional()
25715
25801
  });
25716
25802
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: external_exports.string().optional() });
25803
+ var RecentTracksQueryInput = external_exports.object({
25804
+ /** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
25805
+ deviceIds: external_exports.array(external_exports.number()),
25806
+ /** Window lower bound on `lastSeen` (inclusive). */
25807
+ since: external_exports.number().optional(),
25808
+ /** Window upper bound on `lastSeen` (inclusive). */
25809
+ until: external_exports.number().optional(),
25810
+ /** Page size. Default 200, max 1000. */
25811
+ limit: external_exports.number().int().min(1).max(1e3).default(200),
25812
+ /** Opaque continuation cursor from a previous page's `nextCursor`.
25813
+ * Encodes the (lastSeen, trackId) sort position — treat as opaque. */
25814
+ cursor: external_exports.string().optional(),
25815
+ /** See {@link TrackProjectionSchema}. Default `full`. */
25816
+ projection: TrackProjectionSchema.optional()
25817
+ });
25818
+ var RecentTracksPageSchema = external_exports.object({
25819
+ /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
25820
+ tracks: external_exports.array(TrackSchema).readonly(),
25821
+ /** Cursor for the next page, or null when this page is the last. */
25822
+ nextCursor: external_exports.string().nullable()
25823
+ });
25717
25824
  var KeyEventQueryInput = external_exports.object({
25718
25825
  deviceId: external_exports.number(),
25719
25826
  /** Window lower bound (track firstSeen ≥ since). */
@@ -25810,8 +25917,27 @@ var pipelineAnalyticsCapability = {
25810
25917
  deviceId: external_exports.number(),
25811
25918
  since: external_exports.number().optional(),
25812
25919
  until: external_exports.number().optional(),
25813
- limit: external_exports.number().optional()
25920
+ limit: external_exports.number().optional(),
25921
+ /** Spatial filter — only tracks whose trajectory intersects the zone
25922
+ * (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
25923
+ * envelope columns, then precisely tested per position. Tracks with
25924
+ * an unknown envelope (no frame dims at persist time) always match. */
25925
+ zone: TrackZoneFilterSchema.optional(),
25926
+ /** See {@link TrackProjectionSchema}. Default `full` (backward
25927
+ * compatible — omitting the field keeps today's exact behaviour). */
25928
+ projection: TrackProjectionSchema.optional()
25814
25929
  }), external_exports.array(TrackSchema).readonly()),
25930
+ /**
25931
+ * Batched cluster-wide track listing — ONE call for the events page /
25932
+ * reel first paint instead of a per-camera `listTracks` fan-out. Merges
25933
+ * the persisted completed tracks of every requested device, sorted by
25934
+ * `lastSeen` DESC with a stable (lastSeen, trackId) cursor. Per-device
25935
+ * indexed pages (`idx_tracks_device_lastSeen`) are k-way merged
25936
+ * provider-side; `projection: 'slim'` drops the heavy `positions[]` /
25937
+ * `snapshots[]` JSON (returned as empty arrays). Active in-RAM tracks
25938
+ * are not included (same contract as `listTracks`).
25939
+ */
25940
+ listRecentTracks: method(RecentTracksQueryInput, RecentTracksPageSchema),
25815
25941
  clearTracks: method(external_exports.object({ deviceId: external_exports.number() }), external_exports.void(), {
25816
25942
  kind: "mutation",
25817
25943
  auth: "admin"
@@ -25820,6 +25946,26 @@ var pipelineAnalyticsCapability = {
25820
25946
  getObjectEvents: method(ObjectEventQueryInput, external_exports.array(ObjectEventSchema).readonly()),
25821
25947
  getAudioEvents: method(DeviceEventQueryInput, external_exports.array(AudioEventSchema).readonly()),
25822
25948
  /**
25949
+ * Every event kind the device can produce: built-ins (motion + audio),
25950
+ * detection classes actually observed for the device (from the track
25951
+ * history), and sensor kinds contributed by LINKED devices (resolved via
25952
+ * `device-manager.getLinkedDevices`, mapped through `EVENT_KIND_BY_CAP`).
25953
+ */
25954
+ listEventKinds: method(external_exports.object({ deviceId: external_exports.number() }), external_exports.array(EventKindDescriptorSchema).readonly()),
25955
+ /**
25956
+ * Sensor-event history for a camera: state changes of LINKED sensor
25957
+ * devices, attributed to the camera at ingest time (one row per linked
25958
+ * camera). Mirrors `getAudioEvents` query semantics; `kinds` narrows to
25959
+ * a kind subset.
25960
+ */
25961
+ getSensorEvents: method(external_exports.object({
25962
+ deviceId: external_exports.number(),
25963
+ since: external_exports.number().optional(),
25964
+ until: external_exports.number().optional(),
25965
+ kinds: external_exports.array(external_exports.string()).optional(),
25966
+ limit: external_exports.number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
25967
+ }), external_exports.array(SensorEventSchema).readonly()),
25968
+ /**
25823
25969
  * Importance-ranked highlights for a device+window. Queries completed
25824
25970
  * tracks by (deviceId, firstSeen ∈ [since,until]), scores each (or reuses
25825
25971
  * the persisted score), filters by minImportance/classFilter, orders by
@@ -29758,7 +29904,8 @@ var LocateSegmentResultSchema = external_exports.discriminatedUnion("kind", [ext
29758
29904
  bytes: external_exports.number()
29759
29905
  }), external_exports.object({
29760
29906
  kind: external_exports.literal("gap"),
29761
- nearestEdgeMs: external_exports.number().nullable()
29907
+ nearestEdgeMs: external_exports.number().nullable(),
29908
+ prevEndMs: external_exports.number().nullable().optional()
29762
29909
  })]);
29763
29910
  var ReadSegmentBytesResultSchema = external_exports.object({ data: external_exports.instanceof(Uint8Array) });
29764
29911
  var recordingCapability = {
@@ -31381,6 +31528,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
31381
31528
  addonId: null,
31382
31529
  access: "view"
31383
31530
  },
31531
+ "deviceManager.getLinkedDevices": {
31532
+ capName: "device-manager",
31533
+ capScope: "system",
31534
+ addonId: null,
31535
+ access: "view"
31536
+ },
31384
31537
  "deviceManager.getRoleDisplayDefaults": {
31385
31538
  capName: "device-manager",
31386
31539
  capScope: "system",
@@ -32935,6 +33088,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
32935
33088
  addonId: null,
32936
33089
  access: "view"
32937
33090
  },
33091
+ "pipelineAnalytics.getSensorEvents": {
33092
+ capName: "pipeline-analytics",
33093
+ capScope: "device",
33094
+ addonId: null,
33095
+ access: "view"
33096
+ },
32938
33097
  "pipelineAnalytics.getTrack": {
32939
33098
  capName: "pipeline-analytics",
32940
33099
  capScope: "device",
@@ -32947,6 +33106,18 @@ var METHOD_ACCESS_MAP = Object.freeze({
32947
33106
  addonId: null,
32948
33107
  access: "view"
32949
33108
  },
33109
+ "pipelineAnalytics.listEventKinds": {
33110
+ capName: "pipeline-analytics",
33111
+ capScope: "device",
33112
+ addonId: null,
33113
+ access: "view"
33114
+ },
33115
+ "pipelineAnalytics.listRecentTracks": {
33116
+ capName: "pipeline-analytics",
33117
+ capScope: "device",
33118
+ addonId: null,
33119
+ access: "view"
33120
+ },
32950
33121
  "pipelineAnalytics.listTracks": {
32951
33122
  capName: "pipeline-analytics",
32952
33123
  capScope: "device",
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runDiscover
4
- } from "./chunk-VLAF6UXF.js";
4
+ } from "./chunk-DQY2C7GE.js";
5
5
  import "./chunk-K3NQKI34.js";
6
6
 
7
7
  // src/cli.ts
@@ -1079,7 +1079,7 @@ function isUnknown(_value) {
1079
1079
  return true;
1080
1080
  }
1081
1081
  async function resolveServerInteractive(presetNamespace) {
1082
- const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-BJ6SMXC2.js");
1082
+ const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-RSNWCHBL.js");
1083
1083
  if (presetNamespace) {
1084
1084
  const spinner4 = clack.spinner();
1085
1085
  spinner4.start(`Discovering hub on LAN (namespace "${presetNamespace}")`);
@@ -5,7 +5,7 @@ import {
5
5
  filterHubNodes,
6
6
  resolveHubFromDiscovered,
7
7
  runDiscover
8
- } from "./chunk-VLAF6UXF.js";
8
+ } from "./chunk-DQY2C7GE.js";
9
9
  import "./chunk-K3NQKI34.js";
10
10
  export {
11
11
  DEFAULT_HUB_HTTPS_PORT,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camstack",
3
- "version": "1.1.26",
3
+ "version": "1.1.27",
4
4
  "description": "CLI tool for managing and running CamStack server",
5
5
  "keywords": [
6
6
  "camstack",