@camstack/system 1.2.117 → 1.2.118

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 (58) hide show
  1. package/dist/addon-utils.d.ts +1 -1
  2. package/dist/addon-utils.js +1 -1
  3. package/dist/addon-utils.mjs +1 -1
  4. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  5. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  6. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  7. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  8. package/dist/builtins/alerts/alerts.addon.js +1 -1
  9. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  10. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  11. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  12. package/dist/builtins/console-logging/index.js +1 -1
  13. package/dist/builtins/console-logging/index.mjs +1 -1
  14. package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
  15. package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
  16. package/dist/builtins/device-manager/device-manager.addon.js +2 -2
  17. package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
  18. package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
  19. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
  20. package/dist/builtins/hub-forwarder/index.js +1 -1
  21. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  22. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  23. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  24. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  25. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  26. package/dist/builtins/local-network/local-network.addon.d.ts +24 -2
  27. package/dist/builtins/local-network/local-network.addon.js +63 -17
  28. package/dist/builtins/local-network/local-network.addon.mjs +62 -18
  29. package/dist/builtins/loki-logging/index.js +1 -1
  30. package/dist/builtins/loki-logging/index.mjs +1 -1
  31. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  32. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  33. package/dist/builtins/platform-probe/index.js +1 -1
  34. package/dist/builtins/platform-probe/index.mjs +1 -1
  35. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  36. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  37. package/dist/builtins/snapshot/index.js +1 -1
  38. package/dist/builtins/snapshot/index.mjs +1 -1
  39. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  40. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  41. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +2 -2
  42. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +2 -2
  43. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  44. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  45. package/dist/builtins/system-config/system-config.addon.js +1 -1
  46. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  47. package/dist/builtins/winston-logging/index.js +1 -1
  48. package/dist/builtins/winston-logging/index.mjs +1 -1
  49. package/dist/{dist-DMEGlqg6.js → dist-C2_1HCpW.js} +133 -15
  50. package/dist/{dist-D4Vmj8iw.mjs → dist-DCTpBXm4.mjs} +133 -15
  51. package/dist/download/model-downloader.d.ts +18 -1
  52. package/dist/{file-data-plane-CuE_hBli.mjs → file-data-plane-BhKdxJgf.mjs} +49 -13
  53. package/dist/{file-data-plane-DUHPHa-Y.js → file-data-plane-DO8KbxCe.js} +49 -13
  54. package/dist/index.js +2 -2
  55. package/dist/index.mjs +2 -2
  56. package/dist/{retired-settings-keys--aM_vGF9.mjs → retired-settings-keys-Czd76yLZ.mjs} +1 -1
  57. package/dist/{retired-settings-keys-DET4YkAU.js → retired-settings-keys-DHRXLMPn.js} +1 -1
  58. package/package.json +1 -1
@@ -14,7 +14,7 @@
14
14
  *
15
15
  * See memory: camstack_runner_ram_and_build_rootcause.
16
16
  */
17
- export { downloadFile, ensureModel, isModelDownloaded, deleteModelFromDisk, collectModelFiles, getModelFilePath, } from './download/model-downloader.js';
17
+ export { downloadFile, ensureModel, isModelDownloaded, deleteModelFromDisk, collectModelFiles, getModelFilePath, type DownloadFileOptions, type DownloadRedirectPolicy, } from './download/model-downloader.js';
18
18
  export { ModelDownloadService } from './download/model-download-service.js';
19
19
  export { createFileDataPlaneHandler } from './http/file-data-plane.js';
20
20
  export { parseRangeHeader, contentTypeFor, type ByteRange, } from './http/authenticated-file-server.js';
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("./chunk-Cek0wNdY.js");
3
- const require_file_data_plane = require("./file-data-plane-DUHPHa-Y.js");
3
+ const require_file_data_plane = require("./file-data-plane-DO8KbxCe.js");
4
4
  const require_custom_action_registry = require("./custom-action-registry-jY0NOZK8.js");
5
5
  exports.CustomActionRegistry = require_custom_action_registry.CustomActionRegistry;
6
6
  exports.ModelDownloadService = require_file_data_plane.ModelDownloadService;
@@ -1,3 +1,3 @@
1
- import { c as collectModelFiles, f as ensureModel, h as isModelDownloaded, i as parseRangeHeader, l as deleteModelFromDisk, m as getModelFilePath, n as contentTypeFor, s as ModelDownloadService, t as createFileDataPlaneHandler, u as downloadFile } from "./file-data-plane-CuE_hBli.mjs";
1
+ import { c as collectModelFiles, f as ensureModel, h as isModelDownloaded, i as parseRangeHeader, l as deleteModelFromDisk, m as getModelFilePath, n as contentTypeFor, s as ModelDownloadService, t as createFileDataPlaneHandler, u as downloadFile } from "./file-data-plane-BhKdxJgf.mjs";
2
2
  import { t as CustomActionRegistry } from "./custom-action-registry-F__gp_VX.mjs";
