@camstack/addon-provider-tuya 0.2.119 → 0.2.120

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 +122 -76
  2. package/dist/addon.mjs +122 -76
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -11354,11 +11354,11 @@ var ModelVariantGroupSchema = object({
11354
11354
  /** Quantization axis. Omit ⇒ the fp32 base build. */
11355
11355
  precision: _enum(["fp32", "int8"]).optional(),
11356
11356
  /**
11357
- * Speed-optimization axis. Omit ⇒ the standard build. `fast` marks a
11358
- * latency-optimized export (e.g. ReLU-activation variant) — the slot the
11359
- * future performance variants plug into.
11357
+ * Training / latency-variant axis. Omit ⇒ the standard build. `test` marks
11358
+ * an alternate training of the same family (Scrypted `relu_test`); chip
11359
+ * label is "Test".
11360
11360
  */
11361
- optimization: _enum(["standard", "fast"]).optional(),
11361
+ optimization: _enum(["standard", "test"]).optional(),
11362
11362
  /**
11363
11363
  * Input-resolution axis (square input side, px). Omit ⇒ the family's native
11364
11364
  * resolution (640 for yolo26). Reduced-input builds (320 / 256) are a big,
@@ -11381,9 +11381,10 @@ var ModelProviderIdSchema = _enum([
11381
11381
  * are per upstream. A persisted custom-model row written when this field was a
11382
11382
  * string still parses — the string is lifted into `{ weights }`.
11383
11383
  *
11384
- * Every licence surface (the admin "Models and licenses" page,
11385
- * `THIRD_PARTY_MODELS.md`, the Hugging Face model table) is GENERATED from
11386
- * these records by `scripts/gen-model-licenses.ts` (D661).
11384
+ * Every machine licence surface (`THIRD_PARTY_MODELS.md`, the Hugging Face
11385
+ * model table) is GENERATED from these records by
11386
+ * `scripts/gen-model-licenses.ts` (D661). Operator-facing docs live in
11387
+ * `camstack/docs` → `/docs/detection/models`.
11387
11388
  */
11388
11389
  var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { weights: value } : value, object({
11389
11390
  /** SPDX id of the WEIGHTS' terms, a `LicenseRef-*` for non-SPDX terms, or `UNKNOWN`. */
@@ -15014,7 +15015,7 @@ DeviceType.Camera;
15014
15015
  * This matters here more than anywhere else in the repo, because every provider
15015
15016
  * that knows a device's host knows its PASSWORD too: `{ host, port, username,
15016
15017
  * password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
15017
- * and `http://admin:hunter2@192.168.x.x/` is a URL a browser accepts. The
15018
+ * and `http://admin:hunter2@192.168.60.139/` is a URL a browser accepts. The
15018
15019
  * camera's own page will ask for its own login. That is correct, and pre-
15019
15020
  * filling it is the operator's business, not ours.
15020
15021
  *
@@ -18203,7 +18204,7 @@ method(object({
18203
18204
  timeoutMs: 6e5
18204
18205
  });
18205
18206
  method(object({
18206
- nodeId: string(),
18207
+ targetNodeId: string(),
18207
18208
  modelId: string(),
18208
18209
  format: _enum(MODEL_FORMATS),
18209
18210
  entry: ModelCatalogEntrySchema
@@ -20707,8 +20708,9 @@ var NcRuleSchema = NcRuleInputSchema.extend({
20707
20708
  disabledTargetIds: array(string()).default([])
20708
20709
  });
20709
20710
  /**
20710
- * The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
20711
- * still-true state. `backups-exports` and `alarm` are not sections — a completed
20711
+ * The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
20712
+ * report a still-true state. `addons` is the crash-looped addons only and
20713
+ * `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
20712
20714
  * job is not an open state, and the alarm stays instant.
20713
20715
  */
20714
20716
  var NcStateSummarySectionIdSchema = _enum([
@@ -20720,6 +20722,7 @@ var NcStateSummarySectionIdSchema = _enum([
20720
20722
  "detection-blind",
20721
20723
  "nodes",
20722
20724
  "addons",
20725
+ "addon-updates",
20723
20726
  "updates"
20724
20727
  ]);
20725
20728
  /** One section of a previewed state summary. `unavailable` = its state could not be read. */
@@ -21200,7 +21203,19 @@ var NcAlarmModeDelaysListSchema = array(object({
21200
21203
  * When this mode may be armed. Absent / null = always allowed (same as a
21201
21204
  * rule with no `schedule`). Evaluated with {@link isScheduleActive}.
21202
21205
  */
21203
- schedule: NcScheduleSchema.optional()
21206
+ schedule: NcScheduleSchema.optional(),
21207
+ /**
21208
+ * D706: while this mode's ENTRY DELAY runs, do the alarm rules' own pushes go out (as an
21209
+ * intrusion naming the locations)? Absent = false — the entry-delay notification is the
21210
+ * only one, and the matches ride the triggered notification's mosaic (D705).
21211
+ */
21212
+ notifyDuringEntryDelay: boolean().optional(),
21213
+ /**
21214
+ * D706: notify "watched again" when a sensor this arm bypassed closes and opens again.
21215
+ * Absent = false (logged, not sent). Even when true it is not sent when that same sensor
21216
+ * is the one that starts the entry delay — the entry-delay notification already names it.
21217
+ */
21218
+ notifySensorRewatched: boolean().optional()
21204
21219
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
21205
21220
  var NcAlarmModeDelaysEditListSchema = array(object({
21206
21221
  mode: AlarmArmModeSchema,
@@ -21209,7 +21224,11 @@ var NcAlarmModeDelaysEditListSchema = array(object({
21209
21224
  triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
21210
21225
  postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
21211
21226
  /** Set a schedule, or `null` to clear (mode always allowed again). */
21212
- schedule: NcScheduleSchema.nullable().optional()
21227
+ schedule: NcScheduleSchema.nullable().optional(),
21228
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
21229
+ notifyDuringEntryDelay: boolean().nullable().optional(),
21230
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
21231
+ notifySensorRewatched: boolean().nullable().optional()
21213
21232
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
21214
21233
  /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
21215
21234
  var NcAlarmNonBlockingEditSchema = object({
@@ -22170,39 +22189,19 @@ Object.freeze(Object.fromEntries([{
22170
22189
  label: "Face recognition model",
22171
22190
  defaultModelId: "auraface-r100",
22172
22191
  indexName: "the enrolled face gallery",
22173
- options: [
22174
- {
22175
- id: "auraface-r100",
22176
- label: "AuraFace R100"
22177
- },
22178
- {
22179
- id: "arcface-r100",
22180
- label: "ArcFace (ResNet34)"
22181
- },
22182
- {
22183
- id: "inception-resnet-v1",
22184
- label: "Inception ResNet V1"
22185
- }
22186
- ]
22192
+ options: [{
22193
+ id: "auraface-r100",
22194
+ label: "AuraFace R100"
22195
+ }]
22187
22196
  }, {
22188
22197
  stepId: "clip-embedding",
22189
22198
  label: "Semantic search model",
22190
- defaultModelId: "mobileclip-s1",
22199
+ defaultModelId: "siglip2-b16-224",
22191
22200
  indexName: "the object semantic-search index",
22192
- options: [
22193
- {
22194
- id: "mobileclip-s1",
22195
- label: "MobileCLIP S1"
22196
- },
22197
- {
22198
- id: "mobileclip-s2",
22199
- label: "MobileCLIP S2"
22200
- },
22201
- {
22202
- id: "siglip2-b16-224",
22203
- label: "SigLIP2 B/16 (Apache-2.0)"
22204
- }
22205
- ]
22201
+ options: [{
22202
+ id: "siglip2-b16-224",
22203
+ label: "SigLIP2 B/16 (Apache-2.0)"
22204
+ }]
22206
22205
  }].map((s) => [s.stepId, s.defaultModelId])));
22207
22206
  var CLUSTER_STEP_SETTING_FIELDS = [{
22208
22207
  stepId: "face-embedding",
@@ -25090,6 +25089,22 @@ var MotionSourceEnum = _enum([
25090
25089
  "device-activity"
25091
25090
  ]);
25092
25091
  /**
25092
+ * What opened an on-motion detection SESSION: the motion source that passed the
25093
+ * camera's `motionSources` gate, and what raised it (the camera itself, or a
25094
+ * sensor the operator attached — D672). `sensorName` is the attached sensor's
25095
+ * device name as the orchestrator's camera-sensors resolution last read it;
25096
+ * absent when unknown or when the camera itself triggered.
25097
+ *
25098
+ * Carried on the session attach ONLY so the runner's `DetectionPhaseTransition`
25099
+ * can say what started the session (D672 rule 11, amended 2026-10-06). The
25100
+ * runner never decides anything on it.
25101
+ */
25102
+ var SessionTriggerSchema = object({
25103
+ source: MotionSourceEnum,
25104
+ triggeredBy: MotionTriggeredBySchema,
25105
+ sensorName: string().optional()
25106
+ });
25107
+ /**
25093
25108
  * List of motion sources active on a camera. Empty array is valid:
25094
25109
  * "no source" — happens for battery cams without firmware motion when
25095
25110
  * the operator hasn't opted into the SW analyzer (would hold the
@@ -25341,6 +25356,14 @@ var RunnerCameraConfigSchema = object({
25341
25356
  */
25342
25357
  motionSources: MotionSourcesSchema.default(["analyzer"]),
25343
25358
  /**
25359
+ * What opened this attach, on a SESSION attach only (see
25360
+ * {@link SessionTriggerSchema}). OPTIONAL with no default: absent on a
25361
+ * standing attach, an occupancy burst, a re-dispatch with no motion event
25362
+ * behind it, and every attach from an orchestrator older than the field — the
25363
+ * runner then names no source on the phase event.
25364
+ */
25365
+ sessionTrigger: SessionTriggerSchema.optional(),
25366
+ /**
25344
25367
  * WHICH root detector runs for this camera. The detection counterpart of
25345
25368
  * {@link motionSources}, same shape and same discipline: a per-camera list
25346
25369
  * of sources the system understands, vendor-agnostic, owned here.
@@ -32737,7 +32760,7 @@ var LocalInterfaceSchema = object({
32737
32760
  name: string(),
32738
32761
  family: _enum(["IPv4", "IPv6"]),
32739
32762
  address: string(),
32740
- /** CIDR shorthand (e.g. `192.168.x.x/24`). Empty when OS doesn't expose. */
32763
+ /** CIDR shorthand (e.g. `192.168.10.10/24`). Empty when OS doesn't expose. */
32741
32764
  cidr: string(),
32742
32765
  /** OS netmask. Stable across calls so the SDK can hash on it. */
32743
32766
  netmask: string(),
@@ -32791,7 +32814,8 @@ var ConnectionEndpointSchema = object({
32791
32814
  "lan-ipv4",
32792
32815
  "lan-ipv6",
32793
32816
  "public",
32794
- "loopback"
32817
+ "loopback",
32818
+ "app-link"
32795
32819
  ]),
32796
32820
  /**
32797
32821
  * Originating-interface kind — `lan`/`wifi`/`docker`/`vpn`/`other`/
@@ -32860,15 +32884,27 @@ var GetConnectionEndpointsResultSchema = object({
32860
32884
  localPort: AdvertisedLocalPortSchema
32861
32885
  });
32862
32886
  /**
32863
- * The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
32864
- * AUTO (resolved from the candidate ranking at send time); `resolved` reports
32865
- * what AUTO currently picks, so the UI can show the effective value either way.
32887
+ * The address flagged for notification links. `baseUrl: null` = AUTO, which
32888
+ * since D709 is the CamStack app link; `resolved` reports the effective value,
32889
+ * so the UI can show it either way.
32866
32890
  */
32867
32891
  var NotificationEndpointSchema = object({
32868
32892
  /** The operator's explicit choice, or null for AUTO. */
32869
32893
  baseUrl: string().nullable(),
32870
- /** What the ranking currently resolves to (null when nothing is reachable). */
32871
- resolved: string().nullable()
32894
+ /**
32895
+ * The effective flagged address: the explicit choice, else (AUTO) the
32896
+ * CamStack app link `https://camstack.zentik.app` (D709). A pre-D709 hub
32897
+ * answered the public tunnel / mesh here, or null.
32898
+ */
32899
+ resolved: string().nullable(),
32900
+ /**
32901
+ * The hub origin an app link carries as `hub=` (D709): the hub's best
32902
+ * public HTTPS address — the tunnel, then the mesh (Tailscale MagicDNS) —
32903
+ * picked from this cap's own palette by `pickAppLinkHub`. `null` when the
32904
+ * hub advertises neither; the app link is then minted without `hub=`.
32905
+ * Absent on a pre-D709 hub.
32906
+ */
32907
+ appLinkHub: string().nullable()
32872
32908
  });
32873
32909
  /**
32874
32910
  * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
@@ -32922,7 +32958,11 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
32922
32958
  * Pass `'https'` when the caller is itself loaded over HTTPS
32923
32959
  * to avoid mixed-content blocks in the browser. The public
32924
32960
  * tunnel always emits `https://` regardless. */
32925
- scheme: _enum(["http", "https"]).optional()
32961
+ scheme: _enum(["http", "https"]).optional(),
32962
+ /** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
32963
+ * an address notification links can be flagged with, not a hub
32964
+ * route. Default `false`: racers and rankers never see it. */
32965
+ includeAppLink: boolean().optional()
32926
32966
  }), 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, {
32927
32967
  kind: "mutation",
32928
32968
  auth: "admin"
@@ -33251,7 +33291,7 @@ var MeshPeerSchema = object({
33251
33291
  tags: array(string()).readonly(),
33252
33292
  /** True when the peer advertises itself as an exit-node candidate. */
33253
33293
  exitNodeOption: boolean(),
33254
- /** Subnet routes the peer advertises (e.g. `["192.168.x.x/24"]`). */
33294
+ /** Subnet routes the peer advertises (e.g. `["192.168.10.0/24"]`). */
33255
33295
  advertisedRoutes: array(string()).readonly(),
33256
33296
  /** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
33257
33297
  userLogin: string().nullable(),
@@ -34579,7 +34619,13 @@ var OsdStatusSchema = object({ overlays: array(object({
34579
34619
  */
34580
34620
  availablePositions: array(OsdPositionEnum).readonly(),
34581
34621
  /** Firmware does not allow editing the `text` field (e.g. timestamp). */
34582
- readOnly: boolean().optional()
34622
+ readOnly: boolean().optional(),
34623
+ /**
34624
+ * Firmware text ceiling for this overlay. Absent = no known limit.
34625
+ * The OSD manager truncates here on every write — never stores its own
34626
+ * copy on the binding.
34627
+ */
34628
+ maxCharacters: number().int().positive().optional()
34583
34629
  })).readonly() });
34584
34630
  var OsdOverlayPatchSchema = object({
34585
34631
  enabled: boolean().optional(),
@@ -34630,7 +34676,9 @@ var OsdTemplateBindingSchema = object({
34630
34676
  valuePath: string().min(1).max(64),
34631
34677
  /** Convert TO this unit at render (`tryConvertUnit`). Absent = source unit. */
34632
34678
  displayUnit: string().max(16).optional(),
34633
- maxDecimals: number().int().min(0).max(4).default(1)
34679
+ maxDecimals: number().int().min(0).max(4).default(1),
34680
+ /** Raw value → display text (same shape as slot binding). Empty string hides. */
34681
+ valueMap: record(string(), string()).optional()
34634
34682
  });
34635
34683
  /**
34636
34684
  * A named template: bindings (alias → leaf field) + a parser that
@@ -34680,18 +34728,11 @@ var OsdSlotBindingSchema = object({
34680
34728
  source: OsdSourceSchema,
34681
34729
  /** `${value}` and `${unit}` are substituted; every occurrence. */
34682
34730
  template: string().max(96).default("${value}"),
34683
- /** Truncate with an ellipsis past this length. Absent = no limit. */
34684
- maxCharacters: number().int().min(4).max(64).optional(),
34685
34731
  /**
34686
34732
  * Decimal places for a numeric value. `0` yields an integer — the
34687
34733
  * documented workaround for firmwares that reject `.` in overlay text.
34688
34734
  */
34689
34735
  maxDecimals: number().int().min(0).max(4).default(1),
34690
- /**
34691
- * Appended via `${unit}` when no unit conversion produces a label.
34692
- * Prefer `source.displayUnit` for converted device-state values.
34693
- */
34694
- unitLabel: string().max(8).optional(),
34695
34736
  /** Raw value → display text, e.g. `{"true":"MOTION","false":""}`. */
34696
34737
  valueMap: record(string(), string()).optional(),
34697
34738
  /** Time windows in which the slot is shown. Absent = always. */
@@ -34700,9 +34741,7 @@ var OsdSlotBindingSchema = object({
34700
34741
  * Display gate, in the notification centre's condition vocabulary.
34701
34742
  * Only the keys reported by `getConditionSupport` are accepted.
34702
34743
  */
34703
- conditions: NcConditionsSchema.optional(),
34704
- /** Rendered when the gate is closed or the value unreadable. Empty = hide. */
34705
- fallbackText: string().max(64).default("")
34744
+ conditions: NcConditionsSchema.optional()
34706
34745
  });
34707
34746
  /** One camera slot, as the operator sees it: firmware truth + our binding. */
34708
34747
  var OsdSlotViewSchema = object({
@@ -52935,12 +52974,14 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
52935
52974
  {
52936
52975
  id: "addons",
52937
52976
  family: "system",
52938
- label: "Addons",
52939
- kinds: [
52940
- "addon-crash-loop",
52941
- "addon-update-available",
52942
- "addon-updated"
52943
- ]
52977
+ label: "Addons stopped",
52978
+ kinds: ["addon-crash-loop"]
52979
+ },
52980
+ {
52981
+ id: "addon-updates",
52982
+ family: "system",
52983
+ label: "Addon updates",
52984
+ kinds: ["addon-update-available", "addon-updated"]
52944
52985
  },
52945
52986
  {
52946
52987
  id: "updates",
@@ -53100,13 +53141,15 @@ var STATE_SUMMARY_SECTION_VARS = [
53100
53141
  },
53101
53142
  {
53102
53143
  name: "summaryAddons",
53103
- label: "Summary: addons",
53104
- example: "@camstack/addon-recorder 1.2.3 → 1.2.4",
53105
- kinds: [
53106
- "addon-crash-loop",
53107
- "addon-update-available",
53108
- "addon-updated"
53109
- ]
53144
+ label: "Summary: addons stopped",
53145
+ example: "hub — recorder stopped after repeated crashes",
53146
+ kinds: ["addon-crash-loop"]
53147
+ },
53148
+ {
53149
+ name: "summaryAddonUpdates",
53150
+ label: "Summary: addon updates",
53151
+ example: "hub:\n• @camstack/addon-recorder 1.2.3 → 1.2.4",
53152
+ kinds: ["addon-update-available", "addon-updated"]
53110
53153
  },
53111
53154
  {
53112
53155
  name: "summaryUpdates",
@@ -53190,6 +53233,7 @@ var STATE_SUMMARY_VARS = [
53190
53233
  [...RULE_BODY_ONLY],
53191
53234
  [...RULE_TEXT],
53192
53235
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
53236
+ ([...RULE_TEXT], [...COMBINED_ALARM]),
53193
53237
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
53194
53238
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
53195
53239
  ([...RULE_TEXT], [...CONSUMABLE]),
@@ -53230,6 +53274,8 @@ var STATE_SUMMARY_VARS = [
53230
53274
  [...RULE_TEXT],
53231
53275
  [...RULE_TEXT],
53232
53276
  [...RULE_TEXT],
53277
+ [...RULE_TEXT],
53278
+ [...RULE_TEXT],
53233
53279
  ...STATE_SUMMARY_VARS
53234
53280
  ];
53235
53281
  new Set([
package/dist/addon.mjs CHANGED
@@ -11353,11 +11353,11 @@ var ModelVariantGroupSchema = object({
11353
11353
  /** Quantization axis. Omit ⇒ the fp32 base build. */
11354
11354
  precision: _enum(["fp32", "int8"]).optional(),
11355
11355
  /**
11356
- * Speed-optimization axis. Omit ⇒ the standard build. `fast` marks a
11357
- * latency-optimized export (e.g. ReLU-activation variant) — the slot the
11358
- * future performance variants plug into.
11356
+ * Training / latency-variant axis. Omit ⇒ the standard build. `test` marks
11357
+ * an alternate training of the same family (Scrypted `relu_test`); chip
11358
+ * label is "Test".
11359
11359
  */
11360
- optimization: _enum(["standard", "fast"]).optional(),
11360
+ optimization: _enum(["standard", "test"]).optional(),
11361
11361
  /**
11362
11362
  * Input-resolution axis (square input side, px). Omit ⇒ the family's native
11363
11363
  * resolution (640 for yolo26). Reduced-input builds (320 / 256) are a big,
@@ -11380,9 +11380,10 @@ var ModelProviderIdSchema = _enum([
11380
11380
  * are per upstream. A persisted custom-model row written when this field was a
11381
11381
  * string still parses — the string is lifted into `{ weights }`.
11382
11382
  *
11383
- * Every licence surface (the admin "Models and licenses" page,
11384
- * `THIRD_PARTY_MODELS.md`, the Hugging Face model table) is GENERATED from
11385
- * these records by `scripts/gen-model-licenses.ts` (D661).
11383
+ * Every machine licence surface (`THIRD_PARTY_MODELS.md`, the Hugging Face
11384
+ * model table) is GENERATED from these records by
11385
+ * `scripts/gen-model-licenses.ts` (D661). Operator-facing docs live in
11386
+ * `camstack/docs` → `/docs/detection/models`.
11386
11387
  */
11387
11388
  var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { weights: value } : value, object({
11388
11389
  /** SPDX id of the WEIGHTS' terms, a `LicenseRef-*` for non-SPDX terms, or `UNKNOWN`. */
@@ -15013,7 +15014,7 @@ DeviceType.Camera;
15013
15014
  * This matters here more than anywhere else in the repo, because every provider
15014
15015
  * that knows a device's host knows its PASSWORD too: `{ host, port, username,
15015
15016
  * password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
15016
- * and `http://admin:hunter2@192.168.x.x/` is a URL a browser accepts. The
15017
+ * and `http://admin:hunter2@192.168.60.139/` is a URL a browser accepts. The
15017
15018
  * camera's own page will ask for its own login. That is correct, and pre-
15018
15019
  * filling it is the operator's business, not ours.
15019
15020
  *
@@ -18202,7 +18203,7 @@ method(object({
18202
18203
  timeoutMs: 6e5
18203
18204
  });
18204
18205
  method(object({
18205
- nodeId: string(),
18206
+ targetNodeId: string(),
18206
18207
  modelId: string(),
18207
18208
  format: _enum(MODEL_FORMATS),
18208
18209
  entry: ModelCatalogEntrySchema
@@ -20706,8 +20707,9 @@ var NcRuleSchema = NcRuleInputSchema.extend({
20706
20707
  disabledTargetIds: array(string()).default([])
20707
20708
  });
20708
20709
  /**
20709
- * The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
20710
- * still-true state. `backups-exports` and `alarm` are not sections — a completed
20710
+ * The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
20711
+ * report a still-true state. `addons` is the crash-looped addons only and
20712
+ * `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
20711
20713
  * job is not an open state, and the alarm stays instant.
20712
20714
  */
20713
20715
  var NcStateSummarySectionIdSchema = _enum([
@@ -20719,6 +20721,7 @@ var NcStateSummarySectionIdSchema = _enum([
20719
20721
  "detection-blind",
20720
20722
  "nodes",
20721
20723
  "addons",
20724
+ "addon-updates",
20722
20725
  "updates"
20723
20726
  ]);
20724
20727
  /** One section of a previewed state summary. `unavailable` = its state could not be read. */
@@ -21199,7 +21202,19 @@ var NcAlarmModeDelaysListSchema = array(object({
21199
21202
  * When this mode may be armed. Absent / null = always allowed (same as a
21200
21203
  * rule with no `schedule`). Evaluated with {@link isScheduleActive}.
21201
21204
  */
21202
- schedule: NcScheduleSchema.optional()
21205
+ schedule: NcScheduleSchema.optional(),
21206
+ /**
21207
+ * D706: while this mode's ENTRY DELAY runs, do the alarm rules' own pushes go out (as an
21208
+ * intrusion naming the locations)? Absent = false — the entry-delay notification is the
21209
+ * only one, and the matches ride the triggered notification's mosaic (D705).
21210
+ */
21211
+ notifyDuringEntryDelay: boolean().optional(),
21212
+ /**
21213
+ * D706: notify "watched again" when a sensor this arm bypassed closes and opens again.
21214
+ * Absent = false (logged, not sent). Even when true it is not sent when that same sensor
21215
+ * is the one that starts the entry delay — the entry-delay notification already names it.
21216
+ */
21217
+ notifySensorRewatched: boolean().optional()
21203
21218
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
21204
21219
  var NcAlarmModeDelaysEditListSchema = array(object({
21205
21220
  mode: AlarmArmModeSchema,
@@ -21208,7 +21223,11 @@ var NcAlarmModeDelaysEditListSchema = array(object({
21208
21223
  triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
21209
21224
  postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
21210
21225
  /** Set a schedule, or `null` to clear (mode always allowed again). */
21211
- schedule: NcScheduleSchema.nullable().optional()
21226
+ schedule: NcScheduleSchema.nullable().optional(),
21227
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
21228
+ notifyDuringEntryDelay: boolean().nullable().optional(),
21229
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
21230
+ notifySensorRewatched: boolean().nullable().optional()
21212
21231
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
21213
21232
  /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
21214
21233
  var NcAlarmNonBlockingEditSchema = object({
@@ -22169,39 +22188,19 @@ Object.freeze(Object.fromEntries([{
22169
22188
  label: "Face recognition model",
22170
22189
  defaultModelId: "auraface-r100",
22171
22190
  indexName: "the enrolled face gallery",
22172
- options: [
22173
- {
22174
- id: "auraface-r100",
22175
- label: "AuraFace R100"
22176
- },
22177
- {
22178
- id: "arcface-r100",
22179
- label: "ArcFace (ResNet34)"
22180
- },
22181
- {
22182
- id: "inception-resnet-v1",
22183
- label: "Inception ResNet V1"
22184
- }
22185
- ]
22191
+ options: [{
22192
+ id: "auraface-r100",
22193
+ label: "AuraFace R100"
22194
+ }]
22186
22195
  }, {
22187
22196
  stepId: "clip-embedding",
22188
22197
  label: "Semantic search model",
22189
- defaultModelId: "mobileclip-s1",
22198
+ defaultModelId: "siglip2-b16-224",
22190
22199
  indexName: "the object semantic-search index",
22191
- options: [
22192
- {
22193
- id: "mobileclip-s1",
22194
- label: "MobileCLIP S1"
22195
- },
22196
- {
22197
- id: "mobileclip-s2",
22198
- label: "MobileCLIP S2"
22199
- },
22200
- {
22201
- id: "siglip2-b16-224",
22202
- label: "SigLIP2 B/16 (Apache-2.0)"
22203
- }
22204
- ]
22200
+ options: [{
22201
+ id: "siglip2-b16-224",
22202
+ label: "SigLIP2 B/16 (Apache-2.0)"
22203
+ }]
22205
22204
  }].map((s) => [s.stepId, s.defaultModelId])));
22206
22205
  var CLUSTER_STEP_SETTING_FIELDS = [{
22207
22206
  stepId: "face-embedding",
@@ -25089,6 +25088,22 @@ var MotionSourceEnum = _enum([
25089
25088
  "device-activity"
25090
25089
  ]);
25091
25090
  /**
25091
+ * What opened an on-motion detection SESSION: the motion source that passed the
25092
+ * camera's `motionSources` gate, and what raised it (the camera itself, or a
25093
+ * sensor the operator attached — D672). `sensorName` is the attached sensor's
25094
+ * device name as the orchestrator's camera-sensors resolution last read it;
25095
+ * absent when unknown or when the camera itself triggered.
25096
+ *
25097
+ * Carried on the session attach ONLY so the runner's `DetectionPhaseTransition`
25098
+ * can say what started the session (D672 rule 11, amended 2026-10-06). The
25099
+ * runner never decides anything on it.
25100
+ */
25101
+ var SessionTriggerSchema = object({
25102
+ source: MotionSourceEnum,
25103
+ triggeredBy: MotionTriggeredBySchema,
25104
+ sensorName: string().optional()
25105
+ });
25106
+ /**
25092
25107
  * List of motion sources active on a camera. Empty array is valid:
25093
25108
  * "no source" — happens for battery cams without firmware motion when
25094
25109
  * the operator hasn't opted into the SW analyzer (would hold the
@@ -25340,6 +25355,14 @@ var RunnerCameraConfigSchema = object({
25340
25355
  */
25341
25356
  motionSources: MotionSourcesSchema.default(["analyzer"]),
25342
25357
  /**
25358
+ * What opened this attach, on a SESSION attach only (see
25359
+ * {@link SessionTriggerSchema}). OPTIONAL with no default: absent on a
25360
+ * standing attach, an occupancy burst, a re-dispatch with no motion event
25361
+ * behind it, and every attach from an orchestrator older than the field — the
25362
+ * runner then names no source on the phase event.
25363
+ */
25364
+ sessionTrigger: SessionTriggerSchema.optional(),
25365
+ /**
25343
25366
  * WHICH root detector runs for this camera. The detection counterpart of
25344
25367
  * {@link motionSources}, same shape and same discipline: a per-camera list
25345
25368
  * of sources the system understands, vendor-agnostic, owned here.
@@ -32736,7 +32759,7 @@ var LocalInterfaceSchema = object({
32736
32759
  name: string(),
32737
32760
  family: _enum(["IPv4", "IPv6"]),
32738
32761
  address: string(),
32739
- /** CIDR shorthand (e.g. `192.168.x.x/24`). Empty when OS doesn't expose. */
32762
+ /** CIDR shorthand (e.g. `192.168.10.10/24`). Empty when OS doesn't expose. */
32740
32763
  cidr: string(),
32741
32764
  /** OS netmask. Stable across calls so the SDK can hash on it. */
32742
32765
  netmask: string(),
@@ -32790,7 +32813,8 @@ var ConnectionEndpointSchema = object({
32790
32813
  "lan-ipv4",
32791
32814
  "lan-ipv6",
32792
32815
  "public",
32793
- "loopback"
32816
+ "loopback",
32817
+ "app-link"
32794
32818
  ]),
32795
32819
  /**
32796
32820
  * Originating-interface kind — `lan`/`wifi`/`docker`/`vpn`/`other`/
@@ -32859,15 +32883,27 @@ var GetConnectionEndpointsResultSchema = object({
32859
32883
  localPort: AdvertisedLocalPortSchema
32860
32884
  });
32861
32885
  /**
32862
- * The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
32863
- * AUTO (resolved from the candidate ranking at send time); `resolved` reports
32864
- * what AUTO currently picks, so the UI can show the effective value either way.
32886
+ * The address flagged for notification links. `baseUrl: null` = AUTO, which
32887
+ * since D709 is the CamStack app link; `resolved` reports the effective value,
32888
+ * so the UI can show it either way.
32865
32889
  */
32866
32890
  var NotificationEndpointSchema = object({
32867
32891
  /** The operator's explicit choice, or null for AUTO. */
32868
32892
  baseUrl: string().nullable(),
32869
- /** What the ranking currently resolves to (null when nothing is reachable). */
32870
- resolved: string().nullable()
32893
+ /**
32894
+ * The effective flagged address: the explicit choice, else (AUTO) the
32895
+ * CamStack app link `https://camstack.zentik.app` (D709). A pre-D709 hub
32896
+ * answered the public tunnel / mesh here, or null.
32897
+ */
32898
+ resolved: string().nullable(),
32899
+ /**
32900
+ * The hub origin an app link carries as `hub=` (D709): the hub's best
32901
+ * public HTTPS address — the tunnel, then the mesh (Tailscale MagicDNS) —
32902
+ * picked from this cap's own palette by `pickAppLinkHub`. `null` when the
32903
+ * hub advertises neither; the app link is then minted without `hub=`.
32904
+ * Absent on a pre-D709 hub.
32905
+ */
32906
+ appLinkHub: string().nullable()
32871
32907
  });
32872
32908
  /**
32873
32909
  * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
@@ -32921,7 +32957,11 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
32921
32957
  * Pass `'https'` when the caller is itself loaded over HTTPS
32922
32958
  * to avoid mixed-content blocks in the browser. The public
32923
32959
  * tunnel always emits `https://` regardless. */
32924
- scheme: _enum(["http", "https"]).optional()
32960
+ scheme: _enum(["http", "https"]).optional(),
32961
+ /** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
32962
+ * an address notification links can be flagged with, not a hub
32963
+ * route. Default `false`: racers and rankers never see it. */
32964
+ includeAppLink: boolean().optional()
32925
32965
  }), 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, {
32926
32966
  kind: "mutation",
32927
32967
  auth: "admin"
@@ -33250,7 +33290,7 @@ var MeshPeerSchema = object({
33250
33290
  tags: array(string()).readonly(),
33251
33291
  /** True when the peer advertises itself as an exit-node candidate. */
33252
33292
  exitNodeOption: boolean(),
33253
- /** Subnet routes the peer advertises (e.g. `["192.168.x.x/24"]`). */
33293
+ /** Subnet routes the peer advertises (e.g. `["192.168.10.0/24"]`). */
33254
33294
  advertisedRoutes: array(string()).readonly(),
33255
33295
  /** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
33256
33296
  userLogin: string().nullable(),
@@ -34578,7 +34618,13 @@ var OsdStatusSchema = object({ overlays: array(object({
34578
34618
  */
34579
34619
  availablePositions: array(OsdPositionEnum).readonly(),
34580
34620
  /** Firmware does not allow editing the `text` field (e.g. timestamp). */
34581
- readOnly: boolean().optional()
34621
+ readOnly: boolean().optional(),
34622
+ /**
34623
+ * Firmware text ceiling for this overlay. Absent = no known limit.
34624
+ * The OSD manager truncates here on every write — never stores its own
34625
+ * copy on the binding.
34626
+ */
34627
+ maxCharacters: number().int().positive().optional()
34582
34628
  })).readonly() });
34583
34629
  var OsdOverlayPatchSchema = object({
34584
34630
  enabled: boolean().optional(),
@@ -34629,7 +34675,9 @@ var OsdTemplateBindingSchema = object({
34629
34675
  valuePath: string().min(1).max(64),
34630
34676
  /** Convert TO this unit at render (`tryConvertUnit`). Absent = source unit. */
34631
34677
  displayUnit: string().max(16).optional(),
34632
- maxDecimals: number().int().min(0).max(4).default(1)
34678
+ maxDecimals: number().int().min(0).max(4).default(1),
34679
+ /** Raw value → display text (same shape as slot binding). Empty string hides. */
34680
+ valueMap: record(string(), string()).optional()
34633
34681
  });
34634
34682
  /**
34635
34683
  * A named template: bindings (alias → leaf field) + a parser that
@@ -34679,18 +34727,11 @@ var OsdSlotBindingSchema = object({
34679
34727
  source: OsdSourceSchema,
34680
34728
  /** `${value}` and `${unit}` are substituted; every occurrence. */
34681
34729
  template: string().max(96).default("${value}"),
34682
- /** Truncate with an ellipsis past this length. Absent = no limit. */
34683
- maxCharacters: number().int().min(4).max(64).optional(),
34684
34730
  /**
34685
34731
  * Decimal places for a numeric value. `0` yields an integer — the
34686
34732
  * documented workaround for firmwares that reject `.` in overlay text.
34687
34733
  */
34688
34734
  maxDecimals: number().int().min(0).max(4).default(1),
34689
- /**
34690
- * Appended via `${unit}` when no unit conversion produces a label.
34691
- * Prefer `source.displayUnit` for converted device-state values.
34692
- */
34693
- unitLabel: string().max(8).optional(),
34694
34735
  /** Raw value → display text, e.g. `{"true":"MOTION","false":""}`. */
34695
34736
  valueMap: record(string(), string()).optional(),
34696
34737
  /** Time windows in which the slot is shown. Absent = always. */
@@ -34699,9 +34740,7 @@ var OsdSlotBindingSchema = object({
34699
34740
  * Display gate, in the notification centre's condition vocabulary.
34700
34741
  * Only the keys reported by `getConditionSupport` are accepted.
34701
34742
  */
34702
- conditions: NcConditionsSchema.optional(),
34703
- /** Rendered when the gate is closed or the value unreadable. Empty = hide. */
34704
- fallbackText: string().max(64).default("")
34743
+ conditions: NcConditionsSchema.optional()
34705
34744
  });
34706
34745
  /** One camera slot, as the operator sees it: firmware truth + our binding. */
34707
34746
  var OsdSlotViewSchema = object({
@@ -52934,12 +52973,14 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
52934
52973
  {
52935
52974
  id: "addons",
52936
52975
  family: "system",
52937
- label: "Addons",
52938
- kinds: [
52939
- "addon-crash-loop",
52940
- "addon-update-available",
52941
- "addon-updated"
52942
- ]
52976
+ label: "Addons stopped",
52977
+ kinds: ["addon-crash-loop"]
52978
+ },
52979
+ {
52980
+ id: "addon-updates",
52981
+ family: "system",
52982
+ label: "Addon updates",
52983
+ kinds: ["addon-update-available", "addon-updated"]
52943
52984
  },
52944
52985
  {
52945
52986
  id: "updates",
@@ -53099,13 +53140,15 @@ var STATE_SUMMARY_SECTION_VARS = [
53099
53140
  },
53100
53141
  {
53101
53142
  name: "summaryAddons",
53102
- label: "Summary: addons",
53103
- example: "@camstack/addon-recorder 1.2.3 → 1.2.4",
53104
- kinds: [
53105
- "addon-crash-loop",
53106
- "addon-update-available",
53107
- "addon-updated"
53108
- ]
53143
+ label: "Summary: addons stopped",
53144
+ example: "hub — recorder stopped after repeated crashes",
53145
+ kinds: ["addon-crash-loop"]
53146
+ },
53147
+ {
53148
+ name: "summaryAddonUpdates",
53149
+ label: "Summary: addon updates",
53150
+ example: "hub:\n• @camstack/addon-recorder 1.2.3 → 1.2.4",
53151
+ kinds: ["addon-update-available", "addon-updated"]
53109
53152
  },
53110
53153
  {
53111
53154
  name: "summaryUpdates",
@@ -53189,6 +53232,7 @@ var STATE_SUMMARY_VARS = [
53189
53232
  [...RULE_BODY_ONLY],
53190
53233
  [...RULE_TEXT],
53191
53234
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
53235
+ ([...RULE_TEXT], [...COMBINED_ALARM]),
53192
53236
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
53193
53237
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
53194
53238
  ([...RULE_TEXT], [...CONSUMABLE]),
@@ -53229,6 +53273,8 @@ var STATE_SUMMARY_VARS = [
53229
53273
  [...RULE_TEXT],
53230
53274
  [...RULE_TEXT],
53231
53275
  [...RULE_TEXT],
53276
+ [...RULE_TEXT],
53277
+ [...RULE_TEXT],
53232
53278
  ...STATE_SUMMARY_VARS
53233
53279
  ];
53234
53280
  new Set([
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-tuya",
3
- "version": "0.2.119",
3
+ "version": "0.2.120",
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",