@camstack/addon-remote-storage 1.2.25 → 1.2.26

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.
package/dist/s3.addon.js CHANGED
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_shared = require("./shared-DmwERMr_.js");
5
+ const require_shared = require("./shared-UN8idVfB.js");
6
6
  let node_stream = require("node:stream");
7
7
  let _aws_sdk_client_s3 = require("@aws-sdk/client-s3");
8
8
  let _aws_sdk_lib_storage = require("@aws-sdk/lib-storage");
package/dist/s3.addon.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { c as BaseAddon, i as rearmIdleAbort, n as getOptionalBasePath, o as scheduleIdleAbort, s as storageProviderCapability, t as createSessionId } from "./shared-B9MbTJyC.mjs";
1
+ import { c as BaseAddon, i as rearmIdleAbort, n as getOptionalBasePath, o as scheduleIdleAbort, s as storageProviderCapability, t as createSessionId } from "./shared-BwialOVX.mjs";
2
2
  import { PassThrough } from "node:stream";
3
3
  import { DeleteObjectCommand, GetObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectsV2Command, PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
4
4
  import { Upload } from "@aws-sdk/lib-storage";
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_shared = require("./shared-DmwERMr_.js");
5
+ const require_shared = require("./shared-UN8idVfB.js");
6
6
  let ssh2 = require("ssh2");
7
7
  let node_path = require("node:path");
8
8
  node_path = require_shared.__toESM(node_path);
@@ -1,4 +1,4 @@
1
- import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-B9MbTJyC.mjs";
1
+ import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-BwialOVX.mjs";
2
2
  import { Client } from "ssh2";
3
3
  import * as path from "node:path";
4
4
  //#region src/providers/sftp/sftp-config-schema.ts
@@ -8005,6 +8005,15 @@ var LabelDefinitionSchema = object({
8005
8005
  description: string().optional(),
8006
8006
  icon: string().optional()
8007
8007
  });
8008
+ var ClassMapDefinitionSchema = object({
8009
+ mapping: record(string(), _enum([
8010
+ "person",
8011
+ "vehicle",
8012
+ "animal",
8013
+ "package"
8014
+ ])),
8015
+ preserveOriginal: boolean()
8016
+ });
8008
8017
  var MODEL_FORMATS = [
8009
8018
  "onnx",
8010
8019
  "coreml",
@@ -8183,7 +8192,13 @@ var ModelCatalogEntrySchema = object({
8183
8192
  * `id` stays the source of truth for resolution/download/persistence; grouping
8184
8193
  * is a presentation overlay resolved back to an `id`.
8185
8194
  */
8186
- group: ModelVariantGroupSchema.optional()
8195
+ group: ModelVariantGroupSchema.optional(),
8196
+ /**
8197
+ * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
8198
+ * applies (Frigate / COCO public catalog). Set on a custom model whose raw
8199
+ * labels already ARE the CamStack macros (Scrypted identity map).
8200
+ */
8201
+ classMap: ClassMapDefinitionSchema.optional()
8187
8202
  });
8188
8203
  var ConvertTargetSchema = discriminatedUnion("format", [object({
8189
8204
  format: literal("openvino"),
@@ -8212,7 +8227,8 @@ var ModelConvertMetadataSchema = object({
8212
8227
  "ocr",
8213
8228
  "segmentation"
8214
8229
  ]),
8215
- faceAlignment: boolean().optional()
8230
+ faceAlignment: boolean().optional(),
8231
+ classMap: ClassMapDefinitionSchema.optional()
8216
8232
  });
8217
8233
  var ConvertResultSchema = object({
8218
8234
  entry: ModelCatalogEntrySchema,
@@ -17203,6 +17219,33 @@ var NativeCropRefSchema = object({
17203
17219
  h: number()
17204
17220
  })
17205
17221
  });
17222
+ object({
17223
+ crop: object({
17224
+ left: number(),
17225
+ top: number(),
17226
+ width: number().positive(),
17227
+ height: number().positive()
17228
+ }).optional(),
17229
+ content: object({
17230
+ width: number().int().positive(),
17231
+ height: number().int().positive()
17232
+ }),
17233
+ fit: _enum(["stretch", "contain"]),
17234
+ format: _enum([
17235
+ "rgb",
17236
+ "gray",
17237
+ "jpeg"
17238
+ ])
17239
+ });
17240
+ var FrameRefSchema = object({
17241
+ registryId: string().min(1),
17242
+ id: string().min(1),
17243
+ width: number().int().positive(),
17244
+ height: number().int().positive(),
17245
+ format: _enum(["rgb", "gray"]),
17246
+ timestamp: number(),
17247
+ capturedAt: number().optional()
17248
+ });
17206
17249
  var ModelFormatSchema$1 = _enum([
17207
17250
  "onnx",
17208
17251
  "coreml",
@@ -17447,6 +17490,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
17447
17490
  steps: array(PipelineStepInputSchema).min(1),
17448
17491
  frame: FrameInputSchema.optional(),
17449
17492
  /**
17493
+ * Process-local lazy frame. Valid only when caller and provider resolve
17494
+ * in the same execution-group process; split/cross-node callers use
17495
+ * `frame`/`image` inline compatibility instead.
17496
+ */
17497
+ frameRef: FrameRefSchema.optional(),
17498
+ /**
17450
17499
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
17451
17500
  * the decoded pixels live in. One more member of the one-of
17452
17501
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -17702,7 +17751,10 @@ var NativeCropResultSchema = object({
17702
17751
  * Which source served this crop, so a quality-sensitive consumer (the native
17703
17752
  * `keyFrame`) can reject a degraded fallback:
17704
17753
  * - `native` — cut from the decode worker's retained NATIVE surface (the
17705
- * quality path).
17754
+ * quality path). A subject-tile serve is also native-resolution and stays
17755
+ * `native` here: the public enum cannot name `tile` without a breaking cap
17756
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
17757
+ * internal crop result (`nativeHits` vs `tileHits`).
17706
17758
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
17707
17759
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
17708
17760
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -18193,12 +18245,41 @@ var RunnerLocalLoadSchema = object({
18193
18245
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
18194
18246
  * working unchanged when they switch to reading from the runner cap.
18195
18247
  */
18248
+ var FrameLazyCountersSchema = object({
18249
+ framesDecoded: number(),
18250
+ framesAdmitted: number(),
18251
+ framesDroppedPixelFree: number(),
18252
+ viewsMaterialized: number(),
18253
+ viewsSkipped: number(),
18254
+ workerToRunnerBytes: number(),
18255
+ runnerToPoolRawBytes: number(),
18256
+ runnerToPoolJpegBytes: number(),
18257
+ onDemandFullFrameRequests: number(),
18258
+ onDemandCropRequests: number(),
18259
+ nativeHits: number(),
18260
+ nativeMisses: number(),
18261
+ tileHits: number(),
18262
+ tileMisses: number(),
18263
+ fallbackHits: number(),
18264
+ fallbackMisses: number(),
18265
+ retainedWritesAvoided: number(),
18266
+ residentRefs: number(),
18267
+ residentBytes: number(),
18268
+ releases: number(),
18269
+ evictions: number(),
18270
+ staleMisses: number()
18271
+ });
18272
+ var FrameLazyMetricsSchema = object({
18273
+ node: FrameLazyCountersSchema,
18274
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
18275
+ });
18196
18276
  var RunnerLocalMetricsSchema = object({
18197
18277
  nodeId: string(),
18198
18278
  activeCameras: number(),
18199
18279
  throttledCameras: number(),
18200
18280
  avgInferenceTimeMs: number(),
18201
- queueDepth: number()
18281
+ queueDepth: number(),
18282
+ frameLazy: FrameLazyMetricsSchema.optional()
18202
18283
  });
18203
18284
  method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mutation" }), method(object({ deviceId: number() }), object({ success: literal(true) }), { kind: "mutation" }), method(ReportMotionInputSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), RunnerLocalLoadSchema), method(_void(), RunnerLocalMetricsSchema), method(object({ deviceId: number() }), CameraMetricsSchema.nullable()), method(_void(), array(CameraMetricsWithDeviceIdSchema).readonly()), method(_void(), array(number()).readonly()), method(object({
18204
18285
  handle: FrameHandleSchema,
@@ -19543,6 +19624,9 @@ var storageProviderCapability = {
19543
19624
  endDownload: method(EndDownloadInputSchema, _void(), { kind: "mutation" })
19544
19625
  }
19545
19626
  };
19627
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
19628
+ var ProfileSettingsSchemaBridge = unknown().nullable();
19629
+ var ProfileSettingsBagSchema = record(string(), unknown());
19546
19630
  /**
19547
19631
  * A live terminal session hosted by the provider addon. Output and input do
19548
19632
  * NOT flow through the capability — they use the addon data plane
@@ -19572,7 +19656,14 @@ var TerminalSessionInfoSchema = object({
19572
19656
  var TerminalProfileInfoSchema = object({
19573
19657
  profileId: string(),
19574
19658
  label: string(),
19575
- description: string().optional()
19659
+ description: string().optional(),
19660
+ /** Spawn defaults the instance form copies on create. */
19661
+ executable: string().optional(),
19662
+ args: array(string()).readonly().optional(),
19663
+ cwd: string().optional(),
19664
+ environment: array(string()).readonly().optional(),
19665
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
19666
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
19576
19667
  });
19577
19668
  /**
19578
19669
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -19585,7 +19676,12 @@ var TerminalInstanceInfoSchema = object({
19585
19676
  profileId: string(),
19586
19677
  profileLabel: string(),
19587
19678
  name: string(),
19588
- enabled: boolean()
19679
+ enabled: boolean(),
19680
+ executable: string(),
19681
+ args: array(string()).readonly(),
19682
+ cwd: string(),
19683
+ environment: array(string()).readonly(),
19684
+ profileSettings: ProfileSettingsBagSchema
19589
19685
  });
19590
19686
  var TerminalLegacyCameraSchema = object({
19591
19687
  stableId: string(),
@@ -19615,7 +19711,23 @@ var TerminalOutputBatchSchema = object({
19615
19711
  method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }), method(object({
19616
19712
  targetNodeId: string().min(1),
19617
19713
  profileId: string().min(1),
19618
- name: string().trim().min(1).max(160).optional()
19714
+ name: string().trim().min(1).max(160).optional(),
19715
+ executable: string().max(1024).optional(),
19716
+ args: array(string().max(2048)).max(64).optional(),
19717
+ cwd: string().max(1024).optional(),
19718
+ environment: array(string().max(4096)).max(64).optional(),
19719
+ profileSettings: ProfileSettingsBagSchema.optional()
19720
+ }), TerminalInstanceInfoSchema, {
19721
+ kind: "mutation",
19722
+ auth: "admin"
19723
+ }), method(object({
19724
+ instanceId: string().min(1),
19725
+ name: string().trim().min(1).max(160).optional(),
19726
+ executable: string().max(1024).optional(),
19727
+ args: array(string().max(2048)).max(64).optional(),
19728
+ cwd: string().max(1024).optional(),
19729
+ environment: array(string().max(4096)).max(64).optional(),
19730
+ profileSettings: ProfileSettingsBagSchema.optional()
19619
19731
  }), TerminalInstanceInfoSchema, {
19620
19732
  kind: "mutation",
19621
19733
  auth: "admin"
@@ -19637,7 +19749,11 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
19637
19749
  }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
19638
19750
  profileId: string(),
19639
19751
  cols: number().int().positive(),
19640
- rows: number().int().positive()
19752
+ rows: number().int().positive(),
19753
+ executable: string().max(1024).optional(),
19754
+ args: array(string().max(2048)).max(64).optional(),
19755
+ cwd: string().max(1024).optional(),
19756
+ environment: array(string().max(4096)).max(64).optional()
19641
19757
  }), TerminalSessionInfoSchema, {
19642
19758
  kind: "mutation",
19643
19759
  auth: "admin"
@@ -22419,10 +22535,10 @@ DeviceType.LawnMower, method(object({ deviceId: number().int().nonnegative() }),
22419
22535
  *
22420
22536
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
22421
22537
  * to receive an ordered list of candidate base URLs it should race
22422
- * on connect — LAN IPv4 first (lowest latency when on same network),
22423
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
22424
- * race them with short timeouts and stick with the winner for the
22425
- * session.
22538
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
22539
+ * when on the same network), then public hostname (if a tunnel is
22540
+ * up). The SDK can race them with short timeouts and stick with the
22541
+ * winner for the session.
22426
22542
  *
22427
22543
  * Why hub-only: agents are not directly addressable by the operator's
22428
22544
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -22577,6 +22693,17 @@ var NotificationEndpointSchema = object({
22577
22693
  /** What the ranking currently resolves to (null when nothing is reachable). */
22578
22694
  resolved: string().nullable()
22579
22695
  });
22696
+ /**
22697
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
22698
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
22699
+ * currently expands to, so the UI can show the effective set either way.
22700
+ */
22701
+ var ViewerEndpointsSchema = object({
22702
+ /** The operator's explicit race set, or empty for AUTO. */
22703
+ baseUrls: array(string()).readonly(),
22704
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
22705
+ resolved: array(string()).readonly()
22706
+ });
22580
22707
  var AllowedAddressesSchema = object({
22581
22708
  /**
22582
22709
  * Allowlist of interface addresses operators have explicitly opted
@@ -22585,6 +22712,20 @@ var AllowedAddressesSchema = object({
22585
22712
  * Network Addresses admin page and persisted by the addon.
22586
22713
  */
22587
22714
  addresses: array(string()).readonly() });
22715
+ var TlsStatusSchema = object({
22716
+ mode: _enum([
22717
+ "generated",
22718
+ "uploaded",
22719
+ "disabled"
22720
+ ]),
22721
+ leafFingerprintSha256: string().nullable(),
22722
+ caFingerprintSha256: string().nullable(),
22723
+ validTo: string().nullable(),
22724
+ sans: array(string()),
22725
+ caCertPem: string().nullable(),
22726
+ reissueError: string().nullable(),
22727
+ restartRequired: boolean()
22728
+ });
22588
22729
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
22589
22730
  /**
22590
22731
  * LEGACY HINT — do not send from new code. Kept optional so clients
@@ -22594,17 +22735,31 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
22594
22735
  */
22595
22736
  port: number().int().min(1).max(65535).optional(),
22596
22737
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
22597
- * candidate. Default `true`. */
22738
+ * candidate. Default `false` — loopback is not a client route. */
22598
22739
  includeLoopback: boolean().optional(),
22599
- /** Skip IPv6 entries. Some legacy clients can't parse them.
22600
- * Default `false`. */
22740
+ /** Skip IPv6 entries. Default `false` the palette includes stable
22741
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
22742
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
22601
22743
  ipv4Only: boolean().optional(),
22602
22744
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
22603
22745
  * Pass `'https'` when the caller is itself loaded over HTTPS
22604
22746
  * to avoid mixed-content blocks in the browser. The public
22605
22747
  * tunnel always emits `https://` regardless. */
22606
22748
  scheme: _enum(["http", "https"]).optional()
22607
- }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" });
22749
+ }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
22750
+ kind: "mutation",
22751
+ auth: "admin"
22752
+ }), method(object({
22753
+ certPem: string().min(1),
22754
+ keyPem: string().min(1),
22755
+ caPem: string().optional()
22756
+ }), TlsStatusSchema, {
22757
+ kind: "mutation",
22758
+ auth: "admin"
22759
+ }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
22760
+ kind: "mutation",
22761
+ auth: "admin"
22762
+ });
22608
22763
  object({
22609
22764
  /** Lifecycle state of the lock. `jammed` means the motor reported
22610
22765
  * failure to reach the target — operator intervention required. */
@@ -28367,6 +28522,12 @@ Object.freeze({
28367
28522
  addonId: null,
28368
28523
  access: "create"
28369
28524
  },
28525
+ "localNetwork.downloadCa": {
28526
+ capName: "local-network",
28527
+ capScope: "system",
28528
+ addonId: null,
28529
+ access: "view"
28530
+ },
28370
28531
  "localNetwork.getAllowedAddresses": {
28371
28532
  capName: "local-network",
28372
28533
  capScope: "system",
@@ -28391,18 +28552,42 @@ Object.freeze({
28391
28552
  addonId: null,
28392
28553
  access: "view"
28393
28554
  },
28555
+ "localNetwork.getTlsStatus": {
28556
+ capName: "local-network",
28557
+ capScope: "system",
28558
+ addonId: null,
28559
+ access: "view"
28560
+ },
28561
+ "localNetwork.getViewerEndpoints": {
28562
+ capName: "local-network",
28563
+ capScope: "system",
28564
+ addonId: null,
28565
+ access: "view"
28566
+ },
28394
28567
  "localNetwork.list": {
28395
28568
  capName: "local-network",
28396
28569
  capScope: "system",
28397
28570
  addonId: null,
28398
28571
  access: "view"
28399
28572
  },
28573
+ "localNetwork.regenerateCertificate": {
28574
+ capName: "local-network",
28575
+ capScope: "system",
28576
+ addonId: null,
28577
+ access: "create"
28578
+ },
28400
28579
  "localNetwork.resetAllowlistToBestMatch": {
28401
28580
  capName: "local-network",
28402
28581
  capScope: "system",
28403
28582
  addonId: null,
28404
28583
  access: "delete"
28405
28584
  },
28585
+ "localNetwork.revertToGeneratedCertificate": {
28586
+ capName: "local-network",
28587
+ capScope: "system",
28588
+ addonId: null,
28589
+ access: "create"
28590
+ },
28406
28591
  "localNetwork.setAllowedAddresses": {
28407
28592
  capName: "local-network",
28408
28593
  capScope: "system",
@@ -28415,6 +28600,18 @@ Object.freeze({
28415
28600
  addonId: null,
28416
28601
  access: "create"
28417
28602
  },
28603
+ "localNetwork.setViewerEndpoints": {
28604
+ capName: "local-network",
28605
+ capScope: "system",
28606
+ addonId: null,
28607
+ access: "create"
28608
+ },
28609
+ "localNetwork.uploadCertificate": {
28610
+ capName: "local-network",
28611
+ capScope: "system",
28612
+ addonId: null,
28613
+ access: "create"
28614
+ },
28418
28615
  "lockControl.lock": {
28419
28616
  capName: "lock-control",
28420
28617
  capScope: "device",
@@ -31295,6 +31492,12 @@ Object.freeze({
31295
31492
  addonId: null,
31296
31493
  access: "create"
31297
31494
  },
31495
+ "terminalSession.updateInstance": {
31496
+ capName: "terminal-session",
31497
+ capScope: "system",
31498
+ addonId: null,
31499
+ access: "create"
31500
+ },
31298
31501
  "terminalSession.writeInput": {
31299
31502
  capName: "terminal-session",
31300
31503
  capScope: "system",
@@ -33782,6 +33985,35 @@ Object.freeze(Object.fromEntries([{
33782
33985
  }]
33783
33986
  }].map((s) => [s.stepId, s.defaultModelId])));
33784
33987
  string().min(1);
33988
+ var CLUSTER_STEP_SETTING_FIELDS = [{
33989
+ stepId: "face-embedding",
33990
+ key: "minLandmarkFaceSize",
33991
+ label: "Min face size for recognition (detection px)",
33992
+ description: "Refuse to embed a face smaller than this IN THE DETECTION FRAME. Applies to every node — the enrolled gallery is one index, and two admission floors would fill it from two policies. 0 disables the gate.",
33993
+ type: "slider",
33994
+ min: 0,
33995
+ max: 64,
33996
+ step: 2,
33997
+ default: 24
33998
+ }];
33999
+ function clusterStepSettingKey(stepId, fieldKey) {
34000
+ return `clusterStepSetting:${stepId}:${fieldKey}`;
34001
+ }
34002
+ var ClusterSettingNumberSchema = number().finite();
34003
+ function readClusterStepSettings(config) {
34004
+ const out = {};
34005
+ for (const field of CLUSTER_STEP_SETTING_FIELDS) {
34006
+ const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
34007
+ const value = parsed.success ? parsed.data : field.default;
34008
+ const existing = out[field.stepId] ?? {};
34009
+ out[field.stepId] = {
34010
+ ...existing,
34011
+ [field.key]: value
34012
+ };
34013
+ }
34014
+ return out;
34015
+ }
34016
+ readClusterStepSettings({});
33785
34017
  object({
33786
34018
  /**
33787
34019
  * Fraction of the box's own size added on EACH side before cutting.
@@ -8028,6 +8028,15 @@ var LabelDefinitionSchema = object({
8028
8028
  description: string().optional(),
8029
8029
  icon: string().optional()
8030
8030
  });
8031
+ var ClassMapDefinitionSchema = object({
8032
+ mapping: record(string(), _enum([
8033
+ "person",
8034
+ "vehicle",
8035
+ "animal",
8036
+ "package"
8037
+ ])),
8038
+ preserveOriginal: boolean()
8039
+ });
8031
8040
  var MODEL_FORMATS = [
8032
8041
  "onnx",
8033
8042
  "coreml",
@@ -8206,7 +8215,13 @@ var ModelCatalogEntrySchema = object({
8206
8215
  * `id` stays the source of truth for resolution/download/persistence; grouping
8207
8216
  * is a presentation overlay resolved back to an `id`.
8208
8217
  */
8209
- group: ModelVariantGroupSchema.optional()
8218
+ group: ModelVariantGroupSchema.optional(),
8219
+ /**
8220
+ * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
8221
+ * applies (Frigate / COCO public catalog). Set on a custom model whose raw
8222
+ * labels already ARE the CamStack macros (Scrypted identity map).
8223
+ */
8224
+ classMap: ClassMapDefinitionSchema.optional()
8210
8225
  });
8211
8226
  var ConvertTargetSchema = discriminatedUnion("format", [object({
8212
8227
  format: literal("openvino"),
@@ -8235,7 +8250,8 @@ var ModelConvertMetadataSchema = object({
8235
8250
  "ocr",
8236
8251
  "segmentation"
8237
8252
  ]),
8238
- faceAlignment: boolean().optional()
8253
+ faceAlignment: boolean().optional(),
8254
+ classMap: ClassMapDefinitionSchema.optional()
8239
8255
  });
8240
8256
  var ConvertResultSchema = object({
8241
8257
  entry: ModelCatalogEntrySchema,
@@ -17226,6 +17242,33 @@ var NativeCropRefSchema = object({
17226
17242
  h: number()
17227
17243
  })
17228
17244
  });
17245
+ object({
17246
+ crop: object({
17247
+ left: number(),
17248
+ top: number(),
17249
+ width: number().positive(),
17250
+ height: number().positive()
17251
+ }).optional(),
17252
+ content: object({
17253
+ width: number().int().positive(),
17254
+ height: number().int().positive()
17255
+ }),
17256
+ fit: _enum(["stretch", "contain"]),
17257
+ format: _enum([
17258
+ "rgb",
17259
+ "gray",
17260
+ "jpeg"
17261
+ ])
17262
+ });
17263
+ var FrameRefSchema = object({
17264
+ registryId: string().min(1),
17265
+ id: string().min(1),
17266
+ width: number().int().positive(),
17267
+ height: number().int().positive(),
17268
+ format: _enum(["rgb", "gray"]),
17269
+ timestamp: number(),
17270
+ capturedAt: number().optional()
17271
+ });
17229
17272
  var ModelFormatSchema$1 = _enum([
17230
17273
  "onnx",
17231
17274
  "coreml",
@@ -17470,6 +17513,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
17470
17513
  steps: array(PipelineStepInputSchema).min(1),
17471
17514
  frame: FrameInputSchema.optional(),
17472
17515
  /**
17516
+ * Process-local lazy frame. Valid only when caller and provider resolve
17517
+ * in the same execution-group process; split/cross-node callers use
17518
+ * `frame`/`image` inline compatibility instead.
17519
+ */
17520
+ frameRef: FrameRefSchema.optional(),
17521
+ /**
17473
17522
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
17474
17523
  * the decoded pixels live in. One more member of the one-of
17475
17524
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -17725,7 +17774,10 @@ var NativeCropResultSchema = object({
17725
17774
  * Which source served this crop, so a quality-sensitive consumer (the native
17726
17775
  * `keyFrame`) can reject a degraded fallback:
17727
17776
  * - `native` — cut from the decode worker's retained NATIVE surface (the
17728
- * quality path).
17777
+ * quality path). A subject-tile serve is also native-resolution and stays
17778
+ * `native` here: the public enum cannot name `tile` without a breaking cap
17779
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
17780
+ * internal crop result (`nativeHits` vs `tileHits`).
17729
17781
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
17730
17782
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
17731
17783
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -18216,12 +18268,41 @@ var RunnerLocalLoadSchema = object({
18216
18268
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
18217
18269
  * working unchanged when they switch to reading from the runner cap.
18218
18270
  */
18271
+ var FrameLazyCountersSchema = object({
18272
+ framesDecoded: number(),
18273
+ framesAdmitted: number(),
18274
+ framesDroppedPixelFree: number(),
18275
+ viewsMaterialized: number(),
18276
+ viewsSkipped: number(),
18277
+ workerToRunnerBytes: number(),
18278
+ runnerToPoolRawBytes: number(),
18279
+ runnerToPoolJpegBytes: number(),
18280
+ onDemandFullFrameRequests: number(),
18281
+ onDemandCropRequests: number(),
18282
+ nativeHits: number(),
18283
+ nativeMisses: number(),
18284
+ tileHits: number(),
18285
+ tileMisses: number(),
18286
+ fallbackHits: number(),
18287
+ fallbackMisses: number(),
18288
+ retainedWritesAvoided: number(),
18289
+ residentRefs: number(),
18290
+ residentBytes: number(),
18291
+ releases: number(),
18292
+ evictions: number(),
18293
+ staleMisses: number()
18294
+ });
18295
+ var FrameLazyMetricsSchema = object({
18296
+ node: FrameLazyCountersSchema,
18297
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
18298
+ });
18219
18299
  var RunnerLocalMetricsSchema = object({
18220
18300
  nodeId: string(),
18221
18301
  activeCameras: number(),
18222
18302
  throttledCameras: number(),
18223
18303
  avgInferenceTimeMs: number(),
18224
- queueDepth: number()
18304
+ queueDepth: number(),
18305
+ frameLazy: FrameLazyMetricsSchema.optional()
18225
18306
  });
18226
18307
  method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mutation" }), method(object({ deviceId: number() }), object({ success: literal(true) }), { kind: "mutation" }), method(ReportMotionInputSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), RunnerLocalLoadSchema), method(_void(), RunnerLocalMetricsSchema), method(object({ deviceId: number() }), CameraMetricsSchema.nullable()), method(_void(), array(CameraMetricsWithDeviceIdSchema).readonly()), method(_void(), array(number()).readonly()), method(object({
18227
18308
  handle: FrameHandleSchema,
@@ -19566,6 +19647,9 @@ var storageProviderCapability = {
19566
19647
  endDownload: method(EndDownloadInputSchema, _void(), { kind: "mutation" })
19567
19648
  }
19568
19649
  };
19650
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
19651
+ var ProfileSettingsSchemaBridge = unknown().nullable();
19652
+ var ProfileSettingsBagSchema = record(string(), unknown());
19569
19653
  /**
19570
19654
  * A live terminal session hosted by the provider addon. Output and input do
19571
19655
  * NOT flow through the capability — they use the addon data plane
@@ -19595,7 +19679,14 @@ var TerminalSessionInfoSchema = object({
19595
19679
  var TerminalProfileInfoSchema = object({
19596
19680
  profileId: string(),
19597
19681
  label: string(),
19598
- description: string().optional()
19682
+ description: string().optional(),
19683
+ /** Spawn defaults the instance form copies on create. */
19684
+ executable: string().optional(),
19685
+ args: array(string()).readonly().optional(),
19686
+ cwd: string().optional(),
19687
+ environment: array(string()).readonly().optional(),
19688
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
19689
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
19599
19690
  });
19600
19691
  /**
19601
19692
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -19608,7 +19699,12 @@ var TerminalInstanceInfoSchema = object({
19608
19699
  profileId: string(),
19609
19700
  profileLabel: string(),
19610
19701
  name: string(),
19611
- enabled: boolean()
19702
+ enabled: boolean(),
19703
+ executable: string(),
19704
+ args: array(string()).readonly(),
19705
+ cwd: string(),
19706
+ environment: array(string()).readonly(),
19707
+ profileSettings: ProfileSettingsBagSchema
19612
19708
  });
19613
19709
  var TerminalLegacyCameraSchema = object({
19614
19710
  stableId: string(),
@@ -19638,7 +19734,23 @@ var TerminalOutputBatchSchema = object({
19638
19734
  method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }), method(object({
19639
19735
  targetNodeId: string().min(1),
19640
19736
  profileId: string().min(1),
19641
- name: string().trim().min(1).max(160).optional()
19737
+ name: string().trim().min(1).max(160).optional(),
19738
+ executable: string().max(1024).optional(),
19739
+ args: array(string().max(2048)).max(64).optional(),
19740
+ cwd: string().max(1024).optional(),
19741
+ environment: array(string().max(4096)).max(64).optional(),
19742
+ profileSettings: ProfileSettingsBagSchema.optional()
19743
+ }), TerminalInstanceInfoSchema, {
19744
+ kind: "mutation",
19745
+ auth: "admin"
19746
+ }), method(object({
19747
+ instanceId: string().min(1),
19748
+ name: string().trim().min(1).max(160).optional(),
19749
+ executable: string().max(1024).optional(),
19750
+ args: array(string().max(2048)).max(64).optional(),
19751
+ cwd: string().max(1024).optional(),
19752
+ environment: array(string().max(4096)).max(64).optional(),
19753
+ profileSettings: ProfileSettingsBagSchema.optional()
19642
19754
  }), TerminalInstanceInfoSchema, {
19643
19755
  kind: "mutation",
19644
19756
  auth: "admin"
@@ -19660,7 +19772,11 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
19660
19772
  }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
19661
19773
  profileId: string(),
19662
19774
  cols: number().int().positive(),
19663
- rows: number().int().positive()
19775
+ rows: number().int().positive(),
19776
+ executable: string().max(1024).optional(),
19777
+ args: array(string().max(2048)).max(64).optional(),
19778
+ cwd: string().max(1024).optional(),
19779
+ environment: array(string().max(4096)).max(64).optional()
19664
19780
  }), TerminalSessionInfoSchema, {
19665
19781
  kind: "mutation",
19666
19782
  auth: "admin"
@@ -22442,10 +22558,10 @@ DeviceType.LawnMower, method(object({ deviceId: number().int().nonnegative() }),
22442
22558
  *
22443
22559
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
22444
22560
  * to receive an ordered list of candidate base URLs it should race
22445
- * on connect — LAN IPv4 first (lowest latency when on same network),
22446
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
22447
- * race them with short timeouts and stick with the winner for the
22448
- * session.
22561
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
22562
+ * when on the same network), then public hostname (if a tunnel is
22563
+ * up). The SDK can race them with short timeouts and stick with the
22564
+ * winner for the session.
22449
22565
  *
22450
22566
  * Why hub-only: agents are not directly addressable by the operator's
22451
22567
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -22600,6 +22716,17 @@ var NotificationEndpointSchema = object({
22600
22716
  /** What the ranking currently resolves to (null when nothing is reachable). */
22601
22717
  resolved: string().nullable()
22602
22718
  });
22719
+ /**
22720
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
22721
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
22722
+ * currently expands to, so the UI can show the effective set either way.
22723
+ */
22724
+ var ViewerEndpointsSchema = object({
22725
+ /** The operator's explicit race set, or empty for AUTO. */
22726
+ baseUrls: array(string()).readonly(),
22727
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
22728
+ resolved: array(string()).readonly()
22729
+ });
22603
22730
  var AllowedAddressesSchema = object({
22604
22731
  /**
22605
22732
  * Allowlist of interface addresses operators have explicitly opted
@@ -22608,6 +22735,20 @@ var AllowedAddressesSchema = object({
22608
22735
  * Network Addresses admin page and persisted by the addon.
22609
22736
  */
22610
22737
  addresses: array(string()).readonly() });
22738
+ var TlsStatusSchema = object({
22739
+ mode: _enum([
22740
+ "generated",
22741
+ "uploaded",
22742
+ "disabled"
22743
+ ]),
22744
+ leafFingerprintSha256: string().nullable(),
22745
+ caFingerprintSha256: string().nullable(),
22746
+ validTo: string().nullable(),
22747
+ sans: array(string()),
22748
+ caCertPem: string().nullable(),
22749
+ reissueError: string().nullable(),
22750
+ restartRequired: boolean()
22751
+ });
22611
22752
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
22612
22753
  /**
22613
22754
  * LEGACY HINT — do not send from new code. Kept optional so clients
@@ -22617,17 +22758,31 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
22617
22758
  */
22618
22759
  port: number().int().min(1).max(65535).optional(),
22619
22760
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
22620
- * candidate. Default `true`. */
22761
+ * candidate. Default `false` — loopback is not a client route. */
22621
22762
  includeLoopback: boolean().optional(),
22622
- /** Skip IPv6 entries. Some legacy clients can't parse them.
22623
- * Default `false`. */
22763
+ /** Skip IPv6 entries. Default `false` the palette includes stable
22764
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
22765
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
22624
22766
  ipv4Only: boolean().optional(),
22625
22767
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
22626
22768
  * Pass `'https'` when the caller is itself loaded over HTTPS
22627
22769
  * to avoid mixed-content blocks in the browser. The public
22628
22770
  * tunnel always emits `https://` regardless. */
22629
22771
  scheme: _enum(["http", "https"]).optional()
22630
- }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" });
22772
+ }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
22773
+ kind: "mutation",
22774
+ auth: "admin"
22775
+ }), method(object({
22776
+ certPem: string().min(1),
22777
+ keyPem: string().min(1),
22778
+ caPem: string().optional()
22779
+ }), TlsStatusSchema, {
22780
+ kind: "mutation",
22781
+ auth: "admin"
22782
+ }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
22783
+ kind: "mutation",
22784
+ auth: "admin"
22785
+ });
22631
22786
  object({
22632
22787
  /** Lifecycle state of the lock. `jammed` means the motor reported
22633
22788
  * failure to reach the target — operator intervention required. */
@@ -28390,6 +28545,12 @@ Object.freeze({
28390
28545
  addonId: null,
28391
28546
  access: "create"
28392
28547
  },
28548
+ "localNetwork.downloadCa": {
28549
+ capName: "local-network",
28550
+ capScope: "system",
28551
+ addonId: null,
28552
+ access: "view"
28553
+ },
28393
28554
  "localNetwork.getAllowedAddresses": {
28394
28555
  capName: "local-network",
28395
28556
  capScope: "system",
@@ -28414,18 +28575,42 @@ Object.freeze({
28414
28575
  addonId: null,
28415
28576
  access: "view"
28416
28577
  },
28578
+ "localNetwork.getTlsStatus": {
28579
+ capName: "local-network",
28580
+ capScope: "system",
28581
+ addonId: null,
28582
+ access: "view"
28583
+ },
28584
+ "localNetwork.getViewerEndpoints": {
28585
+ capName: "local-network",
28586
+ capScope: "system",
28587
+ addonId: null,
28588
+ access: "view"
28589
+ },
28417
28590
  "localNetwork.list": {
28418
28591
  capName: "local-network",
28419
28592
  capScope: "system",
28420
28593
  addonId: null,
28421
28594
  access: "view"
28422
28595
  },
28596
+ "localNetwork.regenerateCertificate": {
28597
+ capName: "local-network",
28598
+ capScope: "system",
28599
+ addonId: null,
28600
+ access: "create"
28601
+ },
28423
28602
  "localNetwork.resetAllowlistToBestMatch": {
28424
28603
  capName: "local-network",
28425
28604
  capScope: "system",
28426
28605
  addonId: null,
28427
28606
  access: "delete"
28428
28607
  },
28608
+ "localNetwork.revertToGeneratedCertificate": {
28609
+ capName: "local-network",
28610
+ capScope: "system",
28611
+ addonId: null,
28612
+ access: "create"
28613
+ },
28429
28614
  "localNetwork.setAllowedAddresses": {
28430
28615
  capName: "local-network",
28431
28616
  capScope: "system",
@@ -28438,6 +28623,18 @@ Object.freeze({
28438
28623
  addonId: null,
28439
28624
  access: "create"
28440
28625
  },
28626
+ "localNetwork.setViewerEndpoints": {
28627
+ capName: "local-network",
28628
+ capScope: "system",
28629
+ addonId: null,
28630
+ access: "create"
28631
+ },
28632
+ "localNetwork.uploadCertificate": {
28633
+ capName: "local-network",
28634
+ capScope: "system",
28635
+ addonId: null,
28636
+ access: "create"
28637
+ },
28441
28638
  "lockControl.lock": {
28442
28639
  capName: "lock-control",
28443
28640
  capScope: "device",
@@ -31318,6 +31515,12 @@ Object.freeze({
31318
31515
  addonId: null,
31319
31516
  access: "create"
31320
31517
  },
31518
+ "terminalSession.updateInstance": {
31519
+ capName: "terminal-session",
31520
+ capScope: "system",
31521
+ addonId: null,
31522
+ access: "create"
31523
+ },
31321
31524
  "terminalSession.writeInput": {
31322
31525
  capName: "terminal-session",
31323
31526
  capScope: "system",
@@ -33805,6 +34008,35 @@ Object.freeze(Object.fromEntries([{
33805
34008
  }]
33806
34009
  }].map((s) => [s.stepId, s.defaultModelId])));
33807
34010
  string().min(1);
34011
+ var CLUSTER_STEP_SETTING_FIELDS = [{
34012
+ stepId: "face-embedding",
34013
+ key: "minLandmarkFaceSize",
34014
+ label: "Min face size for recognition (detection px)",
34015
+ description: "Refuse to embed a face smaller than this IN THE DETECTION FRAME. Applies to every node — the enrolled gallery is one index, and two admission floors would fill it from two policies. 0 disables the gate.",
34016
+ type: "slider",
34017
+ min: 0,
34018
+ max: 64,
34019
+ step: 2,
34020
+ default: 24
34021
+ }];
34022
+ function clusterStepSettingKey(stepId, fieldKey) {
34023
+ return `clusterStepSetting:${stepId}:${fieldKey}`;
34024
+ }
34025
+ var ClusterSettingNumberSchema = number().finite();
34026
+ function readClusterStepSettings(config) {
34027
+ const out = {};
34028
+ for (const field of CLUSTER_STEP_SETTING_FIELDS) {
34029
+ const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
34030
+ const value = parsed.success ? parsed.data : field.default;
34031
+ const existing = out[field.stepId] ?? {};
34032
+ out[field.stepId] = {
34033
+ ...existing,
34034
+ [field.key]: value
34035
+ };
34036
+ }
34037
+ return out;
34038
+ }
34039
+ readClusterStepSettings({});
33808
34040
  object({
33809
34041
  /**
33810
34042
  * Fraction of the box's own size added on EACH side before cutting.
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_shared = require("./shared-DmwERMr_.js");
5
+ const require_shared = require("./shared-UN8idVfB.js");
6
6
  let node_stream = require("node:stream");
7
7
  let webdav = require("webdav");
8
8
  //#region src/providers/webdav/webdav-config-schema.ts
@@ -1,4 +1,4 @@
1
- import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-B9MbTJyC.mjs";
1
+ import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-BwialOVX.mjs";
2
2
  import { PassThrough } from "node:stream";
3
3
  import { AuthType, createClient } from "webdav";
4
4
  //#region src/providers/webdav/webdav-config-schema.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-remote-storage",
3
- "version": "1.2.25",
3
+ "version": "1.2.26",
4
4
  "description": "Remote storage providers (SFTP, S3, WebDAV) — unifies remote backends behind the storage-provider cap",
5
5
  "keywords": [
6
6
  "camstack",