@camstack/addon-advanced-notifier 1.1.13 → 1.1.15

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.
package/dist/addon.js CHANGED
@@ -4632,7 +4632,7 @@ function _instanceof(cls, params = {}) {
4632
4632
  return inst;
4633
4633
  }
4634
4634
  //#endregion
4635
- //#region ../types/dist/sleep-C2M2zF7x.mjs
4635
+ //#region ../types/dist/sleep-MHm--th-.mjs
4636
4636
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4637
4637
  EventCategory["SystemBoot"] = "system.boot";
4638
4638
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -5894,6 +5894,7 @@ var CamStreamKindSchema = _enum([
5894
5894
  "pull-rtsp",
5895
5895
  "pull-rtmp",
5896
5896
  "pull-http",
5897
+ "pull-flv",
5897
5898
  "pull-rfc4571",
5898
5899
  "push-annexb",
5899
5900
  "derived"
@@ -13217,7 +13218,7 @@ var AddBrokerInputSchema = object({
13217
13218
  });
13218
13219
  var AddBrokerResultSchema = object({ id: string() });
13219
13220
  var IdInputSchema = object({ id: string() });
13220
- var TestResultSchema = discriminatedUnion("ok", [object({
13221
+ var TestResultSchema$1 = discriminatedUnion("ok", [object({
13221
13222
  ok: literal(true),
13222
13223
  latencyMs: number()
13223
13224
  }), object({
@@ -13240,7 +13241,7 @@ var StatusSchema = object({
13240
13241
  brokerCount: number(),
13241
13242
  embeddedRunning: boolean()
13242
13243
  });
13243
- method(_void(), array(BrokerInfoSchema)), method(IdInputSchema, BrokerConnectionDetailsSchema), method(AddBrokerInputSchema, AddBrokerResultSchema, { kind: "mutation" }), method(IdInputSchema, _void(), { kind: "mutation" }), method(IdInputSchema, TestResultSchema, { kind: "mutation" }), method(StartEmbeddedInputSchema, StartEmbeddedResultSchema, { kind: "mutation" }), method(IdInputSchema, _void(), { kind: "mutation" }), method(_void(), StatusSchema);
13244
+ method(_void(), array(BrokerInfoSchema)), method(IdInputSchema, BrokerConnectionDetailsSchema), method(AddBrokerInputSchema, AddBrokerResultSchema, { kind: "mutation" }), method(IdInputSchema, _void(), { kind: "mutation" }), method(IdInputSchema, TestResultSchema$1, { kind: "mutation" }), method(StartEmbeddedInputSchema, StartEmbeddedResultSchema, { kind: "mutation" }), method(IdInputSchema, _void(), { kind: "mutation" }), method(_void(), StatusSchema);
13244
13245
  var NetworkEndpointSchema = object({
13245
13246
  url: string(),
13246
13247
  hostname: string(),
@@ -13274,29 +13275,210 @@ var NetworkEndpointEntrySchema = NetworkEndpointSchema.extend({
13274
13275
  sourcePort: number().optional()
13275
13276
  });
13276
13277
  method(_void(), NetworkEndpointSchema, { kind: "mutation" }), method(_void(), _void(), { kind: "mutation" }), method(_void(), NetworkEndpointSchema.nullable()), method(_void(), NetworkAccessStatusSchema), method(_void(), array(NetworkEndpointEntrySchema).readonly());
13278
+ /**
13279
+ * notification-output — canonical, capability-gated notification delivery.
13280
+ *
13281
+ * Apprise-derived model (see
13282
+ * `docs/superpowers/specs/2026-07-03-notification-output-notifier-matrix.md`):
13283
+ * callers emit ONE canonical `Notification`; each provider declares a
13284
+ * per-kind capability descriptor (`TargetKind`), and the pure degrade
13285
+ * engine (`@camstack/types` `prepareNotification`) transcodes / degrades the
13286
+ * message to what the kind supports — callers never special-case a service.
13287
+ *
13288
+ * DESIGN DECISIONS (locked):
13289
+ * - Target CRUD lives on THIS cap (`upsertTarget` / `deleteTarget` /
13290
+ * `setTargetEnabled`), each provider persisting via the `settings-store`
13291
+ * cap. Rationale: the admin UI needs one uniform surface across the
13292
+ * notifiers addon AND the HA addon; the addon-`globalSettingsSchema`-array
13293
+ * alternative would fork the UI per addon and cannot host the
13294
+ * discovery→adopt flow.
13295
+ * - `listTargetKinds` / `listTargets` / `discoverTargets` return arrays →
13296
+ * the generated cap-mount auto-`concatCollection`-fans them across every
13297
+ * registered provider (notifiers addon + HA addon) so one catalog is
13298
+ * routable. `send` / `testTarget` / CRUD route to ONE provider by the
13299
+ * `addonId` the generated collection router extracts from the call input.
13300
+ * - `Attachment.bytes` is `Uint8Array`. Transport-safe: superjson (the tRPC
13301
+ * transformer) + UDS MsgPack both round-trip typed arrays — already used by
13302
+ * `storage` / `storage-provider` / `recording` caps over the same path. No
13303
+ * base64 fallback needed.
13304
+ *
13305
+ * TODO (deferred, closed-set change — separate decision): add
13306
+ * `providerKind: 'notify'` so notification providers surface on the unified
13307
+ * admin "Integrations" page.
13308
+ */
13309
+ /**
13310
+ * Zentik-derived typed-media enum — the superset across every kind. Each
13311
+ * adapter picks what it supports and the degrade engine filters the rest.
13312
+ */
13313
+ var AttachmentMediaTypeSchema = _enum([
13314
+ "image",
13315
+ "video",
13316
+ "gif",
13317
+ "audio",
13318
+ "icon"
13319
+ ]);
13320
+ /**
13321
+ * A single attachment. Exactly one of `url` (remote source, most adapters
13322
+ * prefer this) or `bytes` (inline source; required for Pushover-style
13323
+ * bytes-only kinds) MUST be present — the degrade engine expresses a
13324
+ * url→bytes fetch as a `needsFetch` directive the adapter executes.
13325
+ */
13326
+ var AttachmentSchema = object({
13327
+ mediaType: AttachmentMediaTypeSchema,
13328
+ url: string().optional(),
13329
+ bytes: _instanceof(Uint8Array).optional(),
13330
+ mime: string().optional(),
13331
+ name: string().optional()
13332
+ }).refine((a) => a.url !== void 0 || a.bytes !== void 0, { message: "Attachment requires either `url` or `bytes`" });
13333
+ var NotificationFormatSchema = _enum([
13334
+ "text",
13335
+ "markdown",
13336
+ "html"
13337
+ ]);
13338
+ /** A single tap-through action button. */
13339
+ var NotificationActionSchema = object({
13340
+ id: string(),
13341
+ label: string(),
13342
+ url: string().optional()
13343
+ });
13344
+ /**
13345
+ * The canonical notification. `body` is the only hard field (Apprise model).
13346
+ * `priority` is a 5-level ORDINAL (1=lowest … 3=normal(default) … 5=urgent),
13347
+ * NOT a fixed severity enum — each kind declares its own `caps.levels` and
13348
+ * the adapter maps this ordinal onto its native level. `level?` is an
13349
+ * optional kind-native level id (`emergency`, `silent`, …) that overrides
13350
+ * `priority` for that one target.
13351
+ */
13352
+ var NotificationSchema = object({
13353
+ body: string(),
13354
+ title: string().optional(),
13355
+ format: NotificationFormatSchema.default("text"),
13356
+ priority: number().int().min(1).max(5).default(3),
13357
+ level: string().optional(),
13358
+ attachments: array(AttachmentSchema).optional(),
13359
+ clickUrl: string().optional(),
13360
+ actions: array(NotificationActionSchema).optional(),
13361
+ sound: string().optional(),
13362
+ ttl: number().optional(),
13363
+ tag: string().optional(),
13364
+ deviceId: number().optional(),
13365
+ eventId: string().optional(),
13366
+ metadata: record(string(), unknown()).optional()
13367
+ });
13368
+ /** One declared native severity/priority level for a kind. */
13369
+ var TargetKindLevelSchema = object({
13370
+ id: string(),
13371
+ label: string(),
13372
+ /** Which canonical priority (1..5) this level maps to. `null` = qualitative-only. */
13373
+ ordinal: number().int().min(1).max(5).nullable(),
13374
+ flags: object({
13375
+ critical: boolean().optional(),
13376
+ silent: boolean().optional(),
13377
+ noPush: boolean().optional()
13378
+ }).optional(),
13379
+ /** e.g. Pushover `emergency` requires `retry` / `expire`. */
13380
+ requires: array(string()).optional(),
13381
+ description: string().optional()
13382
+ });
13383
+ /** The full capability block consulted before dispatch. */
13384
+ var TargetKindCapsSchema = object({
13385
+ attachments: object({
13386
+ mediaTypes: array(AttachmentMediaTypeSchema),
13387
+ mode: _enum([
13388
+ "url",
13389
+ "bytes",
13390
+ "both"
13391
+ ]),
13392
+ max: number().int().nonnegative(),
13393
+ maxBytes: number().int().positive().optional()
13394
+ }),
13395
+ /** Max action buttons (0 = none). */
13396
+ actions: number().int().nonnegative(),
13397
+ levels: array(TargetKindLevelSchema),
13398
+ format: array(NotificationFormatSchema),
13399
+ clickUrl: boolean(),
13400
+ sound: boolean(),
13401
+ ttl: boolean(),
13402
+ bodyMaxLen: number().int().positive()
13403
+ });
13404
+ /**
13405
+ * `configSchema` is a `ConfigUISchema` tree passed through to the admin
13406
+ * FormBuilder. Stored as `z.unknown()` at the cap seam (mirrors
13407
+ * `device-provider.getChildCreationSchema` `CreationSchemaOutputSchema`) —
13408
+ * the union is large and not meant for runtime validation here; the exported
13409
+ * `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
13410
+ */
13411
+ var ConfigSchemaPassthrough = unknown();
13412
+ var TargetKindSchema = object({
13413
+ kind: string(),
13414
+ label: string(),
13415
+ icon: string(),
13416
+ /** Stamped by each provider so the concat-fanned catalog stays routable. */
13417
+ addonId: string(),
13418
+ configSchema: ConfigSchemaPassthrough,
13419
+ supportsDiscovery: boolean(),
13420
+ caps: TargetKindCapsSchema
13421
+ });
13422
+ /**
13423
+ * A persisted target. `config` holds secrets; providers REDACT secret fields
13424
+ * (return a presence marker only) when serving `listTargets` — never
13425
+ * round-trip a stored secret to the UI.
13426
+ */
13427
+ var TargetSchema = object({
13428
+ id: string(),
13429
+ name: string(),
13430
+ kind: string(),
13431
+ addonId: string(),
13432
+ enabled: boolean(),
13433
+ config: record(string(), unknown())
13434
+ });
13435
+ /** A discovery-surfaced candidate (config is partial + non-secret). */
13436
+ var DiscoveredTargetSchema = object({
13437
+ kind: string(),
13438
+ suggestedName: string(),
13439
+ config: record(string(), unknown())
13440
+ });
13441
+ /** The degrade engine's report — what was resolved / dropped / degraded. */
13442
+ var RenderedAsSchema = object({
13443
+ level: string(),
13444
+ format: NotificationFormatSchema,
13445
+ attachmentsSent: number().int().nonnegative(),
13446
+ actionsSent: number().int().nonnegative(),
13447
+ truncated: boolean(),
13448
+ dropped: array(string())
13449
+ });
13450
+ var SendResultSchema = object({
13451
+ success: boolean(),
13452
+ error: string().optional(),
13453
+ renderedAs: RenderedAsSchema.optional()
13454
+ });
13455
+ /** Same shape as SendResult — kept as a distinct name for the test panel. */
13456
+ var TestResultSchema = SendResultSchema;
13277
13457
  var notificationOutputCapability = {
13278
13458
  name: "notification-output",
13279
13459
  scope: "system",
13280
13460
  mode: "collection",
13281
13461
  methods: {
13462
+ listTargetKinds: method(object({}), array(TargetKindSchema)),
13463
+ listTargets: method(object({}), array(TargetSchema)),
13464
+ discoverTargets: method(object({
13465
+ kind: string(),
13466
+ config: record(string(), unknown()).optional()
13467
+ }), array(DiscoveredTargetSchema)),
13282
13468
  send: method(object({
13283
- title: string(),
13284
- body: string(),
13285
- imageUrl: string().optional(),
13286
- deviceId: number().optional(),
13287
- eventId: string().optional(),
13288
- priority: _enum([
13289
- "low",
13290
- "normal",
13291
- "high",
13292
- "critical"
13293
- ]).default("normal"),
13294
- metadata: record(string(), unknown()).optional()
13295
- }), _void(), { kind: "mutation" }),
13296
- sendTest: method(_void(), object({
13297
- success: boolean(),
13298
- error: string().optional()
13299
- }), { kind: "mutation" })
13469
+ targetId: string(),
13470
+ notification: NotificationSchema
13471
+ }), SendResultSchema, { kind: "mutation" }),
13472
+ testTarget: method(object({
13473
+ targetId: string(),
13474
+ sample: NotificationSchema.optional()
13475
+ }), TestResultSchema, { kind: "mutation" }),
13476
+ upsertTarget: method(object({ target: TargetSchema }), TargetSchema, { kind: "mutation" }),
13477
+ deleteTarget: method(object({ targetId: string() }), _void(), { kind: "mutation" }),
13478
+ setTargetEnabled: method(object({
13479
+ targetId: string(),
13480
+ enabled: boolean()
13481
+ }), _void(), { kind: "mutation" })
13300
13482
  }
13301
13483
  };
13302
13484
  /**
@@ -19293,13 +19475,49 @@ Object.freeze({
19293
19475
  addonId: null,
19294
19476
  access: "create"
19295
19477
  },
19478
+ "notificationOutput.deleteTarget": {
19479
+ capName: "notification-output",
19480
+ capScope: "system",
19481
+ addonId: null,
19482
+ access: "delete"
19483
+ },
19484
+ "notificationOutput.discoverTargets": {
19485
+ capName: "notification-output",
19486
+ capScope: "system",
19487
+ addonId: null,
19488
+ access: "view"
19489
+ },
19490
+ "notificationOutput.listTargetKinds": {
19491
+ capName: "notification-output",
19492
+ capScope: "system",
19493
+ addonId: null,
19494
+ access: "view"
19495
+ },
19496
+ "notificationOutput.listTargets": {
19497
+ capName: "notification-output",
19498
+ capScope: "system",
19499
+ addonId: null,
19500
+ access: "view"
19501
+ },
19296
19502
  "notificationOutput.send": {
19297
19503
  capName: "notification-output",
19298
19504
  capScope: "system",
19299
19505
  addonId: null,
19300
19506
  access: "create"
19301
19507
  },
19302
- "notificationOutput.sendTest": {
19508
+ "notificationOutput.setTargetEnabled": {
19509
+ capName: "notification-output",
19510
+ capScope: "system",
19511
+ addonId: null,
19512
+ access: "create"
19513
+ },
19514
+ "notificationOutput.testTarget": {
19515
+ capName: "notification-output",
19516
+ capScope: "system",
19517
+ addonId: null,
19518
+ access: "create"
19519
+ },
19520
+ "notificationOutput.upsertTarget": {
19303
19521
  capName: "notification-output",
19304
19522
  capScope: "system",
19305
19523
  addonId: null,
@@ -21285,42 +21503,120 @@ object({
21285
21503
  schemaVersion: literal(1)
21286
21504
  });
21287
21505
  //#endregion
21288
- //#region src/rules/rule-store.ts
21506
+ //#region src/history/audit-log.ts
21289
21507
  var COLLECTION$1 = "addon-settings";
21290
- var KEY = "advanced-notifier:rules";
21291
- var RuleStore = class {
21508
+ var LOG_KEY = "notifier-history:log";
21509
+ var AuditLog = class {
21292
21510
  api;
21293
- constructor(api) {
21511
+ maxEntries;
21512
+ constructor(api, maxEntries = 1e3) {
21294
21513
  this.api = api;
21514
+ this.maxEntries = maxEntries;
21295
21515
  }
21296
- async getRules() {
21516
+ async record(entry) {
21517
+ const updated = [...await this.getAll(), entry];
21518
+ const trimmed = updated.length > this.maxEntries ? updated.slice(updated.length - this.maxEntries) : updated;
21519
+ await this.api.settingsStore.set.mutate({
21520
+ collection: COLLECTION$1,
21521
+ key: LOG_KEY,
21522
+ value: trimmed
21523
+ });
21524
+ }
21525
+ async getHistory(filter) {
21526
+ let entries = await this.getAll();
21527
+ if (filter?.ruleId) entries = entries.filter((e) => e.ruleId === filter.ruleId);
21528
+ if (filter?.deviceId) {
21529
+ const deviceId = filter.deviceId;
21530
+ entries = entries.filter((e) => e.deviceId === deviceId);
21531
+ }
21532
+ if (filter?.from !== void 0) {
21533
+ const from = filter.from;
21534
+ entries = entries.filter((e) => e.timestamp >= from);
21535
+ }
21536
+ if (filter?.to !== void 0) {
21537
+ const to = filter.to;
21538
+ entries = entries.filter((e) => e.timestamp <= to);
21539
+ }
21540
+ if (filter?.limit) entries = entries.slice(-filter.limit);
21541
+ return entries;
21542
+ }
21543
+ async getAll() {
21297
21544
  const raw = await this.api.settingsStore.get.query({
21298
21545
  collection: COLLECTION$1,
21299
- key: KEY
21546
+ key: LOG_KEY
21300
21547
  });
21301
21548
  if (!raw || !Array.isArray(raw)) return [];
21302
21549
  return raw;
21303
21550
  }
21304
- async saveRules(rules) {
21305
- await this.api.settingsStore.set.mutate({
21306
- collection: COLLECTION$1,
21307
- key: KEY,
21308
- value: [...rules]
21551
+ };
21552
+ //#endregion
21553
+ //#region src/outputs/console.ts
21554
+ var ConsoleOutput = class {
21555
+ id = "console";
21556
+ name = "Console Log";
21557
+ icon = "terminal";
21558
+ logger;
21559
+ constructor(logger) {
21560
+ this.logger = logger;
21561
+ }
21562
+ async send(notification) {
21563
+ this.logger.info(`[p${notification.priority}] ${notification.title ?? ""}: ${notification.body}`, notification.deviceId !== void 0 ? { tags: { deviceId: notification.deviceId } } : void 0);
21564
+ }
21565
+ async sendTest() {
21566
+ await this.send({
21567
+ title: "Test",
21568
+ body: "Console output working",
21569
+ format: "text",
21570
+ priority: 3
21309
21571
  });
21572
+ return { success: true };
21310
21573
  }
21311
- async upsertRule(rule) {
21312
- const rules = await this.getRules();
21313
- const idx = rules.findIndex((r) => r.id === rule.id);
21314
- if (idx >= 0) rules[idx] = rule;
21315
- else rules.push(rule);
21316
- await this.saveRules(rules);
21574
+ };
21575
+ //#endregion
21576
+ //#region src/rules/cooldown.ts
21577
+ var CooldownTracker = class {
21578
+ lastFired = /* @__PURE__ */ new Map();
21579
+ canFire(ruleId, cooldownSeconds) {
21580
+ const last = this.lastFired.get(ruleId);
21581
+ if (last === void 0) return true;
21582
+ return (Date.now() - last) / 1e3 >= cooldownSeconds;
21317
21583
  }
21318
- async deleteRule(ruleId) {
21319
- const rules = await this.getRules();
21320
- await this.saveRules(rules.filter((r) => r.id !== ruleId));
21584
+ recordFire(ruleId) {
21585
+ this.lastFired.set(ruleId, Date.now());
21586
+ }
21587
+ reset() {
21588
+ this.lastFired.clear();
21321
21589
  }
21322
21590
  };
21323
21591
  //#endregion
21592
+ //#region src/rules/recent-events.ts
21593
+ /**
21594
+ * Rehydrate serialized recent events into `SystemEvent`s and drop any that
21595
+ * fall before `since`. Order is preserved (the hub returns oldest → newest).
21596
+ */
21597
+ function reconstructRecentEvents(serialized, since) {
21598
+ const sinceMs = since.getTime();
21599
+ const events = [];
21600
+ for (const e of serialized) {
21601
+ const timestamp = new Date(e.timestamp);
21602
+ if (timestamp.getTime() < sinceMs) continue;
21603
+ events.push({
21604
+ id: e.id,
21605
+ timestamp,
21606
+ source: {
21607
+ type: e.source.type,
21608
+ id: e.source.id,
21609
+ ...e.source.nodeId !== void 0 ? { nodeId: e.source.nodeId } : {},
21610
+ ...e.source.addonId !== void 0 ? { addonId: e.source.addonId } : {},
21611
+ ...e.source.deviceId !== void 0 ? { deviceId: e.source.deviceId } : {}
21612
+ },
21613
+ category: e.category,
21614
+ data: e.data
21615
+ });
21616
+ }
21617
+ return events;
21618
+ }
21619
+ //#endregion
21324
21620
  //#region src/rules/rule-engine.ts
21325
21621
  var RuleEngine = class {
21326
21622
  clip;
@@ -21393,19 +21689,39 @@ var RuleEngine = class {
21393
21689
  }
21394
21690
  };
21395
21691
  //#endregion
21396
- //#region src/rules/cooldown.ts
21397
- var CooldownTracker = class {
21398
- lastFired = /* @__PURE__ */ new Map();
21399
- canFire(ruleId, cooldownSeconds) {
21400
- const last = this.lastFired.get(ruleId);
21401
- if (last === void 0) return true;
21402
- return (Date.now() - last) / 1e3 >= cooldownSeconds;
21692
+ //#region src/rules/rule-store.ts
21693
+ var COLLECTION = "addon-settings";
21694
+ var KEY = "advanced-notifier:rules";
21695
+ var RuleStore = class {
21696
+ api;
21697
+ constructor(api) {
21698
+ this.api = api;
21403
21699
  }
21404
- recordFire(ruleId) {
21405
- this.lastFired.set(ruleId, Date.now());
21700
+ async getRules() {
21701
+ const raw = await this.api.settingsStore.get.query({
21702
+ collection: COLLECTION,
21703
+ key: KEY
21704
+ });
21705
+ if (!raw || !Array.isArray(raw)) return [];
21706
+ return raw;
21406
21707
  }
21407
- reset() {
21408
- this.lastFired.clear();
21708
+ async saveRules(rules) {
21709
+ await this.api.settingsStore.set.mutate({
21710
+ collection: COLLECTION,
21711
+ key: KEY,
21712
+ value: [...rules]
21713
+ });
21714
+ }
21715
+ async upsertRule(rule) {
21716
+ const rules = await this.getRules();
21717
+ const idx = rules.findIndex((r) => r.id === rule.id);
21718
+ if (idx >= 0) rules[idx] = rule;
21719
+ else rules.push(rule);
21720
+ await this.saveRules(rules);
21721
+ }
21722
+ async deleteRule(ruleId) {
21723
+ const rules = await this.getRules();
21724
+ await this.saveRules(rules.filter((r) => r.id !== ruleId));
21409
21725
  }
21410
21726
  };
21411
21727
  //#endregion
@@ -21417,77 +21733,6 @@ function renderTemplate(template, variables) {
21417
21733
  });
21418
21734
  }
21419
21735
  //#endregion
21420
- //#region src/outputs/console.ts
21421
- var ConsoleOutput = class {
21422
- id = "console";
21423
- name = "Console Log";
21424
- icon = "terminal";
21425
- logger;
21426
- constructor(logger) {
21427
- this.logger = logger;
21428
- }
21429
- async send(notification) {
21430
- this.logger.info(`[${notification.severity}] ${notification.title}: ${notification.message}`, notification.deviceId !== void 0 ? { tags: { deviceId: notification.deviceId } } : void 0);
21431
- }
21432
- async sendTest() {
21433
- await this.send({
21434
- title: "Test",
21435
- message: "Console output working",
21436
- severity: "info",
21437
- category: "test",
21438
- timestamp: Date.now()
21439
- });
21440
- return { success: true };
21441
- }
21442
- };
21443
- //#endregion
21444
- //#region src/history/audit-log.ts
21445
- var COLLECTION = "addon-settings";
21446
- var LOG_KEY = "notifier-history:log";
21447
- var AuditLog = class {
21448
- api;
21449
- maxEntries;
21450
- constructor(api, maxEntries = 1e3) {
21451
- this.api = api;
21452
- this.maxEntries = maxEntries;
21453
- }
21454
- async record(entry) {
21455
- const updated = [...await this.getAll(), entry];
21456
- const trimmed = updated.length > this.maxEntries ? updated.slice(updated.length - this.maxEntries) : updated;
21457
- await this.api.settingsStore.set.mutate({
21458
- collection: COLLECTION,
21459
- key: LOG_KEY,
21460
- value: trimmed
21461
- });
21462
- }
21463
- async getHistory(filter) {
21464
- let entries = await this.getAll();
21465
- if (filter?.ruleId) entries = entries.filter((e) => e.ruleId === filter.ruleId);
21466
- if (filter?.deviceId) {
21467
- const deviceId = filter.deviceId;
21468
- entries = entries.filter((e) => e.deviceId === deviceId);
21469
- }
21470
- if (filter?.from !== void 0) {
21471
- const from = filter.from;
21472
- entries = entries.filter((e) => e.timestamp >= from);
21473
- }
21474
- if (filter?.to !== void 0) {
21475
- const to = filter.to;
21476
- entries = entries.filter((e) => e.timestamp <= to);
21477
- }
21478
- if (filter?.limit) entries = entries.slice(-filter.limit);
21479
- return entries;
21480
- }
21481
- async getAll() {
21482
- const raw = await this.api.settingsStore.get.query({
21483
- collection: COLLECTION,
21484
- key: LOG_KEY
21485
- });
21486
- if (!raw || !Array.isArray(raw)) return [];
21487
- return raw;
21488
- }
21489
- };
21490
- //#endregion
21491
21736
  //#region src/addon.ts
21492
21737
  var EVENT_CATEGORIES = [
21493
21738
  EventCategory.DetectionRaw,
@@ -21539,7 +21784,9 @@ var AdvancedNotifierAddon = class extends BaseAddon {
21539
21784
  const rule = this.cachedRules.find((r) => r.id === ruleId);
21540
21785
  if (!rule) return { results: [] };
21541
21786
  const since = /* @__PURE__ */ new Date(Date.now() - lookbackMinutes * 60 * 1e3);
21542
- return { results: this.ctx.eventBus.getRecent({ category: void 0 }, 1e3).filter((e) => e.timestamp >= since).map((event) => {
21787
+ const api = this.ctx.api;
21788
+ if (!api) return { results: [] };
21789
+ return { results: reconstructRecentEvents(await api.eventBusProxy.getRecent.query({ limit: 1e3 }), since).map((event) => {
21543
21790
  const matched = this.ruleEngine.evaluate(event, [rule]);
21544
21791
  return {
21545
21792
  ruleId,
@@ -21703,12 +21950,11 @@ var AdvancedNotifierAddon = class extends BaseAddon {
21703
21950
  const deviceId = Number.isFinite(deviceIdNum) ? deviceIdNum : void 0;
21704
21951
  const notification = {
21705
21952
  title,
21706
- message,
21707
- severity: this.priorityToSeverity(rule.priority),
21708
- category: event.category,
21953
+ body: message,
21954
+ format: "text",
21955
+ priority: this.priorityToOrdinal(rule.priority),
21709
21956
  deviceId,
21710
- data: event.data,
21711
- timestamp: event.timestamp.getTime()
21957
+ metadata: event.data
21712
21958
  };
21713
21959
  let success = true;
21714
21960
  let dispatchError;
@@ -21753,10 +21999,18 @@ var AdvancedNotifierAddon = class extends BaseAddon {
21753
21999
  timestamp: event.timestamp.toISOString()
21754
22000
  };
21755
22001
  }
21756
- priorityToSeverity(priority) {
21757
- if (priority === "critical") return "critical";
21758
- if (priority === "high") return "warning";
21759
- return "info";
22002
+ /**
22003
+ * Map a rule's qualitative priority onto the canonical 1..5 ordinal.
22004
+ * Callers now pass ordinal priority; each `notification-output` provider
22005
+ * maps the ordinal onto its declared native level.
22006
+ */
22007
+ priorityToOrdinal(priority) {
22008
+ switch (priority) {
22009
+ case "critical": return 5;
22010
+ case "high": return 4;
22011
+ case "low": return 2;
22012
+ default: return 3;
22013
+ }
21760
22014
  }
21761
22015
  };
21762
22016
  //#endregion