@camstack/system 1.2.244 → 1.2.245

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.
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("./chunk-Cek0wNdY.js");
3
3
  const require_event_loop_stall_monitor = require("./event-loop-stall-monitor-CAsHdMwP.js");
4
4
  const require_custom_action_registry = require("./custom-action-registry-acBY3mHA.js");
5
- const require_snapshot_courtesy = require("./snapshot-courtesy-oeTWCXPv.js");
5
+ const require_snapshot_courtesy = require("./snapshot-courtesy-Cqs7GkOV.js");
6
6
  exports.COURTESY_DEFAULT_WIDTH = require_snapshot_courtesy.COURTESY_DEFAULT_WIDTH;
7
7
  exports.CustomActionRegistry = require_custom_action_registry.CustomActionRegistry;
8
8
  exports.ModelDownloadService = require_event_loop_stall_monitor.ModelDownloadService;
@@ -1,4 +1,4 @@
1
1
  import { a as createFileDataPlaneHandler, c as parseRangeHeader, d as ModelDownloadService, f as collectModelFiles, g as ensureModel, i as startEventLoopStallMonitor, m as downloadFile, n as STALL_TICK_MS, o as contentTypeFor, p as deleteModelFromDisk, r as attributeStall, t as STALL_REPORT_MS, v as getModelFilePath, y as isModelDownloaded } from "./event-loop-stall-monitor-GPrVvx14.mjs";
2
2
  import { t as CustomActionRegistry } from "./custom-action-registry-B4Cf4O_X.mjs";
3
- import { i as renderCourtesyOverlayJpeg, n as courtesyCacheKey, r as renderCourtesyJpeg, t as COURTESY_DEFAULT_WIDTH } from "./snapshot-courtesy-LoJNgHHZ.mjs";
3
+ import { i as renderCourtesyOverlayJpeg, n as courtesyCacheKey, r as renderCourtesyJpeg, t as COURTESY_DEFAULT_WIDTH } from "./snapshot-courtesy-CZPvteq2.mjs";
4
4
  export { COURTESY_DEFAULT_WIDTH, CustomActionRegistry, ModelDownloadService, STALL_REPORT_MS, STALL_TICK_MS, attributeStall, collectModelFiles, contentTypeFor, courtesyCacheKey, createFileDataPlaneHandler, deleteModelFromDisk, downloadFile, ensureModel, getModelFilePath, isModelDownloaded, parseRangeHeader, renderCourtesyJpeg, renderCourtesyOverlayJpeg, startEventLoopStallMonitor };