3
3
  export { CustomActionRegistry, ModelDownloadService, collectModelFiles, contentTypeFor, createFileDataPlaneHandler, deleteModelFromDisk, downloadFile, ensureModel, getModelFilePath, isModelDownloaded, parseRangeHeader };
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DMEGlqg6.js");
6
+ const require_dist = require("../../dist-C2_1HCpW.js");
7
7
  const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
8
8
  let node_crypto = require("node:crypto");
9
9
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { Gt as EventCategory, v as addonPagesCapability, vt as errMsg, yt as BaseAddon } from "../../dist-D4Vmj8iw.mjs";
1
+ import { Gt as EventCategory, v as addonPagesCapability, vt as errMsg, yt as BaseAddon } from "../../dist-DCTpBXm4.mjs";
2
2
  import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
3
3
  import { createHash, randomUUID } from "node:crypto";
4
4
  import * as path$1 from "node:path";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DMEGlqg6.js");
6
+ const require_dist = require("../../dist-C2_1HCpW.js");
7
7
  const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
8
8
  let node_crypto = require("node:crypto");
9
9
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { Gt as EventCategory, b as addonWidgetsCapability, vt as errMsg, yt as BaseAddon } from "../../dist-D4Vmj8iw.mjs";
1
+ import { Gt as EventCategory, b as addonWidgetsCapability, vt as errMsg, yt as BaseAddon } from "../../dist-DCTpBXm4.mjs";
2
2
  import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
3
3
  import { createHash, randomUUID } from "node:crypto";
4
4
  import * as path$1 from "node:path";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DMEGlqg6.js");
6
+ const require_dist = require("../../dist-C2_1HCpW.js");
7
7
  //#region src/builtins/alerts/prune-policy.ts
