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.
3 lines (2 loc) • 4.64 kB
JavaScript
import{readFileSync as w,readdirSync as p,statSync as y}from"node:fs";import f from"node:path";import{homedir as h}from"node:os";import{log as T}from"../../core/log/index.js";import{readFirstLines as g}from"../../core/util/read-first-lines.js";const j=100;function m(i){const n=i.replace(/\[\[message_id:[^\]]+\]\]/g,"").replace(/\s+/g," ").trim();if(n)return n.length>j?n.slice(0,j)+"\u2026":n}function A(i){for(const n of i){if(!n||typeof n!="object")continue;const t=n;if(t.type!=="user")continue;const s=t.content;if(typeof s=="string")return m(s);if(Array.isArray(s)){for(const e of s)if(e&&typeof e=="object"&&"text"in e&&typeof e.text=="string")return m(e.text)}}}function M(i){for(const n of i)try{const t=JSON.parse(n);if(t.type!=="user")continue;const s=t.message?.parts;if(Array.isArray(s)){for(const e of s)if(e&&typeof e=="object"&&"text"in e&&typeof e.text=="string")return m(e.text)}}catch{}}function x(i){if(typeof i=="string")return i;if(Array.isArray(i))for(const n of i){if(!n||typeof n!="object")continue;const t=n;if(typeof t.text=="string")return t.text;if(typeof t.data=="string")return t.data}}function F(i){const n=g(i,131072);for(const t of n)try{const s=JSON.parse(t);if(s.kind!=="Prompt")continue;const e=x(s.data?.content);if(!e)continue;const o=m(e);if(o)return o}catch{}}function k(i){try{const n=Math.round(y(i).mtimeMs),t=JSON.parse(w(i,"utf8")),s=t.session_id;if(!s)return null;const e=t.updated_at?new Date(t.updated_at).getTime():n,o=t.created_at?new Date(t.created_at).getTime():void 0;return{sessionId:s,cwd:t.cwd||"",title:typeof t.title=="string"?m(t.title):void 0,createdAt:Number.isFinite(o)?o:void 0,updatedAt:Number.isFinite(e)?e:n,mtimeMs:n}}catch{return null}}function S(i,n){try{const t=w(f.join(i,".gemini","history",n,".project_root"),"utf8").trim();return f.isAbsolute(t)?t:""}catch{return""}}function b(i){try{const n=Math.round(y(i).mtimeMs),s=g(i,32768).join(`
`),e=JSON.parse(s);if(!e.sessionId)return null;const o=A(e.messages||[]);return{sessionId:e.sessionId,startTime:e.startTime,title:o,mtimeMs:n}}catch{return null}}function I(i){try{const n=Math.round(y(i).mtimeMs),t=g(i,16384);if(t.length===0)return null;const s=JSON.parse(t[0]),e=s.sessionId;if(!e)return null;let o;for(const c of t.slice(1))try{const u=JSON.parse(c);if(u.type==="user"){const a=u.content;if(typeof a=="string"){o=m(a);break}if(Array.isArray(a)){for(const r of a)if(r&&typeof r=="object"&&"text"in r&&typeof r.text=="string"){o=m(r.text);break}}if(o)break}}catch{}return{sessionId:e,startTime:s.startTime,title:o,mtimeMs:n}}catch{return null}}function J(i){try{const n=Math.round(y(i).mtimeMs),t=g(i,16384);if(t.length===0)return null;const s=JSON.parse(t[0]),e=s.sessionId;if(!e)return null;const o=M(t);return{sessionId:e,cwd:s.cwd,title:o,mtimeMs:n}}catch{return null}}function D(i=h()){const n=f.join(i,".gemini","tmp"),t=[];let s;try{s=p(n,{withFileTypes:!0})}catch{return t}for(const e of s){if(!e.isDirectory())continue;const o=f.join(n,e.name,"chats"),c=e.name,u=S(i,c);let a;try{a=p(o,{withFileTypes:!0})}catch{continue}for(const r of a){if(!r.isFile()||!r.name.startsWith("session-"))continue;const d=f.join(o,r.name);let l=null;r.name.endsWith(".json")?l=b(d):r.name.endsWith(".jsonl")&&(l=I(d)),l&&t.push({sessionId:l.sessionId,cwd:u,title:l.title,agentType:"gemini",createdAt:l.startTime?new Date(l.startTime).getTime():void 0,updatedAt:l.mtimeMs,filePath:d})}}return t}function N(i=h()){const n=f.join(i,".qwen","projects"),t=[];let s;try{s=p(n,{withFileTypes:!0})}catch{return t}for(const e of s){if(!e.isDirectory())continue;const o=f.join(n,e.name,"chats"),c=e.name;let u;try{u=p(o,{withFileTypes:!0})}catch{continue}for(const a of u){if(!a.isFile()||!a.name.endsWith(".jsonl"))continue;const r=f.join(o,a.name),d=J(r);d&&t.push({sessionId:d.sessionId,cwd:d.cwd||c,title:d.title,agentType:"qwen",updatedAt:d.mtimeMs,filePath:r})}}return t}function _(i=h()){const n=f.join(i,".kiro","sessions","cli"),t=[];let s;try{s=p(n,{withFileTypes:!0})}catch{return t}for(const e of s){if(!e.isFile()||!e.name.endsWith(".json"))continue;const o=f.join(n,e.name),c=k(o);if(!c)continue;const u=o.slice(0,-5)+".jsonl";let a=F(u)||c.title,r=Math.max(c.updatedAt,c.mtimeMs);try{r=Math.max(r,Math.round(y(u).mtimeMs))}catch{}t.push({sessionId:c.sessionId,cwd:c.cwd,title:a,agentType:"kiro",createdAt:c.createdAt,updatedAt:r,filePath:o})}return t}function C(i=h()){const n=D(i),t=N(i),s=_(i),e=[...n,...t,...s];return e.sort((o,c)=>c.updatedAt-o.updatedAt),T.info("acp-session-scanner",`Scanned ${e.length} ACP sessions (gemini=${n.length}, qwen=${t.length}, kiro=${s.length})`),e}export{C as scanAcpSessions};