@kitelev/exocortex-cli 15.169.0 → 15.169.1

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.
Files changed (2) hide show
  1. package/dist/index.js +2 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // @kitelev/exocortex-cli v15.169.0
2
+ // @kitelev/exocortex-cli v15.169.1
3
3
  // CLI tool for Exocortex knowledge management system - SPARQL queries, task management, and more
4
4
  // License: MIT
5
5
 
@@ -805,7 +805,7 @@ exo__BacklinksTableBlock_columns:${f==="[]"?" []":f}
805
805
  `),console.log(`${"Rank".padEnd(6)}${"Term".padEnd(30)}${"Freq".padEnd(8)}Sample UIDs`),console.log("-".repeat(90)),c.forEach((u,f)=>{let d=`#${f+1}`.padEnd(6),h=u.term.padEnd(30),p=String(u.frequency).padEnd(8),y=u.sample_uids.join(", ");console.log(`${d}${h}${p}${y}`)})})}o(ON,"backfillOrphanTermsCommand");function FN(){let n=new ae("backfill").description("Concept backfill tools for aiKnow assets");return n.addCommand(PN()),n.addCommand(ON()),n}o(FN,"backfillCommand");var Fy=require("path"),BN=require("fs"),VN=require("os");var Py=require("child_process"),Oy=require("fs"),kN=require("path");var Zi=require("fs"),Ry=K(require("path")),NN=require("crypto");var fJ=/^---\s*\r?\n([\s\S]*?)\r?\n---\s*(?:\r?\n([\s\S]*))?$/;function DN(n){let e=n.match(fJ);if(!e)return null;let[,t,r=""]=e,i=ar.load(t);if(i==null)return{frontmatter:{},body:r};if(typeof i!="object"||Array.isArray(i))throw new Error("frontmatter is not a YAML mapping");return{frontmatter:i,body:r}}o(DN,"parseFile");function dJ(n,e){let t=ar.dump(n,{lineWidth:-1,quotingType:'"',forceQuotes:!1,noRefs:!0}),r=e.length>0?e:"";return`---
806
806
  ${t}---
807
807
  ${r}`}o(dJ,"serializeFile");function LN(n,e,t={}){let r=Ry.default.dirname(n),i=Ry.default.basename(n),s=Ry.default.join(r,`.${i}.tmp.${process.pid}.${(0,NN.randomBytes)(6).toString("hex")}`);try{let a=(0,Zi.readFileSync)(n,"utf8"),c;try{c=DN(a)}catch(f){return{success:!1,verified:!1,reason:"parse-error",error:f.message}}if(!c)return{success:!1,verified:!1,reason:"no-frontmatter"};let l={...c.frontmatter,...e},u=dJ(l,c.body);if((0,Zi.writeFileSync)(s,u,"utf8"),(0,Zi.renameSync)(s,n),t.verifyKey!==void 0){let f=(0,Zi.readFileSync)(n,"utf8"),d;try{d=DN(f)}catch(p){return{success:!1,verified:!1,reason:"parse-error",error:p.message}}if(!d)return{success:!1,verified:!1,reason:"no-frontmatter"};let h=d.frontmatter[t.verifyKey];return h!==t.verifyValue?{success:!1,verified:!1,reason:"verify-mismatch",error:`expected ${t.verifyKey}=${String(t.verifyValue)}, got ${String(h)}`}:{success:!0,verified:!0}}return{success:!0,verified:!0}}catch(a){if((0,Zi.existsSync)(s))try{(0,Zi.unlinkSync)(s)}catch{}return{success:!1,verified:!1,reason:"fs-error",error:a.message}}}o(LN,"atomicUpdateFrontmatter");var hJ=/^claude-child-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/,pJ=/^claude-child-([0-9a-f]{8})-(\d+)$/,mJ="EffortStatusDoing";function MN(n){return e=>new Promise((t,r)=>{n(e,(i,s,a)=>{i?r(Object.assign(i,{stdout:s,stderr:a})):t(s)})})}o(MN,"makeExecPromise");async function gJ(n=Py.exec){let e=MN(n),t;try{t=await e("tmux list-sessions -F '#{session_name}' 2>/dev/null")}catch{return[]}let r=[];for(let i of t.split(`
