3 * @description Agent v3 white-labeled MeshCentral installer distribution. Provides token-based and authenticated
4 * download endpoints for Windows (EXE), Linux (shell script), and macOS (PKG) installers. Proxies requests to
5 * MeshCentral server with tenant-specific mesh IDs. Includes installation scripts for automated deployment.
6 * @module routes/agent-v3
10 * @apiDefine AgentV3Group Agent v3 (MeshCentral)
11 * White-labeled MeshCentral agent installers
15 * Agent v3 Download URLs and Installer Management
17 * This route provides white-labeled MeshCentral agent installers
18 * branded as "EverydayTech Agent v3"
21const express = require('express');
22const router = express.Router();
23const authenticateToken = require('../middleware/auth');
24const axios = require('axios');
25const jwt = require('jsonwebtoken');
26const pool = require('../services/db');
28const MESHCENTRAL_URL = process.env.MESHCENTRAL_URL || 'https://rmm-psa-meshcentral-aq48h.ondigitalocean.app';
29const JWT_SECRET = process.env.JWT_SECRET;
32 * @api {get} /api/agent-v3/download-token Generate Download Token
33 * @apiName GenerateAgentV3DownloadToken
34 * @apiGroup AgentV3Group
35 * @apiDescription Generates temporary JWT token for agent installer downloads. Token expires in 7 days and is
36 * stateless (verified via JWT signature). No authentication required. Use token in /download/:platform/:token endpoints.
37 * @apiSuccess {boolean} success Operation status (true)
38 * @apiSuccess {string} token JWT download token
39 * @apiSuccess {number} expiresIn Token lifetime in seconds (604800)
40 * @apiError 500 Token generation failed
41 * @apiExample {curl} Example:
42 * curl https://api.example.com/api/agent-v3/download-token
43 * @apiExample {json} Success-Response (200):
44 * {"success": true, "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "expiresIn": 300}
47 * Generate temporary download token (public, rate-limited)
48 * GET /api/agent-v3/download-token
50 * Returns a JWT token that expires in 7 days. The token is stateless
51 * and verified using JWT signature checking, so it persists across server restarts.
53router.get('/download-token', (req, res) => {
55 // Generate JWT token with 7 day expiry
56 const token = jwt.sign(
57 { purpose: 'agent-download', timestamp: Date.now() },
65 expiresIn: 604800 // seconds (7 days)
69 console.error('❌ [AgentV3] Error generating download token:', error);
70 res.status(500).json({ error: 'Failed to generate download token' });
74// ====================================================================================
75// DOWNLOAD ROUTES - IMPORTANT: Parametrized routes (:token) MUST come before
76// non-parametrized routes to prevent Express from matching /:token as auth route
77// ====================================================================================
79router.get('/download/windows/:token', async (req, res) => {
81 const { token } = req.params;
82 const { tenant } = req.query;
84 console.log(`📥 [AgentV3] Windows download request - Token: ${token.substring(0, 20)}..., Tenant: ${tenant}`);
86 // Verify JWT signature and expiry (JWT handles expiry automatically)
89 decoded = jwt.verify(token, JWT_SECRET);
90 console.log(`✅ [AgentV3] Token verified - Purpose: ${decoded.purpose}`);
92 console.error(`❌ [AgentV3] JWT verification failed:`, err.message);
93 return res.status(401).json({ error: 'Invalid or expired download token' });
96 // Get tenant's MeshCentral group ID
97 let meshId = process.env.MESHCENTRAL_DEFAULT_MESH_ID || '';
100 const result = await pool.query(
101 'SELECT meshcentral_group_id FROM tenants WHERE tenant_id = $1',
104 if (result.rows.length > 0 && result.rows[0].meshcentral_group_id) {
105 meshId = result.rows[0].meshcentral_group_id;
106 console.log(`✅ [AgentV3] Windows agent for tenant ${tenant} - mesh: ${meshId.substring(0, 30)}...`);
108 console.warn(`⚠️ [AgentV3] Tenant ${tenant} has no meshcentral_group_id, using default`);
111 console.error(`❌ [AgentV3] DB error fetching mesh ID:`, dbErr.message, dbErr.stack);
112 // Continue with default mesh ID
116 // Download the agent directly from MeshCentral (public endpoint, no auth required)
117 const installUrl = `${MESHCENTRAL_URL}/meshagents?id=4&meshid=${meshId}&installflags=0&meshinstall=6`;
118 console.log(`🔗 [AgentV3] Fetching from MeshCentral: ${installUrl.substring(0, 100)}...`);
120 const response = await axios({
123 responseType: 'stream',
125 'User-Agent': 'EverydayTech-RMM/3.0'
127 timeout: 30000, // 30 second timeout
128 maxRedirects: 5 // Follow redirects
131 console.log(`✅ [AgentV3] MeshCentral response received, streaming to client`);
133 res.setHeader('Content-Type', 'application/octet-stream');
134 res.setHeader('Content-Disposition', 'attachment; filename="everydaytech-agent-v3.exe"');
136 // Handle stream errors
137 response.data.on('error', (streamErr) => {
138 console.error(`❌ [AgentV3] Stream error:`, streamErr.message);
141 response.data.pipe(res);
144 console.error('❌ [AgentV3] Error downloading Windows agent:', error.message);
145 console.error('Stack:', error.stack);
146 if (!res.headersSent) {
147 res.status(500).json({ error: 'Failed to download installer', details: error.message });
153 * @api {get} /api/agent-v3/download/linux/:token Download Linux Installer (Token)
154 * @apiName DownloadLinuxAgentToken
155 * @apiGroup AgentV3Group
156 * @apiDescription Downloads Linux shell script installer using temporary token. Authenticates with MeshCentral admin
157 * credentials, fetches tenant-specific mesh ID if tenant parameter provided, and returns bash installation script.
158 * Token expires in 7 days.
159 * @apiParam {string} token Download token from /download-token endpoint
160 * @apiParam (Query) {UUID} [tenant] Tenant UUID for mesh-specific installer
161 * @apiSuccess (200) {String} script Linux installation shell script (text/plain)
162 * @apiError 401 Invalid or expired token
163 * @apiError 500 MeshCentral authentication/download error
164 * @apiExample {curl} Example:
165 * curl "https://api.example.com/api/agent-v3/download/linux/eyJhbGc...?tenant=550e8400-e29b-41d4-a716-446655440000" \
169 * Download Linux agent with temporary token
170 * GET /api/agent-v3/download/linux/:token
172router.get('/download/windows', authenticateToken, async (req, res) => {
174 const meshId = process.env.MESHCENTRAL_DEFAULT_MESH_ID || '';
175 const installUrl = `${MESHCENTRAL_URL}/meshagents?id=4&meshid=${meshId}&installflags=0&meshinstall=6`;
177 // Stream the installer from MeshCentral to the client
178 const response = await axios({
181 responseType: 'stream',
182 // MeshCentral may require these headers
184 'User-Agent': 'EverydayTech-RMM/3.0'
188 // Set appropriate headers for download
189 res.setHeader('Content-Type', 'application/octet-stream');
190 res.setHeader('Content-Disposition', 'attachment; filename="everydaytech-agent-v3.exe"');
193 response.data.pipe(res);
196 console.error('❌ [AgentV3] Error proxying Windows installer:', error.message);
197 res.status(500).json({
198 error: 'Failed to download installer',
199 details: error.message
205 * @api {get} /api/agent-v3/download/linux Download Linux Installer (Auth)
206 * @apiName DownloadLinuxAgentAuth
207 * @apiGroup AgentV3Group
208 * @apiDescription Proxies Linux shell script installer from MeshCentral with JWT authentication. Returns bash script
209 * as text/plain. Requires valid Bearer token.
210 * @apiSuccess (200) {String} script Linux installation shell script (text/plain)
211 * @apiError 401 Authentication required
212 * @apiError 500 MeshCentral proxy error
213 * @apiExample {curl} Example:
214 * curl https://api.example.com/api/agent-v3/download/linux \
215 * -H "Authorization: Bearer YOUR_TOKEN" | sudo bash
218 * Proxy download endpoint for Linux agent script (JWT authenticated)
219 * GET /api/agent-v3/download/linux
221router.get('/download/linux/:token', async (req, res) => {
223 const { token } = req.params;
224 const { tenant } = req.query;
226 console.log(`📥 [AgentV3] Linux download request - Token: ${token.substring(0, 20)}..., Tenant: ${tenant}`);
228 // Verify JWT signature and expiry
231 decoded = jwt.verify(token, JWT_SECRET);
232 console.log(`✅ [AgentV3] Token verified - Purpose: ${decoded.purpose}`);
234 console.error(`❌ [AgentV3] JWT verification failed:`, err.message);
235 return res.status(401).send('#!/bin/bash\necho "Error: Invalid or expired download token"');
238 // Get tenant's MeshCentral group ID
239 let meshId = process.env.MESHCENTRAL_DEFAULT_MESH_ID || '';
242 const result = await pool.query(
243 'SELECT meshcentral_group_id FROM tenants WHERE tenant_id = $1',
246 if (result.rows.length > 0 && result.rows[0].meshcentral_group_id) {
247 meshId = result.rows[0].meshcentral_group_id;
248 console.log(`✅ [AgentV3] Linux agent for tenant ${tenant} - mesh: ${meshId.substring(0, 30)}...`);
250 console.warn(`⚠️ [AgentV3] Tenant ${tenant} has no meshcentral_group_id, using default`);
253 console.error(`❌ [AgentV3] DB error fetching mesh ID:`, dbErr.message, dbErr.stack);
257 // Download the agent directly from MeshCentral (public endpoint, no auth required)
258 const installUrl = `${MESHCENTRAL_URL}/meshagents?script=1&id=4&meshid=${meshId}&installflags=0`;
259 console.log(`🔗 [AgentV3] Fetching from MeshCentral: ${installUrl.substring(0, 100)}...`);
261 const response = await axios({
265 'User-Agent': 'EverydayTech-RMM/3.0'
268 maxRedirects: 5 // Follow redirects
271 console.log(`✅ [AgentV3] MeshCentral response received, sending to client`);
273 res.type('text/plain');
274 res.send(response.data);
277 console.error('❌ [AgentV3] Error downloading Linux agent:', error.message);
278 console.error('Stack:', error.stack);
279 if (!res.headersSent) {
280 res.status(500).send('#!/bin/bash\necho "Error: Failed to download installer"');
286 * @api {get} /api/agent-v3/download/macos/:token Download macOS Installer (Token)
287 * @apiName DownloadMacOSAgentToken
288 * @apiGroup AgentV3Group
289 * @apiDescription Downloads macOS PKG installer using temporary token. Authenticates with MeshCentral admin credentials,
290 * fetches tenant-specific mesh ID if tenant parameter provided, and streams package file. Token expires in 7 days.
291 * @apiParam {string} token Download token from /download-token endpoint
292 * @apiParam (Query) {UUID} [tenant] Tenant UUID for mesh-specific installer
293 * @apiSuccess (200) {Binary} pkg macOS installer package (application/octet-stream)
294 * @apiError 401 Invalid or expired token
295 * @apiError 500 MeshCentral authentication/download error
296 * @apiExample {curl} Example:
297 * curl "https://api.example.com/api/agent-v3/download/macos/eyJhbGc...?tenant=550e8400-e29b-41d4-a716-446655440000" \
298 * -o everydaytech-agent-v3.pkg
301 * Download macOS agent with temporary token
302 * GET /api/agent-v3/download/macos/:token
304router.get('/download/linux', authenticateToken, async (req, res) => {
306 const meshId = process.env.MESHCENTRAL_DEFAULT_MESH_ID || '';
307 const installUrl = `${MESHCENTRAL_URL}/meshagents?script=1&id=4&meshid=${meshId}&installflags=0`;
309 const response = await axios({
313 'User-Agent': 'EverydayTech-RMM/3.0'
317 res.type('text/plain');
318 res.send(response.data);
321 console.error('❌ [AgentV3] Error proxying Linux installer:', error.message);
322 res.status(500).send('#!/bin/bash\necho "Error: Failed to download installer"');
327 * @api {get} /api/agent-v3/download/macos Download macOS Installer (Auth)
328 * @apiName DownloadMacOSAgentAuth
329 * @apiGroup AgentV3Group
330 * @apiDescription Proxies macOS PKG installer from MeshCentral with JWT authentication. Streams package file to
331 * client with "everydaytech-agent-v3.pkg" filename. Requires valid Bearer token.
332 * @apiSuccess (200) {Binary} pkg macOS installer package (application/octet-stream)
333 * @apiError 401 Authentication required
334 * @apiError 500 MeshCentral proxy error
335 * @apiExample {curl} Example:
336 * curl https://api.example.com/api/agent-v3/download/macos \
337 * -H "Authorization: Bearer YOUR_TOKEN" \
338 * -o everydaytech-agent-v3.pkg
341 * Proxy download endpoint for macOS agent (JWT authenticated)
342 * GET /api/agent-v3/download/macos
344router.get('/download/macos/:token', async (req, res) => {
346 const { token } = req.params;
347 const { tenant } = req.query;
349 console.log(`📥 [AgentV3] macOS download request - Token: ${token.substring(0, 20)}..., Tenant: ${tenant}`);
351 // Verify JWT signature and expiry
354 decoded = jwt.verify(token, JWT_SECRET);
355 console.log(`✅ [AgentV3] Token verified - Purpose: ${decoded.purpose}`);
357 console.error(`❌ [AgentV3] JWT verification failed:`, err.message);
358 return res.status(401).json({ error: 'Invalid or expired download token' });
361 // Get tenant's MeshCentral group ID
362 let meshId = process.env.MESHCENTRAL_DEFAULT_MESH_ID || '';
365 const result = await pool.query(
366 'SELECT meshcentral_group_id FROM tenants WHERE tenant_id = $1',
369 if (result.rows.length > 0 && result.rows[0].meshcentral_group_id) {
370 meshId = result.rows[0].meshcentral_group_id;
371 console.log(`✅ [AgentV3] macOS agent for tenant ${tenant} - mesh: ${meshId.substring(0, 30)}...`);
373 console.warn(`⚠️ [AgentV3] Tenant ${tenant} has no meshcentral_group_id, using default`);
376 console.error(`❌ [AgentV3] DB error fetching mesh ID:`, dbErr.message, dbErr.stack);
380 // Download the agent directly from MeshCentral (public endpoint, no auth required)
381 const installUrl = `${MESHCENTRAL_URL}/meshagents?id=4&meshid=${meshId}&installflags=0&meshinstall=16`;
382 console.log(`🔗 [AgentV3] Fetching from MeshCentral: ${installUrl.substring(0, 100)}...`);
384 const response = await axios({
387 responseType: 'stream',
389 'User-Agent': 'EverydayTech-RMM/3.0'
392 maxRedirects: 5 // Follow redirects
395 console.log(`✅ [AgentV3] MeshCentral response received, streaming to client`);
397 res.setHeader('Content-Type', 'application/octet-stream');
398 res.setHeader('Content-Disposition', 'attachment; filename="everydaytech-agent-v3.pkg"');
400 // Handle stream errors
401 response.data.on('error', (streamErr) => {
402 console.error(`❌ [AgentV3] Stream error:`, streamErr.message);
405 response.data.pipe(res);
408 console.error('❌ [AgentV3] Error downloading macOS agent:', error.message);
409 console.error('Stack:', error.stack);
410 if (!res.headersSent) {
411 res.status(500).json({ error: 'Failed to download installer', details: error.message });
417 * @api {get} /api/agent-v3/downloads Get Download URLs
418 * @apiName GetAgentV3DownloadURLs
419 * @apiGroup AgentV3Group
420 * @apiDescription Returns authenticated download URLs for all platforms and architectures. Includes installation
421 * instructions and MeshCentral server metadata. Requires JWT authentication.
422 * @apiSuccess {boolean} success Operation status (true)
423 * @apiSuccess {string} meshcentralUrl MeshCentral server URL
424 * @apiSuccess {string} meshId Default mesh ID
425 * @apiSuccess {object} downloads Platform-specific download URLs
426 * @apiSuccess {object} downloads.windows Windows download options
427 * @apiSuccess {object} downloads.windows.x64 64-bit Windows installer URL
428 * @apiSuccess {object} downloads.linux Linux download options
429 * @apiSuccess {object} downloads.macos macOS download options
430 * @apiSuccess {Object} instructions Platform-specific installation instructions
431 * @apiError 401 Authentication required
432 * @apiError 500 Server error
433 * @apiExample {curl} Example:
434 * curl https://api.example.com/api/agent-v3/downloads \
435 * -H "Authorization: Bearer YOUR_TOKEN"
436 * @apiExample {json} Success-Response (200):
439 * "meshcentralUrl": "https://mesh.example.com",
441 * "windows": {"x64": {"exe": "https://api.example.com/api/agent-v3/download/windows", "name": "EverydayTech Agent v3 (Windows 64-bit)"}}
443 * "instructions": {"windows": "Run the .exe or .msi installer as Administrator"}
447 * Get agent download URLs for all platforms
448 * GET /api/agent-v3/downloads
450router.get('/download/macos', authenticateToken, async (req, res) => {
452 const meshId = process.env.MESHCENTRAL_DEFAULT_MESH_ID || '';
453 const installUrl = `${MESHCENTRAL_URL}/meshagents?id=4&meshid=${meshId}&installflags=0&meshinstall=16`;
455 const response = await axios({
458 responseType: 'stream',
460 'User-Agent': 'EverydayTech-RMM/3.0'
464 res.setHeader('Content-Type', 'application/octet-stream');
465 res.setHeader('Content-Disposition', 'attachment; filename="everydaytech-agent-v3.pkg"');
466 response.data.pipe(res);
469 console.error('❌ [AgentV3] Error proxying macOS installer:', error.message);
470 res.status(500).json({ error: 'Failed to download installer' });
475 * @api {get} /api/agent-v3/download/windows/:token Download Windows Installer (Token)
476 * @apiName DownloadWindowsAgentToken
477 * @apiGroup AgentV3Group
478 * @apiDescription Downloads Windows EXE installer using temporary token from /download-token endpoint. Authenticates
479 * with MeshCentral admin credentials, fetches tenant-specific mesh ID from database if tenant query parameter provided,
480 * and streams installer binary. Token expires in 7 days. Logs detailed operation trace for debugging.
481 * @apiParam {string} token Download token from /download-token endpoint
482 * @apiParam (Query) {UUID} [tenant] Tenant UUID for mesh-specific installer
483 * @apiSuccess (200) {Binary} exe Windows installer binary (application/octet-stream)
484 * @apiError 401 Invalid or expired token
485 * @apiError 500 MeshCentral authentication/download error
486 * @apiExample {curl} Example:
487 * curl "https://api.example.com/api/agent-v3/download/windows/eyJhbGc...?tenant=550e8400-e29b-41d4-a716-446655440000" \
488 * -o everydaytech-agent-v3.exe
491 * Download Windows agent with temporary token
492 * GET /api/agent-v3/download/windows/:token
495router.get('/downloads', authenticateToken, async (req, res) => {
497 // MeshCentral agent download URLs
498 // Proxied through our backend with JWT authentication
500 const backendUrl = process.env.BACKEND_URL || 'https://rmm-psa-backend-t9f7k.ondigitalocean.app';
505 exe: `${backendUrl}/api/agent-v3/download/windows`,
506 msi: `${backendUrl}/api/agent-v3/download/windows`,
507 name: 'EverydayTech Agent v3 (Windows 64-bit)'
510 exe: `${backendUrl}/api/agent-v3/download/windows`,
511 name: 'EverydayTech Agent v3 (Windows 32-bit)'
516 sh: `${backendUrl}/api/agent-v3/download/linux`,
517 name: 'EverydayTech Agent v3 (Linux 64-bit)'
520 sh: `${backendUrl}/api/agent-v3/download/linux`,
521 name: 'EverydayTech Agent v3 (Linux ARM)'
526 pkg: `${backendUrl}/api/agent-v3/download/macos`,
527 name: 'EverydayTech Agent v3 (macOS Intel)'
530 pkg: `${backendUrl}/api/agent-v3/download/macos`,
531 name: 'EverydayTech Agent v3 (macOS Apple Silicon)'
538 meshcentralUrl: MESHCENTRAL_URL,
540 downloads: downloads,
542 windows: 'Run the .exe or .msi installer as Administrator',
543 linux: 'Download and run: wget -O install.sh [URL] && sudo bash install.sh',
544 macos: 'Download the .pkg file and double-click to install'
549 console.error('❌ [AgentV3] Error getting downloads:', error);
550 res.status(500).json({ error: 'Failed to get agent downloads' });
555 * @api {get} /api/agent-v3/install-script Get Linux/macOS Install Script
556 * @apiName GetAgentV3InstallScript
557 * @apiGroup AgentV3Group
558 * @apiDescription Returns bash installation script for Linux/macOS. Script generates temporary download token,
559 * downloads installer from /download/linux/:token endpoint, and executes with sudo. No authentication required.
560 * @apiSuccess (200) {String} script Bash installation script (text/plain)
561 * @apiError 500 Script generation error
562 * @apiExample {curl} Example:
563 * curl https://api.example.com/api/agent-v3/install-script | sudo bash
566 * Get agent installation script for Linux/Mac
567 * GET /api/agent-v3/install-script
569router.get('/install-script', async (req, res) => {
571 const backendUrl = process.env.BACKEND_URL || 'https://rmm-psa-backend-t9f7k.ondigitalocean.app';
573 res.type('text/plain');
574 res.send(`#!/bin/bash
575# EverydayTech Agent v3 Installation Script
577# This script downloads and installs the EverydayTech RMM Agent
578# The agent will appear in your dashboard: https://everydaytech.au
580echo "🚀 Installing EverydayTech Agent v3..."
583# Get temporary download token
584echo "Getting download token..."
585TOKEN_RESPONSE=$(curl -s "${backendUrl}/api/agent-v3/download-token")
586TOKEN=$(echo $TOKEN_RESPONSE | grep -o '"token":"[^"]*' | cut -d'"' -f4)
588if [ -z "$TOKEN" ]; then
589 echo "❌ Failed to get download token"
593# Download and run the installer
594echo "Downloading installer..."
595wget -qO- "${backendUrl}/api/agent-v3/download/linux/$TOKEN" | sudo bash
599 echo "✅ EverydayTech Agent v3 installed successfully!"
600 echo " The agent will appear in your dashboard within 30 seconds."
601 echo " Dashboard: https://everydaytech.au"
604 echo "❌ Installation failed. Please check the error messages above."
610 console.error('❌ [AgentV3] Error generating install script:', error);
611 res.status(500).send('# Error generating install script');
616 * @api {get} /api/agent-v3/install-script/windows Get Windows PowerShell Install Script
617 * @apiName GetAgentV3WindowsInstallScript
618 * @apiGroup AgentV3Group
619 * @apiDescription Returns PowerShell installation script for Windows. Script generates temporary download token,
620 * downloads EXE to %TEMP%, executes with silent flag (/S), checks service status, and cleans up. No authentication required.
621 * @apiSuccess (200) {String} script PowerShell installation script (text/plain)
622 * @apiError 500 Script generation error
623 * @apiExample {powershell} Example:
624 * iwr -useb https://api.example.com/api/agent-v3/install-script/windows | iex
627 * Get Windows PowerShell installation script
628 * GET /api/agent-v3/install-script/windows
630router.get('/install-script/windows', async (req, res) => {
632 const backendUrl = process.env.BACKEND_URL || 'https://rmm-psa-backend-t9f7k.ondigitalocean.app';
634 res.type('text/plain');
635 res.send(`# EverydayTech Agent v3 Installation Script (Windows)
637# Run this in PowerShell as Administrator:
638# iwr -useb https://rmm-psa-backend-t9f7k.ondigitalocean.app/api/agent-v3/install-script/windows | iex
640Write-Host "🚀 Installing EverydayTech Agent v3..." -ForegroundColor Cyan
643# Get temporary download token
644Write-Host "Getting download token..."
645$tokenResponse = Invoke-RestMethod -Uri "${backendUrl}/api/agent-v3/download-token"
646$token = $tokenResponse.token
649 Write-Host "❌ Failed to get download token" -ForegroundColor Red
654$installerPath = "$env:TEMP\\everydaytech-agent-v3.exe"
655Write-Host "Downloading installer..."
656Invoke-WebRequest -Uri "${backendUrl}/api/agent-v3/download/windows/$token" -OutFile $installerPath
659Write-Host "Running installer..."
660Start-Process -FilePath $installerPath -ArgumentList "/S" -Wait
662# Check if service is running
663$service = Get-Service -Name "EverydayTechAgent" -ErrorAction SilentlyContinue
664if ($service -and $service.Status -eq "Running") {
666 Write-Host "✅ EverydayTech Agent v3 installed successfully!" -ForegroundColor Green
667 Write-Host " The agent will appear in your dashboard within 30 seconds." -ForegroundColor Green
668 Write-Host " Dashboard: https://everydaytech.au" -ForegroundColor Cyan
671 Write-Host "⚠️ Installation completed but service may not be running." -ForegroundColor Yellow
672 Write-Host " Please check Windows Services for 'EverydayTech Agent'" -ForegroundColor Yellow
676Remove-Item $installerPath -Force -ErrorAction SilentlyContinue
680 console.error('❌ [AgentV3] Error generating Windows install script:', error);
681 res.status(500).send('# Error generating install script');
686 * @api {get} /api/agent-v3/config Get Agent v3 Configuration
687 * @apiName GetAgentV3Config
688 * @apiGroup AgentV3Group
689 * @apiDescription Returns agent v3 configuration including MeshCentral server URL, default mesh ID, version, and
690 * feature list (remote desktop, terminal access, file transfer, hardware inventory, auto-updates, cross-platform,
691 * real-time status, event logging). Requires JWT authentication.
692 * @apiSuccess {boolean} success Operation status (true)
693 * @apiSuccess {string} meshcentralUrl MeshCentral server URL
694 * @apiSuccess {string} meshId Default mesh ID
695 * @apiSuccess {string} version Agent version ("3.0.0")
696 * @apiSuccess {string[]} features Feature list
697 * @apiError 401 Authentication required
698 * @apiError 500 Server error
699 * @apiExample {curl} Example:
700 * curl https://api.example.com/api/agent-v3/config \
701 * -H "Authorization: Bearer YOUR_TOKEN"
702 * @apiExample {json} Success-Response (200):
705 * "meshcentralUrl": "https://mesh.example.com",
706 * "meshId": "mesh/abc123...",
707 * "version": "3.0.0",
708 * "features": ["Remote Desktop (High Performance)", "Terminal/SSH Access", "File Transfer"]
712 * Get agent configuration info
713 * GET /api/agent-v3/config
715router.get('/config', authenticateToken, async (req, res) => {
719 meshcentralUrl: MESHCENTRAL_URL,
720 meshId: process.env.MESHCENTRAL_DEFAULT_MESH_ID || 'Not configured',
723 'Remote Desktop (High Performance)',
724 'Terminal/SSH Access',
726 'System Information Collection',
727 'Hardware Inventory',
729 'Cross-Platform (Windows, Linux, macOS)',
730 'Real-time Connection Status',
733 setupRequired: !process.env.MESHCENTRAL_DEFAULT_MESH_ID,
734 setupInstructions: 'Login to MeshCentral, create a device group, and add MESHCENTRAL_DEFAULT_MESH_ID to environment variables'
737 console.error('❌ [AgentV3] Error getting config:', error);
738 res.status(500).json({ error: 'Failed to get agent config' });
742module.exports = router;