@camstack/addon-agent-ui 1.2.165 → 1.2.167

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/addon.js +191 -27
  2. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -19846,14 +19846,52 @@ var NcAlarmNonBlockingEditSchema = object({
19846
19846
  nonBlocking: boolean()
19847
19847
  });
19848
19848
  /**
19849
+ * Controllable openings: opt IN to blocking (default is do not block). Contacts
19850
+ * keep using {@link NcAlarmNonBlockingEditSchema}.
19851
+ */
19852
+ var NcAlarmBlockingEditSchema = object({
19853
+ mode: AlarmArmModeSchema,
19854
+ deviceId: number().int().positive(),
19855
+ /** true = on the list (blocks when open); false = off the list (default). */
19856
+ blocking: boolean()
19857
+ });
19858
+ /**
19859
+ * Controllable openings: opt OUT of secure-on-arm (default is secure ON —
19860
+ * close / lock / turn off when this mode arms).
19861
+ */
19862
+ var NcAlarmSecureOnArmEditSchema = object({
19863
+ mode: AlarmArmModeSchema,
19864
+ deviceId: number().int().positive(),
19865
+ /** true = secure on arm (default); false = do not actuate on arm. */
19866
+ secureOnArm: boolean()
19867
+ });
19868
+ /**
19869
+ * One arm mode's device-id list (non-blocking, blocking, or secure-on-arm-off).
19870
+ */
19871
+ var NcAlarmModeDeviceListSchema = object({
19872
+ mode: AlarmArmModeSchema,
19873
+ deviceIds: array(number().int()).max(200)
19874
+ });
19875
+ /**
19876
+ * One arm mode's non-blocking list: devices that may be open when that mode
19877
+ * arms, without the arm being refused.
19878
+ */
19879
+ var NcAlarmNonBlockingSchema = NcAlarmModeDeviceListSchema;
19880
+ /** Controllable devices that DO block when open (opt-in; default empty). */
19881
+ var NcAlarmBlockingSchema = NcAlarmModeDeviceListSchema;
19882
+ /**
19883
+ * Controllable devices that do NOT secure on arm (opt-out; default empty =
19884
+ * every controllable secures).
19885
+ */
19886
+ var NcAlarmSecureOnArmOffSchema = NcAlarmModeDeviceListSchema;
19887
+ /**
19849
19888
  * The per-mode lists, at most one per mode. Two lists for one mode have no
19850
19889
  * meaning a reader could agree on (union? the last one?), so they are refused
19851
19890
  * at the boundary rather than interpreted.
19852
19891
  */
19853
- var NcAlarmNonBlockingListSchema = array(object({
19854
- mode: AlarmArmModeSchema,
19855
- deviceIds: array(number().int()).max(200)
19856
- })).max(8).refine(uniqueModes, { message: "nonBlocking: at most one list per arm mode" });
19892
+ var NcAlarmNonBlockingListSchema = array(NcAlarmNonBlockingSchema).max(8).refine(uniqueModes, { message: "nonBlocking: at most one list per arm mode" });
19893
+ var NcAlarmBlockingListSchema = array(NcAlarmBlockingSchema).max(8).refine(uniqueModes, { message: "blocking: at most one list per arm mode" });
19894
+ var NcAlarmSecureOnArmOffListSchema = array(NcAlarmSecureOnArmOffSchema).max(8).refine(uniqueModes, { message: "secureOnArmOff: at most one list per arm mode" });
19857
19895
  /**
19858
19896
  * The three durations — global, and per mode since D697 — the panel's state
19859
19897
  * machine runs on, who hears about its transitions, and which openings each mode tolerates.
@@ -19896,9 +19934,23 @@ var NcAlarmSettingsSchema = object({
19896
19934
  * arm (a window left ajar for the cat under `home`, say). At most one entry
19897
19935
  * per mode is meaningful. Defaulted to `[]` so a blob stored before D630
19898
19936
  * parses as "every opening blocks" — the behaviour it was written under.
19937
+ * Contacts use this list; controllable openings use {@link blocking} instead
19938
+ * (default: do not block).
19899
19939
  */
19900
19940
  nonBlocking: NcAlarmNonBlockingListSchema.default([]),
