← back to Letsbegin

app/api/processes/stop/route.ts

72 lines

import { NextRequest, NextResponse } from 'next/server'
import { execSync } from 'child_process'
import * as fs from 'fs'
import * as path from 'path'

const STATE_FILE = '/tmp/ralph-state.json'

export async function POST(request: NextRequest) {
  try {
    const { projectPath, project, pid } = await request.json()

    if (!projectPath || !project) {
      return NextResponse.json({ error: 'Missing projectPath or project' }, { status: 400 })
    }

    // Kill the process if PID provided
    if (pid && pid > 0) {
      try {
        // Try to kill the process group first
        process.kill(-pid, 'SIGTERM')
      } catch (e) {
        try {
          // Fallback to killing just the process
          process.kill(pid, 'SIGTERM')
        } catch {}
      }
    }

    // Kill any claude processes running for this project
    try {
      execSync(`pkill -f "claude.*${project}" || true`, { stdio: 'pipe' })
    } catch {}

    // Kill any ralph-runner processes
    try {
      execSync(`pkill -f "ralph-runner.*${project}" || true`, { stdio: 'pipe' })
    } catch {}

    // Update state file
    if (fs.existsSync(STATE_FILE)) {
      try {
        const state = JSON.parse(fs.readFileSync(STATE_FILE, 'utf-8'))
        if (state.project === project || state.projectPath === projectPath) {
          state.running = false
          state.logs = state.logs || []
          state.logs.push(`> Stopped by user at ${new Date().toLocaleTimeString()}`)
          fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2))
        }
      } catch {}
    }

    // Update progress.txt to mark as stopped
    const progressFile = path.join(projectPath, 'scripts', 'ralph', 'progress.txt')
    if (fs.existsSync(progressFile)) {
      let content = fs.readFileSync(progressFile, 'utf-8')
      // Replace any RUNNING status with STOPPED
      content = content.replace(/: RUNNING/g, ': STOPPED')
      content += `\n\nStopped by user at ${new Date().toISOString()}`
      fs.writeFileSync(progressFile, content)
    }

    return NextResponse.json({
      success: true,
      message: `Stopped Ralph for ${project}`
    })

  } catch (error: any) {
    console.error('Stop process error:', error)
    return NextResponse.json({ error: error.message }, { status: 500 })
  }
}