p3x-redis-ui-server
Version:
🏍️ P3X Redis UI server — Socket.IO backend for the dual Angular + React frontend with AI queries, 54 languages, and auto data decompression
2 lines (1 loc) • 4.75 kB
JavaScript
import*as t from"../../shared.mjs";import{TOOL_SCHEMAS as e,runTool as o}from"./tools.mjs";import{buildSystemPrompt as n,callGroq as r,cleanAiText as s,parseAiResponse as a,summarizeMessages as i,truncateToolContent as c}from"../../../../lib/ai/prompt.mjs";const l=t.argumentParser,u=["subscribe","monitor","quit","psubscribe"],m={flushdb:"flushdb",flushall:"flushall",dbsize:"dbsize"};async function p(t,e){const o=l(e);if(0===o.length)throw new Error("Empty command");const n=o.shift().toLowerCase();if(u.includes(n))throw new Error(`Command '${n}' is not allowed`);const r=m[n];return r&&"function"==typeof t[r]?await t[r](...o):await t.call(n,...o)}async function d({messages:t,tools:e,apiKey:o,useOwnKey:n}){const s=p3xrs.cfg.groqMaxTokens||65536;if(n&&o){const n=await r({messages:t,tools:e,apiKey:o,model:"openai/gpt-oss-120b",maxTokens:s});return n.choices?.[0]?.message||{}}const a="string"==typeof p3xrs.cfg.aiNetworkUrl&&p3xrs.cfg.aiNetworkUrl.length>0?p3xrs.cfg.aiNetworkUrl:"development"===process.env.NODE_ENV?"http://localhost:8003":"https://network.corifeus.com";let i;try{i=await fetch(`${a}/public/ai/redis-query`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({messages:t,tools:e&&e.length>0?e:void 0,apiKey:o||void 0})})}catch{throw new Error("AI service is not reachable")}if(!(i.headers.get("content-type")||"").includes("application/json"))throw new Error(`AI service returned invalid response (${i.status})`);const c=await i.json();if("ok"!==c.status)throw new Error(c.message||"AI query failed");return c.data?.message?c.data.message:void 0!==c.data?.command?{role:"assistant",content:(c.data.command||"")+(c.data.explanation?"\n---\n"+c.data.explanation:"")}:{role:"assistant",content:""}}const f=t=>i(t).chars;function h(t){let e=-1;for(let o=t.length-1;o>=0;o--){const n=t[o];if("assistant"===n.role&&Array.isArray(n.tool_calls)&&n.tool_calls.length>0){e=o;break}}for(let o=0;o<e;o++){const e=t[o];if("tool"!==e.role||"string"!=typeof e.content)continue;if(e.content.startsWith("[prior tool result"))continue;const n=e.content.slice(0,150).replace(/\s+/g," ");e.content=`[prior tool result summarized: ${n}${e.content.length>150?"...":""}]`}}function g(t){if(!(f(t)<=24e3))for(let e=0;e<t.length;e++){if(f(t)<=24e3)return;const o=t[e];"tool"===o.role&&"string"==typeof o.content&&o.content.length>200&&(o.content=`[earlier tool result \u2014 summarized: ${o.content.slice(0,150)}...]`)}}export default async t=>{const{socket:r,payload:s}=t;try{const{prompt:i,context:l,execute:u}=s;if(!i||"string"!=typeof i||0===i.trim().length)throw new Error("AI_PROMPT_REQUIRED");if(i.length>4096)throw new Error("AI prompt too long (max 4096 characters)");if(!1===p3xrs.cfg.aiEnabled)throw new Error("AI_DISABLED");const m=p3xrs.cfg.groqApiKey||"",f=!0===p3xrs.cfg.aiUseOwnKey,y="connected"===l?.connectionState&&r.p3xrs?.ioredis?r.p3xrs.ioredis:null;console.info(f&&m?"ai-redis-query: using direct Groq API (own key)":"ai-redis-query: using network proxy","\u2014 tools",y?"enabled":"disabled");const w=await async function({prompt:t,context:r,apiKey:s,useOwnKey:i,redis:l}){const u=[{role:"system",content:n(r,{includeToolUse:!0})},{role:"user",content:t}],m=l&&"connected"===r?.connectionState,p=m?e:[],f=[];for(let t=0;t<5;t++){h(u),g(u);const t=await d({messages:u,tools:p,apiKey:s,useOwnKey:i});u.push(t);const e=t.tool_calls||[];if(0===e.length){const e=(t.content||"").trim();return{...a(e),toolTrail:f}}const n=e.slice(0,10);for(const t of n){let e={};try{e=JSON.parse(t.function?.arguments||"{}")}catch{e={}}const n=t.function?.name||"";let r;r=m?await o(l,n,e):{ok:!1,error:"Not connected to Redis \u2014 tools are unavailable.",ms:0},f.push({name:n,args:e,ok:r.ok,result:r.result,error:r.error,ms:r.ms}),u.push({role:"tool",tool_call_id:t.id,content:r.ok?c(r.result):`ERROR: ${r.error}`})}}return{command:"",explanation:"AI investigation exceeded the tool-call limit without reaching a conclusion. Partial tool trail below.",toolTrail:f}}({prompt:i.trim(),context:l,apiKey:m||void 0,useOwnKey:f&&Boolean(m),redis:y}),x={status:"ok",command:w.command,explanation:w.explanation,toolTrail:w.toolTrail};if(u&&y)if(!0===r.p3xrs.readonly)x.executed=!1,x.executionError="readonly-connection-mode";else{const t=w.command.split("\n").filter(t=>t.trim().length>0),e=[];for(const o of t)try{const t=await p(y,o);e.push({command:o,result:t})}catch(t){e.push({command:o,error:t.message})}x.executed=!0,x.results=e}r.emit(t.responseEvent,x)}catch(e){console.error("ai-redis-query error",e);let o=e.message||String(e);403===e.status||o.includes("blocked_api_access")?o="blocked_api_access":(429===e.status||o.includes("rate_limit"))&&(o="rate_limit"),r.emit(t.responseEvent,{status:"error",error:o})}};