@camstack/system 1.2.42 → 1.2.44

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 (49) hide show
  1. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  2. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  3. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/alerts/alerts.addon.js +1 -1
  6. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  7. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  8. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  9. package/dist/builtins/console-logging/index.js +1 -1
  10. package/dist/builtins/console-logging/index.mjs +1 -1
  11. package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
  12. package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
  13. package/dist/builtins/device-manager/device-manager.addon.js +1 -1
  14. package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
  15. package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
  16. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
  17. package/dist/builtins/hub-forwarder/index.js +1 -1
  18. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  19. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  20. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  21. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  22. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  23. package/dist/builtins/local-network/local-network.addon.js +1 -1
  24. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  25. package/dist/builtins/loki-logging/index.js +1 -1
  26. package/dist/builtins/loki-logging/index.mjs +1 -1
  27. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  28. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  29. package/dist/builtins/platform-probe/index.js +1 -1
  30. package/dist/builtins/platform-probe/index.mjs +1 -1
  31. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  32. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  33. package/dist/builtins/snapshot/index.js +1 -1
  34. package/dist/builtins/snapshot/index.mjs +1 -1
  35. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  36. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  37. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +1 -1
  38. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +1 -1
  39. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  40. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  41. package/dist/builtins/system-config/system-config.addon.js +1 -1
  42. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  43. package/dist/builtins/winston-logging/index.js +1 -1
  44. package/dist/builtins/winston-logging/index.mjs +1 -1
  45. package/dist/{dist-BpVtesRV.mjs → dist-BZAMwgix.mjs} +344 -243
  46. package/dist/{dist-DBeh_RnY.js → dist-CBwOEr6q.js} +344 -243
  47. package/dist/index.js +1 -1
  48. package/dist/index.mjs +1 -1
  49. package/package.json +1 -1
@@ -5281,6 +5281,292 @@ var MaskGridDimsSchema = zod.z.object({
5281
5281
  height: zod.z.number()
5282
5282
  });
