@camstack/addon-pipeline 1.2.633 → 1.2.634

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 (36) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/audio-analyzer/index.js +3 -3
  3. package/dist/audio-analyzer/index.mjs +3 -3
  4. package/dist/{custom-model-catalog-BcYQkMoD.mjs → custom-model-catalog-BjkdcgOE.mjs} +2 -2
  5. package/dist/{custom-model-catalog-Bsfg7BkC.js → custom-model-catalog-CgSsz_wK.js} +2 -2
  6. package/dist/detection-pipeline/index.js +4 -4
  7. package/dist/detection-pipeline/index.mjs +4 -4
  8. package/dist/{dist-DQcSGwGp.js → dist-C5sQVajZ.js} +600 -6
  9. package/dist/{dist-rqX8QLAU.mjs → dist-DlB7gVjz.mjs} +600 -6
  10. package/dist/{model-catalogs-BIQmZA1O.js → model-catalogs-D6iqJdhC.js} +1 -1
  11. package/dist/{model-catalogs-C3fsKl2H.mjs → model-catalogs-XdVK-cpH.mjs} +1 -1
  12. package/dist/motion-wasm/index.js +1 -1
  13. package/dist/motion-wasm/index.mjs +1 -1
  14. package/dist/{node-CxeIzhfZ.mjs → node-DI6cJT3H.mjs} +1 -1
  15. package/dist/{node-Bq2OdtOJ.js → node-DqynP4Sn.js} +1 -1
  16. package/dist/pipeline-runner/index.js +3 -3
  17. package/dist/pipeline-runner/index.mjs +3 -3
  18. package/dist/{process-memory-DscuOZuW.js → process-memory-BWsvhswo.js} +1 -1
  19. package/dist/{process-memory-BJ4dGThE.mjs → process-memory-CdsO2dxD.mjs} +1 -1
  20. package/dist/recorder/index.js +8 -2
  21. package/dist/recorder/index.mjs +8 -2
  22. package/dist/{segment-demux-js-CUvevVpm.js → segment-demux-js-CEqPvaCD.js} +1 -1
  23. package/dist/{segment-demux-js-CTN4M0L6.mjs → segment-demux-js-jzhozTBr.mjs} +1 -1
  24. package/dist/stream-broker/_stub.js +2 -2
  25. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-ypdxRUwS.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BfutHWHx.mjs} +2 -2
  26. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DfXSkf61.mjs +26 -0
  27. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CGcEN1m1.mjs +26 -0
  28. package/dist/stream-broker/demux-worker-child.js +1 -1
  29. package/dist/stream-broker/demux-worker-child.mjs +1 -1
  30. package/dist/stream-broker/{hostInit-DskyymXn.mjs → hostInit-oZNKK5YV.mjs} +2 -2
  31. package/dist/stream-broker/index.js +76 -11
  32. package/dist/stream-broker/index.mjs +76 -11
  33. package/dist/stream-broker/remoteEntry.js +1 -1
  34. package/package.json +1 -1
  35. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BOIc62S5.mjs +0 -26
  36. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CY6cGkjo.mjs +0 -26
