@xenosystem/agent-sdk 0.9.19 → 0.9.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -46,7 +46,7 @@ ${this.stringify(t.data)}
46
46
  `)+`
47
47
  `;await g(this.transcriptPath,a);let l=this.buildMarkdownDocument(o,"session store");if(await g(this.markdownPath,l),!this.workspaceMirrorDisabled){let c=await this.resolveWorkspaceMarkdownPath();if(c)try{let u=this.buildMarkdownDocument(o,"workspace mirror");await g(c,u)}catch(u){this.workspaceMirrorDisabled=!0,D("Transcript workspace mirror disabled",u)}}}async truncateAfterMessageCount(t){let e=await f(this.transcriptPath);if(!e)return;let n=U(e),i=Math.max(0,t),s=0,o=[];for(let c of n){if(c.type==="user_message"||c.type==="assistant_message"){if(s>=i)break;s+=1}o.push(c)}let a=o.length>0?o.map(c=>JSON.stringify(c)).join(`
48
48
  `)+`
49
- `:"";await g(this.transcriptPath,a);let l=this.buildMarkdownDocument(o,"session store");if(await g(this.markdownPath,l),!this.workspaceMirrorDisabled){let c=await this.resolveWorkspaceMarkdownPath();if(c)try{let u=this.buildMarkdownDocument(o,"workspace mirror");await g(c,u)}catch(u){this.workspaceMirrorDisabled=!0,D("Transcript workspace mirror disabled",u)}}}getSequence(){return this.sequence}async initialize(){try{let t=await f(this.transcriptPath);if(!t){this.sequence=0;return}let e=U(t);if(e.length===0){this.sequence=0;return}let n=e[e.length-1];this.sequence=n.sequence+1}catch(t){let e=t instanceof Error?t.message:String(t);D(`Transcript initialization warning: ${e}. Starting with empty transcript.`),this.sequence=0}}async flush(){await this.writeQueue}};var J=x(require("path"),1),Ut=require("crypto"),Jt=require("fs/promises");var ve={View:"Read",Replace:"Write",GlobTool:"Glob",GrepTool:"Grep",SQLiteAnalyze:"SqliteAnalyze",ReadNotebook:"NotebookRead",NotebookEditCell:"NotebookEdit"};function st(r){return ve[r]??r}var N=class{sessionDir;checkpointsDir;autoInterval;lastCheckpointMessageCount=0;constructor(t,e){this.sessionDir=t,this.checkpointsDir=J.join(t,"checkpoints"),this.autoInterval=e?.autoInterval??10}async initialize(){let t=await this.list();t.length>0&&(this.lastCheckpointMessageCount=t[0].messageCount)}async create(t){await G(this.checkpointsDir);let e=(0,Ut.randomUUID)(),n={id:e,name:t.description,trigger:t.trigger,createdAt:new Date().toISOString(),messageCount:t.messages.length,tokenCount:this.estimateTokens(t.messages)},i={info:n,messages:t.messages},s=J.join(this.checkpointsDir,`${e}.json`);return await g(s,JSON.stringify(i,null,2)),this.lastCheckpointMessageCount=t.messages.length,n}async list(){let t=await Ft(this.checkpointsDir,/\.json$/),e=[];for(let n of t){let i=await f(n);if(i){let s=y(i,null);if(s){let o=await(0,Jt.stat)(n);e.push({info:s.info,modifiedAtMs:o.mtimeMs})}}}return e.sort((n,i)=>new Date(i.info.createdAt).getTime()-new Date(n.info.createdAt).getTime()||i.modifiedAtMs-n.modifiedAtMs).map(({info:n})=>n)}async restore(t){let e=J.join(this.checkpointsDir,`${t}.json`),n;try{n=await f(e)}catch(s){let o=s instanceof Error?s.message:String(s);throw new Error(`Failed to read checkpoint ${t}: ${o}`)}if(!n)throw new Error(`Checkpoint not found: ${t} (path: ${e})`);let i=y(n,null);if(!i)throw new Error(`Invalid checkpoint data for ${t}: JSON parse failed`);if(!i.messages||!Array.isArray(i.messages))throw new Error(`Invalid checkpoint data for ${t}: missing or invalid messages array`);if(!i.info)throw new Error(`Invalid checkpoint data for ${t}: missing info object`);return{messages:i.messages,info:i.info}}shouldAutoCheckpoint(t){return t-this.lastCheckpointMessageCount>=this.autoInterval}static isDangerousOperation(t,e){if(t=st(t),t==="Write")return!0;if(t==="Bash"){let i=e.command?.toLowerCase()||"";return["rm ","del ","git push","git reset","drop ","truncate"].some(o=>i.includes(o))}return!1}async delete(t){let e=J.join(this.checkpointsDir,`${t}.json`);await R(e)}estimateTokens(t){let e=0;for(let n of t)if(typeof n.content=="string")e+=Math.ceil(n.content.length/4);else if(Array.isArray(n.content))for(let i of n.content)"text"in i&&(e+=Math.ceil(i.text.length/4));return e}};var I=x(require("path"),1),Pt=x(require("os"),1),W=x(require("fs"),1);var be=Symbol.for("@xenosystem/agent-sdk/shutdown-registry"),Re=globalThis,xt=Re[be]??={cleanups:new Set,exitHandlerRegistered:!1,signalHandlersInstalled:!1},Et=xt.cleanups;function De(){for(let r of Et)try{r()}catch{}}function qt(r){return Et.add(r),!xt.exitHandlerRegistered&&typeof process<"u"&&typeof process.on=="function"&&(xt.exitHandlerRegistered=!0,process.on("exit",De)),()=>{Et.delete(r)}}var zt="0.9.19";var Ie=1e4,Ce=6e4,Me="session.lock",_e="lock.json",q=new Set;function Ae(){for(let r of q)try{W.unlinkSync(r)}catch{}q.clear()}qt(Ae);var $=class r{sessionDir;lockPath;legacyLockPath;sessionId;heartbeatTimer;constructor(t){this.sessionDir=t,this.lockPath=I.join(t,Me),this.legacyLockPath=I.join(t,_e),this.sessionId=I.basename(t)}async acquire(){let t=new Date().toISOString(),e={schemaVersion:1,name:`session:${this.sessionId}`,sessionId:this.sessionId,pid:process.pid,hostname:Pt.hostname(),processStartedAt:new Date(Date.now()-Math.floor(process.uptime()*1e3)).toISOString(),version:zt,acquiredAt:t,updatedAt:t,heartbeat:t},n=I.dirname(this.lockPath);await W.promises.mkdir(n,{recursive:!0});let i=await this.findExistingLockPath();if(i){if(!await this.isStalePath(i)){let o=await this.readLockAt(i);throw new Error(`Session ${this.sessionId} is already locked by PID ${o?.pid} on ${o?.hostname}`)}await R(i)}try{await W.promises.writeFile(this.lockPath,JSON.stringify(e,null,2),{flag:"wx",encoding:"utf-8"}),q.add(this.lockPath)}catch(s){if(s.code==="EEXIST"){if(!await this.isStalePath(this.lockPath)){let l=await this.readLockAt(this.lockPath);throw new Error(`Session ${this.sessionId} is already locked by PID ${l?.pid} on ${l?.hostname}`)}await R(this.lockPath);try{await W.promises.writeFile(this.lockPath,JSON.stringify(e,null,2),{flag:"wx",encoding:"utf-8"})}catch(l){throw l.code==="EEXIST"?new Error(`Session ${this.sessionId} lock was acquired by another process during stale recovery`):l}q.add(this.lockPath)}else throw s}}async release(){this.stopHeartbeat(),q.delete(this.lockPath),await R(this.lockPath)}async isLocked(){let t=await this.findExistingLockPath();return t?!await this.isStalePath(t):!1}async isStale(){let t=await this.findExistingLockPath();return t?this.isStalePath(t):!1}async isStalePath(t){let e=await this.readLockAt(t);if(!e)return!1;let n=new Date(e.heartbeat).getTime();return Date.now()-n>Ce}startHeartbeat(t=Ie){this.heartbeatTimer&&this.stopHeartbeat(),this.heartbeatTimer=setInterval(async()=>{try{await this.updateHeartbeat()}catch(e){let n=e instanceof Error?e.message:String(e);if(e?.code==="ENOENT"){_("SessionLock: Session directory removed, stopping heartbeat"),this.stopHeartbeat();return}_(`SessionLock: Failed to update heartbeat: ${n}`)}},t),this.heartbeatTimer.unref()}stopHeartbeat(){this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=void 0)}async updateHeartbeat(){let t=await this.readLockAt(this.lockPath);t&&(t.pid!==process.pid||t.hostname!==Pt.hostname()||(t.heartbeat=new Date().toISOString(),t.updatedAt=t.heartbeat,await g(this.lockPath,JSON.stringify(t,null,2))))}async readLock(){let t=await this.findExistingLockPath();return t?this.readLockAt(t):null}async readLockAt(t){let e=await f(t);return e?y(e,null):null}async findExistingLockPath(){return await f(this.lockPath)?this.lockPath:await f(this.legacyLockPath)?this.legacyLockPath:null}static async cleanStale(t){let e=await et(t),n=[];for(let i of e){let s=new r(i);if(await s.isStale()){let a=await s.findExistingLockPath();a&&await R(a),n.push(I.basename(i))}}return n}};var v=x(require("path"),1);var T=x(require("path"),1);function Oe(r,t){let e=T.resolve(r),n=T.resolve(r,t);return n===e?!0:e===T.parse(e).root?n.startsWith(e):n.startsWith(e+T.sep)}function L(r,t){if(T.isAbsolute(t))return T.resolve(t);if(!Oe(r,t))throw new Error(`PathSecurity: Path traversal attempt detected: ${t}`);return T.resolve(r,t)}var k=x(require("path"),1),ct=x(require("os"),1),S=x(require("node:fs/promises"),1),lt=require("node:crypto");var F=require("node:os");var Tt=require("node:path"),Tn=(0,F.platform)();var vn=(0,F.release)(),bn=(0,F.homedir)();function ot(){let r=process.env.XENO_AGENT_HOME?.trim();return r?(0,Tt.resolve)(r):(0,Tt.resolve)((0,F.homedir)(),".xeno-agent")}var Vt=1,Xt="recent.json",Ne=".lock",Yt=".entries",$e=3e4,vt=6e4,Qt=new Set(["EACCES","EBUSY","EPERM"]),Le=[5,10,20,40,80,160,320],at=new Map;function Fe(r,t){let e=(0,lt.createHash)("sha256").update(t).digest("hex");return k.join(`${r}${Yt}`,`${e}.json`)}async function bt(r,t,e){let n={schemaVersion:1,key:t,entry:e};await g(Fe(r,t),JSON.stringify(n)+`
49
+ `:"";await g(this.transcriptPath,a);let l=this.buildMarkdownDocument(o,"session store");if(await g(this.markdownPath,l),!this.workspaceMirrorDisabled){let c=await this.resolveWorkspaceMarkdownPath();if(c)try{let u=this.buildMarkdownDocument(o,"workspace mirror");await g(c,u)}catch(u){this.workspaceMirrorDisabled=!0,D("Transcript workspace mirror disabled",u)}}}getSequence(){return this.sequence}async initialize(){try{let t=await f(this.transcriptPath);if(!t){this.sequence=0;return}let e=U(t);if(e.length===0){this.sequence=0;return}let n=e[e.length-1];this.sequence=n.sequence+1}catch(t){let e=t instanceof Error?t.message:String(t);D(`Transcript initialization warning: ${e}. Starting with empty transcript.`),this.sequence=0}}async flush(){await this.writeQueue}};var J=x(require("path"),1),Ut=require("crypto"),Jt=require("fs/promises");var ve={View:"Read",Replace:"Write",GlobTool:"Glob",GrepTool:"Grep",SQLiteAnalyze:"SqliteAnalyze",ReadNotebook:"NotebookRead",NotebookEditCell:"NotebookEdit"};function st(r){return ve[r]??r}var N=class{sessionDir;checkpointsDir;autoInterval;lastCheckpointMessageCount=0;constructor(t,e){this.sessionDir=t,this.checkpointsDir=J.join(t,"checkpoints"),this.autoInterval=e?.autoInterval??10}async initialize(){let t=await this.list();t.length>0&&(this.lastCheckpointMessageCount=t[0].messageCount)}async create(t){await G(this.checkpointsDir);let e=(0,Ut.randomUUID)(),n={id:e,name:t.description,trigger:t.trigger,createdAt:new Date().toISOString(),messageCount:t.messages.length,tokenCount:this.estimateTokens(t.messages)},i={info:n,messages:t.messages},s=J.join(this.checkpointsDir,`${e}.json`);return await g(s,JSON.stringify(i,null,2)),this.lastCheckpointMessageCount=t.messages.length,n}async list(){let t=await Ft(this.checkpointsDir,/\.json$/),e=[];for(let n of t){let i=await f(n);if(i){let s=y(i,null);if(s){let o=await(0,Jt.stat)(n);e.push({info:s.info,modifiedAtMs:o.mtimeMs})}}}return e.sort((n,i)=>new Date(i.info.createdAt).getTime()-new Date(n.info.createdAt).getTime()||i.modifiedAtMs-n.modifiedAtMs).map(({info:n})=>n)}async restore(t){let e=J.join(this.checkpointsDir,`${t}.json`),n;try{n=await f(e)}catch(s){let o=s instanceof Error?s.message:String(s);throw new Error(`Failed to read checkpoint ${t}: ${o}`)}if(!n)throw new Error(`Checkpoint not found: ${t} (path: ${e})`);let i=y(n,null);if(!i)throw new Error(`Invalid checkpoint data for ${t}: JSON parse failed`);if(!i.messages||!Array.isArray(i.messages))throw new Error(`Invalid checkpoint data for ${t}: missing or invalid messages array`);if(!i.info)throw new Error(`Invalid checkpoint data for ${t}: missing info object`);return{messages:i.messages,info:i.info}}shouldAutoCheckpoint(t){return t-this.lastCheckpointMessageCount>=this.autoInterval}static isDangerousOperation(t,e){if(t=st(t),t==="Write")return!0;if(t==="Bash"){let i=e.command?.toLowerCase()||"";return["rm ","del ","git push","git reset","drop ","truncate"].some(o=>i.includes(o))}return!1}async delete(t){let e=J.join(this.checkpointsDir,`${t}.json`);await R(e)}estimateTokens(t){let e=0;for(let n of t)if(typeof n.content=="string")e+=Math.ceil(n.content.length/4);else if(Array.isArray(n.content))for(let i of n.content)"text"in i&&(e+=Math.ceil(i.text.length/4));return e}};var I=x(require("path"),1),Pt=x(require("os"),1),W=x(require("fs"),1);var be=Symbol.for("@xenosystem/agent-sdk/shutdown-registry"),Re=globalThis,xt=Re[be]??={cleanups:new Set,exitHandlerRegistered:!1,signalHandlersInstalled:!1},Et=xt.cleanups;function De(){for(let r of Et)try{r()}catch{}}function qt(r){return Et.add(r),!xt.exitHandlerRegistered&&typeof process<"u"&&typeof process.on=="function"&&(xt.exitHandlerRegistered=!0,process.on("exit",De)),()=>{Et.delete(r)}}var zt="0.9.21";var Ie=1e4,Ce=6e4,Me="session.lock",_e="lock.json",q=new Set;function Ae(){for(let r of q)try{W.unlinkSync(r)}catch{}q.clear()}qt(Ae);var $=class r{sessionDir;lockPath;legacyLockPath;sessionId;heartbeatTimer;constructor(t){this.sessionDir=t,this.lockPath=I.join(t,Me),this.legacyLockPath=I.join(t,_e),this.sessionId=I.basename(t)}async acquire(){let t=new Date().toISOString(),e={schemaVersion:1,name:`session:${this.sessionId}`,sessionId:this.sessionId,pid:process.pid,hostname:Pt.hostname(),processStartedAt:new Date(Date.now()-Math.floor(process.uptime()*1e3)).toISOString(),version:zt,acquiredAt:t,updatedAt:t,heartbeat:t},n=I.dirname(this.lockPath);await W.promises.mkdir(n,{recursive:!0});let i=await this.findExistingLockPath();if(i){if(!await this.isStalePath(i)){let o=await this.readLockAt(i);throw new Error(`Session ${this.sessionId} is already locked by PID ${o?.pid} on ${o?.hostname}`)}await R(i)}try{await W.promises.writeFile(this.lockPath,JSON.stringify(e,null,2),{flag:"wx",encoding:"utf-8"}),q.add(this.lockPath)}catch(s){if(s.code==="EEXIST"){if(!await this.isStalePath(this.lockPath)){let l=await this.readLockAt(this.lockPath);throw new Error(`Session ${this.sessionId} is already locked by PID ${l?.pid} on ${l?.hostname}`)}await R(this.lockPath);try{await W.promises.writeFile(this.lockPath,JSON.stringify(e,null,2),{flag:"wx",encoding:"utf-8"})}catch(l){throw l.code==="EEXIST"?new Error(`Session ${this.sessionId} lock was acquired by another process during stale recovery`):l}q.add(this.lockPath)}else throw s}}async release(){this.stopHeartbeat(),q.delete(this.lockPath),await R(this.lockPath)}async isLocked(){let t=await this.findExistingLockPath();return t?!await this.isStalePath(t):!1}async isStale(){let t=await this.findExistingLockPath();return t?this.isStalePath(t):!1}async isStalePath(t){let e=await this.readLockAt(t);if(!e)return!1;let n=new Date(e.heartbeat).getTime();return Date.now()-n>Ce}startHeartbeat(t=Ie){this.heartbeatTimer&&this.stopHeartbeat(),this.heartbeatTimer=setInterval(async()=>{try{await this.updateHeartbeat()}catch(e){let n=e instanceof Error?e.message:String(e);if(e?.code==="ENOENT"){_("SessionLock: Session directory removed, stopping heartbeat"),this.stopHeartbeat();return}_(`SessionLock: Failed to update heartbeat: ${n}`)}},t),this.heartbeatTimer.unref()}stopHeartbeat(){this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=void 0)}async updateHeartbeat(){let t=await this.readLockAt(this.lockPath);t&&(t.pid!==process.pid||t.hostname!==Pt.hostname()||(t.heartbeat=new Date().toISOString(),t.updatedAt=t.heartbeat,await g(this.lockPath,JSON.stringify(t,null,2))))}async readLock(){let t=await this.findExistingLockPath();return t?this.readLockAt(t):null}async readLockAt(t){let e=await f(t);return e?y(e,null):null}async findExistingLockPath(){return await f(this.lockPath)?this.lockPath:await f(this.legacyLockPath)?this.legacyLockPath:null}static async cleanStale(t){let e=await et(t),n=[];for(let i of e){let s=new r(i);if(await s.isStale()){let a=await s.findExistingLockPath();a&&await R(a),n.push(I.basename(i))}}return n}};var v=x(require("path"),1);var T=x(require("path"),1);function Oe(r,t){let e=T.resolve(r),n=T.resolve(r,t);return n===e?!0:e===T.parse(e).root?n.startsWith(e):n.startsWith(e+T.sep)}function L(r,t){if(T.isAbsolute(t))return T.resolve(t);if(!Oe(r,t))throw new Error(`PathSecurity: Path traversal attempt detected: ${t}`);return T.resolve(r,t)}var k=x(require("path"),1),ct=x(require("os"),1),S=x(require("node:fs/promises"),1),lt=require("node:crypto");var F=require("node:os");var Tt=require("node:path"),Tn=(0,F.platform)();var vn=(0,F.release)(),bn=(0,F.homedir)();function ot(){let r=process.env.XENO_AGENT_HOME?.trim();return r?(0,Tt.resolve)(r):(0,Tt.resolve)((0,F.homedir)(),".xeno-agent")}var Vt=1,Xt="recent.json",Ne=".lock",Yt=".entries",$e=3e4,vt=6e4,Qt=new Set(["EACCES","EBUSY","EPERM"]),Le=[5,10,20,40,80,160,320],at=new Map;function Fe(r,t){let e=(0,lt.createHash)("sha256").update(t).digest("hex");return k.join(`${r}${Yt}`,`${e}.json`)}async function bt(r,t,e){let n={schemaVersion:1,key:t,entry:e};await g(Fe(r,t),JSON.stringify(n)+`
50
50
  `)}async function Be(r,t){let e=`${r}${Yt}`,n;try{n=await S.readdir(e)}catch(i){if(i.code==="ENOENT")return;throw i}await Promise.all(n.filter(i=>i.endsWith(".json")).map(async i=>{let s=await S.readFile(k.join(e,i),"utf8").catch(()=>""),o=y(s,null);if(!(!o||o.schemaVersion!==1||typeof o.key!="string")){if(o.entry===null){delete t[o.key];return}typeof o.entry.sessionId!="string"||typeof o.entry.endedAt!="string"||(t[o.key]=o.entry)}}))}function Kt(r){if(!Number.isInteger(r)||r<=0)return!1;try{return process.kill(r,0),!0}catch(t){return t.code==="EPERM"}}async function je(r){try{let[t,e]=await Promise.all([S.readFile(k.join(r,"owner.json"),"utf8").catch(()=>""),S.stat(r)]),n=y(t,null);return n?.hostname===ct.hostname()&&Kt(n.pid)?!1:n?.hostname&&n.hostname!==ct.hostname()||!n?Date.now()-e.mtimeMs>vt:Date.now()-e.mtimeMs>vt||!Kt(n.pid)}catch{return!1}}async function Zt(r){for(let t=0;;t+=1)try{await S.rm(r,{recursive:!0});return}catch(e){let n=e.code;if(n==="ENOENT")return;let i=Le[t];if(process.platform!=="win32"||!n||!Qt.has(n)||i===void 0)throw e;await new Promise(s=>setTimeout(s,i))}}async function Ge(r,t){try{let e=await S.readFile(k.join(r,"owner.json"),"utf8");y(e,null)?.token===t&&await Zt(r)}catch(e){if(e.code!=="ENOENT")throw e}}async function Rt(r,t){let e=B(r),n=at.get(e)??Promise.resolve(),i,s=new Promise(o=>{i=o});at.set(e,s),await n;try{return await We(e,t)}finally{i(),at.get(e)===s&&at.delete(e)}}async function We(r,t){let e=`${r}${Ne}`,n=(0,lt.randomUUID)(),i=Date.now();await S.mkdir(k.dirname(r),{recursive:!0});for(let s=0;;s+=1){let o={schemaVersion:1,token:n,pid:process.pid,hostname:ct.hostname(),acquiredAt:new Date().toISOString()};try{await S.mkdir(e),await S.writeFile(k.join(e,"owner.json"),JSON.stringify(o),"utf8");break}catch(a){let l=a.code,c=process.platform==="win32"&&!!l&&Qt.has(l);if(l!=="EEXIST"&&!c)throw a;if(await je(e)){await Zt(e);continue}if(Date.now()-i>=$e)throw new Error(`Timed out waiting for recent-sessions index lock: ${e}`);let u=Math.min(100,5+s*5)+Math.floor(Math.random()*10);await new Promise(m=>setTimeout(m,u))}}try{return await t()}finally{await Ge(e,n)}}function B(r){return r===void 0?k.join(ot(),Xt):k.join(r,".xeno-agent",Xt)}function z(r){let t=k.normalize(r).replace(/[\\/]+$/,""),e=t.length>0?t:k.parse(k.normalize(r)).root;return process.platform==="win32"?e.toLowerCase():e}async function C(r){let t=B(r),e=tt(t)?await f(t):null,n=e?y(e,null):null,i=n&&typeof n=="object"?n:null,s={},o=i?.version===Vt&&i.entries&&typeof i.entries=="object"?i.entries:{};for(let[a,l]of Object.entries(o)){if(!l||typeof l!="object")continue;let c=l;typeof c.sessionId!="string"||c.sessionId.length===0||typeof c.endedAt=="string"&&(s[a]={sessionId:c.sessionId,endedAt:c.endedAt,role:typeof c.role=="string"?c.role:void 0})}return await Be(t,s),{version:Vt,entries:s}}async function ut(r,t={}){let e=await C(t.homeDir),n=z(r),i=e.entries[n];if(i&&!(t.role&&i.role&&i.role!==t.role))return i}async function pt(r,t={}){let e=z(r.cwd),n={sessionId:r.sessionId,role:r.role,endedAt:r.endedAt??new Date().toISOString()},i=B(t.homeDir);await bt(i,e,n),await Rt(t.homeDir,async()=>{let s=await C(t.homeDir);s.entries[e]=n,await g(i,JSON.stringify(s,null,2)+`
