lightman-agent 1.0.4 → 1.0.6
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/agent.config.template.json +30 -30
- package/package.json +52 -52
- package/public/assets/index-CcBNCz6h.css +1 -1
- package/public/assets/index-D9QHMG8k.js +1 -0
- package/public/assets/index-H-8HDl46.js +1 -1
- package/public/assets/index-YodeiCia.css +1 -0
- package/public/assets/index-legacy-DWtNM8y7.js +41 -0
- package/public/assets/museum-map-CwVDA2z1.svg +4182 -0
- package/public/assets/polyfills-legacy-DyVYWHbW.js +4 -0
- package/public/index.html +7 -2
- package/public/templates/custom08/elements/back-button.svg +20 -0
- package/public/templates/custom08/elements/base-map-background.svg +37 -0
- package/public/templates/custom08/elements/base-map.svg +1191 -0
- package/public/templates/custom08/elements/gallery-1-2-3-info-panel.svg +236 -0
- package/public/templates/custom08/elements/gallery-4-5-6-7-info-panel.svg +266 -0
- package/public/templates/custom08/elements/gallery-8-9-info-panel.svg +274 -0
- package/public/templates/custom08/elements/gallery-labels/_nav-map-styles.css +554 -0
- package/public/templates/custom08/elements/gallery-labels/_styles.css +556 -0
- package/public/templates/custom08/elements/gallery-labels/gallery-1.svg +35 -0
- package/public/templates/custom08/elements/gallery-labels/gallery-2.svg +34 -0
- package/public/templates/custom08/elements/gallery-labels/gallery-3.svg +34 -0
- package/public/templates/custom08/elements/gallery-labels/gallery-4.svg +37 -0
- package/public/templates/custom08/elements/gallery-labels/gallery-5.svg +34 -0
- package/public/templates/custom08/elements/gallery-labels/gallery-6.svg +34 -0
- package/public/templates/custom08/elements/gallery-labels/gallery-7.svg +34 -0
- package/public/templates/custom08/elements/gallery-labels/gallery-8.svg +37 -0
- package/public/templates/custom08/elements/gallery-labels/gallery-9.svg +34 -0
- package/public/templates/custom08/elements/hand-hint.png +0 -0
- package/public/templates/custom08/elements/idle-screen-bg.svg +5 -0
- package/public/templates/custom08/elements/idle-screen-map.svg +627 -0
- package/public/templates/custom08/elements/idle-screen-text.svg +350 -0
- package/public/templates/custom08/elements/key-map-1.svg +986 -0
- package/public/templates/custom08/elements/key-map-2.svg +1018 -0
- package/public/templates/custom08/elements/key-map-3.svg +1019 -0
- package/public/templates/custom08/elements/key-map-combined.svg +1001 -0
- package/public/templates/custom08/elements/map-highlight-marker.svg +11 -0
- package/public/templates/custom08/elements/map-pin-marker.svg +15 -0
- package/public/templates/custom08/elements/map-teardrop-star-marker.svg +13 -0
- package/public/templates/custom08/elements/nav-circle-galleries-1-3.svg +21 -0
- package/public/templates/custom08/elements/nav-circle-galleries-4-7.svg +24 -0
- package/public/templates/custom08/elements/nav-circle-galleries-8-9.svg +20 -0
- package/public/templates/custom08/elements/section1-map.svg +1435 -0
- package/public/templates/custom08/elements/section2-map.svg +1724 -0
- package/public/templates/custom08/elements/section3-map.svg +1295 -0
- package/public/templates/custom08/fonts/CabinetGrotesk-Variable.ttf +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-05_at_7.23.12_PM.png +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-05_at_7.23.56_PM.png +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-05_at_7.24.24_PM.png +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.31.58_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.32.11_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.32.36_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.32.48_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.32.59_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.33.15_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.33.27_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.33.34_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.33.42_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.33.50_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.33.58_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.34.04_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.34.11_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.34.20_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.34.57_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.35.03_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.35.16_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.35.23_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/prologue-highlight.png +0 -0
- package/scripts/guardian.ps1 +75 -75
- package/scripts/install-linux.sh +134 -134
- package/scripts/install-rpi.sh +117 -117
- package/scripts/install-windows.ps1 +513 -512
- package/scripts/launch-kiosk.vbs +101 -101
- package/scripts/lightman-agent.logrotate +12 -12
- package/scripts/lightman-agent.service +38 -38
- package/scripts/lightman-shell.bat +107 -107
- package/scripts/reinstall-windows.ps1 +26 -26
- package/scripts/restore-desktop.ps1 +32 -32
- package/scripts/setup.ps1 +116 -116
- package/scripts/setup.sh +115 -115
- package/scripts/sync-display.mjs +20 -0
- package/scripts/uninstall-linux.sh +50 -50
- package/scripts/uninstall-windows.ps1 +54 -54
- package/src/commands/display.ts +177 -177
- package/src/commands/kiosk.ts +113 -113
- package/src/commands/maintenance.ts +106 -106
- package/src/commands/network.ts +129 -129
- package/src/commands/power.ts +163 -163
- package/src/commands/rpi.ts +45 -45
- package/src/commands/screenshot.ts +166 -166
- package/src/commands/serial.ts +17 -17
- package/src/commands/update.ts +124 -124
- package/src/index.ts +652 -652
- package/src/lib/config.ts +69 -69
- package/src/lib/identity.ts +40 -40
- package/src/lib/logger.ts +137 -137
- package/src/lib/platform.ts +10 -10
- package/src/lib/rpi.ts +180 -180
- package/src/lib/screens.ts +128 -128
- package/src/lib/types.ts +176 -176
- package/src/services/commands.ts +107 -107
- package/src/services/health.ts +161 -161
- package/src/services/kiosk.ts +384 -384
- package/src/services/localEvents.ts +60 -60
- package/src/services/logForwarder.ts +72 -72
- package/src/services/multiScreenKiosk.ts +324 -324
- package/src/services/oscBridge.ts +186 -186
- package/src/services/powerScheduler.ts +260 -260
- package/src/services/provisioning.ts +120 -120
- package/src/services/serialBridge.ts +230 -230
- package/src/services/serviceLauncher.ts +183 -183
- package/src/services/staticServer.ts +226 -226
- package/src/services/updater.ts +249 -249
- package/src/services/watchdog.ts +310 -310
- package/src/services/websocket.ts +152 -152
- package/tsconfig.json +28 -28
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
import { WebSocketServer, WebSocket } from 'ws';
|
|
2
|
-
import type { Logger } from '../lib/logger.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Local hardware event broadcaster.
|
|
6
|
-
* Runs a WebSocket server on localhost only so the local Chrome display
|
|
7
|
-
* can receive hardware events directly from the agent — no server round-trip.
|
|
8
|
-
*/
|
|
9
|
-
export class LocalEventServer {
|
|
10
|
-
private wss: WebSocketServer | null = null;
|
|
11
|
-
private clients: Set<WebSocket> = new Set();
|
|
12
|
-
private port: number;
|
|
13
|
-
private logger: Logger;
|
|
14
|
-
|
|
15
|
-
constructor(port: number, logger: Logger) {
|
|
16
|
-
this.port = port;
|
|
17
|
-
this.logger = logger;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
start(): void {
|
|
21
|
-
this.wss = new WebSocketServer({ host: '127.0.0.1', port: this.port });
|
|
22
|
-
|
|
23
|
-
this.wss.on('connection', (ws) => {
|
|
24
|
-
this.clients.add(ws);
|
|
25
|
-
this.logger.debug(`[LocalEvents] Display connected (total: ${this.clients.size})`);
|
|
26
|
-
|
|
27
|
-
ws.on('close', () => {
|
|
28
|
-
this.clients.delete(ws);
|
|
29
|
-
this.logger.debug(`[LocalEvents] Display disconnected (total: ${this.clients.size})`);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
ws.on('error', () => {
|
|
33
|
-
this.clients.delete(ws);
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
this.wss.on('error', (err) => {
|
|
38
|
-
this.logger.error('[LocalEvents] Server error:', err);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
this.logger.info(`[LocalEvents] Hardware event server listening on ws://127.0.0.1:${this.port}`);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
broadcast(event: Record<string, unknown>): void {
|
|
45
|
-
if (this.clients.size === 0) return;
|
|
46
|
-
const msg = JSON.stringify(event);
|
|
47
|
-
for (const ws of this.clients) {
|
|
48
|
-
if (ws.readyState === WebSocket.OPEN) {
|
|
49
|
-
ws.send(msg);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
this.logger.debug(`[LocalEvents] Broadcast to ${this.clients.size} client(s): ${event.type}`);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
stop(): void {
|
|
56
|
-
this.wss?.close();
|
|
57
|
-
this.wss = null;
|
|
58
|
-
this.clients.clear();
|
|
59
|
-
}
|
|
60
|
-
}
|
|
1
|
+
import { WebSocketServer, WebSocket } from 'ws';
|
|
2
|
+
import type { Logger } from '../lib/logger.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Local hardware event broadcaster.
|
|
6
|
+
* Runs a WebSocket server on localhost only so the local Chrome display
|
|
7
|
+
* can receive hardware events directly from the agent — no server round-trip.
|
|
8
|
+
*/
|
|
9
|
+
export class LocalEventServer {
|
|
10
|
+
private wss: WebSocketServer | null = null;
|
|
11
|
+
private clients: Set<WebSocket> = new Set();
|
|
12
|
+
private port: number;
|
|
13
|
+
private logger: Logger;
|
|
14
|
+
|
|
15
|
+
constructor(port: number, logger: Logger) {
|
|
16
|
+
this.port = port;
|
|
17
|
+
this.logger = logger;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
start(): void {
|
|
21
|
+
this.wss = new WebSocketServer({ host: '127.0.0.1', port: this.port });
|
|
22
|
+
|
|
23
|
+
this.wss.on('connection', (ws) => {
|
|
24
|
+
this.clients.add(ws);
|
|
25
|
+
this.logger.debug(`[LocalEvents] Display connected (total: ${this.clients.size})`);
|
|
26
|
+
|
|
27
|
+
ws.on('close', () => {
|
|
28
|
+
this.clients.delete(ws);
|
|
29
|
+
this.logger.debug(`[LocalEvents] Display disconnected (total: ${this.clients.size})`);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
ws.on('error', () => {
|
|
33
|
+
this.clients.delete(ws);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
this.wss.on('error', (err) => {
|
|
38
|
+
this.logger.error('[LocalEvents] Server error:', err);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
this.logger.info(`[LocalEvents] Hardware event server listening on ws://127.0.0.1:${this.port}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
broadcast(event: Record<string, unknown>): void {
|
|
45
|
+
if (this.clients.size === 0) return;
|
|
46
|
+
const msg = JSON.stringify(event);
|
|
47
|
+
for (const ws of this.clients) {
|
|
48
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
49
|
+
ws.send(msg);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
this.logger.debug(`[LocalEvents] Broadcast to ${this.clients.size} client(s): ${event.type}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
stop(): void {
|
|
56
|
+
this.wss?.close();
|
|
57
|
+
this.wss = null;
|
|
58
|
+
this.clients.clear();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -1,72 +1,72 @@
|
|
|
1
|
-
import type { WsClient } from './websocket.js';
|
|
2
|
-
import type { Logger } from '../lib/logger.js';
|
|
3
|
-
import type { LogEntry, WsMessage } from '../lib/types.js';
|
|
4
|
-
|
|
5
|
-
interface LogForwarderConfig {
|
|
6
|
-
batchIntervalMs: number;
|
|
7
|
-
maxBatchSize: number;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const DEFAULT_CONFIG: LogForwarderConfig = {
|
|
11
|
-
batchIntervalMs: 30_000,
|
|
12
|
-
maxBatchSize: 100,
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export class LogForwarder {
|
|
16
|
-
private wsClient: WsClient;
|
|
17
|
-
private logger: Logger;
|
|
18
|
-
private config: LogForwarderConfig;
|
|
19
|
-
private buffer: LogEntry[] = [];
|
|
20
|
-
private timer: NodeJS.Timeout | null = null;
|
|
21
|
-
|
|
22
|
-
constructor(wsClient: WsClient, logger: Logger, config?: Partial<LogForwarderConfig>) {
|
|
23
|
-
this.wsClient = wsClient;
|
|
24
|
-
this.logger = logger;
|
|
25
|
-
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
onLog(entry: LogEntry): void {
|
|
29
|
-
this.buffer = [...this.buffer, entry];
|
|
30
|
-
// Flush if buffer exceeds max batch size
|
|
31
|
-
if (this.buffer.length >= this.config.maxBatchSize) {
|
|
32
|
-
this.flush();
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
start(): void {
|
|
37
|
-
if (this.timer !== null) {
|
|
38
|
-
this.logger.warn('Log forwarder already running, ignoring duplicate start()');
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
this.timer = setInterval(() => {
|
|
42
|
-
this.flush();
|
|
43
|
-
}, this.config.batchIntervalMs);
|
|
44
|
-
this.logger.info(`Log forwarder started (interval: ${this.config.batchIntervalMs}ms, maxBatch: ${this.config.maxBatchSize})`);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
stop(): void {
|
|
48
|
-
if (this.timer) {
|
|
49
|
-
clearInterval(this.timer);
|
|
50
|
-
this.timer = null;
|
|
51
|
-
}
|
|
52
|
-
// Final flush
|
|
53
|
-
this.flush();
|
|
54
|
-
this.logger.info('Log forwarder stopped');
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
flush(): void {
|
|
58
|
-
if (this.buffer.length === 0) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const entries = this.buffer;
|
|
63
|
-
this.buffer = [];
|
|
64
|
-
|
|
65
|
-
const msg: WsMessage = {
|
|
66
|
-
type: 'agent:logs',
|
|
67
|
-
payload: { entries: entries as unknown as Record<string, unknown>[] } as unknown as Record<string, unknown>,
|
|
68
|
-
timestamp: Date.now(),
|
|
69
|
-
};
|
|
70
|
-
this.wsClient.send(msg);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
1
|
+
import type { WsClient } from './websocket.js';
|
|
2
|
+
import type { Logger } from '../lib/logger.js';
|
|
3
|
+
import type { LogEntry, WsMessage } from '../lib/types.js';
|
|
4
|
+
|
|
5
|
+
interface LogForwarderConfig {
|
|
6
|
+
batchIntervalMs: number;
|
|
7
|
+
maxBatchSize: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const DEFAULT_CONFIG: LogForwarderConfig = {
|
|
11
|
+
batchIntervalMs: 30_000,
|
|
12
|
+
maxBatchSize: 100,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export class LogForwarder {
|
|
16
|
+
private wsClient: WsClient;
|
|
17
|
+
private logger: Logger;
|
|
18
|
+
private config: LogForwarderConfig;
|
|
19
|
+
private buffer: LogEntry[] = [];
|
|
20
|
+
private timer: NodeJS.Timeout | null = null;
|
|
21
|
+
|
|
22
|
+
constructor(wsClient: WsClient, logger: Logger, config?: Partial<LogForwarderConfig>) {
|
|
23
|
+
this.wsClient = wsClient;
|
|
24
|
+
this.logger = logger;
|
|
25
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
onLog(entry: LogEntry): void {
|
|
29
|
+
this.buffer = [...this.buffer, entry];
|
|
30
|
+
// Flush if buffer exceeds max batch size
|
|
31
|
+
if (this.buffer.length >= this.config.maxBatchSize) {
|
|
32
|
+
this.flush();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
start(): void {
|
|
37
|
+
if (this.timer !== null) {
|
|
38
|
+
this.logger.warn('Log forwarder already running, ignoring duplicate start()');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
this.timer = setInterval(() => {
|
|
42
|
+
this.flush();
|
|
43
|
+
}, this.config.batchIntervalMs);
|
|
44
|
+
this.logger.info(`Log forwarder started (interval: ${this.config.batchIntervalMs}ms, maxBatch: ${this.config.maxBatchSize})`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
stop(): void {
|
|
48
|
+
if (this.timer) {
|
|
49
|
+
clearInterval(this.timer);
|
|
50
|
+
this.timer = null;
|
|
51
|
+
}
|
|
52
|
+
// Final flush
|
|
53
|
+
this.flush();
|
|
54
|
+
this.logger.info('Log forwarder stopped');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
flush(): void {
|
|
58
|
+
if (this.buffer.length === 0) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const entries = this.buffer;
|
|
63
|
+
this.buffer = [];
|
|
64
|
+
|
|
65
|
+
const msg: WsMessage = {
|
|
66
|
+
type: 'agent:logs',
|
|
67
|
+
payload: { entries: entries as unknown as Record<string, unknown>[] } as unknown as Record<string, unknown>,
|
|
68
|
+
timestamp: Date.now(),
|
|
69
|
+
};
|
|
70
|
+
this.wsClient.send(msg);
|
|
71
|
+
}
|
|
72
|
+
}
|