UNPKG

grix-connector

Version:

Connect local AI coding agents (Claude, Codex, Gemini, Qwen, DeepSeek, Cursor, OpenCode, Pi, OpenHuman, Reasonix) to the Grix scheduling platform. Also serves as an OpenClaw plugin for Grix channel transport.

4 lines (3 loc) 1.86 kB
import{readFile as p}from"node:fs/promises";import g from"node:path";import{appendRotatingFile as f}from"./rotation.js";const u=2e3;function d(o){return o.length<=u?o:o.slice(0,u)+`... [truncated, total ${o.length} chars]`}class y{logsDir;rotationOptions;writeQueues=new Map;constructor(t,e={}){this.logsDir=t,this.rotationOptions=e}resolveFilePath(t){const e=t.replace(/[^a-zA-Z0-9._-]+/g,"-");return g.join(this.logsDir,"sessions",e,"conversation.jsonl")}enqueueWrite(t,e){const n=(this.writeQueues.get(t)??Promise.resolve()).catch(()=>{}).then(e).catch(s=>{console.error(`[conversation-log] Write failed for session ${t}: ${s instanceof Error?s.message:s}`)});this.writeQueues.set(t,n),n.finally(()=>{this.writeQueues.get(t)===n&&this.writeQueues.delete(t)})}append(t,e){this.enqueueWrite(t,async()=>{const i=this.resolveFilePath(t);await f(i,`${JSON.stringify(e)} `,this.rotationOptions)})}async readHistory(t,e=20){const i=this.resolveFilePath(t);let n;try{n=await p(i,"utf8")}catch{return[]}const h=n.split(` `).filter(r=>r.trim()).slice(-e),a=[];for(const r of h)try{const c=JSON.parse(r),l=(c.content??"").trim();l&&!m(l)&&a.push(c)}catch{}return a}logInbound(t,e){this.append(t,{ts:Date.now(),dir:"inbound",event_id:e.event_id??"",msg_id:e.msg_id??"",sender_id:e.sender_id??"",msg_type:e.msg_type??1,content_len:e.content?.length??0,content:e.content?d(e.content):void 0})}logOutbound(t,e,i,n){this.append(t,{ts:Date.now(),dir:"outbound",event_id:e,kind:i,text_len:n?.length??0,content:n?d(n):void 0})}logResult(t,e,i,n){this.append(t,{ts:Date.now(),dir:"result",event_id:e,status:i,msg:n})}async close(){const t=[...this.writeQueues.values()];await Promise.all(t.map(e=>e.catch(()=>{})))}}function m(o){const t=o.trim();return t.startsWith("grix://")||t.includes("[[Tool]")||t.includes("[[exec-approval-resolution")}export{y as ConversationLog};