51
51
  `)})}async function te(r,t={}){let e=z(r),n=B(t.homeDir);(await C(t.homeDir)).entries[e]&&(await bt(n,e,null),await Rt(t.homeDir,async()=>{let s=await C(t.homeDir);delete s.entries[e],await g(n,JSON.stringify(s,null,2)+`
52
52
  `)}))}async function V(r,t={}){let e=await C(t.homeDir),n=Object.entries(e.entries).filter(([,s])=>s.sessionId===r).map(([s])=>s);if(n.length===0)return;let i=B(t.homeDir);await Promise.all(n.map(s=>bt(i,s,null))),await Rt(t.homeDir,async()=>{let s=await C(t.homeDir);for(let[o,a]of Object.entries(s.entries))a.sessionId===r&&delete s.entries[o];await g(i,JSON.stringify(s,null,2)+`
@@ -46,7 +46,7 @@ ${this.stringify(t.data)}
46
46
  `)+`
47
47
  `;await m(this.transcriptPath,a);let l=this.buildMarkdownDocument(o,"session store");if(await m(this.markdownPath,l),!this.workspaceMirrorDisabled){let c=await this.resolveWorkspaceMarkdownPath();if(c)try{let u=this.buildMarkdownDocument(o,"workspace mirror");await m(c,u)}catch(u){this.workspaceMirrorDisabled=!0,b("Transcript workspace mirror disabled",u)}}}async truncateAfterMessageCount(t){let e=await g(this.transcriptPath);if(!e)return;let n=G(e),i=Math.max(0,t),s=0,o=[];for(let c of n){if(c.type==="user_message"||c.type==="assistant_message"){if(s>=i)break;s+=1}o.push(c)}let a=o.length>0?o.map(c=>JSON.stringify(c)).join(`
