lightman-agent 1.0.15 → 1.0.17
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.json +2 -1
- package/agent.config.template.json +1 -0
- package/package.json +1 -1
- package/scripts/guardian.ps1 +124 -50
- package/scripts/install-windows.ps1 +90 -27
- package/scripts/setup.ps1 +22 -17
- package/src/lib/config.ts +3 -2
- package/src/lib/types.ts +1 -0
- package/src/services/provisioning.ts +4 -2
package/agent.config.json
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
"logLevel": "debug",
|
|
6
6
|
"logFile": "agent.log",
|
|
7
7
|
"identityFile": ".lightman-identity.json",
|
|
8
|
+
"pairingTimeoutSeconds": 900,
|
|
8
9
|
"kiosk": {
|
|
9
10
|
"browserPath": "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
|
|
10
11
|
"defaultUrl": "http://localhost:3403/display/a-av03",
|
|
@@ -19,4 +20,4 @@
|
|
|
19
20
|
"timezone": "Asia/Kolkata",
|
|
20
21
|
"shutdownWarningSeconds": 60
|
|
21
22
|
}
|
|
22
|
-
}
|
|
23
|
+
}
|
package/package.json
CHANGED
package/scripts/guardian.ps1
CHANGED
|
@@ -2,30 +2,88 @@
|
|
|
2
2
|
# Runs every 5 minutes via Task Scheduler.
|
|
3
3
|
# Restarts the NSSM service if it's down. Checks Chrome kiosk health.
|
|
4
4
|
|
|
5
|
-
$LogDir = "C:\ProgramData\Lightman\logs"
|
|
6
|
-
$LogFile = Join-Path $LogDir "guardian.log"
|
|
7
|
-
$ServiceName = "LightmanAgent"
|
|
8
|
-
$NssmExe = "C:\ProgramData\Lightman\nssm\nssm.exe"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
5
|
+
$LogDir = "C:\ProgramData\Lightman\logs"
|
|
6
|
+
$LogFile = Join-Path $LogDir "guardian.log"
|
|
7
|
+
$ServiceName = "LightmanAgent"
|
|
8
|
+
$NssmExe = "C:\ProgramData\Lightman\nssm\nssm.exe"
|
|
9
|
+
$InstallDir = "C:\Program Files\Lightman\Agent"
|
|
10
|
+
$ChromeDataDir = "C:\ProgramData\Lightman\chrome-kiosk"
|
|
11
|
+
|
|
12
|
+
function Write-GuardianLog($msg) {
|
|
13
|
+
$ts = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
|
14
|
+
try {
|
|
15
|
+
if (-not (Test-Path $LogDir)) { New-Item -ItemType Directory -Force -Path $LogDir | Out-Null }
|
|
14
16
|
Add-Content -Path $LogFile -Value "[$ts] $msg" -ErrorAction SilentlyContinue
|
|
15
17
|
if ((Get-Item $LogFile -ErrorAction SilentlyContinue).Length -gt 1MB) {
|
|
16
18
|
$rotated = "$LogFile.old"
|
|
17
19
|
if (Test-Path $rotated) { Remove-Item $rotated -Force }
|
|
18
20
|
Rename-Item $LogFile $rotated -Force
|
|
19
21
|
}
|
|
20
|
-
} catch { }
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
} catch { }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function Get-LightmanNodeProcesses {
|
|
26
|
+
try {
|
|
27
|
+
@(Get-CimInstance Win32_Process -Filter "Name = 'node.exe'" -ErrorAction SilentlyContinue | Where-Object {
|
|
28
|
+
$_.CommandLine -and (
|
|
29
|
+
$_.CommandLine -like "*$InstallDir*" -or
|
|
30
|
+
$_.CommandLine -match 'dist\\index\.js|src\\index\.ts|cms-agent\.js'
|
|
31
|
+
)
|
|
32
|
+
})
|
|
33
|
+
} catch {
|
|
34
|
+
@()
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function Stop-LightmanNodeProcesses {
|
|
39
|
+
$procs = Get-LightmanNodeProcesses
|
|
40
|
+
if (-not $procs -or $procs.Count -eq 0) {
|
|
41
|
+
Write-GuardianLog "No LIGHTMAN-owned node.exe process found"
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
foreach ($proc in $procs) {
|
|
46
|
+
try {
|
|
47
|
+
Stop-Process -Id $proc.ProcessId -Force -ErrorAction Stop
|
|
48
|
+
Write-GuardianLog "Stopped LIGHTMAN node.exe PID $($proc.ProcessId)"
|
|
49
|
+
} catch {
|
|
50
|
+
Write-GuardianLog "Failed to stop LIGHTMAN node.exe PID $($proc.ProcessId): $_"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function Get-LightmanShellMode {
|
|
56
|
+
$configPath = Join-Path $InstallDir "agent.config.json"
|
|
57
|
+
try {
|
|
58
|
+
if (-not (Test-Path $configPath)) { return $false }
|
|
59
|
+
$config = Get-Content $configPath -Raw | ConvertFrom-Json
|
|
60
|
+
return [bool]($config.kiosk.shellMode)
|
|
61
|
+
} catch {
|
|
62
|
+
return $false
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function Get-LightmanChromeProcesses {
|
|
67
|
+
try {
|
|
68
|
+
@(Get-CimInstance Win32_Process -Filter "Name = 'chrome.exe'" -ErrorAction SilentlyContinue | Where-Object {
|
|
69
|
+
$_.CommandLine -and (
|
|
70
|
+
$_.CommandLine -like "*$ChromeDataDir*" -or
|
|
71
|
+
$_.CommandLine -like "*chrome-kiosk*"
|
|
72
|
+
)
|
|
73
|
+
})
|
|
74
|
+
} catch {
|
|
75
|
+
@()
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
$shellMode = Get-LightmanShellMode
|
|
81
|
+
|
|
82
|
+
# 1. Check LIGHTMAN service
|
|
83
|
+
$svc = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
|
|
84
|
+
if (-not $svc) {
|
|
85
|
+
$svc = Get-Service -DisplayName "LIGHTMAN*" -ErrorAction SilentlyContinue | Select-Object -First 1
|
|
86
|
+
}
|
|
29
87
|
|
|
30
88
|
if (-not $svc) {
|
|
31
89
|
Write-GuardianLog "CRITICAL: Service not found!"
|
|
@@ -41,35 +99,51 @@ try {
|
|
|
41
99
|
} else {
|
|
42
100
|
Start-Service -Name $svc.Name -ErrorAction SilentlyContinue
|
|
43
101
|
}
|
|
44
|
-
Start-Sleep -Seconds 5
|
|
45
|
-
$svc.Refresh()
|
|
46
|
-
Write-GuardianLog "After restart: $($svc.Status)"
|
|
47
|
-
}
|
|
48
|
-
elseif ($svc.Status -in @('StartPending', 'StopPending')) {
|
|
49
|
-
Write-GuardianLog "Service
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
102
|
+
Start-Sleep -Seconds 5
|
|
103
|
+
$svc.Refresh()
|
|
104
|
+
Write-GuardianLog "After restart: $($svc.Status)"
|
|
105
|
+
}
|
|
106
|
+
elseif ($svc.Status -in @('StartPending', 'StopPending')) {
|
|
107
|
+
Write-GuardianLog "Service is $($svc.Status). Waiting before targeted restart..."
|
|
108
|
+
Start-Sleep -Seconds 15
|
|
109
|
+
$svc.Refresh()
|
|
110
|
+
if ($svc.Status -in @('StartPending', 'StopPending')) {
|
|
111
|
+
Write-GuardianLog "Service still stuck in $($svc.Status). Restarting LIGHTMAN service only."
|
|
112
|
+
Stop-LightmanNodeProcesses
|
|
113
|
+
Start-Sleep -Seconds 3
|
|
114
|
+
if (Test-Path $NssmExe) {
|
|
115
|
+
& $NssmExe restart $ServiceName 2>$null
|
|
116
|
+
} else {
|
|
117
|
+
Stop-Service -Name $svc.Name -Force -ErrorAction SilentlyContinue
|
|
118
|
+
Start-Sleep -Seconds 2
|
|
119
|
+
Start-Service -Name $svc.Name -ErrorAction SilentlyContinue
|
|
120
|
+
}
|
|
121
|
+
Start-Sleep -Seconds 5
|
|
122
|
+
$svc.Refresh()
|
|
123
|
+
Write-GuardianLog "After targeted restart: $($svc.Status)"
|
|
124
|
+
} else {
|
|
125
|
+
Write-GuardianLog "Service recovered during wait: $($svc.Status)"
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
# 2. Check Chrome kiosk
|
|
131
|
+
$chrome = Get-LightmanChromeProcesses
|
|
132
|
+
if (-not $chrome) {
|
|
133
|
+
if ($shellMode) {
|
|
134
|
+
Write-GuardianLog "LIGHTMAN kiosk Chrome not running, but shell mode is enabled. Shell will relaunch it."
|
|
135
|
+
} else {
|
|
136
|
+
$vbsPath = Join-Path $InstallDir "launch-kiosk.vbs"
|
|
137
|
+
if (Test-Path $vbsPath) {
|
|
138
|
+
Start-Sleep -Seconds 10
|
|
139
|
+
$chromeRecheck = Get-LightmanChromeProcesses
|
|
140
|
+
if (-not $chromeRecheck) {
|
|
141
|
+
Write-GuardianLog "LIGHTMAN Chrome not running. Launching via VBS..."
|
|
142
|
+
Start-Process "wscript.exe" -ArgumentList """$vbsPath""" -WindowStyle Hidden
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
} catch {
|
|
148
|
+
Write-GuardianLog "Guardian error: $_"
|
|
149
|
+
}
|
|
@@ -9,13 +9,14 @@
|
|
|
9
9
|
# powershell -ExecutionPolicy Bypass -File install-windows.ps1 -Slug "F-AV01" -Server "http://..." -ShellReplace
|
|
10
10
|
#Requires -RunAsAdministrator
|
|
11
11
|
|
|
12
|
-
param(
|
|
13
|
-
[Parameter(Mandatory=$true)] [string]$Slug,
|
|
14
|
-
[Parameter(Mandatory=$true)] [string]$Server,
|
|
15
|
-
[string]$Timezone = "Asia/Kolkata",
|
|
16
|
-
[
|
|
17
|
-
[
|
|
18
|
-
|
|
12
|
+
param(
|
|
13
|
+
[Parameter(Mandatory=$true)] [string]$Slug,
|
|
14
|
+
[Parameter(Mandatory=$true)] [string]$Server,
|
|
15
|
+
[string]$Timezone = "Asia/Kolkata",
|
|
16
|
+
[int]$PairingTimeoutSeconds = 900,
|
|
17
|
+
[string]$Username = "",
|
|
18
|
+
[switch]$ShellReplace = $false
|
|
19
|
+
)
|
|
19
20
|
|
|
20
21
|
$ErrorActionPreference = "Stop"
|
|
21
22
|
|
|
@@ -27,21 +28,83 @@ $NssmExe = "$NssmDir\nssm.exe"
|
|
|
27
28
|
$ServiceName = "LightmanAgent"
|
|
28
29
|
$GuardianTask = "LIGHTMAN Guardian"
|
|
29
30
|
$KioskTask = "LIGHTMAN Kiosk Browser"
|
|
30
|
-
$AgentTask = "LIGHTMAN Agent"
|
|
31
|
-
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
32
|
-
$AgentDir = Split-Path -Parent $ScriptDir
|
|
33
|
-
|
|
34
|
-
if (-not $Username) { $Username = $env:USERNAME }
|
|
31
|
+
$AgentTask = "LIGHTMAN Agent"
|
|
32
|
+
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
33
|
+
$AgentDir = Split-Path -Parent $ScriptDir
|
|
34
|
+
|
|
35
|
+
if (-not $Username) { $Username = $env:USERNAME }
|
|
36
|
+
|
|
37
|
+
function Get-LightmanNodeProcesses {
|
|
38
|
+
try {
|
|
39
|
+
@(Get-CimInstance Win32_Process -Filter "Name = 'node.exe'" -ErrorAction SilentlyContinue | Where-Object {
|
|
40
|
+
$_.CommandLine -and (
|
|
41
|
+
$_.CommandLine -like "*$InstallDir*" -or
|
|
42
|
+
$_.CommandLine -like "*$AgentDir*" -or
|
|
43
|
+
$_.CommandLine -match 'dist\\index\.js|src\\index\.ts|cms-agent\.js'
|
|
44
|
+
)
|
|
45
|
+
})
|
|
46
|
+
} catch {
|
|
47
|
+
@()
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function Stop-LightmanNodeProcesses {
|
|
52
|
+
$procs = Get-LightmanNodeProcesses
|
|
53
|
+
if (-not $procs -or $procs.Count -eq 0) {
|
|
54
|
+
Write-Host " No LIGHTMAN-owned node.exe processes found" -ForegroundColor DarkGray
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
foreach ($proc in $procs) {
|
|
59
|
+
try {
|
|
60
|
+
Stop-Process -Id $proc.ProcessId -Force -ErrorAction Stop
|
|
61
|
+
Write-Host " Stopped LIGHTMAN node.exe PID $($proc.ProcessId)" -ForegroundColor DarkGray
|
|
62
|
+
} catch {
|
|
63
|
+
Write-Host " Failed to stop LIGHTMAN node.exe PID $($proc.ProcessId): $_" -ForegroundColor Yellow
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function Get-LightmanChromeProcesses {
|
|
69
|
+
try {
|
|
70
|
+
@(Get-CimInstance Win32_Process -Filter "Name = 'chrome.exe'" -ErrorAction SilentlyContinue | Where-Object {
|
|
71
|
+
$_.CommandLine -and (
|
|
72
|
+
$_.CommandLine -like "*$ChromeData*" -or
|
|
73
|
+
$_.CommandLine -like "*chrome-kiosk*"
|
|
74
|
+
)
|
|
75
|
+
})
|
|
76
|
+
} catch {
|
|
77
|
+
@()
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function Stop-LightmanChromeProcesses {
|
|
82
|
+
$procs = Get-LightmanChromeProcesses
|
|
83
|
+
if (-not $procs -or $procs.Count -eq 0) {
|
|
84
|
+
Write-Host " No LIGHTMAN kiosk Chrome processes found" -ForegroundColor DarkGray
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
foreach ($proc in $procs) {
|
|
89
|
+
try {
|
|
90
|
+
Stop-Process -Id $proc.ProcessId -Force -ErrorAction Stop
|
|
91
|
+
Write-Host " Stopped LIGHTMAN Chrome PID $($proc.ProcessId)" -ForegroundColor DarkGray
|
|
92
|
+
} catch {
|
|
93
|
+
Write-Host " Failed to stop LIGHTMAN Chrome PID $($proc.ProcessId): $_" -ForegroundColor Yellow
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
35
97
|
|
|
36
98
|
Write-Host ""
|
|
37
99
|
Write-Host "=============================================" -ForegroundColor Cyan
|
|
38
100
|
Write-Host " LIGHTMAN Agent - Complete Windows Installer" -ForegroundColor Cyan
|
|
39
101
|
Write-Host "=============================================" -ForegroundColor Cyan
|
|
40
|
-
Write-Host " Device slug : $Slug"
|
|
41
|
-
Write-Host " Server URL : $Server"
|
|
42
|
-
Write-Host " Username : $Username"
|
|
43
|
-
Write-Host " Mode : $(if ($ShellReplace) { 'Shell Replacement' } else { 'Standard' })"
|
|
44
|
-
Write-Host ""
|
|
102
|
+
Write-Host " Device slug : $Slug"
|
|
103
|
+
Write-Host " Server URL : $Server"
|
|
104
|
+
Write-Host " Username : $Username"
|
|
105
|
+
Write-Host " Mode : $(if ($ShellReplace) { 'Shell Replacement' } else { 'Standard' })"
|
|
106
|
+
Write-Host " Pair timeout: $(if ($PairingTimeoutSeconds -eq 0) { 'Disabled' } else { "$PairingTimeoutSeconds s" })"
|
|
107
|
+
Write-Host ""
|
|
45
108
|
|
|
46
109
|
# ============================================================
|
|
47
110
|
# PHASE 0: NUKE EVERYTHING FROM PREVIOUS INSTALLS
|
|
@@ -68,11 +131,11 @@ foreach ($tn in @($AgentTask, $KioskTask, $GuardianTask)) {
|
|
|
68
131
|
if ($t) { Stop-ScheduledTask -TaskName $tn -ErrorAction SilentlyContinue; Unregister-ScheduledTask -TaskName $tn -Confirm:$false -ErrorAction SilentlyContinue }
|
|
69
132
|
}
|
|
70
133
|
|
|
71
|
-
# Kill processes
|
|
72
|
-
Write-Host "[0c]
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
Start-Sleep -Seconds 2
|
|
134
|
+
# Kill only LIGHTMAN-owned processes
|
|
135
|
+
Write-Host "[0c] Stopping LIGHTMAN node/chrome processes only..." -ForegroundColor Yellow
|
|
136
|
+
Stop-LightmanNodeProcesses
|
|
137
|
+
Stop-LightmanChromeProcesses
|
|
138
|
+
Start-Sleep -Seconds 2
|
|
76
139
|
|
|
77
140
|
# Remove old files (keep NSSM and logs)
|
|
78
141
|
Write-Host "[0d] Removing old agent files..." -ForegroundColor Yellow
|
|
@@ -142,11 +205,11 @@ Pop-Location
|
|
|
142
205
|
|
|
143
206
|
# --- 6. Generate config ---
|
|
144
207
|
Write-Host "[6/19] Generating config..." -ForegroundColor Yellow
|
|
145
|
-
if ($ShellReplace) {
|
|
146
|
-
& "$ScriptDir\setup.ps1" -Slug $Slug -Server $Server -Timezone $Timezone -InstallDir $InstallDir -ShellMode
|
|
147
|
-
} else {
|
|
148
|
-
& "$ScriptDir\setup.ps1" -Slug $Slug -Server $Server -Timezone $Timezone -InstallDir $InstallDir
|
|
149
|
-
}
|
|
208
|
+
if ($ShellReplace) {
|
|
209
|
+
& "$ScriptDir\setup.ps1" -Slug $Slug -Server $Server -Timezone $Timezone -PairingTimeoutSeconds $PairingTimeoutSeconds -InstallDir $InstallDir -ShellMode
|
|
210
|
+
} else {
|
|
211
|
+
& "$ScriptDir\setup.ps1" -Slug $Slug -Server $Server -Timezone $Timezone -PairingTimeoutSeconds $PairingTimeoutSeconds -InstallDir $InstallDir
|
|
212
|
+
}
|
|
150
213
|
|
|
151
214
|
# --- 7. Fix BOM ---
|
|
152
215
|
Write-Host "[7/19] Fixing config encoding..." -ForegroundColor Yellow
|
package/scripts/setup.ps1
CHANGED
|
@@ -15,11 +15,14 @@ param(
|
|
|
15
15
|
[Parameter(Mandatory=$true)]
|
|
16
16
|
[string]$Server,
|
|
17
17
|
|
|
18
|
-
[Parameter(Mandatory=$false)]
|
|
19
|
-
[string]$Timezone = "Asia/Kolkata",
|
|
20
|
-
|
|
21
|
-
[Parameter(Mandatory=$false)]
|
|
22
|
-
[
|
|
18
|
+
[Parameter(Mandatory=$false)]
|
|
19
|
+
[string]$Timezone = "Asia/Kolkata",
|
|
20
|
+
|
|
21
|
+
[Parameter(Mandatory=$false)]
|
|
22
|
+
[int]$PairingTimeoutSeconds = 900,
|
|
23
|
+
|
|
24
|
+
[Parameter(Mandatory=$false)]
|
|
25
|
+
[string]$InstallDir = $null,
|
|
23
26
|
|
|
24
27
|
[Parameter(Mandatory=$false)]
|
|
25
28
|
[switch]$ShellMode = $false
|
|
@@ -36,11 +39,12 @@ if (-not $InstallDir) {
|
|
|
36
39
|
|
|
37
40
|
Write-Host ""
|
|
38
41
|
Write-Host "=== LIGHTMAN Agent - Device Setup ===" -ForegroundColor Cyan
|
|
39
|
-
Write-Host " Slug: $Slug"
|
|
40
|
-
Write-Host " Server: $Server"
|
|
41
|
-
Write-Host " Install dir: $InstallDir"
|
|
42
|
-
Write-Host " Timezone: $Timezone"
|
|
43
|
-
Write-Host ""
|
|
42
|
+
Write-Host " Slug: $Slug"
|
|
43
|
+
Write-Host " Server: $Server"
|
|
44
|
+
Write-Host " Install dir: $InstallDir"
|
|
45
|
+
Write-Host " Timezone: $Timezone"
|
|
46
|
+
Write-Host " Pair timeout: $(if ($PairingTimeoutSeconds -eq 0) { 'Disabled' } else { "$PairingTimeoutSeconds s" })"
|
|
47
|
+
Write-Host ""
|
|
44
48
|
|
|
45
49
|
# 1. Clear cached identity (CRITICAL - prevents old device credentials leaking)
|
|
46
50
|
$IdentityFile = Join-Path $InstallDir ".lightman-identity.json"
|
|
@@ -83,13 +87,14 @@ $Template = Get-Content $TemplatePath -Raw
|
|
|
83
87
|
$BrowserEscaped = $BrowserPath -replace '\\', '\\'
|
|
84
88
|
$ChromeDirEscaped = $ChromeDataDir -replace '\\', '\\'
|
|
85
89
|
|
|
86
|
-
$Config = $Template `
|
|
87
|
-
-replace '__SERVER_URL__', $Server `
|
|
88
|
-
-replace '__DEVICE_SLUG__', $Slug `
|
|
89
|
-
-replace '__KIOSK_URL__', $KioskUrl `
|
|
90
|
-
-replace '__BROWSER_PATH__', $BrowserEscaped `
|
|
91
|
-
-replace '__CHROME_DATA_DIR__', $ChromeDirEscaped `
|
|
92
|
-
-replace '
|
|
90
|
+
$Config = $Template `
|
|
91
|
+
-replace '__SERVER_URL__', $Server `
|
|
92
|
+
-replace '__DEVICE_SLUG__', $Slug `
|
|
93
|
+
-replace '__KIOSK_URL__', $KioskUrl `
|
|
94
|
+
-replace '__BROWSER_PATH__', $BrowserEscaped `
|
|
95
|
+
-replace '__CHROME_DATA_DIR__', $ChromeDirEscaped `
|
|
96
|
+
-replace '__PAIRING_TIMEOUT_SECONDS__', $PairingTimeoutSeconds `
|
|
97
|
+
-replace 'Asia/Kolkata', $Timezone
|
|
93
98
|
|
|
94
99
|
# 6. Inject shellMode into kiosk config if requested
|
|
95
100
|
if ($ShellMode) {
|
package/src/lib/config.ts
CHANGED
|
@@ -32,8 +32,9 @@ const configSchema = z.object({
|
|
|
32
32
|
healthIntervalMs: z.number().int().min(5000).default(60000),
|
|
33
33
|
logLevel: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
|
|
34
34
|
logFile: z.string().default('agent.log'),
|
|
35
|
-
identityFile: z.string().default('.lightman-identity.json'),
|
|
36
|
-
|
|
35
|
+
identityFile: z.string().default('.lightman-identity.json'),
|
|
36
|
+
pairingTimeoutSeconds: z.number().int().min(0).default(900),
|
|
37
|
+
localServices: z.boolean().default(true),
|
|
37
38
|
kiosk: kioskSchema.optional(),
|
|
38
39
|
screenshot: screenshotSchema.optional(),
|
|
39
40
|
powerSchedule: powerScheduleSchema.optional(),
|
package/src/lib/types.ts
CHANGED
|
@@ -6,6 +6,7 @@ export interface AgentConfig {
|
|
|
6
6
|
logLevel: 'debug' | 'info' | 'warn' | 'error';
|
|
7
7
|
logFile: string;
|
|
8
8
|
identityFile: string;
|
|
9
|
+
pairingTimeoutSeconds?: number;
|
|
9
10
|
/** When false, agent runs in kiosk-only mode — no local server/display processes. Default: true */
|
|
10
11
|
localServices: boolean;
|
|
11
12
|
kiosk?: KioskConfig;
|
|
@@ -61,10 +61,12 @@ export async function provision(
|
|
|
61
61
|
const code = data.code as string;
|
|
62
62
|
logger.warn(`Pairing required. Enter code in admin UI: ${code}`);
|
|
63
63
|
logger.info('Waiting for admin to approve pairing...');
|
|
64
|
+
const pairingTimeoutMs = Math.max(0, config.pairingTimeoutSeconds ?? 900) * 1000;
|
|
64
65
|
|
|
65
66
|
const identity = await pollForPairing(
|
|
66
67
|
`${baseUrl}/status?code=${encodeURIComponent(code)}`,
|
|
67
|
-
logger
|
|
68
|
+
logger,
|
|
69
|
+
pairingTimeoutMs
|
|
68
70
|
);
|
|
69
71
|
|
|
70
72
|
writeIdentity(config.identityFile, identity);
|
|
@@ -81,7 +83,7 @@ async function pollForPairing(
|
|
|
81
83
|
timeoutMs = 600_000,
|
|
82
84
|
intervalMs = 5_000
|
|
83
85
|
): Promise<Identity> {
|
|
84
|
-
const deadline = Date.now() + timeoutMs;
|
|
86
|
+
const deadline = timeoutMs <= 0 ? Number.POSITIVE_INFINITY : Date.now() + timeoutMs;
|
|
85
87
|
|
|
86
88
|
while (Date.now() < deadline) {
|
|
87
89
|
await sleep(intervalMs);
|