@camstack/addon-import-alexa 0.2.155 → 0.2.157

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 (20) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/{MotionZonesSettings-BAg3ARov.mjs → MotionZonesSettings-Z-NRG681.mjs} +2 -2
  3. package/dist/{PrivacyMaskSettings-C0cYJFNC.mjs → PrivacyMaskSettings-DiS2hPpi.mjs} +4 -4
  4. package/dist/{SceneMonitorEditor-BL8xJKp6.mjs → SceneMonitorEditor-BYYK_XwY.mjs} +3 -3
  5. package/dist/_stub.js +610 -638
  6. package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_import_alexa_page-DIPd9Gv5.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_import_alexa_page-B4G6E4Vs.mjs} +3 -3
  7. package/dist/_virtual_mf___mfe_internal__addon_import_alexa_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DCV5s91A.mjs +26 -0
  8. package/dist/addon-import-alexa.css +1 -1
  9. package/dist/addon.js +757 -97
  10. package/dist/addon.mjs +757 -97
  11. package/dist/{hostInit-M4qqEmdk.mjs → hostInit-DWBMKrvf.mjs} +2 -2
  12. package/dist/{player-overlays-COWyo9kN.mjs → player-overlays-5MrLqX2i.mjs} +1 -1
  13. package/dist/remoteEntry.js +1 -1
  14. package/dist/{responsive-CLpz8rKp.mjs → responsive-CsfyZVWS.mjs} +1 -1
  15. package/dist/{scene-monitor-copy-ciy3zaiU.mjs → scene-monitor-copy-DOuMmSwJ.mjs} +1 -1
  16. package/dist/{square-YnF15tkM.mjs → square-BGn7yRva.mjs} +1 -1
  17. package/dist/{trash-2-dnzK3zvI.mjs → trash-2-BiBTPv8Y.mjs} +1 -1
  18. package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_import_alexa_page__remoteEntry_js-FpscgjXK.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_import_alexa_page__remoteEntry_js-BniKFfAU.mjs} +1 -1
  19. package/package.json +1 -1
  20. package/dist/_virtual_mf___mfe_internal__addon_import_alexa_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BU5ExEvB.mjs +0 -26
package/dist/addon.js CHANGED
@@ -34,8 +34,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
34
34
  var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
35
35
  //#endregion
36
36
  let node_crypto = require("node:crypto");
37
- let node_os = require("node:os");
38
- node_os = __toESM(node_os, 1);
39
37
  let node_fs = require("node:fs");
40
38
  node_fs = __toESM(node_fs, 1);
41
39
  let node_path = require("node:path");
@@ -43,10 +41,12 @@ let node_path$1 = __toESM(node_path, 1);
43
41
  node_path = __toESM(node_path);
44
42
  let node_fs_promises = require("node:fs/promises");
45
43
  node_fs_promises = __toESM(node_fs_promises, 1);
44
+ let node_os = require("node:os");
45
+ node_os = __toESM(node_os, 1);
46
46
  let node_child_process = require("node:child_process");
47
47
  require("node:zlib");
48
48
  let node_url = require("node:url");
49
- //#region ../types/dist/event-category-CT-hz5Rb.mjs
49
+ //#region ../types/dist/event-category-hdMR7CTW.mjs
50
50
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
51
51
  EventCategory["SystemBoot"] = "system.boot";
52
52
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -811,6 +811,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
811
811
  */
812
812
  EventCategory["AccessoriesChanged"] = "accessories.onAccessoriesChanged";
813
813
  /**
814
+ * An action run started or ended. Emitted by the `actions` surface.
815
+ * Payload: `ActionRunChanged` (`{ actionId, runId, isRunning, outcome?, lastRunAt, lastError }`).
816
+ */
817
+ EventCategory["ActionsRunChanged"] = "actions.onRunChanged";
818
+ /**
814
819
  * Progress update from a running model conversion job.
815
820
  * Payload: `{ kind: 'model-convert', phase, sessionId?, pct?, detail? }`.
816
821
  * Emitted by `addon-model-studio` on the converting node.
@@ -5622,7 +5627,7 @@ var ZodIssueCode = {
5622
5627
  var ZodFirstPartyTypeKind;
5623
5628
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5624
5629
  //#endregion
5625
- //#region ../types/dist/sleep--jXS9hWo.mjs
5630
+ //#region ../types/dist/sleep-BHjNez61.mjs
5626
5631
  /**
5627
5632
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5628
5633
  * window to float samples (D455).
@@ -8952,6 +8957,8 @@ Object.freeze({ "doorbell": "lastPressedAt" });
8952
8957
  /** Every capability name, so addon code can check a name without the schema graph. */
8953
8958
  var CAP_NAMES = Object.freeze([
8954
8959
  "accessories",
8960
+ "action-source",
8961
+ "actions",
8955
8962
  "addon-pages",
8956
8963
  "addon-pages-source",
8957
8964
  "addon-routes",
@@ -10254,6 +10261,18 @@ Object.freeze({
10254
10261
  "path": "foodLevel",
10255
10262
  "valueType": "number"
10256
10263
  },
10264
+ {
10265
+ "path": "bowlFood",
10266
+ "valueType": "number"
10267
+ },
10268
+ {
10269
+ "path": "eating",
10270
+ "valueType": "boolean"
10271
+ },
10272
+ {
10273
+ "path": "supportsMarkRefilled",
10274
+ "valueType": "boolean"
10275
+ },
10257
10276
  {
10258
10277
  "path": "food1",
10259
10278
  "valueType": "number"
@@ -15927,7 +15946,23 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
15927
15946
  kind: literal("schedule"),
15928
15947
  cron: string().min(1).max(120)
15929
15948
  }),
15930
- object({ kind: literal("manual") })
15949
+ object({ kind: literal("manual") }),
15950
+ object({
15951
+ kind: literal("detection"),
15952
+ /** Class names. A macro class (`animal`, `vehicle`, `person`, `package`)
15953
+ * matches every raw class that maps to it; any other name matches
15954
+ * exactly. */
15955
+ classes: array(string().min(1)).min(1),
15956
+ deviceIds: array(number().int().nonnegative()).min(1),
15957
+ /** The track must have visited at least one of these zones. */
15958
+ zones: array(string().min(1)).min(1).optional(),
15959
+ /** Best-so-far confidence the track must reach. */
15960
+ minScore: number().min(0).max(1).optional()
15961
+ }),
15962
+ object({
15963
+ kind: literal("interval"),
15964
+ minutes: number().int().min(1).max(1440)
15965
+ })
15931
15966
  ]);
