@camstack/addon-provider-reolink 1.2.173 → 1.2.175

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 +128 -81
  2. package/dist/addon.mjs +128 -81
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -11170,11 +11170,11 @@ var ModelVariantGroupSchema = object({
11170
11170
  /** Quantization axis. Omit ⇒ the fp32 base build. */
11171
11171
  precision: _enum(["fp32", "int8"]).optional(),
11172
11172
  /**
11173
- * Speed-optimization axis. Omit ⇒ the standard build. `fast` marks a
11174
- * latency-optimized export (e.g. ReLU-activation variant) — the slot the
11175
- * future performance variants plug into.
11173
+ * Training / latency-variant axis. Omit ⇒ the standard build. `test` marks
11174
+ * an alternate training of the same family (Scrypted `relu_test`); chip
11175
+ * label is "Test".
11176
11176
  */
11177
- optimization: _enum(["standard", "fast"]).optional(),
11177
+ optimization: _enum(["standard", "test"]).optional(),
11178
11178
  /**
11179
11179
  * Input-resolution axis (square input side, px). Omit ⇒ the family's native
11180
11180
  * resolution (640 for yolo26). Reduced-input builds (320 / 256) are a big,
@@ -11197,9 +11197,10 @@ var ModelProviderIdSchema = _enum([
11197
11197
  * are per upstream. A persisted custom-model row written when this field was a
11198
11198
  * string still parses — the string is lifted into `{ weights }`.
11199
11199
  *
11200
- * Every licence surface (the admin "Models and licenses" page,
11201
- * `THIRD_PARTY_MODELS.md`, the Hugging Face model table) is GENERATED from
11202
- * these records by `scripts/gen-model-licenses.ts` (D661).
11200
+ * Every machine licence surface (`THIRD_PARTY_MODELS.md`, the Hugging Face
11201
+ * model table) is GENERATED from these records by
11202
+ * `scripts/gen-model-licenses.ts` (D661). Operator-facing docs live in
11203
+ * `camstack/docs` → `/docs/detection/models`.
11203
11204
  */
11204
11205
  var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { weights: value } : value, object({
11205
11206
  /** SPDX id of the WEIGHTS' terms, a `LicenseRef-*` for non-SPDX terms, or `UNKNOWN`. */
@@ -14830,7 +14831,7 @@ DeviceType.Camera;
14830
14831
  * This matters here more than anywhere else in the repo, because every provider
14831
14832
  * that knows a device's host knows its PASSWORD too: `{ host, port, username,
14832
14833
  * password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
14833
- * and `http://admin:hunter2@192.168.x.x/` is a URL a browser accepts. The
14834
+ * and `http://admin:hunter2@192.168.60.139/` is a URL a browser accepts. The
14834
14835
  * camera's own page will ask for its own login. That is correct, and pre-
14835
14836
  * filling it is the operator's business, not ours.
14836
14837
  *
@@ -18155,7 +18156,7 @@ method(object({
18155
18156
  timeoutMs: 6e5
18156
18157
  });
18157
18158
  method(object({
18158
- nodeId: string(),
18159
+ targetNodeId: string(),
18159
18160
  modelId: string(),
18160
18161
  format: _enum(MODEL_FORMATS),
18161
18162
  entry: ModelCatalogEntrySchema
@@ -20659,8 +20660,9 @@ var NcRuleSchema = NcRuleInputSchema.extend({
20659
20660
  disabledTargetIds: array(string()).default([])
20660
20661
  });
20661
20662
  /**
20662
- * The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
20663
- * still-true state. `backups-exports` and `alarm` are not sections — a completed
20663
+ * The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
20664
+ * report a still-true state. `addons` is the crash-looped addons only and
20665
+ * `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
20664
20666
  * job is not an open state, and the alarm stays instant.
20665
20667
  */
20666
20668
  var NcStateSummarySectionIdSchema = _enum([
@@ -20672,6 +20674,7 @@ var NcStateSummarySectionIdSchema = _enum([
20672
20674
  "detection-blind",
20673
20675
  "nodes",
20674
20676
  "addons",
20677
+ "addon-updates",
20675
20678
  "updates"
20676
20679
  ]);
20677
20680
  /** One section of a previewed state summary. `unavailable` = its state could not be read. */
@@ -21152,7 +21155,19 @@ var NcAlarmModeDelaysListSchema = array(object({
21152
21155
  * When this mode may be armed. Absent / null = always allowed (same as a
21153
21156
  * rule with no `schedule`). Evaluated with {@link isScheduleActive}.
21154
21157
  */
21155
- schedule: NcScheduleSchema.optional()
21158
+ schedule: NcScheduleSchema.optional(),
21159
+ /**
21160
+ * D706: while this mode's ENTRY DELAY runs, do the alarm rules' own pushes go out (as an
21161
+ * intrusion naming the locations)? Absent = false — the entry-delay notification is the
21162
+ * only one, and the matches ride the triggered notification's mosaic (D705).
21163
+ */
21164
+ notifyDuringEntryDelay: boolean().optional(),
21165
+ /**
21166
+ * D706: notify "watched again" when a sensor this arm bypassed closes and opens again.
21167
+ * Absent = false (logged, not sent). Even when true it is not sent when that same sensor
21168
+ * is the one that starts the entry delay — the entry-delay notification already names it.
21169
+ */
21170
+ notifySensorRewatched: boolean().optional()
21156
21171
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
21157
21172
  var NcAlarmModeDelaysEditListSchema = array(object({
21158
21173
  mode: AlarmArmModeSchema,
@@ -21161,7 +21176,11 @@ var NcAlarmModeDelaysEditListSchema = array(object({
21161
21176
  triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
21162
21177
  postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
21163
21178
  /** Set a schedule, or `null` to clear (mode always allowed again). */
21164
- schedule: NcScheduleSchema.nullable().optional()
21179
+ schedule: NcScheduleSchema.nullable().optional(),
21180
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
21181
+ notifyDuringEntryDelay: boolean().nullable().optional(),
21182
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
21183
+ notifySensorRewatched: boolean().nullable().optional()
21165
21184
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
21166
21185
  /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
21167
21186
  var NcAlarmNonBlockingEditSchema = object({
@@ -22122,39 +22141,19 @@ Object.freeze(Object.fromEntries([{
22122
22141
  label: "Face recognition model",
22123
22142
  defaultModelId: "auraface-r100",
22124
22143
  indexName: "the enrolled face gallery",
22125
- options: [
22126
- {
22127
- id: "auraface-r100",
22128
- label: "AuraFace R100"
22129
- },
22130
- {
22131
- id: "arcface-r100",
22132
- label: "ArcFace (ResNet34)"
22133
- },
22134
- {
22135
- id: "inception-resnet-v1",
22136
- label: "Inception ResNet V1"
22137
- }
22138
- ]
22144
+ options: [{
22145
+ id: "auraface-r100",
22146
+ label: "AuraFace R100"
22147
+ }]
22139
22148
  }, {
22140
22149
  stepId: "clip-embedding",
22141
22150
  label: "Semantic search model",
22142
- defaultModelId: "mobileclip-s1",
22151
+ defaultModelId: "siglip2-b16-224",
22143
22152
  indexName: "the object semantic-search index",
22144
- options: [
22145
- {
22146
- id: "mobileclip-s1",
22147
- label: "MobileCLIP S1"
22148
- },
22149
- {
22150
- id: "mobileclip-s2",
22151
- label: "MobileCLIP S2"
22152
- },
22153
- {
22154
- id: "siglip2-b16-224",
22155
- label: "SigLIP2 B/16 (Apache-2.0)"
22156
- }
22157
- ]
22153
+ options: [{
22154
+ id: "siglip2-b16-224",
22155
+ label: "SigLIP2 B/16 (Apache-2.0)"
22156
+ }]
22158
22157
  }].map((s) => [s.stepId, s.defaultModelId])));
22159
22158
  var CLUSTER_STEP_SETTING_FIELDS = [{
22160
22159
  stepId: "face-embedding",
@@ -25042,6 +25041,22 @@ var MotionSourceEnum = _enum([
25042
25041
  "device-activity"
25043
25042
  ]);
25044
25043
  /**
25044
+ * What opened an on-motion detection SESSION: the motion source that passed the
25045
+ * camera's `motionSources` gate, and what raised it (the camera itself, or a
25046
+ * sensor the operator attached — D672). `sensorName` is the attached sensor's
25047
+ * device name as the orchestrator's camera-sensors resolution last read it;
25048
+ * absent when unknown or when the camera itself triggered.
25049
+ *
25050
+ * Carried on the session attach ONLY so the runner's `DetectionPhaseTransition`
25051
+ * can say what started the session (D672 rule 11, amended 2026-10-06). The
25052
+ * runner never decides anything on it.
25053
+ */
25054
+ var SessionTriggerSchema = object({
25055
+ source: MotionSourceEnum,
25056
+ triggeredBy: MotionTriggeredBySchema,
25057
+ sensorName: string().optional()
25058
+ });
25059
+ /**
25045
25060
  * List of motion sources active on a camera. Empty array is valid:
25046
25061
  * "no source" — happens for battery cams without firmware motion when
25047
25062
  * the operator hasn't opted into the SW analyzer (would hold the
@@ -25293,6 +25308,14 @@ var RunnerCameraConfigSchema = object({
25293
25308
  */
25294
25309
  motionSources: MotionSourcesSchema.default(["analyzer"]),
25295
25310
  /**
25311
+ * What opened this attach, on a SESSION attach only (see
25312
+ * {@link SessionTriggerSchema}). OPTIONAL with no default: absent on a
25313
+ * standing attach, an occupancy burst, a re-dispatch with no motion event
25314
+ * behind it, and every attach from an orchestrator older than the field — the
25315
+ * runner then names no source on the phase event.
25316
+ */
25317
+ sessionTrigger: SessionTriggerSchema.optional(),
25318
+ /**
25296
25319
  * WHICH root detector runs for this camera. The detection counterpart of
25297
25320
  * {@link motionSources}, same shape and same discipline: a per-camera list
25298
25321
  * of sources the system understands, vendor-agnostic, owned here.
@@ -33203,7 +33226,7 @@ var LocalInterfaceSchema = object({
33203
33226
  name: string(),
33204
33227
  family: _enum(["IPv4", "IPv6"]),
33205
33228
  address: string(),
33206
- /** CIDR shorthand (e.g. `192.168.x.x/24`). Empty when OS doesn't expose. */
33229
+ /** CIDR shorthand (e.g. `192.168.10.10/24`). Empty when OS doesn't expose. */
33207
33230
  cidr: string(),
33208
33231
  /** OS netmask. Stable across calls so the SDK can hash on it. */
33209
33232
  netmask: string(),
@@ -33257,7 +33280,8 @@ var ConnectionEndpointSchema = object({
33257
33280
  "lan-ipv4",
33258
33281
  "lan-ipv6",
33259
33282
  "public",
33260
- "loopback"
33283
+ "loopback",
33284
+ "app-link"
33261
33285
  ]),
33262
33286
  /**
33263
33287
  * Originating-interface kind — `lan`/`wifi`/`docker`/`vpn`/`other`/
@@ -33326,15 +33350,27 @@ var GetConnectionEndpointsResultSchema = object({
33326
33350
  localPort: AdvertisedLocalPortSchema
33327
33351
  });
33328
33352
  /**
33329
- * The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
33330
- * AUTO (resolved from the candidate ranking at send time); `resolved` reports
33331
- * what AUTO currently picks, so the UI can show the effective value either way.
33353
+ * The address flagged for notification links. `baseUrl: null` = AUTO, which
33354
+ * since D709 is the CamStack app link; `resolved` reports the effective value,
33355
+ * so the UI can show it either way.
33332
33356
  */
33333
33357
  var NotificationEndpointSchema = object({
33334
33358
  /** The operator's explicit choice, or null for AUTO. */
33335
33359
  baseUrl: string().nullable(),
33336
- /** What the ranking currently resolves to (null when nothing is reachable). */
33337
- resolved: string().nullable()
33360
+ /**
33361
+ * The effective flagged address: the explicit choice, else (AUTO) the
33362
+ * CamStack app link `https://camstack.zentik.app` (D709). A pre-D709 hub
33363
+ * answered the public tunnel / mesh here, or null.
33364
+ */
33365
+ resolved: string().nullable(),
33366
+ /**
33367
+ * The hub origin an app link carries as `hub=` (D709): the hub's best
33368
+ * public HTTPS address — the tunnel, then the mesh (Tailscale MagicDNS) —
33369
+ * picked from this cap's own palette by `pickAppLinkHub`. `null` when the
33370
+ * hub advertises neither; the app link is then minted without `hub=`.
33371
+ * Absent on a pre-D709 hub.
33372
+ */
33373
+ appLinkHub: string().nullable()
33338
33374
  });
33339
33375
  /**
33340
33376
  * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
@@ -33388,7 +33424,11 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
33388
33424
  * Pass `'https'` when the caller is itself loaded over HTTPS
33389
33425
  * to avoid mixed-content blocks in the browser. The public
33390
33426
  * tunnel always emits `https://` regardless. */
33391
- scheme: _enum(["http", "https"]).optional()
33427
+ scheme: _enum(["http", "https"]).optional(),
33428
+ /** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
33429
+ * an address notification links can be flagged with, not a hub
33430
+ * route. Default `false`: racers and rankers never see it. */
33431
+ includeAppLink: boolean().optional()
33392
33432
  }), 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, {
33393
33433
  kind: "mutation",
33394
33434
  auth: "admin"
@@ -33717,7 +33757,7 @@ var MeshPeerSchema = object({
33717
33757
  tags: array(string()).readonly(),
33718
33758
  /** True when the peer advertises itself as an exit-node candidate. */
33719
33759
  exitNodeOption: boolean(),
33720
- /** Subnet routes the peer advertises (e.g. `["192.168.x.x/24"]`). */
33760
+ /** Subnet routes the peer advertises (e.g. `["192.168.10.0/24"]`). */
33721
33761
  advertisedRoutes: array(string()).readonly(),
33722
33762
  /** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
33723
33763
  userLogin: string().nullable(),
@@ -35065,7 +35105,13 @@ var OsdStatusSchema = object({ overlays: array(object({
35065
35105
  */
35066
35106
  availablePositions: array(OsdPositionEnum).readonly(),
35067
35107
  /** Firmware does not allow editing the `text` field (e.g. timestamp). */
35068
- readOnly: boolean().optional()
35108
+ readOnly: boolean().optional(),
35109
+ /**
35110
+ * Firmware text ceiling for this overlay. Absent = no known limit.
35111
+ * The OSD manager truncates here on every write — never stores its own
35112
+ * copy on the binding.
35113
+ */
35114
+ maxCharacters: number().int().positive().optional()
35069
35115
  })).readonly() });
35070
35116
  var OsdOverlayPatchSchema = object({
35071
35117
  enabled: boolean().optional(),
@@ -35162,7 +35208,9 @@ var OsdTemplateBindingSchema = object({
35162
35208
  valuePath: string().min(1).max(64),
35163
35209
  /** Convert TO this unit at render (`tryConvertUnit`). Absent = source unit. */
35164
35210
  displayUnit: string().max(16).optional(),
35165
- maxDecimals: number().int().min(0).max(4).default(1)
35211
+ maxDecimals: number().int().min(0).max(4).default(1),
35212
+ /** Raw value → display text (same shape as slot binding). Empty string hides. */
35213
+ valueMap: record(string(), string()).optional()
35166
35214
  });
35167
35215
  /**
35168
35216
  * A named template: bindings (alias → leaf field) + a parser that
@@ -35212,18 +35260,11 @@ var OsdSlotBindingSchema = object({
35212
35260
  source: OsdSourceSchema,
35213
35261
  /** `${value}` and `${unit}` are substituted; every occurrence. */
35214
35262
  template: string().max(96).default("${value}"),
35215
- /** Truncate with an ellipsis past this length. Absent = no limit. */
35216
- maxCharacters: number().int().min(4).max(64).optional(),
35217
35263
  /**
35218
35264
  * Decimal places for a numeric value. `0` yields an integer — the
35219
35265
  * documented workaround for firmwares that reject `.` in overlay text.
35220
35266
  */
35221
35267
  maxDecimals: number().int().min(0).max(4).default(1),
35222
- /**
35223
- * Appended via `${unit}` when no unit conversion produces a label.
35224
- * Prefer `source.displayUnit` for converted device-state values.
35225
- */
35226
- unitLabel: string().max(8).optional(),
35227
35268
  /** Raw value → display text, e.g. `{"true":"MOTION","false":""}`. */
35228
35269
  valueMap: record(string(), string()).optional(),
35229
35270
  /** Time windows in which the slot is shown. Absent = always. */
@@ -35232,9 +35273,7 @@ var OsdSlotBindingSchema = object({
35232
35273
  * Display gate, in the notification centre's condition vocabulary.
35233
35274
  * Only the keys reported by `getConditionSupport` are accepted.
35234
35275
  */
35235
- conditions: NcConditionsSchema.optional(),
35236
- /** Rendered when the gate is closed or the value unreadable. Empty = hide. */
35237
- fallbackText: string().max(64).default("")
35276
+ conditions: NcConditionsSchema.optional()
35238
35277
  });
35239
35278
  /** One camera slot, as the operator sees it: firmware truth + our binding. */
35240
35279
  var OsdSlotViewSchema = object({
@@ -54149,12 +54188,14 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
54149
54188
  {
54150
54189
  id: "addons",
54151
54190
  family: "system",
54152
- label: "Addons",
54153
- kinds: [
54154
- "addon-crash-loop",
54155
- "addon-update-available",
54156
- "addon-updated"
54157
- ]
54191
+ label: "Addons stopped",
54192
+ kinds: ["addon-crash-loop"]
54193
+ },
54194
+ {
54195
+ id: "addon-updates",
54196
+ family: "system",
54197
+ label: "Addon updates",
54198
+ kinds: ["addon-update-available", "addon-updated"]
54158
54199
  },
54159
54200
  {
54160
54201
  id: "updates",
@@ -54314,13 +54355,15 @@ var STATE_SUMMARY_SECTION_VARS = [
54314
54355
  },
54315
54356
  {
54316
54357
  name: "summaryAddons",
54317
- label: "Summary: addons",
54318
- example: "@camstack/addon-recorder 1.2.3 → 1.2.4",
54319
- kinds: [
54320
- "addon-crash-loop",
54321
- "addon-update-available",
54322
- "addon-updated"
54323
- ]
54358
+ label: "Summary: addons stopped",
54359
+ example: "hub — recorder stopped after repeated crashes",
54360
+ kinds: ["addon-crash-loop"]
54361
+ },
54362
+ {
54363
+ name: "summaryAddonUpdates",
54364
+ label: "Summary: addon updates",
54365
+ example: "hub:\n• @camstack/addon-recorder 1.2.3 → 1.2.4",
54366
+ kinds: ["addon-update-available", "addon-updated"]
54324
54367
  },
54325
54368
  {
54326
54369
  name: "summaryUpdates",
@@ -54404,6 +54447,7 @@ var STATE_SUMMARY_VARS = [
54404
54447
  [...RULE_BODY_ONLY],
54405
54448
  [...RULE_TEXT],
54406
54449
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
54450
+ ([...RULE_TEXT], [...COMBINED_ALARM]),
54407
54451
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
54408
54452
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
54409
54453
  ([...RULE_TEXT], [...CONSUMABLE]),
@@ -54444,6 +54488,8 @@ var STATE_SUMMARY_VARS = [
54444
54488
  [...RULE_TEXT],
54445
54489
  [...RULE_TEXT],
54446
54490
  [...RULE_TEXT],
54491
+ [...RULE_TEXT],
54492
+ [...RULE_TEXT],
54447
54493
  ...STATE_SUMMARY_VARS
54448
54494
  ];
54449
54495
  new Set([
@@ -163099,6 +163145,7 @@ function overlaysFromOsdSnapshot(snapshot) {
163099
163145
  enabled: snapshot.channelEnabled === true,
163100
163146
  text: snapshot.channelName ?? "",
163101
163147
  availablePositions: CORNER_POSITIONS,
163148
+ maxCharacters: 31,
163102
163149
  ...channelPosition !== void 0 ? { position: channelPosition } : {}
163103
163150
  },
163104
163151
  {
@@ -172305,7 +172352,7 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
172305
172352
  key: "host",
172306
172353
  label: "Camera IP",
172307
172354
  required: true,
172308
- placeholder: "192.168.x.x"
172355
+ placeholder: "192.168.10.100"
172309
172356
  },
172310
172357
  {
172311
172358
  type: "number",
@@ -174511,7 +174558,7 @@ var ReolinkHub = class ReolinkHub extends BaseDevice {
174511
174558
  key: "host",
174512
174559
  label: "Hub IP",
174513
174560
  required: true,
174514
- placeholder: "192.168.x.x"
174561
+ placeholder: "192.168.10.100"
174515
174562
  },
174516
174563
  {
174517
174564
  type: "number",
@@ -175345,7 +175392,7 @@ function buildDiscoveryParamsFormSchema() {
175345
175392
  }, {
175346
175393
  id: "scan",
175347
175394
  title: "Scan options",
175348
- description: "Leave the network blank to scan the local subnet. To find cameras on a different subnet, enter its CIDR (e.g. 192.168.x.x/24).",
175395
+ description: "Leave the network blank to scan the local subnet. To find cameras on a different subnet, enter its CIDR (e.g. 192.168.20.0/24).",
175349
175396
  columns: 1,
175350
175397
  fields: [
175351
175398
  {
@@ -175353,7 +175400,7 @@ function buildDiscoveryParamsFormSchema() {
175353
175400
  key: "networkCidr",
175354
175401
  label: "Network (CIDR)",
175355
175402
  required: false,
175356
- placeholder: "192.168.x.x/24"
175403
+ placeholder: "192.168.20.0/24"
175357
175404
  },
175358
175405
  {
175359
175406
  type: "boolean",
@@ -175437,7 +175484,7 @@ function buildCreationFormSchema() {
175437
175484
  key: "host",
175438
175485
  label: "Host (IP / hostname / UID)",
175439
175486
  required: true,
175440
- placeholder: "192.168.x.x",
175487
+ placeholder: "192.168.10.100",
175441
175488
  description: "For UDP-only mode you can leave the host blank and supply the camera UID below — the library will discover it on the network.",
175442
175489
  inputType: "text"
175443
175490
  },
package/dist/addon.mjs CHANGED
@@ -11162,11 +11162,11 @@ var ModelVariantGroupSchema = object({
11162
11162
  /** Quantization axis. Omit ⇒ the fp32 base build. */
11163
11163
  precision: _enum(["fp32", "int8"]).optional(),
11164
11164
  /**
11165
- * Speed-optimization axis. Omit ⇒ the standard build. `fast` marks a
11166
- * latency-optimized export (e.g. ReLU-activation variant) — the slot the
11167
- * future performance variants plug into.
11165
+ * Training / latency-variant axis. Omit ⇒ the standard build. `test` marks
11166
+ * an alternate training of the same family (Scrypted `relu_test`); chip
11167
+ * label is "Test".
11168
11168
  */
11169
- optimization: _enum(["standard", "fast"]).optional(),
11169
+ optimization: _enum(["standard", "test"]).optional(),
11170
11170
  /**
11171
11171
  * Input-resolution axis (square input side, px). Omit ⇒ the family's native
11172
11172
  * resolution (640 for yolo26). Reduced-input builds (320 / 256) are a big,
@@ -11189,9 +11189,10 @@ var ModelProviderIdSchema = _enum([
11189
11189
  * are per upstream. A persisted custom-model row written when this field was a
11190
11190
  * string still parses — the string is lifted into `{ weights }`.
11191
11191
  *
11192
- * Every licence surface (the admin "Models and licenses" page,
11193
- * `THIRD_PARTY_MODELS.md`, the Hugging Face model table) is GENERATED from
11194
- * these records by `scripts/gen-model-licenses.ts` (D661).
11192
+ * Every machine licence surface (`THIRD_PARTY_MODELS.md`, the Hugging Face
11193
+ * model table) is GENERATED from these records by
11194
+ * `scripts/gen-model-licenses.ts` (D661). Operator-facing docs live in
11195
+ * `camstack/docs` → `/docs/detection/models`.
11195
11196
  */
11196
11197
  var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { weights: value } : value, object({
11197
11198
  /** SPDX id of the WEIGHTS' terms, a `LicenseRef-*` for non-SPDX terms, or `UNKNOWN`. */
@@ -14822,7 +14823,7 @@ DeviceType.Camera;
14822
14823
  * This matters here more than anywhere else in the repo, because every provider
14823
14824
  * that knows a device's host knows its PASSWORD too: `{ host, port, username,
14824
14825
  * password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
14825
- * and `http://admin:hunter2@192.168.x.x/` is a URL a browser accepts. The
14826
+ * and `http://admin:hunter2@192.168.60.139/` is a URL a browser accepts. The
14826
14827
  * camera's own page will ask for its own login. That is correct, and pre-
14827
14828
  * filling it is the operator's business, not ours.
14828
14829
  *
@@ -18147,7 +18148,7 @@ method(object({
18147
18148
  timeoutMs: 6e5
18148
18149
  });
18149
18150
  method(object({
18150
- nodeId: string(),
18151
+ targetNodeId: string(),
18151
18152
  modelId: string(),
18152
18153
  format: _enum(MODEL_FORMATS),
18153
18154
  entry: ModelCatalogEntrySchema
@@ -20651,8 +20652,9 @@ var NcRuleSchema = NcRuleInputSchema.extend({
20651
20652
  disabledTargetIds: array(string()).default([])
20652
20653
  });
20653
20654
  /**
20654
- * The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
20655
- * still-true state. `backups-exports` and `alarm` are not sections — a completed
20655
+ * The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
20656
+ * report a still-true state. `addons` is the crash-looped addons only and
20657
+ * `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
20656
20658
  * job is not an open state, and the alarm stays instant.
20657
20659
  */
20658
20660
  var NcStateSummarySectionIdSchema = _enum([
@@ -20664,6 +20666,7 @@ var NcStateSummarySectionIdSchema = _enum([
20664
20666
  "detection-blind",
20665
20667
  "nodes",
20666
20668
  "addons",
20669
+ "addon-updates",
20667
20670
  "updates"
20668
20671
  ]);
20669
20672
  /** One section of a previewed state summary. `unavailable` = its state could not be read. */
@@ -21144,7 +21147,19 @@ var NcAlarmModeDelaysListSchema = array(object({
21144
21147
  * When this mode may be armed. Absent / null = always allowed (same as a
21145
21148
  * rule with no `schedule`). Evaluated with {@link isScheduleActive}.
21146
21149
  */
21147
- schedule: NcScheduleSchema.optional()
21150
+ schedule: NcScheduleSchema.optional(),
21151
+ /**
21152
+ * D706: while this mode's ENTRY DELAY runs, do the alarm rules' own pushes go out (as an
21153
+ * intrusion naming the locations)? Absent = false — the entry-delay notification is the
21154
+ * only one, and the matches ride the triggered notification's mosaic (D705).
21155
+ */
21156
+ notifyDuringEntryDelay: boolean().optional(),
21157
+ /**
21158
+ * D706: notify "watched again" when a sensor this arm bypassed closes and opens again.
21159
+ * Absent = false (logged, not sent). Even when true it is not sent when that same sensor
21160
+ * is the one that starts the entry delay — the entry-delay notification already names it.
21161
+ */
21162
+ notifySensorRewatched: boolean().optional()
21148
21163
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
21149
21164
  var NcAlarmModeDelaysEditListSchema = array(object({
21150
21165
  mode: AlarmArmModeSchema,
@@ -21153,7 +21168,11 @@ var NcAlarmModeDelaysEditListSchema = array(object({
21153
21168
  triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
21154
21169
  postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
21155
21170
  /** Set a schedule, or `null` to clear (mode always allowed again). */
21156
- schedule: NcScheduleSchema.nullable().optional()
21171
+ schedule: NcScheduleSchema.nullable().optional(),
21172
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
21173
+ notifyDuringEntryDelay: boolean().nullable().optional(),
21174
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
21175
+ notifySensorRewatched: boolean().nullable().optional()
21157
21176
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
21158
21177
  /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
21159
21178
  var NcAlarmNonBlockingEditSchema = object({
@@ -22114,39 +22133,19 @@ Object.freeze(Object.fromEntries([{
22114
22133
  label: "Face recognition model",
22115
22134
  defaultModelId: "auraface-r100",
22116
22135
  indexName: "the enrolled face gallery",
22117
- options: [
22118
- {
22119
- id: "auraface-r100",
22120
- label: "AuraFace R100"
22121
- },
22122
- {
22123
- id: "arcface-r100",
22124
- label: "ArcFace (ResNet34)"
22125
- },
22126
- {
22127
- id: "inception-resnet-v1",
22128
- label: "Inception ResNet V1"
22129
- }
22130
- ]
22136
+ options: [{
22137
+ id: "auraface-r100",
22138
+ label: "AuraFace R100"
22139
+ }]
22131
22140
  }, {
22132
22141
  stepId: "clip-embedding",
22133
22142
  label: "Semantic search model",
22134
- defaultModelId: "mobileclip-s1",
22143
+ defaultModelId: "siglip2-b16-224",
22135
22144
  indexName: "the object semantic-search index",
22136
- options: [
22137
- {
22138
- id: "mobileclip-s1",
22139
- label: "MobileCLIP S1"
22140
- },
22141
- {
22142
- id: "mobileclip-s2",
22143
- label: "MobileCLIP S2"
22144
- },
22145
- {
22146
- id: "siglip2-b16-224",
22147
- label: "SigLIP2 B/16 (Apache-2.0)"
22148
- }
22149
- ]
22145
+ options: [{
22146
+ id: "siglip2-b16-224",
22147
+ label: "SigLIP2 B/16 (Apache-2.0)"
22148
+ }]
22150
22149
  }].map((s) => [s.stepId, s.defaultModelId])));
22151
22150
  var CLUSTER_STEP_SETTING_FIELDS = [{
22152
22151
  stepId: "face-embedding",
@@ -25034,6 +25033,22 @@ var MotionSourceEnum = _enum([
25034
25033
  "device-activity"
25035
25034
  ]);
25036
25035
  /**
25036
+ * What opened an on-motion detection SESSION: the motion source that passed the
25037
+ * camera's `motionSources` gate, and what raised it (the camera itself, or a
25038
+ * sensor the operator attached — D672). `sensorName` is the attached sensor's
25039
+ * device name as the orchestrator's camera-sensors resolution last read it;
25040
+ * absent when unknown or when the camera itself triggered.
25041
+ *
25042
+ * Carried on the session attach ONLY so the runner's `DetectionPhaseTransition`
25043
+ * can say what started the session (D672 rule 11, amended 2026-10-06). The
25044
+ * runner never decides anything on it.
25045
+ */
25046
+ var SessionTriggerSchema = object({
25047
+ source: MotionSourceEnum,
25048
+ triggeredBy: MotionTriggeredBySchema,
25049
+ sensorName: string().optional()
25050
+ });
25051
+ /**
25037
25052
  * List of motion sources active on a camera. Empty array is valid:
25038
25053
  * "no source" — happens for battery cams without firmware motion when
25039
25054
  * the operator hasn't opted into the SW analyzer (would hold the
@@ -25285,6 +25300,14 @@ var RunnerCameraConfigSchema = object({
25285
25300
  */
25286
25301
  motionSources: MotionSourcesSchema.default(["analyzer"]),
25287
25302
  /**
25303
+ * What opened this attach, on a SESSION attach only (see
25304
+ * {@link SessionTriggerSchema}). OPTIONAL with no default: absent on a
25305
+ * standing attach, an occupancy burst, a re-dispatch with no motion event
25306
+ * behind it, and every attach from an orchestrator older than the field — the
25307
+ * runner then names no source on the phase event.
25308
+ */
25309
+ sessionTrigger: SessionTriggerSchema.optional(),
25310
+ /**
25288
25311
  * WHICH root detector runs for this camera. The detection counterpart of
25289
25312
  * {@link motionSources}, same shape and same discipline: a per-camera list
25290
25313
  * of sources the system understands, vendor-agnostic, owned here.
@@ -33195,7 +33218,7 @@ var LocalInterfaceSchema = object({
33195
33218
  name: string(),
33196
33219
  family: _enum(["IPv4", "IPv6"]),
33197
33220
  address: string(),
33198
- /** CIDR shorthand (e.g. `192.168.x.x/24`). Empty when OS doesn't expose. */
33221
+ /** CIDR shorthand (e.g. `192.168.10.10/24`). Empty when OS doesn't expose. */
33199
33222
  cidr: string(),
33200
33223
  /** OS netmask. Stable across calls so the SDK can hash on it. */
33201
33224
  netmask: string(),
@@ -33249,7 +33272,8 @@ var ConnectionEndpointSchema = object({
33249
33272
  "lan-ipv4",
33250
33273
  "lan-ipv6",
33251
33274
  "public",
33252
- "loopback"
33275
+ "loopback",
33276
+ "app-link"
33253
33277
  ]),
33254
33278
  /**
33255
33279
  * Originating-interface kind — `lan`/`wifi`/`docker`/`vpn`/`other`/
@@ -33318,15 +33342,27 @@ var GetConnectionEndpointsResultSchema = object({
33318
33342
  localPort: AdvertisedLocalPortSchema
33319
33343
  });
33320
33344
  /**
33321
- * The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
33322
- * AUTO (resolved from the candidate ranking at send time); `resolved` reports
33323
- * what AUTO currently picks, so the UI can show the effective value either way.
33345
+ * The address flagged for notification links. `baseUrl: null` = AUTO, which
33346
+ * since D709 is the CamStack app link; `resolved` reports the effective value,
33347
+ * so the UI can show it either way.
33324
33348
  */
33325
33349
  var NotificationEndpointSchema = object({
33326
33350
  /** The operator's explicit choice, or null for AUTO. */
33327
33351
  baseUrl: string().nullable(),
33328
- /** What the ranking currently resolves to (null when nothing is reachable). */
33329
- resolved: string().nullable()
33352
+ /**
33353
+ * The effective flagged address: the explicit choice, else (AUTO) the
33354
+ * CamStack app link `https://camstack.zentik.app` (D709). A pre-D709 hub
33355
+ * answered the public tunnel / mesh here, or null.
33356
+ */
33357
+ resolved: string().nullable(),
33358
+ /**
33359
+ * The hub origin an app link carries as `hub=` (D709): the hub's best
33360
+ * public HTTPS address — the tunnel, then the mesh (Tailscale MagicDNS) —
33361
+ * picked from this cap's own palette by `pickAppLinkHub`. `null` when the
33362
+ * hub advertises neither; the app link is then minted without `hub=`.
33363
+ * Absent on a pre-D709 hub.
33364
+ */
33365
+ appLinkHub: string().nullable()
33330
33366
  });
33331
33367
  /**
33332
33368
  * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
@@ -33380,7 +33416,11 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
33380
33416
  * Pass `'https'` when the caller is itself loaded over HTTPS
33381
33417
  * to avoid mixed-content blocks in the browser. The public
33382
33418
  * tunnel always emits `https://` regardless. */
33383
- scheme: _enum(["http", "https"]).optional()
33419
+ scheme: _enum(["http", "https"]).optional(),
33420
+ /** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
33421
+ * an address notification links can be flagged with, not a hub
33422
+ * route. Default `false`: racers and rankers never see it. */
33423
+ includeAppLink: boolean().optional()
33384
33424
  }), 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, {
33385
33425
  kind: "mutation",
33386
33426
  auth: "admin"
@@ -33709,7 +33749,7 @@ var MeshPeerSchema = object({
33709
33749
  tags: array(string()).readonly(),
33710
33750
  /** True when the peer advertises itself as an exit-node candidate. */
33711
33751
  exitNodeOption: boolean(),
33712
- /** Subnet routes the peer advertises (e.g. `["192.168.x.x/24"]`). */
33752
+ /** Subnet routes the peer advertises (e.g. `["192.168.10.0/24"]`). */
33713
33753
  advertisedRoutes: array(string()).readonly(),
33714
33754
  /** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
33715
33755
  userLogin: string().nullable(),
@@ -35057,7 +35097,13 @@ var OsdStatusSchema = object({ overlays: array(object({
35057
35097
  */
35058
35098
  availablePositions: array(OsdPositionEnum).readonly(),
35059
35099
  /** Firmware does not allow editing the `text` field (e.g. timestamp). */
35060
- readOnly: boolean().optional()
35100
+ readOnly: boolean().optional(),
35101
+ /**
35102
+ * Firmware text ceiling for this overlay. Absent = no known limit.
35103
+ * The OSD manager truncates here on every write — never stores its own
35104
+ * copy on the binding.
35105
+ */
35106
+ maxCharacters: number().int().positive().optional()
35061
35107
  })).readonly() });
35062
35108
  var OsdOverlayPatchSchema = object({
35063
35109
  enabled: boolean().optional(),
@@ -35154,7 +35200,9 @@ var OsdTemplateBindingSchema = object({
35154
35200
  valuePath: string().min(1).max(64),
35155
35201
  /** Convert TO this unit at render (`tryConvertUnit`). Absent = source unit. */
35156
35202
  displayUnit: string().max(16).optional(),
35157
- maxDecimals: number().int().min(0).max(4).default(1)
35203
+ maxDecimals: number().int().min(0).max(4).default(1),
35204
+ /** Raw value → display text (same shape as slot binding). Empty string hides. */
35205
+ valueMap: record(string(), string()).optional()
35158
35206
  });
35159
35207
  /**
35160
35208
  * A named template: bindings (alias → leaf field) + a parser that
@@ -35204,18 +35252,11 @@ var OsdSlotBindingSchema = object({
35204
35252
  source: OsdSourceSchema,
35205
35253
  /** `${value}` and `${unit}` are substituted; every occurrence. */
35206
35254
  template: string().max(96).default("${value}"),
35207
- /** Truncate with an ellipsis past this length. Absent = no limit. */
35208
- maxCharacters: number().int().min(4).max(64).optional(),
35209
35255
  /**
35210
35256
  * Decimal places for a numeric value. `0` yields an integer — the
35211
35257
  * documented workaround for firmwares that reject `.` in overlay text.
35212
35258
  */
35213
35259
  maxDecimals: number().int().min(0).max(4).default(1),
35214
- /**
35215
- * Appended via `${unit}` when no unit conversion produces a label.
35216
- * Prefer `source.displayUnit` for converted device-state values.
35217
- */
35218
- unitLabel: string().max(8).optional(),
35219
35260
  /** Raw value → display text, e.g. `{"true":"MOTION","false":""}`. */
35220
35261
  valueMap: record(string(), string()).optional(),
35221
35262
  /** Time windows in which the slot is shown. Absent = always. */
@@ -35224,9 +35265,7 @@ var OsdSlotBindingSchema = object({
35224
35265
  * Display gate, in the notification centre's condition vocabulary.
35225
35266
  * Only the keys reported by `getConditionSupport` are accepted.
35226
35267
  */
35227
- conditions: NcConditionsSchema.optional(),
35228
- /** Rendered when the gate is closed or the value unreadable. Empty = hide. */
35229
- fallbackText: string().max(64).default("")
35268
+ conditions: NcConditionsSchema.optional()
35230
35269
  });
35231
35270
  /** One camera slot, as the operator sees it: firmware truth + our binding. */
35232
35271
  var OsdSlotViewSchema = object({
@@ -54141,12 +54180,14 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
54141
54180
  {
54142
54181
  id: "addons",
54143
54182
  family: "system",
54144
- label: "Addons",
54145
- kinds: [
54146
- "addon-crash-loop",
54147
- "addon-update-available",
54148
- "addon-updated"
54149
- ]
54183
+ label: "Addons stopped",
54184
+ kinds: ["addon-crash-loop"]
54185
+ },
54186
+ {
54187
+ id: "addon-updates",
54188
+ family: "system",
54189
+ label: "Addon updates",
54190
+ kinds: ["addon-update-available", "addon-updated"]
54150
54191
  },
54151
54192
  {
54152
54193
  id: "updates",
@@ -54306,13 +54347,15 @@ var STATE_SUMMARY_SECTION_VARS = [
54306
54347
  },
54307
54348
  {
54308
54349
  name: "summaryAddons",
54309
- label: "Summary: addons",
54310
- example: "@camstack/addon-recorder 1.2.3 → 1.2.4",
54311
- kinds: [
54312
- "addon-crash-loop",
54313
- "addon-update-available",
54314
- "addon-updated"
54315
- ]
54350
+ label: "Summary: addons stopped",
54351
+ example: "hub — recorder stopped after repeated crashes",
54352
+ kinds: ["addon-crash-loop"]
54353
+ },
54354
+ {
54355
+ name: "summaryAddonUpdates",
54356
+ label: "Summary: addon updates",
54357
+ example: "hub:\n• @camstack/addon-recorder 1.2.3 → 1.2.4",
54358
+ kinds: ["addon-update-available", "addon-updated"]
54316
54359
  },
54317
54360
  {
54318
54361
  name: "summaryUpdates",
@@ -54396,6 +54439,7 @@ var STATE_SUMMARY_VARS = [
54396
54439
  [...RULE_BODY_ONLY],
54397
54440
  [...RULE_TEXT],
54398
54441
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
54442
+ ([...RULE_TEXT], [...COMBINED_ALARM]),
54399
54443
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
54400
54444
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
54401
54445
  ([...RULE_TEXT], [...CONSUMABLE]),
@@ -54436,6 +54480,8 @@ var STATE_SUMMARY_VARS = [
54436
54480
  [...RULE_TEXT],
54437
54481
  [...RULE_TEXT],
54438
54482
  [...RULE_TEXT],
54483
+ [...RULE_TEXT],
54484
+ [...RULE_TEXT],
54439
54485
  ...STATE_SUMMARY_VARS
54440
54486
  ];
54441
54487
  new Set([
@@ -163091,6 +163137,7 @@ function overlaysFromOsdSnapshot(snapshot) {
163091
163137
  enabled: snapshot.channelEnabled === true,
163092
163138
  text: snapshot.channelName ?? "",
163093
163139
  availablePositions: CORNER_POSITIONS,
163140
+ maxCharacters: 31,
163094
163141
  ...channelPosition !== void 0 ? { position: channelPosition } : {}
163095
163142
  },
163096
163143
  {
@@ -172297,7 +172344,7 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
172297
172344
  key: "host",
172298
172345
  label: "Camera IP",
172299
172346
  required: true,
172300
- placeholder: "192.168.x.x"
172347
+ placeholder: "192.168.10.100"
172301
172348
  },
172302
172349
  {
172303
172350
  type: "number",
@@ -174503,7 +174550,7 @@ var ReolinkHub = class ReolinkHub extends BaseDevice {
174503
174550
  key: "host",
174504
174551
  label: "Hub IP",
174505
174552
  required: true,
174506
- placeholder: "192.168.x.x"
174553
+ placeholder: "192.168.10.100"
174507
174554
  },
174508
174555
  {
174509
174556
  type: "number",
@@ -175337,7 +175384,7 @@ function buildDiscoveryParamsFormSchema() {
175337
175384
  }, {
175338
175385
  id: "scan",
175339
175386
  title: "Scan options",
175340
- description: "Leave the network blank to scan the local subnet. To find cameras on a different subnet, enter its CIDR (e.g. 192.168.x.x/24).",
175387
+ description: "Leave the network blank to scan the local subnet. To find cameras on a different subnet, enter its CIDR (e.g. 192.168.20.0/24).",
175341
175388
  columns: 1,
175342
175389
  fields: [
175343
175390
  {
@@ -175345,7 +175392,7 @@ function buildDiscoveryParamsFormSchema() {
175345
175392
  key: "networkCidr",
175346
175393
  label: "Network (CIDR)",
175347
175394
  required: false,
175348
- placeholder: "192.168.x.x/24"
175395
+ placeholder: "192.168.20.0/24"
175349
175396
  },
175350
175397
  {
175351
175398
  type: "boolean",
@@ -175429,7 +175476,7 @@ function buildCreationFormSchema() {
175429
175476
  key: "host",
175430
175477
  label: "Host (IP / hostname / UID)",
175431
175478
  required: true,
175432
- placeholder: "192.168.x.x",
175479
+ placeholder: "192.168.10.100",
175433
175480
  description: "For UDP-only mode you can leave the host blank and supply the camera UID below — the library will discover it on the network.",
175434
175481
  inputType: "text"
175435
175482
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-reolink",
3
- "version": "1.2.173",
3
+ "version": "1.2.175",
4
4
  "description": "Reolink camera device provider addon for CamStack — native Baichuan protocol",
5
5
  "keywords": [
6
6
  "camstack",