import { NextResponse } from 'next/server' import { requireRole } from '@/lib/auth' import { runOpenClaw } from '@/lib/command' import { getDatabase } from '@/lib/db' import { logger } from '@/lib/logger' export async function POST(request: Request) { const auth = requireRole(request, 'admin') if ('error' in auth) { return NextResponse.json({ error: auth.error }, { status: auth.status }) } let installedBefore: string | null = null try { const vResult = await runOpenClaw(['--version'], { timeoutMs: 3000 }) const match = vResult.stdout.match(/(\d+\.\d+\.\d+)/) if (match) installedBefore = match[1] } catch { return NextResponse.json( { error: 'OpenClaw is not installed or not reachable' }, { status: 400 } ) } try { const result = await runOpenClaw(['update', '--channel', 'stable'], { timeoutMs: 5 * 60 * 1000, }) // Read new version after update let installedAfter: string | null = null try { const vResult = await runOpenClaw(['--version'], { timeoutMs: 3000 }) const match = vResult.stdout.match(/(\d+\.\d+\.\d+)/) if (match) installedAfter = match[1] } catch { /* keep null */ } // Audit log try { const db = getDatabase() db.prepare( 'INSERT INTO audit_log (action, actor, detail) VALUES (?, ?, ?)' ).run( 'openclaw.update', auth.user.username, JSON.stringify({ previousVersion: installedBefore, newVersion: installedAfter }) ) } catch { /* non-critical */ } return NextResponse.json({ success: true, previousVersion: installedBefore, newVersion: installedAfter, output: result.stdout, }) } catch (err: any) { const detail = err?.stderr?.toString?.()?.trim() || err?.stdout?.toString?.()?.trim() || err?.message || 'Unknown error during OpenClaw update' logger.error({ err }, 'OpenClaw update failed') return NextResponse.json( { error: 'OpenClaw update failed', detail }, { status: 500 } ) } }