5283
5283
  /**
5284
+ * notification-output — canonical, capability-gated notification delivery.
5285
+ *
5286
+ * Apprise-derived model (see
5287
+ * `docs/superpowers/specs/2026-07-03-notification-output-notifier-matrix.md`):
5288
+ * callers emit ONE canonical `Notification`; each provider declares a
5289
+ * per-kind capability descriptor (`TargetKind`), and the pure degrade
5290
+ * engine (`@camstack/types` `prepareNotification`) transcodes / degrades the
5291
+ * message to what the kind supports — callers never special-case a service.
5292
+ *
5293
+ * DESIGN DECISIONS (locked):
5294
+ * - Target CRUD lives on THIS cap (`upsertTarget` / `deleteTarget` /
5295
+ * `setTargetEnabled`), each provider persisting via the `settings-store`
5296
+ * cap. Rationale: the admin UI needs one uniform surface across the
5297
+ * notifiers addon AND the HA addon; the addon-`globalSettingsSchema`-array
5298
+ * alternative would fork the UI per addon and cannot host the
5299
+ * discovery→adopt flow.
5300
+ * - `listTargetKinds` / `listTargets` / `discoverTargets` return arrays →
5301
+ * the generated cap-mount auto-`concatCollection`-fans them across every
5302
+ * registered provider (notifiers addon + HA addon) so one catalog is
5303
+ * routable. `send` / `testTarget` / CRUD route to ONE provider by the
5304
+ * `addonId` the generated collection router extracts from the call input.
5305
+ * - `Attachment.bytes` is `Uint8Array`. Transport-safe: superjson (the tRPC
5306
+ * transformer) + UDS MsgPack both round-trip typed arrays — already used by
5307
+ * `storage` / `storage-provider` / `recording` caps over the same path. No
5308
+ * base64 fallback needed.
5309
+ *
5310
+ * TODO (deferred, closed-set change — separate decision): add
5311
+ * `providerKind: 'notify'` so notification providers surface on the unified
5312
+ * admin "Integrations" page.
5313
+ */
5314
+ /**
5315
+ * Zentik-derived typed-media enum — the superset across every kind. Each
5316
+ * adapter picks what it supports and the degrade engine filters the rest.
5317
+ */
5318
+ var AttachmentMediaTypeSchema = zod.z.enum([
5319
+ "image",
5320
+ "video",
5321
+ "gif",
5322
+ "audio",
5323
+ "icon"
5324
+ ]);
5325
+ /**
5326
+ * A single attachment. Exactly one of `url` (remote source, most adapters
5327
+ * prefer this) or `bytes` (inline source; required for Pushover-style
5328
+ * bytes-only kinds) MUST be present — the degrade engine expresses a
5329
+ * url→bytes fetch as a `needsFetch` directive the adapter executes.
5330
+ */
5331
+ var AttachmentSchema = zod.z.object({
5332
+ mediaType: AttachmentMediaTypeSchema,
5333
+ url: zod.z.string().optional(),
5334
+ bytes: zod.z.instanceof(Uint8Array).optional(),
5335
+ mime: zod.z.string().optional(),
5336
+ name: zod.z.string().optional()
5337
+ }).refine((a) => a.url !== void 0 || a.bytes !== void 0, { message: "Attachment requires either `url` or `bytes`" });
5338
+ var NotificationFormatSchema = zod.z.enum([
5339
+ "text",
5340
+ "markdown",
5341
+ "html"
5342
+ ]);
5343
+ /**
5344
+ * The CLOSED icon vocabulary an action button may use.
5345
+ *
5346
+ * A closed set, not a free string, and that is the whole point: an arbitrary
5347
+ * icon name is one that ntfy renders, zentik silently drops, and nobody
5348
+ * notices — the same class of gap as a zone vocabulary nothing produced
5349
+ * ([D35](../../../docs/decisions/adr-0035.md)). Every adapter maps this set or
5350
+ * declares `actionIcons: false` and the degrade engine strips the field.
5351
+ *
5352
+ * Named by INTENT, never by glyph. "check" would tie the vocabulary to one
5353
+ * renderer's icon set; "acknowledge" survives an adapter that draws it
5354
+ * differently.
5355
+ */
5356
+ var NotificationActionIconSchema = zod.z.enum([
5357
+ "acknowledge",
5358
+ "dismiss",
5359
+ "silence",
5360
+ "view",
5361
+ "play",
5362
+ "open",
5363
+ "close",
5364
+ "lock",
5365
+ "unlock",
5366
+ "arm",
5367
+ "disarm",
5368
+ "light",
5369
+ "alert"
5370
+ ]);
5371
+ /** A single tap-through action button. */
5372
+ var NotificationActionSchema = zod.z.object({
5373
+ id: zod.z.string(),
5374
+ label: zod.z.string(),
5375
+ url: zod.z.string().optional(),
5376
+ /** Dropped by the degrade engine for a kind with `caps.actionIcons: false`. */
5377
+ icon: NotificationActionIconSchema.optional(),
5378
+ /**
5379
+ * Renders in a warning style where the notifier supports it.
5380
+ *
5381
+ * A HINT, never a gate. The callback's authority is its token and nothing
5382
+ * else — see `notification-center/action-token.ts` for what that does and
5383
+ * does not buy.
5384
+ */
5385
+ destructive: zod.z.boolean().optional()
5386
+ });
5387
+ /**
5388
+ * The canonical notification. `body` is the only hard field (Apprise model).
5389
+ * `priority` is a 5-level ORDINAL (1=lowest … 3=normal(default) … 5=urgent),
5390
+ * NOT a fixed severity enum — each kind declares its own `caps.levels` and
5391
+ * the adapter maps this ordinal onto its native level. `level?` is an
5392
+ * optional kind-native level id (`emergency`, `silent`, …) that overrides
5393
+ * `priority` for that one target.
5394
+ */
5395
+ var NotificationSchema = zod.z.object({
5396
+ body: zod.z.string(),
5397
+ title: zod.z.string().optional(),
5398
+ format: NotificationFormatSchema.default("text"),
5399
+ priority: zod.z.number().int().min(1).max(5).default(3),
5400
+ level: zod.z.string().optional(),
5401
+ attachments: zod.z.array(AttachmentSchema).optional(),
5402
+ clickUrl: zod.z.string().optional(),
5403
+ actions: zod.z.array(NotificationActionSchema).optional(),
5404
+ sound: zod.z.string().optional(),
5405
+ ttl: zod.z.number().optional(),
5406
+ tag: zod.z.string().optional(),
5407
+ deviceId: zod.z.number().optional(),
5408
+ eventId: zod.z.string().optional(),
5409
+ metadata: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
5410
+ });
5411
+ /** One declared native severity/priority level for a kind. */
5412
+ var TargetKindLevelSchema = zod.z.object({
5413
+ id: zod.z.string(),
5414
+ label: zod.z.string(),
5415
+ /** Which canonical priority (1..5) this level maps to. `null` = qualitative-only. */
5416
+ ordinal: zod.z.number().int().min(1).max(5).nullable(),
5417
+ flags: zod.z.object({
5418
+ critical: zod.z.boolean().optional(),
5419
+ silent: zod.z.boolean().optional(),
5420
+ noPush: zod.z.boolean().optional()
5421
+ }).optional(),
5422
+ /** e.g. Pushover `emergency` requires `retry` / `expire`. */
5423
+ requires: zod.z.array(zod.z.string()).optional(),
5424
+ description: zod.z.string().optional()
5425
+ });
5426
+ /** Attachment capabilities for a kind (drives the degrade engine + test panel). */
5427
+ var TargetKindAttachmentsCapsSchema = zod.z.object({
5428
+ mediaTypes: zod.z.array(AttachmentMediaTypeSchema),
5429
+ mode: zod.z.enum([
5430
+ "url",
5431
+ "bytes",
5432
+ "both"
5433
+ ]),
5434
+ max: zod.z.number().int().nonnegative(),
5435
+ maxBytes: zod.z.number().int().positive().optional()
5436
+ });
5437
+ /** The full capability block consulted before dispatch. */
5438
+ var TargetKindCapsSchema = zod.z.object({
5439
+ attachments: TargetKindAttachmentsCapsSchema,
5440
+ /** Max action buttons (0 = none). */
5441
+ actions: zod.z.number().int().nonnegative(),
5442
+ /**
5443
+ * Whether this kind renders a per-action ICON.
5444
+ *
5445
+ * `.optional()`, deliberately NOT `.default(false)`: a Zod default does not
5446
+ * run on the addon cap path — three production failures in one day taught
5447
+ * this repo that once. Absent is read as false by the degrade engine, which
5448
+ * is the safe direction: an icon that is not rendered costs nothing, an icon
5449
+ * assumed and dropped costs the operator's trust in the field.
5450
+ */
5451
+ actionIcons: zod.z.boolean().optional(),
5452
+ levels: zod.z.array(TargetKindLevelSchema),
5453
+ format: zod.z.array(NotificationFormatSchema),
5454
+ clickUrl: zod.z.boolean(),
5455
+ sound: zod.z.boolean(),
5456
+ ttl: zod.z.boolean(),
5457
+ bodyMaxLen: zod.z.number().int().positive()
5458
+ });
5459
+ /**
5460
+ * `configSchema` is a `ConfigUISchema` tree passed through to the admin
5461
+ * FormBuilder. Stored as `z.unknown()` at the cap seam (mirrors
5462
+ * `device-provider.getChildCreationSchema` `CreationSchemaOutputSchema`) —
5463
+ * the union is large and not meant for runtime validation here; the exported
5464
+ * `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
5465
+ */
5466
+ var ConfigSchemaPassthrough$1 = zod.z.unknown();
5467
+ var TargetKindSchema = zod.z.object({
5468
+ kind: zod.z.string(),
5469
+ label: zod.z.string(),
5470
+ icon: zod.z.string(),
5471
+ /** Stamped by each provider so the concat-fanned catalog stays routable. */
5472
+ addonId: zod.z.string(),
5473
+ /**
5474
+ * URL of the kind's bundled BRAND icon, served by the providing addon over
5475
+ * its own `addon-routes` surface (`/addon/<addonId>/icons/<kind>`). Absent
5476
+ * when the addon bundles no icon for that kind — the client then falls back
5477
+ * to a neutral glyph rather than rendering the raw `icon` NAME as text.
5478
+ *
5479
+ * Root-relative on purpose: it resolves against whatever origin serves a web
5480
+ * client, and a native client joins it onto its own hub base.
5481
+ *
5482
+ * DECLARED here deliberately. It used to travel as an undeclared passthrough
5483
+ * field that survived only because the runtime cap-router forwards provider
5484
+ * output verbatim — so every consumer had to re-declare it by hand to stop
5485
+ * its own Zod parse from stripping it, and the whole arrangement would have
5486
+ * broken silently the moment output validation was tightened anywhere.
5487
+ */
5488
+ iconUrl: zod.z.string().optional(),
5489
+ /**
5490
+ * Media type of {@link iconUrl} (`image/svg+xml`, `image/png`, …).
5491
+ *
5492
+ * The server knows this and therefore says it, because the client cannot
5493
+ * safely guess: a React-Native client renders SVG and raster through two
5494
+ * DIFFERENT components (`react-native-svg` vs `expo-image` — expo-image does
5495
+ * not decode SVG on iOS/Android), so without this it silently fell back to a
5496
+ * placeholder glyph for every vector icon while the web build looked fine.
5497
+ *
5498
+ * Absent when {@link iconUrl} is absent, or for a legacy provider that has
5499
+ * not been updated — a client that cannot determine the type should prefer
5500
+ * its raster path, which is the safe default for an unknown image.
5501
+ */
5502
+ iconMediaType: zod.z.string().optional(),
5503
+ configSchema: ConfigSchemaPassthrough$1,
5504
+ supportsDiscovery: zod.z.boolean(),
5505
+ caps: TargetKindCapsSchema
5506
+ });
5507
+ /**
5508
+ * A persisted target. `config` holds secrets; providers REDACT secret fields
5509
+ * (return a presence marker only) when serving `listTargets` — never
5510
+ * round-trip a stored secret to the UI.
5511
+ */
5512
+ var TargetSchema = zod.z.object({
5513
+ id: zod.z.string(),
5514
+ name: zod.z.string(),
5515
+ kind: zod.z.string(),
5516
+ addonId: zod.z.string(),
5517
+ enabled: zod.z.boolean(),
5518
+ config: zod.z.record(zod.z.string(), zod.z.unknown())
5519
+ });
5520
+ /** A discovery-surfaced candidate (config is partial + non-secret). */
5521
+ var DiscoveredTargetSchema = zod.z.object({
5522
+ kind: zod.z.string(),
5523
+ suggestedName: zod.z.string(),
5524
+ config: zod.z.record(zod.z.string(), zod.z.unknown())
5525
+ });
5526
+ /** The degrade engine's report — what was resolved / dropped / degraded. */
5527
+ var RenderedAsSchema = zod.z.object({
5528
+ level: zod.z.string(),
5529
+ format: NotificationFormatSchema,
5530
+ attachmentsSent: zod.z.number().int().nonnegative(),
5531
+ actionsSent: zod.z.number().int().nonnegative(),
5532
+ truncated: zod.z.boolean(),
5533
+ dropped: zod.z.array(zod.z.string())
5534
+ });
5535
+ var SendResultSchema = zod.z.object({
5536
+ success: zod.z.boolean(),
5537
+ error: zod.z.string().optional(),
5538
+ renderedAs: RenderedAsSchema.optional()
5539
+ });
5540
+ /** Same shape as SendResult — kept as a distinct name for the test panel. */
5541
+ var TestResultSchema = SendResultSchema;
5542
+ var notificationOutputCapability = {
5543
+ name: "notification-output",
5544
+ scope: "system",
5545
+ mode: "collection",
5546
+ methods: {
5547
+ listTargetKinds: method(zod.z.object({}), zod.z.array(TargetKindSchema)),
5548
+ listTargets: method(zod.z.object({}), zod.z.array(TargetSchema)),
5549
+ discoverTargets: method(zod.z.object({
5550
+ kind: zod.z.string(),
5551
+ config: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
5552
+ }), zod.z.array(DiscoveredTargetSchema)),
5553
+ send: method(zod.z.object({
5554
+ targetId: zod.z.string(),
5555
+ notification: NotificationSchema
5556
+ }), SendResultSchema, { kind: "mutation" }),
5557
+ testTarget: method(zod.z.object({
5558
+ targetId: zod.z.string(),
5559
+ sample: NotificationSchema.optional()
5560
+ }), TestResultSchema, { kind: "mutation" }),
5561
+ upsertTarget: method(zod.z.object({ target: TargetSchema }), TargetSchema, { kind: "mutation" }),
5562
+ deleteTarget: method(zod.z.object({ targetId: zod.z.string() }), zod.z.void(), { kind: "mutation" }),
5563
+ setTargetEnabled: method(zod.z.object({
5564
+ targetId: zod.z.string(),
5565
+ enabled: zod.z.boolean()
5566
+ }), zod.z.void(), { kind: "mutation" })
5567
+ }
5568
+ };
5569
+ /**
5284
5570
  * notification-rules — the Notification Center rule surface (P1 core).
5285
5571
  *
5286
5572
  * Spec: `docs/superpowers/specs/2026-07-22-notification-center-requirements.md`
@@ -5465,6 +5751,28 @@ var NcRuleActionSequenceSchema = zod.z.object({
5465
5751
  actions: zod.z.array(NcRuleActionSchema).min(1)
5466
5752
  });
5467
5753
  /**
5754
+ * One button carried by the notification, running a named sequence on tap.
5755
+ *
5756
+ * **Read this before adding a button that does something physical.** The tap
5757
+ * arrives over a link that travelled through third-party infrastructure — ntfy,
5758
+ * a push relay, whatever forwarded the message — and the callback's ONLY
5759
+ * authority is the token in that link: single-use, short-lived, bound to this
5760
+ * one action of this one notification. It does not identify who tapped.
5761
+ * Whoever holds the notification can run the button, once, inside the window.
5762
+ * That is the operator's explicit choice (2026-08-05), and `destructive` is a
5763
+ * rendering hint, not a second gate. [D47](decisions/adr-0047.md).
5764
+ */
5765
+ var NcRuleNotificationButtonSchema = zod.z.object({
5766
+ /** Stable id — travels in the callback and identifies the button in logs. */
5767
+ id: zod.z.string().min(1).max(64),
5768
+ label: zod.z.string().min(1).max(40),
5769
+ /** Name of a sequence in `onTrigger`. The dispatcher drops a button whose
5770
+ * sequence does not exist rather than minting a token for nothing. */
5771
+ sequence: zod.z.string().min(1).max(120),
5772
+ icon: NotificationActionIconSchema.optional(),
5773
+ destructive: zod.z.boolean().optional()
5774
+ });
5775
+ /**
5468
5776
  * Sequences a rule runs, by hook point.
5469
5777
  *
5470
5778
  * ONLY `onTrigger` is here, deliberately. The reference also has activation /
@@ -5472,9 +5780,26 @@ var NcRuleActionSequenceSchema = zod.z.object({
5472
5780
  * repo's expensive failure mode is declaring a surface nothing produces, so a
5473
5781
  * hook appears here in the same change that produces its edge, never before.
5474
5782
  */
