@camstack/addon-import-alexa 0.2.141 → 0.2.143

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 (3) hide show
  1. package/dist/addon.js +237 -61
  2. package/dist/addon.mjs +237 -61
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -38,7 +38,7 @@ let node_os = require("node:os");
38
38
  let node_fs = require("node:fs");
39
39
  let node_path = require("node:path");
40
40
  node_path = __toESM(node_path);
41
- //#region ../types/dist/event-category-DOl51-Ij.mjs
41
+ //#region ../types/dist/event-category-BfJwUd2S.mjs
42
42
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
43
43
  EventCategory["SystemBoot"] = "system.boot";
44
44
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -355,6 +355,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
355
355
  */
356
356
  EventCategory["PipelineDetectionBlind"] = "pipeline.detection-blind";
357
357
  /**
358
+ * A camera's motion source has fired constantly with no subject for an hour
359
+ * (motion duty or session count over the bar, zero detections) — it is not
360
+ * blind, its motion zones or sensitivity want tuning (D907). Paired with
361
+ * {@link PipelineMotionCalm}.
362
+ */
363
+ EventCategory["PipelineMotionNoisy"] = "pipeline.motion-noisy";
364
+ /** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
365
+ EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
366
+ /**
358
367
  * Per-camera pipeline config was mutated by the orchestrator
359
368
  * (3-level settings change via `setAgentAddonDefaults` /
360
369
  * `setCameraStepToggle` / `setCameraPipelineForAgent` or a
@@ -726,6 +735,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
726
735
  EventCategory["BackupRestored"] = "backup.restored";
727
736
  EventCategory["NotificationDispatched"] = "notification.dispatched";
728
737
  EventCategory["NotificationFailed"] = "notification.failed";
738
+ /**
739
+ * A notification rule that cannot work (D905): its stored row does not load,
740
+ * or it still names a device / delivery target the prune CONFIRMED deleted.
741
+ * One edge per rule per distinct set of reasons; never on an unanswered read.
742
+ */
743
+ EventCategory["NotificationRuleBroken"] = "notification.rule-broken";
744
+ /** The clear of {@link NotificationRuleBroken}: the rule loads and names nothing deleted. */
745
+ EventCategory["NotificationRuleRepaired"] = "notification.rule-repaired";
729
746
  EventCategory["DeviceUpdated"] = "device.updated";
730
747
  /**
731
748
  * Transport-level connectivity. Emitted by the device driver when
@@ -5586,7 +5603,7 @@ var ZodIssueCode = {
5586
5603
  var ZodFirstPartyTypeKind;
5587
5604
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5588
5605
  //#endregion
5589
- //#region ../types/dist/sleep-_sV1BE2f.mjs
5606
+ //#region ../types/dist/sleep-DJFUfKvA.mjs
5590
5607
  /**
5591
5608
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5592
5609
  * window to float samples (D455).
@@ -8185,7 +8202,7 @@ var EntryDescriptorSchema = object({
8185
8202
  /** JSON Schema of the entry body; `secret: true` marks a password field. */
8186
8203
  fields: record(string(), unknown())
8187
8204
  }).strict();
