@agentdeck/bridge 1.0.1 → 1.0.3
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.
- package/assets/fm-helper/agentdeck-fm-helper +0 -0
- package/dist/apme/collector.d.ts.map +1 -1
- package/dist/apme/collector.js +5 -2
- package/dist/apme/collector.js.map +1 -1
- package/dist/apme/runner.d.ts +11 -0
- package/dist/apme/runner.d.ts.map +1 -1
- package/dist/apme/runner.js +60 -4
- package/dist/apme/runner.js.map +1 -1
- package/dist/apme/settings.d.ts +10 -0
- package/dist/apme/settings.d.ts.map +1 -1
- package/dist/apme/settings.js +14 -0
- package/dist/apme/settings.js.map +1 -1
- package/dist/awaiting-overlay.d.ts +44 -10
- package/dist/awaiting-overlay.d.ts.map +1 -1
- package/dist/awaiting-overlay.js +96 -28
- package/dist/awaiting-overlay.js.map +1 -1
- package/dist/bridge-core.d.ts +10 -0
- package/dist/bridge-core.d.ts.map +1 -1
- package/dist/bridge-core.js +47 -12
- package/dist/bridge-core.js.map +1 -1
- package/dist/card-feed.d.ts +107 -0
- package/dist/card-feed.d.ts.map +1 -0
- package/dist/card-feed.js +277 -0
- package/dist/card-feed.js.map +1 -0
- package/dist/card-modules.d.ts +87 -0
- package/dist/card-modules.d.ts.map +1 -0
- package/dist/card-modules.js +179 -0
- package/dist/card-modules.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +93 -0
- package/dist/cli.js.map +1 -1
- package/dist/daemon-server.d.ts.map +1 -1
- package/dist/daemon-server.js +1025 -50
- package/dist/daemon-server.js.map +1 -1
- package/dist/daemon-ws-client.d.ts +2 -1
- package/dist/daemon-ws-client.d.ts.map +1 -1
- package/dist/daemon-ws-client.js +2 -1
- package/dist/daemon-ws-client.js.map +1 -1
- package/dist/daemon.js +1 -1
- package/dist/device-photo.d.ts +86 -0
- package/dist/device-photo.d.ts.map +1 -0
- package/dist/device-photo.js +200 -0
- package/dist/device-photo.js.map +1 -0
- package/dist/device-voice-reply.d.ts +124 -0
- package/dist/device-voice-reply.d.ts.map +1 -0
- package/dist/device-voice-reply.js +236 -0
- package/dist/device-voice-reply.js.map +1 -0
- package/dist/device-voice.d.ts +56 -0
- package/dist/device-voice.d.ts.map +1 -0
- package/dist/device-voice.js +134 -0
- package/dist/device-voice.js.map +1 -0
- package/dist/esp32-serial.d.ts +40 -0
- package/dist/esp32-serial.d.ts.map +1 -1
- package/dist/esp32-serial.js +109 -13
- package/dist/esp32-serial.js.map +1 -1
- package/dist/foundation-models-helper.d.ts +30 -0
- package/dist/foundation-models-helper.d.ts.map +1 -1
- package/dist/foundation-models-helper.js +45 -0
- package/dist/foundation-models-helper.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/mdns.d.ts +11 -0
- package/dist/mdns.d.ts.map +1 -1
- package/dist/mdns.js +13 -0
- package/dist/mdns.js.map +1 -1
- package/dist/observed-inject.d.ts +119 -0
- package/dist/observed-inject.d.ts.map +1 -0
- package/dist/observed-inject.js +405 -0
- package/dist/observed-inject.js.map +1 -0
- package/dist/passive-observer.d.ts +14 -0
- package/dist/passive-observer.d.ts.map +1 -1
- package/dist/passive-observer.js +35 -5
- package/dist/passive-observer.js.map +1 -1
- package/dist/peripheral-mapping.d.ts +65 -0
- package/dist/peripheral-mapping.d.ts.map +1 -0
- package/dist/peripheral-mapping.js +115 -0
- package/dist/peripheral-mapping.js.map +1 -0
- package/dist/session-aggregator.d.ts +4 -1
- package/dist/session-aggregator.d.ts.map +1 -1
- package/dist/session-aggregator.js +5 -5
- package/dist/session-aggregator.js.map +1 -1
- package/dist/session-id-resolve.d.ts +17 -0
- package/dist/session-id-resolve.d.ts.map +1 -0
- package/dist/session-id-resolve.js +35 -0
- package/dist/session-id-resolve.js.map +1 -0
- package/dist/session-registry.d.ts +12 -0
- package/dist/session-registry.d.ts.map +1 -1
- package/dist/session-registry.js +31 -0
- package/dist/session-registry.js.map +1 -1
- package/dist/session-transcript-timeline.d.ts +7 -0
- package/dist/session-transcript-timeline.d.ts.map +1 -1
- package/dist/session-transcript-timeline.js +16 -6
- package/dist/session-transcript-timeline.js.map +1 -1
- package/dist/timeline-store.js +2 -2
- package/dist/timeline-store.js.map +1 -1
- package/dist/usage-event.d.ts.map +1 -1
- package/dist/usage-event.js +14 -7
- package/dist/usage-event.js.map +1 -1
- package/dist/voice.d.ts +13 -10
- package/dist/voice.d.ts.map +1 -1
- package/dist/voice.js +26 -272
- package/dist/voice.js.map +1 -1
- package/dist/ws-server.d.ts +14 -0
- package/dist/ws-server.d.ts.map +1 -1
- package/dist/ws-server.js +66 -1
- package/dist/ws-server.js.map +1 -1
- package/fm-helper/AgentDeckFMHelper.swift +303 -0
- package/package.json +3 -3
- package/dist/d200h/hid-protocol.d.ts +0 -62
- package/dist/d200h/hid-protocol.d.ts.map +0 -1
- package/dist/d200h/hid-protocol.js +0 -124
- package/dist/d200h/hid-protocol.js.map +0 -1
- package/dist/d200h/image-renderer.d.ts +0 -24
- package/dist/d200h/image-renderer.d.ts.map +0 -1
- package/dist/d200h/image-renderer.js +0 -321
- package/dist/d200h/image-renderer.js.map +0 -1
- package/dist/hook-migration.d.ts +0 -2
- package/dist/hook-migration.d.ts.map +0 -1
- package/dist/hook-migration.js +0 -104
- package/dist/hook-migration.js.map +0 -1
- package/dist/modules/d200h-module.d.ts +0 -65
- package/dist/modules/d200h-module.d.ts.map +0 -1
- package/dist/modules/d200h-module.js +0 -495
- package/dist/modules/d200h-module.js.map +0 -1
- package/dist/modules/d200h-renderer.d.ts +0 -7
- package/dist/modules/d200h-renderer.d.ts.map +0 -1
- package/dist/modules/d200h-renderer.js +0 -321
- package/dist/modules/d200h-renderer.js.map +0 -1
- package/dist/modules/trmnl-module.d.ts +0 -38
- package/dist/modules/trmnl-module.d.ts.map +0 -1
- package/dist/modules/trmnl-module.js +0 -111
- package/dist/modules/trmnl-module.js.map +0 -1
- package/dist/trmnl/byos-server.d.ts +0 -39
- package/dist/trmnl/byos-server.d.ts.map +0 -1
- package/dist/trmnl/byos-server.js +0 -301
- package/dist/trmnl/byos-server.js.map +0 -1
- package/dist/trmnl/frame-cache.d.ts +0 -37
- package/dist/trmnl/frame-cache.d.ts.map +0 -1
- package/dist/trmnl/frame-cache.js +0 -157
- package/dist/trmnl/frame-cache.js.map +0 -1
- package/dist/trmnl/image-renderer.d.ts +0 -27
- package/dist/trmnl/image-renderer.d.ts.map +0 -1
- package/dist/trmnl/image-renderer.js +0 -235
- package/dist/trmnl/image-renderer.js.map +0 -1
- package/dist/trmnl/trmnl-settings.d.ts +0 -96
- package/dist/trmnl/trmnl-settings.d.ts.map +0 -1
- package/dist/trmnl/trmnl-settings.js +0 -177
- package/dist/trmnl/trmnl-settings.js.map +0 -1
- package/dist/trmnl/trmnl-telemetry.d.ts +0 -47
- package/dist/trmnl/trmnl-telemetry.d.ts.map +0 -1
- package/dist/trmnl/trmnl-telemetry.js +0 -56
- package/dist/trmnl/trmnl-telemetry.js.map +0 -1
- package/dist/whisper-server-manager.d.ts +0 -19
- package/dist/whisper-server-manager.d.ts.map +0 -1
- package/dist/whisper-server-manager.js +0 -171
- package/dist/whisper-server-manager.js.map +0 -1
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
import { TRMNL_WIDTH, TRMNL_HEIGHT } from '@agentdeck/shared';
|
|
2
|
-
import { ensureDevice, findDeviceByMac, loadTrmnlConfig, normalizeMac, effectiveRefreshRate, effectiveImageTimeout, TRMNL_WEAK_RSSI_DBM, } from './trmnl-settings.js';
|
|
3
|
-
import { getTrmnlFrame, getTrmnlFrameByKey, forceRenderTrmnlFrame, getTrmnlActivity } from './frame-cache.js';
|
|
4
|
-
import { recordTelemetry } from './trmnl-telemetry.js';
|
|
5
|
-
import { debug, logTagged } from '../logger.js';
|
|
6
|
-
const TAG = 'trmnl-byos';
|
|
7
|
-
/** MACs currently flagged weak-signal — tracked so we log a transition, not every poll. */
|
|
8
|
-
const weakRssiMacs = new Set();
|
|
9
|
-
/**
|
|
10
|
-
* Log once when a panel's RSSI crosses into/out of the weak-link threshold. A
|
|
11
|
-
* weak/lossy WiFi link is the dominant real-world cause of the firmware's
|
|
12
|
-
* "WiFi connected / not responding" (WIFI_FAILED) screen, so this gives an
|
|
13
|
-
* operator a correlatable record — always visible (not gated behind --debug),
|
|
14
|
-
* but rate-limited to state transitions instead of spamming every poll.
|
|
15
|
-
*/
|
|
16
|
-
function noteRssiHealth(mac, rssi) {
|
|
17
|
-
const key = normalizeMac(mac);
|
|
18
|
-
if (!key)
|
|
19
|
-
return;
|
|
20
|
-
const isWeak = rssi != null && Number.isFinite(rssi) && rssi <= TRMNL_WEAK_RSSI_DBM;
|
|
21
|
-
const wasWeak = weakRssiMacs.has(key);
|
|
22
|
-
if (isWeak && !wasWeak) {
|
|
23
|
-
weakRssiMacs.add(key);
|
|
24
|
-
logTagged(TAG, `weak WiFi signal on ${key}: rssi=${rssi}dBm (<= ${TRMNL_WEAK_RSSI_DBM}dBm threshold) — ` +
|
|
25
|
-
`image_url_timeout widened; panel may show "not responding" if this persists`);
|
|
26
|
-
}
|
|
27
|
-
else if (!isWeak && wasWeak) {
|
|
28
|
-
weakRssiMacs.delete(key);
|
|
29
|
-
logTagged(TAG, `WiFi signal recovered on ${key}: rssi=${rssi ?? 'n/a'}dBm`);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
/** Test helper — clear weak-RSSI transition tracking. */
|
|
33
|
-
export function _resetWeakRssiTracking() {
|
|
34
|
-
weakRssiMacs.clear();
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Record a poll and log when the panel comes back after missing its window.
|
|
38
|
-
* A battery e-ink panel polls on the cadence we hand it; a gap of more than
|
|
39
|
-
* 2× the slow cadence (+ grace) means at least one poll round-trip failed at
|
|
40
|
-
* the network layer — exactly the moment the firmware flashes its "TRMNL not
|
|
41
|
-
* responding" screen. Logging the gap on recovery (always visible, one line
|
|
42
|
-
* per incident) gives the operator a correlatable record of every dead window.
|
|
43
|
-
*/
|
|
44
|
-
function notePollGap(mac, h, cfg) {
|
|
45
|
-
const now = Date.now();
|
|
46
|
-
const prevLastSeen = recordTelemetry(mac, h, now);
|
|
47
|
-
if (prevLastSeen == null)
|
|
48
|
-
return;
|
|
49
|
-
const gapSec = Math.round((now - prevLastSeen) / 1000);
|
|
50
|
-
const expected = Math.max(cfg.refreshRate, cfg.refreshActive);
|
|
51
|
-
if (gapSec > expected * 2 + 30) {
|
|
52
|
-
logTagged(TAG, `panel ${normalizeMac(mac)} back after ${gapSec}s silence (cadence ${expected}s) — ` +
|
|
53
|
-
`it missed ≥1 poll window; likely showed "not responding" in between ` +
|
|
54
|
-
`(rssi=${h.rssi ?? 'n/a'}dBm battery=${h.batteryVoltage ?? 'n/a'}V)`);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
// Sane device-reported resolution bounds; anything outside falls back to OG size.
|
|
58
|
-
const MIN_DIM = 120;
|
|
59
|
-
const MAX_DIM = 4000;
|
|
60
|
-
function header(req, name) {
|
|
61
|
-
const v = req.headers[name.toLowerCase()];
|
|
62
|
-
return Array.isArray(v) ? (v[0] ?? '') : (v ?? '');
|
|
63
|
-
}
|
|
64
|
-
function toNum(v) {
|
|
65
|
-
if (!v)
|
|
66
|
-
return null;
|
|
67
|
-
const n = Number(v.trim());
|
|
68
|
-
return Number.isFinite(n) ? n : null;
|
|
69
|
-
}
|
|
70
|
-
/** Parse the BYOS telemetry headers a panel sends on /api/setup + /api/display. */
|
|
71
|
-
function parseDeviceHeaders(req) {
|
|
72
|
-
const sane = (n) => (n != null && n >= MIN_DIM && n <= MAX_DIM ? Math.round(n) : null);
|
|
73
|
-
return {
|
|
74
|
-
mac: header(req, 'ID'),
|
|
75
|
-
accessToken: header(req, 'Access-Token'),
|
|
76
|
-
fwVersion: header(req, 'FW-Version'),
|
|
77
|
-
batteryVoltage: toNum(header(req, 'Battery-Voltage')),
|
|
78
|
-
rssi: toNum(header(req, 'RSSI')),
|
|
79
|
-
refreshRate: toNum(header(req, 'Refresh-Rate')),
|
|
80
|
-
width: sane(toNum(header(req, 'Width'))),
|
|
81
|
-
height: sane(toNum(header(req, 'Height'))),
|
|
82
|
-
userAgent: header(req, 'User-Agent'),
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
/** Render size for a device: its reported resolution, or the OG default. */
|
|
86
|
-
function renderSize(h) {
|
|
87
|
-
return { width: h.width ?? TRMNL_WIDTH, height: h.height ?? TRMNL_HEIGHT };
|
|
88
|
-
}
|
|
89
|
-
/** Build the image URL, qualified by resolution so the image route serves the
|
|
90
|
-
* right-sized frame. The hash is the cache-buster the firmware re-downloads on. */
|
|
91
|
-
function imageUrl(req, size, hash) {
|
|
92
|
-
return `${imageBase(req)}/trmnl/image/${size.width}x${size.height}-${hash}.png`;
|
|
93
|
-
}
|
|
94
|
-
function imageBase(req) {
|
|
95
|
-
// The device reached us at exactly this host:port — reuse it so the image_url
|
|
96
|
-
// is always resolvable from the device's perspective (no IP guessing).
|
|
97
|
-
return `http://${req.headers.host ?? 'localhost'}`;
|
|
98
|
-
}
|
|
99
|
-
function sendJson(res, status, body) {
|
|
100
|
-
const payload = JSON.stringify(body);
|
|
101
|
-
res.writeHead(status, {
|
|
102
|
-
'Content-Type': 'application/json',
|
|
103
|
-
'Cache-Control': 'no-store',
|
|
104
|
-
'Access-Control-Allow-Origin': '*',
|
|
105
|
-
});
|
|
106
|
-
res.end(payload);
|
|
107
|
-
}
|
|
108
|
-
/** GET /api/setup — enroll the device (by MAC) and hand back an api_key. */
|
|
109
|
-
export function handleTrmnlSetup(req, res) {
|
|
110
|
-
const h = parseDeviceHeaders(req);
|
|
111
|
-
const mac = h.mac;
|
|
112
|
-
if (!mac) {
|
|
113
|
-
sendJson(res, 400, { status: 400, message: 'Missing ID (MAC) header' });
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
const { device, created } = ensureDevice(mac);
|
|
117
|
-
if (!device) {
|
|
118
|
-
// autoRegister is off and this MAC isn't enrolled.
|
|
119
|
-
debug(TAG, `setup rejected for ${normalizeMac(mac)} (autoRegister off, not enrolled)`);
|
|
120
|
-
sendJson(res, 404, { status: 404, message: 'Device not enrolled. Add it to settings.trmnl.devices.' });
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
notePollGap(mac, h, loadTrmnlConfig());
|
|
124
|
-
noteRssiHealth(mac, h.rssi);
|
|
125
|
-
const size = renderSize(h);
|
|
126
|
-
if (created) {
|
|
127
|
-
debug(TAG, `enrolled TRMNL ${device.mac} as ${device.friendlyId} (${size.width}x${size.height})`);
|
|
128
|
-
forceRenderTrmnlFrame(size.width, size.height); // first served image reflects live state
|
|
129
|
-
}
|
|
130
|
-
const frame = getTrmnlFrame(size.width, size.height);
|
|
131
|
-
sendJson(res, 200, {
|
|
132
|
-
status: 200,
|
|
133
|
-
api_key: device.apiKey,
|
|
134
|
-
friendly_id: device.friendlyId,
|
|
135
|
-
image_url: imageUrl(req, size, frame.contentHash),
|
|
136
|
-
filename: frame.contentHash,
|
|
137
|
-
message: 'Welcome to AgentDeck',
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* GET /api/display — return the next image + polling cadence.
|
|
142
|
-
*
|
|
143
|
-
* NOTE: we always reply with HTTP 200; the BYOS `status` field carries the real
|
|
144
|
-
* signal (0 = show image, 202 = call /api/setup). Stock firmware treats a non-200
|
|
145
|
-
* HTTP status as an error and goes back to sleep without rendering, so HTTP 200 is
|
|
146
|
-
* required even in the "needs setup" case.
|
|
147
|
-
*/
|
|
148
|
-
export function handleTrmnlDisplay(req, res) {
|
|
149
|
-
const h = parseDeviceHeaders(req);
|
|
150
|
-
const mac = h.mac;
|
|
151
|
-
const cfg = loadTrmnlConfig();
|
|
152
|
-
const size = renderSize(h);
|
|
153
|
-
if (mac) {
|
|
154
|
-
notePollGap(mac, h, cfg);
|
|
155
|
-
noteRssiHealth(mac, h.rssi);
|
|
156
|
-
}
|
|
157
|
-
let device = mac ? findDeviceByMac(mac) : undefined;
|
|
158
|
-
if (!device) {
|
|
159
|
-
// Real devices often carry an api_key from a prior (cloud) setup and never
|
|
160
|
-
// call /api/setup again — they poll /api/display straight away. If we answer
|
|
161
|
-
// "not registered" (status 202) they just sleep/retry forever and never show
|
|
162
|
-
// a screen. So auto-enroll on first poll (when autoRegister is on) and serve
|
|
163
|
-
// a real dashboard (status 0). Only fall back to 202 when autoRegister is off.
|
|
164
|
-
if (mac && cfg.autoRegister) {
|
|
165
|
-
const r = ensureDevice(mac);
|
|
166
|
-
device = r.device;
|
|
167
|
-
if (r.created) {
|
|
168
|
-
debug(TAG, `auto-enrolled ${normalizeMac(mac)} on display poll (${size.width}x${size.height})`);
|
|
169
|
-
forceRenderTrmnlFrame(size.width, size.height);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
if (!device) {
|
|
173
|
-
// autoRegister off and unenrolled: serve a real, correctly-sized frame (the
|
|
174
|
-
// idle hero / dashboard) rather than a bogus `setup.png` the image route
|
|
175
|
-
// can't match. status 202 still tells the firmware "not fully set up".
|
|
176
|
-
const setupFrame = getTrmnlFrame(size.width, size.height);
|
|
177
|
-
debug(TAG, `display from unenrolled ${normalizeMac(mac)} (autoRegister off) — requesting setup`);
|
|
178
|
-
sendJson(res, 200, {
|
|
179
|
-
status: 202,
|
|
180
|
-
image_url: imageUrl(req, size, setupFrame.contentHash),
|
|
181
|
-
filename: setupFrame.contentHash,
|
|
182
|
-
refresh_rate: cfg.refreshRate,
|
|
183
|
-
image_url_timeout: effectiveImageTimeout(cfg, { rssi: h.rssi }),
|
|
184
|
-
special_function: 'sleep',
|
|
185
|
-
reset_firmware: false,
|
|
186
|
-
update_firmware: false,
|
|
187
|
-
firmware_url: null,
|
|
188
|
-
});
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
// Soft auth only: the MAC (ID header) identifies the device. The api_key it
|
|
193
|
-
// presents may have been issued by a previous/cloud server, so we don't
|
|
194
|
-
// hard-reject on mismatch — this is same-LAN hardware.
|
|
195
|
-
const frame = getTrmnlFrame(size.width, size.height);
|
|
196
|
-
// Adaptive cadence: poll fast while an agent is AWAITING/WORKING, slow when idle.
|
|
197
|
-
const activity = getTrmnlActivity();
|
|
198
|
-
const refreshRate = effectiveRefreshRate(cfg, activity);
|
|
199
|
-
// Widen the image-download window on a weak link so a lossy GET still finishes
|
|
200
|
-
// before the firmware shows "not responding" (WIFI_FAILED).
|
|
201
|
-
const imageTimeout = effectiveImageTimeout(cfg, { rssi: h.rssi });
|
|
202
|
-
debug(TAG, `display ${normalizeMac(mac)} ${size.width}x${size.height} hash=${frame.contentHash} ` +
|
|
203
|
-
`refresh=${refreshRate}s imageTimeout=${imageTimeout}s rssi=${h.rssi ?? 'n/a'} ` +
|
|
204
|
-
`awaiting=${activity.awaiting} working=${activity.working}`);
|
|
205
|
-
sendJson(res, 200, {
|
|
206
|
-
status: 0,
|
|
207
|
-
image_url: imageUrl(req, size, frame.contentHash),
|
|
208
|
-
filename: frame.contentHash,
|
|
209
|
-
// Number (matches the reference BYOS + firmware's uint parse), not a string.
|
|
210
|
-
refresh_rate: refreshRate,
|
|
211
|
-
// Generous, link-aware image-download window so a flaky WiFi link doesn't trip
|
|
212
|
-
// the firmware's "not responding" screen.
|
|
213
|
-
image_url_timeout: imageTimeout,
|
|
214
|
-
special_function: 'sleep',
|
|
215
|
-
reset_firmware: false,
|
|
216
|
-
update_firmware: false,
|
|
217
|
-
firmware_url: null,
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
/** GET /trmnl/image/<W>x<H>-<hash>.png — serve the 1-bit PNG for that resolution. */
|
|
221
|
-
export function handleTrmnlImage(req, res) {
|
|
222
|
-
// The URL carries the resolution (and a cache-busting hash) so we serve the
|
|
223
|
-
// right-sized frame. We ignore the hash itself — the device always wants the
|
|
224
|
-
// freshest screen for its resolution. Unknown/legacy URLs fall back to the
|
|
225
|
-
// default-size frame.
|
|
226
|
-
const pathname = (req.url || '').split('?')[0];
|
|
227
|
-
const m = /\/trmnl\/image\/(\d+)x(\d+)-[0-9a-f]+\.png$/.exec(pathname);
|
|
228
|
-
let frame;
|
|
229
|
-
if (m) {
|
|
230
|
-
const key = `${m[1]}x${m[2]}`;
|
|
231
|
-
frame = getTrmnlFrameByKey(key) ?? getTrmnlFrame(Number(m[1]), Number(m[2]));
|
|
232
|
-
}
|
|
233
|
-
if (!frame)
|
|
234
|
-
frame = getTrmnlFrame();
|
|
235
|
-
res.writeHead(200, {
|
|
236
|
-
'Content-Type': frame.contentType,
|
|
237
|
-
'Content-Length': frame.buffer.length,
|
|
238
|
-
'Cache-Control': 'no-store',
|
|
239
|
-
'Access-Control-Allow-Origin': '*',
|
|
240
|
-
});
|
|
241
|
-
res.end(frame.buffer);
|
|
242
|
-
}
|
|
243
|
-
// Device-log throttle: the firmware only POSTs /api/log when something went
|
|
244
|
-
// wrong on its side (failed poll, image timeout, low battery), so these lines
|
|
245
|
-
// ARE the root-cause record for "not responding" incidents. Always log them,
|
|
246
|
-
// but cap the rate per panel so a wedged device can't flood stderr.
|
|
247
|
-
const DEVICE_LOG_INTERVAL_MS = 10_000;
|
|
248
|
-
const lastDeviceLogAt = new Map();
|
|
249
|
-
/** Compress the firmware's log JSON into one greppable line (best effort). */
|
|
250
|
-
function summarizeDeviceLog(body) {
|
|
251
|
-
try {
|
|
252
|
-
const parsed = JSON.parse(body);
|
|
253
|
-
const arr = parsed?.log?.logs_array ?? parsed?.logs?.logs_array ?? parsed?.logs_array;
|
|
254
|
-
if (Array.isArray(arr) && arr.length > 0) {
|
|
255
|
-
return arr
|
|
256
|
-
.map((e) => `[${e?.log_codeline ?? e?.log_sourcefile ?? '?'}] ${e?.log_message ?? JSON.stringify(e)}`)
|
|
257
|
-
.join(' | ')
|
|
258
|
-
.slice(0, 600);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
catch {
|
|
262
|
-
/* not JSON — fall through to raw */
|
|
263
|
-
}
|
|
264
|
-
return body.replace(/\s+/g, ' ').slice(0, 600);
|
|
265
|
-
}
|
|
266
|
-
/** POST /api/log — the panel's own error report; always logged (rate-limited). */
|
|
267
|
-
export function handleTrmnlLog(req, res) {
|
|
268
|
-
let body = '';
|
|
269
|
-
req.on('data', (c) => {
|
|
270
|
-
body += c;
|
|
271
|
-
if (body.length > 64_000)
|
|
272
|
-
req.destroy();
|
|
273
|
-
});
|
|
274
|
-
req.on('end', () => {
|
|
275
|
-
const mac = normalizeMac(header(req, 'ID'));
|
|
276
|
-
const now = Date.now();
|
|
277
|
-
if (now - (lastDeviceLogAt.get(mac) ?? 0) >= DEVICE_LOG_INTERVAL_MS) {
|
|
278
|
-
lastDeviceLogAt.set(mac, now);
|
|
279
|
-
logTagged(TAG, `device log from ${mac}: ${summarizeDeviceLog(body)}`);
|
|
280
|
-
}
|
|
281
|
-
else {
|
|
282
|
-
debug(TAG, `device log from ${mac} (throttled): ${body.slice(0, 500)}`);
|
|
283
|
-
}
|
|
284
|
-
res.writeHead(204, { 'Access-Control-Allow-Origin': '*' });
|
|
285
|
-
res.end();
|
|
286
|
-
});
|
|
287
|
-
req.on('error', () => {
|
|
288
|
-
try {
|
|
289
|
-
res.writeHead(204);
|
|
290
|
-
res.end();
|
|
291
|
-
}
|
|
292
|
-
catch {
|
|
293
|
-
/* ignore */
|
|
294
|
-
}
|
|
295
|
-
});
|
|
296
|
-
}
|
|
297
|
-
/** True for any path this module owns, so the daemon router can delegate. */
|
|
298
|
-
export function isTrmnlImagePath(pathname) {
|
|
299
|
-
return pathname.startsWith('/trmnl/image/');
|
|
300
|
-
}
|
|
301
|
-
//# sourceMappingURL=byos-server.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"byos-server.js","sourceRoot":"","sources":["../../src/trmnl/byos-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TRMNL frame cache — the rendered 1-bit PNG dashboards the BYOS HTTP routes
|
|
3
|
-
* serve. The device module keeps them fresh by re-rendering on state change; the
|
|
4
|
-
* daemon's /api/display + /trmnl/image routes read them. Unlike push devices
|
|
5
|
-
* (Pixoo/D200H), TRMNL pulls on its own schedule, so we only hold the latest
|
|
6
|
-
* frame per resolution and let each device fetch it when it polls.
|
|
7
|
-
*
|
|
8
|
-
* Frames are keyed by `"<W>x<H>"` rather than a single global frame: different
|
|
9
|
-
* BYOS panels report different resolutions, and each must get a correctly-sized
|
|
10
|
-
* image. The map is bounded (typically one resolution is in use) to cap memory.
|
|
11
|
-
*/
|
|
12
|
-
import { type TrmnlFrame } from './image-renderer.js';
|
|
13
|
-
/** Visual-state fingerprint (excludes the wall clock so it doesn't churn). */
|
|
14
|
-
export declare function trmnlStateHash(evt: any): string;
|
|
15
|
-
/** AWAITING/WORKING counts from the last known state — drives adaptive cadence. */
|
|
16
|
-
export declare function getTrmnlActivity(): {
|
|
17
|
-
awaiting: number;
|
|
18
|
-
working: number;
|
|
19
|
-
};
|
|
20
|
-
/** Store the latest broadcast state for lazy rendering, without rendering now. */
|
|
21
|
-
export declare function setTrmnlState(evt: any): void;
|
|
22
|
-
/**
|
|
23
|
-
* Re-render every cached resolution whose visual state changed. Returns true if
|
|
24
|
-
* any new frame was produced. Called by the device module on each broadcast. If
|
|
25
|
-
* no device has polled yet, primes the default resolution so a first poll is
|
|
26
|
-
* instant.
|
|
27
|
-
*/
|
|
28
|
-
export declare function refreshTrmnlFrame(evt: any): boolean;
|
|
29
|
-
/** Force a render from the last known state for a resolution (e.g. after setup). */
|
|
30
|
-
export declare function forceRenderTrmnlFrame(width?: number, height?: number): TrmnlFrame;
|
|
31
|
-
/** Frame for a resolution, lazily rendered from the last known state if absent. */
|
|
32
|
-
export declare function getTrmnlFrame(width?: number, height?: number): TrmnlFrame;
|
|
33
|
-
/** Frame for an exact `"<W>x<H>"` key, or undefined if not cached. */
|
|
34
|
-
export declare function getTrmnlFrameByKey(key: string): TrmnlFrame | undefined;
|
|
35
|
-
/** Active resolution keys currently held in the cache. */
|
|
36
|
-
export declare function getTrmnlFrameKeys(): string[];
|
|
37
|
-
//# sourceMappingURL=frame-cache.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"frame-cache.d.ts","sourceRoot":"","sources":["../../src/trmnl/frame-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAsCxE,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CA+B/C;AAED,mFAAmF;AACnF,wBAAgB,gBAAgB,IAAI;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAUxE;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAE5C;AAuBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAcnD;AAED,oFAAoF;AACpF,wBAAgB,qBAAqB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,UAAU,CAEjF;AAED,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,UAAU,CAGzE;AAED,sEAAsE;AACtE,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAEtE;AAED,0DAA0D;AAC1D,wBAAgB,iBAAiB,IAAI,MAAM,EAAE,CAE5C"}
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TRMNL frame cache — the rendered 1-bit PNG dashboards the BYOS HTTP routes
|
|
3
|
-
* serve. The device module keeps them fresh by re-rendering on state change; the
|
|
4
|
-
* daemon's /api/display + /trmnl/image routes read them. Unlike push devices
|
|
5
|
-
* (Pixoo/D200H), TRMNL pulls on its own schedule, so we only hold the latest
|
|
6
|
-
* frame per resolution and let each device fetch it when it polls.
|
|
7
|
-
*
|
|
8
|
-
* Frames are keyed by `"<W>x<H>"` rather than a single global frame: different
|
|
9
|
-
* BYOS panels report different resolutions, and each must get a correctly-sized
|
|
10
|
-
* image. The map is bounded (typically one resolution is in use) to cap memory.
|
|
11
|
-
*/
|
|
12
|
-
import { renderTrmnlFrame } from './image-renderer.js';
|
|
13
|
-
import { TRMNL_WIDTH, TRMNL_HEIGHT } from '@agentdeck/shared';
|
|
14
|
-
const DEFAULT_KEY = `${TRMNL_WIDTH}x${TRMNL_HEIGHT}`;
|
|
15
|
-
/** Bound on distinct resolutions held at once (insertion-order LRU eviction). */
|
|
16
|
-
const MAX_FRAMES = 8;
|
|
17
|
-
/** Resolution-keyed cache. Insertion order doubles as LRU recency. */
|
|
18
|
-
const frames = new Map();
|
|
19
|
-
const lastHashByKey = new Map();
|
|
20
|
-
let lastStateEvt = {
|
|
21
|
-
state: 'IDLE',
|
|
22
|
-
projectName: '',
|
|
23
|
-
modelName: '',
|
|
24
|
-
mode: 'default',
|
|
25
|
-
agentType: 'daemon',
|
|
26
|
-
fiveHourPercent: 0,
|
|
27
|
-
sevenDayPercent: 0,
|
|
28
|
-
totalTokens: 0,
|
|
29
|
-
totalCost: 0,
|
|
30
|
-
options: [],
|
|
31
|
-
currentTool: '',
|
|
32
|
-
allSessions: [],
|
|
33
|
-
};
|
|
34
|
-
function sizeKey(width, height) {
|
|
35
|
-
const w = width && width > 0 ? Math.round(width) : TRMNL_WIDTH;
|
|
36
|
-
const h = height && height > 0 ? Math.round(height) : TRMNL_HEIGHT;
|
|
37
|
-
return `${w}x${h}`;
|
|
38
|
-
}
|
|
39
|
-
function parseKey(key) {
|
|
40
|
-
const m = /^(\d+)x(\d+)$/.exec(key);
|
|
41
|
-
if (!m)
|
|
42
|
-
return { width: TRMNL_WIDTH, height: TRMNL_HEIGHT };
|
|
43
|
-
return { width: Number(m[1]), height: Number(m[2]) };
|
|
44
|
-
}
|
|
45
|
-
/** Visual-state fingerprint (excludes the wall clock so it doesn't churn). */
|
|
46
|
-
export function trmnlStateHash(evt) {
|
|
47
|
-
const sessions = Array.isArray(evt?.allSessions) ? evt.allSessions : [];
|
|
48
|
-
const sessKey = sessions
|
|
49
|
-
.map((s) => `${s?.id}:${s?.agentType}:${s?.state}:${s?.projectName}:${s?.modelName}:${s?.goal ?? ''}`)
|
|
50
|
-
.join('|');
|
|
51
|
-
// No wall-clock / freshness component: a real TRMNL caches by `filename` and
|
|
52
|
-
// skips the (battery + flaky-WiFi) re-download when it's unchanged. So the hash
|
|
53
|
-
// must change ONLY on real visual change — never churn it for a ticking clock.
|
|
54
|
-
return [
|
|
55
|
-
evt?.state,
|
|
56
|
-
evt?.projectName,
|
|
57
|
-
evt?.modelName,
|
|
58
|
-
evt?.usageKnown ? Math.round(evt?.fiveHourPercent ?? 0) : 'na',
|
|
59
|
-
evt?.usageKnown ? Math.round(evt?.sevenDayPercent ?? 0) : 'na',
|
|
60
|
-
// Reset windows roll over rarely — include them so a rollover re-renders the
|
|
61
|
-
// countdown, but they don't churn minute-to-minute.
|
|
62
|
-
evt?.fiveHourResetsAt ?? '',
|
|
63
|
-
evt?.sevenDayResetsAt ?? '',
|
|
64
|
-
// Codex (ChatGPT) rolling windows render a second footer row — fold them in
|
|
65
|
-
// so a Codex-only usage change still re-renders the panel (otherwise the
|
|
66
|
-
// Claude-only hash above would mask it and the TRMNL would skip the redraw).
|
|
67
|
-
evt?.codexRateLimits?.primary?.usedPercent != null
|
|
68
|
-
? Math.round(evt.codexRateLimits.primary.usedPercent)
|
|
69
|
-
: 'na',
|
|
70
|
-
evt?.codexRateLimits?.secondary?.usedPercent != null
|
|
71
|
-
? Math.round(evt.codexRateLimits.secondary.usedPercent)
|
|
72
|
-
: 'na',
|
|
73
|
-
evt?.codexRateLimits?.primary?.resetsAt ?? '',
|
|
74
|
-
evt?.codexRateLimits?.secondary?.resetsAt ?? '',
|
|
75
|
-
sessKey,
|
|
76
|
-
].join('~');
|
|
77
|
-
}
|
|
78
|
-
/** AWAITING/WORKING counts from the last known state — drives adaptive cadence. */
|
|
79
|
-
export function getTrmnlActivity() {
|
|
80
|
-
const sessions = Array.isArray(lastStateEvt?.allSessions) ? lastStateEvt.allSessions : [];
|
|
81
|
-
let awaiting = 0;
|
|
82
|
-
let working = 0;
|
|
83
|
-
for (const s of sessions) {
|
|
84
|
-
const st = String(s?.state ?? '').toLowerCase();
|
|
85
|
-
if (st.startsWith('awaiting'))
|
|
86
|
-
awaiting++;
|
|
87
|
-
else if (st === 'processing')
|
|
88
|
-
working++;
|
|
89
|
-
}
|
|
90
|
-
return { awaiting, working };
|
|
91
|
-
}
|
|
92
|
-
/** Store the latest broadcast state for lazy rendering, without rendering now. */
|
|
93
|
-
export function setTrmnlState(evt) {
|
|
94
|
-
lastStateEvt = evt;
|
|
95
|
-
}
|
|
96
|
-
/** Render (and cache) the current state for one resolution key, with LRU eviction. */
|
|
97
|
-
function renderForKey(key) {
|
|
98
|
-
const { width, height } = parseKey(key);
|
|
99
|
-
let frame = renderTrmnlFrame(lastStateEvt, undefined, { width, height });
|
|
100
|
-
// A degraded frame is a blank fallback (render threw). Keep serving the last
|
|
101
|
-
// good frame for this resolution — a stale dashboard beats an empty panel.
|
|
102
|
-
// The state hash still advances so we retry on the next real state change.
|
|
103
|
-
const prev = frames.get(key);
|
|
104
|
-
if (frame.degraded && prev && !prev.degraded)
|
|
105
|
-
frame = prev;
|
|
106
|
-
frames.delete(key); // re-insert to mark most-recently-used
|
|
107
|
-
frames.set(key, frame);
|
|
108
|
-
lastHashByKey.set(key, trmnlStateHash(lastStateEvt));
|
|
109
|
-
while (frames.size > MAX_FRAMES) {
|
|
110
|
-
const oldest = frames.keys().next().value;
|
|
111
|
-
if (oldest === undefined)
|
|
112
|
-
break;
|
|
113
|
-
frames.delete(oldest);
|
|
114
|
-
lastHashByKey.delete(oldest);
|
|
115
|
-
}
|
|
116
|
-
return frame;
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Re-render every cached resolution whose visual state changed. Returns true if
|
|
120
|
-
* any new frame was produced. Called by the device module on each broadcast. If
|
|
121
|
-
* no device has polled yet, primes the default resolution so a first poll is
|
|
122
|
-
* instant.
|
|
123
|
-
*/
|
|
124
|
-
export function refreshTrmnlFrame(evt) {
|
|
125
|
-
lastStateEvt = evt;
|
|
126
|
-
const hash = trmnlStateHash(evt);
|
|
127
|
-
if (frames.size === 0) {
|
|
128
|
-
renderForKey(DEFAULT_KEY);
|
|
129
|
-
return true;
|
|
130
|
-
}
|
|
131
|
-
let rendered = false;
|
|
132
|
-
for (const key of [...frames.keys()]) {
|
|
133
|
-
if (lastHashByKey.get(key) === hash)
|
|
134
|
-
continue;
|
|
135
|
-
renderForKey(key);
|
|
136
|
-
rendered = true;
|
|
137
|
-
}
|
|
138
|
-
return rendered;
|
|
139
|
-
}
|
|
140
|
-
/** Force a render from the last known state for a resolution (e.g. after setup). */
|
|
141
|
-
export function forceRenderTrmnlFrame(width, height) {
|
|
142
|
-
return renderForKey(sizeKey(width, height));
|
|
143
|
-
}
|
|
144
|
-
/** Frame for a resolution, lazily rendered from the last known state if absent. */
|
|
145
|
-
export function getTrmnlFrame(width, height) {
|
|
146
|
-
const key = sizeKey(width, height);
|
|
147
|
-
return frames.get(key) ?? renderForKey(key);
|
|
148
|
-
}
|
|
149
|
-
/** Frame for an exact `"<W>x<H>"` key, or undefined if not cached. */
|
|
150
|
-
export function getTrmnlFrameByKey(key) {
|
|
151
|
-
return frames.get(key);
|
|
152
|
-
}
|
|
153
|
-
/** Active resolution keys currently held in the cache. */
|
|
154
|
-
export function getTrmnlFrameKeys() {
|
|
155
|
-
return [...frames.keys()];
|
|
156
|
-
}
|
|
157
|
-
//# sourceMappingURL=frame-cache.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"frame-cache.js","sourceRoot":"","sources":["../../src/trmnl/frame-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,gBAAgB,EAAmB,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE9D,MAAM,WAAW,GAAG,GAAG,WAAW,IAAI,YAAY,EAAE,CAAC;AACrD,iFAAiF;AACjF,MAAM,UAAU,GAAG,CAAC,CAAC;AAErB,sEAAsE;AACtE,MAAM,MAAM,GAAG,IAAI,GAAG,EAAsB,CAAC;AAC7C,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;AAEhD,IAAI,YAAY,GAAQ;IACtB,KAAK,EAAE,MAAM;IACb,WAAW,EAAE,EAAE;IACf,SAAS,EAAE,EAAE;IACb,IAAI,EAAE,SAAS;IACf,SAAS,EAAE,QAAQ;IACnB,eAAe,EAAE,CAAC;IAClB,eAAe,EAAE,CAAC;IAClB,WAAW,EAAE,CAAC;IACd,SAAS,EAAE,CAAC;IACZ,OAAO,EAAE,EAAE;IACX,WAAW,EAAE,EAAE;IACf,WAAW,EAAE,EAAE;CAChB,CAAC;AAEF,SAAS,OAAO,CAAC,KAAc,EAAE,MAAe;IAC9C,MAAM,CAAC,GAAG,KAAK,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;IAC/D,MAAM,CAAC,GAAG,MAAM,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;IACnE,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;AACrB,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW;IAC3B,MAAM,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IAC5D,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACvD,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,cAAc,CAAC,GAAQ;IACrC,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IACxE,MAAM,OAAO,GAAG,QAAQ;SACrB,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,SAAS,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,WAAW,IAAI,CAAC,EAAE,SAAS,IAAI,CAAC,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;SAC1G,IAAI,CAAC,GAAG,CAAC,CAAC;IACb,6EAA6E;IAC7E,gFAAgF;IAChF,+EAA+E;IAC/E,OAAO;QACL,GAAG,EAAE,KAAK;QACV,GAAG,EAAE,WAAW;QAChB,GAAG,EAAE,SAAS;QACd,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,eAAe,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI;QAC9D,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,eAAe,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI;QAC9D,6EAA6E;QAC7E,oDAAoD;QACpD,GAAG,EAAE,gBAAgB,IAAI,EAAE;QAC3B,GAAG,EAAE,gBAAgB,IAAI,EAAE;QAC3B,4EAA4E;QAC5E,yEAAyE;QACzE,6EAA6E;QAC7E,GAAG,EAAE,eAAe,EAAE,OAAO,EAAE,WAAW,IAAI,IAAI;YAChD,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,OAAO,CAAC,WAAW,CAAC;YACrD,CAAC,CAAC,IAAI;QACR,GAAG,EAAE,eAAe,EAAE,SAAS,EAAE,WAAW,IAAI,IAAI;YAClD,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,SAAS,CAAC,WAAW,CAAC;YACvD,CAAC,CAAC,IAAI;QACR,GAAG,EAAE,eAAe,EAAE,OAAO,EAAE,QAAQ,IAAI,EAAE;QAC7C,GAAG,EAAE,eAAe,EAAE,SAAS,EAAE,QAAQ,IAAI,EAAE;QAC/C,OAAO;KACR,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACd,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,gBAAgB;IAC9B,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1F,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;QAChD,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,QAAQ,EAAE,CAAC;aACrC,IAAI,EAAE,KAAK,YAAY;YAAE,OAAO,EAAE,CAAC;IAC1C,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AAC/B,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,aAAa,CAAC,GAAQ;IACpC,YAAY,GAAG,GAAG,CAAC;AACrB,CAAC;AAED,sFAAsF;AACtF,SAAS,YAAY,CAAC,GAAW;IAC/B,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IACxC,IAAI,KAAK,GAAG,gBAAgB,CAAC,YAAY,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IACzE,6EAA6E;IAC7E,2EAA2E;IAC3E,2EAA2E;IAC3E,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,KAAK,CAAC,QAAQ,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ;QAAE,KAAK,GAAG,IAAI,CAAC;IAC3D,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,uCAAuC;IAC3D,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACvB,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;IACrD,OAAO,MAAM,CAAC,IAAI,GAAG,UAAU,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAA2B,CAAC;QAChE,IAAI,MAAM,KAAK,SAAS;YAAE,MAAM;QAChC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACtB,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAQ;IACxC,YAAY,GAAG,GAAG,CAAC;IACnB,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACtB,YAAY,CAAC,WAAW,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QACrC,IAAI,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI;YAAE,SAAS;QAC9C,YAAY,CAAC,GAAG,CAAC,CAAC;QAClB,QAAQ,GAAG,IAAI,CAAC;IAClB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,qBAAqB,CAAC,KAAc,EAAE,MAAe;IACnE,OAAO,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,aAAa,CAAC,KAAc,EAAE,MAAe;IAC3D,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACnC,OAAO,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC;AAC9C,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,OAAO,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,iBAAiB;IAC/B,OAAO,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;AAC5B,CAAC"}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/** Initialize the renderer (loads resvg-js if available). Call once at start. */
|
|
2
|
-
export declare function initTrmnlRenderer(): Promise<void>;
|
|
3
|
-
export declare function isTrmnlResvgLoaded(): boolean;
|
|
4
|
-
export interface TrmnlFrame {
|
|
5
|
-
buffer: Buffer;
|
|
6
|
-
/** Short stable hash of the image bytes — used as the BYOS `filename`. */
|
|
7
|
-
contentHash: string;
|
|
8
|
-
width: number;
|
|
9
|
-
height: number;
|
|
10
|
-
contentType: 'image/png';
|
|
11
|
-
/**
|
|
12
|
-
* True when this frame is a blank fallback (render threw or resvg missing),
|
|
13
|
-
* NOT a real dashboard. The frame cache uses this to keep serving the last
|
|
14
|
-
* good frame instead of flashing the panel to an empty white screen.
|
|
15
|
-
*/
|
|
16
|
-
degraded?: boolean;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Render the AgentDeck dashboard for the given broadcast state into a 1-bit PNG.
|
|
20
|
-
* Accepts a raw state event or a pre-parsed DashState (passed through to the
|
|
21
|
-
* shared layout). `now` may be supplied for deterministic tests.
|
|
22
|
-
*/
|
|
23
|
-
export declare function renderTrmnlFrame(stateEvt: any, now?: Date, size?: {
|
|
24
|
-
width: number;
|
|
25
|
-
height: number;
|
|
26
|
-
}): TrmnlFrame;
|
|
27
|
-
//# sourceMappingURL=image-renderer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"image-renderer.d.ts","sourceRoot":"","sources":["../../src/trmnl/image-renderer.ts"],"names":[],"mappings":"AA8EA,iFAAiF;AACjF,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAEvD;AAED,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C;AA4GD,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,WAAW,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAMD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,GAAG,EACb,GAAG,CAAC,EAAE,IAAI,EACV,IAAI,CAAC,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACvC,UAAU,CAwCZ"}
|