feat: initial Claude chat (sechenov)
This commit is contained in:
67
server.js
Normal file
67
server.js
Normal file
@@ -0,0 +1,67 @@
|
||||
const express = require('express');
|
||||
const { spawn, execSync } = require('child_process');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
|
||||
const app = express();
|
||||
app.use(express.json({ limit: '10mb' }));
|
||||
app.use(express.static(path.join(__dirname, 'public')));
|
||||
|
||||
// Resolve claude binary
|
||||
let CLAUDE_BIN = 'claude';
|
||||
{
|
||||
const local = '/app/claude-bin/node_modules/.bin/claude';
|
||||
if (fs.existsSync(local)) {
|
||||
CLAUDE_BIN = local;
|
||||
} else {
|
||||
try {
|
||||
CLAUDE_BIN = execSync('which claude 2>/dev/null || echo claude', { encoding: 'utf8' }).trim();
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
console.log(`✓ Claude binary: ${CLAUDE_BIN}`);
|
||||
|
||||
const MODELS = {
|
||||
sonnet: 'claude-sonnet-4-6',
|
||||
haiku: 'claude-haiku-4-5-20251001',
|
||||
};
|
||||
|
||||
app.post('/api/chat', (req, res) => {
|
||||
const { text, model = 'sonnet' } = req.body;
|
||||
if (!text?.trim()) return res.status(400).json({ error: 'text required' });
|
||||
|
||||
const modelId = MODELS[model] || MODELS.sonnet;
|
||||
const configDir = process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), '.claude');
|
||||
|
||||
res.setHeader('Content-Type', 'text/event-stream');
|
||||
res.setHeader('Cache-Control', 'no-cache');
|
||||
res.setHeader('Connection', 'keep-alive');
|
||||
|
||||
const env = { ...process.env, CLAUDE_CONFIG_DIR: configDir };
|
||||
|
||||
const proc = spawn(CLAUDE_BIN, ['-p', text, '--model', modelId, '--output-format', 'text'], {
|
||||
env,
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
});
|
||||
|
||||
proc.stdout.on('data', (chunk) => {
|
||||
res.write(`data: ${JSON.stringify({ text: chunk.toString() })}\n\n`);
|
||||
});
|
||||
|
||||
proc.stderr.on('data', (chunk) => {
|
||||
console.error('[claude stderr]', chunk.toString().substring(0, 300));
|
||||
});
|
||||
|
||||
proc.on('close', (code) => {
|
||||
if (code !== 0) {
|
||||
res.write(`data: ${JSON.stringify({ error: `Ошибка (code ${code}). Проверь auth: claude --version` })}\n\n`);
|
||||
}
|
||||
res.write('data: [DONE]\n\n');
|
||||
res.end();
|
||||
});
|
||||
|
||||
req.on('close', () => { try { proc.kill(); } catch (e) {} });
|
||||
});
|
||||
|
||||
app.listen(8108, () => console.log('sechenov :8108'));
|
||||
Reference in New Issue
Block a user