import { existsSync, readFileSync, writeFileSync, unlinkSync, mkdirSync } from "node:fs" import { dirname, join } from "node:path" import { parseFrontmatter } from "../../shared/frontmatter" import type { RalphLoopState } from "./types" import { DEFAULT_STATE_FILE, DEFAULT_COMPLETION_PROMISE, DEFAULT_MAX_ITERATIONS } from "./constants" export function getStateFilePath(directory: string, customPath?: string): string { return customPath ? join(directory, customPath) : join(directory, DEFAULT_STATE_FILE) } export function readState(directory: string, customPath?: string): RalphLoopState | null { const filePath = getStateFilePath(directory, customPath) if (!existsSync(filePath)) { return null } try { const content = readFileSync(filePath, "utf-8") const { data, body } = parseFrontmatter>(content) const active = data.active const iteration = data.iteration if (active === undefined || iteration === undefined) { return null } const isActive = active === true || active === "true" const iterationNum = typeof iteration === "number" ? iteration : Number(iteration) if (isNaN(iterationNum)) { return null } const stripQuotes = (val: unknown): string => { const str = String(val ?? "") return str.replace(/^["']|["']$/g, "") } return { active: isActive, iteration: iterationNum, max_iterations: Number(data.max_iterations) || DEFAULT_MAX_ITERATIONS, completion_promise: stripQuotes(data.completion_promise) || DEFAULT_COMPLETION_PROMISE, started_at: stripQuotes(data.started_at) || new Date().toISOString(), prompt: body.trim(), session_id: data.session_id ? stripQuotes(data.session_id) : undefined, ultrawork: data.ultrawork === true || data.ultrawork === "true" ? true : undefined, strategy: data.strategy === "reset" || data.strategy === "continue" ? data.strategy : undefined, } } catch { return null } } export function writeState( directory: string, state: RalphLoopState, customPath?: string ): boolean { const filePath = getStateFilePath(directory, customPath) try { const dir = dirname(filePath) if (!existsSync(dir)) { mkdirSync(dir, { recursive: true }) } const sessionIdLine = state.session_id ? `session_id: "${state.session_id}"\n` : "" const ultraworkLine = state.ultrawork !== undefined ? `ultrawork: ${state.ultrawork}\n` : "" const strategyLine = state.strategy ? `strategy: "${state.strategy}"\n` : "" const content = `--- active: ${state.active} iteration: ${state.iteration} max_iterations: ${state.max_iterations} completion_promise: "${state.completion_promise}" started_at: "${state.started_at}" ${sessionIdLine}${ultraworkLine}${strategyLine}--- ${state.prompt} ` writeFileSync(filePath, content, "utf-8") return true } catch { return false } } export function clearState(directory: string, customPath?: string): boolean { const filePath = getStateFilePath(directory, customPath) try { if (existsSync(filePath)) { unlinkSync(filePath) } return true } catch { return false } } export function incrementIteration( directory: string, customPath?: string ): RalphLoopState | null { const state = readState(directory, customPath) if (!state) return null state.iteration += 1 if (writeState(directory, state, customPath)) { return state } return null }