@camstack/addon-agent-ui 1.1.13 → 1.1.14

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
@@ -4629,7 +4629,7 @@ function _instanceof(cls, params = {}) {
4629
4629
  return inst;
4630
4630
  }
4631
4631
  //#endregion
4632
- //#region ../types/dist/sleep-C2M2zF7x.mjs
4632
+ //#region ../types/dist/sleep-MHm--th-.mjs
4633
4633
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4634
4634
  EventCategory["SystemBoot"] = "system.boot";
4635
4635
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -5891,6 +5891,7 @@ var CamStreamKindSchema = _enum([
5891
5891
  "pull-rtsp",
5892
5892
  "pull-rtmp",
5893
5893
  "pull-http",
5894
+ "pull-flv",
5894
5895
  "pull-rfc4571",
5895
5896
  "push-annexb",
5896
5897
  "derived"
@@ -9788,6 +9789,31 @@ var ReportMotionInputSchema = object({
9788
9789
  regions: array(MotionRegionSchema).readonly().optional()
9789
9790
  });
9790
9791
  /**
9792
+ * Where a runner gets a camera's decoded frames (cross-node Phase 2,
9793
+ * restream-owner model — P2c).
9794
+ *
9795
+ * - `local-broker` (DEFAULT): today's path — subscribe to the co-located
9796
+ * stream-broker's shm frame plane. Every pre-P2c attach payload (no
9797
+ * `frameSource` key) parses to this, so the field is additive with zero
9798
+ * behavior change.
9799
+ * - `remote-restream`: the detect node is NOT the camera's source-owner.
9800
+ * The runner acquires the owner's COMPRESSED passthrough restream
9801
+ * (`streamBroker.getStreamWithCodec({video:'copy'})` — refcounted, the
9802
+ * double-pull guard) and decodes LOCALLY via a satellite frame plane +
9803
+ * pull-mode decoder session pinned to its own node. The shm ring stays
9804
+ * node-local; only H.264/H.265 packets cross the wire.
9805
+ * `hubHostnameOverride` mirrors the recorder's `recordingHubHostname`:
9806
+ * when set it overrides the `CAMSTACK_HUB_URL`-derived host the runner
9807
+ * dials for the owner's restream.
9808
+ */
9809
+ var RunnerFrameSourceSchema = discriminatedUnion("kind", [object({ kind: literal("local-broker") }), object({
9810
+ kind: literal("remote-restream"),
9811
+ /** The camera's source-owner node (slice 1: always the hub). */
9812
+ ownerNodeId: string(),
9813
+ /** Operator override for the owner host the runner dials. */
9814
+ hubHostnameOverride: string().optional()
9815
+ })]).describe("Per-camera frame-source mode for the runner (P2c)");
9816
+ /**
9791
9817
  * Camera assignment payload sent by `addon-pipeline-orchestrator` to a
9792
9818
  * specific runner instance via `attachCamera`. Carries everything the
9793
9819
  * runner needs to subscribe to the local broker and execute inference.
@@ -9885,7 +9911,15 @@ var RunnerCameraConfigSchema = object({
9885
9911
  */
9886
9912
  onboardMotionDrivesAnalyzer: boolean().default(true),
9887
9913
  occupancyRecheckSec: number().min(occupancyRecheckSecField.min).max(occupancyRecheckSecField.max).default(occupancyRecheckSecField.default),
9888
- occupancyRecheckFrames: number().min(occupancyRecheckFramesField.min).max(occupancyRecheckFramesField.max).default(occupancyRecheckFramesField.default)
9914
+ occupancyRecheckFrames: number().min(occupancyRecheckFramesField.min).max(occupancyRecheckFramesField.max).default(occupancyRecheckFramesField.default),
9915
+ /**
9916
+ * Where this runner gets the camera's decoded frames (P2c). Defaulted so
9917
+ * every existing payload behaves as `local-broker` — the pre-Phase-2 path.
9918
+ * Populated with `remote-restream` by the orchestrator ONLY when the
9919
+ * camera's detect node differs from its source-owner (P2d, gated by the
9920
+ * `remoteSourcingNodes` rollout setting).
9921
+ */
9922
+ frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" })
9889
9923
  });
9890
9924
  motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
