camstack 1.2.161 → 1.2.163
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.
|
@@ -19746,7 +19746,23 @@ var PickStreamRequirementsSchema = external_exports.object({
|
|
|
19746
19746
|
* This is what lets one picker serve both the bypass and the full source
|
|
19747
19747
|
* choice, instead of a consumer scoring privately when the bypass misses.
|
|
19748
19748
|
*/
|
|
19749
|
-
allowTranscode: external_exports.boolean().optional()
|
|
19749
|
+
allowTranscode: external_exports.boolean().optional(),
|
|
19750
|
+
/**
|
|
19751
|
+
* Consider ONLY streams the broker has bound to a profile slot.
|
|
19752
|
+
*
|
|
19753
|
+
* A consumer that dials the broker — which is every exporter, since none
|
|
19754
|
+
* of them may open the camera's own URL — can do nothing with a source
|
|
19755
|
+
* that has no slot: there is no restream to dial. Without this the picker
|
|
19756
|
+
* can name such a stream, and each consumer discovers the dead end for
|
|
19757
|
+
* itself: Alexa's `profileForCamStream` returns `null` and it quietly
|
|
19758
|
+
* falls back, and HomeKit would have had to grow the same function again.
|
|
19759
|
+
*
|
|
19760
|
+
* Default `false`, and deliberately so: the BROKER itself picks through
|
|
19761
|
+
* here when it decides which source to BIND to a slot
|
|
19762
|
+
* (`computeInitialAssignment`), and it must see the unbound ones or it
|
|
19763
|
+
* could never bind them.
|
|
19764
|
+
*/
|
|
19765
|
+
requireProfileBound: external_exports.boolean().optional()
|
|
19750
19766
|
}).readonly();
|
|
19751
19767
|
var PickStreamPreferencesSchema = external_exports.object({
|
|
19752
19768
|
/**
|
|
@@ -19787,7 +19803,43 @@ var PickedCamStreamSchema = external_exports.object({
|
|
|
19787
19803
|
*/
|
|
19788
19804
|
transcodes: external_exports.boolean(),
|
|
19789
19805
|
/** One-line explanation of why this stream won — for logs / debug UI. */
|
|
19790
|
-
reason: external_exports.string()
|
|
19806
|
+
reason: external_exports.string(),
|
|
19807
|
+
/**
|
|
19808
|
+
* The broker profile slot this source is bound to, when it is bound.
|
|
19809
|
+
*
|
|
19810
|
+
* Answered HERE because every consumer needs it and none of them can get it
|
|
19811
|
+
* from the `camStreamId` alone. Alexa wrote `profileForCamStream` for it —
|
|
19812
|
+
* a second cap read plus a `null` branch — and HomeKit was about to write
|
|
19813
|
+
* the same function a second time.
|
|
19814
|
+
*
|
|
19815
|
+
* Absent when the source has no slot, which a caller passing
|
|
19816
|
+
* `requireProfileBound` can never see.
|
|
19817
|
+
*/
|
|
19818
|
+
profile: CamProfileSchema.optional(),
|
|
19819
|
+
/** The broker id of that slot, for logs that must name what was dialled. */
|
|
19820
|
+
brokerId: external_exports.string().optional(),
|
|
19821
|
+
/**
|
|
19822
|
+
* The broker restream URL to dial for this stream.
|
|
19823
|
+
*
|
|
19824
|
+
* An exporter must never open the camera's own URL — the broker is the one
|
|
19825
|
+
* that dials the camera, and every consumer goes through its restream. So
|
|
19826
|
+
* the picker answers with the thing a consumer may actually use, instead of
|
|
19827
|
+
* naming a source and leaving each caller to look the URL up.
|
|
19828
|
+
*/
|
|
19829
|
+
url: external_exports.string().optional(),
|
|
19830
|
+
/**
|
|
19831
|
+
* Frames per second this stream really delivers, and where the number came
|
|
19832
|
+
* from.
|
|
19833
|
+
*
|
|
19834
|
+
* It is here because getting it wrong is expensive and silent: a HomeKit
|
|
19835
|
+
* accessory advertised 720p at 24 fps while the slot serving it ran at 9,
|
|
19836
|
+
* and the controller rendered nothing at all. The source is carried with the
|
|
19837
|
+
* value for the same reason the bitrate evidence is: `published` is what the
|
|
19838
|
+
* publisher declares and `measured` is what the broker observed, and they
|
|
19839
|
+
* are not interchangeable.
|
|
19840
|
+
*/
|
|
19841
|
+
fps: external_exports.number().positive().optional(),
|
|
19842
|
+
fpsSource: external_exports.enum(["published", "measured"]).optional()
|
|
19791
19843
|
});
|
|
19792
19844
|
var cameraStreamsCapability = {
|
|
19793
19845
|
name: "camera-streams",
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runDiscover
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-QT7LGBTP.js";
|
|
5
5
|
import "./chunk-LMMQX4CK.js";
|
|
6
6
|
|
|
7
7
|
// src/cli.ts
|
|
@@ -38,7 +38,7 @@ async function runServe(args) {
|
|
|
38
38
|
...typeof values.data === "string" ? { data: values.data } : {}
|
|
39
39
|
};
|
|
40
40
|
Object.assign(process.env, buildServeEnv(opts));
|
|
41
|
-
await import("./launcher-
|
|
41
|
+
await import("./launcher-JVXE2AOJ.js");
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
// src/commands/agent.ts
|
|
@@ -83,7 +83,7 @@ async function runAgent(args) {
|
|
|
83
83
|
...typeof values.port === "string" ? { port: values.port } : {}
|
|
84
84
|
};
|
|
85
85
|
Object.assign(process.env, buildAgentEnv(opts));
|
|
86
|
-
await import("./launcher-
|
|
86
|
+
await import("./launcher-JVXE2AOJ.js");
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
// src/commands/setup.ts
|
|
@@ -1140,7 +1140,7 @@ function isUnknown(_value) {
|
|
|
1140
1140
|
return true;
|
|
1141
1141
|
}
|
|
1142
1142
|
async function resolveServerInteractive(presetNamespace) {
|
|
1143
|
-
const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-
|
|
1143
|
+
const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-NGNF47ZY.js");
|
|
1144
1144
|
if (presetNamespace) {
|
|
1145
1145
|
const spinner4 = clack.spinner();
|
|
1146
1146
|
spinner4.start(`Discovering hub on LAN (namespace "${presetNamespace}")`);
|
|
@@ -23633,9 +23633,9 @@ var require_zod = __commonJS({
|
|
|
23633
23633
|
}
|
|
23634
23634
|
});
|
|
23635
23635
|
|
|
23636
|
-
// ../system/dist/dist-
|
|
23637
|
-
var
|
|
23638
|
-
"../system/dist/dist-
|
|
23636
|
+
// ../system/dist/dist-CpXBoZOv.js
|
|
23637
|
+
var require_dist_CpXBoZOv = __commonJS({
|
|
23638
|
+
"../system/dist/dist-CpXBoZOv.js"(exports) {
|
|
23639
23639
|
"use strict";
|
|
23640
23640
|
var zod = require_zod();
|
|
23641
23641
|
var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
|
|
@@ -30405,7 +30405,23 @@ var require_dist_Cz6h6Nc3 = __commonJS({
|
|
|
30405
30405
|
* This is what lets one picker serve both the bypass and the full source
|
|
30406
30406
|
* choice, instead of a consumer scoring privately when the bypass misses.
|
|
30407
30407
|
*/
|
|
30408
|
-
allowTranscode: zod.z.boolean().optional()
|
|
30408
|
+
allowTranscode: zod.z.boolean().optional(),
|
|
30409
|
+
/**
|
|
30410
|
+
* Consider ONLY streams the broker has bound to a profile slot.
|
|
30411
|
+
*
|
|
30412
|
+
* A consumer that dials the broker — which is every exporter, since none
|
|
30413
|
+
* of them may open the camera's own URL — can do nothing with a source
|
|
30414
|
+
* that has no slot: there is no restream to dial. Without this the picker
|
|
30415
|
+
* can name such a stream, and each consumer discovers the dead end for
|
|
30416
|
+
* itself: Alexa's `profileForCamStream` returns `null` and it quietly
|
|
30417
|
+
* falls back, and HomeKit would have had to grow the same function again.
|
|
30418
|
+
*
|
|
30419
|
+
* Default `false`, and deliberately so: the BROKER itself picks through
|
|
30420
|
+
* here when it decides which source to BIND to a slot
|
|
30421
|
+
* (`computeInitialAssignment`), and it must see the unbound ones or it
|
|
30422
|
+
* could never bind them.
|
|
30423
|
+
*/
|
|
30424
|
+
requireProfileBound: zod.z.boolean().optional()
|
|
30409
30425
|
}).readonly();
|
|
30410
30426
|
var PickStreamPreferencesSchema = zod.z.object({
|
|
30411
30427
|
/**
|
|
@@ -30446,7 +30462,43 @@ var require_dist_Cz6h6Nc3 = __commonJS({
|
|
|
30446
30462
|
*/
|
|
30447
30463
|
transcodes: zod.z.boolean(),
|
|
30448
30464
|
/** One-line explanation of why this stream won — for logs / debug UI. */
|
|
30449
|
-
reason: zod.z.string()
|
|
30465
|
+
reason: zod.z.string(),
|
|
30466
|
+
/**
|
|
30467
|
+
* The broker profile slot this source is bound to, when it is bound.
|
|
30468
|
+
*
|
|
30469
|
+
* Answered HERE because every consumer needs it and none of them can get it
|
|
30470
|
+
* from the `camStreamId` alone. Alexa wrote `profileForCamStream` for it —
|
|
30471
|
+
* a second cap read plus a `null` branch — and HomeKit was about to write
|
|
30472
|
+
* the same function a second time.
|
|
30473
|
+
*
|
|
30474
|
+
* Absent when the source has no slot, which a caller passing
|
|
30475
|
+
* `requireProfileBound` can never see.
|
|
30476
|
+
*/
|
|
30477
|
+
profile: CamProfileSchema.optional(),
|
|
30478
|
+
/** The broker id of that slot, for logs that must name what was dialled. */
|
|
30479
|
+
brokerId: zod.z.string().optional(),
|
|
30480
|
+
/**
|
|
30481
|
+
* The broker restream URL to dial for this stream.
|
|
30482
|
+
*
|
|
30483
|
+
* An exporter must never open the camera's own URL — the broker is the one
|
|
30484
|
+
* that dials the camera, and every consumer goes through its restream. So
|
|
30485
|
+
* the picker answers with the thing a consumer may actually use, instead of
|
|
30486
|
+
* naming a source and leaving each caller to look the URL up.
|
|
30487
|
+
*/
|
|
30488
|
+
url: zod.z.string().optional(),
|
|
30489
|
+
/**
|
|
30490
|
+
* Frames per second this stream really delivers, and where the number came
|
|
30491
|
+
* from.
|
|
30492
|
+
*
|
|
30493
|
+
* It is here because getting it wrong is expensive and silent: a HomeKit
|
|
30494
|
+
* accessory advertised 720p at 24 fps while the slot serving it ran at 9,
|
|
30495
|
+
* and the controller rendered nothing at all. The source is carried with the
|
|
30496
|
+
* value for the same reason the bitrate evidence is: `published` is what the
|
|
30497
|
+
* publisher declares and `measured` is what the broker observed, and they
|
|
30498
|
+
* are not interchangeable.
|
|
30499
|
+
*/
|
|
30500
|
+
fps: zod.z.number().positive().optional(),
|
|
30501
|
+
fpsSource: zod.z.enum(["published", "measured"]).optional()
|
|
30450
30502
|
});
|
|
30451
30503
|
var cameraStreamsCapability = {
|
|
30452
30504
|
name: "camera-streams",
|
|
@@ -62805,7 +62857,7 @@ var require_alerts_addon = __commonJS({
|
|
|
62805
62857
|
[Symbol.toStringTag]: { value: "Module" }
|
|
62806
62858
|
});
|
|
62807
62859
|
require_chunk_Cek0wNdY();
|
|
62808
|
-
var require_dist10 =
|
|
62860
|
+
var require_dist10 = require_dist_CpXBoZOv();
|
|
62809
62861
|
function selectExpired(alerts, cutoffMs) {
|
|
62810
62862
|
return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
|
|
62811
62863
|
}
|
|
@@ -63624,7 +63676,7 @@ var require_console_logging = __commonJS({
|
|
|
63624
63676
|
[Symbol.toStringTag]: { value: "Module" }
|
|
63625
63677
|
});
|
|
63626
63678
|
require_chunk_Cek0wNdY();
|
|
63627
|
-
var require_dist10 =
|
|
63679
|
+
var require_dist10 = require_dist_CpXBoZOv();
|
|
63628
63680
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
63629
63681
|
var LEVEL_RANK = {
|
|
63630
63682
|
debug: 0,
|
|
@@ -63718,7 +63770,7 @@ var require_core_blocks_addon = __commonJS({
|
|
|
63718
63770
|
"use strict";
|
|
63719
63771
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
63720
63772
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
63721
|
-
var require_dist10 =
|
|
63773
|
+
var require_dist10 = require_dist_CpXBoZOv();
|
|
63722
63774
|
var node_crypto = __require("crypto");
|
|
63723
63775
|
var node_fs_promises = __require("fs/promises");
|
|
63724
63776
|
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
@@ -64615,11 +64667,11 @@ var require_core_blocks = __commonJS({
|
|
|
64615
64667
|
}
|
|
64616
64668
|
});
|
|
64617
64669
|
|
|
64618
|
-
// ../system/dist/retired-settings-keys-
|
|
64619
|
-
var
|
|
64620
|
-
"../system/dist/retired-settings-keys-
|
|
64670
|
+
// ../system/dist/retired-settings-keys-1sEBolVU.js
|
|
64671
|
+
var require_retired_settings_keys_1sEBolVU = __commonJS({
|
|
64672
|
+
"../system/dist/retired-settings-keys-1sEBolVU.js"(exports) {
|
|
64621
64673
|
"use strict";
|
|
64622
|
-
var require_dist10 =
|
|
64674
|
+
var require_dist10 = require_dist_CpXBoZOv();
|
|
64623
64675
|
function settingsStoreIsAuthoritativeHere(env) {
|
|
64624
64676
|
const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
|
|
64625
64677
|
return raw === "" || raw === "hub";
|
|
@@ -66856,8 +66908,8 @@ var require_device_manager_addon = __commonJS({
|
|
|
66856
66908
|
[Symbol.toStringTag]: { value: "Module" }
|
|
66857
66909
|
});
|
|
66858
66910
|
require_chunk_Cek0wNdY();
|
|
66859
|
-
var require_dist10 =
|
|
66860
|
-
var require_retired_settings_keys =
|
|
66911
|
+
var require_dist10 = require_dist_CpXBoZOv();
|
|
66912
|
+
var require_retired_settings_keys = require_retired_settings_keys_1sEBolVU();
|
|
66861
66913
|
var node_crypto = __require("crypto");
|
|
66862
66914
|
var _camstack_types_node = require_node();
|
|
66863
66915
|
var JOB_HISTORY = 20;
|
|
@@ -72865,7 +72917,7 @@ var require_hub_forwarder = __commonJS({
|
|
|
72865
72917
|
[Symbol.toStringTag]: { value: "Module" }
|
|
72866
72918
|
});
|
|
72867
72919
|
require_chunk_Cek0wNdY();
|
|
72868
|
-
var require_dist10 =
|
|
72920
|
+
var require_dist10 = require_dist_CpXBoZOv();
|
|
72869
72921
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
72870
72922
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
72871
72923
|
var HubForwarderDestination = class {
|
|
@@ -73002,7 +73054,7 @@ var require_liveness_monitor_addon = __commonJS({
|
|
|
73002
73054
|
"use strict";
|
|
73003
73055
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
73004
73056
|
require_chunk_Cek0wNdY();
|
|
73005
|
-
var require_dist10 =
|
|
73057
|
+
var require_dist10 = require_dist_CpXBoZOv();
|
|
73006
73058
|
var NO_DEVICES = "liveness:no-devices";
|
|
73007
73059
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
73008
73060
|
var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
|
|
@@ -73198,7 +73250,7 @@ var require_local_auth_addon = __commonJS({
|
|
|
73198
73250
|
[Symbol.toStringTag]: { value: "Module" }
|
|
73199
73251
|
});
|
|
73200
73252
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
73201
|
-
var require_dist10 =
|
|
73253
|
+
var require_dist10 = require_dist_CpXBoZOv();
|
|
73202
73254
|
var node_crypto = __require("crypto");
|
|
73203
73255
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
73204
73256
|
var crypto$1 = __require("crypto");
|
|
@@ -81011,7 +81063,7 @@ var require_loki_logging = __commonJS({
|
|
|
81011
81063
|
[Symbol.toStringTag]: { value: "Module" }
|
|
81012
81064
|
});
|
|
81013
81065
|
require_chunk_Cek0wNdY();
|
|
81014
|
-
var require_dist10 =
|
|
81066
|
+
var require_dist10 = require_dist_CpXBoZOv();
|
|
81015
81067
|
function sanitizeLabelName(raw) {
|
|
81016
81068
|
const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
|
|
81017
81069
|
return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
|
|
@@ -81598,7 +81650,7 @@ var require_native_metrics_addon = __commonJS({
|
|
|
81598
81650
|
[Symbol.toStringTag]: { value: "Module" }
|
|
81599
81651
|
});
|
|
81600
81652
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
81601
|
-
var require_dist10 =
|
|
81653
|
+
var require_dist10 = require_dist_CpXBoZOv();
|
|
81602
81654
|
var node_fs_promises = __require("fs/promises");
|
|
81603
81655
|
var node_fs = __require("fs");
|
|
81604
81656
|
node_fs = require_chunk.__toESM(node_fs);
|
|
@@ -84351,7 +84403,7 @@ var require_filesystem_storage_addon = __commonJS({
|
|
|
84351
84403
|
[Symbol.toStringTag]: { value: "Module" }
|
|
84352
84404
|
});
|
|
84353
84405
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
84354
|
-
var require_dist10 =
|
|
84406
|
+
var require_dist10 = require_dist_CpXBoZOv();
|
|
84355
84407
|
var node_crypto = __require("crypto");
|
|
84356
84408
|
var node_fs_promises = __require("fs/promises");
|
|
84357
84409
|
var node_path = __require("path");
|
|
@@ -85578,8 +85630,8 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
85578
85630
|
[Symbol.toStringTag]: { value: "Module" }
|
|
85579
85631
|
});
|
|
85580
85632
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
85581
|
-
var require_dist10 =
|
|
85582
|
-
var require_retired_settings_keys =
|
|
85633
|
+
var require_dist10 = require_dist_CpXBoZOv();
|
|
85634
|
+
var require_retired_settings_keys = require_retired_settings_keys_1sEBolVU();
|
|
85583
85635
|
var require_wal_checkpoint_policy = require_wal_checkpoint_policy_CCJZngds();
|
|
85584
85636
|
var node_crypto = __require("crypto");
|
|
85585
85637
|
var node_path = __require("path");
|
|
@@ -88366,7 +88418,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
88366
88418
|
[Symbol.toStringTag]: { value: "Module" }
|
|
88367
88419
|
});
|
|
88368
88420
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
88369
|
-
var require_dist10 =
|
|
88421
|
+
var require_dist10 = require_dist_CpXBoZOv();
|
|
88370
88422
|
var require_hub_cap_forward = require_hub_cap_forward_DmHNjbB0();
|
|
88371
88423
|
var zod = require_zod();
|
|
88372
88424
|
var node_crypto = __require("crypto");
|
|
@@ -92093,7 +92145,7 @@ var require_system_config_addon = __commonJS({
|
|
|
92093
92145
|
[Symbol.toStringTag]: { value: "Module" }
|
|
92094
92146
|
});
|
|
92095
92147
|
require_chunk_Cek0wNdY();
|
|
92096
|
-
var require_dist10 =
|
|
92148
|
+
var require_dist10 = require_dist_CpXBoZOv();
|
|
92097
92149
|
var SECTION_TITLES = {
|
|
92098
92150
|
server: "Server",
|
|
92099
92151
|
auth: "Authentication"
|
|
@@ -110154,7 +110206,7 @@ var require_winston_logging = __commonJS({
|
|
|
110154
110206
|
[Symbol.toStringTag]: { value: "Module" }
|
|
110155
110207
|
});
|
|
110156
110208
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
110157
|
-
var require_dist10 =
|
|
110209
|
+
var require_dist10 = require_dist_CpXBoZOv();
|
|
110158
110210
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
110159
110211
|
var node_path = __require("path");
|
|
110160
110212
|
node_path = require_chunk.__toESM(node_path);
|
|
@@ -136421,7 +136473,7 @@ var require_dist3 = __commonJS({
|
|
|
136421
136473
|
"use strict";
|
|
136422
136474
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
136423
136475
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
136424
|
-
var require_dist10 =
|
|
136476
|
+
var require_dist10 = require_dist_CpXBoZOv();
|
|
136425
136477
|
var require_builtins_alerts_alerts_addon = require_alerts_addon();
|
|
136426
136478
|
require_alerts();
|
|
136427
136479
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
@@ -224230,7 +224282,23 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
224230
224282
|
* This is what lets one picker serve both the bypass and the full source
|
|
224231
224283
|
* choice, instead of a consumer scoring privately when the bypass misses.
|
|
224232
224284
|
*/
|
|
224233
|
-
allowTranscode: zod.z.boolean().optional()
|
|
224285
|
+
allowTranscode: zod.z.boolean().optional(),
|
|
224286
|
+
/**
|
|
224287
|
+
* Consider ONLY streams the broker has bound to a profile slot.
|
|
224288
|
+
*
|
|
224289
|
+
* A consumer that dials the broker — which is every exporter, since none
|
|
224290
|
+
* of them may open the camera's own URL — can do nothing with a source
|
|
224291
|
+
* that has no slot: there is no restream to dial. Without this the picker
|
|
224292
|
+
* can name such a stream, and each consumer discovers the dead end for
|
|
224293
|
+
* itself: Alexa's `profileForCamStream` returns `null` and it quietly
|
|
224294
|
+
* falls back, and HomeKit would have had to grow the same function again.
|
|
224295
|
+
*
|
|
224296
|
+
* Default `false`, and deliberately so: the BROKER itself picks through
|
|
224297
|
+
* here when it decides which source to BIND to a slot
|
|
224298
|
+
* (`computeInitialAssignment`), and it must see the unbound ones or it
|
|
224299
|
+
* could never bind them.
|
|
224300
|
+
*/
|
|
224301
|
+
requireProfileBound: zod.z.boolean().optional()
|
|
224234
224302
|
}).readonly();
|
|
224235
224303
|
var PickStreamPreferencesSchema = zod.z.object({
|
|
224236
224304
|
/**
|
|
@@ -224271,7 +224339,43 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
224271
224339
|
*/
|
|
224272
224340
|
transcodes: zod.z.boolean(),
|
|
224273
224341
|
/** One-line explanation of why this stream won — for logs / debug UI. */
|
|
224274
|
-
reason: zod.z.string()
|
|
224342
|
+
reason: zod.z.string(),
|
|
224343
|
+
/**
|
|
224344
|
+
* The broker profile slot this source is bound to, when it is bound.
|
|
224345
|
+
*
|
|
224346
|
+
* Answered HERE because every consumer needs it and none of them can get it
|
|
224347
|
+
* from the `camStreamId` alone. Alexa wrote `profileForCamStream` for it —
|
|
224348
|
+
* a second cap read plus a `null` branch — and HomeKit was about to write
|
|
224349
|
+
* the same function a second time.
|
|
224350
|
+
*
|
|
224351
|
+
* Absent when the source has no slot, which a caller passing
|
|
224352
|
+
* `requireProfileBound` can never see.
|
|
224353
|
+
*/
|
|
224354
|
+
profile: require_sleep.CamProfileSchema.optional(),
|
|
224355
|
+
/** The broker id of that slot, for logs that must name what was dialled. */
|
|
224356
|
+
brokerId: zod.z.string().optional(),
|
|
224357
|
+
/**
|
|
224358
|
+
* The broker restream URL to dial for this stream.
|
|
224359
|
+
*
|
|
224360
|
+
* An exporter must never open the camera's own URL — the broker is the one
|
|
224361
|
+
* that dials the camera, and every consumer goes through its restream. So
|
|
224362
|
+
* the picker answers with the thing a consumer may actually use, instead of
|
|
224363
|
+
* naming a source and leaving each caller to look the URL up.
|
|
224364
|
+
*/
|
|
224365
|
+
url: zod.z.string().optional(),
|
|
224366
|
+
/**
|
|
224367
|
+
* Frames per second this stream really delivers, and where the number came
|
|
224368
|
+
* from.
|
|
224369
|
+
*
|
|
224370
|
+
* It is here because getting it wrong is expensive and silent: a HomeKit
|
|
224371
|
+
* accessory advertised 720p at 24 fps while the slot serving it ran at 9,
|
|
224372
|
+
* and the controller rendered nothing at all. The source is carried with the
|
|
224373
|
+
* value for the same reason the bitrate evidence is: `published` is what the
|
|
224374
|
+
* publisher declares and `measured` is what the broker observed, and they
|
|
224375
|
+
* are not interchangeable.
|
|
224376
|
+
*/
|
|
224377
|
+
fps: zod.z.number().positive().optional(),
|
|
224378
|
+
fpsSource: zod.z.enum(["published", "measured"]).optional()
|
|
224275
224379
|
});
|
|
224276
224380
|
var cameraStreamsCapability = {
|
|
224277
224381
|
name: "camera-streams",
|
|
@@ -431481,6 +431585,24 @@ var require_runner_convergence = __commonJS({
|
|
|
431481
431585
|
}
|
|
431482
431586
|
});
|
|
431483
431587
|
|
|
431588
|
+
// ../../server/backend/dist/core/addon/runner-serialization.js
|
|
431589
|
+
var require_runner_serialization = __commonJS({
|
|
431590
|
+
"../../server/backend/dist/core/addon/runner-serialization.js"(exports) {
|
|
431591
|
+
"use strict";
|
|
431592
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
431593
|
+
exports.createRunnerSerializer = createRunnerSerializer;
|
|
431594
|
+
function createRunnerSerializer() {
|
|
431595
|
+
const tails = /* @__PURE__ */ new Map();
|
|
431596
|
+
return (runnerId, converge) => {
|
|
431597
|
+
const previous = tails.get(runnerId) ?? Promise.resolve();
|
|
431598
|
+
const result = previous.then(converge, converge);
|
|
431599
|
+
tails.set(runnerId, result.then(() => void 0, () => void 0));
|
|
431600
|
+
return result;
|
|
431601
|
+
};
|
|
431602
|
+
}
|
|
431603
|
+
}
|
|
431604
|
+
});
|
|
431605
|
+
|
|
431484
431606
|
// ../../server/backend/dist/core/addon/runner-spawn-fanout.js
|
|
431485
431607
|
var require_runner_spawn_fanout = __commonJS({
|
|
431486
431608
|
"../../server/backend/dist/core/addon/runner-spawn-fanout.js"(exports) {
|
|
@@ -431588,6 +431710,7 @@ var require_addon_registry_service = __commonJS({
|
|
|
431588
431710
|
var forked_custom_actions_js_1 = require_forked_custom_actions();
|
|
431589
431711
|
var prune_misplaced_addons_js_1 = require_prune_misplaced_addons();
|
|
431590
431712
|
var runner_convergence_1 = require_runner_convergence();
|
|
431713
|
+
var runner_serialization_1 = require_runner_serialization();
|
|
431591
431714
|
var runner_spawn_fanout_js_1 = require_runner_spawn_fanout();
|
|
431592
431715
|
function shouldEvictMissingOnDisk(entry, id, onDiskIds) {
|
|
431593
431716
|
return entry.source === "installed" && entry.packageName !== "@camstack/system" && !onDiskIds.has(id);
|
|
@@ -433954,6 +434077,12 @@ var require_addon_registry_service = __commonJS({
|
|
|
433954
434077
|
* a group respawns the ENTIRE group (they share a process): the operator's
|
|
433955
434078
|
* "update one → respawn the whole group" invariant.
|
|
433956
434079
|
*/
|
|
434080
|
+
/**
|
|
434081
|
+
* One converge at a time per runner. See `runner-serialization.ts` for the
|
|
434082
|
+
* two live episodes this closes and why the lock inside `process-service`
|
|
434083
|
+
* could not.
|
|
434084
|
+
*/
|
|
434085
|
+
serializeRunner = (0, runner_serialization_1.createRunnerSerializer)();
|
|
433957
434086
|
async ensureForkedRunner(addonId, opts) {
|
|
433958
434087
|
const entry = this.addonEntries.get(addonId);
|
|
433959
434088
|
if (!entry?.declaration || !entry.addonDir) {
|
|
@@ -433964,33 +434093,35 @@ var require_addon_registry_service = __commonJS({
|
|
|
433964
434093
|
{ addonId, addonDir: entry.addonDir }
|
|
433965
434094
|
];
|
|
433966
434095
|
const effectiveRestart = opts.restart && roster.length > 1 && Date.now() - (this.recentGroupRespawns.get(runnerId) ?? 0) < GROUP_RESPAWN_COALESCE_MS ? false : opts.restart;
|
|
433967
|
-
|
|
433968
|
-
|
|
433969
|
-
|
|
433970
|
-
|
|
433971
|
-
this.
|
|
433972
|
-
|
|
434096
|
+
return this.serializeRunner(runnerId, async () => {
|
|
434097
|
+
const running = await this.listRunnerProcesses();
|
|
434098
|
+
const plan = (0, runner_convergence_1.planRunnerConvergence)(runnerId, roster.map((r) => r.addonId), running, { restart: effectiveRestart });
|
|
434099
|
+
for (const name of plan.stop) {
|
|
434100
|
+
await this.broker.call("$process.stop", { name }).catch((err) => {
|
|
434101
|
+
this.logger.warn("ensureForkedRunner: failed to stop stale runner (continuing)", {
|
|
434102
|
+
meta: { runnerId, stale: name, error: (0, types_1.errMsg)(err) }
|
|
434103
|
+
});
|
|
433973
434104
|
});
|
|
433974
|
-
});
|
|
433975
|
-
}
|
|
433976
|
-
if (plan.action === "spawn") {
|
|
433977
|
-
await this.broker.call("$process.spawnRunner", { runnerId, addons: roster }).catch((err) => {
|
|
433978
|
-
if (!/already running/i.test((0, types_1.errMsg)(err)))
|
|
433979
|
-
throw err;
|
|
433980
|
-
});
|
|
433981
|
-
this.recentGroupRespawns.set(runnerId, Date.now());
|
|
433982
|
-
} else if (plan.action === "restart") {
|
|
433983
|
-
const res = await this.broker.call("$process.restart", { name: runnerId });
|
|
433984
|
-
if (!res.success) {
|
|
433985
|
-
throw new Error(`Process restart failed: ${res.reason ?? "unknown"}`);
|
|
433986
434105
|
}
|
|
433987
|
-
|
|
433988
|
-
|
|
433989
|
-
|
|
433990
|
-
|
|
433991
|
-
|
|
433992
|
-
|
|
433993
|
-
|
|
434106
|
+
if (plan.action === "spawn") {
|
|
434107
|
+
await this.broker.call("$process.spawnRunner", { runnerId, addons: roster }).catch((err) => {
|
|
434108
|
+
if (!/already running/i.test((0, types_1.errMsg)(err)))
|
|
434109
|
+
throw err;
|
|
434110
|
+
});
|
|
434111
|
+
this.recentGroupRespawns.set(runnerId, Date.now());
|
|
434112
|
+
} else if (plan.action === "restart") {
|
|
434113
|
+
const res = await this.broker.call("$process.restart", { name: runnerId });
|
|
434114
|
+
if (!res.success) {
|
|
434115
|
+
throw new Error(`Process restart failed: ${res.reason ?? "unknown"}`);
|
|
434116
|
+
}
|
|
434117
|
+
this.recentGroupRespawns.set(runnerId, Date.now());
|
|
434118
|
+
}
|
|
434119
|
+
for (const { addonId: memberId } of roster) {
|
|
434120
|
+
const memberEntry = this.addonEntries.get(memberId);
|
|
434121
|
+
if (memberEntry)
|
|
434122
|
+
memberEntry.initialized = true;
|
|
434123
|
+
}
|
|
434124
|
+
});
|
|
433994
434125
|
}
|
|
433995
434126
|
/**
|
|
433996
434127
|
* Apply the custom-action catalogs a UDS child DESCRIBED in its register
|