15932
15967
  /**
15933
15968
  * One action step.
@@ -15947,28 +15982,47 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
15947
15982
  * is called. The runner still receives a number and is untouched; the
15948
15983
  * resolution is the recipe's job, not the runner's.
15949
15984
  */
15985
+ var AutomationWaitStepSchema = object({
15986
+ kind: literal("wait"),
15987
+ seconds: number().min(0).max(300)
15988
+ });
15989
+ var AutomationCapStepSchema = object({
15990
+ kind: literal("cap"),
15991
+ /**
15992
+ * One device, several same-family devices (locks / climate family / …),
15993
+ * or `{ $var }` for the device that triggered the run. An array is
15994
+ * fan-out at codegen — each id gets the same cap.method call.
15995
+ */
15996
+ deviceId: union([
15997
+ number().int(),
15998
+ array(number().int()).min(1),
15999
+ object({ $var: string().min(1) })
16000
+ ]),
16001
+ cap: string().min(1),
16002
+ method: string().min(1),
16003
+ /** Values may carry `{{vars.x}}` slots, or be exactly `{ $var: 'name' }`, which
16004
+ * SUBSTITUTE and do not evaluate (§3.2.3). Anything beyond substitution is
16005
+ * the expression leaf. */
16006
+ args: record(string(), unknown()).optional()
16007
+ });
16008
+ /**
16009
+ * The steps an internal Action may contain: cap and wait, and nothing that can
16010
+ * call back into an Action — so an Action can never reach itself (no cycles).
16011
+ */
16012
+ var ActionStepSchema = discriminatedUnion("kind", [AutomationWaitStepSchema, AutomationCapStepSchema]);
15950
16013
  var AutomationActionSchema = discriminatedUnion("kind", [
16014
+ AutomationWaitStepSchema,
16015
+ AutomationCapStepSchema,
15951
16016
  object({
15952
- kind: literal("wait"),
15953
- seconds: number().min(0).max(300)
15954
- }),
15955
- object({
15956
- kind: literal("cap"),
15957
- /**
15958
- * One device, several same-family devices (locks / climate family / …),
15959
- * or `{ $var }` for the device that triggered the run. An array is
15960
- * fan-out at codegen — each id gets the same cap.method call.
15961
- */
15962
- deviceId: union([
15963
- number().int(),
15964
- array(number().int()).min(1),
15965
- object({ $var: string().min(1) })
15966
- ]),
15967
- cap: string().min(1),
15968
- method: string().min(1),
15969
- /** Values may carry `{{vars.x}}` slots, which SUBSTITUTE and do not
15970
- * evaluate (§3.2.3). Anything beyond substitution is the expression leaf. */
15971
- args: record(string(), unknown()).optional()
16017
+ kind: literal("action"),
16018
+ /** An entry of the `actions` surface (`internal:<uuid>` or `<addonId>:<localId>`). */
16019
+ actionId: string().min(1),
16020
+ /** Values for the action's declared variables; the others take their default. */
16021
+ variables: record(string(), union([
16022
+ string(),
16023
+ number(),
16024
+ boolean()
16025
+ ])).optional()
15972
16026
  }),
15973
16027
  object({
15974
16028
  kind: literal("code"),
@@ -15977,10 +16031,356 @@ var AutomationActionSchema = discriminatedUnion("kind", [
15977
16031
  code: string().min(1).max(2e4)
15978
16032
  })
15979
16033
  ]);
16034
+ /**
16035
+ * How a trigger that arrives while the automation is busy (or cooling down) is
16036
+ * handled. One of the automation's execution modes, never a property of its
16037
+ * actions. Absent means `single`.
16038
+ *
16039
+ * - `single` — drop the trigger while a run is in progress (traced + logged).
16040
+ * - `restart` — abort the run in progress (at its next step boundary), start fresh.
16041
+ * - `queued` — queue up to `max` triggers, drop the rest (traced).
16042
+ * - `parallel` — up to `max` runs at once, drop the rest (traced).
16043
+ * - `cooldown` — `single`, and no new run until `minutes` after the last run
16044
+ * STARTED; persisted across a restart. A manual trigger bypasses only this
16045
+ * wait, never the single/queued limits.
16046
+ */
16047
+ var AutomationRunModeSchema = discriminatedUnion("mode", [
16048
+ object({ mode: literal("single") }),
16049
+ object({ mode: literal("restart") }),
16050
+ object({
16051
+ mode: literal("queued"),
16052
+ max: number().int().min(1).max(10)
16053
+ }),
16054
+ object({
16055
+ mode: literal("parallel"),
16056
+ max: number().int().min(1).max(10)
16057
+ }),
16058
+ object({
16059
+ mode: literal("cooldown"),
16060
+ minutes: number().int().min(1).max(1440)
16061
+ })
16062
+ ]);
15980
16063
  var AutomationRecipeSchema = object({
15981
16064
  triggers: array(AutomationTriggerSchema),
15982
16065
  conditions: AutomationConditionSchema.optional(),
15983
- actions: array(AutomationActionSchema)
16066
+ actions: array(AutomationActionSchema),
16067
+ runMode: AutomationRunModeSchema.optional(),
16068
+ /** How many run traces the automation keeps (default {@link DEFAULT_TRACE_KEEP}). */
16069
+ keepTraces: number().int().min(1).max(100).optional()
16070
+ });
16071
+ new Set([
16072
+ {
16073
+ id: "person",
16074
+ name: "Person"
16075
+ },
16076
+ {
16077
+ id: "vehicle",
16078
+ name: "Vehicle"
16079
+ },
16080
+ {
16081
+ id: "animal",
16082
+ name: "Animal"
16083
+ },
16084
+ {
16085
+ id: "package",
16086
+ name: "Package"
16087
+ }
16088
+ ].map((l) => l.id));
16089
+ var COCO_TO_MACRO = {
16090
+ mapping: {
16091
+ person: "person",
16092
+ bicycle: "vehicle",
16093
+ car: "vehicle",
16094
+ motorcycle: "vehicle",
16095
+ airplane: "vehicle",
16096
+ bus: "vehicle",
16097
+ train: "vehicle",
16098
+ truck: "vehicle",
16099
+ boat: "vehicle",
16100
+ bird: "animal",
16101
+ cat: "animal",
16102
+ dog: "animal",
16103
+ horse: "animal",
16104
+ sheep: "animal",
16105
+ cow: "animal",
16106
+ elephant: "animal",
16107
+ bear: "animal",
16108
+ zebra: "animal",
16109
+ giraffe: "animal",
16110
+ suitcase: "package",
16111
+ backpack: "package",
16112
+ handbag: "package"
16113
+ },
16114
+ preserveOriginal: false
16115
+ };
16116
+ new Set(Object.values(COCO_TO_MACRO.mapping));
16117
+ /**
16118
+ * Run traces — what an automation (or, later, an Action run) DID, node by node,
16119
+ * so the editor can paint every block green or red with its reason.
16120
+ *
16121
+ * A trace is data, not a log: it covers the WHOLE tree — the trigger stage,
16122
+ * every condition node (containers and leaves, including the ones a
16123
+ * short-circuit never reached), the run-mode verdict and every action step —
16124
+ * each addressed by a stable path (`conditions.0.1`, `actions.2`, or `steps.N`
16125
+ * for an Action run). Skipped
16126
+ * evaluations are traced too, and identical consecutive skips collapse into a
16127
+ * repeat count so a trigger that fails every 5 minutes cannot flush real runs.
16128
+ *
16129
+ * {@link AutomationStepTraceSchema} is deliberately free of automation
16130
+ * vocabulary so an Action run records the same step shape.
16131
+ */
16132
+ /** A value a trace may show: JSON primitives and short lists, nothing deeper. */
16133
+ var TraceValueSchema = union([
16134
+ string(),
16135
+ number(),
16136
+ boolean(),
16137
+ _null(),
16138
+ array(union([string(), number()]))
16139
+ ]);
16140
+ var AutomationRunOutcomeSchema = _enum([
16141
+ "ran",
16142
+ "skipped-trigger",
16143
+ "skipped-conditions",
16144
+ "skipped-cooldown",
16145
+ "skipped-overlap",
16146
+ "failed",
16147
+ "aborted"
16148
+ ]);
16149
+ /** `not-evaluated` = a short-circuit never reached the node. */
16150
+ var TraceNodeOutcomeSchema = _enum([
16151
+ "pass",
16152
+ "fail",
16153
+ "not-evaluated"
16154
+ ]);
16155
+ var AutomationTriggerTraceSchema = object({
16156
+ kind: string().min(1),
16157
+ outcome: _enum(["pass", "fail"]),
16158
+ /** Why an event was rejected ("class person not in [dog]") or what fired. */
16159
+ reason: string(),
16160
+ /** deviceId, className, trackId, score … — only what the trigger exposes. */
16161
+ vars: record(string(), TraceValueSchema)
16162
+ });
16163
+ var AutomationConditionTraceNodeSchema = object({
16164
+ /** `conditions` for the root, `conditions.<i>` for its i-th child, … */
16165
+ path: string().min(1),
16166
+ kind: _enum([
16167
+ "all",
16168
+ "any",
16169
+ "not",
16170
+ "condition",
16171
+ "expression"
16172
+ ]),
16173
+ outcome: TraceNodeOutcomeSchema,
16174
+ reason: string(),
16175
+ deviceId: number().int().optional(),
16176
+ cap: string().optional(),
16177
+ fieldPath: string().optional(),
16178
+ operator: string().optional(),
16179
+ expected: TraceValueSchema.optional(),
16180
+ /** What the mirror held; `null` when it held nothing (unknown). */
16181
+ observed: TraceValueSchema.optional()
16182
+ });
16183
+ var AutomationRunVerdictSchema = object({
16184
+ mode: AutomationRunModeSchema,
16185
+ decision: _enum([
16186
+ "run",
16187
+ "queued",
16188
+ "restart",
16189
+ "drop",
16190
+ "cooldown",
16191
+ "bypass"
16192
+ ]),
16193
+ reason: string()
16194
+ });
16195
+ /** One executed (or not-run) step — shared by automations and Action runs. */
16196
+ var AutomationStepTraceSchema = object({
16197
+ /** `actions.<i>` */
16198
+ path: string().min(1),
16199
+ kind: string().min(1),
16200
+ cap: string().optional(),
16201
+ method: string().optional(),
16202
+ deviceId: number().int().optional(),
16203
+ startedAt: number().optional(),
16204
+ endedAt: number().optional(),
16205
+ outcome: _enum([
16206
+ "ok",
16207
+ "error",
16208
+ "not-run"
16209
+ ]),
16210
+ message: string().optional()
16211
+ });
16212
+ var AutomationRunTraceSchema = object({
16213
+ runId: string().min(1),
16214
+ startedAt: number(),
16215
+ endedAt: number(),
16216
+ trigger: AutomationTriggerTraceSchema,
16217
+ conditions: array(AutomationConditionTraceNodeSchema),
16218
+ verdict: AutomationRunVerdictSchema.optional(),
16219
+ steps: array(AutomationStepTraceSchema),
16220
+ outcome: AutomationRunOutcomeSchema,
16221
+ /** How many identical consecutive skips this trace stands for (>= 1). */
16222
+ repeat: number().int().min(1),
16223
+ /** When the latest of those repeats happened. */
16224
+ lastAt: number()
16225
+ });
16226
+ /**
16227
+ * What the hub's `runs` ledger holds for one owner (`automation:<blockId>` or
16228
+ * `action:<actionId>`): the cooldown stamp and the trace ring.
16229
+ */
16230
+ var AutomationStateDocSchema = object({
16231
+ version: literal(1),
16232
+ lastRunStartedAt: number().nullable(),
16233
+ traces: array(AutomationRunTraceSchema)
16234
+ });
16235
+ /**
16236
+ * Actions — named, runnable things an operator (or an automation) can start,
16237
+ * declared as LIST ENTRIES, never as devices.
16238
+ *
16239
+ * An entry is either **internal** (a short list of cap/wait steps kept in the
16240
+ * hub's `actions` record kind) or declared by an addon through the
16241
+ * `action-source` collection (a Home Assistant script, a scene …). The one
16242
+ * surface the UI and automations talk to is the `actions` cap; it keeps no
16243
+ * catalog of its own (D3) — every `list` asks the providers live.
16244
+ *
16245
+ * This file is the data half: the entry schema, the variables an entry may
16246
+ * declare, and the pure resolution of the values a run was given. It holds no
16247
+ * runtime.
16248
+ */
16249
+ /** What a variable's value is. `select` takes one of `options`. */
16250
+ var ActionVariableTypeSchema = _enum([
16251
+ "string",
16252
+ "number",
16253
+ "boolean",
16254
+ "select"
16255
+ ]);
16256
+ var ACTION_VARIABLE_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
16257
+ var ActionVariableValueSchema = union([
16258
+ string(),
16259
+ number(),
16260
+ boolean()
16261
+ ]);
16262
+ /**
16263
+ * One declared variable. Steps reference it as `{ $var: 'name' }` (the whole
16264
+ * value) or `{{vars.name}}` (inside a string) in their args.
16265
+ */
16266
+ var ActionVariableSchema = object({
16267
+ name: string().regex(ACTION_VARIABLE_NAME_RE),
16268
+ label: string().min(1).max(120).optional(),
16269
+ type: ActionVariableTypeSchema,
16270
+ required: boolean().optional(),
16271
+ default: ActionVariableValueSchema.optional(),
16272
+ /** The allowed values of a `select`. */
16273
+ options: array(string().min(1)).min(1).optional()
16274
+ }).superRefine((v, ctx) => {
16275
+ if (v.type === "select" && v.options === void 0) ctx.addIssue({
16276
+ code: "custom",
16277
+ message: "a select variable needs options",
16278
+ path: ["options"]
16279
+ });
16280
+ if (v.default !== void 0 && variableValueError(v, v.default) !== null) ctx.addIssue({
16281
+ code: "custom",
16282
+ message: variableValueError(v, v.default) ?? "invalid default",
16283
+ path: ["default"]
16284
+ });
16285
+ });
16286
+ /** Why `value` is not a legal value for the variable, or null when it is. */
16287
+ function variableValueError(variable, value) {
16288
+ switch (variable.type) {
16289
+ case "string": return typeof value === "string" ? null : `variable "${variable.name}" must be a string`;
16290
+ case "number": return typeof value === "number" && Number.isFinite(value) ? null : `variable "${variable.name}" must be a number`;
16291
+ case "boolean": return typeof value === "boolean" ? null : `variable "${variable.name}" must be true or false`;
16292
+ case "select": return typeof value === "string" && (variable.options ?? []).includes(value) ? null : `variable "${variable.name}" must be one of ${(variable.options ?? []).join(", ")}`;
16293
+ }
16294
+ }
16295
+ var ActionSourceKindSchema = _enum(["internal", "addon"]);
16296
+ function isInternalActionId(actionId) {
16297
+ return actionId.startsWith("internal:") && actionId.length > 9;
16298
+ }
16299
+ /** The addon behind a `<addonId>:<localId>` id, or null for anything else (internal included). */
16300
+ function addonIdOfActionId(actionId) {
16301
+ if (isInternalActionId(actionId)) return null;
16302
+ const at = actionId.indexOf(":");
16303
+ return at > 0 && at < actionId.length - 1 ? actionId.slice(0, at) : null;
16304
+ }
16305
+ var ActionStatusSchema = object({
16306
+ isRunning: boolean(),
16307
+ /** Ms epoch the latest run STARTED; null when it never ran. */
16308
+ lastRunAt: number().nullable(),
16309
+ /** The latest run's failure; null on success or when it never ran. */
16310
+ lastError: string().nullable()
16311
+ });
16312
+ var ActionEntrySchema = object({
16313
+ /** `internal:<uuid>` or `<addonId>:<localId>`. */
16314
+ id: string().min(3),
16315
+ name: string().min(1).max(120),
16316
+ /** The addon that declared it; `core-blocks` for an internal one. */
16317
+ addonId: string().min(1),
16318
+ source: ActionSourceKindSchema,
16319
+ /** An addon-declared entry is edited where it was declared. */
16320
+ readOnly: boolean(),
16321
+ /** Internal only: cap and wait steps. No action-in-action, so no cycles. */
16322
+ steps: array(ActionStepSchema).min(1).max(50).optional(),
16323
+ variables: array(ActionVariableSchema).max(20).optional(),
16324
+ status: ActionStatusSchema
16325
+ }).superRefine((entry, ctx) => {
16326
+ if (entry.source === "internal") {
16327
+ if (!isInternalActionId(entry.id)) ctx.addIssue({
16328
+ code: "custom",
16329
+ message: "an internal action id is internal:<uuid>",
16330
+ path: ["id"]
16331
+ });
16332
+ return;
16333
+ }
16334
+ if (entry.steps !== void 0) ctx.addIssue({
16335
+ code: "custom",
16336
+ message: "only an internal action carries steps",
16337
+ path: ["steps"]
16338
+ });
16339
+ if (!entry.readOnly) ctx.addIssue({
16340
+ code: "custom",
16341
+ message: "an addon action is read-only here",
16342
+ path: ["readOnly"]
16343
+ });
16344
+ if (addonIdOfActionId(entry.id) === null) ctx.addIssue({
16345
+ code: "custom",
16346
+ message: "an addon action id is <addonId>:<localId>",
16347
+ path: ["id"]
16348
+ });
16349
+ });
16350
+ /** What an operator writes for an internal action. */
16351
+ var ActionInputSchema = object({
16352
+ name: string().min(1).max(120),
16353
+ steps: array(ActionStepSchema).min(1).max(50),
16354
+ variables: array(ActionVariableSchema).max(20).optional()
16355
+ });
16356
+ /** Who started a run. Absent = the operator pressed it. */
16357
+ var ActionRunOriginSchema = object({
16358
+ /** The automation block whose step started it. */
16359
+ blockId: string().min(1).optional() });
16360
+ /** `started` = the caller did not ask to wait. */
16361
+ var ActionRunOutcomeSchema = union([AutomationRunOutcomeSchema, literal("started")]);
16362
+ var ActionRunResultSchema = object({
16363
+ runId: string().min(1),
16364
+ outcome: ActionRunOutcomeSchema,
16365
+ /** Why it did not run, or what failed. */
16366
+ message: string().optional()
16367
+ });
16368
+ _enum([
16369
+ "not-found",
16370
+ "read-only",
16371
+ "invalid-variables",
16372
+ "invalid-steps",
16373
+ "not-linked",
16374
+ "busy"
16375
+ ]);
16376
+ object({
16377
+ actionId: string(),
16378
+ runId: string(),
16379
+ isRunning: boolean(),
16380
+ /** Set when the run ended. */
16381
+ outcome: AutomationRunOutcomeSchema.optional(),
16382
+ lastRunAt: number().nullable(),
16383
+ lastError: string().nullable()
15984
16384
  });
15985
16385
  /**
15986
16386
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
@@ -19715,7 +20115,18 @@ method(object({}), object({ blocks: array(CoreBlockSchema) }), { auth: "admin" }
19715
20115
  kind: "mutation",
19716
20116
  auth: "admin",
19717
20117
  access: "view"
19718
- });
20118
+ }), method(object({
20119
+ blockId: string().min(1),
20120
+ trace: AutomationRunTraceSchema.optional(),
20121
+ runStartedAt: number().optional(),
20122
+ keepTraces: number().int().min(1).max(100).optional()
20123
+ }), _void(), {
20124
+ kind: "mutation",
20125
+ auth: "admin"
20126
+ }), method(object({ blockId: string().min(1) }), AutomationStateDocSchema, { auth: "admin" }), method(object({ blockId: string().min(1) }), object({
20127
+ traces: array(AutomationRunTraceSchema),
20128
+ lastError: string().nullable()
20129
+ }), { auth: "admin" });
19719
20130
  /**
19720
20131
  * `custom-model-registry` — collection cap exposing operator-registered
19721
20132
  * custom detection models. Each provider (today: `addon-model-studio`)
@@ -45039,51 +45450,6 @@ var notificationOutputCapability = {
45039
45450
  })
45040
45451
  }
45041
45452
  };
45042
- new Set([
45043
- {
45044
- id: "person",
45045
- name: "Person"
45046
- },
45047
- {
45048
- id: "vehicle",
45049
- name: "Vehicle"
45050
- },
45051
- {
45052
- id: "animal",
45053
- name: "Animal"
45054
- },
45055
- {
45056
- id: "package",
45057
- name: "Package"
45058
- }
45059
- ].map((l) => l.id));
45060
- var COCO_TO_MACRO = {
45061
- mapping: {
45062
- person: "person",
45063
- bicycle: "vehicle",
45064
- car: "vehicle",
45065
- motorcycle: "vehicle",
45066
- airplane: "vehicle",
45067
- bus: "vehicle",
45068
- train: "vehicle",
45069
- truck: "vehicle",
45070
- boat: "vehicle",
45071
- bird: "animal",
45072
- cat: "animal",
45073
- dog: "animal",
45074
- horse: "animal",
45075
- sheep: "animal",
45076
- cow: "animal",
45077
- elephant: "animal",
45078
- bear: "animal",
45079
- zebra: "animal",
45080
- giraffe: "animal",
45081
- suitcase: "package",
45082
- backpack: "package",
45083
- handbag: "package"
45084
- },
45085
- preserveOriginal: false
45086
- };
45087
45453
  var AUDIO_MACRO_LABELS = [
45088
45454
  {
45089
45455
  id: "speech",
@@ -57889,6 +58255,84 @@ var audioMetricsCapability = {
57889
58255
  */
57890
58256
  history: "none"
57891
58257
  };
58258
+ method(object({}), array(ActionEntrySchema), { auth: "admin" }), method(object({
58259
+ actionId: string().min(1),
58260
+ variables: record(string(), ActionVariableValueSchema).optional()
58261
+ }), _void(), {
58262
+ kind: "mutation",
58263
+ auth: "admin"
58264
+ }), method(object({ actionId: string().min(1) }), _void(), {
58265
+ kind: "mutation",
58266
+ auth: "admin"
58267
+ });
58268
+ /**
58269
+ * actions — the ONE surface for runnable actions, for the UI and for
58270
+ * automations. Provided by the core-blocks builtin on the hub.
58271
+ *
58272
+ * An action is a LIST ENTRY, not a device (D883): either internal (cap and wait
58273
+ * steps, kept in the hub's `actions` record kind) or declared by an addon over
58274
+ * `action-source`. `list` asks every `action-source` provider LIVE and overlays
58275
+ * the run status from the hub's `runs` ledger; there is no catalog here to
58276
+ * drift (D3).
58277
+ *
58278
+ * **Permissions follow the camera, as linked devices do.** An action is linked
58279
+ * to cameras by the operator (`setLinks`, D356: nothing links itself). A
58280
+ * non-admin may `get` / `run` an action only through a camera they may see that
58281
+ * links it: they name the camera (`deviceId`, a top-level field so the scope
58282
+ * gate sees it) and the provider refuses an action that camera does not link.
58283
+ * An admin, and an in-process caller (an automation block), may run any action.
58284
+ * Every refusal is typed (`[not-linked] …`) and logged.
58285
+ *
58286
+ * A second `run` of an action that is already running is REFUSED — traced and
58287
+ * logged — never queued.
58288
+ */
58289
+ var ActionIdInput = object({ actionId: string().min(1) });
58290
+ var ActionLinksSchema = object({
58291
+ deviceId: number().int().nonnegative(),
58292
+ actionIds: array(string().min(1)).max(100)
58293
+ });
58294
+ method(object({}), array(ActionEntrySchema), { auth: "admin" }), method(object({
58295
+ actionId: string().min(1),
58296
+ deviceId: number().int().nonnegative().optional()
58297
+ }), object({ action: ActionEntrySchema.nullable() }), {
58298
+ role: "viewer",
58299
+ auth: "protected",
58300
+ kind: "query",
58301
+ caller: "required"
58302
+ }), method(object({
58303
+ actionId: string().min(1),
58304
+ variables: record(string(), ActionVariableValueSchema).optional(),
58305
+ wait: boolean().optional(),
58306
+ origin: ActionRunOriginSchema.optional(),
58307
+ deviceId: number().int().nonnegative().optional()
58308
+ }), ActionRunResultSchema, {
58309
+ role: "viewer",
58310
+ auth: "protected",
58311
+ kind: "mutation",
58312
+ caller: "required"
58313
+ }), method(ActionIdInput, _void(), {
58314
+ kind: "mutation",
58315
+ auth: "admin"
58316
+ }), method(ActionIdInput, object({ traces: array(AutomationRunTraceSchema) }), { auth: "admin" }), method(object({ action: ActionInputSchema }), object({ action: ActionEntrySchema }), {
58317
+ kind: "mutation",
58318
+ auth: "admin"
58319
+ }), method(object({
58320
+ actionId: string().min(1),
58321
+ action: ActionInputSchema.partial()
58322
+ }), object({ action: ActionEntrySchema }), {
58323
+ kind: "mutation",
58324
+ auth: "admin"
58325
+ }), method(ActionIdInput, _void(), {
58326
+ kind: "mutation",
58327
+ auth: "admin"
58328
+ }), method(object({ deviceId: number().int().nonnegative() }), array(ActionEntrySchema), {
58329
+ role: "viewer",
58330
+ auth: "protected",
58331
+ kind: "query"
58332
+ }), method(object({ deviceId: number().int().nonnegative() }), ActionLinksSchema, { auth: "admin" }), method(ActionLinksSchema, ActionLinksSchema, {
58333
+ kind: "mutation",
58334
+ auth: "admin"
58335
+ });
57892
58336
  /**
57893
58337
  * Automation-control cap. Models HA `automation.*` entities on
57894
58338
  * `DeviceType.Automation`. An automation is a trigger+condition+
@@ -64351,10 +64795,20 @@ var PetFeederDeviceStatusSchema = _enum([
64351
64795
  ]);
64352
64796
  var gramsPortion = number().int().min(4).max(200);
64353
64797
  var PetFeederStatusSchema = object({
64354
- /** Food currently in the bowl (grams). Null when the device has not
64355
- * reported a reading yet. On dual-hopper models this is the combined
64356
- * bowl reading; per-hopper levels live in `food1`/`food2`. */
64798
+ /** Food in the TANK (hopper), as the feeder's own sensor reports it
64799
+ * (`state.food`). A coarse level code, not grams — `0` is empty. The
64800
+ * amount in the bowl is `bowlFood`. On dual-hopper models this is the
64801
+ * combined reading; per-hopper levels live in `food1`/`food2`. Null when
64802
+ * the device has not reported yet. */
64357
64803
  foodLevel: number().nullable().meta(readingMeta("none")),
64804
+ /** Food in the BOWL as the feeder reports it (`state.bowl`), in the
64805
+ * feeder's own units. Null when the model reports none. */
64806
+ bowlFood: number().nullable().meta(readingMeta("none")),
64807
+ /** True while the pet is eating (`state.eating`). */
64808
+ eating: boolean(),
64809
+ /** Whether `markFoodReplenished` does anything on this model. When false
64810
+ * the client must not offer it. */
64811
+ supportsMarkRefilled: boolean(),
64358
64812
  /** Hopper-1 food level (grams) on dual-hopper feeders; null on
64359
64813
  * single-hopper models. */
64360
64814
  food1: number().nullable().meta(readingMeta("none")),
@@ -64362,8 +64816,8 @@ var PetFeederStatusSchema = object({
64362
64816
  * single-hopper models. */
64363
64817
  food2: number().nullable().meta(readingMeta("none")),
64364
64818
  /** Derived low-food flag — mirrors the HA `food_level` binary_sensor
64365
- * (`device_class: problem`, on = low). True when the bowl is empty /
64366
- * below the feeder's low threshold. */
64819
+ * (`device_class: problem`, on = low). True when the tank reports empty,
64820
+ * or, on a dual-hopper model, when EITHER hopper is empty. */
64367
64821
  lowFood: boolean(),
64368
64822
  /** Battery charge 0..100 (%). Null on mains-powered models or when the
64369
64823
  * device has no battery reading. */
@@ -64431,7 +64885,9 @@ var petFeederCapability = {
64431
64885
  kind: "mutation",
64432
64886
  auth: "protected"
64433
64887
  }),
64434
- /** Mark a hopper as refilled (D4H/D4S/D4SH). */
64888
+ /** Tell the PetKit cloud a hopper was refilled so it stops its low-food
64889
+ * reminders (D4H/D4S/D4SH only — see `supportsMarkRefilled`). It does not
64890
+ * change any sensor reading. */
64435
64891
  markFoodReplenished: method(object({ deviceId: number().int().nonnegative() }), _void(), {
64436
64892
  kind: "mutation",
64437
64893
  auth: "protected"
@@ -64504,6 +64960,7 @@ var petFeederCapability = {
64504
64960
  */
64505
64961
  history: { fields: {
64506
64962
  foodLevel: { kind: "gauge" },
64963
+ bowlFood: { kind: "gauge" },
64507
64964
  food1: { kind: "gauge" },
64508
64965
  food2: { kind: "gauge" },
64509
64966
  batteryPower: {
@@ -72059,6 +72516,104 @@ Object.freeze({
72059
72516
  access: "create",
72060
72517
  role: "admin"
72061
72518
  },
72519
+ "actions.create": {
72520
+ capName: "actions",
72521
+ capScope: "system",
72522
+ addonId: null,
72523
+ access: "create",
72524
+ role: "admin"
72525
+ },
72526
+ "actions.delete": {
72527
+ capName: "actions",
72528
+ capScope: "system",
72529
+ addonId: null,
72530
+ access: "delete",
72531
+ role: "admin"
72532
+ },
72533
+ "actions.get": {
72534
+ capName: "actions",
72535
+ capScope: "system",
72536
+ addonId: null,
72537
+ access: "view",
72538
+ role: "viewer"
72539
+ },
72540
+ "actions.getLinks": {
72541
+ capName: "actions",
72542
+ capScope: "system",
72543
+ addonId: null,
72544
+ access: "view",
72545
+ role: "admin"
72546
+ },
72547
+ "actions.getTraces": {
72548
+ capName: "actions",
72549
+ capScope: "system",
72550
+ addonId: null,
72551
+ access: "view",
72552
+ role: "admin"
72553
+ },
72554
+ "actions.list": {
72555
+ capName: "actions",
72556
+ capScope: "system",
72557
+ addonId: null,
72558
+ access: "view",
72559
+ role: "admin"
72560
+ },
72561
+ "actions.listForCamera": {
72562
+ capName: "actions",
72563
+ capScope: "system",
72564
+ addonId: null,
72565
+ access: "view",
72566
+ role: "viewer"
72567
+ },
72568
+ "actions.run": {
72569
+ capName: "actions",
72570
+ capScope: "system",
72571
+ addonId: null,
72572
+ access: "create",
72573
+ role: "viewer"
72574
+ },
72575
+ "actions.setLinks": {
72576
+ capName: "actions",
72577
+ capScope: "system",
72578
+ addonId: null,
72579
+ access: "create",
72580
+ role: "admin"
72581
+ },
72582
+ "actions.stop": {
72583
+ capName: "actions",
72584
+ capScope: "system",
72585
+ addonId: null,
72586
+ access: "create",
72587
+ role: "admin"
72588
+ },
72589
+ "actions.update": {
72590
+ capName: "actions",
72591
+ capScope: "system",
72592
+ addonId: null,
72593
+ access: "create",
72594
+ role: "admin"
72595
+ },
72596
+ "actionSource.listActions": {
72597
+ capName: "action-source",
72598
+ capScope: "system",
72599
+ addonId: null,
72600
+ access: "view",
72601
+ role: "admin"
72602
+ },
72603
+ "actionSource.runAction": {
72604
+ capName: "action-source",
72605
+ capScope: "system",
72606
+ addonId: null,
72607
+ access: "create",
72608
+ role: "admin"
72609
+ },
72610
+ "actionSource.stopAction": {
72611
+ capName: "action-source",
72612
+ capScope: "system",
72613
+ addonId: null,
72614
+ access: "create",
72615
+ role: "admin"
72616
+ },
72062
72617
  "addonPages.listPages": {
72063
72618
  capName: "addon-pages",
72064
72619
  capScope: "system",
@@ -73340,6 +73895,13 @@ Object.freeze({
73340
73895
  access: "view",
73341
73896
  role: "admin"
73342
73897
  },
73898
+ "coreBlocks.getAutomationRunState": {
73899
+ capName: "core-blocks",
73900
+ capScope: "system",
73901
+ addonId: null,
73902
+ access: "view",
73903
+ role: "admin"
73904
+ },
73343
73905
  "coreBlocks.getBlockSettings": {
73344
73906
  capName: "core-blocks",
73345
73907
  capScope: "system",
@@ -73361,6 +73923,13 @@ Object.freeze({
73361
73923
  access: "view",
73362
73924
  role: "admin"
73363
73925
  },
73926
+ "coreBlocks.getTraces": {
73927
+ capName: "core-blocks",
73928
+ capScope: "system",
73929
+ addonId: null,
73930
+ access: "view",
73931
+ role: "admin"
73932
+ },
73364
73933
  "coreBlocks.getTypeDefs": {
73365
73934
  capName: "core-blocks",
73366
73935
  capScope: "system",
@@ -73396,6 +73965,13 @@ Object.freeze({
73396
73965
  access: "create",
73397
73966
  role: "admin"
73398
73967
  },
73968
+ "coreBlocks.reportAutomationRun": {
73969
+ capName: "core-blocks",
73970
+ capScope: "system",
73971
+ addonId: null,
73972
+ access: "create",
73973
+ role: "admin"
73974
+ },
73399
73975
  "coreBlocks.restart": {
73400
73976
  capName: "core-blocks",
73401
73977
  capScope: "system",
@@ -85550,6 +86126,8 @@ var ML = "model and training machinery — no device action";
85550
86126
  var INTERNAL = "internal plumbing between addons — never operator-facing";
85551
86127
  /** Every system-scoped cap, with why it is not a device's vocabulary. */
85552
86128
  var SYSTEM_CAP_VOCABULARY = {
86129
+ "action-source": system(INTERNAL),
86130
+ actions: system("declared actions — run from the Actions page and from the cameras that link them"),
85553
86131
  "addon-pages": system(UI_PLUMBING),
85554
86132
  "addon-pages-source": system(UI_PLUMBING),
85555
86133
  "addon-routes": system(UI_PLUMBING),
@@ -85746,6 +86324,31 @@ Object.freeze({
85746
86324
  form: "single",
85747
86325
  optional: false
85748
86326
  }],
86327
+ "actions.get": [{
86328
+ name: "deviceId",
86329
+ form: "single",
86330
+ optional: true
86331
+ }],
86332
+ "actions.getLinks": [{
86333
+ name: "deviceId",
86334
+ form: "single",
86335
+ optional: false
86336
+ }],
86337
+ "actions.listForCamera": [{
86338
+ name: "deviceId",
86339
+ form: "single",
86340
+ optional: false
86341
+ }],
86342
+ "actions.run": [{
86343
+ name: "deviceId",
86344
+ form: "single",
86345
+ optional: true
86346
+ }],
86347
+ "actions.setLinks": [{
86348
+ name: "deviceId",
86349
+ form: "single",
86350
+ optional: false
86351
+ }],
85749
86352
  "addonSettings.getDeviceSettings": [{
85750
86353
  name: "deviceId",
85751
86354
  form: "single",
@@ -90090,11 +90693,11 @@ var AlexaBrokerEntrySchema = object({
90090
90693
  * operator's browser uses (alexa-cookie2 rewrites Amazon URLs to absolute
90091
90694
  * `http://<proxyHost>:<proxyPort>/...`), so it is a directly-reachable host —
90092
90695
  * the hub's LAN IP/hostname — NOT behind the hub's HTTPS data-plane mount.
90093
- * Empty `proxyHost` ⇒ auto-detect the host's primary non-loopback IPv4 at
90094
- * login-start time.
90696
+ * Empty `proxyHost` ⇒ the first LAN address of the hub's `appConnections`
90697
+ * role (local-network palette) at login-start time.
90095
90698
  */
90096
90699
  var alexaProxyLoginSchema = object({
90097
- proxyHost: string().default("").describe("Host/IP the browser uses to reach the login proxy (blank = auto-detect)"),
90700
+ proxyHost: string().default("").describe("Host/IP the browser uses to reach the login proxy (blank = the hub LAN address)"),
90098
90701
  proxyPort: preprocess((v) => v === "" || v === null ? void 0 : v, number().int().min(1).max(65535).default(3456)).describe("Port the local Amazon-login proxy listens on (must be reachable)")
90099
90702
  });
90100
90703
  /**
@@ -131602,6 +132205,7 @@ var AlexaProxyLoginSession = class {
131602
132205
  error: errMsg(err)
131603
132206
  } });
131604
132207
  }
132208
+ await stopProxy(remote, this.#logger, this.#opts.sessionId);
131605
132209
  }
131606
132210
  /** Mark cancelled + dispose. */
131607
132211
  async cancel() {
@@ -131655,6 +132259,24 @@ var AlexaProxyLoginSession = class {
131655
132259
  this.dispose();
131656
132260
  }
131657
132261
  };
132262
+ /** Close the login proxy so its port is free for the next session (idempotent). */
132263
+ function stopProxy(remote, logger, sessionId) {
132264
+ return new Promise((resolve) => {
132265
+ try {
132266
+ if (typeof remote.stopProxyServer !== "function") {
132267
+ resolve();
132268
+ return;
132269
+ }
132270
+ remote.stopProxyServer(() => resolve());
132271
+ } catch (err) {
132272
+ logger.warn("alexa proxy-login: stopProxyServer failed", { meta: {
132273
+ sessionId,
132274
+ error: errMsg(err)
132275
+ } });
132276
+ resolve();
132277
+ }
132278
+ });
132279
+ }
131658
132280
  /**
131659
132281
  * Lines emitted by alexa-cookie2 that contain raw credential material
131660
132282
  * (cookie values, CSRF tokens, bearer tokens). Any log line matching this
@@ -131682,15 +132304,62 @@ function isStringOrObject(value) {
131682
132304
  return typeof value === "string" || typeof value === "object" && value !== null;
131683
132305
  }
131684
132306
  //#endregion
132307
+ //#region src/alexa-proxy-host.ts
132308
+ /** Typed refusal: names WHY no proxy host could be chosen. */
132309
+ var AlexaProxyHostError = class extends Error {
132310
+ reason;
132311
+ constructor(reason, message, options) {
132312
+ super(message, options);
132313
+ this.name = "AlexaProxyHostError";
132314
+ this.reason = reason;
132315
+ }
132316
+ };
132317
+ var PRIVATE_IPV4 = /^(10\.|192\.168\.|172\.(1[6-9]|2\d|3[01])\.|169\.254\.)/;
132318
+ var IPV4_LITERAL = /^\d{1,3}(\.\d{1,3}){3}$/;
132319
+ /** A host a browser on the hub's network reaches directly: private IPv4, `.local`, or a bare name. */
132320
+ function isLanHost(host) {
132321
+ if (host.length === 0) return false;
132322
+ if (IPV4_LITERAL.test(host)) return PRIVATE_IPV4.test(host);
132323
+ if (host.includes(":")) return false;
132324
+ return host.endsWith(".local") || !host.includes(".");
132325
+ }
132326
+ function lanHostOf(address) {
132327
+ try {
132328
+ const host = new URL(address).hostname;
132329
+ return isLanHost(host) && host !== "localhost" ? host : null;
132330
+ } catch {
132331
+ return null;
132332
+ }
132333
+ }
132334
+ async function resolveProxyHost(input) {
132335
+ const override = input.override.trim();
132336
+ if (override.length > 0) return override;
132337
+ let addresses;
132338
+ try {
132339
+ addresses = await input.readAppConnections();
132340
+ } catch (err) {
132341
+ input.logger.warn("alexa proxy-login: hub addresses unavailable from local-network", { meta: { error: errMsg(err) } });
132342
+ throw new AlexaProxyHostError("palette-unavailable", "alexa proxy-login: the hub address list is unavailable — set proxyHost in settings", { cause: err });
132343
+ }
132344
+ for (const address of addresses) {
132345
+ const host = lanHostOf(address);
132346
+ if (host !== null) return host;
132347
+ }
132348
+ input.logger.warn("alexa proxy-login: no LAN address among the hub appConnections", { meta: { addresses: [...addresses] } });
132349
+ throw new AlexaProxyHostError("no-lan-address", "alexa proxy-login: the hub has no LAN address the browser can open directly — set proxyHost in settings");
132350
+ }
132351
+ //#endregion
131685
132352
  //#region src/alexa-proxy-login-manager.ts
131686
132353
  var AlexaProxyLoginManager = class {
131687
132354
  #logger;
131688
132355
  #getProxyConfig;
132356
+ #getAppConnectionAddresses;
131689
132357
  #session = null;
131690
132358
  #captured = /* @__PURE__ */ new Map();
131691
132359
  constructor(deps) {
131692
132360
  this.#logger = deps.logger;
131693
132361
  this.#getProxyConfig = deps.getProxyConfig;
132362
+ this.#getAppConnectionAddresses = deps.getAppConnectionAddresses;
131694
132363
  }
131695
132364
  /**
131696
132365
  * Start a fresh proxy-login. Cancels any in-flight session first (single
@@ -131699,8 +132368,11 @@ var AlexaProxyLoginManager = class {
131699
132368
  async start(amazonDomain) {
131700
132369
  await this.cancelActive();
131701
132370
  const { proxyHost, proxyPort } = this.#getProxyConfig();
131702
- const host = proxyHost.length > 0 ? proxyHost : detectPrimaryIpv4();
131703
- if (host.length === 0) throw new Error("alexa proxy-login: could not auto-detect a reachable host IP — set proxyHost in settings");
132371
+ const host = await resolveProxyHost({
132372
+ override: proxyHost,
132373
+ readAppConnections: this.#getAppConnectionAddresses,
132374
+ logger: this.#logger
132375
+ });
131704
132376
  const sessionId = (0, node_crypto.randomBytes)(9).toString("base64url");
131705
132377
  const session = new AlexaProxyLoginSession({
131706
132378
  sessionId,
@@ -131768,19 +132440,6 @@ var AlexaProxyLoginManager = class {
131768
132440
  }
131769
132441
  };
131770
132442
  /**
131771
- * Best-effort primary non-loopback IPv4 of the host. Used when the operator
131772
- * leaves `proxyHost` blank. Returns '' when none found (then the operator must
131773
- * set it explicitly — common on multi-homed/containerised hosts).
131774
- */
131775
- function detectPrimaryIpv4() {
131776
- const ifaces = (0, node_os.networkInterfaces)();
131777
- for (const addrs of Object.values(ifaces)) {
131778
- if (addrs === void 0) continue;
131779
- for (const addr of addrs) if (addr.family === "IPv4" && !addr.internal && addr.address.length > 0) return addr.address;
131780
- }
131781
- return "";
131782
- }
131783
- /**
131784
132443
  * Serialize the captured `cookieData` blob into the single STRING the broker
131785
132444
  * connection stores in its `cookie` field. `AlexaRemoteClient` already parses a
131786
132445
  * JSON-object cookie string back into the richer object form on init, so we
@@ -135477,7 +136136,8 @@ var AlexaImportAddon = class extends BaseDeviceProvider {
135477
136136
  proxyHost: cfg.proxyHost,
135478
136137
  proxyPort: cfg.proxyPort
135479
136138
  };
135480
- }
136139
+ },
136140
+ getAppConnectionAddresses: async () => (await this.ctx.api.localNetwork.getAddresses.query()).roles.appConnections.resolved
135481
136141
  });
135482
136142
  this.ctx.logger.info("Alexa: import addon initialised", { meta: { brokerCount: this.activeBrokers.length } });
135483
136143
  await this.reconcileIntegrationsToBrokers();