camstack 1.2.51 → 1.2.53

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.
@@ -14522,7 +14522,7 @@ function date4(params) {
14522
14522
  // ../../node_modules/zod/v4/classic/external.js
14523
14523
  config(en_default());
14524
14524
 
14525
- // ../types/dist/sleep-Dolp38qx.mjs
14525
+ // ../types/dist/sleep-C9C8EoK8.mjs
14526
14526
  var WELL_KNOWN_TABS = [
14527
14527
  {
14528
14528
  id: "overview",
@@ -17070,6 +17070,10 @@ var addonSettingsCapability = {
17070
17070
  kind: "mutation",
17071
17071
  auth: "admin"
17072
17072
  }),
17073
+ getIntegrationSettings: method(external_exports.object({
17074
+ addonId: external_exports.string(),
17075
+ nodeId: external_exports.string().optional()
17076
+ }), SettingsSchemaWithValuesSchema.nullable()),
17073
17077
  getDeviceSettings: method(external_exports.object({
17074
17078
  addonId: external_exports.string(),
17075
17079
  deviceId: external_exports.number(),
@@ -38487,6 +38491,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
38487
38491
  addonId: null,
38488
38492
  access: "view"
38489
38493
  },
38494
+ "addonSettings.getIntegrationSettings": {
38495
+ capName: "addon-settings",
38496
+ capScope: "system",
38497
+ addonId: null,
38498
+ access: "view"
38499
+ },
38490
38500
  "addonSettings.updateDeviceSettings": {
38491
38501
  capName: "addon-settings",
38492
38502
  capScope: "system",
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runDiscover
4
- } from "./chunk-HPFKAZ3A.js";
4
+ } from "./chunk-P6IF6IX5.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-EJ6BGNVY.js");
41
+ await import("./launcher-3YAJ644E.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-EJ6BGNVY.js");
86
+ await import("./launcher-3YAJ644E.js");
87
87
  }
88
88
 
89
89
  // src/commands/setup.ts
@@ -1130,7 +1130,7 @@ function isUnknown(_value) {
1130
1130
  return true;
1131
1131
  }
1132
1132
  async function resolveServerInteractive(presetNamespace) {
1133
- const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-OVQWH2QN.js");
1133
+ const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-255INDLH.js");
1134
1134
  if (presetNamespace) {
1135
1135
  const spinner4 = clack.spinner();
1136
1136
  spinner4.start(`Discovering hub on LAN (namespace "${presetNamespace}")`);
@@ -5,7 +5,7 @@ import {
5
5
  filterHubNodes,
6
6
  resolveHubFromDiscovered,
7
7
  runDiscover
8
- } from "./chunk-HPFKAZ3A.js";
8
+ } from "./chunk-P6IF6IX5.js";
9
9
  import "./chunk-LMMQX4CK.js";
10
10
  export {
11
11
  DEFAULT_HUB_HTTPS_PORT,
@@ -23633,9 +23633,9 @@ var require_zod = __commonJS({
23633
23633
  }
23634
23634
  });
23635
23635
 
23636
- // ../system/dist/dist-Dl6MFXPr.js
23637
- var require_dist_Dl6MFXPr = __commonJS({
23638
- "../system/dist/dist-Dl6MFXPr.js"(exports) {
23636
+ // ../system/dist/dist-DdEXjTDo.js
23637
+ var require_dist_DdEXjTDo = __commonJS({
23638
+ "../system/dist/dist-DdEXjTDo.js"(exports) {
23639
23639
  "use strict";
23640
23640
  var zod = require_zod();
23641
23641
  var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
@@ -24231,6 +24231,40 @@ var require_dist_Dl6MFXPr = __commonJS({
24231
24231
  deviceSettingsSchema() {
24232
24232
  return null;
24233
24233
  }
24234
+ /**
24235
+ * INTEGRATION-LEVEL SETTINGS — declare which of this addon's global sections
24236
+ * ARE the configuration of its integration.
24237
+ *
24238
+ * Return the `ConfigSection.id`s, from {@link globalSettingsSchema}, that an
24239
+ * operator should find on the addon's integration page (System →
24240
+ * Integrations → <name>) rather than only in the cluster-wide list of every
24241
+ * addon. Empty (the default) means the addon has no integration-level
24242
+ * settings and no such surface is offered — this is opt-in, because whether
24243
+ * an addon's configuration IS its integration's configuration depends on the
24244
+ * nature of the integration.
24245
+ *
24246
+ * WHAT THIS IS NOT. It is not a scope. The selected sections keep living in
24247
+ * the ONE global schema, in the ONE addon store, written by the ONE
24248
+ * `updateGlobalSettings` path. There is deliberately no
24249
+ * `updateIntegrationSettings`: a second write path is how a surface acquires
24250
+ * a second store key, and this repo has shipped that twice (`btmPath@hub`,
24251
+ * D266). Selecting sections cannot introduce a key that selecting cannot.
24252
+ *
24253
+ * WHY IT IS A LIST OF SECTION IDS AND NOT A MARKER ON THE SECTION.
24254
+ * `ConfigFieldBase` used to carry `scope?: 'device' | 'global'` and it was
24255
+ * removed with the reason recorded at
24256
+ * `packages/types/src/interfaces/config-ui.ts:249` — *"a field's scope is
24257
+ * determined by WHICH schema it lives in, not by a field-level marker."* A
24258
+ * marker sprinkled across sections also has to borrow a field that already
24259
+ * means something else; borrowing `section.tab` put the literal word
24260
+ * "integration" into an operator-facing tab bar, because `tab` means "how to
24261
+ * GROUP this visually" and cannot also mean "where this lives" (D269
24262
+ * supersedes D268). One declaration, in one place, next to the schema whose
24263
+ * ids it names.
24264
+ */
24265
+ integrationSettingSections() {
24266
+ return [];
24267
+ }
24234
24268
  async getGlobalSettings(overlay, cap, nodeId) {
24235
24269
  const schema = this.globalSettingsSchema(cap);
24236
24270
  if (!schema) return { sections: [] };
@@ -24241,6 +24275,55 @@ var require_dist_Dl6MFXPr = __commonJS({
24241
24275
  } : projected);
24242
24276
  }
24243
24277
  /**
24278
+ * The integration-level view of this addon's settings: exactly the sections
24279
+ * named by {@link integrationSettingSections}, hydrated from the SAME store
24280
+ * `getGlobalSettings` reads, and narrowed to cluster-scoped fields.
24281
+ *
24282
+ * Returns `null` when the addon declared nothing — an addon that opts out has
24283
+ * no integration settings surface at all, rather than an empty one that reads
24284
+ * as a failed load.
24285
+ *
24286
+ * Three properties hold BY CONSTRUCTION, which is why they are here in core
24287
+ * and not in whichever UI happens to render this:
24288
+ *
24289
+ * 1. **One key.** The payload is a SUBSET of the global schema, so a field
24290
+ * shown here is the same field, with the same bare key, that the addon's
24291
+ * own page shows. There is no integration-specific writer — callers save
24292
+ * through `updateGlobalSettings` — so a second store key is unreachable,
24293
+ * not merely discouraged.
24294
+ * 2. **No node scope.** `perNode: true` fields are DROPPED. Their store key
24295
+ * is `<key>@<nodeId>` and an integration is not a node; whichever node
24296
+ * such a field silently picked would be a wrong answer for the operator
24297
+ * who opened the page (D266).
24298
+ * 3. **No silent typo.** A declared id that names no section throws. The
24299
+ * alternative — skip it — turns a rename into a surface that quietly
24300
+ * empties, which looks exactly like an addon with nothing to configure.
24301
+ */
24302
+ async getIntegrationSettings(nodeId) {
24303
+ const declared = this.integrationSettingSections();
24304
+ if (declared.length === 0) return null;
24305
+ const schema = this.globalSettingsSchema();
24306
+ if (!schema) throw new Error(`${this.constructor.name}: integrationSettingSections() names [${declared.join(", ")}] but globalSettingsSchema() returns null.`);
24307
+ const byId = new Map(schema.sections.map((section) => [section.id, section]));
24308
+ const sections = [];
24309
+ for (const id of declared) {
24310
+ const section = byId.get(id);
24311
+ if (!section) throw new Error(`${this.constructor.name}: integrationSettingSections() names unknown section "${id}". Known sections: [${[...byId.keys()].join(", ")}].`);
24312
+ const fields = dropPerNodeFields(section.fields);
24313
+ if (fields.length === 0) continue;
24314
+ sections.push({
24315
+ ...section,
24316
+ fields
24317
+ });
24318
+ }
24319
+ if (sections.length === 0) return null;
24320
+ const projected = await this.resolveGlobalStore(nodeId);
24321
+ return hydrateSchema({
24322
+ ...schema,
24323
+ sections
24324
+ }, projected);
24325
+ }
24326
+ /**
24244
24327
  * The raw addon store PROJECTED onto the target node's bare per-node keys:
24245
24328
  * every `perNode: true` field carries THAT node's scoped value on its bare
24246
24329
  * key (absent scoped key ⇒ key absent, so the schema `default` wins — no
@@ -24540,6 +24623,33 @@ var require_dist_Dl6MFXPr = __commonJS({
24540
24623
  return {};
24541
24624
  }
24542
24625
  };
24626
+ function dropPerNodeFields(fields) {
24627
+ const kept = [];
24628
+ for (const field of fields) {
24629
+ if (field.type === "group") {
24630
+ const inner = dropPerNodeFields(field.fields);
24631
+ if (inner.length > 0) kept.push({
24632
+ ...field,
24633
+ fields: inner
24634
+ });
24635
+ continue;
24636
+ }
24637
+ if (field.type === "sub-tabs") {
24638
+ const tabs = field.tabs.map((tab) => ({
24639
+ ...tab,
24640
+ fields: dropPerNodeFields(tab.fields)
24641
+ })).filter((tab) => tab.fields.length > 0);
24642
+ if (tabs.length > 0) kept.push({
24643
+ ...field,
24644
+ tabs
24645
+ });
24646
+ continue;
24647
+ }
24648
+ if ("perNode" in field && field.perNode === true) continue;
24649
+ kept.push(field);
24650
+ }
24651
+ return kept;
24652
+ }
24543
24653
  function collectPerNodeFieldKeys(fields) {
24544
24654
  const collected = [];
24545
24655
  for (const field of fields) {
@@ -27528,6 +27638,10 @@ var require_dist_Dl6MFXPr = __commonJS({
27528
27638
  kind: "mutation",
27529
27639
  auth: "admin"
27530
27640
  }),
27641
+ getIntegrationSettings: method(zod.z.object({
27642
+ addonId: zod.z.string(),
27643
+ nodeId: zod.z.string().optional()
27644
+ }), SettingsSchemaWithValuesSchema.nullable()),
27531
27645
  getDeviceSettings: method(zod.z.object({
27532
27646
  addonId: zod.z.string(),
27533
27647
  deviceId: zod.z.number(),
@@ -48902,7 +49016,7 @@ var require_dist_Dl6MFXPr = __commonJS({
48902
49016
  "ffmpeg.binaryPath": "ffmpeg",
48903
49017
  "ffmpeg.hwAccel": "auto",
48904
49018
  "ffmpeg.threadCount": 0,
48905
- "auth.tokenExpiry": "7d"
49019
+ "auth.tokenExpiry": "30d"
48906
49020
  };
48907
49021
  var AccessoryKind = {
48908
49022
  Siren: DeviceRole.Siren,
@@ -49658,6 +49772,12 @@ var require_dist_Dl6MFXPr = __commonJS({
49658
49772
  addonId: null,
49659
49773
  access: "view"
49660
49774
  },
49775
+ "addonSettings.getIntegrationSettings": {
49776
+ capName: "addon-settings",
49777
+ capScope: "system",
49778
+ addonId: null,
49779
+ access: "view"
49780
+ },
49661
49781
  "addonSettings.updateDeviceSettings": {
49662
49782
  capName: "addon-settings",
49663
49783
  capScope: "system",
@@ -58395,7 +58515,7 @@ var require_alerts_addon = __commonJS({
58395
58515
  [Symbol.toStringTag]: { value: "Module" }
58396
58516
  });
58397
58517
  require_chunk_Cek0wNdY();
58398
- var require_dist10 = require_dist_Dl6MFXPr();
58518
+ var require_dist10 = require_dist_DdEXjTDo();
58399
58519
  function selectExpired(alerts, cutoffMs) {
58400
58520
  return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
58401
58521
  }
@@ -59214,7 +59334,7 @@ var require_console_logging = __commonJS({
59214
59334
  [Symbol.toStringTag]: { value: "Module" }
59215
59335
  });
59216
59336
  require_chunk_Cek0wNdY();
59217
- var require_dist10 = require_dist_Dl6MFXPr();
59337
+ var require_dist10 = require_dist_DdEXjTDo();
59218
59338
  var require_formatter = require_formatter_DqAKDlvN();
59219
59339
  var LEVEL_RANK = {
59220
59340
  debug: 0,
@@ -59308,7 +59428,7 @@ var require_core_blocks_addon = __commonJS({
59308
59428
  "use strict";
59309
59429
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
59310
59430
  var require_chunk = require_chunk_Cek0wNdY();
59311
- var require_dist10 = require_dist_Dl6MFXPr();
59431
+ var require_dist10 = require_dist_DdEXjTDo();
59312
59432
  var node_crypto = __require("crypto");
59313
59433
  var node_fs_promises = __require("fs/promises");
59314
59434
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -60205,28 +60325,88 @@ var require_core_blocks = __commonJS({
60205
60325
  }
60206
60326
  });
60207
60327
 
60208
- // ../system/dist/retired-settings-keys-6w_JOqBg.js
60209
- var require_retired_settings_keys_6w_JOqBg = __commonJS({
60210
- "../system/dist/retired-settings-keys-6w_JOqBg.js"(exports) {
60328
+ // ../system/dist/retired-settings-keys-BXaTgLyZ.js
60329
+ var require_retired_settings_keys_BXaTgLyZ = __commonJS({
60330
+ "../system/dist/retired-settings-keys-BXaTgLyZ.js"(exports) {
60211
60331
  "use strict";
60212
- var require_dist10 = require_dist_Dl6MFXPr();
60332
+ var require_dist10 = require_dist_DdEXjTDo();
60213
60333
  function settingsStoreIsAuthoritativeHere(env) {
60214
60334
  const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
60215
60335
  return raw === "" || raw === "hub";
60216
60336
  }
60217
- var RETIRED_SETTINGS_KEYS = [{
60218
- namespace: "detection-pipeline",
60219
- collection: "addon-settings",
60220
- row: "root",
60221
- keys: ["pipelineSteps", "pipelineEngine"],
60222
- perNodeKeys: [
60223
- "engineRuntime",
60224
- "engineBackend",
60225
- "engineDevice",
60226
- "probedBestEngine"
60227
- ],
60228
- reason: "global step/engine seed and the per-node engine cascade \u2014 both removed; the live per-camera dispatch path never read either"
60229
- }];
60337
+ var RETIRED_SETTINGS_KEYS = [
60338
+ {
60339
+ namespace: "detection-pipeline",
60340
+ collection: "addon-settings",
60341
+ row: "root",
60342
+ keys: ["pipelineSteps", "pipelineEngine"],
60343
+ perNodeKeys: [
60344
+ "engineRuntime",
60345
+ "engineBackend",
60346
+ "engineDevice",
60347
+ "probedBestEngine"
60348
+ ],
60349
+ reason: "global step/engine seed and the per-node engine cascade \u2014 both removed; the live per-camera dispatch path never read either"
60350
+ },
60351
+ {
60352
+ namespace: "pipeline-orchestrator",
60353
+ collection: "addon-settings",
60354
+ row: "root",
60355
+ keys: [
60356
+ "enabledNodes",
60357
+ "enabledDecoderNodes",
60358
+ "enabledAudioNodes",
60359
+ "remoteSourcingNodes",
60360
+ "nativeLeaseTtlMs"
60361
+ ],
60362
+ perNodeKeys: ["backend"],
60363
+ reason: 'the pre-singleton "enabled nodes" role model (node capability now lives per node in agent-settings and is derived by NodeTopology.refresh, never read from this row), `nativeLeaseTtlMs` superseded by `nativeLeaseActivityMs`, and the decoder `backend` selector whose resolver returns DEFAULT_DECODER_BACKEND unconditionally (decoder-backend.ts)'
60364
+ },
60365
+ {
60366
+ namespace: "stream-broker",
60367
+ collection: "addon-settings",
60368
+ row: "root",
60369
+ keys: [
60370
+ "maxDecodeFps",
60371
+ "initialReconnectDelayMs",
60372
+ "maxReconnectDelayMs"
60373
+ ],
60374
+ perNodeKeys: [],
60375
+ reason: "three form knobs deleted 2026-08-28 (D272): nothing capped decode fps, and the reconnect ladder has always run on the INITIAL/MAX_RECONNECT_DELAY_MS constants"
60376
+ },
60377
+ {
60378
+ namespace: "embedding-encoder",
60379
+ collection: "addon-settings",
60380
+ row: "root",
60381
+ keys: ["runtime", "backend"],
60382
+ perNodeKeys: [],
60383
+ reason: "two selects deleted 2026-08-28 (D272); their only reference was a withTags log field, and the CUDA/CoreML options named acceleration that has never existed \u2014 embedding inference is always ONNX in the embedded Python"
60384
+ },
60385
+ {
60386
+ namespace: "audio-analyzer",
60387
+ collection: "addon-settings",
60388
+ row: "root",
60389
+ keys: ["selectedAudioModel", "probedBestAudioBackend"],
60390
+ perNodeKeys: [],
60391
+ reason: "`selectedAudioModel` deleted 2026-08-28 (D272) \u2014 createAudioPipeline takes a backend and no model id, so it never reached inference; the BARE `probedBestAudioBackend` is pre-perNode residue that projectStore already drops (no bare fallback), so no node can ever read it"
60392
+ },
60393
+ {
60394
+ namespace: "decoder-nodeav",
60395
+ collection: "addon-settings",
60396
+ row: "root",
60397
+ keys: ["probedBestHwaccel"],
60398
+ perNodeKeys: [],
60399
+ reason: "bare pre-perNode residue \u2014 the live probe result is `probedBestHwaccel@<nodeId>` and `projectStore` deliberately drops the bare key, so nothing can read it"
60400
+ },
60401
+ {
60402
+ namespace: "pipeline-analytics",
60403
+ collection: "addon-settings",
60404
+ row: "root",
60405
+ keys: ["mediaAttachPolicy"],
60406
+ perNodeKeys: [],
60407
+ reason: "deleted 2026-08-28 (D272) \u2014 absent from MediaSettingsSchema, so the value was never even resolved, let alone read"
60408
+ }
60409
+ ];
60230
60410
  var RETIRED_SETTINGS_ROWS = [
60231
60411
  {
60232
60412
  collection: "addon-settings",
@@ -62363,8 +62543,8 @@ var require_device_manager_addon = __commonJS({
62363
62543
  [Symbol.toStringTag]: { value: "Module" }
62364
62544
  });
62365
62545
  require_chunk_Cek0wNdY();
62366
- var require_dist10 = require_dist_Dl6MFXPr();
62367
- var require_retired_settings_keys = require_retired_settings_keys_6w_JOqBg();
62546
+ var require_dist10 = require_dist_DdEXjTDo();
62547
+ var require_retired_settings_keys = require_retired_settings_keys_BXaTgLyZ();
62368
62548
  var node_crypto = __require("crypto");
62369
62549
  var _camstack_types_node = require_node();
62370
62550
  var JOB_HISTORY = 20;
@@ -67113,7 +67293,7 @@ var require_hub_forwarder = __commonJS({
67113
67293
  [Symbol.toStringTag]: { value: "Module" }
67114
67294
  });
67115
67295
  require_chunk_Cek0wNdY();
67116
- var require_dist10 = require_dist_Dl6MFXPr();
67296
+ var require_dist10 = require_dist_DdEXjTDo();
67117
67297
  var require_formatter = require_formatter_DqAKDlvN();
67118
67298
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
67119
67299
  var HubForwarderDestination = class {
@@ -67250,7 +67430,7 @@ var require_liveness_monitor_addon = __commonJS({
67250
67430
  "use strict";
67251
67431
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
67252
67432
  require_chunk_Cek0wNdY();
67253
- var require_dist10 = require_dist_Dl6MFXPr();
67433
+ var require_dist10 = require_dist_DdEXjTDo();
67254
67434
  var NO_DEVICES = "liveness:no-devices";
67255
67435
  var ALL_OFFLINE = "liveness:all-devices-offline";
67256
67436
  var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
@@ -67440,7 +67620,7 @@ var require_local_auth_addon = __commonJS({
67440
67620
  [Symbol.toStringTag]: { value: "Module" }
67441
67621
  });
67442
67622
  var require_chunk = require_chunk_Cek0wNdY();
67443
- var require_dist10 = require_dist_Dl6MFXPr();
67623
+ var require_dist10 = require_dist_DdEXjTDo();
67444
67624
  var node_crypto = __require("crypto");
67445
67625
  node_crypto = require_chunk.__toESM(node_crypto);
67446
67626
  var crypto$1 = __require("crypto");
@@ -71954,6 +72134,99 @@ var require_local_auth_addon = __commonJS({
71954
72134
  };
71955
72135
  }));
71956
72136
  var import_jsonwebtoken = /* @__PURE__ */ require_chunk.__toESM(require_jsonwebtoken());
72137
+ var DURATION_PATTERN = /^(\d+(?:\.\d+)?)\s*(ms|milliseconds?|msecs?|s|secs?|seconds?|m|mins?|minutes?|h|hrs?|hours?|d|days?|w|weeks?|y|yrs?|years?)$/i;
72138
+ var UNIT_MS = {
72139
+ ms: 1,
72140
+ msec: 1,
72141
+ msecs: 1,
72142
+ millisecond: 1,
72143
+ milliseconds: 1,
72144
+ s: 1e3,
72145
+ sec: 1e3,
72146
+ secs: 1e3,
72147
+ second: 1e3,
72148
+ seconds: 1e3,
72149
+ m: 6e4,
72150
+ min: 6e4,
72151
+ mins: 6e4,
72152
+ minute: 6e4,
72153
+ minutes: 6e4,
72154
+ h: 36e5,
72155
+ hr: 36e5,
72156
+ hrs: 36e5,
72157
+ hour: 36e5,
72158
+ hours: 36e5,
72159
+ d: 864e5,
72160
+ day: 864e5,
72161
+ days: 864e5,
72162
+ w: 6048e5,
72163
+ week: 6048e5,
72164
+ weeks: 6048e5,
72165
+ y: 315576e5,
72166
+ yr: 315576e5,
72167
+ yrs: 315576e5,
72168
+ year: 315576e5,
72169
+ years: 315576e5
72170
+ };
72171
+ var MIN_EXPIRY_MS = 6e4;
72172
+ var MAX_EXPIRY_MS = 365 * 864e5;
72173
+ function durationMs(candidate) {
72174
+ const match = DURATION_PATTERN.exec(candidate);
72175
+ if (match === null) return null;
72176
+ const amount = Number(match[1]);
72177
+ const unitMs = UNIT_MS[match[2].toLowerCase()];
72178
+ if (!Number.isFinite(amount) || unitMs === void 0) return null;
72179
+ return amount * unitMs;
72180
+ }
72181
+ var DEFAULT_SECONDS = (() => {
72182
+ const ms = durationMs("30d");
72183
+ if (ms === null) throw new Error(`DEFAULT_TOKEN_EXPIRY is not a duration: 30d`);
72184
+ return ms / 1e3;
72185
+ })();
72186
+ function refuse(reason) {
72187
+ return {
72188
+ ok: false,
72189
+ reason,
72190
+ seconds: DEFAULT_SECONDS,
72191
+ value: "30d"
72192
+ };
72193
+ }
72194
+ function parseTokenExpiry(configured) {
72195
+ if (configured === void 0 || configured === null) return {
72196
+ ok: true,
72197
+ seconds: DEFAULT_SECONDS,
72198
+ value: "30d"
72199
+ };
72200
+ if (typeof configured !== "string") return refuse("not-a-string");
72201
+ const trimmed = configured.trim();
72202
+ if (trimmed === "") return {
72203
+ ok: true,
72204
+ seconds: DEFAULT_SECONDS,
72205
+ value: "30d"
72206
+ };
72207
+ const totalMs = durationMs(trimmed);
72208
+ if (totalMs === null) return refuse("malformed");
72209
+ if (totalMs < MIN_EXPIRY_MS) return refuse("too-short");
72210
+ if (totalMs > MAX_EXPIRY_MS) return refuse("too-long");
72211
+ return {
72212
+ ok: true,
72213
+ seconds: totalMs / 1e3,
72214
+ value: trimmed
72215
+ };
72216
+ }
72217
+ var REJECTION_DETAIL = {
72218
+ "not-a-string": "value is not a string",
72219
+ malformed: "not a duration string (expected e.g. 24h, 7d, 30d \u2014 a bare number is NOT seconds)",
72220
+ "too-short": `shorter than the ${MIN_EXPIRY_MS / 1e3}s minimum`,
72221
+ "too-long": `longer than the ${MAX_EXPIRY_MS / 864e5}d maximum`
72222
+ };
72223
+ function logTokenExpiryRejection(configured, rejection, logger) {
72224
+ logger.warn(`auth.tokenExpiry REJECTED \u2014 ${REJECTION_DETAIL[rejection.reason]}; signing with the default 30d instead`, { meta: {
72225
+ configured,
72226
+ reason: rejection.reason,
72227
+ applied: rejection.value
72228
+ } });
72229
+ }
71957
72230
  var noopLogger = {
71958
72231
  debug() {
71959
72232
  },
@@ -71974,6 +72247,16 @@ var require_local_auth_addon = __commonJS({
71974
72247
  config;
71975
72248
  jwtSecret;
71976
72249
  logger;
72250
+ /**
72251
+ * Offending `auth.tokenExpiry` values already reported by this instance.
72252
+ *
72253
+ * `signToken` re-reads the setting on EVERY mint so an operator's change
72254
+ * takes effect without a restart — which also means a bad value would log
72255
+ * once per login and once per silent refresh from every viewer. The refusal
72256
+ * must be visible, not repeated: the first mint after a bad save logs, the
72257
+ * rest resolve silently to the same default until the value changes.
72258
+ */
72259
+ reportedInvalidExpiries = /* @__PURE__ */ new Set();
71977
72260
  constructor(config, logger = noopLogger) {
71978
72261
  this.config = config;
71979
72262
  this.logger = logger;
@@ -71988,8 +72271,15 @@ var require_local_auth_addon = __commonJS({
71988
72271
  }
71989
72272
  signToken(payload) {
71990
72273
  const configured = this.config.get("auth.tokenExpiry");
71991
- const expiresIn = typeof configured === "string" && configured.trim() !== "" ? configured.trim() : "30d";
71992
- return import_jsonwebtoken.sign({ ...payload }, this.jwtSecret, { expiresIn });
72274
+ const parsed = parseTokenExpiry(configured);
72275
+ if (!parsed.ok) {
72276
+ const seen = typeof configured === "string" ? configured : JSON.stringify(configured);
72277
+ if (!this.reportedInvalidExpiries.has(seen)) {
72278
+ this.reportedInvalidExpiries.add(seen);
72279
+ logTokenExpiryRejection(configured, parsed, this.logger);
72280
+ }
72281
+ }
72282
+ return import_jsonwebtoken.sign({ ...payload }, this.jwtSecret, { expiresIn: parsed.seconds });
71993
72283
  }
71994
72284
  verifyToken(token2) {
71995
72285
  return import_jsonwebtoken.verify(token2, this.jwtSecret);
@@ -74276,6 +74566,30 @@ var require_local_auth_addon = __commonJS({
74276
74566
  return parseRow(results[0].data);
74277
74567
  }
74278
74568
  };
74569
+ function createAuthConfigReader(resolved, writeAuthSection) {
74570
+ return {
74571
+ get(path) {
74572
+ switch (path) {
74573
+ case "auth.jwtSecret":
74574
+ return narrow(resolved.jwtSecret);
74575
+ case "auth.adminUsername":
74576
+ return narrow(resolved.adminUsername);
74577
+ case "auth.adminPassword":
74578
+ return narrow(resolved.adminPassword);
74579
+ case "auth.tokenExpiry":
74580
+ return narrow(resolved.tokenExpiry);
74581
+ default:
74582
+ return;
74583
+ }
74584
+ },
74585
+ update(_section, data) {
74586
+ if (typeof data["jwtSecret"] === "string") writeAuthSection({ jwtSecret: data["jwtSecret"] });
74587
+ }
74588
+ };
74589
+ }
74590
+ function narrow(value) {
74591
+ return value;
74592
+ }
74279
74593
  var USERS_COLLECTION = "users";
74280
74594
  var API_KEYS_COLLECTION = "api_keys";
74281
74595
  var SCOPED_TOKENS_COLLECTION = "scoped_tokens";
@@ -74806,19 +75120,14 @@ var require_local_auth_addon = __commonJS({
74806
75120
  }
74807
75121
  async onInitialize() {
74808
75122
  const authSection = await this.ctx.settings?.getSection("auth") ?? {};
74809
- const resolvedJwtSecret = typeof authSection["jwtSecret"] === "string" ? authSection["jwtSecret"] : this.config.jwtSecret ?? "";
74810
- const resolvedAdminUser = typeof authSection["adminUsername"] === "string" && authSection["adminUsername"] ? authSection["adminUsername"] : this.config.adminUsername ?? "";
74811
- const resolvedAdminPass = typeof authSection["adminPassword"] === "string" && authSection["adminPassword"] ? authSection["adminPassword"] : this.config.adminPassword ?? "";
74812
- const reader = {
74813
- get(path) {
74814
- if (path === "auth.jwtSecret") return resolvedJwtSecret;
74815
- if (path === "auth.adminUsername") return resolvedAdminUser;
74816
- if (path === "auth.adminPassword") return resolvedAdminPass;
74817
- },
74818
- update: (_section, data) => {
74819
- if (typeof data["jwtSecret"] === "string") this.ctx.settings?.setSection("auth", { jwtSecret: data["jwtSecret"] });
74820
- }
74821
- };
75123
+ const reader = createAuthConfigReader({
75124
+ jwtSecret: typeof authSection["jwtSecret"] === "string" ? authSection["jwtSecret"] : this.config.jwtSecret ?? "",
75125
+ adminUsername: typeof authSection["adminUsername"] === "string" && authSection["adminUsername"] ? authSection["adminUsername"] : this.config.adminUsername ?? "",
75126
+ adminPassword: typeof authSection["adminPassword"] === "string" && authSection["adminPassword"] ? authSection["adminPassword"] : this.config.adminPassword ?? "",
75127
+ tokenExpiry: typeof authSection["tokenExpiry"] === "string" && authSection["tokenExpiry"] ? authSection["tokenExpiry"] : void 0
75128
+ }, (patch) => {
75129
+ this.ctx.settings?.setSection("auth", patch);
75130
+ });
74822
75131
  this.authManager = new AuthManager(reader, this.ctx.logger);
74823
75132
  const store = this.ctx.api?.settingsStore;
74824
75133
  if (store) {
@@ -75124,7 +75433,7 @@ var require_loki_logging = __commonJS({
75124
75433
  [Symbol.toStringTag]: { value: "Module" }
75125
75434
  });
75126
75435
  require_chunk_Cek0wNdY();
75127
- var require_dist10 = require_dist_Dl6MFXPr();
75436
+ var require_dist10 = require_dist_DdEXjTDo();
75128
75437
  function sanitizeLabelName(raw) {
75129
75438
  const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
75130
75439
  return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
@@ -75689,7 +75998,7 @@ var require_native_metrics_addon = __commonJS({
75689
75998
  [Symbol.toStringTag]: { value: "Module" }
75690
75999
  });
75691
76000
  var require_chunk = require_chunk_Cek0wNdY();
75692
- var require_dist10 = require_dist_Dl6MFXPr();
76001
+ var require_dist10 = require_dist_DdEXjTDo();
75693
76002
  var node_fs_promises = __require("fs/promises");
75694
76003
  var node_child_process = __require("child_process");
75695
76004
  var node_util = __require("util");
@@ -77646,7 +77955,7 @@ var require_filesystem_storage_addon = __commonJS({
77646
77955
  [Symbol.toStringTag]: { value: "Module" }
77647
77956
  });
77648
77957
  var require_chunk = require_chunk_Cek0wNdY();
77649
- var require_dist10 = require_dist_Dl6MFXPr();
77958
+ var require_dist10 = require_dist_DdEXjTDo();
77650
77959
  var node_crypto = __require("crypto");
77651
77960
  var node_fs_promises = __require("fs/promises");
77652
77961
  var node_path = __require("path");
@@ -78762,8 +79071,8 @@ var require_sqlite_settings_addon = __commonJS({
78762
79071
  [Symbol.toStringTag]: { value: "Module" }
78763
79072
  });
78764
79073
  var require_chunk = require_chunk_Cek0wNdY();
78765
- var require_dist10 = require_dist_Dl6MFXPr();
78766
- var require_retired_settings_keys = require_retired_settings_keys_6w_JOqBg();
79074
+ var require_dist10 = require_dist_DdEXjTDo();
79075
+ var require_retired_settings_keys = require_retired_settings_keys_BXaTgLyZ();
78767
79076
  var node_crypto = __require("crypto");
78768
79077
  var node_fs = __require("fs");
78769
79078
  var node_module = __require("module");
@@ -81042,7 +81351,7 @@ var require_storage_orchestrator_addon = __commonJS({
81042
81351
  [Symbol.toStringTag]: { value: "Module" }
81043
81352
  });
81044
81353
  var require_chunk = require_chunk_Cek0wNdY();
81045
- var require_dist10 = require_dist_Dl6MFXPr();
81354
+ var require_dist10 = require_dist_DdEXjTDo();
81046
81355
  var node_crypto = __require("crypto");
81047
81356
  var node_fs_promises = __require("fs/promises");
81048
81357
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -82923,7 +83232,7 @@ var require_system_config_addon = __commonJS({
82923
83232
  [Symbol.toStringTag]: { value: "Module" }
82924
83233
  });
82925
83234
  require_chunk_Cek0wNdY();
82926
- var require_dist10 = require_dist_Dl6MFXPr();
83235
+ var require_dist10 = require_dist_DdEXjTDo();
82927
83236
  var SECTION_TITLES = {
82928
83237
  server: "Server",
82929
83238
  auth: "Authentication"
@@ -82988,7 +83297,7 @@ var require_system_config_addon = __commonJS({
82988
83297
  type: "text",
82989
83298
  key: "tokenExpiry",
82990
83299
  label: "Token Expiry",
82991
- description: "JWT token lifetime (e.g. 24h, 7d, 30d)",
83300
+ description: "Lifetime of a session token, as a duration string (e.g. 24h, 7d, 30d). A bare number is rejected \u2014 it would be read as milliseconds. Applies to tokens issued from the next login or silent refresh; tokens already handed out keep the lifetime they were signed with.",
82992
83301
  placeholder: "30d",
82993
83302
  default: "30d"
82994
83303
  }]
@@ -100984,7 +101293,7 @@ var require_winston_logging = __commonJS({
100984
101293
  [Symbol.toStringTag]: { value: "Module" }
100985
101294
  });
100986
101295
  var require_chunk = require_chunk_Cek0wNdY();
100987
- var require_dist10 = require_dist_Dl6MFXPr();
101296
+ var require_dist10 = require_dist_DdEXjTDo();
100988
101297
  var require_formatter = require_formatter_DqAKDlvN();
100989
101298
  var node_path = __require("path");
100990
101299
  node_path = require_chunk.__toESM(node_path);
@@ -102927,9 +103236,9 @@ var require_event_category_BaEgqJNv = __commonJS({
102927
103236
  }
102928
103237
  });
102929
103238
 
102930
- // ../types/dist/sleep-9d8tJRbO.js
102931
- var require_sleep_9d8tJRbO = __commonJS({
102932
- "../types/dist/sleep-9d8tJRbO.js"(exports) {
103239
+ // ../types/dist/sleep-DUxF5DdC.js
103240
+ var require_sleep_DUxF5DdC = __commonJS({
103241
+ "../types/dist/sleep-DUxF5DdC.js"(exports) {
102933
103242
  "use strict";
102934
103243
  var require_event_category = require_event_category_BaEgqJNv();
102935
103244
  var zod = require_zod();
@@ -103418,6 +103727,40 @@ var require_sleep_9d8tJRbO = __commonJS({
103418
103727
  deviceSettingsSchema() {
103419
103728
  return null;
103420
103729
  }
103730
+ /**
103731
+ * INTEGRATION-LEVEL SETTINGS — declare which of this addon's global sections
103732
+ * ARE the configuration of its integration.
103733
+ *
103734
+ * Return the `ConfigSection.id`s, from {@link globalSettingsSchema}, that an
103735
+ * operator should find on the addon's integration page (System →
103736
+ * Integrations → <name>) rather than only in the cluster-wide list of every
103737
+ * addon. Empty (the default) means the addon has no integration-level
103738
+ * settings and no such surface is offered — this is opt-in, because whether
103739
+ * an addon's configuration IS its integration's configuration depends on the
103740
+ * nature of the integration.
103741
+ *
103742
+ * WHAT THIS IS NOT. It is not a scope. The selected sections keep living in
103743
+ * the ONE global schema, in the ONE addon store, written by the ONE
103744
+ * `updateGlobalSettings` path. There is deliberately no
103745
+ * `updateIntegrationSettings`: a second write path is how a surface acquires
103746
+ * a second store key, and this repo has shipped that twice (`btmPath@hub`,
103747
+ * D266). Selecting sections cannot introduce a key that selecting cannot.
103748
+ *
103749
+ * WHY IT IS A LIST OF SECTION IDS AND NOT A MARKER ON THE SECTION.
103750
+ * `ConfigFieldBase` used to carry `scope?: 'device' | 'global'` and it was
103751
+ * removed with the reason recorded at
103752
+ * `packages/types/src/interfaces/config-ui.ts:249` — *"a field's scope is
103753
+ * determined by WHICH schema it lives in, not by a field-level marker."* A
103754
+ * marker sprinkled across sections also has to borrow a field that already
103755
+ * means something else; borrowing `section.tab` put the literal word
103756
+ * "integration" into an operator-facing tab bar, because `tab` means "how to
103757
+ * GROUP this visually" and cannot also mean "where this lives" (D269
103758
+ * supersedes D268). One declaration, in one place, next to the schema whose
103759
+ * ids it names.
103760
+ */
103761
+ integrationSettingSections() {
103762
+ return [];
103763
+ }
103421
103764
  async getGlobalSettings(overlay, cap, nodeId) {
103422
103765
  const schema = this.globalSettingsSchema(cap);
103423
103766
  if (!schema) return { sections: [] };
@@ -103428,6 +103771,55 @@ var require_sleep_9d8tJRbO = __commonJS({
103428
103771
  } : projected);
103429
103772
  }
103430
103773
  /**
103774
+ * The integration-level view of this addon's settings: exactly the sections
103775
+ * named by {@link integrationSettingSections}, hydrated from the SAME store
103776
+ * `getGlobalSettings` reads, and narrowed to cluster-scoped fields.
103777
+ *
103778
+ * Returns `null` when the addon declared nothing — an addon that opts out has
103779
+ * no integration settings surface at all, rather than an empty one that reads
103780
+ * as a failed load.
103781
+ *
103782
+ * Three properties hold BY CONSTRUCTION, which is why they are here in core
103783
+ * and not in whichever UI happens to render this:
103784
+ *
103785
+ * 1. **One key.** The payload is a SUBSET of the global schema, so a field
103786
+ * shown here is the same field, with the same bare key, that the addon's
103787
+ * own page shows. There is no integration-specific writer — callers save
103788
+ * through `updateGlobalSettings` — so a second store key is unreachable,
103789
+ * not merely discouraged.
103790
+ * 2. **No node scope.** `perNode: true` fields are DROPPED. Their store key
103791
+ * is `<key>@<nodeId>` and an integration is not a node; whichever node
103792
+ * such a field silently picked would be a wrong answer for the operator
103793
+ * who opened the page (D266).
103794
+ * 3. **No silent typo.** A declared id that names no section throws. The
103795
+ * alternative — skip it — turns a rename into a surface that quietly
103796
+ * empties, which looks exactly like an addon with nothing to configure.
103797
+ */
103798
+ async getIntegrationSettings(nodeId) {
103799
+ const declared = this.integrationSettingSections();
103800
+ if (declared.length === 0) return null;
103801
+ const schema = this.globalSettingsSchema();
103802
+ if (!schema) throw new Error(`${this.constructor.name}: integrationSettingSections() names [${declared.join(", ")}] but globalSettingsSchema() returns null.`);
103803
+ const byId = new Map(schema.sections.map((section) => [section.id, section]));
103804
+ const sections = [];
103805
+ for (const id of declared) {
103806
+ const section = byId.get(id);
103807
+ if (!section) throw new Error(`${this.constructor.name}: integrationSettingSections() names unknown section "${id}". Known sections: [${[...byId.keys()].join(", ")}].`);
103808
+ const fields = dropPerNodeFields(section.fields);
103809
+ if (fields.length === 0) continue;
103810
+ sections.push({
103811
+ ...section,
103812
+ fields
103813
+ });
103814
+ }
103815
+ if (sections.length === 0) return null;
103816
+ const projected = await this.resolveGlobalStore(nodeId);
103817
+ return hydrateSchema({
103818
+ ...schema,
103819
+ sections
103820
+ }, projected);
103821
+ }
103822
+ /**
103431
103823
  * The raw addon store PROJECTED onto the target node's bare per-node keys:
103432
103824
  * every `perNode: true` field carries THAT node's scoped value on its bare
103433
103825
  * key (absent scoped key ⇒ key absent, so the schema `default` wins — no
@@ -103727,6 +104119,33 @@ var require_sleep_9d8tJRbO = __commonJS({
103727
104119
  return {};
103728
104120
  }
103729
104121
  };
104122
+ function dropPerNodeFields(fields) {
104123
+ const kept = [];
104124
+ for (const field of fields) {
104125
+ if (field.type === "group") {
104126
+ const inner = dropPerNodeFields(field.fields);
104127
+ if (inner.length > 0) kept.push({
104128
+ ...field,
104129
+ fields: inner
104130
+ });
104131
+ continue;
104132
+ }
104133
+ if (field.type === "sub-tabs") {
104134
+ const tabs = field.tabs.map((tab) => ({
104135
+ ...tab,
104136
+ fields: dropPerNodeFields(tab.fields)
104137
+ })).filter((tab) => tab.fields.length > 0);
104138
+ if (tabs.length > 0) kept.push({
104139
+ ...field,
104140
+ tabs
104141
+ });
104142
+ continue;
104143
+ }
104144
+ if ("perNode" in field && field.perNode === true) continue;
104145
+ kept.push(field);
104146
+ }
104147
+ return kept;
104148
+ }
103730
104149
  function collectPerNodeFieldKeys(fields) {
103731
104150
  const collected = [];
103732
104151
  for (const field of fields) {
@@ -106483,7 +106902,7 @@ var require_addon = __commonJS({
106483
106902
  "use strict";
106484
106903
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
106485
106904
  var require_event_category = require_event_category_BaEgqJNv();
106486
- var require_sleep = require_sleep_9d8tJRbO();
106905
+ var require_sleep = require_sleep_DUxF5DdC();
106487
106906
  var require_err_msg = require_err_msg_COpsHMw2();
106488
106907
  var CAP_INPUT_DEFAULTS = Object.freeze({
106489
106908
  "addons": { "getLogs": { "limit": 100 } },
@@ -113361,12 +113780,12 @@ var require_dist2 = __commonJS({
113361
113780
  }
113362
113781
  });
113363
113782
 
113364
- // ../system/dist/manifest-python-deps-FYZBHc3v.js
113365
- var require_manifest_python_deps_FYZBHc3v = __commonJS({
113366
- "../system/dist/manifest-python-deps-FYZBHc3v.js"(exports) {
113783
+ // ../system/dist/manifest-python-deps-CivtrAha.js
113784
+ var require_manifest_python_deps_CivtrAha = __commonJS({
113785
+ "../system/dist/manifest-python-deps-CivtrAha.js"(exports) {
113367
113786
  "use strict";
113368
113787
  var require_chunk = require_chunk_Cek0wNdY();
113369
- require_dist_Dl6MFXPr();
113788
+ require_dist_DdEXjTDo();
113370
113789
  var node_crypto = __require("crypto");
113371
113790
  node_crypto = require_chunk.__toESM(node_crypto);
113372
113791
  var _camstack_types_node = require_node();
@@ -124481,7 +124900,7 @@ var require_dist3 = __commonJS({
124481
124900
  "use strict";
124482
124901
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
124483
124902
  var require_chunk = require_chunk_Cek0wNdY();
124484
- var require_dist10 = require_dist_Dl6MFXPr();
124903
+ var require_dist10 = require_dist_DdEXjTDo();
124485
124904
  var require_builtins_alerts_alerts_addon = require_alerts_addon();
124486
124905
  require_alerts();
124487
124906
  var require_formatter = require_formatter_DqAKDlvN();
@@ -124507,7 +124926,7 @@ var require_dist3 = __commonJS({
124507
124926
  var require_builtins_winston_logging_index = require_winston_logging();
124508
124927
  var require_file_data_plane = require_file_data_plane_DO8KbxCe();
124509
124928
  var require_tls$1 = require_tls_u8QCJCFE();
124510
- var require_manifest_python_deps = require_manifest_python_deps_FYZBHc3v();
124929
+ var require_manifest_python_deps = require_manifest_python_deps_CivtrAha();
124511
124930
  var require_resource_monitor = require_resource_monitor_CdnzxBLP();
124512
124931
  var require_custom_action_registry = require_custom_action_registry_jY0NOZK8();
124513
124932
  var zod = require_zod();
@@ -205223,7 +205642,7 @@ var require_dist4 = __commonJS({
205223
205642
  "use strict";
205224
205643
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
205225
205644
  var require_event_category = require_event_category_BaEgqJNv();
205226
- var require_sleep = require_sleep_9d8tJRbO();
205645
+ var require_sleep = require_sleep_DUxF5DdC();
205227
205646
  var require_canonical_hash = require_canonical_hash_DNV8S5ET();
205228
205647
  var require_enums2 = require_enums();
205229
205648
  var require_err_msg = require_err_msg_COpsHMw2();
@@ -208876,6 +209295,10 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
208876
209295
  kind: "mutation",
208877
209296
  auth: "admin"
208878
209297
  }),
209298
+ getIntegrationSettings: require_sleep.method(zod.z.object({
209299
+ addonId: zod.z.string(),
209300
+ nodeId: zod.z.string().optional()
209301
+ }), SettingsSchemaWithValuesSchema.nullable()),
208879
209302
  getDeviceSettings: require_sleep.method(zod.z.object({
208880
209303
  addonId: zod.z.string(),
208881
209304
  deviceId: zod.z.number(),
@@ -209155,8 +209578,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
209155
209578
  ];
209156
209579
  var DEFAULT_AUDIO_ANALYZER_CONFIG = {
209157
209580
  audioBackend: "auto",
209158
- probedBestAudioBackend: "",
209159
- selectedAudioModel: ""
209581
+ probedBestAudioBackend: ""
209160
209582
  };
209161
209583
  var audioAnalyzerCapability = {
209162
209584
  name: "audio-analyzer",
@@ -231423,6 +231845,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
231423
231845
  }
231424
231846
  var HF_REPO = "camstack/camstack-models";
231425
231847
  var HF_BASE_URL = `https://huggingface.co/${HF_REPO}/resolve/main`;
231848
+ var DEFAULT_TOKEN_EXPIRY = "30d";
231426
231849
  var RUNTIME_DEFAULTS = {
231427
231850
  "features.streaming": true,
231428
231851
  "features.notifications": true,
@@ -231451,7 +231874,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
231451
231874
  "ffmpeg.binaryPath": "ffmpeg",
231452
231875
  "ffmpeg.hwAccel": "auto",
231453
231876
  "ffmpeg.threadCount": 0,
231454
- "auth.tokenExpiry": "7d"
231877
+ "auth.tokenExpiry": "30d"
231455
231878
  };
231456
231879
  var AccessoryKind = {
231457
231880
  Siren: require_sleep.DeviceRole.Siren,
@@ -235050,6 +235473,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
235050
235473
  addonId: null,
235051
235474
  access: "view"
235052
235475
  },
235476
+ "addonSettings.getIntegrationSettings": {
235477
+ capName: "addon-settings",
235478
+ capScope: "system",
235479
+ addonId: null,
235480
+ access: "view"
235481
+ },
235053
235482
  "addonSettings.updateDeviceSettings": {
235054
235483
  capName: "addon-settings",
235055
235484
  capScope: "system",
@@ -243252,7 +243681,8 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
243252
243681
  },
243253
243682
  addonSettings: {
243254
243683
  getGlobalSettings: (input) => dispatch("addonSettings", "getGlobalSettings", "query", input),
243255
- updateGlobalSettings: (input) => dispatch("addonSettings", "updateGlobalSettings", "mutation", input)
243684
+ updateGlobalSettings: (input) => dispatch("addonSettings", "updateGlobalSettings", "mutation", input),
243685
+ getIntegrationSettings: (input) => dispatch("addonSettings", "getIntegrationSettings", "query", input)
243256
243686
  },
243257
243687
  addonWidgets: { listWidgets: (input) => dispatch("addonWidgets", "listWidgets", "query", input) },
243258
243688
  alerts: {
@@ -246697,6 +247127,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
246697
247127
  exports.DEFAULT_RETENTION = DEFAULT_RETENTION;
246698
247128
  exports.DEFAULT_RUNTIME_STATE_DURABILITY = require_sleep.DEFAULT_RUNTIME_STATE_DURABILITY;
246699
247129
  exports.DEFAULT_TIMELAPSE_PREVIEW_TEXT = DEFAULT_TIMELAPSE_PREVIEW_TEXT;
247130
+ exports.DEFAULT_TOKEN_EXPIRY = DEFAULT_TOKEN_EXPIRY;
246700
247131
  exports.DETAIL_CROP_PADDING_FIELD = DETAIL_CROP_PADDING_FIELD;
246701
247132
  exports.DETAIL_CROP_PADDING_KEY = DETAIL_CROP_PADDING_KEY;
246702
247133
  exports.DETAIL_CROP_SECTION_ID = DETAIL_CROP_SECTION_ID;
@@ -412320,6 +412751,16 @@ var require_addon_settings_provider = __commonJS({
412320
412751
  }
412321
412752
  return forkedUpdate(input.addonId, "updateGlobalSettings", { patch: input.patch, ...input.nodeId ? { nodeId: input.nodeId } : {} }, input.nodeId);
412322
412753
  },
412754
+ async getIntegrationSettings(input) {
412755
+ if (gateway.isInProcess(input.addonId, input.nodeId)) {
412756
+ const addon = getAddon(input.addonId);
412757
+ if (!addon || typeof addon.getIntegrationSettings !== "function")
412758
+ return null;
412759
+ const result = await addon.getIntegrationSettings(input.nodeId);
412760
+ return result ? reshapeForOutput(result) : null;
412761
+ }
412762
+ return forkedGet(input.addonId, "getIntegrationSettings", { ...input.nodeId ? { nodeId: input.nodeId } : {} }, input.nodeId);
412763
+ },
412323
412764
  async getDeviceSettings(input) {
412324
412765
  if (gateway.isInProcess(input.addonId, input.nodeId)) {
412325
412766
  const addon = getAddon(input.addonId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camstack",
3
- "version": "1.2.51",
3
+ "version": "1.2.53",
4
4
  "description": "CLI tool for managing and running CamStack server",
5
5
  "keywords": [
6
6
  "camstack",