808
- `).map(s=>s.trim()).filter(Boolean)){let s=hJ.exec(i);if(s){r.push({sessionName:i,uuid:s[1],type:"full"});continue}let a=pJ.exec(i);a&&r.push({sessionName:i,uuid:a[1],type:"short"})}return r}o(gJ,"listClaudeChildSessions");function yJ(n,e,t){let r=null,i=e.toLowerCase();function s(a){if(r)return;let c;try{c=(0,Oy.readdirSync)(a,{withFileTypes:!0})}catch{return}for(let l of c){if(r)return;if(l.name.startsWith(".")||l.name==="node_modules")continue;let u=(0,kN.join)(a,l.name);if(l.isDirectory())s(u);else if(l.name.endsWith(".md")){let f=l.name.slice(0,-3).toLowerCase();(t==="full"&&f===i||t==="short"&&f.startsWith(i))&&(r=u)}}}return o(s,"walk"),s(n),r}o(yJ,"findVaultFile");function _J(n,e){try{let i=(e??(s=>(0,Oy.readFileSync)(s,"utf8")))(n).match(/ems__Effort_status\s*:.*\[\[([^\]]+)\]\]/);return i?i[1].includes(mJ):!1}catch{return!1}}o(_J,"isTaskDoing");async function jN(n,e=Py.exec,t){let r=await gJ(e),i=[];for(let s of r){let a=yJ(n,s.uuid,s.type);if(!a){i.push({sessionName:s.sessionName,taskUuid:s.uuid,taskFilePath:null,reason:"vault task not found"});continue}_J(a,t)||i.push({sessionName:s.sessionName,taskUuid:s.uuid,taskFilePath:a,reason:"vault task status != Doing"})}return i}o(jN,"detectOrphans");async function $N(n,e,t=Py.exec,r=LN){let i=MN(t);if(e)return{ok:!0};let s=new Date().toISOString();if(n.taskFilePath)try{r(n.taskFilePath,{ems__Effort_status:"[[ems__EffortStatusFailed]]",aiTask__Task_lastError:`orphan recovery: ${n.reason}`,exo__Asset_updatedAt:s})}catch(a){return{ok:!1,error:`vault update failed: ${a.message}`}}try{await i(`tmux kill-session -t ${JSON.stringify(n.sessionName)}`)}catch{}return{ok:!0}}o($N,"recoverOrphan");function SJ(){return process.env.EXOCORTEX_VAULT??(0,Fy.join)((0,VN.homedir)(),"vault-2025")}o(SJ,"defaultVault");function UN(){return new ae("recover").description("Detect and recover orphaned claude-child tmux sessions. A session is orphaned when the corresponding vault task is not in Doing status. Default mode: dry-run (no changes). Use --apply to perform recovery.").option("--vault <path>","Path to Obsidian vault",SJ()).option("--dry-run","List orphans without applying changes (default)",!1).option("--apply","Apply orphan recovery: set Failed + kill tmux session",!1).action(async n=>{let e=(0,Fy.resolve)(n.vault);if(!(0,BN.existsSync)(e)){console.error(`[recover] vault not found: ${e}`),process.exitCode=1;return}let t=!n.apply;console.log(`[recover] vault=${e} mode=${t?"dry-run":"apply"}`);let r=await jN(e);if(r.length===0){console.log("[recover] No orphaned claude-child sessions found.");return}console.log(`[recover] Found ${r.length} orphan(s):`);for(let a of r){let c=a.taskFilePath??"(not found in vault)";console.log(` session=${a.sessionName} uuid=${a.taskUuid} reason=${a.reason}`),console.log(` file=${c}`)}if(t){console.log("[recover] Dry-run mode: no changes applied. Use --apply to recover.");return}let i=0,s=0;for(let a of r){let c=await $N(a,!1);c.ok?(i++,console.log(`[recover] RECOVERED: ${a.sessionName}`)):(s++,console.error(`[recover] ERROR recovering ${a.sessionName}: ${c.error}`))}console.log(`[recover] Done: recovered=${i} errors=${s}`),s>0&&(process.exitCode=1)})}o(UN,"recoverCommand");function qN(n){n.addCommand(eF()),n.addCommand(iF()),n.addCommand(sF())}o(qN,"addQuerySubcommands");function WN(n){let e=new ae;e.name("exocortex").description("CLI tool for Exocortex knowledge management system").version(n??"15.169.0");let t=e.command("exoql").description("ExoQL query execution and cache management");qN(t);let r=e.command("sparql").description("(deprecated) Use 'exoql' instead");return qN(r),r.hook("preAction",()=>{console.error('\u26A0\uFE0F "sparql" is deprecated. Use "exoql" instead.')}),e.addCommand(hD()),e.addCommand(gD()),e.addCommand(yD()),e.addCommand(SD()),e.addCommand(vD()),e.addCommand(AD()),e.addCommand(RD()),e.addCommand(UD()),e.addCommand(GD()),e.addCommand(YD()),e.addCommand(ZD()),e.addCommand(eN()),e.addCommand(rN()),e.addCommand(hN()),e.addCommand(yN()),e.addCommand(TN()),e.addCommand(AN()),e.addCommand(FN()),e.addCommand(UN()),e}o(WN,"createProgram");WN().parse();0&&(module.exports={createProgram});
808
+ `).map(s=>s.trim()).filter(Boolean)){let s=hJ.exec(i);if(s){r.push({sessionName:i,uuid:s[1],type:"full"});continue}let a=pJ.exec(i);a&&r.push({sessionName:i,uuid:a[1],type:"short"})}return r}o(gJ,"listClaudeChildSessions");function yJ(n,e,t){let r=null,i=e.toLowerCase();function s(a){if(r)return;let c;try{c=(0,Oy.readdirSync)(a,{withFileTypes:!0})}catch{return}for(let l of c){if(r)return;if(l.name.startsWith(".")||l.name==="node_modules")continue;let u=(0,kN.join)(a,l.name);if(l.isDirectory())s(u);else if(l.name.endsWith(".md")){let f=l.name.slice(0,-3).toLowerCase();(t==="full"&&f===i||t==="short"&&f.startsWith(i))&&(r=u)}}}return o(s,"walk"),s(n),r}o(yJ,"findVaultFile");function _J(n,e){try{let i=(e??(s=>(0,Oy.readFileSync)(s,"utf8")))(n).match(/ems__Effort_status\s*:.*\[\[([^\]]+)\]\]/);return i?i[1].includes(mJ):!1}catch{return!1}}o(_J,"isTaskDoing");async function jN(n,e=Py.exec,t){let r=await gJ(e),i=[];for(let s of r){let a=yJ(n,s.uuid,s.type);if(!a){i.push({sessionName:s.sessionName,taskUuid:s.uuid,taskFilePath:null,reason:"vault task not found"});continue}_J(a,t)||i.push({sessionName:s.sessionName,taskUuid:s.uuid,taskFilePath:a,reason:"vault task status != Doing"})}return i}o(jN,"detectOrphans");async function $N(n,e,t=Py.exec,r=LN){let i=MN(t);if(e)return{ok:!0};let s=new Date().toISOString();if(n.taskFilePath)try{r(n.taskFilePath,{ems__Effort_status:"[[ems__EffortStatusFailed]]",aiTask__Task_lastError:`orphan recovery: ${n.reason}`,exo__Asset_updatedAt:s})}catch(a){return{ok:!1,error:`vault update failed: ${a.message}`}}try{await i(`tmux kill-session -t ${JSON.stringify(n.sessionName)}`)}catch{}return{ok:!0}}o($N,"recoverOrphan");function SJ(){return process.env.EXOCORTEX_VAULT??(0,Fy.join)((0,VN.homedir)(),"vault-2025")}o(SJ,"defaultVault");function UN(){return new ae("recover").description("Detect and recover orphaned claude-child tmux sessions. A session is orphaned when the corresponding vault task is not in Doing status. Default mode: dry-run (no changes). Use --apply to perform recovery.").option("--vault <path>","Path to Obsidian vault",SJ()).option("--dry-run","List orphans without applying changes (default)",!1).option("--apply","Apply orphan recovery: set Failed + kill tmux session",!1).action(async n=>{let e=(0,Fy.resolve)(n.vault);if(!(0,BN.existsSync)(e)){console.error(`[recover] vault not found: ${e}`),process.exitCode=1;return}let t=!n.apply;console.log(`[recover] vault=${e} mode=${t?"dry-run":"apply"}`);let r=await jN(e);if(r.length===0){console.log("[recover] No orphaned claude-child sessions found.");return}console.log(`[recover] Found ${r.length} orphan(s):`);for(let a of r){let c=a.taskFilePath??"(not found in vault)";console.log(` session=${a.sessionName} uuid=${a.taskUuid} reason=${a.reason}`),console.log(` file=${c}`)}if(t){console.log("[recover] Dry-run mode: no changes applied. Use --apply to recover.");return}let i=0,s=0;for(let a of r){let c=await $N(a,!1);c.ok?(i++,console.log(`[recover] RECOVERED: ${a.sessionName}`)):(s++,console.error(`[recover] ERROR recovering ${a.sessionName}: ${c.error}`))}console.log(`[recover] Done: recovered=${i} errors=${s}`),s>0&&(process.exitCode=1)})}o(UN,"recoverCommand");function qN(n){n.addCommand(eF()),n.addCommand(iF()),n.addCommand(sF())}o(qN,"addQuerySubcommands");function WN(n){let e=new ae;e.name("exocortex").description("CLI tool for Exocortex knowledge management system").version(n??"15.169.1");let t=e.command("exoql").description("ExoQL query execution and cache management");qN(t);let r=e.command("sparql").description("(deprecated) Use 'exoql' instead");return qN(r),r.hook("preAction",()=>{console.error('\u26A0\uFE0F "sparql" is deprecated. Use "exoql" instead.')}),e.addCommand(hD()),e.addCommand(gD()),e.addCommand(yD()),e.addCommand(SD()),e.addCommand(vD()),e.addCommand(AD()),e.addCommand(RD()),e.addCommand(UD()),e.addCommand(GD()),e.addCommand(YD()),e.addCommand(ZD()),e.addCommand(eN()),e.addCommand(rN()),e.addCommand(hN()),e.addCommand(yN()),e.addCommand(TN()),e.addCommand(AN()),e.addCommand(FN()),e.addCommand(UN()),e}o(WN,"createProgram");WN().parse();0&&(module.exports={createProgram});
809
809
  /*! Bundled license information:
810
810
 
811
811
  reflect-metadata/Reflect.js:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitelev/exocortex-cli",
3
- "version": "15.169.0",
3
+ "version": "15.169.1",
4
4
  "description": "CLI tool for Exocortex knowledge management system - SPARQL queries, task management, and more",
5
5
  "main": "dist/index.js",
6
6
  "bin": {