19901
19941
  /**
19942
+ * Per arm mode, controllable openings that DO refuse the arm when open.
19943
+ * Default `[]` = none block (secure-on-arm closes them instead). Absent on a
19944
+ * blob older than this field — read as empty.
19945
+ */
19946
+ blocking: NcAlarmBlockingListSchema.default([]),
19947
+ /**
19948
+ * Per arm mode, controllable openings that must NOT be actuated on arm.
19949
+ * Default `[]` = every controllable secures (close / lock / off). Absent on
19950
+ * an older blob — read as empty (secure ON).
19951
+ */
19952
+ secureOnArmOff: NcAlarmSecureOnArmOffListSchema.default([]),
19953
+ /**
19902
19954
  * Per arm mode, the delays that mode OVERRIDES (D697). A mode with no entry, or an entry
19903
19955
  * without a field, uses the global value above — so `[]`, the default, is exactly the
19904
19956
  * behaviour of a blob stored before this field existed. Read through `resolveModeDelays`.
@@ -19908,7 +19960,7 @@ var NcAlarmSettingsSchema = object({
19908
19960
  /**
19909
19961
  * Every field optional — a tab edits one control at a time.
19910
19962
  *
19911
- * `nonBlocking` and `modeDelays` are re-declared WITHOUT their defaults:
19963
+ * List fields and `modeDelays` are re-declared WITHOUT their defaults:
19912
19964
  * `.partial()` does not remove an inner `.default()`, so a patch that never
19913
19965
  * named the field would parse to `[]` and wipe every mode's list on an
19914
19966
  * unrelated edit (the same trap {@link NcRulePatchSchema} documents). Here
@@ -19916,11 +19968,15 @@ var NcAlarmSettingsSchema = object({
19916
19968
  */
19917
19969
  var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
19918
19970
  nonBlocking: NcAlarmNonBlockingListSchema,
19971
+ blocking: NcAlarmBlockingListSchema,
19972
+ secureOnArmOff: NcAlarmSecureOnArmOffListSchema,
19919
19973
  /** Per-mode, per-field edits — NOT the whole list (see NcAlarmModeDelaysEditSchema). */
19920
19974
  modeDelays: NcAlarmModeDelaysEditListSchema,
19921
19975
  /** ONE membership change; the panel applies it to the list it holds at its turn. */
19922
- nonBlockingEdit: NcAlarmNonBlockingEditSchema
19923
- }).partial().refine((p) => p.nonBlocking === void 0 || p.nonBlockingEdit === void 0, { message: "nonBlocking and nonBlockingEdit are exclusive — send the whole lists or one edit" });
19976
+ nonBlockingEdit: NcAlarmNonBlockingEditSchema,
19977
+ blockingEdit: NcAlarmBlockingEditSchema,
19978
+ secureOnArmEdit: NcAlarmSecureOnArmEditSchema
19979
+ }).partial().refine((p) => p.nonBlocking === void 0 || p.nonBlockingEdit === void 0, { message: "nonBlocking and nonBlockingEdit are exclusive — send the whole lists or one edit" }).refine((p) => p.blocking === void 0 || p.blockingEdit === void 0, { message: "blocking and blockingEdit are exclusive — send the whole lists or one edit" }).refine((p) => p.secureOnArmOff === void 0 || p.secureOnArmEdit === void 0, { message: "secureOnArmOff and secureOnArmEdit are exclusive — send the whole lists or one edit" });
19924
19980
  /**
19925
19981
  * What one arm mode actually arms, DERIVED from the enabled rules gated on it.
19926
19982
  * Never authored, never stored — see `alarm-mode-coverage.ts` for why a stored
@@ -20035,7 +20091,13 @@ var NcAlarmSensorStateSchema = object({
20035
20091
  /** Why `unknown`: the read failed, or the slice holds no word its cap defines (a placeholder included). */
20036
20092
  unknownWhy: _enum(["read-failed", "unknown-word"]).nullable(),
20037
20093
  /** The device manager's liveness as the centre mirrors it; null = not known. */
20038
- online: boolean().nullable()
20094
+ online: boolean().nullable(),
20095
+ /**
20096
+ * True when the opening is a cover / lock / switch — the table shows the
20097
+ * Secure-on-arm switch and uses the controllable defaults. False for contacts
20098
+ * and for non-openings. Defaulted so an older hub answer still parses.
20099
+ */
20100
+ controllable: boolean().default(false)
20039
20101
  });
20040
20102
  var NcAlarmSensorsInputSchema = object({ deviceIds: array(number().int().positive()).max(500) });
