File size: 3,546 Bytes
13b72a8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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'));