@@ -5580,7 +5580,7 @@ var ZodIssueCode = {
5580
5580
  var ZodFirstPartyTypeKind;
5581
5581
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5582
5582
  //#endregion
5583
- //#region ../types/dist/sleep-Crlmu_tO.mjs
5583
+ //#region ../types/dist/sleep-DJws6ho7.mjs
5584
5584
  /**
5585
5585
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5586
5586
  * window to float samples (D455).
@@ -9124,6 +9124,7 @@ var CAP_NAMES = Object.freeze([
9124
9124
  "image-settings",
9125
9125
  "integrations",
9126
9126
  "intercom",
9127
+ "ir-transmitter",
9127
9128
  "keychain",
9128
9129
  "keychain-admin",
9129
9130
  "lawn-mower-control",
@@ -9182,6 +9183,7 @@ var CAP_NAMES = Object.freeze([
9182
9183
  "recording-onboard",
9183
9184
  "recording-signal",
9184
9185
  "records",
9186
+ "remote",
9185
9187
  "running-state",
9186
9188
  "scene-monitor",
9187
9189
  "script-runner",
@@ -9205,6 +9207,7 @@ var CAP_NAMES = Object.freeze([
9205
9207
  "system",
9206
9208
  "tamper",
9207
9209
  "temperature-sensor",
9210
+ "template",
9208
9211
  "terminal-session",
9209
9212
  "toast",
9210
9213
  "training",
@@ -10145,6 +10148,11 @@ Object.freeze({
10145
10148
  "standby"
10146
10149
  ]
10147
10150
  },
10151
+ {
10152
+ "path": "stateSource",
10153
+ "valueType": "enum",
10154
+ "enumValues": ["reported", "assumed"]
10155
+ },
10148
10156
  {
10149
10157
  "path": "volumeLevel",
10150
10158
  "valueType": "number"
@@ -10371,6 +10379,11 @@ Object.freeze({
10371
10379
  "path": "batteryPower",
10372
10380
  "valueType": "number"
10373
10381
  },
10382
+ {
10383
+ "path": "powerSource",
10384
+ "valueType": "enum",
10385
+ "enumValues": ["mains", "battery"]
10386
+ },
10374
10387
  {
10375
10388
  "path": "desiccantLeftDays",
10376
10389
  "valueType": "number"
@@ -10415,6 +10428,18 @@ Object.freeze({
10415
10428
  {
10416
10429
  "path": "volume",
10417
10430
  "valueType": "number"
10431
+ },
10432
+ {
10433
+ "path": "lastFeedGrams",
10434
+ "valueType": "number"
10435
+ },
10436
+ {
10437
+ "path": "lastFeedHopper1",
10438
+ "valueType": "number"
10439
+ },
10440
+ {
10441
+ "path": "lastFeedHopper2",
10442
+ "valueType": "number"
10418
10443
  }
10419
10444
  ],
10420
10445
  "power-meter": [
@@ -11106,7 +11131,7 @@ function sleep(ms) {
11106
11131
  return new Promise((resolve) => setTimeout(resolve, Math.max(0, ms)));
11107
11132
  }
11108
11133
  //#endregion
11109
- //#region ../types/dist/err-msg-DIorGYeC.mjs
11134
+ //#region ../types/dist/err-msg-BCdlR2Li.mjs
11110
11135
  var DeviceType = /* @__PURE__ */ function(DeviceType) {
11111
11136
  DeviceType["Camera"] = "camera";
11112
11137
  DeviceType["Hub"] = "hub";
@@ -11452,6 +11477,9 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
11452
11477
  /** Fallback when the notifier service name doesn't match a known
11453
11478
  * pattern. */
11454
11479
  DeviceRole["GenericNotifier"] = "generic-notifier";
11480
+ /** Emits a pulse train (infrared or RF) on request — the `ir-transmitter`
11481
+ * cap. A `DeviceType.Generic` device. */
11482
+ DeviceRole["IrTransmitter"] = "ir-transmitter";
11455
11483
  return DeviceRole;
11456
11484
  }({});
11457
11485
  /**
@@ -11465,7 +11493,7 @@ function errMsg(err) {
11465
11493
  return String(err);
11466
11494
  }
11467
11495
  //#endregion
11468
- //#region ../types/dist/composition-DwA0uVW5.mjs
11496
+ //#region ../types/dist/composition-bIBW5_13.mjs
11469
11497
  var AUDIO_ENCODER_BY_CODEC = {
11470
11498
  opus: "libopus",
11471
11499
  aac: "aac",
@@ -11923,6 +11951,15 @@ function audioPlanFromEncodeProfile(audio) {
11923
11951
  * plane. Width / height / fps / bitrate in the profile are a downstream BUDGET,
11924
11952
  * not a forced rescale.
11925
11953
  */
11954
+ /**
11955
+ * Probe bound for an input that is one of OUR OWN RTSP restreams. Not zero: a
11956
+ * zero-length probe makes ffmpeg trust the SDP completely, and a restream that
11957
+ * announces a track it never sends would leave the mapping wrong unnoticed.
11958
+ */
11959
+ var RESTREAM_INPUT_PROBE = {
11960
+ analyzeDurationUs: 2e5,
11961
+ probeSizeBytes: 64 * 1024
11962
+ };
11926
11963
  function invocationFromEncodeProfile(input) {
11927
11964
  const v = input.profile.video;
11928
11965
  const shouldCopy = v.codec === "copy" || input.forceReencode !== true && v.codec === input.sourceCodec;
@@ -11960,6 +11997,8 @@ function invocationFromEncodeProfile(input) {
11960
11997
  url: input.sourceUrl,
11961
11998
  rtspTransport: "tcp",
11962
11999
  fflags: ["+discardcorrupt"],
12000
+ analyzeDurationUs: RESTREAM_INPUT_PROBE.analyzeDurationUs,
12001
+ probeSizeBytes: RESTREAM_INPUT_PROBE.probeSizeBytes,
11963
12002
  ...input.profile.inputArgs?.length ? { extraArgs: input.profile.inputArgs } : {}
11964
12003
  },
11965
12004
  video,
@@ -19408,9 +19447,21 @@ var AlertSeveritySchema = _enum([
19408
19447
  "error",
19409
19448
  "critical"
19410
19449
  ]);
19450
+ /**
19451
+ * An action that RUNS something instead of going somewhere: the admin UI calls
19452
+ * the addon's custom action (`addons.custom`) with exactly these fields. The
19453
+ * producer owns the meaning; the UI knows nothing about the addon or the kind.
19454
+ */
19455
+ var AlertActionInvokeSchema = object({
19456
+ addonId: string().min(1),
19457
+ action: string().min(1),
19458
+ input: record(string(), unknown()).optional()
19459
+ });
19460
+ /** An action has `href` (a link) OR `invoke` (a button that runs a custom action). */
19411
19461
  var AlertActionSchema = object({
19412
19462
  label: string(),
19413
19463
  href: string().optional(),
19464
+ invoke: AlertActionInvokeSchema.optional(),
19414
19465
  /**
19415
19466
  * How `href` is followed. Absent / `app`: an admin-ui route (client-side).
19416
19467
  * `server`: a route the HUB serves (an addon HTTP route such as an OAuth
@@ -62122,11 +62173,373 @@ DeviceType.Light, method(object({
62122
62173
  level: number().min(0).max(100),
62123
62174
  lastChangedAt: number()
62124
62175
  });
62176
+ /**
62177
+ * The role vocabulary of a remote (D963): what a button MEANS, independent of
62178
+ * how it is wired. A layout template places buttons by role; a device binds a
62179
+ * role to an action; an exporter asks for a role by name. Roles are shared so
62180
+ * one layout fits every appliance and one voice command fits every binding.
62181
+ *
62182
+ * A role outside this list is `custom:<key>` — the operator's own button (a
62183
+ * SmartIR source, a channel preset). The key is a lowercase slug.
62184
+ */
62185
+ var REMOTE_KNOWN_ROLES = [
62186
+ "power",
62187
+ "power_on",
62188
+ "power_off",
62189
+ "volume_up",
62190
+ "volume_down",
62191
+ "mute",
62192
+ "channel_up",
62193
+ "channel_down",
62194
+ "up",
62195
+ "down",
62196
+ "left",
62197
+ "right",
62198
+ "ok",
62199
+ "back",
62200
+ "home",
62201
+ "menu",
62202
+ "info",
62203
+ "guide",
62204
+ "exit",
62205
+ "input",
62206
+ "play",
62207
+ "pause",
62208
+ "play_pause",
62209
+ "stop",
62210
+ "next",
62211
+ "previous",
62212
+ "fast_forward",
62213
+ "rewind",
62214
+ "digit_0",
62215
+ "digit_1",
62216
+ "digit_2",
62217
+ "digit_3",
62218
+ "digit_4",
62219
+ "digit_5",
62220
+ "digit_6",
62221
+ "digit_7",
62222
+ "digit_8",
62223
+ "digit_9"
62224
+ ];
62225
+ var CUSTOM_KEY_RE = /^[a-z0-9][a-z0-9_]{0,47}$/;
62226
+ var KNOWN_ROLES = new Set(REMOTE_KNOWN_ROLES);
62227
+ function isRemoteKnownRole(value) {
62228
+ return KNOWN_ROLES.has(value);
62229
+ }
62230
+ function isRemoteCustomKey(key) {
62231
+ return CUSTOM_KEY_RE.test(key);
62232
+ }
62233
+ /** The key of a `custom:<key>` role, or null for any other string. */
62234
+ function customKeyOfRole(role) {
62235
+ if (!role.startsWith("custom:")) return null;
62236
+ const key = role.slice(7);
62237
+ return isRemoteCustomKey(key) ? key : null;
62238
+ }
62239
+ function isRemoteRole(value) {
62240
+ return isRemoteKnownRole(value) || customKeyOfRole(value) !== null;
62241
+ }
62242
+ var RemoteRoleSchema = string().refine(isRemoteRole, { message: "a role is one of the known roles or custom:<key> (lowercase letters, digits, _)" });
62243
+ var RemoteBindingSchema = object({ action: AutomationCapStepSchema.extend({ deviceId: number().int().nonnegative() }) });
62244
+ var RemoteCustomButtonSchema = object({
62245
+ /** The slug after `custom:` in the role. */
62246
+ key: string().refine(isRemoteCustomKey, { message: "a lowercase slug" }),
62247
+ /** What the operator calls it, and what a voice command may name. */
62248
+ name: string().min(1).max(60)
62249
+ });
62250
+ var RemotePowerModeSchema = _enum(["toggle", "discrete"]);
62251
+ var RemoteConfigSchema = object({
62252
+ layoutTemplateId: string().min(1).nullable(),
62253
+ /**
62254
+ * The transmitter device new bindings and an import send through. A binding
62255
+ * names its own device, so one command may override it.
62256
+ */
62257
+ defaultTransmitterId: number().int().nonnegative().nullable().default(null),
62258
+ /** Keyed by role. A role with no entry falls back to the native cap. */
62259
+ bindings: record(string(), RemoteBindingSchema),
62260
+ customButtons: array(RemoteCustomButtonSchema).max(100),
62261
+ power: object({ mode: RemotePowerModeSchema })
62262
+ }).superRefine((config, ctx) => {
62263
+ const roles = Object.keys(config.bindings);
62264
+ if (roles.length > 200) ctx.addIssue({
62265
+ code: "custom",
62266
+ message: "too many bindings",
62267
+ path: ["bindings"]
62268
+ });
62269
+ for (const role of roles) if (!isRemoteRole(role)) ctx.addIssue({
62270
+ code: "custom",
62271
+ message: `"${role}" is not a role`,
62272
+ path: ["bindings", role]
62273
+ });
62274
+ const keys = /* @__PURE__ */ new Set();
62275
+ config.customButtons.forEach((button, index) => {
62276
+ if (keys.has(button.key)) ctx.addIssue({
62277
+ code: "custom",
62278
+ message: `custom button "${button.key}" is listed twice`,
62279
+ path: [
62280
+ "customButtons",
62281
+ index,
62282
+ "key"
62283
+ ]
62284
+ });
62285
+ keys.add(button.key);
62286
+ });
62287
+ for (const role of roles) {
62288
+ const key = customKeyOfRole(role);
62289
+ if (key !== null && !keys.has(key)) ctx.addIssue({
62290
+ code: "custom",
62291
+ message: `${role} is bound but has no entry in customButtons`,
62292
+ path: ["bindings", role]
62293
+ });
62294
+ }
62295
+ });
62296
+ object({
62297
+ power: object({
62298
+ state: _enum(["on", "off"]),
62299
+ at: number()
62300
+ }).nullable(),
62301
+ muted: object({
62302
+ value: boolean(),
62303
+ at: number()
62304
+ }).nullable()
62305
+ });
62306
+ var RemoteLayoutButtonSchema = object({
62307
+ id: string().min(1).max(40),
62308
+ /** 0-based grid position. */
62309
+ row: number().int().min(0).max(24),
62310
+ col: number().int().min(0).max(24),
62311
+ rowSpan: number().int().min(1).max(24),
62312
+ colSpan: number().int().min(1).max(24),
62313
+ icon: string().min(1).max(60).optional(),
62314
+ label: string().min(1).max(40).optional(),
62315
+ role: RemoteRoleSchema
62316
+ });
62317
+ object({
62318
+ columns: number().int().min(1).max(24),
62319
+ rows: number().int().min(1).max(24),
62320
+ buttons: array(RemoteLayoutButtonSchema).max(200)
62321
+ }).superRefine((grid, ctx) => {
62322
+ const ids = /* @__PURE__ */ new Set();
62323
+ const taken = /* @__PURE__ */ new Map();
62324
+ grid.buttons.forEach((button, index) => {
62325
+ if (ids.has(button.id)) ctx.addIssue({
62326
+ code: "custom",
62327
+ message: `button id "${button.id}" is used twice`,
62328
+ path: [
62329
+ "buttons",
62330
+ index,
62331
+ "id"
62332
+ ]
62333
+ });
62334
+ ids.add(button.id);
62335
+ if (button.row + button.rowSpan > grid.rows || button.col + button.colSpan > grid.columns) {
62336
+ ctx.addIssue({
62337
+ code: "custom",
62338
+ message: `button "${button.id}" leaves the grid`,
62339
+ path: ["buttons", index]
62340
+ });
62341
+ return;
62342
+ }
62343
+ for (let r = button.row; r < button.row + button.rowSpan; r += 1) for (let c = button.col; c < button.col + button.colSpan; c += 1) {
62344
+ const cell = `${r}:${c}`;
62345
+ const other = taken.get(cell);
62346
+ if (other !== void 0) {
62347
+ ctx.addIssue({
62348
+ code: "custom",
62349
+ message: `buttons "${other}" and "${button.id}" overlap`,
62350
+ path: ["buttons", index]
62351
+ });
62352
+ return;
62353
+ }
62354
+ taken.set(cell, button.id);
62355
+ }
62356
+ });
62357
+ });
62358
+ var RemoteBoundCommandSchema = object({
62359
+ role: RemoteRoleSchema,
62360
+ /** The operator's name for a custom button; absent for a known role. */
62361
+ label: string().optional(),
62362
+ custom: boolean()
62363
+ });
62364
+ var RemoteCommandListSchema = object({
62365
+ layoutTemplateId: string().nullable(),
62366
+ power: object({ mode: RemotePowerModeSchema }),
62367
+ /** Only the roles that are BOUND — the ones a press can reach. */
62368
+ commands: array(RemoteBoundCommandSchema)
62369
+ });
62370
+ var RemoteRefusalReasonSchema = _enum([
62371
+ "no-remote",
62372
+ "unbound-role",
62373
+ "action-failed"
62374
+ ]);
62375
+ var RemoteSendResultSchema = discriminatedUnion("status", [
62376
+ object({
62377
+ status: literal("sent"),
62378
+ /** How many times the action ran. */
62379
+ sends: number().int().min(1)
62380
+ }),
62381
+ object({
62382
+ status: literal("skipped"),
62383
+ reason: literal("already-in-state")
62384
+ }),
62385
+ object({
62386
+ status: literal("refused"),
62387
+ reason: RemoteRefusalReasonSchema,
62388
+ detail: string().optional()
62389
+ })
62390
+ ]);
62391
+ var RemoteMediaCommandSchema = _enum([
62392
+ "play",
62393
+ "pause",
62394
+ "stop",
62395
+ "next",
62396
+ "previous",
62397
+ "setMute",
62398
+ "selectSource"
62399
+ ]);
62400
+ /** A send result, or `not-routed`: the role is not bound, so the native cap answers. */
62401
+ var RemoteMediaCommandResultSchema = discriminatedUnion("status", [...RemoteSendResultSchema.options, object({ status: literal("not-routed") })]);
62402
+ var RemoteSetConfigResultSchema = discriminatedUnion("status", [object({ status: literal("saved") }), object({
62403
+ status: literal("refused"),
62404
+ reason: _enum(["unknown-template", "not-a-media-player"]),
62405
+ detail: string()
62406
+ })]);
62407
+ var deviceInput = object({ deviceId: number().int().nonnegative() });
62408
+ DeviceType.MediaPlayer;
62409
+ method(deviceInput, RemoteConfigSchema, { auth: "admin" }), method(deviceInput.extend({ config: RemoteConfigSchema }), RemoteSetConfigResultSchema, {
62410
+ kind: "mutation",
62411
+ auth: "admin"
62412
+ }), method(deviceInput, RemoteCommandListSchema, { auth: "protected" }), method(deviceInput.extend({
62413
+ role: RemoteRoleSchema,
62414
+ /** Sends in a row (volume steps). */
62415
+ repeat: number().int().min(1).max(50).default(1)
62416
+ }), RemoteSendResultSchema, {
62417
+ kind: "mutation",
62418
+ auth: "protected"
62419
+ }), method(deviceInput.extend({
62420
+ command: RemoteMediaCommandSchema,
62421
+ muted: boolean().optional(),
62422
+ source: string().optional(),
62423
+ repeat: number().int().min(1).max(50).default(1)
62424
+ }), RemoteMediaCommandResultSchema, {
62425
+ kind: "mutation",
62426
+ auth: "protected"
62427
+ });
62428
+ var TemplateKindSchema = _enum(["remote"]);
62429
+ /**
62430
+ * template — the generic store of reusable, named operator data (D963). A
62431
+ * record is `{ id, kind, name, payload }`; the kinds (today only `remote`, the
62432
+ * button grid of a remote) and the schema each payload must satisfy are
62433
+ * declared by the system in `template-kinds.ts`. Nothing here is specific to a
62434
+ * kind: the engine validates a payload against its kind's schema and, on a
62435
+ * delete, asks the kind's owner whether anything still points at the record.
62436
+ *
62437
+ * Every refusal is a typed result — a UI says "unknown kind" or names the
62438
+ * devices that still use a template, without parsing text.
62439
+ */
62440
+ var TemplateRecordSchema = object({
62441
+ id: string().min(1),
62442
+ kind: TemplateKindSchema,
62443
+ name: string().min(1).max(120),
62444
+ /** Shaped by the kind; `checkTemplatePayload(kind, payload)` reads it. */
62445
+ payload: unknown(),
62446
+ createdAt: number(),
62447
+ updatedAt: number()
62448
+ });
62449
+ var TemplateWriteResultSchema = discriminatedUnion("status", [object({
62450
+ status: literal("saved"),
62451
+ template: TemplateRecordSchema
62452
+ }), object({
62453
+ status: literal("refused"),
62454
+ reason: _enum(["invalid-payload", "not-found"]),
62455
+ detail: string()
62456
+ })]);
62457
+ /** A device still pointing at a template. */
62458
+ var TemplateUserSchema = object({
62459
+ deviceId: number().int().nonnegative(),
62460
+ name: string()
62461
+ });
62462
+ var TemplateDeleteResultSchema = discriminatedUnion("status", [
62463
+ object({ status: literal("deleted") }),
62464
+ object({ status: literal("not-found") }),
62465
+ object({
62466
+ status: literal("in-use"),
62467
+ devices: array(TemplateUserSchema).min(1)
62468
+ })
62469
+ ]);
62470
+ method(object({ kind: TemplateKindSchema.optional() }), array(TemplateRecordSchema), { auth: "protected" }), method(object({ id: string().min(1) }), TemplateRecordSchema.nullable(), { auth: "protected" }), method(object({
62471
+ kind: TemplateKindSchema,
62472
+ name: string().min(1).max(120),
62473
+ payload: unknown()
62474
+ }), TemplateWriteResultSchema, {
62475
+ kind: "mutation",
62476
+ auth: "admin"
62477
+ }), method(object({
62478
+ id: string().min(1),
62479
+ name: string().min(1).max(120).optional(),
62480
+ payload: unknown().optional()
62481
+ }), TemplateWriteResultSchema, {
62482
+ kind: "mutation",
62483
+ auth: "admin"
62484
+ }), method(object({ id: string().min(1) }), TemplateDeleteResultSchema, {
62485
+ kind: "mutation",
62486
+ auth: "admin"
62487
+ });
62125
62488
  DeviceType.Button, method(object({ deviceId: number().int().nonnegative() }), _void(), {
62126
62489
  kind: "mutation",
62127
62490
  auth: "protected"
62128
62491
  });
62129
62492
  /**
62493
+ * A pulse train in signed microseconds: mark (+) first, then space (-), strictly
62494
+ * alternating, no zeros, 2..1024 entries.
62495
+ */
62496
+ var IrTimingsSchema = array(number().int()).min(2).max(1024).superRefine((timings, ctx) => {
62497
+ timings.forEach((value, index) => {
62498
+ const expectMark = index % 2 === 0;
62499
+ if (value === 0 || value > 0 !== expectMark) ctx.addIssue({
62500
+ code: "custom",
62501
+ message: `timing ${index} must be a non-zero ${expectMark ? "mark (positive)" : "space (negative)"}`,
62502
+ path: [index]
62503
+ });
62504
+ });
62505
+ });
62506
+ /** Per-command transmit options. Every key is optional; a transmitter applies what it can. */
62507
+ var TransmitSettingsSchema = object({
62508
+ carrierHz: number().int().positive().optional(),
62509
+ dutyCyclePercent: number().int().min(1).max(100).optional(),
62510
+ repeat: number().int().min(0).max(20).optional(),
62511
+ repeatDelayMs: number().int().min(0).optional()
62512
+ });
62513
+ /** The setting keys a transmitter may declare as settable (`getInfo.settable`). */
62514
+ var TransmitSettingKeySchema = _enum([
62515
+ "carrierHz",
62516
+ "dutyCyclePercent",
62517
+ "repeat",
62518
+ "repeatDelayMs"
62519
+ ]);
62520
+ var IrMediumSchema = _enum(["ir", "rf"]);
62521
+ var IrSendResultSchema = object({
62522
+ ok: literal(true),
62523
+ /** Settings the transmitter could not apply; the train was still sent. */
62524
+ ignoredSettings: array(string())
62525
+ });
62526
+ var IrTransmitterInfoSchema = object({
62527
+ media: array(IrMediumSchema),
62528
+ settable: array(TransmitSettingKeySchema),
62529
+ maxTimings: number().int().positive()
62530
+ });
62531
+ DeviceType.Generic, method(object({
62532
+ deviceId: number().int().nonnegative(),
62533
+ timings: IrTimingsSchema,
62534
+ settings: TransmitSettingsSchema.optional()
62535
+ }), IrSendResultSchema, {
62536
+ kind: "mutation",
62537
+ auth: "protected"
62538
+ }), method(object({ deviceId: number().int().nonnegative() }), IrTransmitterInfoSchema, {
62539
+ kind: "query",
62540
+ auth: "protected"
62541
+ });
62542
+ /**
62130
62543
  * `calendar-source` — collection cap exposing per-provider calendars and
62131
62544
  * their events. Every addon that contributes calendars (Home Assistant,
62132
62545
  * a future Google Calendar addon, …) registers a provider here. The hub
@@ -64821,9 +65234,35 @@ var MediaInfoSchema = object({
64821
65234
  /** Optional cover-art / thumbnail URL. */
64822
65235
  imageUrl: string().optional()
64823
65236
  });
65237
+ /**
65238
+ * Where `state`, `volumeLevel`, `isMuted` and `source` come from. `reported`:
65239
+ * the device said so. `assumed`: the driver has no feedback (infrared) and
65240
+ * tracks what it last SENT; it moves only after a send was accepted, and a
65241
+ * human at the real remote makes it wrong. A UI shows an assumed value as a
65242
+ * guess, never as a reading.
65243
+ */
65244
+ var MediaPlayerStateSourceSchema = _enum(["reported", "assumed"]);
65245
+ /** The fields of a media-player status a driver can only guess. */
65246
+ var MediaPlayerAssumedFieldSchema = _enum([
65247
+ "state",
65248
+ "volumeLevel",
65249
+ "isMuted",
65250
+ "source"
65251
+ ]);
64824
65252
  object({
64825
65253
  /** Playback lifecycle state. */
64826
65254
  state: MediaPlayerStateSchema,
65255
+ /**
65256
+ * Whether the state fields are readings or the driver's own bookkeeping.
65257
+ * A slice written before this field existed parses as `reported`.
65258
+ */
65259
+ stateSource: MediaPlayerStateSourceSchema.default("reported"),
65260
+ /**
65261
+ * Which fields are the driver's own guess. `stateSource` is `assumed` when
65262
+ * this is not empty; a field not listed here is a reading even then (power
65263
+ * from a running-state source, mute guessed from the last send).
65264
+ */
65265
+ assumedFields: array(MediaPlayerAssumedFieldSchema).default([]),
64827
65266
  /** Volume as 0..100 inclusive. Null when the device has no volume
64828
65267
  * surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
64829
65268
  volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
@@ -66229,9 +66668,14 @@ object({
66229
66668
  * (`device_class: problem`, on = low). True when the tank reports empty,
66230
66669
  * or, on a dual-hopper model, when EITHER hopper is empty. */
66231
66670
  lowFood: boolean(),
66232
- /** Battery charge 0..100 (%). Null on mains-powered models or when the
66233
- * device has no battery reading. */
66671
+ /** Battery charge 0..100 (%). On a feeder running on `mains` this is the
66672
+ * BACKUP battery's charge, not the power source. Null when the device has
66673
+ * no battery reading. */
66234
66674
  batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
66675
+ /** What the feeder is powered from right now: `mains` (plugged in, the
66676
+ * battery is only a backup) or `battery`. Null when the device does not
66677
+ * report it. */
66678
+ powerSource: _enum(["mains", "battery"]).nullable(),
66235
66679
  /**
66236
66680
  * Desiccant life remaining, stored in seconds (duration base, D944).
66237
66681
  * Providers convert from the days the feeder reports. Null when the
@@ -66259,6 +66703,14 @@ object({
66259
66703
  feedSound: boolean(),
66260
66704
  /** Speaker / prompt volume level (device-scaled integer). */
66261
66705
  volume: number().meta(readingMeta("none")),
66706
+ /** Portion (grams) of the last manual feed sent from a single-hopper
66707
+ * stepper — the default the next manual feed starts from. Persisted per
66708
+ * device by the provider; null until a manual feed has been sent. */
66709
+ lastFeedGrams: gramsPortion.nullable(),
66710
+ /** Hopper-1 portion of the last manual feed (dual-hopper); null until sent. */
66711
+ lastFeedHopper1: gramsPortion.nullable(),
66712
+ /** Hopper-2 portion of the last manual feed (dual-hopper); null until sent. */
66713
+ lastFeedHopper2: gramsPortion.nullable(),
66262
66714
  /** Ms epoch when the slice was last refreshed from the cloud. */
66263
66715
  lastFetchedAt: number()
66264
66716
  });
@@ -71424,6 +71876,14 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
71424
71876
  kind: "mutation",
71425
71877
  auth: "admin"
71426
71878
  });