20041
20103
  var NcAlarmSensorsSchema = object({
@@ -28090,6 +28152,65 @@ DeviceType.Button, method(object({ deviceId: number().int().nonnegative() }), _v
28090
28152
  auth: "protected"
28091
28153
  });
28092
28154
  /**
28155
+ * `calendar-source` — collection cap exposing per-provider calendars and
28156
+ * their events. Every addon that contributes calendars (Home Assistant,
28157
+ * a future Google Calendar addon, …) registers a provider here. The hub
28158
+ * singleton `calendars` walks the collection and merges the answers.
28159
+ *
28160
+ * Mirrors `addon-pages-source`: the public listing is a different shape
28161
+ * (source-stamped ids) and lives on the aggregator.
28162
+ */
28163
+ var CalendarSourceKindSchema = _enum(["ha", "addon"]);
28164
+ var CalendarInfoSchema = object({
28165
+ /** Provider-local id (e.g. HA `calendar.family`). The aggregator prefixes. */
28166
+ id: string().min(1),
28167
+ name: string().min(1),
28168
+ source: CalendarSourceKindSchema,
28169
+ enabled: boolean()
28170
+ });
28171
+ var CalendarEventSchema = object({
28172
+ id: string().min(1),
28173
+ calendarId: string().min(1),
28174
+ title: string(),
28175
+ startMs: number().int(),
28176
+ endMs: number().int(),
28177
+ allDay: boolean().optional(),
28178
+ description: string().optional(),
28179
+ location: string().optional()
28180
+ });
28181
+ var CalendarListEventsInputSchema = object({
28182
+ calendarIds: array(string().min(1)).max(64).optional(),
28183
+ startMs: number().int(),
28184
+ endMs: number().int()
28185
+ });
28186
+ method(_void(), array(CalendarInfoSchema).readonly(), { auth: "admin" }), method(CalendarListEventsInputSchema, array(CalendarEventSchema).readonly(), { auth: "admin" });
28187
+ /**
28188
+ * `calendars` — system-scoped singleton. Public surface admin-ui and the
28189
+ * notification-center calendar-events producer consume.
28190
+ *
28191
+ * Walks every `calendar-source` provider, stamps each calendar with a
28192
+ * cluster-stable id (`<sourceAddonId>:<localId>`) and the providing
28193
+ * addon's id, and fans `listEvents` out the same way. Home Assistant
28194
+ * import is a built-in refresh of the HA source rather than a second
28195
+ * registry — `importFromHomeAssistant` asks that source to re-discover.
28196
+ */
28197
+ var CalendarEntrySchema = CalendarInfoSchema.extend({
28198
+ /** Cluster-stable id: `<providerAddonId>:<localId>`. */
28199
+ id: string().min(1),
28200
+ /** The addon that registered the calendar-source provider. */
28201
+ providerAddonId: string().min(1).optional()
28202
+ });
28203
+ var CalendarImportResultSchema = object({
28204
+ imported: number().int().nonnegative(),
28205
+ /** Absent when no HA calendar-source provider was reachable. */
28206
+ providerAddonId: string().min(1).optional(),
28207
+ error: string().optional()
28208
+ });
28209
+ method(_void(), array(CalendarEntrySchema).readonly(), { auth: "admin" }), method(CalendarListEventsInputSchema, array(CalendarEventSchema).readonly(), { auth: "admin" }), method(_void(), CalendarImportResultSchema, {
28210
+ auth: "admin",
28211
+ kind: "mutation"
28212
+ });
28213
+ /**
28093
28214
  * camera-credentials — device-scoped cap exposing the camera's network
28094
28215
  * + auth surface in a vendor-neutral shape.
28095
28216
  *
@@ -31340,22 +31461,35 @@ DeviceType.Camera, method(object({
31340
31461
  deviceId: number(),
31341
31462
  status: OsdStatusSchema
31342
31463
  });
31464
+ _enum([
31465
+ "value",
31466
+ "unit",
31467
+ "full"
31468
+ ]);
31469
+ _enum([
31470
+ "value+unit",
31471
+ "value",
31472
+ "unit"
31473
+ ]);
31343
31474
  /**
31344
- * `osd-manager` — the ORCHESTRATOR over the device-scope `osd` cap.
31345
- *
31346
- * The `osd` cap is the firmware contract: it probes a camera's overlay
31347
- * SLOTS and writes literal text into one. It has no idea WHERE that text
31348
- * comes from, and it must not — a driver that grew a "show the temperature
31349
- * here" feature would grow it once per vendor.
31350
- *
31351
- * This cap owns the other half: a per-(camera, slot) BINDING that says
31352
- * which value feeds the slot, how it is formatted, and under which
31353
- * conditions it is shown at all. Named TEMPLATES combine many device
31354
- * fields into one overlay string (Scrypted OSD Manager parity).
31475
+ * How the operator reached the leaf device. `deviceId` is ALWAYS the
31476
+ * OSD-supported leaf that is read; `containerId` is set when the pick
31477
+ * went through a container (gateway) first.
31355
31478
  */
31356
- /** One field reference inside a named multi-device template. */
31357
- var OsdTemplateFieldSchema = object({
31358
- deviceId: number().int(),
31479
+ var OsdTemplatePickSchema = object({
31480
+ containerId: number().int().optional(),
31481
+ deviceId: number().int()
31482
+ });
31483
+ /**
31484
+ * One named binding inside a multi-device template: device path + unit
31485
+ * selection + precision. The parser expands `{alias}`, `{alias.value}`,
31486
+ * `{alias.unit}`, or `{alias.full}` from the same binding — there is no
31487
+ * per-binding format lock.
31488
+ */
31489
+ var OsdTemplateBindingSchema = object({
31490
+ /** Token stem in the parser, e.g. `t` → `{t}` / `{t.value}`. Unique within the template. */
31491
+ alias: string().min(1).max(32).regex(/^[A-Za-z][A-Za-z0-9_-]*$/, "alias must start with a letter"),
31492
+ pick: OsdTemplatePickSchema,
31359
31493
  capName: string().min(1).max(64),
31360
31494
  valuePath: string().min(1).max(64),
31361
31495
  /** Convert TO this unit at render (`tryConvertUnit`). Absent = source unit. */
@@ -31363,14 +31497,14 @@ var OsdTemplateFieldSchema = object({
31363
31497
  maxDecimals: number().int().min(0).max(4).default(1)
31364
31498
  });
31365
31499
  /**
31366
- * A named template: several device fields → one parser string with
31367
- * `{deviceId.capName.valuePath}` tokens (Scrypted `{deviceId.sensorId}`).
31500
+ * A named template: bindings (alias → leaf field) + a parser that
31501
+ * references `{alias}` / `{alias.value}` / `{alias.unit}` / `{alias.full}`.
31368
31502
  */
31369
31503
  var OsdNamedTemplateSchema = object({
31370
31504
  id: string().min(1).max(64),
31371
31505
  name: string().min(1).max(64),
31372
- fields: array(OsdTemplateFieldSchema).max(32).default([]),
31373
- /** Parser with multi-token placeholders, e.g. `T {12.thermometer.value}°`. */
31506
+ bindings: array(OsdTemplateBindingSchema).max(32).default([]),
31507
+ /** Parser with alias placeholders, e.g. `{t.value} {t.unit} / {h}`. */
31374
31508
  parser: string().max(256).default("")
31375
31509
  });
31376
31510
  /** Where a slot's value comes from. */
@@ -37773,6 +37907,36 @@ Object.freeze({
37773
37907
  addonId: null,
37774
37908
  access: "create"
37775
37909
  },
37910
+ "calendars.importFromHomeAssistant": {
37911
+ capName: "calendars",
37912
+ capScope: "system",
37913
+ addonId: null,
37914
+ access: "create"
37915
+ },
37916
+ "calendars.listCalendars": {
37917
+ capName: "calendars",
37918
+ capScope: "system",
37919
+ addonId: null,
37920
+ access: "view"
37921
+ },
37922
+ "calendars.listEvents": {
37923
+ capName: "calendars",
37924
+ capScope: "system",
37925
+ addonId: null,
37926
+ access: "view"
37927
+ },
37928
+ "calendarSource.listCalendars": {
37929
+ capName: "calendar-source",
37930
+ capScope: "system",
37931
+ addonId: null,
37932
+ access: "view"
37933
+ },
37934
+ "calendarSource.listEvents": {
37935
+ capName: "calendar-source",
37936
+ capScope: "system",
37937
+ addonId: null,
37938
+ access: "view"
37939
+ },
37776
37940
  "cameraCredentials.getCredentials": {
37777
37941
  capName: "camera-credentials",
37778
37942
  capScope: "device",
@@ -47756,7 +47920,7 @@ var AgentUIAddon = class extends BaseAddon {
47756
47920
  capability: adminUiCapability,
47757
47921
  provider: {
47758
47922
  getStaticDir: async () => ({ staticDir: path.resolve(__dirname) }),
47759
- getVersion: async () => ({ version: "1.2.165" })
47923
+ getVersion: async () => ({ version: "1.2.167" })
47760
47924
  }
47761
47925
  }];
47762
47926
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-agent-ui",
3
- "version": "1.2.165",
3
+ "version": "1.2.167",
4
4
  "description": "Agent UI — lightweight status dashboard served by every agent node",
5
5
  "keywords": [
6
6
  "camstack",