48
48
  `)+`
49
- `:"";await m(this.transcriptPath,a);let l=this.buildMarkdownDocument(o,"session store");if(await m(this.markdownPath,l),!this.workspaceMirrorDisabled){let c=await this.resolveWorkspaceMarkdownPath();if(c)try{let u=this.buildMarkdownDocument(o,"workspace mirror");await m(c,u)}catch(u){this.workspaceMirrorDisabled=!0,b("Transcript workspace mirror disabled",u)}}}getSequence(){return this.sequence}async initialize(){try{let t=await g(this.transcriptPath);if(!t){this.sequence=0;return}let e=G(t);if(e.length===0){this.sequence=0;return}let n=e[e.length-1];this.sequence=n.sequence+1}catch(t){let e=t instanceof Error?t.message:String(t);b(`Transcript initialization warning: ${e}. Starting with empty transcript.`),this.sequence=0}}async flush(){await this.writeQueue}};import*as W from"path";import{randomUUID as he}from"crypto";import{stat as we}from"fs/promises";var fe={View:"Read",Replace:"Write",GlobTool:"Glob",GrepTool:"Grep",SQLiteAnalyze:"SqliteAnalyze",ReadNotebook:"NotebookRead",NotebookEditCell:"NotebookEdit"};function Y(r){return fe[r]??r}var N=class{sessionDir;checkpointsDir;autoInterval;lastCheckpointMessageCount=0;constructor(t,e){this.sessionDir=t,this.checkpointsDir=W.join(t,"checkpoints"),this.autoInterval=e?.autoInterval??10}async initialize(){let t=await this.list();t.length>0&&(this.lastCheckpointMessageCount=t[0].messageCount)}async create(t){await A(this.checkpointsDir);let e=he(),n={id:e,name:t.description,trigger:t.trigger,createdAt:new Date().toISOString(),messageCount:t.messages.length,tokenCount:this.estimateTokens(t.messages)},i={info:n,messages:t.messages},s=W.join(this.checkpointsDir,`${e}.json`);return await m(s,JSON.stringify(i,null,2)),this.lastCheckpointMessageCount=t.messages.length,n}async list(){let t=await It(this.checkpointsDir,/\.json$/),e=[];for(let n of t){let i=await g(n);if(i){let s=w(i,null);if(s){let o=await we(n);e.push({info:s.info,modifiedAtMs:o.mtimeMs})}}}return e.sort((n,i)=>new Date(i.info.createdAt).getTime()-new Date(n.info.createdAt).getTime()||i.modifiedAtMs-n.modifiedAtMs).map(({info:n})=>n)}async restore(t){let e=W.join(this.checkpointsDir,`${t}.json`),n;try{n=await g(e)}catch(s){let o=s instanceof Error?s.message:String(s);throw new Error(`Failed to read checkpoint ${t}: ${o}`)}if(!n)throw new Error(`Checkpoint not found: ${t} (path: ${e})`);let i=w(n,null);if(!i)throw new Error(`Invalid checkpoint data for ${t}: JSON parse failed`);if(!i.messages||!Array.isArray(i.messages))throw new Error(`Invalid checkpoint data for ${t}: missing or invalid messages array`);if(!i.info)throw new Error(`Invalid checkpoint data for ${t}: missing info object`);return{messages:i.messages,info:i.info}}shouldAutoCheckpoint(t){return t-this.lastCheckpointMessageCount>=this.autoInterval}static isDangerousOperation(t,e){if(t=Y(t),t==="Write")return!0;if(t==="Bash"){let i=e.command?.toLowerCase()||"";return["rm ","del ","git push","git reset","drop ","truncate"].some(o=>i.includes(o))}return!1}async delete(t){let e=W.join(this.checkpointsDir,`${t}.json`);await v(e)}estimateTokens(t){let e=0;for(let n of t)if(typeof n.content=="string")e+=Math.ceil(n.content.length/4);else if(Array.isArray(n.content))for(let i of n.content)"text"in i&&(e+=Math.ceil(i.text.length/4));return e}};import*as R from"path";import*as mt from"os";import*as $ from"fs";var ye=Symbol.for("@xenosystem/agent-sdk/shutdown-registry"),ke=globalThis,pt=ke[ye]??={cleanups:new Set,exitHandlerRegistered:!1,signalHandlersInstalled:!1},dt=pt.cleanups;function Se(){for(let r of dt)try{r()}catch{}}function $t(r){return dt.add(r),!pt.exitHandlerRegistered&&typeof process<"u"&&typeof process.on=="function"&&(pt.exitHandlerRegistered=!0,process.on("exit",Se)),()=>{dt.delete(r)}}var Lt="0.9.19";var xe=1e4,Ee=6e4,Pe="session.lock",Te="lock.json",H=new Set;function ve(){for(let r of H)try{$.unlinkSync(r)}catch{}H.clear()}$t(ve);var L=class r{sessionDir;lockPath;legacyLockPath;sessionId;heartbeatTimer;constructor(t){this.sessionDir=t,this.lockPath=R.join(t,Pe),this.legacyLockPath=R.join(t,Te),this.sessionId=R.basename(t)}async acquire(){let t=new Date().toISOString(),e={schemaVersion:1,name:`session:${this.sessionId}`,sessionId:this.sessionId,pid:process.pid,hostname:mt.hostname(),processStartedAt:new Date(Date.now()-Math.floor(process.uptime()*1e3)).toISOString(),version:Lt,acquiredAt:t,updatedAt:t,heartbeat:t},n=R.dirname(this.lockPath);await $.promises.mkdir(n,{recursive:!0});let i=await this.findExistingLockPath();if(i){if(!await this.isStalePath(i)){let o=await this.readLockAt(i);throw new Error(`Session ${this.sessionId} is already locked by PID ${o?.pid} on ${o?.hostname}`)}await v(i)}try{await $.promises.writeFile(this.lockPath,JSON.stringify(e,null,2),{flag:"wx",encoding:"utf-8"}),H.add(this.lockPath)}catch(s){if(s.code==="EEXIST"){if(!await this.isStalePath(this.lockPath)){let l=await this.readLockAt(this.lockPath);throw new Error(`Session ${this.sessionId} is already locked by PID ${l?.pid} on ${l?.hostname}`)}await v(this.lockPath);try{await $.promises.writeFile(this.lockPath,JSON.stringify(e,null,2),{flag:"wx",encoding:"utf-8"})}catch(l){throw l.code==="EEXIST"?new Error(`Session ${this.sessionId} lock was acquired by another process during stale recovery`):l}H.add(this.lockPath)}else throw s}}async release(){this.stopHeartbeat(),H.delete(this.lockPath),await v(this.lockPath)}async isLocked(){let t=await this.findExistingLockPath();return t?!await this.isStalePath(t):!1}async isStale(){let t=await this.findExistingLockPath();return t?this.isStalePath(t):!1}async isStalePath(t){let e=await this.readLockAt(t);if(!e)return!1;let n=new Date(e.heartbeat).getTime();return Date.now()-n>Ee}startHeartbeat(t=xe){this.heartbeatTimer&&this.stopHeartbeat(),this.heartbeatTimer=setInterval(async()=>{try{await this.updateHeartbeat()}catch(e){let n=e instanceof Error?e.message:String(e);if(e?.code==="ENOENT"){I("SessionLock: Session directory removed, stopping heartbeat"),this.stopHeartbeat();return}I(`SessionLock: Failed to update heartbeat: ${n}`)}},t),this.heartbeatTimer.unref()}stopHeartbeat(){this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=void 0)}async updateHeartbeat(){let t=await this.readLockAt(this.lockPath);t&&(t.pid!==process.pid||t.hostname!==mt.hostname()||(t.heartbeat=new Date().toISOString(),t.updatedAt=t.heartbeat,await m(this.lockPath,JSON.stringify(t,null,2))))}async readLock(){let t=await this.findExistingLockPath();return t?this.readLockAt(t):null}async readLockAt(t){let e=await g(t);return e?w(e,null):null}async findExistingLockPath(){return await g(this.lockPath)?this.lockPath:await g(this.legacyLockPath)?this.legacyLockPath:null}static async cleanStale(t){let e=await X(t),n=[];for(let i of e){let s=new r(i);if(await s.isStale()){let a=await s.findExistingLockPath();a&&await v(a),n.push(R.basename(i))}}return n}};import*as P from"path";import*as E from"path";function be(r,t){let e=E.resolve(r),n=E.resolve(r,t);return n===e?!0:e===E.parse(e).root?n.startsWith(e):n.startsWith(e+E.sep)}function M(r,t){if(E.isAbsolute(t))return E.resolve(t);if(!be(r,t))throw new Error(`PathSecurity: Path traversal attempt detected: ${t}`);return E.resolve(r,t)}import*as y from"path";import*as tt from"os";import*as k from"node:fs/promises";import{createHash as Ie,randomUUID as Ce}from"node:crypto";import{homedir as Bt,platform as Re,release as De}from"node:os";import{resolve as Ft}from"node:path";var Cn=Re();var Mn=De(),_n=Bt();function Q(){let r=process.env.XENO_AGENT_HOME?.trim();return r?Ft(r):Ft(Bt(),".xeno-agent")}var jt=1,Gt="recent.json",Me=".lock",Ht=".entries",_e=3e4,gt=6e4,Ut=new Set(["EACCES","EBUSY","EPERM"]),Ae=[5,10,20,40,80,160,320],Z=new Map;function Oe(r,t){let e=Ie("sha256").update(t).digest("hex");return y.join(`${r}${Ht}`,`${e}.json`)}async function ft(r,t,e){let n={schemaVersion:1,key:t,entry:e};await m(Oe(r,t),JSON.stringify(n)+`
49
+ `:"";await m(this.transcriptPath,a);let l=this.buildMarkdownDocument(o,"session store");if(await m(this.markdownPath,l),!this.workspaceMirrorDisabled){let c=await this.resolveWorkspaceMarkdownPath();if(c)try{let u=this.buildMarkdownDocument(o,"workspace mirror");await m(c,u)}catch(u){this.workspaceMirrorDisabled=!0,b("Transcript workspace mirror disabled",u)}}}getSequence(){return this.sequence}async initialize(){try{let t=await g(this.transcriptPath);if(!t){this.sequence=0;return}let e=G(t);if(e.length===0){this.sequence=0;return}let n=e[e.length-1];this.sequence=n.sequence+1}catch(t){let e=t instanceof Error?t.message:String(t);b(`Transcript initialization warning: ${e}. Starting with empty transcript.`),this.sequence=0}}async flush(){await this.writeQueue}};import*as W from"path";import{randomUUID as he}from"crypto";import{stat as we}from"fs/promises";var fe={View:"Read",Replace:"Write",GlobTool:"Glob",GrepTool:"Grep",SQLiteAnalyze:"SqliteAnalyze",ReadNotebook:"NotebookRead",NotebookEditCell:"NotebookEdit"};function Y(r){return fe[r]??r}var N=class{sessionDir;checkpointsDir;autoInterval;lastCheckpointMessageCount=0;constructor(t,e){this.sessionDir=t,this.checkpointsDir=W.join(t,"checkpoints"),this.autoInterval=e?.autoInterval??10}async initialize(){let t=await this.list();t.length>0&&(this.lastCheckpointMessageCount=t[0].messageCount)}async create(t){await A(this.checkpointsDir);let e=he(),n={id:e,name:t.description,trigger:t.trigger,createdAt:new Date().toISOString(),messageCount:t.messages.length,tokenCount:this.estimateTokens(t.messages)},i={info:n,messages:t.messages},s=W.join(this.checkpointsDir,`${e}.json`);return await m(s,JSON.stringify(i,null,2)),this.lastCheckpointMessageCount=t.messages.length,n}async list(){let t=await It(this.checkpointsDir,/\.json$/),e=[];for(let n of t){let i=await g(n);if(i){let s=w(i,null);if(s){let o=await we(n);e.push({info:s.info,modifiedAtMs:o.mtimeMs})}}}return e.sort((n,i)=>new Date(i.info.createdAt).getTime()-new Date(n.info.createdAt).getTime()||i.modifiedAtMs-n.modifiedAtMs).map(({info:n})=>n)}async restore(t){let e=W.join(this.checkpointsDir,`${t}.json`),n;try{n=await g(e)}catch(s){let o=s instanceof Error?s.message:String(s);throw new Error(`Failed to read checkpoint ${t}: ${o}`)}if(!n)throw new Error(`Checkpoint not found: ${t} (path: ${e})`);let i=w(n,null);if(!i)throw new Error(`Invalid checkpoint data for ${t}: JSON parse failed`);if(!i.messages||!Array.isArray(i.messages))throw new Error(`Invalid checkpoint data for ${t}: missing or invalid messages array`);if(!i.info)throw new Error(`Invalid checkpoint data for ${t}: missing info object`);return{messages:i.messages,info:i.info}}shouldAutoCheckpoint(t){return t-this.lastCheckpointMessageCount>=this.autoInterval}static isDangerousOperation(t,e){if(t=Y(t),t==="Write")return!0;if(t==="Bash"){let i=e.command?.toLowerCase()||"";return["rm ","del ","git push","git reset","drop ","truncate"].some(o=>i.includes(o))}return!1}async delete(t){let e=W.join(this.checkpointsDir,`${t}.json`);await v(e)}estimateTokens(t){let e=0;for(let n of t)if(typeof n.content=="string")e+=Math.ceil(n.content.length/4);else if(Array.isArray(n.content))for(let i of n.content)"text"in i&&(e+=Math.ceil(i.text.length/4));return e}};import*as R from"path";import*as mt from"os";import*as $ from"fs";var ye=Symbol.for("@xenosystem/agent-sdk/shutdown-registry"),ke=globalThis,pt=ke[ye]??={cleanups:new Set,exitHandlerRegistered:!1,signalHandlersInstalled:!1},dt=pt.cleanups;function Se(){for(let r of dt)try{r()}catch{}}function $t(r){return dt.add(r),!pt.exitHandlerRegistered&&typeof process<"u"&&typeof process.on=="function"&&(pt.exitHandlerRegistered=!0,process.on("exit",Se)),()=>{dt.delete(r)}}var Lt="0.9.21";var xe=1e4,Ee=6e4,Pe="session.lock",Te="lock.json",H=new Set;function ve(){for(let r of H)try{$.unlinkSync(r)}catch{}H.clear()}$t(ve);var L=class r{sessionDir;lockPath;legacyLockPath;sessionId;heartbeatTimer;constructor(t){this.sessionDir=t,this.lockPath=R.join(t,Pe),this.legacyLockPath=R.join(t,Te),this.sessionId=R.basename(t)}async acquire(){let t=new Date().toISOString(),e={schemaVersion:1,name:`session:${this.sessionId}`,sessionId:this.sessionId,pid:process.pid,hostname:mt.hostname(),processStartedAt:new Date(Date.now()-Math.floor(process.uptime()*1e3)).toISOString(),version:Lt,acquiredAt:t,updatedAt:t,heartbeat:t},n=R.dirname(this.lockPath);await $.promises.mkdir(n,{recursive:!0});let i=await this.findExistingLockPath();if(i){if(!await this.isStalePath(i)){let o=await this.readLockAt(i);throw new Error(`Session ${this.sessionId} is already locked by PID ${o?.pid} on ${o?.hostname}`)}await v(i)}try{await $.promises.writeFile(this.lockPath,JSON.stringify(e,null,2),{flag:"wx",encoding:"utf-8"}),H.add(this.lockPath)}catch(s){if(s.code==="EEXIST"){if(!await this.isStalePath(this.lockPath)){let l=await this.readLockAt(this.lockPath);throw new Error(`Session ${this.sessionId} is already locked by PID ${l?.pid} on ${l?.hostname}`)}await v(this.lockPath);try{await $.promises.writeFile(this.lockPath,JSON.stringify(e,null,2),{flag:"wx",encoding:"utf-8"})}catch(l){throw l.code==="EEXIST"?new Error(`Session ${this.sessionId} lock was acquired by another process during stale recovery`):l}H.add(this.lockPath)}else throw s}}async release(){this.stopHeartbeat(),H.delete(this.lockPath),await v(this.lockPath)}async isLocked(){let t=await this.findExistingLockPath();return t?!await this.isStalePath(t):!1}async isStale(){let t=await this.findExistingLockPath();return t?this.isStalePath(t):!1}async isStalePath(t){let e=await this.readLockAt(t);if(!e)return!1;let n=new Date(e.heartbeat).getTime();return Date.now()-n>Ee}startHeartbeat(t=xe){this.heartbeatTimer&&this.stopHeartbeat(),this.heartbeatTimer=setInterval(async()=>{try{await this.updateHeartbeat()}catch(e){let n=e instanceof Error?e.message:String(e);if(e?.code==="ENOENT"){I("SessionLock: Session directory removed, stopping heartbeat"),this.stopHeartbeat();return}I(`SessionLock: Failed to update heartbeat: ${n}`)}},t),this.heartbeatTimer.unref()}stopHeartbeat(){this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=void 0)}async updateHeartbeat(){let t=await this.readLockAt(this.lockPath);t&&(t.pid!==process.pid||t.hostname!==mt.hostname()||(t.heartbeat=new Date().toISOString(),t.updatedAt=t.heartbeat,await m(this.lockPath,JSON.stringify(t,null,2))))}async readLock(){let t=await this.findExistingLockPath();return t?this.readLockAt(t):null}async readLockAt(t){let e=await g(t);return e?w(e,null):null}async findExistingLockPath(){return await g(this.lockPath)?this.lockPath:await g(this.legacyLockPath)?this.legacyLockPath:null}static async cleanStale(t){let e=await X(t),n=[];for(let i of e){let s=new r(i);if(await s.isStale()){let a=await s.findExistingLockPath();a&&await v(a),n.push(R.basename(i))}}return n}};import*as P from"path";import*as E from"path";function be(r,t){let e=E.resolve(r),n=E.resolve(r,t);return n===e?!0:e===E.parse(e).root?n.startsWith(e):n.startsWith(e+E.sep)}function M(r,t){if(E.isAbsolute(t))return E.resolve(t);if(!be(r,t))throw new Error(`PathSecurity: Path traversal attempt detected: ${t}`);return E.resolve(r,t)}import*as y from"path";import*as tt from"os";import*as k from"node:fs/promises";import{createHash as Ie,randomUUID as Ce}from"node:crypto";import{homedir as Bt,platform as Re,release as De}from"node:os";import{resolve as Ft}from"node:path";var Cn=Re();var Mn=De(),_n=Bt();function Q(){let r=process.env.XENO_AGENT_HOME?.trim();return r?Ft(r):Ft(Bt(),".xeno-agent")}var jt=1,Gt="recent.json",Me=".lock",Ht=".entries",_e=3e4,gt=6e4,Ut=new Set(["EACCES","EBUSY","EPERM"]),Ae=[5,10,20,40,80,160,320],Z=new Map;function Oe(r,t){let e=Ie("sha256").update(t).digest("hex");return y.join(`${r}${Ht}`,`${e}.json`)}async function ft(r,t,e){let n={schemaVersion:1,key:t,entry:e};await m(Oe(r,t),JSON.stringify(n)+`
50
50
  `)}async function Ne(r,t){let e=`${r}${Ht}`,n;try{n=await k.readdir(e)}catch(i){if(i.code==="ENOENT")return;throw i}await Promise.all(n.filter(i=>i.endsWith(".json")).map(async i=>{let s=await k.readFile(y.join(e,i),"utf8").catch(()=>""),o=w(s,null);if(!(!o||o.schemaVersion!==1||typeof o.key!="string")){if(o.entry===null){delete t[o.key];return}typeof o.entry.sessionId!="string"||typeof o.entry.endedAt!="string"||(t[o.key]=o.entry)}}))}function Wt(r){if(!Number.isInteger(r)||r<=0)return!1;try{return process.kill(r,0),!0}catch(t){return t.code==="EPERM"}}async function $e(r){try{let[t,e]=await Promise.all([k.readFile(y.join(r,"owner.json"),"utf8").catch(()=>""),k.stat(r)]),n=w(t,null);return n?.hostname===tt.hostname()&&Wt(n.pid)?!1:n?.hostname&&n.hostname!==tt.hostname()||!n?Date.now()-e.mtimeMs>gt:Date.now()-e.mtimeMs>gt||!Wt(n.pid)}catch{return!1}}async function Jt(r){for(let t=0;;t+=1)try{await k.rm(r,{recursive:!0});return}catch(e){let n=e.code;if(n==="ENOENT")return;let i=Ae[t];if(process.platform!=="win32"||!n||!Ut.has(n)||i===void 0)throw e;await new Promise(s=>setTimeout(s,i))}}async function Le(r,t){try{let e=await k.readFile(y.join(r,"owner.json"),"utf8");w(e,null)?.token===t&&await Jt(r)}catch(e){if(e.code!=="ENOENT")throw e}}async function ht(r,t){let e=F(r),n=Z.get(e)??Promise.resolve(),i,s=new Promise(o=>{i=o});Z.set(e,s),await n;try{return await Fe(e,t)}finally{i(),Z.get(e)===s&&Z.delete(e)}}async function Fe(r,t){let e=`${r}${Me}`,n=Ce(),i=Date.now();await k.mkdir(y.dirname(r),{recursive:!0});for(let s=0;;s+=1){let o={schemaVersion:1,token:n,pid:process.pid,hostname:tt.hostname(),acquiredAt:new Date().toISOString()};try{await k.mkdir(e),await k.writeFile(y.join(e,"owner.json"),JSON.stringify(o),"utf8");break}catch(a){let l=a.code,c=process.platform==="win32"&&!!l&&Ut.has(l);if(l!=="EEXIST"&&!c)throw a;if(await $e(e)){await Jt(e);continue}if(Date.now()-i>=_e)throw new Error(`Timed out waiting for recent-sessions index lock: ${e}`);let u=Math.min(100,5+s*5)+Math.floor(Math.random()*10);await new Promise(d=>setTimeout(d,u))}}try{return await t()}finally{await Le(e,n)}}function F(r){return r===void 0?y.join(Q(),Gt):y.join(r,".xeno-agent",Gt)}function et(r){let t=y.normalize(r).replace(/[\\/]+$/,""),e=t.length>0?t:y.parse(y.normalize(r)).root;return process.platform==="win32"?e.toLowerCase():e}async function _(r){let t=F(r),e=V(t)?await g(t):null,n=e?w(e,null):null,i=n&&typeof n=="object"?n:null,s={},o=i?.version===jt&&i.entries&&typeof i.entries=="object"?i.entries:{};for(let[a,l]of Object.entries(o)){if(!l||typeof l!="object")continue;let c=l;typeof c.sessionId!="string"||c.sessionId.length===0||typeof c.endedAt=="string"&&(s[a]={sessionId:c.sessionId,endedAt:c.endedAt,role:typeof c.role=="string"?c.role:void 0})}return await Ne(t,s),{version:jt,entries:s}}async function wt(r,t={}){let e=await _(t.homeDir),n=et(r),i=e.entries[n];if(i&&!(t.role&&i.role&&i.role!==t.role))return i}async function yt(r,t={}){let e=et(r.cwd),n={sessionId:r.sessionId,role:r.role,endedAt:r.endedAt??new Date().toISOString()},i=F(t.homeDir);await ft(i,e,n),await ht(t.homeDir,async()=>{let s=await _(t.homeDir);s.entries[e]=n,await m(i,JSON.stringify(s,null,2)+`