8
8
  /**
9
9
  * Ids older than `cutoffMs`, oldest first.
@@ -1,4 +1,4 @@
1
- import { Gt as EventCategory, Mt as createEvent, n as AlertSchema, vt as errMsg, x as alertsCapability, yt as BaseAddon } from "../../dist-D4Vmj8iw.mjs";
1
+ import { Gt as EventCategory, Mt as createEvent, n as AlertSchema, vt as errMsg, x as alertsCapability, yt as BaseAddon } from "../../dist-DCTpBXm4.mjs";
2
2
  //#region src/builtins/alerts/prune-policy.ts
3
3
  /**
4
4
  * Ids older than `cutoffMs`, oldest first.
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DMEGlqg6.js");
6
+ const require_dist = require("../../dist-C2_1HCpW.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  let buffer = require("buffer");
9
9
  let node_fs_promises = require("node:fs/promises");
@@ -1,4 +1,4 @@
1
- import { C as backupCapability, Gt as EventCategory, yt as BaseAddon } from "../../dist-D4Vmj8iw.mjs";
1
+ import { C as backupCapability, Gt as EventCategory, yt as BaseAddon } from "../../dist-DCTpBXm4.mjs";
2
2
  import { randomBytes, randomUUID } from "node:crypto";
3
3
  import { Buffer as Buffer$1 } from "buffer";
4
4
  import * as fsp from "node:fs/promises";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DMEGlqg6.js");
6
+ const require_dist = require("../../dist-C2_1HCpW.js");
7
7
  const require_formatter = require("../../formatter-DqAKDlvN.js");
8
8
  //#region src/builtins/console-logging/console-destination.ts
9
9
  var LEVEL_RANK = {
@@ -1,4 +1,4 @@
1
- import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-D4Vmj8iw.mjs";
1
+ import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-DCTpBXm4.mjs";
2
2
  import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
3
3
  //#region src/builtins/console-logging/console-destination.ts
4
4
  var LEVEL_RANK = {
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("../../chunk-Cek0wNdY.js");
3
- const require_dist = require("../../dist-DMEGlqg6.js");
3
+ const require_dist = require("../../dist-C2_1HCpW.js");
4
4
  let node_crypto = require("node:crypto");
5
5
  let node_fs_promises = require("node:fs/promises");
6
6
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -1,4 +1,4 @@
1
- import { D as coreBlockAddonId, O as coreBlockIdFromAddonId, c as CoreBlockSchema, k as coreBlocksCapability, l as DeclaredDevices, o as CORE_BLOCKS_ADDON_ID, s as CORE_BLOCK_ADDON_PREFIX, vt as errMsg, yt as BaseAddon } from "../../dist-D4Vmj8iw.mjs";
1
+ import { D as coreBlockAddonId, O as coreBlockIdFromAddonId, c as CoreBlockSchema, k as coreBlocksCapability, l as DeclaredDevices, o as CORE_BLOCKS_ADDON_ID, s as CORE_BLOCK_ADDON_PREFIX, vt as errMsg, yt as BaseAddon } from "../../dist-DCTpBXm4.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import * as fs from "node:fs/promises";
4
4
  import * as path$1 from "node:path";
@@ -3,8 +3,8 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DMEGlqg6.js");
7
- const require_retired_settings_keys = require("../../retired-settings-keys-DET4YkAU.js");
6
+ const require_dist = require("../../dist-C2_1HCpW.js");
7
+ const require_retired_settings_keys = require("../../retired-settings-keys-DHRXLMPn.js");
8
8
  let node_crypto = require("node:crypto");
9
9
  let _camstack_types_node = require("@camstack/types/node");
10
10
  //#region src/builtins/device-manager/adoption-job-engine.ts
@@ -1,5 +1,5 @@
1
- import { Ct as DeviceFeature, E as buildStreamParamsConfigSchema, F as deviceStatusCapability, Gt as EventCategory, Lt as isDeviceConfigCap, N as deviceManagerCapability, Ot as WELL_KNOWN_TAB_MAP, P as deviceStateCapability, R as enumerateItemArrayFields, Tt as DeviceType, Wt as sleep, a as CAP_NAMES_WITH_STATUS, at as runtimeStatePolicyFor, et as normalizeUnit, nt as parseStreamParamsFormPatch, p as STREAM_PROFILE_META, t as ALL_CAPABILITY_DEFINITIONS, u as DeviceStatusSchema, vt as errMsg, wt as DeviceRole, yt as BaseAddon, z as enumerateSchemaFields } from "../../dist-D4Vmj8iw.mjs";
2
- import { n as purgeRetiredSettingsRows } from "../../retired-settings-keys--aM_vGF9.mjs";
1
+ import { Ct as DeviceFeature, E as buildStreamParamsConfigSchema, F as deviceStatusCapability, Gt as EventCategory, Lt as isDeviceConfigCap, N as deviceManagerCapability, Ot as WELL_KNOWN_TAB_MAP, P as deviceStateCapability, R as enumerateItemArrayFields, Tt as DeviceType, Wt as sleep, a as CAP_NAMES_WITH_STATUS, at as runtimeStatePolicyFor, et as normalizeUnit, nt as parseStreamParamsFormPatch, p as STREAM_PROFILE_META, t as ALL_CAPABILITY_DEFINITIONS, u as DeviceStatusSchema, vt as errMsg, wt as DeviceRole, yt as BaseAddon, z as enumerateSchemaFields } from "../../dist-DCTpBXm4.mjs";
2
+ import { n as purgeRetiredSettingsRows } from "../../retired-settings-keys-Czd76yLZ.mjs";
3
3
  import { randomUUID } from "node:crypto";
4
4
  import { canonicalDeviceFingerprint } from "@camstack/types/node";
5
5
  //#region src/builtins/device-manager/adoption-job-engine.ts
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DMEGlqg6.js");
6
+ const require_dist = require("../../dist-C2_1HCpW.js");
7
7
  //#region src/builtins/doorbell/trigger-engine.ts
8
8
  /**
9
9
  * Pure trigger logic for the virtual-doorbell builtin — edge detection over
@@ -1,4 +1,4 @@
1
- import { G as isSameAddonId, Gt as EventCategory, I as doorbellCapability, Mt as createEvent, Tt as DeviceType, vt as errMsg, w as bareAddonId, yt as BaseAddon } from "../../dist-D4Vmj8iw.mjs";
1
+ import { G as isSameAddonId, Gt as EventCategory, I as doorbellCapability, Mt as createEvent, Tt as DeviceType, vt as errMsg, w as bareAddonId, yt as BaseAddon } from "../../dist-DCTpBXm4.mjs";
2
2
  //#region src/builtins/doorbell/trigger-engine.ts
3
3
  /**
4
4
  * Pure trigger logic for the virtual-doorbell builtin — edge detection over
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DMEGlqg6.js");
6
+ const require_dist = require("../../dist-C2_1HCpW.js");
7
7
  const require_formatter = require("../../formatter-DqAKDlvN.js");
8
8
  //#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
9
9
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
@@ -1,4 +1,4 @@
1
- import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-D4Vmj8iw.mjs";
1
+ import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-DCTpBXm4.mjs";
2
2
  import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
3
3
  //#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
4
4
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("../../chunk-Cek0wNdY.js");
3
- const require_dist = require("../../dist-DMEGlqg6.js");
3
+ const require_dist = require("../../dist-C2_1HCpW.js");
4
4
  //#region src/builtins/liveness-monitor/liveness-checks.ts
5
5
  var NO_DEVICES = "liveness:no-devices";
6
6
  var ALL_OFFLINE = "liveness:all-devices-offline";
@@ -1,4 +1,4 @@
1
- import { Gt as EventCategory, Mt as createEvent, vt as errMsg, yt as BaseAddon } from "../../dist-D4Vmj8iw.mjs";
1
+ import { Gt as EventCategory, Mt as createEvent, vt as errMsg, yt as BaseAddon } from "../../dist-DCTpBXm4.mjs";
2
2
  //#region src/builtins/liveness-monitor/liveness-checks.ts
3
3
  var NO_DEVICES = "liveness:no-devices";
4
4
  var ALL_OFFLINE = "liveness:all-devices-offline";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DMEGlqg6.js");
6
+ const require_dist = require("../../dist-C2_1HCpW.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  node_crypto = require_chunk.__toESM(node_crypto);
9
9
  let crypto$1 = require("crypto");
@@ -1,5 +1,5 @@
1
1
  import { i as __require, o as __toESM, t as __commonJSMin } from "../../chunk-CNf5ZN-e.mjs";
2
- import { S as authProviderCapability, _ as UserRecordSchema, ht as userManagementCapability, m as ScopedTokenSchema, r as ApiKeyRecordSchema, yt as BaseAddon } from "../../dist-D4Vmj8iw.mjs";
2
+ import { S as authProviderCapability, _ as UserRecordSchema, ht as userManagementCapability, m as ScopedTokenSchema, r as ApiKeyRecordSchema, yt as BaseAddon } from "../../dist-DCTpBXm4.mjs";
3
3
  import * as crypto$2 from "node:crypto";
4
4
  import { createHash, randomUUID, timingSafeEqual } from "node:crypto";
5
5
  import nodeCrypto from "crypto";
@@ -39,6 +39,11 @@ interface LocalNetworkConfig {
39
39
  * different address after a reboot.
40
40
  */
