import { createRunSummary, } from "./run-summary.js"; import { createSessionSnapshotSummary, sessionSnapshotMetadataLogLines, } from "./session-summary.js"; export function selectSessionGcodeProgram({ snapshot = null, defaultFilename, defaultOpfsPath, wasmPath, gcodeFilenameFromProgramPath, }) { const snapshotOpfsPath = snapshot?.payload?.files?.gcode; if (typeof snapshotOpfsPath === "string") { try { return { filename: gcodeFilenameFromProgramPath(snapshotOpfsPath), opfsPath: snapshotOpfsPath, source: "snapshot", wasmPath, }; } catch { // Invalid snapshot program paths fall back to the UI default program. } } return { filename: defaultFilename, opfsPath: defaultOpfsPath, source: "default", wasmPath, }; } export function createRunSessionReadinessState({ loadedSession = null, snapshot = null, defaultFilename, defaultOpfsPath, wasmPath, gcodeFilenameFromProgramPath, }) { const program = selectSessionGcodeProgram({ snapshot, defaultFilename, defaultOpfsPath, wasmPath, gcodeFilenameFromProgramPath, }); const missing = []; if (!loadedSession?.ini?.wasmPath) { missing.push("loaded-session"); } if (!program.filename || !program.opfsPath || !program.wasmPath) { missing.push("gcode-program"); } const canRun = missing.length === 0; return { phase: canRun ? "ready" : "blocked", canRun, missing, loadedSession: { iniWasmPath: loadedSession?.ini?.wasmPath ?? null, }, snapshot: { present: Boolean(snapshot), label: snapshot?.metadata?.snapshotLabel ?? snapshot?.sessionId ?? null, workflow: snapshot?.metadata?.workflow ?? null, gcodeOpfsPath: snapshot?.payload?.files?.gcode ?? null, }, defaultProgram: { filename: defaultFilename ?? null, opfsPath: defaultOpfsPath ?? null, wasmPath: wasmPath ?? null, }, program, runButton: { enabled: canRun, reason: canRun ? null : `Missing ${missing.join(", ")}.`, }, }; } export function runSessionContextLogLines(program, snapshot = null, snapshotLabel = null) { const summary = createSessionSnapshotSummary({ metadata: snapshot?.metadata ?? {}, }); return [ `Program: ${program.opfsPath} -> ${program.wasmPath}`, `Program source: ${program.source}`, `Snapshot: ${snapshot ? (snapshotLabel ?? snapshot?.metadata?.snapshotLabel ?? snapshot?.sessionId) : "-"}`, ...sessionSnapshotMetadataLogLines(summary), ]; } export async function runGcodeSessionWorkflow({ interp, loadedSession, snapshot = null, defaultFilename, defaultOpfsPath, wasmPath, gcodeFilenameFromProgramPath, loadGcodeProgram, summarizeRun = () => ({}), snapshotLabel = null, }) { const readiness = createRunSessionReadinessState({ loadedSession, snapshot, defaultFilename, defaultOpfsPath, wasmPath, gcodeFilenameFromProgramPath, }); if (!readiness.canRun) { throw new Error("Load a machine session before running G-code."); } const program = readiness.program; const programText = await loadGcodeProgram(program.filename); interp.writeTextFile(program.wasmPath, programText); const resultText = interp.runFileWithIni(program.wasmPath, loadedSession.ini.wasmPath).trim(); const runResultSummary = summarizeRun(resultText, programText); const { motionSnapshots = [], ...runCounts } = runResultSummary; const summary = createRunSummary( program, { runStatus: "ok", iniWasmPath: loadedSession.ini.wasmPath, snapshotLabel: snapshot ? snapshotLabel : null, ...runCounts, }, snapshot, ); return { program: { ...program, text: programText, }, resultText, motionSnapshots, summary, readiness, fields: { sessionGcode: program.opfsPath, runStatus: summary.runStatus, runSource: summary.programSource, runSnapshot: summary.snapshotLabel ?? "-", runWorkflow: summary.workflow ?? "-", runOpfsPath: summary.programOpfsPath, runWasmPath: summary.programWasmPath, }, logLines: [ ...runSessionContextLogLines(program, snapshot, summary.snapshotLabel), `INI: ${loadedSession.ini.wasmPath}`, resultText, ], }; }