78 lines
3.7 KiB
JavaScript
Raw Permalink Normal View History

const express = require('express');
const axios = require('axios');
const { execSync } = require('child_process');
const fs = require('fs');
const Database = require('better-sqlite3');
const { v4: uuidv4 } = require('uuid');
const DEEPSEEK_KEY = 'ARK_API_KEY_REDACTED';
const db = new Database('/opt/zhuyuan/agent/conversations3.db');
db.exec('CREATE TABLE IF NOT EXISTS convs (id TEXT PRIMARY KEY, title TEXT, ctime TEXT, utime TEXT)');
db.exec('CREATE TABLE IF NOT EXISTS msgs (id INTEGER PRIMARY KEY AUTOINCREMENT, cid TEXT, role TEXT, content TEXT, ctime TEXT)');
const app = express();
app.use(express.json());
app.use(express.static('/opt/zhuyuan/agent/public'));
function raw(cmd){ try{ return execSync(cmd,{timeout:5000}).toString().trim() }catch(e){ return '?' } }
function reality(){
return {
host: raw('hostname'),
cpu: raw('top -bn1 | head -5 | head -c 200'),
mem: raw('free -h'),
disk: raw('df -h /'),
pm2: raw('pm2 jlist 2>/dev/null | head -c 500')
};
}
app.get('/api/convs',(req,res)=>{
res.json(db.prepare('SELECT * FROM convs ORDER BY utime DESC').all());
});
app.post('/api/convs',(req,res)=>{
const id=uuidv4();
db.prepare("INSERT INTO convs VALUES(?,?,datetime('now'),datetime('now'))").run(id,'新对话');
res.json({id});
});
app.get('/api/convs/:id',(req,res)=>{
const c=db.prepare('SELECT * FROM convs WHERE id=?').get(req.params.id);
if(!c)return res.status(404).json({e:'not found'});
c.messages=db.prepare('SELECT role,content FROM msgs WHERE cid=? ORDER BY id ASC').all(req.params.id);
res.json(c);
});
app.delete('/api/convs/:id',(req,res)=>{
db.prepare('DELETE FROM msgs WHERE cid=?').run(req.params.id);
db.prepare('DELETE FROM convs WHERE id=?').run(req.params.id);
res.json({ok:1});
});
app.post('/api/chat',async(req,res)=>{
const{conversation_id,message}=req.body;
if(!message)return res.status(400).json({e:'no msg'});
let cid=conversation_id||uuidv4();
if(!conversation_id)db.prepare("INSERT INTO convs VALUES(?,?,datetime('now'),datetime('now'))").run(cid,'新对话');
db.prepare("INSERT INTO msgs(cid,role,content,ctime) VALUES(?,'user',?,datetime('now'))").run(cid,message);
const hist=db.prepare('SELECT role,content FROM msgs WHERE cid=? ORDER BY id DESC LIMIT 30').all(cid).reverse();
const t=db.prepare('SELECT title FROM convs WHERE id=?').get(cid);
if(t&&t.title==='新对话')db.prepare('UPDATE convs SET title=? WHERE id=?').run(message.slice(0,25),cid);
const r=reality();
const ctx='[Server Reality - '+r.host+']'+'\nCPU:\n'+r.cpu+'\nMemory:\n'+r.mem+'\nDisk:\n'+r.disk+'\nPM2:\n'+r.pm2;
const sys='你是光湖团队技术助手由铸渊ICE-GL-ZY001部署。技术主控Awen的AI助手。服务器: 冰朔6台+团队2台。广州是中枢(43.139.217.141)。每次回答时用户消息末尾会附带当前服务器真实采集数据,请基于真实数据回答,不要编造。';
try{
const resp=await axios.post('https://api.deepseek.com/v1/chat/completions',{
model:'deepseek-chat',
messages:[{role:'system',content:sys},...hist.slice(0,-1),{role:'user',content:message+'\n\n'+ctx}],
temperature:0.5,max_tokens:2000
},{headers:{'Authorization':'Bearer '+DEEPSEEK_KEY,'Content-Type':'application/json'}});
const reply=resp.data.choices[0].message.content;
db.prepare("INSERT INTO msgs(cid,role,content,ctime) VALUES(?,'assistant',?,datetime('now'))").run(cid,reply);
db.prepare("UPDATE convs SET utime=datetime('now') WHERE id=?").run(cid);
res.json({conversation_id:cid,reply,reality:r});
}catch(e){res.status(500).json({e:'API:'+e.message})}
});
app.get('/api/reality',(req,res)=>res.json(reality()));
app.get('/api/health',(req,res)=>res.json({ok:1}));
app.listen(3940,'127.0.0.1',()=>console.log('Agent OK'));