41
41
  readonly notificationBaseUrl: string;
42
+ /**
43
+ * Base URLs the SDK / viewer should race. Empty = AUTO (LAN IPv4 + public
44
+ * tunnel). Stored verbatim, same contract as `notificationBaseUrl`.
45
+ */
46
+ readonly viewerBaseUrls: readonly string[];
42
47
  /** LAN HTTP listener. Default true — native apps skip the private cert. */
43
48
  readonly httpEnabled: boolean;
44
49
  /** Dedicated HTTP port. Must not equal the HTTPS listen port. */
@@ -70,6 +75,13 @@ export declare class LocalNetworkAddon extends BaseAddon<LocalNetworkConfig> {
70
75
  * rather than a link that 404s).
71
76
  */
72
77
  private resolveNotificationEndpoint;
78
+ private snapshotViewerEndpoints;
79
+ /**
80
+ * Palette shown in the Network tab: LAN IPv4, stable LAN IPv6, public,
81
+ * mesh. The viewer HTTP/WS race is a subset (`selectViewerEndpoints`) —
82
+ * IPv6 stays in this list because ICE/WebRTC gathers it regardless.
83
+ */
84
+ private buildAdvertisedEndpoints;
73
85
  protected onInitialize(): Promise<ProviderRegistration[]>;
74
86
  protected globalSettingsSchema(): import('@camstack/types').ConfigUISchema;
75
87
  protected onConfigChanged(): Promise<void>;
