@camstack/addon-provider-tuya 0.2.26 → 0.2.27

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 (3) hide show
  1. package/dist/addon.js +248 -16
  2. package/dist/addon.mjs +248 -16
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -8840,6 +8840,15 @@ var LabelDefinitionSchema = object({
8840
8840
  description: string().optional(),
8841
8841
  icon: string().optional()
8842
8842
  });
8843
+ var ClassMapDefinitionSchema = object({
8844
+ mapping: record(string(), _enum([
8845
+ "person",
8846
+ "vehicle",
8847
+ "animal",
8848
+ "package"
8849
+ ])),
8850
+ preserveOriginal: boolean()
8851
+ });
8843
8852
  var MODEL_FORMATS = [
8844
8853
  "onnx",
8845
8854
  "coreml",
@@ -9018,7 +9027,13 @@ var ModelCatalogEntrySchema = object({
9018
9027
  * `id` stays the source of truth for resolution/download/persistence; grouping
9019
9028
  * is a presentation overlay resolved back to an `id`.
9020
9029
  */
9021
- group: ModelVariantGroupSchema.optional()
9030
+ group: ModelVariantGroupSchema.optional(),
9031
+ /**
9032
+ * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
9033
+ * applies (Frigate / COCO public catalog). Set on a custom model whose raw
9034
+ * labels already ARE the CamStack macros (Scrypted identity map).
9035
+ */
9036
+ classMap: ClassMapDefinitionSchema.optional()
9022
9037
  });
9023
9038
  var ConvertTargetSchema = discriminatedUnion("format", [object({
9024
9039
  format: literal("openvino"),
@@ -9047,7 +9062,8 @@ var ModelConvertMetadataSchema = object({
9047
9062
  "ocr",
9048
9063
  "segmentation"
9049
9064
  ]),
9050
- faceAlignment: boolean().optional()
9065
+ faceAlignment: boolean().optional(),
9066
+ classMap: ClassMapDefinitionSchema.optional()
9051
9067
  });
9052
9068
  var ConvertResultSchema = object({
9053
9069
  entry: ModelCatalogEntrySchema,
@@ -18357,6 +18373,33 @@ var NativeCropRefSchema = object({
18357
18373
  h: number()
18358
18374
  })
18359
18375
  });
18376
+ object({
18377
+ crop: object({
18378
+ left: number(),
18379
+ top: number(),
18380
+ width: number().positive(),
18381
+ height: number().positive()
18382
+ }).optional(),
18383
+ content: object({
18384
+ width: number().int().positive(),
18385
+ height: number().int().positive()
18386
+ }),
18387
+ fit: _enum(["stretch", "contain"]),
18388
+ format: _enum([
18389
+ "rgb",
18390
+ "gray",
18391
+ "jpeg"
18392
+ ])
18393
+ });
18394
+ var FrameRefSchema = object({
18395
+ registryId: string().min(1),
18396
+ id: string().min(1),
18397
+ width: number().int().positive(),
18398
+ height: number().int().positive(),
18399
+ format: _enum(["rgb", "gray"]),
18400
+ timestamp: number(),
18401
+ capturedAt: number().optional()
18402
+ });
18360
18403
  var ModelFormatSchema$1 = _enum([
18361
18404
  "onnx",
18362
18405
  "coreml",
@@ -18601,6 +18644,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
18601
18644
  steps: array(PipelineStepInputSchema).min(1),
18602
18645
  frame: FrameInputSchema.optional(),
18603
18646
  /**
18647
+ * Process-local lazy frame. Valid only when caller and provider resolve
18648
+ * in the same execution-group process; split/cross-node callers use
18649
+ * `frame`/`image` inline compatibility instead.
18650
+ */
18651
+ frameRef: FrameRefSchema.optional(),
18652
+ /**
18604
18653
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
18605
18654
  * the decoded pixels live in. One more member of the one-of
18606
18655
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -18896,7 +18945,10 @@ var NativeCropResultSchema = object({
18896
18945
  * Which source served this crop, so a quality-sensitive consumer (the native
18897
18946
  * `keyFrame`) can reject a degraded fallback:
18898
18947
  * - `native` — cut from the decode worker's retained NATIVE surface (the
18899
- * quality path).
18948
+ * quality path). A subject-tile serve is also native-resolution and stays
18949
+ * `native` here: the public enum cannot name `tile` without a breaking cap
18950
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
18951
+ * internal crop result (`nativeHits` vs `tileHits`).
18900
18952
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
18901
18953
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
18902
18954
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -19387,12 +19439,41 @@ var RunnerLocalLoadSchema = object({
19387
19439
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
19388
19440
  * working unchanged when they switch to reading from the runner cap.
19389
19441
  */
19442
+ var FrameLazyCountersSchema = object({
19443
+ framesDecoded: number(),
19444
+ framesAdmitted: number(),
19445
+ framesDroppedPixelFree: number(),
19446
+ viewsMaterialized: number(),
19447
+ viewsSkipped: number(),
19448
+ workerToRunnerBytes: number(),
19449
+ runnerToPoolRawBytes: number(),
19450
+ runnerToPoolJpegBytes: number(),
19451
+ onDemandFullFrameRequests: number(),
19452
+ onDemandCropRequests: number(),
19453
+ nativeHits: number(),
19454
+ nativeMisses: number(),
19455
+ tileHits: number(),
19456
+ tileMisses: number(),
19457
+ fallbackHits: number(),
19458
+ fallbackMisses: number(),
19459
+ retainedWritesAvoided: number(),
19460
+ residentRefs: number(),
19461
+ residentBytes: number(),
19462
+ releases: number(),
19463
+ evictions: number(),
19464
+ staleMisses: number()
19465
+ });
19466
+ var FrameLazyMetricsSchema = object({
19467
+ node: FrameLazyCountersSchema,
19468
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
19469
+ });
19390
19470
  var RunnerLocalMetricsSchema = object({
19391
19471
  nodeId: string(),
19392
19472
  activeCameras: number(),
19393
19473
  throttledCameras: number(),
19394
19474
  avgInferenceTimeMs: number(),
19395
- queueDepth: number()
19475
+ queueDepth: number(),
19476
+ frameLazy: FrameLazyMetricsSchema.optional()
19396
19477
  });
19397
19478
  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({
19398
19479
  handle: FrameHandleSchema,
@@ -20692,6 +20773,9 @@ method(_void(), ProviderInfoSchema), method(object({ config: record(string(), un
20692
20773
  location: StorageLocationSchema,
20693
20774
  relativePath: string()
20694
20775
  }), _void(), { kind: "mutation" }), method(object({ location: StorageLocationSchema }), number().nullable()), method(BeginUploadInputSchema, BeginUploadResultSchema, { kind: "mutation" }), method(WriteChunkInputSchema, _void(), { kind: "mutation" }), method(FinalizeUploadInputSchema, _void(), { kind: "mutation" }), method(AbortUploadInputSchema, _void(), { kind: "mutation" }), method(BeginDownloadInputSchema, BeginDownloadResultSchema, { kind: "mutation" }), method(ReadChunkInputSchema, _instanceof(Uint8Array)), method(EndDownloadInputSchema, _void(), { kind: "mutation" });
20776
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
20777
+ var ProfileSettingsSchemaBridge = unknown().nullable();
20778
+ var ProfileSettingsBagSchema = record(string(), unknown());
20695
20779
  /**
20696
20780
  * A live terminal session hosted by the provider addon. Output and input do
20697
20781
  * NOT flow through the capability — they use the addon data plane
@@ -20721,7 +20805,14 @@ var TerminalSessionInfoSchema = object({
20721
20805
  var TerminalProfileInfoSchema = object({
20722
20806
  profileId: string(),
20723
20807
  label: string(),
20724
- description: string().optional()
20808
+ description: string().optional(),
20809
+ /** Spawn defaults the instance form copies on create. */
20810
+ executable: string().optional(),
20811
+ args: array(string()).readonly().optional(),
20812
+ cwd: string().optional(),
20813
+ environment: array(string()).readonly().optional(),
20814
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
20815
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
20725
20816
  });
20726
20817
  /**
20727
20818
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -20734,7 +20825,12 @@ var TerminalInstanceInfoSchema = object({
20734
20825
  profileId: string(),
20735
20826
  profileLabel: string(),
20736
20827
  name: string(),
20737
- enabled: boolean()
20828
+ enabled: boolean(),
20829
+ executable: string(),
20830
+ args: array(string()).readonly(),
20831
+ cwd: string(),
20832
+ environment: array(string()).readonly(),
20833
+ profileSettings: ProfileSettingsBagSchema
20738
20834
  });
20739
20835
  var TerminalLegacyCameraSchema = object({
20740
20836
  stableId: string(),
@@ -20764,7 +20860,23 @@ var TerminalOutputBatchSchema = object({
20764
20860
  method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }), method(object({
20765
20861
  targetNodeId: string().min(1),
20766
20862
  profileId: string().min(1),
20767
- name: string().trim().min(1).max(160).optional()
20863
+ name: string().trim().min(1).max(160).optional(),
20864
+ executable: string().max(1024).optional(),
20865
+ args: array(string().max(2048)).max(64).optional(),
20866
+ cwd: string().max(1024).optional(),
20867
+ environment: array(string().max(4096)).max(64).optional(),
20868
+ profileSettings: ProfileSettingsBagSchema.optional()
20869
+ }), TerminalInstanceInfoSchema, {
20870
+ kind: "mutation",
20871
+ auth: "admin"
20872
+ }), method(object({
20873
+ instanceId: string().min(1),
20874
+ name: string().trim().min(1).max(160).optional(),
20875
+ executable: string().max(1024).optional(),
20876
+ args: array(string().max(2048)).max(64).optional(),
20877
+ cwd: string().max(1024).optional(),
20878
+ environment: array(string().max(4096)).max(64).optional(),
20879
+ profileSettings: ProfileSettingsBagSchema.optional()
20768
20880
  }), TerminalInstanceInfoSchema, {
20769
20881
  kind: "mutation",
20770
20882
  auth: "admin"
@@ -20786,7 +20898,11 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
20786
20898
  }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
20787
20899
  profileId: string(),
20788
20900
  cols: number().int().positive(),
20789
- rows: number().int().positive()
20901
+ rows: number().int().positive(),
20902
+ executable: string().max(1024).optional(),
20903
+ args: array(string().max(2048)).max(64).optional(),
20904
+ cwd: string().max(1024).optional(),
20905
+ environment: array(string().max(4096)).max(64).optional()
20790
20906
  }), TerminalSessionInfoSchema, {
20791
20907
  kind: "mutation",
20792
20908
  auth: "admin"
@@ -24669,10 +24785,10 @@ var lawnMowerControlCapability = {
24669
24785
  *
24670
24786
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
24671
24787
  * to receive an ordered list of candidate base URLs it should race
24672
- * on connect — LAN IPv4 first (lowest latency when on same network),
24673
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
24674
- * race them with short timeouts and stick with the winner for the
24675
- * session.
24788
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
24789
+ * when on the same network), then public hostname (if a tunnel is
24790
+ * up). The SDK can race them with short timeouts and stick with the
24791
+ * winner for the session.
24676
24792
  *
24677
24793
  * Why hub-only: agents are not directly addressable by the operator's
24678
24794
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -24827,6 +24943,17 @@ var NotificationEndpointSchema = object({
24827
24943
  /** What the ranking currently resolves to (null when nothing is reachable). */
24828
24944
  resolved: string().nullable()
24829
24945
  });
24946
+ /**
24947
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
24948
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
24949
+ * currently expands to, so the UI can show the effective set either way.
24950
+ */
24951
+ var ViewerEndpointsSchema = object({
24952
+ /** The operator's explicit race set, or empty for AUTO. */
24953
+ baseUrls: array(string()).readonly(),
24954
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
24955
+ resolved: array(string()).readonly()
24956
+ });
24830
24957
  var AllowedAddressesSchema = object({
24831
24958
  /**
24832
24959
  * Allowlist of interface addresses operators have explicitly opted
@@ -24835,6 +24962,20 @@ var AllowedAddressesSchema = object({
24835
24962
  * Network Addresses admin page and persisted by the addon.
24836
24963
  */
24837
24964
  addresses: array(string()).readonly() });
24965
+ var TlsStatusSchema = object({
24966
+ mode: _enum([
24967
+ "generated",
24968
+ "uploaded",
24969
+ "disabled"
24970
+ ]),
24971
+ leafFingerprintSha256: string().nullable(),
24972
+ caFingerprintSha256: string().nullable(),
24973
+ validTo: string().nullable(),
24974
+ sans: array(string()),
24975
+ caCertPem: string().nullable(),
24976
+ reissueError: string().nullable(),
24977
+ restartRequired: boolean()
24978
+ });
24838
24979
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
24839
24980
  /**
24840
24981
  * LEGACY HINT — do not send from new code. Kept optional so clients
@@ -24844,17 +24985,31 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
24844
24985
  */
24845
24986
  port: number().int().min(1).max(65535).optional(),
24846
24987
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
24847
- * candidate. Default `true`. */
24988
+ * candidate. Default `false` — loopback is not a client route. */
24848
24989
  includeLoopback: boolean().optional(),
24849
- /** Skip IPv6 entries. Some legacy clients can't parse them.
24850
- * Default `false`. */
24990
+ /** Skip IPv6 entries. Default `false` the palette includes stable
24991
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
24992
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
24851
24993
  ipv4Only: boolean().optional(),
24852
24994
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
24853
24995
  * Pass `'https'` when the caller is itself loaded over HTTPS
24854
24996
  * to avoid mixed-content blocks in the browser. The public
24855
24997
  * tunnel always emits `https://` regardless. */
24856
24998
  scheme: _enum(["http", "https"]).optional()
24857
- }), 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" });
24999
+ }), 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, {
25000
+ kind: "mutation",
25001
+ auth: "admin"
25002
+ }), method(object({
25003
+ certPem: string().min(1),
25004
+ keyPem: string().min(1),
25005
+ caPem: string().optional()
25006
+ }), TlsStatusSchema, {
25007
+ kind: "mutation",
25008
+ auth: "admin"
25009
+ }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
25010
+ kind: "mutation",
25011
+ auth: "admin"
25012
+ });
24858
25013
  var LockControlStatusSchema = object({
24859
25014
  /** Lifecycle state of the lock. `jammed` means the motor reported
24860
25015
  * failure to reach the target — operator intervention required. */
@@ -32881,6 +33036,12 @@ Object.freeze({
32881
33036
  addonId: null,
32882
33037
  access: "create"
32883
33038
  },
33039
+ "localNetwork.downloadCa": {
33040
+ capName: "local-network",
33041
+ capScope: "system",
33042
+ addonId: null,
33043
+ access: "view"
33044
+ },
32884
33045
  "localNetwork.getAllowedAddresses": {
32885
33046
  capName: "local-network",
32886
33047
  capScope: "system",
@@ -32905,18 +33066,42 @@ Object.freeze({
32905
33066
  addonId: null,
32906
33067
  access: "view"
32907
33068
  },
33069
+ "localNetwork.getTlsStatus": {
33070
+ capName: "local-network",
33071
+ capScope: "system",
33072
+ addonId: null,
33073
+ access: "view"
33074
+ },
33075
+ "localNetwork.getViewerEndpoints": {
33076
+ capName: "local-network",
33077
+ capScope: "system",
33078
+ addonId: null,
33079
+ access: "view"
33080
+ },
32908
33081
  "localNetwork.list": {
32909
33082
  capName: "local-network",
32910
33083
  capScope: "system",
32911
33084
  addonId: null,
32912
33085
  access: "view"
32913
33086
  },
33087
+ "localNetwork.regenerateCertificate": {
33088
+ capName: "local-network",
33089
+ capScope: "system",
33090
+ addonId: null,
33091
+ access: "create"
33092
+ },
32914
33093
  "localNetwork.resetAllowlistToBestMatch": {
32915
33094
  capName: "local-network",
32916
33095
  capScope: "system",
32917
33096
  addonId: null,
32918
33097
  access: "delete"
32919
33098
  },
33099
+ "localNetwork.revertToGeneratedCertificate": {
33100
+ capName: "local-network",
33101
+ capScope: "system",
33102
+ addonId: null,
33103
+ access: "create"
33104
+ },
32920
33105
  "localNetwork.setAllowedAddresses": {
32921
33106
  capName: "local-network",
32922
33107
  capScope: "system",
@@ -32929,6 +33114,18 @@ Object.freeze({
32929
33114
  addonId: null,
32930
33115
  access: "create"
32931
33116
  },
33117
+ "localNetwork.setViewerEndpoints": {
33118
+ capName: "local-network",
33119
+ capScope: "system",
33120
+ addonId: null,
33121
+ access: "create"
33122
+ },
33123
+ "localNetwork.uploadCertificate": {
33124
+ capName: "local-network",
33125
+ capScope: "system",
33126
+ addonId: null,
33127
+ access: "create"
33128
+ },
32932
33129
  "lockControl.lock": {
32933
33130
  capName: "lock-control",
32934
33131
  capScope: "device",
@@ -35809,6 +36006,12 @@ Object.freeze({
35809
36006
  addonId: null,
35810
36007
  access: "create"
35811
36008
  },
36009
+ "terminalSession.updateInstance": {
36010
+ capName: "terminal-session",
36011
+ capScope: "system",
36012
+ addonId: null,
36013
+ access: "create"
36014
+ },
35812
36015
  "terminalSession.writeInput": {
35813
36016
  capName: "terminal-session",
35814
36017
  capScope: "system",
@@ -38296,6 +38499,35 @@ Object.freeze(Object.fromEntries([{
38296
38499
  }]
38297
38500
  }].map((s) => [s.stepId, s.defaultModelId])));
38298
38501
  string().min(1);
38502
+ var CLUSTER_STEP_SETTING_FIELDS = [{
38503
+ stepId: "face-embedding",
38504
+ key: "minLandmarkFaceSize",
38505
+ label: "Min face size for recognition (detection px)",
38506
+ 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.",
38507
+ type: "slider",
38508
+ min: 0,
38509
+ max: 64,
38510
+ step: 2,
38511
+ default: 24
38512
+ }];
38513
+ function clusterStepSettingKey(stepId, fieldKey) {
38514
+ return `clusterStepSetting:${stepId}:${fieldKey}`;
38515
+ }
38516
+ var ClusterSettingNumberSchema = number().finite();
38517
+ function readClusterStepSettings(config) {
38518
+ const out = {};
38519
+ for (const field of CLUSTER_STEP_SETTING_FIELDS) {
38520
+ const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
38521
+ const value = parsed.success ? parsed.data : field.default;
38522
+ const existing = out[field.stepId] ?? {};
38523
+ out[field.stepId] = {
38524
+ ...existing,
38525
+ [field.key]: value
38526
+ };
38527
+ }
38528
+ return out;
38529
+ }
38530
+ readClusterStepSettings({});
38299
38531
  object({
38300
38532
  /**
38301
38533
  * Fraction of the box's own size added on EACH side before cutting.
package/dist/addon.mjs CHANGED
@@ -8839,6 +8839,15 @@ var LabelDefinitionSchema = object({
8839
8839
  description: string().optional(),
8840
8840
  icon: string().optional()
8841
8841
  });
8842
+ var ClassMapDefinitionSchema = object({
8843
+ mapping: record(string(), _enum([
8844
+ "person",
8845
+ "vehicle",
8846
+ "animal",
8847
+ "package"
8848
+ ])),
8849
+ preserveOriginal: boolean()
8850
+ });
8842
8851
  var MODEL_FORMATS = [
8843
8852
  "onnx",
8844
8853
  "coreml",
@@ -9017,7 +9026,13 @@ var ModelCatalogEntrySchema = object({
9017
9026
  * `id` stays the source of truth for resolution/download/persistence; grouping
9018
9027
  * is a presentation overlay resolved back to an `id`.
9019
9028
  */
9020
- group: ModelVariantGroupSchema.optional()
9029
+ group: ModelVariantGroupSchema.optional(),
9030
+ /**
9031
+ * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
9032
+ * applies (Frigate / COCO public catalog). Set on a custom model whose raw
9033
+ * labels already ARE the CamStack macros (Scrypted identity map).
9034
+ */
9035
+ classMap: ClassMapDefinitionSchema.optional()
9021
9036
  });
9022
9037
  var ConvertTargetSchema = discriminatedUnion("format", [object({
9023
9038
  format: literal("openvino"),
@@ -9046,7 +9061,8 @@ var ModelConvertMetadataSchema = object({
9046
9061
  "ocr",
9047
9062
  "segmentation"
9048
9063
  ]),
9049
- faceAlignment: boolean().optional()
9064
+ faceAlignment: boolean().optional(),
9065
+ classMap: ClassMapDefinitionSchema.optional()
9050
9066
  });
9051
9067
  var ConvertResultSchema = object({
9052
9068
  entry: ModelCatalogEntrySchema,
@@ -18356,6 +18372,33 @@ var NativeCropRefSchema = object({
18356
18372
  h: number()
18357
18373
  })
18358
18374
  });
18375
+ object({
18376
+ crop: object({
18377
+ left: number(),
18378
+ top: number(),
18379
+ width: number().positive(),
18380
+ height: number().positive()
18381
+ }).optional(),
18382
+ content: object({
18383
+ width: number().int().positive(),
18384
+ height: number().int().positive()
18385
+ }),
18386
+ fit: _enum(["stretch", "contain"]),
18387
+ format: _enum([
18388
+ "rgb",
18389
+ "gray",
18390
+ "jpeg"
18391
+ ])
18392
+ });
18393
+ var FrameRefSchema = object({
18394
+ registryId: string().min(1),
18395
+ id: string().min(1),
18396
+ width: number().int().positive(),
18397
+ height: number().int().positive(),
18398
+ format: _enum(["rgb", "gray"]),
18399
+ timestamp: number(),
18400
+ capturedAt: number().optional()
18401
+ });
18359
18402
  var ModelFormatSchema$1 = _enum([
18360
18403
  "onnx",
18361
18404
  "coreml",
@@ -18600,6 +18643,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
18600
18643
  steps: array(PipelineStepInputSchema).min(1),
18601
18644
  frame: FrameInputSchema.optional(),
18602
18645
  /**
18646
+ * Process-local lazy frame. Valid only when caller and provider resolve
18647
+ * in the same execution-group process; split/cross-node callers use
18648
+ * `frame`/`image` inline compatibility instead.
18649
+ */
18650
+ frameRef: FrameRefSchema.optional(),
18651
+ /**
18603
18652
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
18604
18653
  * the decoded pixels live in. One more member of the one-of
18605
18654
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -18895,7 +18944,10 @@ var NativeCropResultSchema = object({
18895
18944
  * Which source served this crop, so a quality-sensitive consumer (the native
18896
18945
  * `keyFrame`) can reject a degraded fallback:
18897
18946
  * - `native` — cut from the decode worker's retained NATIVE surface (the
18898
- * quality path).
18947
+ * quality path). A subject-tile serve is also native-resolution and stays
18948
+ * `native` here: the public enum cannot name `tile` without a breaking cap
18949
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
18950
+ * internal crop result (`nativeHits` vs `tileHits`).
18899
18951
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
18900
18952
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
18901
18953
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -19386,12 +19438,41 @@ var RunnerLocalLoadSchema = object({
19386
19438
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
19387
19439
  * working unchanged when they switch to reading from the runner cap.
19388
19440
  */
19441
+ var FrameLazyCountersSchema = object({
19442
+ framesDecoded: number(),
19443
+ framesAdmitted: number(),
19444
+ framesDroppedPixelFree: number(),
19445
+ viewsMaterialized: number(),
19446
+ viewsSkipped: number(),
19447
+ workerToRunnerBytes: number(),
19448
+ runnerToPoolRawBytes: number(),
19449
+ runnerToPoolJpegBytes: number(),
19450
+ onDemandFullFrameRequests: number(),
19451
+ onDemandCropRequests: number(),
19452
+ nativeHits: number(),
19453
+ nativeMisses: number(),
19454
+ tileHits: number(),
19455
+ tileMisses: number(),
19456
+ fallbackHits: number(),
19457
+ fallbackMisses: number(),
19458
+ retainedWritesAvoided: number(),
19459
+ residentRefs: number(),
19460
+ residentBytes: number(),
19461
+ releases: number(),
19462
+ evictions: number(),
19463
+ staleMisses: number()
19464
+ });
19465
+ var FrameLazyMetricsSchema = object({
19466
+ node: FrameLazyCountersSchema,
19467
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
19468
+ });
19389
19469
  var RunnerLocalMetricsSchema = object({
19390
19470
  nodeId: string(),
19391
19471
  activeCameras: number(),
19392
19472
  throttledCameras: number(),
19393
19473
  avgInferenceTimeMs: number(),
19394
- queueDepth: number()
19474
+ queueDepth: number(),
19475
+ frameLazy: FrameLazyMetricsSchema.optional()
19395
19476
  });
19396
19477
  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({
19397
19478
  handle: FrameHandleSchema,
@@ -20691,6 +20772,9 @@ method(_void(), ProviderInfoSchema), method(object({ config: record(string(), un
20691
20772
  location: StorageLocationSchema,
20692
20773
  relativePath: string()
20693
20774
  }), _void(), { kind: "mutation" }), method(object({ location: StorageLocationSchema }), number().nullable()), method(BeginUploadInputSchema, BeginUploadResultSchema, { kind: "mutation" }), method(WriteChunkInputSchema, _void(), { kind: "mutation" }), method(FinalizeUploadInputSchema, _void(), { kind: "mutation" }), method(AbortUploadInputSchema, _void(), { kind: "mutation" }), method(BeginDownloadInputSchema, BeginDownloadResultSchema, { kind: "mutation" }), method(ReadChunkInputSchema, _instanceof(Uint8Array)), method(EndDownloadInputSchema, _void(), { kind: "mutation" });
20775
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
20776
+ var ProfileSettingsSchemaBridge = unknown().nullable();
20777
+ var ProfileSettingsBagSchema = record(string(), unknown());
20694
20778
  /**
20695
20779
  * A live terminal session hosted by the provider addon. Output and input do
20696
20780
  * NOT flow through the capability — they use the addon data plane
@@ -20720,7 +20804,14 @@ var TerminalSessionInfoSchema = object({
20720
20804
  var TerminalProfileInfoSchema = object({
20721
20805
  profileId: string(),
20722
20806
  label: string(),
20723
- description: string().optional()
20807
+ description: string().optional(),
20808
+ /** Spawn defaults the instance form copies on create. */
20809
+ executable: string().optional(),
20810
+ args: array(string()).readonly().optional(),
20811
+ cwd: string().optional(),
20812
+ environment: array(string()).readonly().optional(),
20813
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
20814
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
20724
20815
  });
20725
20816
  /**
20726
20817
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -20733,7 +20824,12 @@ var TerminalInstanceInfoSchema = object({
20733
20824
  profileId: string(),
20734
20825
  profileLabel: string(),
20735
20826
  name: string(),
20736
- enabled: boolean()
20827
+ enabled: boolean(),
20828
+ executable: string(),
20829
+ args: array(string()).readonly(),
20830
+ cwd: string(),
20831
+ environment: array(string()).readonly(),
20832
+ profileSettings: ProfileSettingsBagSchema
20737
20833
  });
20738
20834
  var TerminalLegacyCameraSchema = object({
20739
20835
  stableId: string(),
@@ -20763,7 +20859,23 @@ var TerminalOutputBatchSchema = object({
20763
20859
  method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }), method(object({
20764
20860
  targetNodeId: string().min(1),
20765
20861
  profileId: string().min(1),
20766
- name: string().trim().min(1).max(160).optional()
20862
+ name: string().trim().min(1).max(160).optional(),
20863
+ executable: string().max(1024).optional(),
20864
+ args: array(string().max(2048)).max(64).optional(),
20865
+ cwd: string().max(1024).optional(),
20866
+ environment: array(string().max(4096)).max(64).optional(),
20867
+ profileSettings: ProfileSettingsBagSchema.optional()
20868
+ }), TerminalInstanceInfoSchema, {
20869
+ kind: "mutation",
20870
+ auth: "admin"
20871
+ }), method(object({
20872
+ instanceId: string().min(1),
20873
+ name: string().trim().min(1).max(160).optional(),
20874
+ executable: string().max(1024).optional(),
20875
+ args: array(string().max(2048)).max(64).optional(),
20876
+ cwd: string().max(1024).optional(),
20877
+ environment: array(string().max(4096)).max(64).optional(),
20878
+ profileSettings: ProfileSettingsBagSchema.optional()
20767
20879
  }), TerminalInstanceInfoSchema, {
20768
20880
  kind: "mutation",
20769
20881
  auth: "admin"
@@ -20785,7 +20897,11 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
20785
20897
  }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
20786
20898
  profileId: string(),
20787
20899
  cols: number().int().positive(),
20788
- rows: number().int().positive()
20900
+ rows: number().int().positive(),
20901
+ executable: string().max(1024).optional(),
20902
+ args: array(string().max(2048)).max(64).optional(),
20903
+ cwd: string().max(1024).optional(),
20904
+ environment: array(string().max(4096)).max(64).optional()
20789
20905
  }), TerminalSessionInfoSchema, {
20790
20906
  kind: "mutation",
20791
20907
  auth: "admin"
@@ -24668,10 +24784,10 @@ var lawnMowerControlCapability = {
24668
24784
  *
24669
24785
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
24670
24786
  * to receive an ordered list of candidate base URLs it should race
24671
- * on connect — LAN IPv4 first (lowest latency when on same network),
24672
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
24673
- * race them with short timeouts and stick with the winner for the
24674
- * session.
24787
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
24788
+ * when on the same network), then public hostname (if a tunnel is
24789
+ * up). The SDK can race them with short timeouts and stick with the
24790
+ * winner for the session.
24675
24791
  *
24676
24792
  * Why hub-only: agents are not directly addressable by the operator's
24677
24793
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -24826,6 +24942,17 @@ var NotificationEndpointSchema = object({
24826
24942
  /** What the ranking currently resolves to (null when nothing is reachable). */
24827
24943
  resolved: string().nullable()
24828
24944
  });
24945
+ /**
24946
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
24947
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
24948
+ * currently expands to, so the UI can show the effective set either way.
24949
+ */
24950
+ var ViewerEndpointsSchema = object({
24951
+ /** The operator's explicit race set, or empty for AUTO. */
24952
+ baseUrls: array(string()).readonly(),
24953
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
24954
+ resolved: array(string()).readonly()
24955
+ });
24829
24956
  var AllowedAddressesSchema = object({
24830
24957
  /**
24831
24958
  * Allowlist of interface addresses operators have explicitly opted
@@ -24834,6 +24961,20 @@ var AllowedAddressesSchema = object({
24834
24961
  * Network Addresses admin page and persisted by the addon.
24835
24962
  */
24836
24963
  addresses: array(string()).readonly() });
24964
+ var TlsStatusSchema = object({
24965
+ mode: _enum([
24966
+ "generated",
24967
+ "uploaded",
24968
+ "disabled"
24969
+ ]),
24970
+ leafFingerprintSha256: string().nullable(),
24971
+ caFingerprintSha256: string().nullable(),
24972
+ validTo: string().nullable(),
24973
+ sans: array(string()),
24974
+ caCertPem: string().nullable(),
24975
+ reissueError: string().nullable(),
24976
+ restartRequired: boolean()
24977
+ });
24837
24978
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
24838
24979
  /**
24839
24980
  * LEGACY HINT — do not send from new code. Kept optional so clients
@@ -24843,17 +24984,31 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
24843
24984
  */
24844
24985
  port: number().int().min(1).max(65535).optional(),
24845
24986
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
24846
- * candidate. Default `true`. */
24987
+ * candidate. Default `false` — loopback is not a client route. */
24847
24988
  includeLoopback: boolean().optional(),
24848
- /** Skip IPv6 entries. Some legacy clients can't parse them.
24849
- * Default `false`. */
24989
+ /** Skip IPv6 entries. Default `false` the palette includes stable
24990
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
24991
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
24850
24992
  ipv4Only: boolean().optional(),
24851
24993
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
24852
24994
  * Pass `'https'` when the caller is itself loaded over HTTPS
24853
24995
  * to avoid mixed-content blocks in the browser. The public
24854
24996
  * tunnel always emits `https://` regardless. */
24855
24997
  scheme: _enum(["http", "https"]).optional()
24856
- }), 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" });
24998
+ }), 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, {
24999
+ kind: "mutation",
25000
+ auth: "admin"
25001
+ }), method(object({
25002
+ certPem: string().min(1),
25003
+ keyPem: string().min(1),
25004
+ caPem: string().optional()
25005
+ }), TlsStatusSchema, {
25006
+ kind: "mutation",
25007
+ auth: "admin"
25008
+ }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
25009
+ kind: "mutation",
25010
+ auth: "admin"
25011
+ });
24857
25012
  var LockControlStatusSchema = object({
24858
25013
  /** Lifecycle state of the lock. `jammed` means the motor reported
24859
25014
  * failure to reach the target — operator intervention required. */
@@ -32880,6 +33035,12 @@ Object.freeze({
32880
33035
  addonId: null,
32881
33036
  access: "create"
32882
33037
  },
33038
+ "localNetwork.downloadCa": {
33039
+ capName: "local-network",
33040
+ capScope: "system",
33041
+ addonId: null,
33042
+ access: "view"
33043
+ },
32883
33044
  "localNetwork.getAllowedAddresses": {
32884
33045
  capName: "local-network",
32885
33046
  capScope: "system",
@@ -32904,18 +33065,42 @@ Object.freeze({
32904
33065
  addonId: null,
32905
33066
  access: "view"
32906
33067
  },
33068
+ "localNetwork.getTlsStatus": {
33069
+ capName: "local-network",
33070
+ capScope: "system",
33071
+ addonId: null,
33072
+ access: "view"
33073
+ },
33074
+ "localNetwork.getViewerEndpoints": {
33075
+ capName: "local-network",
33076
+ capScope: "system",
33077
+ addonId: null,
33078
+ access: "view"
33079
+ },
32907
33080
  "localNetwork.list": {
32908
33081
  capName: "local-network",
32909
33082
  capScope: "system",
32910
33083
  addonId: null,
32911
33084
  access: "view"
32912
33085
  },
33086
+ "localNetwork.regenerateCertificate": {
33087
+ capName: "local-network",
33088
+ capScope: "system",
33089
+ addonId: null,
33090
+ access: "create"
33091
+ },
32913
33092
  "localNetwork.resetAllowlistToBestMatch": {
32914
33093
  capName: "local-network",
32915
33094
  capScope: "system",
32916
33095
  addonId: null,
32917
33096
  access: "delete"
32918
33097
  },
33098
+ "localNetwork.revertToGeneratedCertificate": {
33099
+ capName: "local-network",
33100
+ capScope: "system",
33101
+ addonId: null,
33102
+ access: "create"
33103
+ },
32919
33104
  "localNetwork.setAllowedAddresses": {
32920
33105
  capName: "local-network",
32921
33106
  capScope: "system",
@@ -32928,6 +33113,18 @@ Object.freeze({
32928
33113
  addonId: null,
32929
33114
  access: "create"
32930
33115
  },
33116
+ "localNetwork.setViewerEndpoints": {
33117
+ capName: "local-network",
33118
+ capScope: "system",
33119
+ addonId: null,
33120
+ access: "create"
33121
+ },
33122
+ "localNetwork.uploadCertificate": {
33123
+ capName: "local-network",
33124
+ capScope: "system",
33125
+ addonId: null,
33126
+ access: "create"
33127
+ },
32931
33128
  "lockControl.lock": {
32932
33129
  capName: "lock-control",
32933
33130
  capScope: "device",
@@ -35808,6 +36005,12 @@ Object.freeze({
35808
36005
  addonId: null,
35809
36006
  access: "create"
35810
36007
  },
36008
+ "terminalSession.updateInstance": {
36009
+ capName: "terminal-session",
36010
+ capScope: "system",
36011
+ addonId: null,
36012
+ access: "create"
36013
+ },
35811
36014
  "terminalSession.writeInput": {
35812
36015
  capName: "terminal-session",
35813
36016
  capScope: "system",
@@ -38295,6 +38498,35 @@ Object.freeze(Object.fromEntries([{
38295
38498
  }]
38296
38499
  }].map((s) => [s.stepId, s.defaultModelId])));
38297
38500
  string().min(1);
38501
+ var CLUSTER_STEP_SETTING_FIELDS = [{
38502
+ stepId: "face-embedding",
38503
+ key: "minLandmarkFaceSize",
38504
+ label: "Min face size for recognition (detection px)",
38505
+ 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.",
38506
+ type: "slider",
38507
+ min: 0,
38508
+ max: 64,
38509
+ step: 2,
38510
+ default: 24
38511
+ }];
38512
+ function clusterStepSettingKey(stepId, fieldKey) {
38513
+ return `clusterStepSetting:${stepId}:${fieldKey}`;
38514
+ }
38515
+ var ClusterSettingNumberSchema = number().finite();
38516
+ function readClusterStepSettings(config) {
38517
+ const out = {};
38518
+ for (const field of CLUSTER_STEP_SETTING_FIELDS) {
38519
+ const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
38520
+ const value = parsed.success ? parsed.data : field.default;
38521
+ const existing = out[field.stepId] ?? {};
38522
+ out[field.stepId] = {
38523
+ ...existing,
38524
+ [field.key]: value
38525
+ };
38526
+ }
38527
+ return out;
38528
+ }
38529
+ readClusterStepSettings({});
38298
38530
  object({
38299
38531
  /**
38300
38532
  * Fraction of the box's own size added on EACH side before cutting.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-tuya",
3
- "version": "0.2.26",
3
+ "version": "0.2.27",
4
4
  "description": "Tuya / Smart Life device-provider addon for CamStack — account-onboarded (Tuya IoT cloud fetch of device localKeys) + LOCAL DP control via the @apocaliss92/nodetuya encrypted-LAN client, exposing switch / water-heater-family kettle entities",
5
5
  "keywords": [
6
6
  "camstack",