8188
- /** What crosses the wire and sits in the engine's catalog: JSON only, no Zod. */
8205
+ /** What crosses the wire from an addon: JSON only, no Zod. An unknown key is refused. */
8189
8206
  var RecordKindDeclarationSchema = object({
8190
8207
  database: _enum(RECORD_DATABASES).default("settings"),
8191
8208
  class: _enum(RECORD_CLASSES),
@@ -8204,14 +8221,6 @@ var RecordKindDeclarationSchema = object({
8204
8221
  secretPaths: array(string().min(1)).default([]),
8205
8222
  /** The id key of each array that carries a secret (`{ headers: 'name' }`). */
8206
8223
  secretArrayKeys: record(string(), string()).default({}),
8207
- /**
8208
- * RETIRED (D900): the legacy table a kind adopted from during the records
8209
- * migration. Nothing declares it any more and nothing reads it; the schema
8210
- * still ACCEPTS it because the catalog rows the migration wrote carry it
8211
- * (an orphaned kind is never redeclared) and an addon built before the
8212
- * removal still sends it. Never set it.
8213
- */
8214
- adoptsFrom: string().min(1).optional(),
8215
8224
  /** Kinds that must agree through `transact` sit in one file under one family name. */
8216
8225
  transactFamily: string().min(1).optional(),
8217
8226
  entry: EntryDescriptorSchema.optional()
@@ -13124,17 +13133,6 @@ object({
13124
13133
  createdAt: number(),
13125
13134
  updatedAt: number()
13126
13135
  });
13127
- object({
13128
- id: string(),
13129
- label: string(),
13130
- isAdmin: boolean().default(false),
13131
- allowedProviders: AllowedProviderSchema,
13132
- allowedDevices: AllowedDevicesSchema,
13133
- tokenHash: string(),
13134
- tokenPrefix: string(),
13135
- createdAt: number(),
13136
- lastUsedAt: number().optional()
13137
- });
13138
13136
  object({
13139
13137
  id: string(),
13140
13138
  userId: string(),
@@ -17184,16 +17182,36 @@ var RecordKindStateSchema = _enum([
17184
17182
  var DeclareKindResultSchema = object({
17185
17183
  kindId: number().int(),
17186
17184
  state: RecordKindStateSchema,
17187
- createdIndexes: array(string()),
17188
- /**
17189
- * RETIRED (D900): always `null`. It carried the records-migration boot guard;
17190
- * it stays on the wire, null, because an addon built before the removal reads
17191
- * an ABSENT field as "adoption pending" and refuses to start.
17192
- */
17193
- adoptionPending: _null()
17185
+ createdIndexes: array(string())
17194
17186
  });
17195
17187
  /** Keychain refs a write released (the old marker is gone from the row): the owner deletes the values. */
17196
17188
  var SecretRefsList = array(string());
17189
+ /**
17190
+ * One op of a `transact`: the single-row writes, each on a kind of the caller.
17191
+ * All ops of one call share ONE database file and ONE `transactFamily`.
17192
+ */
17193
+ var RecordTransactOpSchema = discriminatedUnion("op", [
17194
+ object({
17195
+ op: literal("put"),
17196
+ kind: RecordKindNameSchema,
17197
+ record: RecordInputSchema,
17198
+ ifRev: number().int().min(0).optional()
17199
+ }),
17200
+ object({
17201
+ op: literal("patch"),
17202
+ kind: RecordKindNameSchema,
17203
+ id: RecordIdSchema,
17204
+ data: RecordBodySchema,
17205
+ at: number().int().nullable().optional(),
17206
+ expiresAt: number().int().nullable().optional(),
17207
+ ifRev: number().int().min(1).optional()
17208
+ }),
17209
+ object({
17210
+ op: literal("delete"),
17211
+ kind: RecordKindNameSchema,
17212
+ id: RecordIdSchema
17213
+ })
17214
+ ]);
17197
17215
  var RecordSecretRefsSchema = record(string(), record(string(), string()));
17198
17216
  method(object({ kinds: record(RecordKindNameSchema, RecordKindDeclarationSchema) }), object({ kinds: record(string(), DeclareKindResultSchema) }), {
17199
17217
  kind: "mutation",
@@ -17300,6 +17318,16 @@ method(object({ kinds: record(RecordKindNameSchema, RecordKindDeclarationSchema)
17300
17318
  }), {
17301
17319
  kind: "mutation",
17302
17320
  auth: "admin"
17321
+ }), method(object({ ops: array(RecordTransactOpSchema).min(1).max(RECORD_BATCH_MAX) }), object({
17322
+ results: array(object({
17323
+ rev: number().int().nullable(),
17324
+ deleted: boolean()
17325
+ })),
17326
+ releasedRefs: SecretRefsList,
17327
+ secretRefs: SecretRefsList
17328
+ }), {
17329
+ kind: "mutation",
17330
+ auth: "admin"
17303
17331
  }), method(object({
17304
17332
  deviceId: number().int(),
17305
17333
  kinds: array(RecordKindNameSchema).optional()
@@ -42911,9 +42939,13 @@ var NcSystemEventKindSchema = _enum([
42911
42939
  "node-updating",
42912
42940
  "node-inference-unavailable",
42913
42941
  "detection-blind",
42942
+ "motion-noisy",
42943
+ "motion-calm",
42914
42944
  "recording-stalled",
42915
42945
  "recording-healthy",
42916
42946
  "recording-degraded",
42947
+ "device-attention-required",
42948
+ "device-attention-resolved",
42917
42949
  "storage-location-low",
42918
42950
  "storage-location-critical",
42919
42951
  "storage-location-ok",
@@ -42937,6 +42969,8 @@ var NcSystemEventKindSchema = _enum([
42937
42969
  "alert-critical",
42938
42970
  "alert-error",
42939
42971
  "alert-critical-resolved",
42972
+ "rule-broken",
42973
+ "rule-repaired",
42940
42974
  "camera-online",
42941
42975
  "camera-offline",
42942
42976
  "camera-disabled",
@@ -56252,6 +56286,16 @@ var DishwasherStatusSchema = object({
56252
56286
  powerState: string().nullable(),
56253
56287
  saltLevel: DishwasherConsumableLevelSchema.nullable(),
56254
56288
  rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
56289
+ /**
56290
+ * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
56291
+ * combined care-and-filter reminder raised); false when every such reminder reads clear; null
56292
+ * when none is reported. A cleared reminder is not an unknown one.
56293
+ */
56294
+ filterCleaningDue: boolean().nullable(),
56295
+ /** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
56296
+ machineCareDue: boolean().nullable(),
56297
+ /** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
56298
+ machineCareRemainingRuns: number().int().nonnegative().nullable(),
56255
56299
  /** Option states: null when the appliance does not expose the option or has not said. */
56256
56300
  halfLoad: boolean().nullable(),
56257
56301
  hygienePlus: boolean().nullable(),
@@ -64902,16 +64946,6 @@ var UpdateUserInputSchema = object({
64902
64946
  allowedDevices: record(string(), union([array(string()), literal("*")])).optional(),
64903
64947
  scopes: array(TokenScopeSchema).optional()
64904
64948
  });
64905
- var ApiKeySummarySchema = object({
64906
- id: string(),
64907
- label: string(),
64908
- isAdmin: boolean().default(false),
64909
- allowedProviders: union([array(string()), literal("*")]).optional(),
64910
- allowedDevices: record(string(), union([array(string()), literal("*")])).optional(),
64911
- tokenPrefix: string(),
64912
- createdAt: number(),
64913
- lastUsedAt: number().optional()
64914
- });
64915
64949
  var OauthSessionSummarySchema = object({
64916
64950
  id: string(),
64917
64951
  userId: string(),
@@ -64933,8 +64967,7 @@ var TotpStatusSchema = object({
64933
64967
  confirmedAt: number().nullable()
64934
64968
  });
64935
64969
  /**
64936
- * user-management — singleton capability for user accounts and the
64937
- * legacy API-key rows.
64970
+ * user-management — singleton capability for user accounts.
64938
64971
  *
64939
64972
  * v2 model: every method gated by `auth: 'admin'`. Admin-only delegation
64940
64973
  * — the subset check on `setUserScopes` is moot
@@ -64990,10 +65023,6 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
64990
65023
  }), UserSummarySchema.extend({ passwordHash: string() }).nullable(), {
64991
65024
  kind: "mutation",
64992
65025
  access: "view"
64993
- }), method(_void(), array(ApiKeySummarySchema), { auth: "admin" }), method(object({ id: string() }), object({ success: literal(true) }), {
64994
- kind: "mutation",
64995
- auth: "admin",
64996
- access: "delete"
64997
65026
  }), method(object({ userId: string() }), TotpSetupResultSchema, {
64998
65027
  kind: "mutation",
64999
65028
  auth: "admin",
@@ -74449,6 +74478,12 @@ Object.freeze({
74449
74478
  addonId: null,
74450
74479
  access: "view"
74451
74480
  },
74481
+ "records.transact": {
74482
+ capName: "records",
74483
+ capScope: "system",
74484
+ addonId: null,
74485
+ access: "create"
74486
+ },
74452
74487
  "sceneMonitor.captureReference": {
74453
74488
  capName: "scene-monitor",
74454
74489
  capScope: "device",
@@ -75781,12 +75816,6 @@ Object.freeze({
75781
75816
  addonId: null,
75782
75817
  access: "view"
75783
75818
  },
75784
- "userManagement.listApiKeys": {
75785
- capName: "user-management",
75786
- capScope: "system",
75787
- addonId: null,
75788
- access: "view"
75789
- },
75790
75819
  "userManagement.listExternalIdentities": {
75791
75820
  capName: "user-management",
75792
75821
  capScope: "system",
@@ -75841,12 +75870,6 @@ Object.freeze({
75841
75870
  addonId: null,
75842
75871
  access: "create"
75843
75872
  },
75844
- "userManagement.revokeApiKey": {
75845
- capName: "user-management",
75846
- capScope: "system",
75847
- addonId: null,
75848
- access: "delete"
75849
- },
75850
75873
  "userManagement.revokeOauthSession": {
75851
75874
  capName: "user-management",
75852
75875
  capScope: "system",
@@ -79211,9 +79234,13 @@ new Map(Object.entries({
79211
79234
  "stream-online": "device-events",
79212
79235
  "stream-offline": "device-events",
79213
79236
  "detection-blind": "device-events",
79237
+ "motion-noisy": "device-events",
79238
+ "motion-calm": "device-events",
79214
79239
  "recording-stalled": "device-events",
79215
79240
  "recording-healthy": "device-events",
79216
79241
  "recording-degraded": "device-events",
79242
+ "device-attention-required": "device-events",
79243
+ "device-attention-resolved": "device-events",
79217
79244
  "node-online": "system",
79218
79245
  "node-offline": "system",
79219
79246
  "node-restarting": "system",
@@ -79230,6 +79257,8 @@ new Map(Object.entries({
79230
79257
  "alert-critical": "system",
79231
79258
  "alert-error": "system",
79232
79259
  "alert-critical-resolved": "system",
79260
+ "rule-broken": "system",
79261
+ "rule-repaired": "system",
79233
79262
  "storage-location-low": "system",
79234
79263
  "storage-location-critical": "system",
79235
79264
  "storage-location-ok": "system",
@@ -79294,6 +79323,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
79294
79323
  label: "Detecting nothing",
79295
79324
  kinds: ["detection-blind"]
79296
79325
  },
79326
+ {
79327
+ id: "motion-noise",
79328
+ family: "device-events",
79329
+ label: "Motion without a subject",
79330
+ kinds: ["motion-noisy", "motion-calm"]
79331
+ },
79297
79332
  {
79298
79333
  id: "recording",
79299
79334
  family: "device-events",
@@ -79304,6 +79339,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
79304
79339
  "recording-degraded"
79305
79340
  ]
79306
79341
  },
79342
+ {
79343
+ id: "device-attention",
79344
+ family: "device-events",
79345
+ label: "Needs attention",
79346
+ kinds: ["device-attention-required", "device-attention-resolved"]
79347
+ },
79307
79348
  {
79308
79349
  id: "nodes",
79309
79350
  family: "system",
@@ -79364,6 +79405,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
79364
79405
  "alert-critical-resolved"
79365
79406
  ]
79366
79407
  },
79408
+ {
79409
+ id: "rule-health",
79410
+ family: "system",
79411
+ label: "Notification rules",
79412
+ kinds: ["rule-broken", "rule-repaired"]
79413
+ },
79367
79414
  {
79368
79415
  id: "alarm",
79369
79416
  family: "alarm",
@@ -79437,6 +79484,7 @@ var ALERT_EPISODE = [
79437
79484
  "alert-error",
79438
79485
  "alert-critical-resolved"
79439
79486
  ];
79487
+ var DEVICE_ATTENTION = ["device-attention-required", "device-attention-resolved"];
79440
79488
  var UPDATES = [
79441
79489
  "addon-update-available",
79442
79490
  "server-update-available",
@@ -79466,9 +79514,12 @@ var DEVICE_EVENTS = [
79466
79514
  "stream-online",
79467
79515
  "stream-offline",
79468
79516
  "detection-blind",
79517
+ "motion-noisy",
79518
+ "motion-calm",
79469
79519
  "recording-stalled",
79470
79520
  "recording-healthy",
79471
79521
  "recording-degraded",
79522
+ ...DEVICE_ATTENTION,
79472
79523
  ...ALARM
79473
79524
  ];
79474
79525
  /** Every kind a summary may speak about — the two summarisable families. */
@@ -79636,7 +79687,13 @@ var STATE_SUMMARY_VARS = [
79636
79687
  [...RULE_TEXT],
79637
79688
  [...RULE_TEXT],
79638
79689
  [...RULE_TEXT],
79639
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79690
+ [...RULE_TEXT],
79691
+ [...RULE_TEXT],
79692
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79693
+ [...RULE_TEXT],
79694
+ [...RULE_TEXT],
79695
+ [...RULE_TEXT],
79696
+ [...RULE_TEXT],
79640
79697
  [...RULE_TEXT],
79641
79698
  [...RULE_TEXT],
79642
79699
  [...RULE_TEXT],
@@ -79654,11 +79711,11 @@ var STATE_SUMMARY_VARS = [
79654
79711
  [...RULE_TEXT],
79655
79712
  [...RULE_TEXT],
79656
79713
  [...RULE_TEXT],
79714
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79657
79715
  ([...RULE_TEXT], [...ALERT_EPISODE]),
79716
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79658
79717
  ([...RULE_TEXT], [...ALERT_EPISODE]),
79659
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79660
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79661
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79718
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79662
79719
  [...RULE_TEXT],
79663
79720
  [...RULE_TEXT],
79664
79721
  [...RULE_TEXT],
@@ -79679,6 +79736,125 @@ var STATE_SUMMARY_VARS = [
79679
79736
  [...RULE_TEXT],
79680
79737
  ...STATE_SUMMARY_VARS
79681
79738
  ];
79739
+ new Map([
79740
+ {
79741
+ id: "device-connectivity",
79742
+ family: "device-events",
79743
+ label: "Device connectivity (offline / back online)",
79744
+ bad: ["device-offline"],
79745
+ recovery: ["device-online"],
79746
+ snapshotLabel: "Devices offline now",
79747
+ snapshotSection: "device-state"
79748
+ },
79749
+ {
79750
+ id: "device-switch",
79751
+ family: "device-events",
79752
+ label: "Device switched off / back on",
79753
+ bad: ["device-disabled"],
79754
+ recovery: ["device-enabled"],
79755
+ snapshotLabel: "Devices switched off now",
79756
+ snapshotSection: "device-state"
79757
+ },
79758
+ {
79759
+ id: "stream-connectivity",
79760
+ family: "device-events",
79761
+ label: "Stream connectivity (offline / back online)",
79762
+ bad: ["stream-offline"],
79763
+ recovery: ["stream-online"],
79764
+ snapshotLabel: "Streams offline now",
79765
+ snapshotSection: "streams"
79766
+ },
79767
+ {
79768
+ id: "battery",
79769
+ family: "device-events",
79770
+ label: "Battery (low / back to normal)",
79771
+ bad: ["device-battery-low"],
79772
+ recovery: ["device-battery-normal"],
79773
+ snapshotLabel: "Batteries low now",
79774
+ snapshotSection: "battery"
79775
+ },
79776
+ {
79777
+ id: "consumables",
79778
+ family: "device-events",
79779
+ label: "Consumables (low / replaced)",
79780
+ bad: ["device-consumable-low"],
79781
+ recovery: ["device-consumable-normal"],
79782
+ snapshotLabel: "Consumables low now",
79783
+ snapshotSection: "consumables"
79784
+ },
79785
+ {
79786
+ id: "tanks",
79787
+ family: "device-events",
79788
+ label: "Tanks (low or full / back to normal)",
79789
+ bad: ["device-tank-low", "device-tank-full"],
79790
+ recovery: ["device-tank-normal"],
79791
+ snapshotLabel: "Tanks low or full now",
79792
+ snapshotSection: "tanks"
79793
+ },
79794
+ {
79795
+ id: "motion-noise",
79796
+ family: "device-events",
79797
+ label: "Motion without a subject (constant / calm again)",
79798
+ bad: ["motion-noisy"],
79799
+ recovery: ["motion-calm"],
79800
+ snapshotLabel: "Cameras with constant motion now",
79801
+ snapshotSection: null
79802
+ },
79803
+ {
79804
+ id: "recording-health",
79805
+ family: "device-events",
79806
+ label: "Recording health (stalled or degraded / recording again)",
79807
+ bad: ["recording-stalled", "recording-degraded"],
79808
+ recovery: ["recording-healthy"],
79809
+ snapshotLabel: "Recordings stalled now",
79810
+ snapshotSection: null
79811
+ },
79812
+ {
79813
+ id: "device-attention",
79814
+ family: "device-events",
79815
+ label: "Device needs attention (raised / resolved)",
79816
+ bad: ["device-attention-required"],
79817
+ recovery: ["device-attention-resolved"],
79818
+ snapshotLabel: "Devices needing attention now",
79819
+ snapshotSection: null
79820
+ },
79821
+ {
79822
+ id: "node-connectivity",
79823
+ family: "system",
79824
+ label: "Node connectivity (offline / back online)",
79825
+ bad: ["node-offline"],
79826
+ recovery: ["node-online"],
79827
+ snapshotLabel: "Nodes offline now",
79828
+ snapshotSection: "nodes"
79829
+ },
79830
+ {
79831
+ id: "storage-space",
79832
+ family: "system",
79833
+ label: "Storage space (low or critical / ok again)",
79834
+ bad: ["storage-location-low", "storage-location-critical"],
79835
+ recovery: ["storage-location-ok"],
79836
+ snapshotLabel: "Storage locations low now",
79837
+ snapshotSection: null
79838
+ },
79839
+ {
79840
+ id: "critical-alerts",
79841
+ family: "system",
79842
+ label: "Critical alerts (raised / resolved)",
79843
+ bad: ["alert-critical"],
79844
+ recovery: ["alert-critical-resolved"],
79845
+ snapshotLabel: "Critical alerts open now",
79846
+ snapshotSection: null
79847
+ },
79848
+ {
79849
+ id: "rule-health",
79850
+ family: "system",
79851
+ label: "Rule health (broken / repaired)",
79852
+ bad: ["rule-broken"],
79853
+ recovery: ["rule-repaired"],
79854
+ snapshotLabel: "Notification rules broken now",
79855
+ snapshotSection: null
79856
+ }
79857
+ ].flatMap((spec) => [...spec.bad, ...spec.recovery].map((kind) => [kind, spec])));
79682
79858
  new Set([
79683
79859
  "disarmed",
79684
79860
  "armed_home",
package/dist/addon.mjs CHANGED
@@ -38,7 +38,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
38
38
  var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
39
39
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
40
40
  //#endregion
41
- //#region ../types/dist/event-category-DOl51-Ij.mjs
41
+ //#region ../types/dist/event-category-BfJwUd2S.mjs
42
42
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
43
43
  EventCategory["SystemBoot"] = "system.boot";
44
44
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -355,6 +355,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
355
355
  */
356
356
  EventCategory["PipelineDetectionBlind"] = "pipeline.detection-blind";
357
357
  /**
358
+ * A camera's motion source has fired constantly with no subject for an hour
359
+ * (motion duty or session count over the bar, zero detections) — it is not
360
+ * blind, its motion zones or sensitivity want tuning (D907). Paired with
361
+ * {@link PipelineMotionCalm}.
362
+ */
363
+ EventCategory["PipelineMotionNoisy"] = "pipeline.motion-noisy";
364
+ /** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
365
+ EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
366
+ /**
358
367
  * Per-camera pipeline config was mutated by the orchestrator
359
368
  * (3-level settings change via `setAgentAddonDefaults` /
360
369
  * `setCameraStepToggle` / `setCameraPipelineForAgent` or a
@@ -726,6 +735,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
726
735
  EventCategory["BackupRestored"] = "backup.restored";
727
736
  EventCategory["NotificationDispatched"] = "notification.dispatched";
728
737
  EventCategory["NotificationFailed"] = "notification.failed";
738
+ /**
739
+ * A notification rule that cannot work (D905): its stored row does not load,
740
+ * or it still names a device / delivery target the prune CONFIRMED deleted.
741
+ * One edge per rule per distinct set of reasons; never on an unanswered read.
742
+ */
743
+ EventCategory["NotificationRuleBroken"] = "notification.rule-broken";
744
+ /** The clear of {@link NotificationRuleBroken}: the rule loads and names nothing deleted. */
745
+ EventCategory["NotificationRuleRepaired"] = "notification.rule-repaired";
729
746
  EventCategory["DeviceUpdated"] = "device.updated";
730
747
  /**
731
748
  * Transport-level connectivity. Emitted by the device driver when
@@ -5586,7 +5603,7 @@ var ZodIssueCode = {
5586
5603
  var ZodFirstPartyTypeKind;
5587
5604
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5588
5605
  //#endregion
5589
- //#region ../types/dist/sleep-_sV1BE2f.mjs
5606
+ //#region ../types/dist/sleep-DJFUfKvA.mjs
5590
5607
  /**
5591
5608
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5592
5609
  * window to float samples (D455).
@@ -8185,7 +8202,7 @@ var EntryDescriptorSchema = object({
8185
8202
  /** JSON Schema of the entry body; `secret: true` marks a password field. */
8186
8203
  fields: record(string(), unknown())
8187
8204
  }).strict();
8188
- /** What crosses the wire and sits in the engine's catalog: JSON only, no Zod. */
8205
+ /** What crosses the wire from an addon: JSON only, no Zod. An unknown key is refused. */
8189
8206
  var RecordKindDeclarationSchema = object({
8190
8207
  database: _enum(RECORD_DATABASES).default("settings"),
8191
8208
  class: _enum(RECORD_CLASSES),
@@ -8204,14 +8221,6 @@ var RecordKindDeclarationSchema = object({
8204
8221
  secretPaths: array(string().min(1)).default([]),
8205
8222
  /** The id key of each array that carries a secret (`{ headers: 'name' }`). */
8206
8223
  secretArrayKeys: record(string(), string()).default({}),
8207
- /**
8208
- * RETIRED (D900): the legacy table a kind adopted from during the records
8209
- * migration. Nothing declares it any more and nothing reads it; the schema
8210
- * still ACCEPTS it because the catalog rows the migration wrote carry it
8211
- * (an orphaned kind is never redeclared) and an addon built before the
8212
- * removal still sends it. Never set it.
8213
- */
8214
- adoptsFrom: string().min(1).optional(),
8215
8224
  /** Kinds that must agree through `transact` sit in one file under one family name. */
8216
8225
  transactFamily: string().min(1).optional(),
8217
8226
  entry: EntryDescriptorSchema.optional()
@@ -13124,17 +13133,6 @@ object({
13124
13133
  createdAt: number(),
13125
13134
  updatedAt: number()
13126
13135
  });
13127
- object({
13128
- id: string(),
13129
- label: string(),
13130
- isAdmin: boolean().default(false),
13131
- allowedProviders: AllowedProviderSchema,
13132
- allowedDevices: AllowedDevicesSchema,
13133
- tokenHash: string(),
13134
- tokenPrefix: string(),
13135
- createdAt: number(),
13136
- lastUsedAt: number().optional()
13137
- });
13138
13136
  object({
13139
13137
  id: string(),
13140
13138
  userId: string(),
@@ -17184,16 +17182,36 @@ var RecordKindStateSchema = _enum([
17184
17182
  var DeclareKindResultSchema = object({
17185
17183
  kindId: number().int(),
17186
17184
  state: RecordKindStateSchema,
17187
- createdIndexes: array(string()),
17188
- /**
17189
- * RETIRED (D900): always `null`. It carried the records-migration boot guard;
17190
- * it stays on the wire, null, because an addon built before the removal reads
17191
- * an ABSENT field as "adoption pending" and refuses to start.
17192
- */
17193
- adoptionPending: _null()
17185
+ createdIndexes: array(string())
17194
17186
  });
17195
17187
  /** Keychain refs a write released (the old marker is gone from the row): the owner deletes the values. */
17196
17188
  var SecretRefsList = array(string());
17189
+ /**
17190
+ * One op of a `transact`: the single-row writes, each on a kind of the caller.
17191
+ * All ops of one call share ONE database file and ONE `transactFamily`.
17192
+ */
17193
+ var RecordTransactOpSchema = discriminatedUnion("op", [
17194
+ object({
17195
+ op: literal("put"),
17196
+ kind: RecordKindNameSchema,
17197
+ record: RecordInputSchema,
17198
+ ifRev: number().int().min(0).optional()
17199
+ }),
17200
+ object({
17201
+ op: literal("patch"),
17202
+ kind: RecordKindNameSchema,
17203
+ id: RecordIdSchema,
17204
+ data: RecordBodySchema,
17205
+ at: number().int().nullable().optional(),
17206
+ expiresAt: number().int().nullable().optional(),
17207
+ ifRev: number().int().min(1).optional()
17208
+ }),
17209
+ object({
17210
+ op: literal("delete"),
17211
+ kind: RecordKindNameSchema,
17212
+ id: RecordIdSchema
17213
+ })
17214
+ ]);
17197
17215
  var RecordSecretRefsSchema = record(string(), record(string(), string()));
17198
17216
  method(object({ kinds: record(RecordKindNameSchema, RecordKindDeclarationSchema) }), object({ kinds: record(string(), DeclareKindResultSchema) }), {
17199
17217
  kind: "mutation",
@@ -17300,6 +17318,16 @@ method(object({ kinds: record(RecordKindNameSchema, RecordKindDeclarationSchema)
17300
17318
  }), {
17301
17319
  kind: "mutation",
17302
17320
  auth: "admin"
17321
+ }), method(object({ ops: array(RecordTransactOpSchema).min(1).max(RECORD_BATCH_MAX) }), object({
17322
+ results: array(object({
17323
+ rev: number().int().nullable(),
17324
+ deleted: boolean()
17325
+ })),
17326
+ releasedRefs: SecretRefsList,
17327
+ secretRefs: SecretRefsList
17328
+ }), {
17329
+ kind: "mutation",
17330
+ auth: "admin"
17303
17331
  }), method(object({
17304
17332
  deviceId: number().int(),
17305
17333
  kinds: array(RecordKindNameSchema).optional()
@@ -42911,9 +42939,13 @@ var NcSystemEventKindSchema = _enum([
42911
42939
  "node-updating",
42912
42940
  "node-inference-unavailable",
42913
42941
  "detection-blind",
42942
+ "motion-noisy",
42943
+ "motion-calm",
42914
42944
  "recording-stalled",
42915
42945
  "recording-healthy",
42916
42946
  "recording-degraded",
42947
+ "device-attention-required",
42948
+ "device-attention-resolved",
42917
42949
  "storage-location-low",
42918
42950
  "storage-location-critical",
42919
42951
  "storage-location-ok",
@@ -42937,6 +42969,8 @@ var NcSystemEventKindSchema = _enum([
42937
42969
  "alert-critical",
42938
42970
  "alert-error",
42939
42971
  "alert-critical-resolved",
42972
+ "rule-broken",
42973
+ "rule-repaired",
42940
42974
  "camera-online",
42941
42975
  "camera-offline",
42942
42976
  "camera-disabled",
@@ -56252,6 +56286,16 @@ var DishwasherStatusSchema = object({
56252
56286
  powerState: string().nullable(),
56253
56287
  saltLevel: DishwasherConsumableLevelSchema.nullable(),
56254
56288
  rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
56289
+ /**
56290
+ * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
56291
+ * combined care-and-filter reminder raised); false when every such reminder reads clear; null
56292
+ * when none is reported. A cleared reminder is not an unknown one.
56293
+ */
56294
+ filterCleaningDue: boolean().nullable(),
56295
+ /** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
56296
+ machineCareDue: boolean().nullable(),
56297
+ /** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
56298
+ machineCareRemainingRuns: number().int().nonnegative().nullable(),
56255
56299
  /** Option states: null when the appliance does not expose the option or has not said. */
56256
56300
  halfLoad: boolean().nullable(),
56257
56301
  hygienePlus: boolean().nullable(),
@@ -64902,16 +64946,6 @@ var UpdateUserInputSchema = object({
64902
64946
  allowedDevices: record(string(), union([array(string()), literal("*")])).optional(),
64903
64947
  scopes: array(TokenScopeSchema).optional()
64904
64948
  });
64905
- var ApiKeySummarySchema = object({
64906
- id: string(),
64907
- label: string(),
64908
- isAdmin: boolean().default(false),
64909
- allowedProviders: union([array(string()), literal("*")]).optional(),
64910
- allowedDevices: record(string(), union([array(string()), literal("*")])).optional(),
64911
- tokenPrefix: string(),
64912
- createdAt: number(),
64913
- lastUsedAt: number().optional()
64914
- });
64915
64949
  var OauthSessionSummarySchema = object({
64916
64950
  id: string(),
64917
64951
  userId: string(),
@@ -64933,8 +64967,7 @@ var TotpStatusSchema = object({
64933
64967
  confirmedAt: number().nullable()
64934
64968
  });
64935
64969
  /**
64936
- * user-management — singleton capability for user accounts and the
64937
- * legacy API-key rows.
64970
+ * user-management — singleton capability for user accounts.
64938
64971
  *
64939
64972
  * v2 model: every method gated by `auth: 'admin'`. Admin-only delegation
64940
64973
  * — the subset check on `setUserScopes` is moot
@@ -64990,10 +65023,6 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
64990
65023
  }), UserSummarySchema.extend({ passwordHash: string() }).nullable(), {
64991
65024
  kind: "mutation",
64992
65025
  access: "view"
64993
- }), method(_void(), array(ApiKeySummarySchema), { auth: "admin" }), method(object({ id: string() }), object({ success: literal(true) }), {
64994
- kind: "mutation",
64995
- auth: "admin",
64996
- access: "delete"
64997
65026
  }), method(object({ userId: string() }), TotpSetupResultSchema, {
64998
65027
  kind: "mutation",
64999
65028
  auth: "admin",
@@ -74449,6 +74478,12 @@ Object.freeze({
74449
74478
  addonId: null,
74450
74479
  access: "view"
74451
74480
  },
74481
+ "records.transact": {
74482
+ capName: "records",
74483
+ capScope: "system",
74484
+ addonId: null,
74485
+ access: "create"
74486
+ },
74452
74487
  "sceneMonitor.captureReference": {
74453
74488
  capName: "scene-monitor",
74454
74489
  capScope: "device",
@@ -75781,12 +75816,6 @@ Object.freeze({
75781
75816
  addonId: null,
75782
75817
  access: "view"
75783
75818
  },
75784
- "userManagement.listApiKeys": {
75785
- capName: "user-management",
75786
- capScope: "system",
75787
- addonId: null,
75788
- access: "view"
75789
- },
75790
75819
  "userManagement.listExternalIdentities": {
75791
75820
  capName: "user-management",
75792
75821
  capScope: "system",
@@ -75841,12 +75870,6 @@ Object.freeze({
75841
75870
  addonId: null,
75842
75871
  access: "create"
75843
75872
  },
75844
- "userManagement.revokeApiKey": {
75845
- capName: "user-management",
75846
- capScope: "system",
75847
- addonId: null,
75848
- access: "delete"
75849
- },
75850
75873
  "userManagement.revokeOauthSession": {
75851
75874
  capName: "user-management",
75852
75875
  capScope: "system",
@@ -79211,9 +79234,13 @@ new Map(Object.entries({
79211
79234
  "stream-online": "device-events",
79212
79235
  "stream-offline": "device-events",
79213
79236
  "detection-blind": "device-events",
79237
+ "motion-noisy": "device-events",
79238
+ "motion-calm": "device-events",
79214
79239
  "recording-stalled": "device-events",
79215
79240
  "recording-healthy": "device-events",
79216
79241
  "recording-degraded": "device-events",
79242
+ "device-attention-required": "device-events",
79243
+ "device-attention-resolved": "device-events",
79217
79244
  "node-online": "system",
79218
79245
  "node-offline": "system",
79219
79246
  "node-restarting": "system",
@@ -79230,6 +79257,8 @@ new Map(Object.entries({
79230
79257
  "alert-critical": "system",
79231
79258
  "alert-error": "system",
79232
79259
  "alert-critical-resolved": "system",
79260
+ "rule-broken": "system",
79261
+ "rule-repaired": "system",
79233
79262
  "storage-location-low": "system",
79234
79263
  "storage-location-critical": "system",
79235
79264
  "storage-location-ok": "system",
@@ -79294,6 +79323,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
79294
79323
  label: "Detecting nothing",
79295
79324
  kinds: ["detection-blind"]
79296
79325
  },
79326
+ {
79327
+ id: "motion-noise",
79328
+ family: "device-events",
79329
+ label: "Motion without a subject",
79330
+ kinds: ["motion-noisy", "motion-calm"]
79331
+ },
79297
79332
  {
79298
79333
  id: "recording",
79299
79334
  family: "device-events",
@@ -79304,6 +79339,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
79304
79339
  "recording-degraded"
79305
79340
  ]
79306
79341
  },
79342
+ {
79343
+ id: "device-attention",
79344
+ family: "device-events",
79345
+ label: "Needs attention",
79346
+ kinds: ["device-attention-required", "device-attention-resolved"]
79347
+ },
79307
79348
  {
79308
79349
  id: "nodes",
79309
79350
  family: "system",
@@ -79364,6 +79405,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
79364
79405
  "alert-critical-resolved"
79365
79406
  ]
79366
79407
  },
79408
+ {
79409
+ id: "rule-health",
79410
+ family: "system",
79411
+ label: "Notification rules",
79412
+ kinds: ["rule-broken", "rule-repaired"]
79413
+ },
79367
79414
  {
79368
79415
  id: "alarm",
79369
79416
  family: "alarm",
@@ -79437,6 +79484,7 @@ var ALERT_EPISODE = [
79437
79484
  "alert-error",
79438
79485
  "alert-critical-resolved"
79439
79486
  ];
79487
+ var DEVICE_ATTENTION = ["device-attention-required", "device-attention-resolved"];
79440
79488
  var UPDATES = [
79441
79489
  "addon-update-available",
79442
79490
  "server-update-available",
@@ -79466,9 +79514,12 @@ var DEVICE_EVENTS = [
79466
79514
  "stream-online",
79467
79515
  "stream-offline",
79468
79516
  "detection-blind",
79517
+ "motion-noisy",
79518
+ "motion-calm",
79469
79519
  "recording-stalled",
79470
79520
  "recording-healthy",
79471
79521
  "recording-degraded",
79522
+ ...DEVICE_ATTENTION,
79472
79523
  ...ALARM
79473
79524
  ];
79474
79525
  /** Every kind a summary may speak about — the two summarisable families. */
@@ -79636,7 +79687,13 @@ var STATE_SUMMARY_VARS = [
79636
79687
  [...RULE_TEXT],
79637
79688
  [...RULE_TEXT],
79638
79689
  [...RULE_TEXT],
79639
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79690
+ [...RULE_TEXT],
79691
+ [...RULE_TEXT],
79692
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79693
+ [...RULE_TEXT],
79694
+ [...RULE_TEXT],
79695
+ [...RULE_TEXT],
79696
+ [...RULE_TEXT],
79640
79697
  [...RULE_TEXT],
79641
79698
  [...RULE_TEXT],
79642
79699
  [...RULE_TEXT],
@@ -79654,11 +79711,11 @@ var STATE_SUMMARY_VARS = [
79654
79711
  [...RULE_TEXT],
79655
79712
  [...RULE_TEXT],
79656
79713
  [...RULE_TEXT],
79714
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79657
79715
  ([...RULE_TEXT], [...ALERT_EPISODE]),
79716
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79658
79717
  ([...RULE_TEXT], [...ALERT_EPISODE]),
79659
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79660
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79661
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79718
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79662
79719
  [...RULE_TEXT],
79663
79720
  [...RULE_TEXT],
79664
79721
  [...RULE_TEXT],
@@ -79679,6 +79736,125 @@ var STATE_SUMMARY_VARS = [
79679
79736
  [...RULE_TEXT],
79680
79737
  ...STATE_SUMMARY_VARS
79681
79738
  ];
79739
+ new Map([
79740
+ {
79741
+ id: "device-connectivity",
79742
+ family: "device-events",
79743
+ label: "Device connectivity (offline / back online)",
79744
+ bad: ["device-offline"],
79745
+ recovery: ["device-online"],
79746
+ snapshotLabel: "Devices offline now",
79747
+ snapshotSection: "device-state"
79748
+ },
79749
+ {
79750
+ id: "device-switch",
79751
+ family: "device-events",
79752
+ label: "Device switched off / back on",
79753
+ bad: ["device-disabled"],
79754
+ recovery: ["device-enabled"],
79755
+ snapshotLabel: "Devices switched off now",
79756
+ snapshotSection: "device-state"
79757
+ },
79758
+ {
79759
+ id: "stream-connectivity",
79760
+ family: "device-events",
79761
+ label: "Stream connectivity (offline / back online)",
79762
+ bad: ["stream-offline"],
79763
+ recovery: ["stream-online"],
79764
+ snapshotLabel: "Streams offline now",
79765
+ snapshotSection: "streams"
79766
+ },
79767
+ {
79768
+ id: "battery",
79769
+ family: "device-events",
79770
+ label: "Battery (low / back to normal)",
79771
+ bad: ["device-battery-low"],
79772
+ recovery: ["device-battery-normal"],
79773
+ snapshotLabel: "Batteries low now",
79774
+ snapshotSection: "battery"
79775
+ },
79776
+ {
79777
+ id: "consumables",
79778
+ family: "device-events",
79779
+ label: "Consumables (low / replaced)",
79780
+ bad: ["device-consumable-low"],
79781
+ recovery: ["device-consumable-normal"],
79782
+ snapshotLabel: "Consumables low now",
79783
+ snapshotSection: "consumables"
79784
+ },
79785
+ {
79786
+ id: "tanks",
79787
+ family: "device-events",
79788
+ label: "Tanks (low or full / back to normal)",
79789
+ bad: ["device-tank-low", "device-tank-full"],
79790
+ recovery: ["device-tank-normal"],
79791
+ snapshotLabel: "Tanks low or full now",
79792
+ snapshotSection: "tanks"
79793
+ },
79794
+ {
79795
+ id: "motion-noise",
79796
+ family: "device-events",
79797
+ label: "Motion without a subject (constant / calm again)",
79798
+ bad: ["motion-noisy"],
79799
+ recovery: ["motion-calm"],
79800
+ snapshotLabel: "Cameras with constant motion now",
79801
+ snapshotSection: null
79802
+ },
79803
+ {
79804
+ id: "recording-health",
79805
+ family: "device-events",
79806
+ label: "Recording health (stalled or degraded / recording again)",
79807
+ bad: ["recording-stalled", "recording-degraded"],
79808
+ recovery: ["recording-healthy"],
79809
+ snapshotLabel: "Recordings stalled now",
79810
+ snapshotSection: null
79811
+ },
79812
+ {
79813
+ id: "device-attention",
79814
+ family: "device-events",
79815
+ label: "Device needs attention (raised / resolved)",
79816
+ bad: ["device-attention-required"],
79817
+ recovery: ["device-attention-resolved"],
79818
+ snapshotLabel: "Devices needing attention now",
79819
+ snapshotSection: null
79820
+ },
79821
+ {
79822
+ id: "node-connectivity",
79823
+ family: "system",
79824
+ label: "Node connectivity (offline / back online)",
79825
+ bad: ["node-offline"],
79826
+ recovery: ["node-online"],
79827
+ snapshotLabel: "Nodes offline now",
79828
+ snapshotSection: "nodes"
79829
+ },
79830
+ {
79831
+ id: "storage-space",
79832
+ family: "system",
79833
+ label: "Storage space (low or critical / ok again)",
79834
+ bad: ["storage-location-low", "storage-location-critical"],
79835
+ recovery: ["storage-location-ok"],
79836
+ snapshotLabel: "Storage locations low now",
79837
+ snapshotSection: null
79838
+ },
79839
+ {
79840
+ id: "critical-alerts",
79841
+ family: "system",
79842
+ label: "Critical alerts (raised / resolved)",
79843
+ bad: ["alert-critical"],
79844
+ recovery: ["alert-critical-resolved"],
79845
+ snapshotLabel: "Critical alerts open now",
79846
+ snapshotSection: null
79847
+ },
79848
+ {
79849
+ id: "rule-health",
79850
+ family: "system",
79851
+ label: "Rule health (broken / repaired)",
79852
+ bad: ["rule-broken"],
79853
+ recovery: ["rule-repaired"],
79854
+ snapshotLabel: "Notification rules broken now",
79855
+ snapshotSection: null
79856
+ }
79857
+ ].flatMap((spec) => [...spec.bad, ...spec.recovery].map((kind) => [kind, spec])));
79682
79858
  new Set([
79683
79859
  "disarmed",
79684
79860
  "armed_home",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-import-alexa",
3
- "version": "0.2.141",
3
+ "version": "0.2.143",
4
4
  "description": "Alexa device-import provider for CamStack — imports the smart-home devices in a user's Alexa account via the unofficial alexa-remote2 cookie/token client (the inverse of the Alexa exporter)",
5
5
  "keywords": [
6
6
  "camstack",