@@ -157,8 +169,8 @@ export declare function enumerateOsInterfaces(ifaces: NodeJS.Dict<readonly OsNet
157
169
  * allowlist = no-op (every interface passes); otherwise only entries
158
170
  * whose `address` matches an allowlist entry remain. IPv6 matches the
159
171
  * allowlisted /64 so a rotated privacy address does not hide the live
160
- * GUA. Loopback always survives so the SDK keeps `127.0.0.1` as the
161
- * last-resort fallback.
172
+ * GUA. Loopback is not an advertised client route and is not forced
173
+ * through.
162
174
  */
163
175
  export declare function applyAllowlist(interfaces: readonly LocalInterface[], allowed: readonly string[]): readonly LocalInterface[];
164
176
  /**
@@ -194,6 +206,16 @@ export interface LanHttpAdvertisement {
194
206
  readonly localHostname: string | null;
195
207
  }
196
208
  export declare function buildEndpoints(interfaces: readonly LocalInterface[], port: number, includeLoopback: boolean, ipv4Only: boolean, publicHostname: string, scheme?: 'http' | 'https', meshEndpoint?: MeshEndpointCache | null, lanHttp?: LanHttpAdvertisement | null): ConnectionEndpoint[];
209
+ /** AUTO viewer race: LAN IPv4 + the public tunnel. Never IPv6, mesh, or loopback. */
210
+ export declare function isDefaultViewerEndpoint(endpoint: ConnectionEndpoint): boolean;
211
+ /**
212
+ * The URLs the SDK should race for API / viewer access.
213
+ *
214
+ * Empty `viewerBaseUrls` = AUTO (IPv4 + public tunnel). A non-empty list is
215
+ * the operator's pin; if none of those URLs are in the current palette,
216
+ * fall back to AUTO rather than racing an empty set.
217
+ */
218
+ export declare function selectViewerEndpoints(endpoints: readonly ConnectionEndpoint[], viewerBaseUrls: readonly string[]): ConnectionEndpoint[];
197
219
  /**
198
220
  * First-boot heuristic: which addresses should the allowlist start
199
221
  * with? Includes LAN + Wi-Fi IPv4 addresses + plausible IPv6:
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("../../chunk-Cek0wNdY.js");
3
- const require_dist = require("../../dist-DMEGlqg6.js");
3
+ const require_dist = require("../../dist-C2_1HCpW.js");
4
4
  const require_lan_http_bind = require("../../lan-http-bind-DmgpFP6_.js");
5
5
  let node_fs_promises = require("node:fs/promises");
6
6
  let node_path = require("node:path");
@@ -200,6 +200,7 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
200
200
  allowedAddresses: [],
201
201
  bootSeeded: false,
202
202
  notificationBaseUrl: "",
203
+ viewerBaseUrls: [],
203
204
  httpEnabled: true,
204
205
  httpPort: require_lan_http_bind.DEFAULT_LAN_HTTP_PORT,
205
206
  localHostname: ""
@@ -220,6 +221,31 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
220
221
  if (mesh !== null && mesh.host !== "") return `https://${mesh.host}:${mesh.port}`;
221
222
  return null;
222
223
  }
224
+ async snapshotViewerEndpoints() {
225
+ const selected = selectViewerEndpoints(await this.buildAdvertisedEndpoints(false, false, "http", (await this.resolveAdvertisedListenPort(null)).port), this.config.viewerBaseUrls);
226
+ return {
227
+ baseUrls: this.config.viewerBaseUrls,
228
+ resolved: selected.map((e) => e.baseUrl)
229
+ };
230
+ }
231
+ /**
232
+ * Palette shown in the Network tab: LAN IPv4, stable LAN IPv6, public,
233
+ * mesh. The viewer HTTP/WS race is a subset (`selectViewerEndpoints`) —
234
+ * IPv6 stays in this list because ICE/WebRTC gathers it regardless.
235
+ */
236
+ async buildAdvertisedEndpoints(includeLoopback, ipv4Only, scheme, httpsPort) {
237
+ const allow = this.config.allowedAddresses;
238
+ const interfaces = applyAllowlist(this.enumerate(), allow);
239
+ await this.reconcileMeshEndpoint();
240
+ const httpState = require_lan_http_bind.readLanHttpState();
241
+ return buildEndpoints(interfaces, httpsPort, includeLoopback, ipv4Only, this.publicHostname, scheme, this.meshEndpoint, {
242
+ enabled: this.config.httpEnabled !== false,
243
+ listening: httpState.listening,
244
+ httpPort: this.resolvedHttpPort(),
245
+ httpsPort,
246
+ localHostname: this.config.localHostname || null
247
+ });
248
+ }
223
249
  async onInitialize() {
224
250
  if (!this.config.bootSeeded) {
225
251
  const seed = autoSeedAllowlist(this.enumerate());
@@ -237,27 +263,16 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
237
263
  }),
238
264
  getPreferred: async () => pickPreferred(applyAllowlist(this.enumerate(), this.config.allowedAddresses)),
239
265
  getConnectionEndpoints: async (input) => {
240
- const includeLoopback = input.includeLoopback ?? true;
241
- const ipv4Only = input.ipv4Only ?? false;
266
+ const includeLoopback = input.includeLoopback ?? false;
242
267
  const scheme = input.scheme ?? "http";
243
- const allow = this.config.allowedAddresses;
244
- const interfaces = applyAllowlist(this.enumerate(), allow);
245
268
  const localPort = await this.resolveAdvertisedListenPort(input.port ?? null);
246
269
  if (input.port !== void 0 && input.port !== localPort.port) this.ctx.logger.info("local-network: caller port hint overridden", { meta: {
247
270
  hint: input.port,
248
271
  advertised: localPort.port,
249
272
  source: localPort.source
250
273
  } });
251
- await this.reconcileMeshEndpoint();
252
- const httpState = require_lan_http_bind.readLanHttpState();
253
274
  return {
254
- endpoints: buildEndpoints(interfaces, localPort.port, includeLoopback, ipv4Only, this.publicHostname, scheme, this.meshEndpoint, {
255
- enabled: this.config.httpEnabled !== false,
256
- listening: httpState.listening,
257
- httpPort: this.resolvedHttpPort(),
258
- httpsPort: localPort.port,
259
- localHostname: this.config.localHostname || null
260
- }),
275
+ endpoints: await this.buildAdvertisedEndpoints(includeLoopback, input.ipv4Only ?? false, scheme, localPort.port),
261
276
  localPort
262
277
  };
263
278
  },
@@ -273,6 +288,16 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
273
288
  resolved: this.resolveNotificationEndpoint()
274
289
  };
275
290
  },
291
+ getViewerEndpoints: async () => this.snapshotViewerEndpoints(),
292
+ setViewerEndpoints: async ({ baseUrls }) => {
293
+ const cleaned = [...new Set(baseUrls.filter((u) => u.length > 0))];
294
+ await this.updateGlobalSettings({ viewerBaseUrls: cleaned });
295
+ this.ctx.logger.info("local-network: viewer endpoints set", { meta: {
296
+ count: cleaned.length,
297
+ auto: cleaned.length === 0
298
+ } });
299
+ return this.snapshotViewerEndpoints();
300
+ },
276
301
  getAllowedAddresses: async () => ({ addresses: this.config.allowedAddresses }),
