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.
2 lines (1 loc) • 2.01 kB
JavaScript
import{readdirSync as u,statSync as p}from"node:fs";import l from"node:path";import{homedir as h}from"node:os";import{log as y}from"../../core/log/index.js";import{readFirstLines as T}from"../../core/util/read-first-lines.js";const f=100;function d(i){const t=i.replace(/\[\[message_id:[^\]]+\]\]/g,"").replace(/\s+/g," ").trim();if(t)return t.length>f?t.slice(0,f)+"\u2026":t}function g(i){const t=i.trim();return t?t.startsWith("<local-command-caveat>")||t.startsWith("<local-command-stdout>")||t.startsWith("<command-name>"):!0}function m(i){if(g(i))return;const t=i.match(/<channel[^>]*>([\s\S]+?)<\/channel>/);if(t){const r=t[1].trim();if(r)return d(r)}return d(i)}function S(i){for(const t of i)try{const r=JSON.parse(t);if(r.type!=="user")continue;const s=r.message?.content;if(typeof s=="string"){const e=m(s);if(e)return e;continue}if(Array.isArray(s)){for(const e of s)if(e.type==="text"&&e.text){const o=m(e.text);if(o)return o}}}catch{}}function I(i){try{const t=p(i),r=T(i,131072);let s="",e="",o="";for(const a of r.slice(0,80))try{const n=JSON.parse(a);if(n.sessionId&&!s&&(s=n.sessionId),n.type==="custom-title"&&n.customTitle&&!n.customTitle.startsWith("grix-")&&(e=n.customTitle),n.type==="ai-title"&&n.aiTitle&&!e&&(e=n.aiTitle),n.cwd&&!o&&(o=n.cwd),s&&e&&o)break}catch{}if(!s)return null;const c=e||S(r);return{sessionId:s,cwd:o||void 0,title:c,mtimeMs:Math.round(t.mtimeMs)}}catch{return null}}function C(i=l.join(h(),".claude","projects")){const t=[];let r;try{r=u(i,{withFileTypes:!0})}catch{return t}for(const s of r){if(!s.isDirectory())continue;const e=l.join(i,s.name);let o;try{o=u(e,{withFileTypes:!0})}catch{continue}for(const c of o){if(!c.isFile()||!c.name.endsWith(".jsonl"))continue;const a=l.join(e,c.name),n=I(a);n&&t.push({sessionId:n.sessionId,cwd:n.cwd||"",title:n.title,updatedAt:n.mtimeMs,filePath:a})}}return t.sort((s,e)=>e.updatedAt-s.updatedAt),y.info("claude-session-scanner",`Scanned ${t.length} Claude sessions from ${i}`),t}export{C as scanClaudeSessions};