9891
9925
  /**
@@ -12367,14 +12401,36 @@ var ChildLayoutEntrySchema = object({
12367
12401
  collapsed: boolean().optional()
12368
12402
  });
12369
12403
  /** Cap-wire shape of a DeviceLink — structurally mirrors `DeviceLink` in
12370
- * `device-management.ts`. */
12404
+ * `device-management.ts`. Source is a union: a FIELD source copies a sibling
12405
+ * accessory's status field (`kind` optional/absent for wire compat); a
12406
+ * LITERAL source carries a per-device constant (no sibling is read); a
12407
+ * GLOBAL source (P2e) copies ANY device's status field, addressed by the
12408
+ * source device's full re-sync-stable `stableId`. */
12371
12409
  var DeviceLinkSchema = object({
12372
12410
  id: string(),
12373
- source: object({
12374
- sourceKey: string(),
12375
- cap: string(),
12376
- fieldPath: string()
12377
- }),
12411
+ source: union([
12412
+ object({
12413
+ kind: literal("field").optional(),
12414
+ sourceKey: string(),
12415
+ cap: string(),
12416
+ fieldPath: string()
12417
+ }),
12418
+ object({
12419
+ kind: literal("literal"),
12420
+ value: union([
12421
+ string(),
12422
+ number(),
12423
+ boolean(),
12424
+ _null()
12425
+ ])
12426
+ }),
12427
+ object({
12428
+ kind: literal("global"),
12429
+ sourceStableId: string(),
12430
+ cap: string(),
12431
+ fieldPath: string()
12432
+ })
12433
+ ]),
12378
12434
  target: object({
12379
12435
  cap: string(),
12380
12436
  fieldPath: string(),
@@ -12617,7 +12673,10 @@ method(object({
12617
12673
  }), _void(), {
12618
12674
  kind: "mutation",
12619
12675
  auth: "admin"
12620
- }), method(object({ deviceId: number() }), object({ caps: array(object({
12676
+ }), method(object({
12677
+ deviceId: number(),
12678
+ includeSynthesizable: boolean().optional()
12679
+ }), object({ caps: array(object({
12621
12680
  cap: string(),
12622
12681
  fields: array(object({
12623
12682
  path: string(),
@@ -12627,8 +12686,13 @@ method(object({
12627
12686
  "boolean",
12628
12687
  "enum"
12629
12688
  ]),
12630
- enumValues: array(string()).optional()
12631
- })).readonly()
12689
+ enumValues: array(string()).optional(),
12690
+ item: boolean().optional()
12691
+ })).readonly(),
12692
+ itemArray: object({
12693
+ path: string(),
12694
+ keyField: string()
12695
+ }).optional()
12632
12696
  })).readonly() }), { kind: "query" }), method(object({
12633
12697
  deviceId: number(),
12634
12698
  role: string().nullable()
@@ -12698,7 +12762,11 @@ method(object({
12698
12762
  deviceId: number(),
12699
12763
  entries: array(object({
12700
12764
  capName: string(),
12701
- kind: _enum(["native", "wrapped"]),
12765
+ kind: _enum([
12766
+ "native",
12767
+ "wrapped",
12768
+ "linked"
12769
+ ]),
12702
12770
  providerAddonId: string(),
12703
12771
  providerNodeId: string(),
12704
12772
  nativeAddonId: string()
@@ -12707,7 +12775,11 @@ method(object({
12707
12775
  deviceId: number(),
12708
12776
  entries: array(object({
12709
12777
  capName: string(),
12710
- kind: _enum(["native", "wrapped"]),
12778
+ kind: _enum([
12779
+ "native",
12780
+ "wrapped",
12781
+ "linked"
12782
+ ]),
12711
12783
  providerAddonId: string(),
12712
12784
  providerNodeId: string(),
12713
12785
  nativeAddonId: string()
@@ -13197,7 +13269,7 @@ var AddBrokerInputSchema = object({
13197
13269
  });
13198
13270
  var AddBrokerResultSchema = object({ id: string() });
13199
13271
  var IdInputSchema = object({ id: string() });
13200
- var TestResultSchema = discriminatedUnion("ok", [object({
13272
+ var TestResultSchema$1 = discriminatedUnion("ok", [object({
13201
13273
  ok: literal(true),
13202
13274
  latencyMs: number()
13203
13275
  }), object({
@@ -13220,7 +13292,7 @@ var StatusSchema = object({
13220
13292
  brokerCount: number(),
13221
13293
  embeddedRunning: boolean()
13222
13294
  });
13223
- 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);
13295
+ 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);
13224
13296
  var NetworkEndpointSchema = object({
13225
13297
  url: string(),
13226
13298
  hostname: string(),
@@ -13254,23 +13326,198 @@ var NetworkEndpointEntrySchema = NetworkEndpointSchema.extend({
13254
13326
  sourcePort: number().optional()
13255
13327
  });
13256
13328
  method(_void(), NetworkEndpointSchema, { kind: "mutation" }), method(_void(), _void(), { kind: "mutation" }), method(_void(), NetworkEndpointSchema.nullable()), method(_void(), NetworkAccessStatusSchema), method(_void(), array(NetworkEndpointEntrySchema).readonly());
13257
- method(object({
13258
- title: string(),
13329
+ /**
13330
+ * notification-output — canonical, capability-gated notification delivery.
13331
+ *
13332
+ * Apprise-derived model (see
13333
+ * `docs/superpowers/specs/2026-07-03-notification-output-notifier-matrix.md`):
13334
+ * callers emit ONE canonical `Notification`; each provider declares a
13335
+ * per-kind capability descriptor (`TargetKind`), and the pure degrade
13336
+ * engine (`@camstack/types` `prepareNotification`) transcodes / degrades the
13337
+ * message to what the kind supports — callers never special-case a service.
13338
+ *
13339
+ * DESIGN DECISIONS (locked):
13340
+ * - Target CRUD lives on THIS cap (`upsertTarget` / `deleteTarget` /
13341
+ * `setTargetEnabled`), each provider persisting via the `settings-store`
13342
+ * cap. Rationale: the admin UI needs one uniform surface across the
13343
+ * notifiers addon AND the HA addon; the addon-`globalSettingsSchema`-array
13344
+ * alternative would fork the UI per addon and cannot host the
13345
+ * discovery→adopt flow.
13346
+ * - `listTargetKinds` / `listTargets` / `discoverTargets` return arrays →
13347
+ * the generated cap-mount auto-`concatCollection`-fans them across every
13348
+ * registered provider (notifiers addon + HA addon) so one catalog is
13349
+ * routable. `send` / `testTarget` / CRUD route to ONE provider by the
13350
+ * `addonId` the generated collection router extracts from the call input.
13351
+ * - `Attachment.bytes` is `Uint8Array`. Transport-safe: superjson (the tRPC
13352
+ * transformer) + UDS MsgPack both round-trip typed arrays — already used by
13353
+ * `storage` / `storage-provider` / `recording` caps over the same path. No
13354
+ * base64 fallback needed.
13355
+ *
13356
+ * TODO (deferred, closed-set change — separate decision): add
13357
+ * `providerKind: 'notify'` so notification providers surface on the unified
13358
+ * admin "Integrations" page.
13359
+ */
13360
+ /**
13361
+ * Zentik-derived typed-media enum — the superset across every kind. Each
13362
+ * adapter picks what it supports and the degrade engine filters the rest.
13363
+ */
13364
+ var AttachmentMediaTypeSchema = _enum([
13365
+ "image",
13366
+ "video",
13367
+ "gif",
13368
+ "audio",
13369
+ "icon"
13370
+ ]);
13371
+ /**
13372
+ * A single attachment. Exactly one of `url` (remote source, most adapters
13373
+ * prefer this) or `bytes` (inline source; required for Pushover-style
13374
+ * bytes-only kinds) MUST be present — the degrade engine expresses a
13375
+ * url→bytes fetch as a `needsFetch` directive the adapter executes.
13376
+ */
13377
+ var AttachmentSchema = object({
13378
+ mediaType: AttachmentMediaTypeSchema,
13379
+ url: string().optional(),
13380
+ bytes: _instanceof(Uint8Array).optional(),
13381
+ mime: string().optional(),
13382
+ name: string().optional()
13383
+ }).refine((a) => a.url !== void 0 || a.bytes !== void 0, { message: "Attachment requires either `url` or `bytes`" });
13384
+ var NotificationFormatSchema = _enum([
13385
+ "text",
13386
+ "markdown",
13387
+ "html"
13388
+ ]);
13389
+ /** A single tap-through action button. */
13390
+ var NotificationActionSchema = object({
13391
+ id: string(),
13392
+ label: string(),
13393
+ url: string().optional()
13394
+ });
13395
+ /**
13396
+ * The canonical notification. `body` is the only hard field (Apprise model).
13397
+ * `priority` is a 5-level ORDINAL (1=lowest … 3=normal(default) … 5=urgent),
13398
+ * NOT a fixed severity enum — each kind declares its own `caps.levels` and
13399
+ * the adapter maps this ordinal onto its native level. `level?` is an
13400
+ * optional kind-native level id (`emergency`, `silent`, …) that overrides
13401
+ * `priority` for that one target.
13402
+ */
13403
+ var NotificationSchema = object({
13259
13404
  body: string(),
13260
- imageUrl: string().optional(),
13405
+ title: string().optional(),
13406
+ format: NotificationFormatSchema.default("text"),
13407
+ priority: number().int().min(1).max(5).default(3),
13408
+ level: string().optional(),
13409
+ attachments: array(AttachmentSchema).optional(),
13410
+ clickUrl: string().optional(),
13411
+ actions: array(NotificationActionSchema).optional(),
13412
+ sound: string().optional(),
13413
+ ttl: number().optional(),
13414
+ tag: string().optional(),
13261
13415
  deviceId: number().optional(),
13262
13416
  eventId: string().optional(),
13263
- priority: _enum([
13264
- "low",
13265
- "normal",
13266
- "high",
13267
- "critical"
13268
- ]).default("normal"),
13269
13417
  metadata: record(string(), unknown()).optional()
13270
- }), _void(), { kind: "mutation" }), method(_void(), object({
13418
+ });
13419
+ /** One declared native severity/priority level for a kind. */
13420
+ var TargetKindLevelSchema = object({
13421
+ id: string(),
13422
+ label: string(),
13423
+ /** Which canonical priority (1..5) this level maps to. `null` = qualitative-only. */
13424
+ ordinal: number().int().min(1).max(5).nullable(),
13425
+ flags: object({
13426
+ critical: boolean().optional(),
13427
+ silent: boolean().optional(),
13428
+ noPush: boolean().optional()
13429
+ }).optional(),
13430
+ /** e.g. Pushover `emergency` requires `retry` / `expire`. */
13431
+ requires: array(string()).optional(),
13432
+ description: string().optional()
13433
+ });
13434
+ /** The full capability block consulted before dispatch. */
13435
+ var TargetKindCapsSchema = object({
13436
+ attachments: object({
13437
+ mediaTypes: array(AttachmentMediaTypeSchema),
13438
+ mode: _enum([
13439
+ "url",
13440
+ "bytes",
13441
+ "both"
13442
+ ]),
13443
+ max: number().int().nonnegative(),
13444
+ maxBytes: number().int().positive().optional()
13445
+ }),
13446
+ /** Max action buttons (0 = none). */
13447
+ actions: number().int().nonnegative(),
13448
+ levels: array(TargetKindLevelSchema),
13449
+ format: array(NotificationFormatSchema),
13450
+ clickUrl: boolean(),
13451
+ sound: boolean(),
13452
+ ttl: boolean(),
13453
+ bodyMaxLen: number().int().positive()
13454
+ });
13455
+ /**
13456
+ * `configSchema` is a `ConfigUISchema` tree passed through to the admin
13457
+ * FormBuilder. Stored as `z.unknown()` at the cap seam (mirrors
13458
+ * `device-provider.getChildCreationSchema` `CreationSchemaOutputSchema`) —
13459
+ * the union is large and not meant for runtime validation here; the exported
13460
+ * `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
13461
+ */
13462
+ var ConfigSchemaPassthrough = unknown();
13463
+ var TargetKindSchema = object({
13464
+ kind: string(),
13465
+ label: string(),
13466
+ icon: string(),
13467
+ /** Stamped by each provider so the concat-fanned catalog stays routable. */
13468
+ addonId: string(),
13469
+ configSchema: ConfigSchemaPassthrough,
13470
+ supportsDiscovery: boolean(),
13471
+ caps: TargetKindCapsSchema
13472
+ });
13473
+ /**
13474
+ * A persisted target. `config` holds secrets; providers REDACT secret fields
13475
+ * (return a presence marker only) when serving `listTargets` — never
13476
+ * round-trip a stored secret to the UI.
13477
+ */
13478
+ var TargetSchema = object({
13479
+ id: string(),
13480
+ name: string(),
13481
+ kind: string(),
13482
+ addonId: string(),
13483
+ enabled: boolean(),
13484
+ config: record(string(), unknown())
13485
+ });
13486
+ /** A discovery-surfaced candidate (config is partial + non-secret). */
13487
+ var DiscoveredTargetSchema = object({
13488
+ kind: string(),
13489
+ suggestedName: string(),
13490
+ config: record(string(), unknown())
13491
+ });
13492
+ /** The degrade engine's report — what was resolved / dropped / degraded. */
13493
+ var RenderedAsSchema = object({
13494
+ level: string(),
13495
+ format: NotificationFormatSchema,
13496
+ attachmentsSent: number().int().nonnegative(),
13497
+ actionsSent: number().int().nonnegative(),
13498
+ truncated: boolean(),
13499
+ dropped: array(string())
13500
+ });
13501
+ var SendResultSchema = object({
13271
13502
  success: boolean(),
13272
- error: string().optional()
13273
- }), { kind: "mutation" });
13503
+ error: string().optional(),
13504
+ renderedAs: RenderedAsSchema.optional()
13505
+ });
13506
+ /** Same shape as SendResult — kept as a distinct name for the test panel. */
13507
+ var TestResultSchema = SendResultSchema;
13508
+ method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSchema)), method(object({
13509
+ kind: string(),
13510
+ config: record(string(), unknown()).optional()
13511
+ }), array(DiscoveredTargetSchema)), method(object({
13512
+ targetId: string(),
13513
+ notification: NotificationSchema
13514
+ }), SendResultSchema, { kind: "mutation" }), method(object({
13515
+ targetId: string(),
13516
+ sample: NotificationSchema.optional()
13517
+ }), TestResultSchema, { kind: "mutation" }), method(object({ target: TargetSchema }), TargetSchema, { kind: "mutation" }), method(object({ targetId: string() }), _void(), { kind: "mutation" }), method(object({
13518
+ targetId: string(),
13519
+ enabled: boolean()
13520
+ }), _void(), { kind: "mutation" });
13274
13521
  /**
13275
13522
  * Zod schemas for persisted record types.
13276
13523
  *
@@ -16459,6 +16706,16 @@ DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceI
16459
16706
  kind: "mutation",
16460
16707
  auth: "admin"
16461
16708
  });
16709
+ /**
16710
+ * `recording` cap — footage availability + HLS playback manifests + per-device
16711
+ * recording config. NOTE on events (source of truth, R5/C3): this cap carries
16712
+ * NO event surface — `getPlaybackManifest` returns playlist URLs only. Timeline
16713
+ * events (motion/object/audio) come from `pipelineAnalytics` (durable SQLite
16714
+ * rows); the recorder's internal EventMap markers are ephemeral in-RAM
16715
+ * annotations that are not exposed here and must not be treated as an event
16716
+ * feed. Event<->footage joins are by time, padded with the shared `EVENT_PAD_MS`
16717
+ * (`interfaces/recording-config.ts`).
16718
+ */
16462
16719
  var RecordingStatusSchema = object({
16463
16720
  deviceId: number(),
16464
16721
  enabled: boolean(),
@@ -19265,13 +19522,49 @@ Object.freeze({
19265
19522
  addonId: null,
19266
19523
  access: "create"
19267
19524
  },
19525
+ "notificationOutput.deleteTarget": {
19526
+ capName: "notification-output",
19527
+ capScope: "system",
19528
+ addonId: null,
19529
+ access: "delete"
19530
+ },
19531
+ "notificationOutput.discoverTargets": {
19532
+ capName: "notification-output",
19533
+ capScope: "system",
19534
+ addonId: null,
19535
+ access: "view"
19536
+ },
19537
+ "notificationOutput.listTargetKinds": {
19538
+ capName: "notification-output",
19539
+ capScope: "system",
19540
+ addonId: null,
19541
+ access: "view"
19542
+ },
19543
+ "notificationOutput.listTargets": {
19544
+ capName: "notification-output",
19545
+ capScope: "system",
19546
+ addonId: null,
19547
+ access: "view"
19548
+ },
19268
19549
  "notificationOutput.send": {
19269
19550
  capName: "notification-output",
19270
19551
  capScope: "system",
19271
19552
  addonId: null,
19272
19553
  access: "create"
19273
19554
  },
19274
- "notificationOutput.sendTest": {
19555
+ "notificationOutput.setTargetEnabled": {
19556
+ capName: "notification-output",
19557
+ capScope: "system",
19558
+ addonId: null,
19559
+ access: "create"
19560
+ },
19561
+ "notificationOutput.testTarget": {
19562
+ capName: "notification-output",
19563
+ capScope: "system",
19564
+ addonId: null,
19565
+ access: "create"
19566
+ },
19567
+ "notificationOutput.upsertTarget": {
19275
19568
  capName: "notification-output",
19276
19569
  capScope: "system",
19277
19570
  addonId: null,
@@ -21277,7 +21570,7 @@ var AgentUIAddon = class extends BaseAddon {
21277
21570
  capability: adminUiCapability,
21278
21571
  provider: {
21279
21572
  getStaticDir: async () => ({ staticDir: path.resolve(__dirname) }),
21280
- getVersion: async () => ({ version: "1.1.13" })
21573
+ getVersion: async () => ({ version: "1.1.14" })
21281
21574
  }
21282
21575
  }];
21283
21576
  }