| "use server"; |
|
|
| import { NextResponse } from "next/server"; |
| import { exec } from "child_process"; |
| import { promisify } from "util"; |
| import fs from "fs/promises"; |
| import path from "path"; |
| import os from "os"; |
|
|
| const execAsync = promisify(exec); |
|
|
| |
| const getClaudeSettingsPath = () => { |
| const homeDir = os.homedir(); |
| return path.join(homeDir, ".claude", "settings.json"); |
| }; |
|
|
|
|
| |
| const checkClaudeInstalled = async () => { |
| try { |
| const isWindows = os.platform() === "win32"; |
| const command = isWindows ? "where claude" : "which claude"; |
| const env = isWindows |
| ? { ...process.env, PATH: `${process.env.APPDATA}\\npm;${process.env.PATH}` } |
| : process.env; |
| await execAsync(command, { windowsHide: true, env }); |
| return true; |
| } catch { |
| try { |
| await fs.access(getClaudeSettingsPath()); |
| return true; |
| } catch { |
| return false; |
| } |
| } |
| }; |
|
|
| |
| const readSettings = async () => { |
| try { |
| const settingsPath = getClaudeSettingsPath(); |
| const content = await fs.readFile(settingsPath, "utf-8"); |
| return JSON.parse(content); |
| } catch (error) { |
| if (error.code === "ENOENT") { |
| return null; |
| } |
| throw error; |
| } |
| }; |
|
|
| |
| export async function GET() { |
| try { |
| const isInstalled = await checkClaudeInstalled(); |
| |
| if (!isInstalled) { |
| return NextResponse.json({ |
| installed: false, |
| settings: null, |
| message: "Claude CLI is not installed", |
| }); |
| } |
|
|
| const settings = await readSettings(); |
| const has9Router = !!(settings?.env?.ANTHROPIC_BASE_URL); |
|
|
| return NextResponse.json({ |
| installed: true, |
| settings: settings, |
| has9Router: has9Router, |
| settingsPath: getClaudeSettingsPath(), |
| }); |
| } catch (error) { |
| console.log("Error checking claude settings:", error); |
| return NextResponse.json( |
| { error: "Failed to check claude settings" }, |
| { status: 500 } |
| ); |
| } |
| } |
|
|
| |
| export async function POST(request) { |
| try { |
| const { env } = await request.json(); |
| |
| if (!env || typeof env !== "object") { |
| return NextResponse.json( |
| { error: "Invalid env object" }, |
| { status: 400 } |
| ); |
| } |
|
|
| const settingsPath = getClaudeSettingsPath(); |
| const claudeDir = path.dirname(settingsPath); |
|
|
| |
| await fs.mkdir(claudeDir, { recursive: true }); |
|
|
| |
| let currentSettings = {}; |
| try { |
| const content = await fs.readFile(settingsPath, "utf-8"); |
| currentSettings = JSON.parse(content); |
| } catch (error) { |
| if (error.code !== "ENOENT") { |
| throw error; |
| } |
| } |
|
|
| |
| if (env.ANTHROPIC_BASE_URL) { |
| env.ANTHROPIC_BASE_URL = env.ANTHROPIC_BASE_URL.endsWith("/v1") |
| ? env.ANTHROPIC_BASE_URL |
| : `${env.ANTHROPIC_BASE_URL}/v1`; |
| } |
|
|
| |
| const newSettings = { |
| ...currentSettings, |
| hasCompletedOnboarding: true, |
| env: { |
| ...(currentSettings.env || {}), |
| ...env, |
| }, |
| }; |
|
|
| |
| await fs.writeFile(settingsPath, JSON.stringify(newSettings, null, 2)); |
|
|
| return NextResponse.json({ |
| success: true, |
| message: "Settings updated successfully", |
| }); |
| } catch (error) { |
| console.log("Error updating claude settings:", error); |
| return NextResponse.json( |
| { error: "Failed to update claude settings" }, |
| { status: 500 } |
| ); |
| } |
| } |
|
|
| |
| const RESET_ENV_KEYS = [ |
| "ANTHROPIC_BASE_URL", |
| "ANTHROPIC_AUTH_TOKEN", |
| "ANTHROPIC_DEFAULT_OPUS_MODEL", |
| "ANTHROPIC_DEFAULT_SONNET_MODEL", |
| "ANTHROPIC_DEFAULT_HAIKU_MODEL", |
| "API_TIMEOUT_MS", |
| ]; |
|
|
| |
| export async function DELETE() { |
| try { |
| const settingsPath = getClaudeSettingsPath(); |
|
|
| |
| let currentSettings = {}; |
| try { |
| const content = await fs.readFile(settingsPath, "utf-8"); |
| currentSettings = JSON.parse(content); |
| } catch (error) { |
| if (error.code === "ENOENT") { |
| return NextResponse.json({ |
| success: true, |
| message: "No settings file to reset", |
| }); |
| } |
| throw error; |
| } |
|
|
| |
| if (currentSettings.env) { |
| RESET_ENV_KEYS.forEach((key) => { |
| delete currentSettings.env[key]; |
| }); |
| |
| |
| if (Object.keys(currentSettings.env).length === 0) { |
| delete currentSettings.env; |
| } |
| } |
|
|
| |
| await fs.writeFile(settingsPath, JSON.stringify(currentSettings, null, 2)); |
|
|
| return NextResponse.json({ |
| success: true, |
| message: "Settings reset successfully", |
| }); |
| } catch (error) { |
| console.log("Error resetting claude settings:", error); |
| return NextResponse.json( |
| { error: "Failed to reset claude settings" }, |
| { status: 500 } |
| ); |
| } |
| } |
|
|
|
|