5475
- var NcRuleActionsSchema = zod.z.object({
5476
- /** Runs when the rule MATCHES. */
5477
- onTrigger: zod.z.array(NcRuleActionSequenceSchema).optional() });
5783
+ var NcRuleActionsSchema = zod.z.object({
5784
+ /** Runs when the rule MATCHES. */
5785
+ onTrigger: zod.z.array(NcRuleActionSequenceSchema).optional(),
5786
+ /**
5787
+ * Buttons the NOTIFICATION carries, each running one of this rule's
5788
+ * sequences when tapped.
5789
+ *
5790
+ * Deliberately a REFERENCE to a sequence rather than a second place to
5791
+ * author steps. A button that could define its own actions would be a
5792
+ * parallel actuation vocabulary — the executor's device-scope check, the
5793
+ * stop-at-first-failure rule and the per-sequence throttle all live on
5794
+ * sequences, and a second authoring surface would drift from every one of
5795
+ * them.
5796
+ *
5797
+ * A sequence reachable ONLY by a button simply appears in `onTrigger` with
5798
+ * `enabled: false`: it is then authored, throttled and validated like the
5799
+ * rest, and nothing runs it automatically.
5800
+ */
5801
+ buttons: zod.z.array(NcRuleNotificationButtonSchema).max(8).optional()
5802
+ });
5478
5803
  /**
5479
5804
  * "This rule applies only while `deviceId` is in one of `states`."
5480
5805
  *
@@ -14376,6 +14701,20 @@ var GetInputSchema = zod.z.object({ id: zod.z.string() });
14376
14701
  var AddInputSchema = zod.z.object({
14377
14702
  kind: zod.z.string().min(1),
14378
14703
  name: zod.z.string().min(1),
14704
+ /**
14705
+ * ADOPT an existing id instead of minting a new one.
14706
+ *
14707
+ * Written the day this cost an outage. A broker's id is not a detail: HA
14708
+ * devices carry it inside their `stableId` (`ha:ha_004:dev:…`), so a broker
14709
+ * lost from config and re-added as `ha_001` leaves every one of its devices
14710
+ * bound to a broker that no longer exists. Re-entering the password under the
14711
+ * ORIGINAL id turns a multi-step device migration back into re-entering a
14712
+ * password.
14713
+ *
14714
+ * A provider MUST refuse an id that is already in use — adopting a live
14715
+ * broker's id would silently take it over.
14716
+ */
14717
+ id: zod.z.string().min(1).optional(),
14379
14718
  /** Kind-specific settings (e.g. MQTT `{url,username,password}` or HA
14380
14719
  * `{baseUrl,accessToken}`). Validated by the kind-specific provider
14381
14720
  * branch on receipt — invalid shape rejects the add. */
