Download playground/server/server.js from Snapkitty/j-matrix-twin: direct link, hf CLI and curl.
- Browser
- Download file 6.38 kB
-
https://huggingface.co/Snapkitty/j-matrix-twin/resolve/main/playground/server/server.js
- Command line
-
hf download hf://Snapkitty/j-matrix-twin/playground/server/server.js
-
curl -L -o server.js https://huggingface.co/Snapkitty/j-matrix-twin/resolve/main/playground/server/server.js
6.38 kB
| /** | |
| * J Matrix Twin WebSocket Server | |
| * Executes J code via ijconsole and streams results to browser | |
| */ | |
| const WebSocket = require('ws'); | |
| const { spawn } = require('child_process'); | |
| const http = require('http'); | |
| const fs = require('fs'); | |
| const path = require('path'); | |
| const PORT = process.env.PORT || 8080; | |
| const PUBLIC_DIR = path.join(__dirname, '../public'); | |
| // Create HTTP server for static files | |
| const server = http.createServer((req, res) => { | |
| let filePath = path.join(PUBLIC_DIR, req.url === '/' ? 'index.html' : req.url); | |
| const extname = path.extname(filePath); | |
| const contentTypes = { | |
| '.html': 'text/html', | |
| '.js': 'text/javascript', | |
| '.css': 'text/css', | |
| '.json': 'application/json', | |
| '.png': 'image/png', | |
| '.jpg': 'image/jpg', | |
| '.svg': 'image/svg+xml' | |
| }; | |
| const contentType = contentTypes[extname] || 'text/plain'; | |
| fs.readFile(filePath, (error, content) => { | |
| if (error) { | |
| if (error.code === 'ENOENT') { | |
| res.writeHead(404); | |
| res.end('404 Not Found'); | |
| } else { | |
| res.writeHead(500); | |
| res.end('500 Internal Server Error'); | |
| } | |
| } else { | |
| res.writeHead(200, { 'Content-Type': contentType }); | |
| res.end(content, 'utf-8'); | |
| } | |
| }); | |
| }); | |
| // Create WebSocket server | |
| const wss = new WebSocket.Server({ server }); | |
| // Check if ijconsole is available | |
| function checkJInstallation() { | |
| return new Promise((resolve) => { | |
| const proc = spawn('ijconsole', ['--version'], { shell: true }); | |
| proc.on('error', () => resolve(false)); | |
| proc.on('close', (code) => resolve(code === 0)); | |
| }); | |
| } | |
| // Execute J code | |
| async function executeJCode(code) { | |
| return new Promise((resolve, reject) => { | |
| const jProc = spawn('ijconsole', [], { shell: true }); | |
| let stdout = ''; | |
| let stderr = ''; | |
| jProc.stdout.on('data', (data) => { | |
| stdout += data.toString(); | |
| }); | |
| jProc.stderr.on('data', (data) => { | |
| stderr += data.toString(); | |
| }); | |
| jProc.on('error', (error) => { | |
| reject(new Error(`Failed to spawn ijconsole: ${error.message}`)); | |
| }); | |
| jProc.on('close', (code) => { | |
| if (code !== 0 && stderr) { | |
| reject(new Error(stderr)); | |
| } else { | |
| // Clean up J output (remove prompts, etc.) | |
| const cleaned = stdout | |
| .split('\n') | |
| .filter(line => !line.trim().startsWith(' ')) | |
| .join('\n') | |
| .trim(); | |
| resolve(cleaned); | |
| } | |
| }); | |
| // Send code to J | |
| jProc.stdin.write(code + '\n'); | |
| jProc.stdin.write('exit 0\n'); | |
| jProc.stdin.end(); | |
| // Timeout after 30 seconds | |
| setTimeout(() => { | |
| jProc.kill(); | |
| reject(new Error('Execution timeout (30s)')); | |
| }, 30000); | |
| }); | |
| } | |
| // WebSocket connection handler | |
| wss.on('connection', async (ws) => { | |
| console.log('Client connected'); | |
| // Check J installation | |
| const jAvailable = await checkJInstallation(); | |
| if (jAvailable) { | |
| ws.send(JSON.stringify({ | |
| type: 'status', | |
| status: 'connected', | |
| message: 'J interpreter available' | |
| })); | |
| } else { | |
| ws.send(JSON.stringify({ | |
| type: 'status', | |
| status: 'error', | |
| message: 'J interpreter not found. Install from jsoftware.com' | |
| })); | |
| } | |
| ws.on('message', async (message) => { | |
| try { | |
| const data = JSON.parse(message); | |
| if (data.type === 'execute') { | |
| console.log('Executing J code...'); | |
| if (!jAvailable) { | |
| ws.send(JSON.stringify({ | |
| error: 'J interpreter not available' | |
| })); | |
| return; | |
| } | |
| try { | |
| const output = await executeJCode(data.code); | |
| ws.send(JSON.stringify({ | |
| type: 'result', | |
| output: output | |
| })); | |
| console.log('Execution successful'); | |
| } catch (error) { | |
| ws.send(JSON.stringify({ | |
| type: 'result', | |
| error: error.message | |
| })); | |
| console.error('Execution error:', error.message); | |
| } | |
| } | |
| } catch (error) { | |
| console.error('Message handling error:', error); | |
| ws.send(JSON.stringify({ | |
| error: 'Invalid message format' | |
| })); | |
| } | |
| }); | |
| ws.on('close', () => { | |
| console.log('Client disconnected'); | |
| }); | |
| ws.on('error', (error) => { | |
| console.error('WebSocket error:', error); | |
| }); | |
| }); | |
| // Start server | |
| server.listen(PORT, () => { | |
| console.log('='.repeat(60)); | |
| console.log('J Matrix Twin Playground Server'); | |
| console.log('='.repeat(60)); | |
| console.log(`HTTP Server: http://localhost:${PORT}`); | |
| console.log(`WebSocket: ws://localhost:${PORT}`); | |
| console.log(''); | |
| checkJInstallation().then(available => { | |
| if (available) { | |
| console.log('✓ J interpreter found'); | |
| } else { | |
| console.log('✗ J interpreter not found'); | |
| console.log(' Install from: https://www.jsoftware.com'); | |
| console.log(' Server will run in demo mode'); | |
| } | |
| console.log(''); | |
| console.log('Press Ctrl+C to stop'); | |
| console.log('='.repeat(60)); | |
| }); | |
| }); | |
| // Graceful shutdown | |
| process.on('SIGINT', () => { | |
| console.log('\nShutting down server...'); | |
| wss.clients.forEach(client => { | |
| client.close(); | |
| }); | |
| server.close(() => { | |
| console.log('Server stopped'); | |
| process.exit(0); | |
| }); | |
| }); | |
| // Made with Bob | |