71879
+ discriminatedUnion("kind", [object({
71880
+ kind: literal("raw"),
71881
+ timings: array(number().int()),
71882
+ settings: TransmitSettingsSchema.optional()
71883
+ }), object({
71884
+ kind: literal("pronto"),
71885
+ code: string()
71886
+ })]);
71427
71887
  /**
71428
71888
  * Which of OUR object detections a clip window holds — the ONE overlap rule
71429
71889
  * and the ONE label ranking, for every clip source (D923).
@@ -71466,7 +71926,7 @@ function dominantClipLabels(events) {
71466
71926
  }
71467
71927
  DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
71468
71928
  SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
71469
- DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Camera, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
71929
+ DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Camera, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
71470
71930
  String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
71471
71931
  DeviceRole.BinarySensor, DeviceRole.MotionSensor;
71472
71932
  new Set(CAP_NAMES);
@@ -75089,6 +75549,20 @@ Object.freeze({
75089
75549
  access: "create",
75090
75550
  role: "viewer"
75091
75551
  },
75552
+ "irTransmitter.getInfo": {
75553
+ capName: "ir-transmitter",
75554
+ capScope: "device",
75555
+ addonId: null,
75556
+ access: "view",
75557
+ role: "viewer"
75558
+ },
75559
+ "irTransmitter.send": {
75560
+ capName: "ir-transmitter",
75561
+ capScope: "device",
75562
+ addonId: null,
75563
+ access: "create",
75564
+ role: "viewer"
75565
+ },
75092
75566
  "keychain.delete": {
75093
75567
  capName: "keychain",
75094
75568
  capScope: "system",
@@ -79212,6 +79686,41 @@ Object.freeze({
79212
79686
  access: "create",
79213
79687
  role: "admin"
79214
79688
  },
79689
+ "remote.getConfig": {
79690
+ capName: "remote",
79691
+ capScope: "system",
79692
+ addonId: null,
79693
+ access: "view",
79694
+ role: "admin"
79695
+ },
79696
+ "remote.listCommands": {
79697
+ capName: "remote",
79698
+ capScope: "system",
79699
+ addonId: null,
79700
+ access: "view",
79701
+ role: "admin"
79702
+ },
79703
+ "remote.sendCommand": {
79704
+ capName: "remote",
79705
+ capScope: "system",
79706
+ addonId: null,
79707
+ access: "create",
79708
+ role: "admin"
79709
+ },
79710
+ "remote.sendMediaCommand": {
79711
+ capName: "remote",
79712
+ capScope: "system",
79713
+ addonId: null,
79714
+ access: "create",
79715
+ role: "admin"
79716
+ },
79717
+ "remote.setConfig": {
79718
+ capName: "remote",
79719
+ capScope: "system",
79720
+ addonId: null,
79721
+ access: "create",
79722
+ role: "admin"
79723
+ },
79215
79724
  "runningState.getStatus": {
79216
79725
  capName: "running-state",
79217
79726
  capScope: "device",
@@ -80402,6 +80911,41 @@ Object.freeze({
80402
80911
  access: "view",
80403
80912
  role: "viewer"
80404
80913
  },
80914
+ "template.create": {
80915
+ capName: "template",
80916
+ capScope: "system",
80917
+ addonId: null,
80918
+ access: "create",
80919
+ role: "admin"
80920
+ },
80921
+ "template.delete": {
80922
+ capName: "template",
80923
+ capScope: "system",
80924
+ addonId: null,
80925
+ access: "delete",
80926
+ role: "admin"
80927
+ },
80928
+ "template.get": {
80929
+ capName: "template",
80930
+ capScope: "system",
80931
+ addonId: null,
80932
+ access: "view",
80933
+ role: "admin"
80934
+ },
80935
+ "template.list": {
80936
+ capName: "template",
80937
+ capScope: "system",
80938
+ addonId: null,
80939
+ access: "view",
80940
+ role: "admin"
80941
+ },
80942
+ "template.update": {
80943
+ capName: "template",
80944
+ capScope: "system",
80945
+ addonId: null,
80946
+ access: "create",
80947
+ role: "admin"
80948
+ },
80405
80949
  "terminalSession.adoptLegacyMonitor": {
80406
80950
  capName: "terminal-session",
80407
80951
  capScope: "system",
@@ -82712,6 +83256,11 @@ var ACTUATOR_CAP_VOCABULARY = {
82712
83256
  icon: "circle-dot"
82713
83257
  }]
82714
83258
  },
83259
+ "ir-transmitter": {
83260
+ scope: "device",
83261
+ noun: t("IR / RF transmitter", "Trasmettitore IR / RF"),
83262
+ notOperatorFacing: { send: "a raw pulse train is not something an operator composes in an automation; the remote that owns the command table sends it" }
83263
+ },
82715
83264
  control: {
82716
83265
  scope: "device",
82717
83266
  noun: t("Control", "Controllo"),
@@ -85228,6 +85777,7 @@ var SYSTEM_CAP_VOCABULARY = {
85228
85777
  "recording-archive": system(STORAGE),
85229
85778
  "recording-export": system("recording exports — requested from the timeline, not an automation step"),
85230
85779
  records: system(INTERNAL),
85780
+ remote: system("the per-device remote setup — authored in the Customize remote editor, sent through the remote UI"),
85231
85781
  "server-management": system(CLUSTER),
85232
85782
  "settings-store": system(INTERNAL),
85233
85783
  "smtp-provider": system(INTERNAL),
@@ -85240,6 +85790,7 @@ var SYSTEM_CAP_VOCABULARY = {
85240
85790
  "storage-provider": system(STORAGE),
85241
85791
  "stream-broker": system(PIPELINE),
85242
85792
  system: system(CLUSTER),
85793
+ template: system("operator-authored templates — edited in their own editor, never actuated"),
85243
85794
  "terminal-session": system(CLUSTER),
85244
85795
  toast: system(UI_PLUMBING),
85245
85796
  training: system(ML),
@@ -86431,6 +86982,16 @@ Object.freeze({
86431
86982
  form: "single",
86432
86983
  optional: false
86433
86984
  }],
86985
+ "irTransmitter.getInfo": [{
86986
+ name: "deviceId",
86987
+ form: "single",
86988
+ optional: false
86989
+ }],
86990
+ "irTransmitter.send": [{
86991
+ name: "deviceId",
86992
+ form: "single",
86993
+ optional: false
86994
+ }],
86434
86995
  "keychain.deleteDeviceScope": [{
86435
86996
  name: "deviceId",
86436
86997
  form: "single",
@@ -87656,6 +88217,31 @@ Object.freeze({
87656
88217
  form: "single",
87657
88218
  optional: true
87658
88219
  }],
88220
+ "remote.getConfig": [{
88221
+ name: "deviceId",
88222
+ form: "single",
88223
+ optional: false
88224
+ }],
88225
+ "remote.listCommands": [{
88226
+ name: "deviceId",
88227
+ form: "single",
88228
+ optional: false
88229
+ }],
88230
+ "remote.sendCommand": [{
88231
+ name: "deviceId",
88232
+ form: "single",
88233
+ optional: false
88234
+ }],
88235
+ "remote.sendMediaCommand": [{
88236
+ name: "deviceId",
88237
+ form: "single",
88238
+ optional: false
88239
+ }],
88240
+ "remote.setConfig": [{
88241
+ name: "deviceId",
88242
+ form: "single",
88243
+ optional: false
88244
+ }],
87659
88245
  "runningState.getStatus": [{
87660
88246
  name: "deviceId",
87661
88247
  form: "single",
@@ -91197,6 +91783,14 @@ function armRemovalReconcile(opts) {
91197
91783
  timer.unref?.();
91198
91784
  return () => clearInterval(timer);
91199
91785
  }
91786
+ object({
91787
+ manufacturer: string().optional(),
91788
+ supportedModels: array(string()).optional(),
91789
+ supportedController: string().optional(),
91790
+ commandsEncoding: string(),
91791
+ delay: number().nonnegative().optional(),
91792
+ commands: record(string(), unknown())
91793
+ });
91200
91794
  //#endregion
91201
91795
  Object.defineProperty(exports, "APPEARANCE_BLOCKS", {
91202
91796
  enumerable: true,