const express = require('express'); const mathsteps = require('mathsteps'); const { exec } = require('child_process'); const path = require('path'); const crypto = require('crypto'); const fs = require('fs').promises; const { routeCommand, explainResult } = require('./llmService'); const app = express(); app.use(express.json()); app.use(express.static(path.join(__dirname, 'public'))); // LLM Orchestration Endpoint app.post('/api/orchestrate', async (req, res) => { const { query, provider, apiKey, model } = req.body; // <-- Added model try { const decision = await routeCommand(query, provider, apiKey, model); return res.json({ success: true, engine: decision.engine, command: decision.command }); } catch (err) { return res.status(500).json({ success: false, error: err.message }); } }); // LLM Explanation Endpoint app.post('/api/explain', async (req, res) => { const { context, provider, apiKey, model } = req.body; // <-- Added model try { const explanation = await explainResult(context, provider, apiKey, model); return res.json({ success: true, explanation }); } catch (err) { return res.status(500).json({ success: false, error: err.message }); } }); // ENGINE 1: Mathsteps (Immunized against LLM verb leaks) app.post('/api/solve/steps', (req, res) => { try { let command = req.body.command || ""; // Defensive Programming: Strip English action verbs if the LLM leaked them command = command.replace(/^(solve|simplify|steps|calculate|compute)\s+/gi, '').trim(); const steps = mathsteps.solveEquation(command); const stepsLog = steps.map(step => ({ change: step.changeType, subsequentEquation: step.newEquation.print() })); return res.json({ engine: 'mathsteps', success: true, steps: stepsLog }); } catch (err) { return res.status(400).json({ success: false, error: err.message }); } }); // ENGINE 2: SageMath (Upgraded for Multi-line ODE/PDE scripts) app.post('/api/solve/advanced', async (req, res) => { const { command } = req.body; // Create a unique temporary filename for this calculation const fileId = crypto.randomBytes(16).toString('hex'); const tempFilePath = path.join(__dirname, `script_${fileId}.sage`); try { // Write the LLM's multi-line script to a .sage file await fs.writeFile(tempFilePath, command); // Execute the file using SageMath exec(`sage ${tempFilePath}`, { timeout: 20000 }, async (error, stdout, stderr) => { // Clean up: Delete the file after execution await fs.unlink(tempFilePath).catch(() => console.error("Failed to delete temp file")); if (error) { return res.status(500).json({ success: false, error: stderr || error.message }); } return res.json({ engine: 'sagemath', success: true, result_latex: stdout.trim() }); }); } catch (err) { return res.status(500).json({ success: false, error: err.message }); } }); // ENGINE 3: GeoGebra Bridge app.post('/api/solve/graph', (req, res) => { const config = { "appName": "graphing", "width": 800, "height": 500, "showToolBar": true, "postInitEval": `ggbApplet.evalCommand("${req.body.command}");` }; return res.json({ engine: 'geogebra', success: true, config }); }); app.listen(7860, () => console.log('🚀 Ultimate Math Server on port 7860'));