@@ -16801,14 +17140,14 @@ var LlmProfileSchema = zod.z.object({
16801
17140
  /** ConfigUISchema tree passed through untyped on the wire (the
16802
17141
  * notification-output `ConfigSchemaPassthrough` precedent at
16803
17142
  * notification-output.cap.ts:151); the exported TS type re-tightens it. */
16804
- var ConfigSchemaPassthrough$1 = zod.z.unknown();
17143
+ var ConfigSchemaPassthrough = zod.z.unknown();
16805
17144
  var LlmProfileKindDescriptorSchema = zod.z.object({
16806
17145
  kind: LlmProfileKindSchema,
16807
17146
  label: zod.z.string(),
16808
17147
  icon: zod.z.string(),
16809
17148
  /** Stamped by each provider so the concat-fanned catalog stays routable. */
16810
17149
  addonId: zod.z.string(),
16811
- configSchema: ConfigSchemaPassthrough$1
17150
+ configSchema: ConfigSchemaPassthrough
16812
17151
  });
16813
17152
  var LlmDefaultSelectorSchema = zod.z.union([zod.z.object({ consumer: zod.z.string() }), zod.z.object({ purpose: zod.z.enum(["text", "vision"]) })]);
16814
17153
  var LlmDefaultSchema = zod.z.object({
@@ -17513,244 +17852,6 @@ var networkAccessCapability = {
17513
17852
  }
17514
17853
  };
17515
17854
  /**
17516
- * notification-output — canonical, capability-gated notification delivery.
17517
- *
17518
- * Apprise-derived model (see
17519
- * `docs/superpowers/specs/2026-07-03-notification-output-notifier-matrix.md`):
17520
- * callers emit ONE canonical `Notification`; each provider declares a
17521
- * per-kind capability descriptor (`TargetKind`), and the pure degrade
17522
- * engine (`@camstack/types` `prepareNotification`) transcodes / degrades the
17523
- * message to what the kind supports — callers never special-case a service.
17524
- *
17525
- * DESIGN DECISIONS (locked):
17526
- * - Target CRUD lives on THIS cap (`upsertTarget` / `deleteTarget` /
17527
- * `setTargetEnabled`), each provider persisting via the `settings-store`
17528
- * cap. Rationale: the admin UI needs one uniform surface across the
17529
- * notifiers addon AND the HA addon; the addon-`globalSettingsSchema`-array
17530
- * alternative would fork the UI per addon and cannot host the
17531
- * discovery→adopt flow.
17532
- * - `listTargetKinds` / `listTargets` / `discoverTargets` return arrays →
17533
- * the generated cap-mount auto-`concatCollection`-fans them across every
17534
- * registered provider (notifiers addon + HA addon) so one catalog is
17535
- * routable. `send` / `testTarget` / CRUD route to ONE provider by the
17536
- * `addonId` the generated collection router extracts from the call input.
17537
- * - `Attachment.bytes` is `Uint8Array`. Transport-safe: superjson (the tRPC
17538
- * transformer) + UDS MsgPack both round-trip typed arrays — already used by
17539
- * `storage` / `storage-provider` / `recording` caps over the same path. No
17540
- * base64 fallback needed.
17541
- *
17542
- * TODO (deferred, closed-set change — separate decision): add
17543
- * `providerKind: 'notify'` so notification providers surface on the unified
17544
- * admin "Integrations" page.
17545
- */
17546
- /**
17547
- * Zentik-derived typed-media enum — the superset across every kind. Each
17548
- * adapter picks what it supports and the degrade engine filters the rest.
17549
- */
17550
- var AttachmentMediaTypeSchema = zod.z.enum([
17551
- "image",
17552
- "video",
17553
- "gif",
17554
- "audio",
17555
- "icon"
17556
- ]);
17557
- /**
17558
- * A single attachment. Exactly one of `url` (remote source, most adapters
17559
- * prefer this) or `bytes` (inline source; required for Pushover-style
17560
- * bytes-only kinds) MUST be present — the degrade engine expresses a
17561
- * url→bytes fetch as a `needsFetch` directive the adapter executes.
17562
- */
17563
- var AttachmentSchema = zod.z.object({
17564
- mediaType: AttachmentMediaTypeSchema,
17565
- url: zod.z.string().optional(),
17566
- bytes: zod.z.instanceof(Uint8Array).optional(),
17567
- mime: zod.z.string().optional(),
17568
- name: zod.z.string().optional()
17569
- }).refine((a) => a.url !== void 0 || a.bytes !== void 0, { message: "Attachment requires either `url` or `bytes`" });
17570
- var NotificationFormatSchema = zod.z.enum([
17571
- "text",
17572
- "markdown",
17573
- "html"
17574
- ]);
17575
- /** A single tap-through action button. */
17576
- var NotificationActionSchema = zod.z.object({
17577
- id: zod.z.string(),
17578
- label: zod.z.string(),
17579
- url: zod.z.string().optional()
17580
- });
17581
- /**
17582
- * The canonical notification. `body` is the only hard field (Apprise model).
17583
- * `priority` is a 5-level ORDINAL (1=lowest … 3=normal(default) … 5=urgent),
17584
- * NOT a fixed severity enum — each kind declares its own `caps.levels` and
17585
- * the adapter maps this ordinal onto its native level. `level?` is an
17586
- * optional kind-native level id (`emergency`, `silent`, …) that overrides
17587
- * `priority` for that one target.
17588
- */
17589
- var NotificationSchema = zod.z.object({
17590
- body: zod.z.string(),
17591
- title: zod.z.string().optional(),
17592
- format: NotificationFormatSchema.default("text"),
17593
- priority: zod.z.number().int().min(1).max(5).default(3),
17594
- level: zod.z.string().optional(),
17595
- attachments: zod.z.array(AttachmentSchema).optional(),
17596
- clickUrl: zod.z.string().optional(),
17597
- actions: zod.z.array(NotificationActionSchema).optional(),
17598
- sound: zod.z.string().optional(),
17599
- ttl: zod.z.number().optional(),
17600
- tag: zod.z.string().optional(),
17601
- deviceId: zod.z.number().optional(),
17602
- eventId: zod.z.string().optional(),
17603
- metadata: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
17604
- });
17605
- /** One declared native severity/priority level for a kind. */
17606
- var TargetKindLevelSchema = zod.z.object({
17607
- id: zod.z.string(),
17608
- label: zod.z.string(),
17609
- /** Which canonical priority (1..5) this level maps to. `null` = qualitative-only. */
17610
- ordinal: zod.z.number().int().min(1).max(5).nullable(),
17611
- flags: zod.z.object({
17612
- critical: zod.z.boolean().optional(),
17613
- silent: zod.z.boolean().optional(),
17614
- noPush: zod.z.boolean().optional()
17615
- }).optional(),
17616
- /** e.g. Pushover `emergency` requires `retry` / `expire`. */
17617
- requires: zod.z.array(zod.z.string()).optional(),
17618
- description: zod.z.string().optional()
17619
- });
17620
- /** Attachment capabilities for a kind (drives the degrade engine + test panel). */
17621
- var TargetKindAttachmentsCapsSchema = zod.z.object({
17622
- mediaTypes: zod.z.array(AttachmentMediaTypeSchema),
17623
- mode: zod.z.enum([
17624
- "url",
17625
- "bytes",
17626
- "both"
17627
- ]),
17628
- max: zod.z.number().int().nonnegative(),
17629
- maxBytes: zod.z.number().int().positive().optional()
17630
- });
17631
- /** The full capability block consulted before dispatch. */
17632
- var TargetKindCapsSchema = zod.z.object({
17633
- attachments: TargetKindAttachmentsCapsSchema,
17634
- /** Max action buttons (0 = none). */
17635
- actions: zod.z.number().int().nonnegative(),
17636
- levels: zod.z.array(TargetKindLevelSchema),
17637
- format: zod.z.array(NotificationFormatSchema),
17638
- clickUrl: zod.z.boolean(),
17639
- sound: zod.z.boolean(),
17640
- ttl: zod.z.boolean(),
17641
- bodyMaxLen: zod.z.number().int().positive()
17642
- });
17643
- /**
17644
- * `configSchema` is a `ConfigUISchema` tree passed through to the admin
17645
- * FormBuilder. Stored as `z.unknown()` at the cap seam (mirrors
17646
- * `device-provider.getChildCreationSchema` `CreationSchemaOutputSchema`) —
17647
- * the union is large and not meant for runtime validation here; the exported
17648
- * `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
17649
- */
17650
- var ConfigSchemaPassthrough = zod.z.unknown();
17651
- var TargetKindSchema = zod.z.object({
17652
- kind: zod.z.string(),
17653
- label: zod.z.string(),
17654
- icon: zod.z.string(),
17655
- /** Stamped by each provider so the concat-fanned catalog stays routable. */
17656
- addonId: zod.z.string(),
17657
- /**
17658
- * URL of the kind's bundled BRAND icon, served by the providing addon over
17659
- * its own `addon-routes` surface (`/addon/<addonId>/icons/<kind>`). Absent
17660
- * when the addon bundles no icon for that kind — the client then falls back
17661
- * to a neutral glyph rather than rendering the raw `icon` NAME as text.
17662
- *
17663
- * Root-relative on purpose: it resolves against whatever origin serves a web
17664
- * client, and a native client joins it onto its own hub base.
17665
- *
17666
- * DECLARED here deliberately. It used to travel as an undeclared passthrough
17667
- * field that survived only because the runtime cap-router forwards provider
17668
- * output verbatim — so every consumer had to re-declare it by hand to stop
17669
- * its own Zod parse from stripping it, and the whole arrangement would have
17670
- * broken silently the moment output validation was tightened anywhere.
17671
- */
17672
- iconUrl: zod.z.string().optional(),
17673
- /**
17674
- * Media type of {@link iconUrl} (`image/svg+xml`, `image/png`, …).
17675
- *
17676
- * The server knows this and therefore says it, because the client cannot
17677
- * safely guess: a React-Native client renders SVG and raster through two
17678
- * DIFFERENT components (`react-native-svg` vs `expo-image` — expo-image does
17679
- * not decode SVG on iOS/Android), so without this it silently fell back to a
17680
- * placeholder glyph for every vector icon while the web build looked fine.
17681
- *
17682
- * Absent when {@link iconUrl} is absent, or for a legacy provider that has
17683
- * not been updated — a client that cannot determine the type should prefer
17684
- * its raster path, which is the safe default for an unknown image.
17685
- */
17686
- iconMediaType: zod.z.string().optional(),
17687
- configSchema: ConfigSchemaPassthrough,
17688
- supportsDiscovery: zod.z.boolean(),
17689
- caps: TargetKindCapsSchema
17690
- });
17691
- /**
17692
- * A persisted target. `config` holds secrets; providers REDACT secret fields
17693
- * (return a presence marker only) when serving `listTargets` — never
17694
- * round-trip a stored secret to the UI.
17695
- */
17696
- var TargetSchema = zod.z.object({
17697
- id: zod.z.string(),
17698
- name: zod.z.string(),
17699
- kind: zod.z.string(),
17700
- addonId: zod.z.string(),
17701
- enabled: zod.z.boolean(),
17702
- config: zod.z.record(zod.z.string(), zod.z.unknown())
17703
- });
17704
- /** A discovery-surfaced candidate (config is partial + non-secret). */
17705
- var DiscoveredTargetSchema = zod.z.object({
17706
- kind: zod.z.string(),
17707
- suggestedName: zod.z.string(),
17708
- config: zod.z.record(zod.z.string(), zod.z.unknown())
17709
- });
17710
- /** The degrade engine's report — what was resolved / dropped / degraded. */
17711
- var RenderedAsSchema = zod.z.object({
17712
- level: zod.z.string(),
17713
- format: NotificationFormatSchema,
17714
- attachmentsSent: zod.z.number().int().nonnegative(),
17715
- actionsSent: zod.z.number().int().nonnegative(),
17716
- truncated: zod.z.boolean(),
17717
- dropped: zod.z.array(zod.z.string())
17718
- });
17719
- var SendResultSchema = zod.z.object({
17720
- success: zod.z.boolean(),
17721
- error: zod.z.string().optional(),
17722
- renderedAs: RenderedAsSchema.optional()
17723
- });
17724
- /** Same shape as SendResult — kept as a distinct name for the test panel. */
17725
- var TestResultSchema = SendResultSchema;
17726
- var notificationOutputCapability = {
17727
- name: "notification-output",
17728
- scope: "system",
17729
- mode: "collection",
17730
- methods: {
17731
- listTargetKinds: method(zod.z.object({}), zod.z.array(TargetKindSchema)),
17732
- listTargets: method(zod.z.object({}), zod.z.array(TargetSchema)),
17733
- discoverTargets: method(zod.z.object({
17734
- kind: zod.z.string(),
17735
- config: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
17736
- }), zod.z.array(DiscoveredTargetSchema)),
17737
- send: method(zod.z.object({
17738
- targetId: zod.z.string(),
17739
- notification: NotificationSchema
17740
- }), SendResultSchema, { kind: "mutation" }),
17741
- testTarget: method(zod.z.object({
17742
- targetId: zod.z.string(),
17743
- sample: NotificationSchema.optional()
17744
- }), TestResultSchema, { kind: "mutation" }),
17745
- upsertTarget: method(zod.z.object({ target: TargetSchema }), TargetSchema, { kind: "mutation" }),
17746
- deleteTarget: method(zod.z.object({ targetId: zod.z.string() }), zod.z.void(), { kind: "mutation" }),
17747
- setTargetEnabled: method(zod.z.object({
17748
- targetId: zod.z.string(),
17749
- enabled: zod.z.boolean()
17750
- }), zod.z.void(), { kind: "mutation" })
17751
- }
17752
- };
17753
- /**
17754
17855
  * core-blocks — user-authored TypeScript, stored in the kernel and executed in
17755
17856
  * its own process.
17756
17857
  *
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("./chunk-Cek0wNdY.js");
3
- const require_dist = require("./dist-DBeh_RnY.js");
3
+ const require_dist = require("./dist-CBwOEr6q.js");
4
4
  const require_model_download_service = require("./model-download-service-hf0ookyy.js");
5
5
  const require_manifest_python_deps = require("./manifest-python-deps-BqE5j0-O.js");
6
6
  const require_resource_monitor = require("./resource-monitor-DNNomR-i.js");
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { a as __toCommonJS, i as __require, n as __esmMin, o as __toESM$1, r as __exportAll, t as __commonJSMin$1 } from "./chunk-CNf5ZN-e.mjs";
2
- import { At as readinessKey, B as lifecycleJobSchema, F as isArrayOutputSchema, I as isCollectionArrayMethod, L as isObjectInput, M as extractNestedAddonId, Mt as scopeKey, Ot as parseJsonObject, Pt as EventCategory$1, R as isVoidInput, St as emitDownForOwnedCaps, U as logLevelAtMost, W as looseSchema, X as procedureAuthKey, bt as asString$1, c as METHOD_ACCESS_MAP, dt as DEVICE_STATUS_METHOD, gt as ReadinessTimeoutError, h as addonSettingsCapability, ht as ReadinessRegistry, jt as resolveCapMount, kt as parseJsonUnknown$1, l as RUNTIME_DEFAULTS, lt as DATAPLANE_SECRET_HEADER$1, q as objectInputDeclaresAddonId, st as errMsg$1, t as ALL_CAPABILITY_DEFINITIONS, ut as DEVICE_SETTINGS_CONTRIBUTION_METHODS, vt as asJsonObject$1, wt as expandCapMethods, xt as createEvent, yt as asNumber, z as kebabToCamel } from "./dist-BpVtesRV.mjs";
2
+ import { At as readinessKey, B as lifecycleJobSchema, F as isArrayOutputSchema, I as isCollectionArrayMethod, L as isObjectInput, M as extractNestedAddonId, Mt as scopeKey, Ot as parseJsonObject, Pt as EventCategory$1, R as isVoidInput, St as emitDownForOwnedCaps, U as logLevelAtMost, W as looseSchema, X as procedureAuthKey, bt as asString$1, c as METHOD_ACCESS_MAP, dt as DEVICE_STATUS_METHOD, gt as ReadinessTimeoutError, h as addonSettingsCapability, ht as ReadinessRegistry, jt as resolveCapMount, kt as parseJsonUnknown$1, l as RUNTIME_DEFAULTS, lt as DATAPLANE_SECRET_HEADER$1, q as objectInputDeclaresAddonId, st as errMsg$1, t as ALL_CAPABILITY_DEFINITIONS, ut as DEVICE_SETTINGS_CONTRIBUTION_METHODS, vt as asJsonObject$1, wt as expandCapMethods, xt as createEvent, yt as asNumber, z as kebabToCamel } from "./dist-BZAMwgix.mjs";
3
3
  import { a as downloadModel, c as getModelFilePath, d as contentTypeFor, f as createAuthenticatedFileServer, h as resolveFilePath, i as downloadFile, l as isModelDownloaded, m as parseTokenizedUrl, n as collectModelFiles, o as ensureModel, p as parseRangeHeader, r as deleteModelFromDisk, s as fetchJson, t as ModelDownloadService, u as createFileDataPlaneHandler } from "./model-download-service-Cp9f4dk6.mjs";
4
4
  import { $ as buildNativeCapProxy, A as createHubCapForwardService, B as AGENT_CAP_FWD_ACTION, C as brokerTransportLink, Ct as resolveAddonClass, D as localProviderLink, E as ipcParentLink, F as createUdsLogger, G as callWithServiceDiscovery, H as CapRouteResolver, I as createUdsLoggerWithControl, J as UdsLocalTransportServer, K as createLocalTransport, L as LocalChildClient, M as createUdsEventBridge, N as createUdsEventBus, O as HUB_CAP_FWD_ACTION, P as udsChildLogToWorkerEntry, Q as encodeFrame, R as LocalChildRegistry, S as brokerCallForCap, St as runNpm, T as ipcChildLink, U as CapRouteError, V as AGENT_CAP_FWD_SERVICE, W as classifyCapRoute, X as localEndpointPath, Y as SocketChannel, Z as FrameDecoder, _ as createKernelHwAccel, _t as CapabilityHandle, a as getWorkerDeviceRegistry, b as __resetCapUsageRegistryForTests, bt as installManifestNativeDeps, c as setHubConnected, ct as NATIVE_PROVIDER_SERVICE_INFIX, d as getBrokerEventBus, dt as capBareAction, et as buildUdsNativeCapProxy, f as getMoleculerEventStats, ft as capServiceName, g as AddonDepsManager, gt as DeviceRegistry, h as subscribePassthrough, ht as serializeTypedArrays, i as createUdsAddonContext, it as mountNativeCapService, j as createParentUnownedCallHandler, k as HUB_CAP_FWD_SERVICE, l as EVENT_TOPIC_PREFIX, lt as capActionName, m as setNodeEventInterest, mt as deserializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as createAddonService, p as registerEventBusService, pt as parseCapAction, q as UdsLocalTransportClient, r as createAddonContext, s as getOrInitReadinessRegistryForClient, st as validateProviderRegistrations, t as installManifestPythonDeps, tt as createBrokerDeviceManagerApi, u as clusterEventTopic, ut as capActionSuffix, v as resolveHwAccel, vt as CapabilityUnavailableError, w as buildLinkChain, wt as createAddonDataPlaneFacility, x as getCapUsageRegistry, xt as resolveNpmInvocation, y as CapUsageRegistry, yt as copyBundledNativeModules, z as UDS_NO_ROUTE_PREFIX } from "./manifest-python-deps-Ck4-9K9m.mjs";
5
5
  import { n as getSinglePidStats, t as getPidStats } from "./resource-monitor-BkP504Vq.mjs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/system",
3
- "version": "1.2.42",
3
+ "version": "1.2.44",
4
4
  "description": "Core addon for CamStack — builtins, pipeline, process management, auth, logging, events",
5
5
  "keywords": [
6
6
  "camstack",