@camstack/addon-terminal 0.1.124 → 0.1.126

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
@@ -10657,11 +10657,11 @@ var ModelVariantGroupSchema = object({
10657
10657
  /** Quantization axis. Omit ⇒ the fp32 base build. */
10658
10658
  precision: _enum(["fp32", "int8"]).optional(),
10659
10659
  /**
10660
- * Speed-optimization axis. Omit ⇒ the standard build. `fast` marks a
10661
- * latency-optimized export (e.g. ReLU-activation variant) — the slot the
10662
- * future performance variants plug into.
10660
+ * Training / latency-variant axis. Omit ⇒ the standard build. `test` marks
10661
+ * an alternate training of the same family (Scrypted `relu_test`); chip
10662
+ * label is "Test".
10663
10663
  */
10664
- optimization: _enum(["standard", "fast"]).optional(),
10664
+ optimization: _enum(["standard", "test"]).optional(),
10665
10665
  /**
10666
10666
  * Input-resolution axis (square input side, px). Omit ⇒ the family's native
10667
10667
  * resolution (640 for yolo26). Reduced-input builds (320 / 256) are a big,
@@ -10684,9 +10684,10 @@ var ModelProviderIdSchema = _enum([
10684
10684
  * are per upstream. A persisted custom-model row written when this field was a
10685
10685
  * string still parses — the string is lifted into `{ weights }`.
10686
10686
  *
10687
- * Every licence surface (the admin "Models and licenses" page,
10688
- * `THIRD_PARTY_MODELS.md`, the Hugging Face model table) is GENERATED from
10689
- * these records by `scripts/gen-model-licenses.ts` (D661).
10687
+ * Every machine licence surface (`THIRD_PARTY_MODELS.md`, the Hugging Face
10688
+ * model table) is GENERATED from these records by
10689
+ * `scripts/gen-model-licenses.ts` (D661). Operator-facing docs live in
10690
+ * `camstack/docs` → `/docs/detection/models`.
10690
10691
  */
10691
10692
  var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { weights: value } : value, object({
10692
10693
  /** SPDX id of the WEIGHTS' terms, a `LicenseRef-*` for non-SPDX terms, or `UNKNOWN`. */
@@ -14317,7 +14318,7 @@ DeviceType.Camera;
14317
14318
  * This matters here more than anywhere else in the repo, because every provider
14318
14319
  * that knows a device's host knows its PASSWORD too: `{ host, port, username,
14319
14320
  * password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
14320
- * and `http://admin:hunter2@192.168.x.x/` is a URL a browser accepts. The
14321
+ * and `http://admin:hunter2@192.168.60.139/` is a URL a browser accepts. The
14321
14322
  * camera's own page will ask for its own login. That is correct, and pre-
14322
14323
  * filling it is the operator's business, not ours.
14323
14324
  *
@@ -17408,7 +17409,7 @@ method(object({
17408
17409
  timeoutMs: 6e5
17409
17410
  });
17410
17411
  method(object({
17411
- nodeId: string(),
17412
+ targetNodeId: string(),
17412
17413
  modelId: string(),
17413
17414
  format: _enum(MODEL_FORMATS),
17414
17415
  entry: ModelCatalogEntrySchema
@@ -19912,8 +19913,9 @@ var NcRuleSchema = NcRuleInputSchema.extend({
19912
19913
  disabledTargetIds: array(string()).default([])
19913
19914
  });
19914
19915
  /**
19915
- * The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
19916
- * still-true state. `backups-exports` and `alarm` are not sections — a completed
19916
+ * The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
19917
+ * report a still-true state. `addons` is the crash-looped addons only and
19918
+ * `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
19917
19919
  * job is not an open state, and the alarm stays instant.
19918
19920
  */
19919
19921
  var NcStateSummarySectionIdSchema = _enum([
@@ -19925,6 +19927,7 @@ var NcStateSummarySectionIdSchema = _enum([
19925
19927
  "detection-blind",
19926
19928
  "nodes",
19927
19929
  "addons",
19930
+ "addon-updates",
19928
19931
  "updates"
19929
19932
  ]);
19930
19933
  /** One section of a previewed state summary. `unavailable` = its state could not be read. */
@@ -20405,7 +20408,19 @@ var NcAlarmModeDelaysListSchema = array(object({
20405
20408
  * When this mode may be armed. Absent / null = always allowed (same as a
20406
20409
  * rule with no `schedule`). Evaluated with {@link isScheduleActive}.
20407
20410
  */
20408
- schedule: NcScheduleSchema.optional()
20411
+ schedule: NcScheduleSchema.optional(),
20412
+ /**
20413
+ * D706: while this mode's ENTRY DELAY runs, do the alarm rules' own pushes go out (as an
20414
+ * intrusion naming the locations)? Absent = false — the entry-delay notification is the
20415
+ * only one, and the matches ride the triggered notification's mosaic (D705).
20416
+ */
20417
+ notifyDuringEntryDelay: boolean().optional(),
20418
+ /**
20419
+ * D706: notify "watched again" when a sensor this arm bypassed closes and opens again.
20420
+ * Absent = false (logged, not sent). Even when true it is not sent when that same sensor
20421
+ * is the one that starts the entry delay — the entry-delay notification already names it.
20422
+ */
20423
+ notifySensorRewatched: boolean().optional()
20409
20424
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
20410
20425
  var NcAlarmModeDelaysEditListSchema = array(object({
20411
20426
  mode: AlarmArmModeSchema,
@@ -20414,7 +20429,11 @@ var NcAlarmModeDelaysEditListSchema = array(object({
20414
20429
  triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
20415
20430
  postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
20416
20431
  /** Set a schedule, or `null` to clear (mode always allowed again). */
20417
- schedule: NcScheduleSchema.nullable().optional()
20432
+ schedule: NcScheduleSchema.nullable().optional(),
20433
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
20434
+ notifyDuringEntryDelay: boolean().nullable().optional(),
20435
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
20436
+ notifySensorRewatched: boolean().nullable().optional()
20418
20437
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
20419
20438
  /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
20420
20439
  var NcAlarmNonBlockingEditSchema = object({
@@ -21375,39 +21394,19 @@ Object.freeze(Object.fromEntries([{
21375
21394
  label: "Face recognition model",
21376
21395
  defaultModelId: "auraface-r100",
21377
21396
  indexName: "the enrolled face gallery",
21378
- options: [
21379
- {
21380
- id: "auraface-r100",
21381
- label: "AuraFace R100"
21382
- },
21383
- {
21384
- id: "arcface-r100",
21385
- label: "ArcFace (ResNet34)"
21386
- },
21387
- {
21388
- id: "inception-resnet-v1",
21389
- label: "Inception ResNet V1"
21390
- }
21391
- ]
21397
+ options: [{
21398
+ id: "auraface-r100",
21399
+ label: "AuraFace R100"
21400
+ }]
21392
21401
  }, {
21393
21402
  stepId: "clip-embedding",
21394
21403
  label: "Semantic search model",
21395
- defaultModelId: "mobileclip-s1",
21404
+ defaultModelId: "siglip2-b16-224",
21396
21405
  indexName: "the object semantic-search index",
21397
- options: [
21398
- {
21399
- id: "mobileclip-s1",
21400
- label: "MobileCLIP S1"
21401
- },
21402
- {
21403
- id: "mobileclip-s2",
21404
- label: "MobileCLIP S2"
21405
- },
21406
- {
21407
- id: "siglip2-b16-224",
21408
- label: "SigLIP2 B/16 (Apache-2.0)"
21409
- }
21410
- ]
21406
+ options: [{
21407
+ id: "siglip2-b16-224",
21408
+ label: "SigLIP2 B/16 (Apache-2.0)"
21409
+ }]
21411
21410
  }].map((s) => [s.stepId, s.defaultModelId])));
21412
21411
  var CLUSTER_STEP_SETTING_FIELDS = [{
21413
21412
  stepId: "face-embedding",
@@ -24295,6 +24294,22 @@ var MotionSourceEnum = _enum([
24295
24294
  "device-activity"
24296
24295
  ]);
24297
24296
  /**
24297
+ * What opened an on-motion detection SESSION: the motion source that passed the
24298
+ * camera's `motionSources` gate, and what raised it (the camera itself, or a
24299
+ * sensor the operator attached — D672). `sensorName` is the attached sensor's
24300
+ * device name as the orchestrator's camera-sensors resolution last read it;
24301
+ * absent when unknown or when the camera itself triggered.
24302
+ *
24303
+ * Carried on the session attach ONLY so the runner's `DetectionPhaseTransition`
24304
+ * can say what started the session (D672 rule 11, amended 2026-10-06). The
24305
+ * runner never decides anything on it.
24306
+ */
24307
+ var SessionTriggerSchema = object({
24308
+ source: MotionSourceEnum,
24309
+ triggeredBy: MotionTriggeredBySchema,
24310
+ sensorName: string().optional()
24311
+ });
24312
+ /**
24298
24313
  * List of motion sources active on a camera. Empty array is valid:
24299
24314
  * "no source" — happens for battery cams without firmware motion when
24300
24315
  * the operator hasn't opted into the SW analyzer (would hold the
@@ -24546,6 +24561,14 @@ var RunnerCameraConfigSchema = object({
24546
24561
  */
24547
24562
  motionSources: MotionSourcesSchema.default(["analyzer"]),
24548
24563
  /**
24564
+ * What opened this attach, on a SESSION attach only (see
24565
+ * {@link SessionTriggerSchema}). OPTIONAL with no default: absent on a
24566
+ * standing attach, an occupancy burst, a re-dispatch with no motion event
24567
+ * behind it, and every attach from an orchestrator older than the field — the
24568
+ * runner then names no source on the phase event.
24569
+ */
24570
+ sessionTrigger: SessionTriggerSchema.optional(),
24571
+ /**
24549
24572
  * WHICH root detector runs for this camera. The detection counterpart of
24550
24573
  * {@link motionSources}, same shape and same discipline: a per-camera list
24551
24574
  * of sources the system understands, vendor-agnostic, owned here.
@@ -32082,7 +32105,7 @@ var LocalInterfaceSchema = object({
32082
32105
  name: string(),
32083
32106
  family: _enum(["IPv4", "IPv6"]),
32084
32107
  address: string(),
32085
- /** CIDR shorthand (e.g. `192.168.x.x/24`). Empty when OS doesn't expose. */
32108
+ /** CIDR shorthand (e.g. `192.168.10.10/24`). Empty when OS doesn't expose. */
32086
32109
  cidr: string(),
32087
32110
  /** OS netmask. Stable across calls so the SDK can hash on it. */
32088
32111
  netmask: string(),
@@ -32136,7 +32159,8 @@ var ConnectionEndpointSchema = object({
32136
32159
  "lan-ipv4",
32137
32160
  "lan-ipv6",
32138
32161
  "public",
32139
- "loopback"
32162
+ "loopback",
32163
+ "app-link"
32140
32164
  ]),
32141
32165
  /**
32142
32166
  * Originating-interface kind — `lan`/`wifi`/`docker`/`vpn`/`other`/
@@ -32205,15 +32229,27 @@ var GetConnectionEndpointsResultSchema = object({
32205
32229
  localPort: AdvertisedLocalPortSchema
32206
32230
  });
32207
32231
  /**
32208
- * The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
32209
- * AUTO (resolved from the candidate ranking at send time); `resolved` reports
32210
- * what AUTO currently picks, so the UI can show the effective value either way.
32232
+ * The address flagged for notification links. `baseUrl: null` = AUTO, which
32233
+ * since D709 is the CamStack app link; `resolved` reports the effective value,
32234
+ * so the UI can show it either way.
32211
32235
  */
32212
32236
  var NotificationEndpointSchema = object({
32213
32237
  /** The operator's explicit choice, or null for AUTO. */
32214
32238
  baseUrl: string().nullable(),
32215
- /** What the ranking currently resolves to (null when nothing is reachable). */
32216
- resolved: string().nullable()
32239
+ /**
32240
+ * The effective flagged address: the explicit choice, else (AUTO) the
32241
+ * CamStack app link `https://camstack.zentik.app` (D709). A pre-D709 hub
32242
+ * answered the public tunnel / mesh here, or null.
32243
+ */
32244
+ resolved: string().nullable(),
32245
+ /**
32246
+ * The hub origin an app link carries as `hub=` (D709): the hub's best
32247
+ * public HTTPS address — the tunnel, then the mesh (Tailscale MagicDNS) —
32248
+ * picked from this cap's own palette by `pickAppLinkHub`. `null` when the
32249
+ * hub advertises neither; the app link is then minted without `hub=`.
32250
+ * Absent on a pre-D709 hub.
32251
+ */
32252
+ appLinkHub: string().nullable()
32217
32253
  });
32218
32254
  /**
32219
32255
  * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
@@ -32267,7 +32303,11 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
32267
32303
  * Pass `'https'` when the caller is itself loaded over HTTPS
32268
32304
  * to avoid mixed-content blocks in the browser. The public
32269
32305
  * tunnel always emits `https://` regardless. */
32270
- scheme: _enum(["http", "https"]).optional()
32306
+ scheme: _enum(["http", "https"]).optional(),
32307
+ /** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
32308
+ * an address notification links can be flagged with, not a hub
32309
+ * route. Default `false`: racers and rankers never see it. */
32310
+ includeAppLink: boolean().optional()
32271
32311
  }), 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, {
32272
32312
  kind: "mutation",
32273
32313
  auth: "admin"
@@ -32596,7 +32636,7 @@ var MeshPeerSchema = object({
32596
32636
  tags: array(string()).readonly(),
32597
32637
  /** True when the peer advertises itself as an exit-node candidate. */
32598
32638
  exitNodeOption: boolean(),
32599
- /** Subnet routes the peer advertises (e.g. `["192.168.x.x/24"]`). */
32639
+ /** Subnet routes the peer advertises (e.g. `["192.168.10.0/24"]`). */
32600
32640
  advertisedRoutes: array(string()).readonly(),
32601
32641
  /** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
32602
32642
  userLogin: string().nullable(),
@@ -33924,7 +33964,13 @@ var OsdStatusSchema = object({ overlays: array(object({
33924
33964
  */
33925
33965
  availablePositions: array(OsdPositionEnum).readonly(),
33926
33966
  /** Firmware does not allow editing the `text` field (e.g. timestamp). */
33927
- readOnly: boolean().optional()
33967
+ readOnly: boolean().optional(),
33968
+ /**
33969
+ * Firmware text ceiling for this overlay. Absent = no known limit.
33970
+ * The OSD manager truncates here on every write — never stores its own
33971
+ * copy on the binding.
33972
+ */
33973
+ maxCharacters: number().int().positive().optional()
33928
33974
  })).readonly() });
33929
33975
  var OsdOverlayPatchSchema = object({
33930
33976
  enabled: boolean().optional(),
@@ -33975,7 +34021,9 @@ var OsdTemplateBindingSchema = object({
33975
34021
  valuePath: string().min(1).max(64),
33976
34022
  /** Convert TO this unit at render (`tryConvertUnit`). Absent = source unit. */
33977
34023
  displayUnit: string().max(16).optional(),
33978
- maxDecimals: number().int().min(0).max(4).default(1)
34024
+ maxDecimals: number().int().min(0).max(4).default(1),
34025
+ /** Raw value → display text (same shape as slot binding). Empty string hides. */
34026
+ valueMap: record(string(), string()).optional()
33979
34027
  });
33980
34028
  /**
33981
34029
  * A named template: bindings (alias → leaf field) + a parser that
@@ -34025,18 +34073,11 @@ var OsdSlotBindingSchema = object({
34025
34073
  source: OsdSourceSchema,
34026
34074
  /** `${value}` and `${unit}` are substituted; every occurrence. */
34027
34075
  template: string().max(96).default("${value}"),
34028
- /** Truncate with an ellipsis past this length. Absent = no limit. */
34029
- maxCharacters: number().int().min(4).max(64).optional(),
34030
34076
  /**
34031
34077
  * Decimal places for a numeric value. `0` yields an integer — the
34032
34078
  * documented workaround for firmwares that reject `.` in overlay text.
34033
34079
  */
34034
34080
  maxDecimals: number().int().min(0).max(4).default(1),
34035
- /**
34036
- * Appended via `${unit}` when no unit conversion produces a label.
34037
- * Prefer `source.displayUnit` for converted device-state values.
34038
- */
34039
- unitLabel: string().max(8).optional(),
34040
34081
  /** Raw value → display text, e.g. `{"true":"MOTION","false":""}`. */
34041
34082
  valueMap: record(string(), string()).optional(),
34042
34083
  /** Time windows in which the slot is shown. Absent = always. */
@@ -34045,9 +34086,7 @@ var OsdSlotBindingSchema = object({
34045
34086
  * Display gate, in the notification centre's condition vocabulary.
34046
34087
  * Only the keys reported by `getConditionSupport` are accepted.
34047
34088
  */
34048
- conditions: NcConditionsSchema.optional(),
34049
- /** Rendered when the gate is closed or the value unreadable. Empty = hide. */
34050
- fallbackText: string().max(64).default("")
34089
+ conditions: NcConditionsSchema.optional()
34051
34090
  });
34052
34091
  /** One camera slot, as the operator sees it: firmware truth + our binding. */
34053
34092
  var OsdSlotViewSchema = object({
@@ -51803,12 +51842,14 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
51803
51842
  {
51804
51843
  id: "addons",
51805
51844
  family: "system",
51806
- label: "Addons",
51807
- kinds: [
51808
- "addon-crash-loop",
51809
- "addon-update-available",
51810
- "addon-updated"
51811
- ]
51845
+ label: "Addons stopped",
51846
+ kinds: ["addon-crash-loop"]
51847
+ },
51848
+ {
51849
+ id: "addon-updates",
51850
+ family: "system",
51851
+ label: "Addon updates",
51852
+ kinds: ["addon-update-available", "addon-updated"]
51812
51853
  },
51813
51854
  {
51814
51855
  id: "updates",
@@ -51968,13 +52009,15 @@ var STATE_SUMMARY_SECTION_VARS = [
51968
52009
  },
51969
52010
  {
51970
52011
  name: "summaryAddons",
51971
- label: "Summary: addons",
51972
- example: "@camstack/addon-recorder 1.2.3 → 1.2.4",
51973
- kinds: [
51974
- "addon-crash-loop",
51975
- "addon-update-available",
51976
- "addon-updated"
51977
- ]
52012
+ label: "Summary: addons stopped",
52013
+ example: "hub — recorder stopped after repeated crashes",
52014
+ kinds: ["addon-crash-loop"]
52015
+ },
52016
+ {
52017
+ name: "summaryAddonUpdates",
52018
+ label: "Summary: addon updates",
52019
+ example: "hub:\n• @camstack/addon-recorder 1.2.3 → 1.2.4",
52020
+ kinds: ["addon-update-available", "addon-updated"]
51978
52021
  },
51979
52022
  {
51980
52023
  name: "summaryUpdates",
@@ -52058,6 +52101,7 @@ var STATE_SUMMARY_VARS = [
52058
52101
  [...RULE_BODY_ONLY],
52059
52102
  [...RULE_TEXT],
52060
52103
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
52104
+ ([...RULE_TEXT], [...COMBINED_ALARM]),
52061
52105
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
52062
52106
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
52063
52107
  ([...RULE_TEXT], [...CONSUMABLE]),
@@ -52098,6 +52142,8 @@ var STATE_SUMMARY_VARS = [
52098
52142
  [...RULE_TEXT],
52099
52143
  [...RULE_TEXT],
52100
52144
  [...RULE_TEXT],
52145
+ [...RULE_TEXT],
52146
+ [...RULE_TEXT],
52101
52147
  ...STATE_SUMMARY_VARS
52102
52148
  ];
52103
52149
  new Set([
package/dist/addon.mjs CHANGED
@@ -10634,11 +10634,11 @@ var ModelVariantGroupSchema = object({
10634
10634
  /** Quantization axis. Omit ⇒ the fp32 base build. */
10635
10635
  precision: _enum(["fp32", "int8"]).optional(),
10636
10636
  /**
10637
- * Speed-optimization axis. Omit ⇒ the standard build. `fast` marks a
10638
- * latency-optimized export (e.g. ReLU-activation variant) — the slot the
10639
- * future performance variants plug into.
10637
+ * Training / latency-variant axis. Omit ⇒ the standard build. `test` marks
10638
+ * an alternate training of the same family (Scrypted `relu_test`); chip
10639
+ * label is "Test".
10640
10640
  */
10641
- optimization: _enum(["standard", "fast"]).optional(),
10641
+ optimization: _enum(["standard", "test"]).optional(),
10642
10642
  /**
10643
10643
  * Input-resolution axis (square input side, px). Omit ⇒ the family's native
10644
10644
  * resolution (640 for yolo26). Reduced-input builds (320 / 256) are a big,
@@ -10661,9 +10661,10 @@ var ModelProviderIdSchema = _enum([
10661
10661
  * are per upstream. A persisted custom-model row written when this field was a
10662
10662
  * string still parses — the string is lifted into `{ weights }`.
10663
10663
  *
10664
- * Every licence surface (the admin "Models and licenses" page,
10665
- * `THIRD_PARTY_MODELS.md`, the Hugging Face model table) is GENERATED from
10666
- * these records by `scripts/gen-model-licenses.ts` (D661).
10664
+ * Every machine licence surface (`THIRD_PARTY_MODELS.md`, the Hugging Face
10665
+ * model table) is GENERATED from these records by
10666
+ * `scripts/gen-model-licenses.ts` (D661). Operator-facing docs live in
10667
+ * `camstack/docs` → `/docs/detection/models`.
10667
10668
  */
10668
10669
  var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { weights: value } : value, object({
10669
10670
  /** SPDX id of the WEIGHTS' terms, a `LicenseRef-*` for non-SPDX terms, or `UNKNOWN`. */
@@ -14294,7 +14295,7 @@ DeviceType.Camera;
14294
14295
  * This matters here more than anywhere else in the repo, because every provider
14295
14296
  * that knows a device's host knows its PASSWORD too: `{ host, port, username,
14296
14297
  * password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
14297
- * and `http://admin:hunter2@192.168.x.x/` is a URL a browser accepts. The
14298
+ * and `http://admin:hunter2@192.168.60.139/` is a URL a browser accepts. The
14298
14299
  * camera's own page will ask for its own login. That is correct, and pre-
14299
14300
  * filling it is the operator's business, not ours.
14300
14301
  *
@@ -17385,7 +17386,7 @@ method(object({
17385
17386
  timeoutMs: 6e5
17386
17387
  });
17387
17388
  method(object({
17388
- nodeId: string(),
17389
+ targetNodeId: string(),
17389
17390
  modelId: string(),
17390
17391
  format: _enum(MODEL_FORMATS),
17391
17392
  entry: ModelCatalogEntrySchema
@@ -19889,8 +19890,9 @@ var NcRuleSchema = NcRuleInputSchema.extend({
19889
19890
  disabledTargetIds: array(string()).default([])
19890
19891
  });
19891
19892
  /**
19892
- * The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
19893
- * still-true state. `backups-exports` and `alarm` are not sections — a completed
19893
+ * The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
19894
+ * report a still-true state. `addons` is the crash-looped addons only and
19895
+ * `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
19894
19896
  * job is not an open state, and the alarm stays instant.
19895
19897
  */
19896
19898
  var NcStateSummarySectionIdSchema = _enum([
@@ -19902,6 +19904,7 @@ var NcStateSummarySectionIdSchema = _enum([
19902
19904
  "detection-blind",
19903
19905
  "nodes",
19904
19906
  "addons",
19907
+ "addon-updates",
19905
19908
  "updates"
19906
19909
  ]);
19907
19910
  /** One section of a previewed state summary. `unavailable` = its state could not be read. */
@@ -20382,7 +20385,19 @@ var NcAlarmModeDelaysListSchema = array(object({
20382
20385
  * When this mode may be armed. Absent / null = always allowed (same as a
20383
20386
  * rule with no `schedule`). Evaluated with {@link isScheduleActive}.
20384
20387
  */
20385
- schedule: NcScheduleSchema.optional()
20388
+ schedule: NcScheduleSchema.optional(),
20389
+ /**
20390
+ * D706: while this mode's ENTRY DELAY runs, do the alarm rules' own pushes go out (as an
20391
+ * intrusion naming the locations)? Absent = false — the entry-delay notification is the
20392
+ * only one, and the matches ride the triggered notification's mosaic (D705).
20393
+ */
20394
+ notifyDuringEntryDelay: boolean().optional(),
20395
+ /**
20396
+ * D706: notify "watched again" when a sensor this arm bypassed closes and opens again.
20397
+ * Absent = false (logged, not sent). Even when true it is not sent when that same sensor
20398
+ * is the one that starts the entry delay — the entry-delay notification already names it.
20399
+ */
20400
+ notifySensorRewatched: boolean().optional()
20386
20401
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
20387
20402
  var NcAlarmModeDelaysEditListSchema = array(object({
20388
20403
  mode: AlarmArmModeSchema,
@@ -20391,7 +20406,11 @@ var NcAlarmModeDelaysEditListSchema = array(object({
20391
20406
  triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
20392
20407
  postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
20393
20408
  /** Set a schedule, or `null` to clear (mode always allowed again). */
20394
- schedule: NcScheduleSchema.nullable().optional()
20409
+ schedule: NcScheduleSchema.nullable().optional(),
20410
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
20411
+ notifyDuringEntryDelay: boolean().nullable().optional(),
20412
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
20413
+ notifySensorRewatched: boolean().nullable().optional()
20395
20414
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
20396
20415
  /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
20397
20416
  var NcAlarmNonBlockingEditSchema = object({
@@ -21352,39 +21371,19 @@ Object.freeze(Object.fromEntries([{
21352
21371
  label: "Face recognition model",
21353
21372
  defaultModelId: "auraface-r100",
21354
21373
  indexName: "the enrolled face gallery",
21355
- options: [
21356
- {
21357
- id: "auraface-r100",
21358
- label: "AuraFace R100"
21359
- },
21360
- {
21361
- id: "arcface-r100",
21362
- label: "ArcFace (ResNet34)"
21363
- },
21364
- {
21365
- id: "inception-resnet-v1",
21366
- label: "Inception ResNet V1"
21367
- }
21368
- ]
21374
+ options: [{
21375
+ id: "auraface-r100",
21376
+ label: "AuraFace R100"
21377
+ }]
21369
21378
  }, {
21370
21379
  stepId: "clip-embedding",
21371
21380
  label: "Semantic search model",
21372
- defaultModelId: "mobileclip-s1",
21381
+ defaultModelId: "siglip2-b16-224",
21373
21382
  indexName: "the object semantic-search index",
21374
- options: [
21375
- {
21376
- id: "mobileclip-s1",
21377
- label: "MobileCLIP S1"
21378
- },
21379
- {
21380
- id: "mobileclip-s2",
21381
- label: "MobileCLIP S2"
21382
- },
21383
- {
21384
- id: "siglip2-b16-224",
21385
- label: "SigLIP2 B/16 (Apache-2.0)"
21386
- }
21387
- ]
21383
+ options: [{
21384
+ id: "siglip2-b16-224",
21385
+ label: "SigLIP2 B/16 (Apache-2.0)"
21386
+ }]
21388
21387
  }].map((s) => [s.stepId, s.defaultModelId])));
21389
21388
  var CLUSTER_STEP_SETTING_FIELDS = [{
21390
21389
  stepId: "face-embedding",
@@ -24272,6 +24271,22 @@ var MotionSourceEnum = _enum([
24272
24271
  "device-activity"
24273
24272
  ]);
24274
24273
  /**
24274
+ * What opened an on-motion detection SESSION: the motion source that passed the
24275
+ * camera's `motionSources` gate, and what raised it (the camera itself, or a
24276
+ * sensor the operator attached — D672). `sensorName` is the attached sensor's
24277
+ * device name as the orchestrator's camera-sensors resolution last read it;
24278
+ * absent when unknown or when the camera itself triggered.
24279
+ *
24280
+ * Carried on the session attach ONLY so the runner's `DetectionPhaseTransition`
24281
+ * can say what started the session (D672 rule 11, amended 2026-10-06). The
24282
+ * runner never decides anything on it.
24283
+ */
24284
+ var SessionTriggerSchema = object({
24285
+ source: MotionSourceEnum,
24286
+ triggeredBy: MotionTriggeredBySchema,
24287
+ sensorName: string().optional()
24288
+ });
24289
+ /**
24275
24290
  * List of motion sources active on a camera. Empty array is valid:
24276
24291
  * "no source" — happens for battery cams without firmware motion when
24277
24292
  * the operator hasn't opted into the SW analyzer (would hold the
@@ -24523,6 +24538,14 @@ var RunnerCameraConfigSchema = object({
24523
24538
  */
24524
24539
  motionSources: MotionSourcesSchema.default(["analyzer"]),
24525
24540
  /**
24541
+ * What opened this attach, on a SESSION attach only (see
24542
+ * {@link SessionTriggerSchema}). OPTIONAL with no default: absent on a
24543
+ * standing attach, an occupancy burst, a re-dispatch with no motion event
24544
+ * behind it, and every attach from an orchestrator older than the field — the
24545
+ * runner then names no source on the phase event.
24546
+ */
24547
+ sessionTrigger: SessionTriggerSchema.optional(),
24548
+ /**
24526
24549
  * WHICH root detector runs for this camera. The detection counterpart of
24527
24550
  * {@link motionSources}, same shape and same discipline: a per-camera list
24528
24551
  * of sources the system understands, vendor-agnostic, owned here.
@@ -32059,7 +32082,7 @@ var LocalInterfaceSchema = object({
32059
32082
  name: string(),
32060
32083
  family: _enum(["IPv4", "IPv6"]),
32061
32084
  address: string(),
32062
- /** CIDR shorthand (e.g. `192.168.x.x/24`). Empty when OS doesn't expose. */
32085
+ /** CIDR shorthand (e.g. `192.168.10.10/24`). Empty when OS doesn't expose. */
32063
32086
  cidr: string(),
32064
32087
  /** OS netmask. Stable across calls so the SDK can hash on it. */
32065
32088
  netmask: string(),
@@ -32113,7 +32136,8 @@ var ConnectionEndpointSchema = object({
32113
32136
  "lan-ipv4",
32114
32137
  "lan-ipv6",
32115
32138
  "public",
32116
- "loopback"
32139
+ "loopback",
32140
+ "app-link"
32117
32141
  ]),
32118
32142
  /**
32119
32143
  * Originating-interface kind — `lan`/`wifi`/`docker`/`vpn`/`other`/
@@ -32182,15 +32206,27 @@ var GetConnectionEndpointsResultSchema = object({
32182
32206
  localPort: AdvertisedLocalPortSchema
32183
32207
  });
32184
32208
  /**
32185
- * The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
32186
- * AUTO (resolved from the candidate ranking at send time); `resolved` reports
32187
- * what AUTO currently picks, so the UI can show the effective value either way.
32209
+ * The address flagged for notification links. `baseUrl: null` = AUTO, which
32210
+ * since D709 is the CamStack app link; `resolved` reports the effective value,
32211
+ * so the UI can show it either way.
32188
32212
  */
32189
32213
  var NotificationEndpointSchema = object({
32190
32214
  /** The operator's explicit choice, or null for AUTO. */
32191
32215
  baseUrl: string().nullable(),
32192
- /** What the ranking currently resolves to (null when nothing is reachable). */
32193
- resolved: string().nullable()
32216
+ /**
32217
+ * The effective flagged address: the explicit choice, else (AUTO) the
32218
+ * CamStack app link `https://camstack.zentik.app` (D709). A pre-D709 hub
32219
+ * answered the public tunnel / mesh here, or null.
32220
+ */
32221
+ resolved: string().nullable(),
32222
+ /**
32223
+ * The hub origin an app link carries as `hub=` (D709): the hub's best
32224
+ * public HTTPS address — the tunnel, then the mesh (Tailscale MagicDNS) —
32225
+ * picked from this cap's own palette by `pickAppLinkHub`. `null` when the
32226
+ * hub advertises neither; the app link is then minted without `hub=`.
32227
+ * Absent on a pre-D709 hub.
32228
+ */
32229
+ appLinkHub: string().nullable()
32194
32230
  });
32195
32231
  /**
32196
32232
  * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
@@ -32244,7 +32280,11 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
32244
32280
  * Pass `'https'` when the caller is itself loaded over HTTPS
32245
32281
  * to avoid mixed-content blocks in the browser. The public
32246
32282
  * tunnel always emits `https://` regardless. */
32247
- scheme: _enum(["http", "https"]).optional()
32283
+ scheme: _enum(["http", "https"]).optional(),
32284
+ /** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
32285
+ * an address notification links can be flagged with, not a hub
32286
+ * route. Default `false`: racers and rankers never see it. */
32287
+ includeAppLink: boolean().optional()
32248
32288
  }), 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, {
32249
32289
  kind: "mutation",
32250
32290
  auth: "admin"
@@ -32573,7 +32613,7 @@ var MeshPeerSchema = object({
32573
32613
  tags: array(string()).readonly(),
32574
32614
  /** True when the peer advertises itself as an exit-node candidate. */
32575
32615
  exitNodeOption: boolean(),
32576
- /** Subnet routes the peer advertises (e.g. `["192.168.x.x/24"]`). */
32616
+ /** Subnet routes the peer advertises (e.g. `["192.168.10.0/24"]`). */
32577
32617
  advertisedRoutes: array(string()).readonly(),
32578
32618
  /** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
32579
32619
  userLogin: string().nullable(),
@@ -33901,7 +33941,13 @@ var OsdStatusSchema = object({ overlays: array(object({
33901
33941
  */
33902
33942
  availablePositions: array(OsdPositionEnum).readonly(),
33903
33943
  /** Firmware does not allow editing the `text` field (e.g. timestamp). */
33904
- readOnly: boolean().optional()
33944
+ readOnly: boolean().optional(),
33945
+ /**
33946
+ * Firmware text ceiling for this overlay. Absent = no known limit.
33947
+ * The OSD manager truncates here on every write — never stores its own
33948
+ * copy on the binding.
33949
+ */
33950
+ maxCharacters: number().int().positive().optional()
33905
33951
  })).readonly() });
33906
33952
  var OsdOverlayPatchSchema = object({
33907
33953
  enabled: boolean().optional(),
@@ -33952,7 +33998,9 @@ var OsdTemplateBindingSchema = object({
33952
33998
  valuePath: string().min(1).max(64),
33953
33999
  /** Convert TO this unit at render (`tryConvertUnit`). Absent = source unit. */
33954
34000
  displayUnit: string().max(16).optional(),
33955
- maxDecimals: number().int().min(0).max(4).default(1)
34001
+ maxDecimals: number().int().min(0).max(4).default(1),
34002
+ /** Raw value → display text (same shape as slot binding). Empty string hides. */
34003
+ valueMap: record(string(), string()).optional()
33956
34004
  });
33957
34005
  /**
33958
34006
  * A named template: bindings (alias → leaf field) + a parser that
@@ -34002,18 +34050,11 @@ var OsdSlotBindingSchema = object({
34002
34050
  source: OsdSourceSchema,
34003
34051
  /** `${value}` and `${unit}` are substituted; every occurrence. */
34004
34052
  template: string().max(96).default("${value}"),
34005
- /** Truncate with an ellipsis past this length. Absent = no limit. */
34006
- maxCharacters: number().int().min(4).max(64).optional(),
34007
34053
  /**
34008
34054
  * Decimal places for a numeric value. `0` yields an integer — the
34009
34055
  * documented workaround for firmwares that reject `.` in overlay text.
34010
34056
  */
34011
34057
  maxDecimals: number().int().min(0).max(4).default(1),
34012
- /**
34013
- * Appended via `${unit}` when no unit conversion produces a label.
34014
- * Prefer `source.displayUnit` for converted device-state values.
34015
- */
34016
- unitLabel: string().max(8).optional(),
34017
34058
  /** Raw value → display text, e.g. `{"true":"MOTION","false":""}`. */
34018
34059
  valueMap: record(string(), string()).optional(),
34019
34060
  /** Time windows in which the slot is shown. Absent = always. */
@@ -34022,9 +34063,7 @@ var OsdSlotBindingSchema = object({
34022
34063
  * Display gate, in the notification centre's condition vocabulary.
34023
34064
  * Only the keys reported by `getConditionSupport` are accepted.
34024
34065
  */
34025
- conditions: NcConditionsSchema.optional(),
34026
- /** Rendered when the gate is closed or the value unreadable. Empty = hide. */
34027
- fallbackText: string().max(64).default("")
34066
+ conditions: NcConditionsSchema.optional()
34028
34067
  });
34029
34068
  /** One camera slot, as the operator sees it: firmware truth + our binding. */
34030
34069
  var OsdSlotViewSchema = object({
@@ -51780,12 +51819,14 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
51780
51819
  {
51781
51820
  id: "addons",
51782
51821
  family: "system",
51783
- label: "Addons",
51784
- kinds: [
51785
- "addon-crash-loop",
51786
- "addon-update-available",
51787
- "addon-updated"
51788
- ]
51822
+ label: "Addons stopped",
51823
+ kinds: ["addon-crash-loop"]
51824
+ },
51825
+ {
51826
+ id: "addon-updates",
51827
+ family: "system",
51828
+ label: "Addon updates",
51829
+ kinds: ["addon-update-available", "addon-updated"]
51789
51830
  },
51790
51831
  {
51791
51832
  id: "updates",
@@ -51945,13 +51986,15 @@ var STATE_SUMMARY_SECTION_VARS = [
51945
51986
  },
51946
51987
  {
51947
51988
  name: "summaryAddons",
51948
- label: "Summary: addons",
51949
- example: "@camstack/addon-recorder 1.2.3 → 1.2.4",
51950
- kinds: [
51951
- "addon-crash-loop",
51952
- "addon-update-available",
51953
- "addon-updated"
51954
- ]
51989
+ label: "Summary: addons stopped",
51990
+ example: "hub — recorder stopped after repeated crashes",
51991
+ kinds: ["addon-crash-loop"]
51992
+ },
51993
+ {
51994
+ name: "summaryAddonUpdates",
51995
+ label: "Summary: addon updates",
51996
+ example: "hub:\n• @camstack/addon-recorder 1.2.3 → 1.2.4",
51997
+ kinds: ["addon-update-available", "addon-updated"]
51955
51998
  },
51956
51999
  {
51957
52000
  name: "summaryUpdates",
@@ -52035,6 +52078,7 @@ var STATE_SUMMARY_VARS = [
52035
52078
  [...RULE_BODY_ONLY],
52036
52079
  [...RULE_TEXT],
52037
52080
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
52081
+ ([...RULE_TEXT], [...COMBINED_ALARM]),
52038
52082
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
52039
52083
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
52040
52084
  ([...RULE_TEXT], [...CONSUMABLE]),
@@ -52075,6 +52119,8 @@ var STATE_SUMMARY_VARS = [
52075
52119
  [...RULE_TEXT],
52076
52120
  [...RULE_TEXT],
52077
52121
  [...RULE_TEXT],
52122
+ [...RULE_TEXT],
52123
+ [...RULE_TEXT],
52078
52124
  ...STATE_SUMMARY_VARS
52079
52125
  ];
52080
52126
  new Set([
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-terminal",
3
- "version": "0.1.124",
3
+ "version": "0.1.126",
4
4
  "description": "Interactive terminal sessions (pty + xterm) as a CamStack addon",
5
5
  "keywords": [
6
6
  "camstack",