277
302
  resetAllowlistToBestMatch: async () => {
278
303
  const seed = autoSeedAllowlist(this.enumerate());
@@ -675,12 +700,12 @@ function enumerateOsInterfaces(ifaces, ipv6Flags) {
675
700
  * allowlist = no-op (every interface passes); otherwise only entries
676
701
  * whose `address` matches an allowlist entry remain. IPv6 matches the
677
702
  * allowlisted /64 so a rotated privacy address does not hide the live
678
- * GUA. Loopback always survives so the SDK keeps `127.0.0.1` as the
679
- * last-resort fallback.
703
+ * GUA. Loopback is not an advertised client route and is not forced
704
+ * through.
680
705
  */
681
706
  function applyAllowlist(interfaces, allowed) {
682
707
  if (allowed.length === 0) return interfaces;
683
- return interfaces.filter((i) => i.kind === "loopback" || ipv6AllowlistMatches(i.address, allowed) || allowed.includes(i.address));
708
+ return interfaces.filter((i) => ipv6AllowlistMatches(i.address, allowed) || allowed.includes(i.address));
684
709
  }
685
710
  /**
686
711
  * Rank interfaces and pick the auto-selected outbound one. See the
@@ -775,6 +800,25 @@ function buildEndpoints(interfaces, port, includeLoopback, ipv4Only, publicHostn
775
800
  });
776
801
  return out.toSorted((a, b) => a.priority - b.priority);
777
802
  }
803
+ /** AUTO viewer race: LAN IPv4 + the public tunnel. Never IPv6, mesh, or loopback. */
804
+ function isDefaultViewerEndpoint(endpoint) {
805
+ if (endpoint.kind === "lan-ipv4") return true;
806
+ return endpoint.kind === "public" && endpoint.interfaceKind === "public";
807
+ }
808
+ /**
809
+ * The URLs the SDK should race for API / viewer access.
810
+ *
811
+ * Empty `viewerBaseUrls` = AUTO (IPv4 + public tunnel). A non-empty list is
812
+ * the operator's pin; if none of those URLs are in the current palette,
813
+ * fall back to AUTO rather than racing an empty set.
814
+ */
815
+ function selectViewerEndpoints(endpoints, viewerBaseUrls) {
816
+ const auto = endpoints.filter(isDefaultViewerEndpoint);
817
+ if (viewerBaseUrls.length === 0) return auto;
818
+ const wanted = new Set(viewerBaseUrls);
819
+ const explicit = endpoints.filter((e) => wanted.has(e.baseUrl));
820
+ return explicit.length > 0 ? explicit : auto;
821
+ }
778
822
  /**
779
823
  * First-boot heuristic: which addresses should the allowlist start
780
824
  * with? Includes LAN + Wi-Fi IPv4 addresses + plausible IPv6:
@@ -912,10 +956,12 @@ exports.classifyKind = classifyKind;
912
956
  exports.enumerateOsInterfaces = enumerateOsInterfaces;
913
957
  exports.explainNonPlausible = explainNonPlausible;
914
958
  exports.ipv6Prefix64Key = ipv6Prefix64Key;
959
+ exports.isDefaultViewerEndpoint = isDefaultViewerEndpoint;
915
960
  exports.isPlausibleAutoSeed = isPlausibleAutoSeed;
916
961
  exports.parseProcIfInet6 = parseProcIfInet6;
917
962
  exports.pickPreferred = pickPreferred;
918
963
  exports.prefixLen = prefixLen;
919
964
  exports.reconcileAllowlist = reconcileAllowlist;
920
965
  exports.resolveAdvertisedPort = resolveAdvertisedPort;
966
+ exports.selectViewerEndpoints = selectViewerEndpoints;
921
967
  exports.shouldAdvertiseIpv6 = shouldAdvertiseIpv6;
@@ -1,4 +1,4 @@
1
- import { Gt as EventCategory, Y as localNetworkCapability, yt as BaseAddon } from "../../dist-D4Vmj8iw.mjs";
1
+ import { Gt as EventCategory, Y as localNetworkCapability, yt as BaseAddon } from "../../dist-DCTpBXm4.mjs";
2
2
  import { c as readExtraSans, d as writeExtraSans, f as writeTlsMode, g as reissueTlsLeaf, l as readTlsAccessStatus, m as ensureTlsCert, o as readLanHttpState, p as validateUploadedTls, r as applyLanHttp, t as DEFAULT_LAN_HTTP_PORT, u as readTlsMode } from "../../lan-http-bind-jKrj6OjQ.mjs";
3
3
  import { mkdir, writeFile } from "node:fs/promises";
4
4
  import { join } from "node:path";
@@ -197,6 +197,7 @@ var LocalNetworkAddon = class extends BaseAddon {
197
197
  allowedAddresses: [],
198
198
  bootSeeded: false,
199
199
  notificationBaseUrl: "",
200
+ viewerBaseUrls: [],
200
201
  httpEnabled: true,
201
202
  httpPort: DEFAULT_LAN_HTTP_PORT,
202
203
  localHostname: ""
@@ -217,6 +218,31 @@ var LocalNetworkAddon = class extends BaseAddon {
217
218
  if (mesh !== null && mesh.host !== "") return `https://${mesh.host}:${mesh.port}`;
218
219
  return null;
219
220
  }
221
+ async snapshotViewerEndpoints() {
222
+ const selected = selectViewerEndpoints(await this.buildAdvertisedEndpoints(false, false, "http", (await this.resolveAdvertisedListenPort(null)).port), this.config.viewerBaseUrls);
223
+ return {
224
+ baseUrls: this.config.viewerBaseUrls,
225
+ resolved: selected.map((e) => e.baseUrl)
226
+ };
227
+ }
228
+ /**
229
+ * Palette shown in the Network tab: LAN IPv4, stable LAN IPv6, public,
230
+ * mesh. The viewer HTTP/WS race is a subset (`selectViewerEndpoints`) —
231
+ * IPv6 stays in this list because ICE/WebRTC gathers it regardless.
232
+ */
233
+ async buildAdvertisedEndpoints(includeLoopback, ipv4Only, scheme, httpsPort) {
234
+ const allow = this.config.allowedAddresses;
235
+ const interfaces = applyAllowlist(this.enumerate(), allow);
236
+ await this.reconcileMeshEndpoint();
237
+ const httpState = readLanHttpState();
238
+ return buildEndpoints(interfaces, httpsPort, includeLoopback, ipv4Only, this.publicHostname, scheme, this.meshEndpoint, {
239
+ enabled: this.config.httpEnabled !== false,
240
+ listening: httpState.listening,
241
+ httpPort: this.resolvedHttpPort(),
242
+ httpsPort,
243
+ localHostname: this.config.localHostname || null
244
+ });
245
+ }
220
246
  async onInitialize() {
221
247
  if (!this.config.bootSeeded) {
222
248
  const seed = autoSeedAllowlist(this.enumerate());
@@ -234,27 +260,16 @@ var LocalNetworkAddon = class extends BaseAddon {
234
260
  }),
235
261
  getPreferred: async () => pickPreferred(applyAllowlist(this.enumerate(), this.config.allowedAddresses)),
236
262
  getConnectionEndpoints: async (input) => {
237
- const includeLoopback = input.includeLoopback ?? true;
238
- const ipv4Only = input.ipv4Only ?? false;
263
+ const includeLoopback = input.includeLoopback ?? false;
239
264
  const scheme = input.scheme ?? "http";
240
- const allow = this.config.allowedAddresses;
241
- const interfaces = applyAllowlist(this.enumerate(), allow);
242
265
  const localPort = await this.resolveAdvertisedListenPort(input.port ?? null);
243
266
  if (input.port !== void 0 && input.port !== localPort.port) this.ctx.logger.info("local-network: caller port hint overridden", { meta: {
244
267
  hint: input.port,
245
268
  advertised: localPort.port,
246
269
  source: localPort.source
247
270
  } });
248
- await this.reconcileMeshEndpoint();
249
- const httpState = readLanHttpState();
250
271
  return {
251
- endpoints: buildEndpoints(interfaces, localPort.port, includeLoopback, ipv4Only, this.publicHostname, scheme, this.meshEndpoint, {
252
- enabled: this.config.httpEnabled !== false,
253
- listening: httpState.listening,
254
- httpPort: this.resolvedHttpPort(),
255
- httpsPort: localPort.port,
256
- localHostname: this.config.localHostname || null
257
- }),
272
+ endpoints: await this.buildAdvertisedEndpoints(includeLoopback, input.ipv4Only ?? false, scheme, localPort.port),
258
273
  localPort
259
274
  };
260
275
  },
@@ -270,6 +285,16 @@ var LocalNetworkAddon = class extends BaseAddon {
270
285
  resolved: this.resolveNotificationEndpoint()
271
286
  };
272
287
  },
288
+ getViewerEndpoints: async () => this.snapshotViewerEndpoints(),
289
+ setViewerEndpoints: async ({ baseUrls }) => {
290
+ const cleaned = [...new Set(baseUrls.filter((u) => u.length > 0))];
291
+ await this.updateGlobalSettings({ viewerBaseUrls: cleaned });
292
+ this.ctx.logger.info("local-network: viewer endpoints set", { meta: {
293
+ count: cleaned.length,
294
+ auto: cleaned.length === 0
295
+ } });
296
+ return this.snapshotViewerEndpoints();
297
+ },
273
298
  getAllowedAddresses: async () => ({ addresses: this.config.allowedAddresses }),
274
299
  resetAllowlistToBestMatch: async () => {
275
300
  const seed = autoSeedAllowlist(this.enumerate());
@@ -672,12 +697,12 @@ function enumerateOsInterfaces(ifaces, ipv6Flags) {
672
697
  * allowlist = no-op (every interface passes); otherwise only entries
673
698
  * whose `address` matches an allowlist entry remain. IPv6 matches the
674
699
  * allowlisted /64 so a rotated privacy address does not hide the live
675
- * GUA. Loopback always survives so the SDK keeps `127.0.0.1` as the
676
- * last-resort fallback.
700
+ * GUA. Loopback is not an advertised client route and is not forced
701
+ * through.
677
702
  */
678
703
  function applyAllowlist(interfaces, allowed) {
679
704
  if (allowed.length === 0) return interfaces;
680
- return interfaces.filter((i) => i.kind === "loopback" || ipv6AllowlistMatches(i.address, allowed) || allowed.includes(i.address));
705
+ return interfaces.filter((i) => ipv6AllowlistMatches(i.address, allowed) || allowed.includes(i.address));
681
706
  }
682
707
  /**
683
708
  * Rank interfaces and pick the auto-selected outbound one. See the
@@ -772,6 +797,25 @@ function buildEndpoints(interfaces, port, includeLoopback, ipv4Only, publicHostn
772
797
  });
773
798
  return out.toSorted((a, b) => a.priority - b.priority);
774
799
  }
800
+ /** AUTO viewer race: LAN IPv4 + the public tunnel. Never IPv6, mesh, or loopback. */
801
+ function isDefaultViewerEndpoint(endpoint) {
802
+ if (endpoint.kind === "lan-ipv4") return true;
803
+ return endpoint.kind === "public" && endpoint.interfaceKind === "public";
804
+ }
805
+ /**
806
+ * The URLs the SDK should race for API / viewer access.
807
+ *
808
+ * Empty `viewerBaseUrls` = AUTO (IPv4 + public tunnel). A non-empty list is
809
+ * the operator's pin; if none of those URLs are in the current palette,
810
+ * fall back to AUTO rather than racing an empty set.
811
+ */
812
+ function selectViewerEndpoints(endpoints, viewerBaseUrls) {
813
+ const auto = endpoints.filter(isDefaultViewerEndpoint);
814
+ if (viewerBaseUrls.length === 0) return auto;
815
+ const wanted = new Set(viewerBaseUrls);
816
+ const explicit = endpoints.filter((e) => wanted.has(e.baseUrl));
817
+ return explicit.length > 0 ? explicit : auto;
818
+ }
775
819
  /**
776
820
  * First-boot heuristic: which addresses should the allowlist start
777
821
  * with? Includes LAN + Wi-Fi IPv4 addresses + plausible IPv6:
@@ -900,4 +944,4 @@ function readLinuxIpv6Flags() {
900
944
  }
901
945
  }
902
946
  //#endregion
903
- export { ALLOWLIST_RECONCILE_INTERVAL_MS, LocalNetworkAddon, applyAllowlist, autoSeedAllowlist, buildEndpoints, classifyKind, enumerateOsInterfaces, explainNonPlausible, ipv6Prefix64Key, isPlausibleAutoSeed, parseProcIfInet6, pickPreferred, prefixLen, reconcileAllowlist, resolveAdvertisedPort, shouldAdvertiseIpv6 };
947
+ export { ALLOWLIST_RECONCILE_INTERVAL_MS, LocalNetworkAddon, applyAllowlist, autoSeedAllowlist, buildEndpoints, classifyKind, enumerateOsInterfaces, explainNonPlausible, ipv6Prefix64Key, isDefaultViewerEndpoint, isPlausibleAutoSeed, parseProcIfInet6, pickPreferred, prefixLen, reconcileAllowlist, resolveAdvertisedPort, selectViewerEndpoints, shouldAdvertiseIpv6 };
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DMEGlqg6.js");
6
+ const require_dist = require("../../dist-C2_1HCpW.js");
7
7
  //#region src/builtins/loki-logging/loki-payload.ts
8
8
  /**
9
9
  * Loki rejects a label name that is not a valid Prometheus label
@@ -1,4 +1,4 @@
1
- import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-D4Vmj8iw.mjs";
1
+ import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-DCTpBXm4.mjs";
2
2
  //#region src/builtins/loki-logging/loki-payload.ts
3
3
  /**
4
4
  * Loki rejects a label name that is not a valid Prometheus label
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DMEGlqg6.js");
6
+ const require_dist = require("../../dist-C2_1HCpW.js");
7
7
  let node_child_process = require("node:child_process");
8
8
  let node_util = require("node:util");
9
9
  let node_os = require("node:os");
@@ -1,4 +1,4 @@
1
- import { $ as metricsProviderCapability, Gt as EventCategory, Mt as createEvent, yt as BaseAddon } from "../../dist-D4Vmj8iw.mjs";
1
+ import { $ as metricsProviderCapability, Gt as EventCategory, Mt as createEvent, yt as BaseAddon } from "../../dist-DCTpBXm4.mjs";
2
2
  import { execFile, execFileSync } from "node:child_process";
3
3
  import { promisify } from "node:util";
4
4
  import * as os from "node:os";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DMEGlqg6.js");
6
+ const require_dist = require("../../dist-C2_1HCpW.js");
7
7
  let node_child_process = require("node:child_process");
8
8
  let node_util = require("node:util");
9
9
  let node_os = require("node:os");
@@ -1,5 +1,5 @@
1
1
  import { o as __toESM } from "../../chunk-CNf5ZN-e.mjs";
2
- import { Gt as EventCategory, L as enumerateInferenceDevices, Pt as emitReadiness, ct as scoreRuntimes, rt as platformProbeCapability, vt as errMsg, yt as BaseAddon } from "../../dist-D4Vmj8iw.mjs";
2
+ import { Gt as EventCategory, L as enumerateInferenceDevices, Pt as emitReadiness, ct as scoreRuntimes, rt as platformProbeCapability, vt as errMsg, yt as BaseAddon } from "../../dist-DCTpBXm4.mjs";
3
3
  import { execFile } from "node:child_process";
4
4
  import { promisify } from "node:util";
5
5
  import * as os from "node:os";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DMEGlqg6.js");
6
+ const require_dist = require("../../dist-C2_1HCpW.js");
7
7
  //#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
8
8
  /**
9
9
  * Reconcile the durable `enabledProviders` set against authoritative