51
51
  `)})}async function Be(r,t={}){let e=et(r),n=F(t.homeDir);(await _(t.homeDir)).entries[e]&&(await ft(n,e,null),await ht(t.homeDir,async()=>{let s=await _(t.homeDir);delete s.entries[e],await m(n,JSON.stringify(s,null,2)+`
52
52
  `)}))}async function nt(r,t={}){let e=await _(t.homeDir),n=Object.entries(e.entries).filter(([,s])=>s.sessionId===r).map(([s])=>s);if(n.length===0)return;let i=F(t.homeDir);await Promise.all(n.map(s=>ft(i,s,null))),await ht(t.homeDir,async()=>{let s=await _(t.homeDir);for(let[o,a]of Object.entries(s.entries))a.sessionId===r&&delete s.entries[o];await m(i,JSON.stringify(s,null,2)+`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xenosystem/agent-sdk",
3
- "version": "0.9.19",
3
+ "version": "0.9.21",
4
4
  "description": "XENO Agent SDK built from the same engine as XENO CODE",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -188,7 +188,7 @@
188
188
  "test:release-evidence": "node --test tests/release-certification.test.mjs tests/release-gate-observability.test.mjs",
189
189
  "compliance:runtime-platform": "node scripts/collect-runtime-platform-evidence.mjs",
190
190
  "test:ga:engineering": "npm run typecheck && npm run compliance && npm run test:runtime-coordination && npm run test:tool-schema-conformance && npm run test:tool-failure-guard && npm run test:containment && npm run test:context-compaction && npm run test:provider-conformance && npm run test:app-server-v2 && npm run test:observability && npm run test:package-candidate && npm run test:release-evidence",
191
- "test:ga": "npm run test:ga:engineering && node scripts/verify-release-version.mjs --manifest package.json --require-unused --require-greater-than-latest && node scripts/verify-sdk-ga-evidence.mjs",
191
+ "test:ga": "npm run test:ga:engineering && node scripts/verify-release-version.mjs --manifest package.json --require-unused --require-greater-than-latest && node scripts/verify-sdk-ga-evidence.mjs release/evidence",
192
192
  "bench:coding-tools": "npm run build && node scripts/run-benchmark.mjs",
193
193
  "prepublishOnly": "npm run build && npm run typecheck && node scripts/verify-dist-exports.mjs"
194
194
  },