@@ -4,7 +4,7 @@ Object.defineProperties(exports, {
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
6
  const require_dist = require("../../dist-Cz6h6Nc3.js");
7
- const require_snapshot_courtesy = require("../../snapshot-courtesy-oeTWCXPv.js");
7
+ const require_snapshot_courtesy = require("../../snapshot-courtesy-Cqs7GkOV.js");
8
8
  let zod = require("zod");
9
9
  let node_crypto = require("node:crypto");
10
10
  let _camstack_types_node = require("@camstack/types/node");
@@ -1,5 +1,5 @@
1
1
  import { Bt as snapshotCapability, Cn as EventCategory, G as deriveBatteryPresence, Gt as streamQualityLabel, I as bareAddonId, L as batteryCapability, Xt as errMsg, Zt as BaseAddon, gn as nodePin, i as BatteryStatusSchema, rn as DeviceType, tn as DeviceFeature } from "../../dist-4MS1GNc8.mjs";
2
- import { i as renderCourtesyOverlayJpeg, n as courtesyCacheKey, r as renderCourtesyJpeg } from "../../snapshot-courtesy-LoJNgHHZ.mjs";
2
+ import { i as renderCourtesyOverlayJpeg, n as courtesyCacheKey, r as renderCourtesyJpeg } from "../../snapshot-courtesy-CZPvteq2.mjs";
3
3
  import { z } from "zod";
4
4
  import { randomUUID } from "node:crypto";
5
5
  import { signExpiringUrl, verifyExpiringUrl } from "@camstack/types/node";
@@ -36,8 +36,18 @@ export interface CourtesyFrameSpec {
36
36
  */
37
37
  export declare function buildCourtesySvg(spec: CourtesyFrameSpec): string;
38
38
  /**
39
- * The same state treatment as a courtesy frame, but translucent so the last
40
- * real camera frame remains visible underneath it.
39
+ * The state treatment for a frame that HAS a picture under it: a band along the
40
+ * bottom, and nothing else touched.
41
+ *
42
+ * It was a full-frame wash at 0.62 opacity, under a docblock claiming the frame
43
+ * "remains visible underneath". A 38 % view of a dark room is not a view of it,
44
+ * and the operator read the result as a placeholder rather than as their own
45
+ * camera: *"ma perché Waking? Dovremmo mostrare l'ultimo snapshot
46
+ * disponibile"* (Baby monitor, 2026-09-16).
47
+ *
48
+ * The marker still has to earn its place — a stale frame shown clean gets
49
+ * mistaken for live, which is the reason the treatment exists at all. A band
50
+ * says the same thing a wash said. Covering the picture was never the message.
41
51
  */
42
52
  export declare function buildCourtesyOverlaySvg(spec: CourtesyFrameSpec): string;
43
53
  /** Cache key — a courtesy frame is a pure function of these four. */
@@ -76,26 +76,53 @@ function escapeCourtesyText(value) {
76
76
  * frame read the same, with a floor so a thumbnail stays legible.
77
77
  */
78
78
  function buildCourtesySvg(spec) {
79
- return buildStateSvg(spec, false);
79
+ return buildStateSvg(spec);
80
80
  }
81
81
  /**
82
- * The same state treatment as a courtesy frame, but translucent so the last
83
- * real camera frame remains visible underneath it.
82
+ * The state treatment for a frame that HAS a picture under it: a band along the
83
+ * bottom, and nothing else touched.
84
+ *
85
+ * It was a full-frame wash at 0.62 opacity, under a docblock claiming the frame
86
+ * "remains visible underneath". A 38 % view of a dark room is not a view of it,
87
+ * and the operator read the result as a placeholder rather than as their own
88
+ * camera: *"ma perché Waking? Dovremmo mostrare l'ultimo snapshot
89
+ * disponibile"* (Baby monitor, 2026-09-16).
90
+ *
91
+ * The marker still has to earn its place — a stale frame shown clean gets
92
+ * mistaken for live, which is the reason the treatment exists at all. A band
93
+ * says the same thing a wash said. Covering the picture was never the message.
84
94
  */
85
95
  function buildCourtesyOverlaySvg(spec) {
86
- return buildStateSvg(spec, true);
96
+ const state = escapeCourtesyText(courtesyLabel(spec.reason));
97
+ const name = escapeCourtesyText(spec.deviceName);
98
+ const stateSize = Math.max(11, Math.round(spec.width / 34));
99
+ const bandHeight = Math.max(26, Math.round(stateSize * 2.2));
100
+ const bandTop = Math.max(0, spec.height - bandHeight);
101
+ const baselineY = Math.round(bandTop + bandHeight * .68);
102
+ const textStroke = Math.max(1, Math.round(spec.width / 320));
103
+ return [
104
+ `<svg xmlns="http://www.w3.org/2000/svg" width="${String(spec.width)}" height="${String(spec.height)}">`,
105
+ `<rect x="0" y="${String(bandTop)}" width="${String(spec.width)}" height="${String(bandHeight)}" fill="${courtesyBackground(spec.reason)}" fill-opacity="0.82"/>`,
106
+ `<g font-family="${COURTESY_FONT_STACK}" text-anchor="middle" paint-order="stroke" stroke="#111118" stroke-width="${String(textStroke)}">`,
107
+ `<text x="50%" y="${String(baselineY)}" font-size="${String(stateSize)}" fill="#e8e8ee">${state}`,
108
+ `<tspan fill="#9a9aa8"> · ${name}</tspan>`,
109
+ `</text></g></svg>`
110
+ ].join("");
87
111
  }
88
- function buildStateSvg(spec, overlay) {
112
+ /**
113
+ * The GENERATED card: no picture exists, so this IS the picture. Opaque by
114
+ * necessity — anything translucent here shows black through it.
115
+ */
116
+ function buildStateSvg(spec) {
89
117
  const stateSize = Math.max(12, Math.round(spec.width / 12));
90
118
  const nameSize = Math.max(9, Math.round(spec.width / 26));
91
119
  const state = escapeCourtesyText(courtesyLabel(spec.reason));
92
120
  const name = escapeCourtesyText(spec.deviceName);
93
121
  const midY = spec.height / 2;
94
- const washOpacity = overlay ? "0.62" : "1";
95
122
  const textStroke = Math.max(1, Math.round(spec.width / 320));
96
123
  return [
97
124
  `<svg xmlns="http://www.w3.org/2000/svg" width="${String(spec.width)}" height="${String(spec.height)}">`,
98
- `<rect width="100%" height="100%" fill="${courtesyBackground(spec.reason)}" fill-opacity="${washOpacity}"/>`,
125
+ `<rect width="100%" height="100%" fill="${courtesyBackground(spec.reason)}" fill-opacity="1"/>`,
99
126
  `<g font-family="${COURTESY_FONT_STACK}" text-anchor="middle" paint-order="stroke" stroke="#111118" stroke-width="${String(textStroke)}">`,
100
127
  `<text x="50%" y="${String(Math.round(midY))}" font-size="${String(stateSize)}" fill="#e8e8ee">${state}</text>`,
101
128
  `<text x="50%" y="${String(Math.round(midY + stateSize))}" font-size="${String(nameSize)}" fill="#9a9aa8">${name}</text>`,
@@ -78,26 +78,53 @@ function escapeCourtesyText(value) {
78
78
  * frame read the same, with a floor so a thumbnail stays legible.
79
79
  */
80
80
  function buildCourtesySvg(spec) {
81
- return buildStateSvg(spec, false);
81
+ return buildStateSvg(spec);
82
82
  }
83
83
  /**
84
- * The same state treatment as a courtesy frame, but translucent so the last
85
- * real camera frame remains visible underneath it.
84
+ * The state treatment for a frame that HAS a picture under it: a band along the
85
+ * bottom, and nothing else touched.
86
+ *
87
+ * It was a full-frame wash at 0.62 opacity, under a docblock claiming the frame
88
+ * "remains visible underneath". A 38 % view of a dark room is not a view of it,
89
+ * and the operator read the result as a placeholder rather than as their own
90
+ * camera: *"ma perché Waking? Dovremmo mostrare l'ultimo snapshot
91
+ * disponibile"* (Baby monitor, 2026-09-16).
92
+ *
93
+ * The marker still has to earn its place — a stale frame shown clean gets
94
+ * mistaken for live, which is the reason the treatment exists at all. A band
95
+ * says the same thing a wash said. Covering the picture was never the message.
86
96
  */
87
97
  function buildCourtesyOverlaySvg(spec) {
88
- return buildStateSvg(spec, true);
98
+ const state = escapeCourtesyText(courtesyLabel(spec.reason));
99
+ const name = escapeCourtesyText(spec.deviceName);
100
+ const stateSize = Math.max(11, Math.round(spec.width / 34));
101
+ const bandHeight = Math.max(26, Math.round(stateSize * 2.2));
102
+ const bandTop = Math.max(0, spec.height - bandHeight);
103
+ const baselineY = Math.round(bandTop + bandHeight * .68);
104
+ const textStroke = Math.max(1, Math.round(spec.width / 320));
105
+ return [
106
+ `<svg xmlns="http://www.w3.org/2000/svg" width="${String(spec.width)}" height="${String(spec.height)}">`,
107
+ `<rect x="0" y="${String(bandTop)}" width="${String(spec.width)}" height="${String(bandHeight)}" fill="${courtesyBackground(spec.reason)}" fill-opacity="0.82"/>`,
108
+ `<g font-family="${COURTESY_FONT_STACK}" text-anchor="middle" paint-order="stroke" stroke="#111118" stroke-width="${String(textStroke)}">`,
109
+ `<text x="50%" y="${String(baselineY)}" font-size="${String(stateSize)}" fill="#e8e8ee">${state}`,
110
+ `<tspan fill="#9a9aa8"> · ${name}</tspan>`,
111
+ `</text></g></svg>`
112
+ ].join("");
89
113
  }
90
- function buildStateSvg(spec, overlay) {
114
+ /**
115
+ * The GENERATED card: no picture exists, so this IS the picture. Opaque by
116
+ * necessity — anything translucent here shows black through it.
117
+ */
118
+ function buildStateSvg(spec) {
91
119
  const stateSize = Math.max(12, Math.round(spec.width / 12));
92
120
  const nameSize = Math.max(9, Math.round(spec.width / 26));
93
121
  const state = escapeCourtesyText(courtesyLabel(spec.reason));
94
122
  const name = escapeCourtesyText(spec.deviceName);
95
123
  const midY = spec.height / 2;
96
- const washOpacity = overlay ? "0.62" : "1";
97
124
  const textStroke = Math.max(1, Math.round(spec.width / 320));
98
125
  return [
99
126
  `<svg xmlns="http://www.w3.org/2000/svg" width="${String(spec.width)}" height="${String(spec.height)}">`,
100
- `<rect width="100%" height="100%" fill="${courtesyBackground(spec.reason)}" fill-opacity="${washOpacity}"/>`,
127
+ `<rect width="100%" height="100%" fill="${courtesyBackground(spec.reason)}" fill-opacity="1"/>`,
101
128
  `<g font-family="${COURTESY_FONT_STACK}" text-anchor="middle" paint-order="stroke" stroke="#111118" stroke-width="${String(textStroke)}">`,
102
129
  `<text x="50%" y="${String(Math.round(midY))}" font-size="${String(stateSize)}" fill="#e8e8ee">${state}</text>`,
103
130
  `<text x="50%" y="${String(Math.round(midY + stateSize))}" font-size="${String(nameSize)}" fill="#9a9aa8">${name}</text>`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/system",
3
- "version": "1.2.244",
3
+ "version": "1.2.245",
4
4
  "description": "Core addon for CamStack — builtins, pipeline, process management, auth, logging, events",
5
5
  "keywords": [
6
6
  "camstack",