feat: agent version tracking, update button, device test, COM port list

- Migration 043: agent_version in workstations, netup device type
- agent-ws: sendCommandAndWait for async commands, save version on hello
- workstations route: list-ports, test-device, update, update-all endpoints
- agent-release route: GET /api/agents/latest-release reads latest.yml
- app.ts: serve /agent-updates/ static files
- api.ts: fix camelCase→snake_case for outgoing requests (fixes null:null)
- api.ts: new methods testDevice, sendUpdate, updateAll, listPorts
- EquipmentPage: version badge, update button, test (zap) button per device
- EquipmentPage: COM-port dropdown loaded from agent when online

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-27 13:05:23 +03:00
parent b2b2034f4c
commit 0cce5f566f
7 changed files with 427 additions and 53 deletions

View File

@@ -35,6 +35,7 @@ import scheduleRoutes from './routes/schedule'
import loyaltyRoutes from './routes/loyalty'
import chatRoutes from './routes/chat'
import workstationRoutes from './routes/workstations'
import agentReleaseRoutes from './routes/agent-release'
import { setupAgentWsRoute } from './agent-ws'
import { startJobs } from './jobs'
@@ -53,6 +54,8 @@ export async function buildApp() {
await fastify.register(multipart)
const uploadsDir = process.env.UPLOADS_DIR ?? join(process.cwd(), 'uploads')
await fastify.register(staticFiles, { root: uploadsDir, prefix: '/uploads/' })
const agentUpdatesDir = process.env.AGENT_UPDATES_DIR ?? join(process.cwd(), '..', 'agent-updates')
await fastify.register(staticFiles, { root: agentUpdatesDir, prefix: '/agent-updates/', decorateReply: false })
// ── WebSocket ──────────────────────────────────────────────────────────────
await fastify.register(fastifyWebsocket)
@@ -118,6 +121,7 @@ export async function buildApp() {
await fastify.register(loyaltyRoutes)
await fastify.register(chatRoutes)
await fastify.register(workstationRoutes)
await fastify.register(agentReleaseRoutes)
await fastify.register(setupAgentWsRoute)
startJobs()