@kitelev/exocortex-cli 16.13.3 → 16.13.4

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 v16.13.3
2
+ // @kitelev/exocortex-cli v16.13.4
3
3
  // CLI tool for Exocortex knowledge management system - SPARQL queries, task management, and more
4
4
  // License: MIT
5
5
 
@@ -760,7 +760,7 @@ ${r}`}o(NY,"serializeFile");function gD(n,e,t={}){let r=Mg.default.dirname(n),i=
760
760
  `).map(s=>s.trim()).filter(Boolean)){let s=LY.exec(i);if(s){r.push({sessionName:i,uuid:s[1],type:"full"});continue}let a=kY.exec(i);a&&r.push({sessionName:i,uuid:a[1],type:"short"})}return r}o(MY,"listClaudeChildSessions");function $Y(n,e,t){let r=null,i=e.toLowerCase();function s(a){if(r)return;let c;try{c=(0,Vg.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,yD.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($Y,"findVaultFile");function VY(n,e){try{let i=(e??(s=>(0,Vg.readFileSync)(s,"utf8")))(n).match(/ems__Effort_status\s*:.*\[\[([^\]]+)\]\]/);return i?i[1].includes(jY):!1}catch{return!1}}o(VY,"isTaskDoing");async function bD(n,e=$g.exec,t){let r=await MY(e),i=[];for(let s of r){let a=$Y(n,s.uuid,s.type);if(!a){i.push({sessionName:s.sessionName,taskUuid:s.uuid,taskFilePath:null,reason:"vault task not found"});continue}VY(a,t)||i.push({sessionName:s.sessionName,taskUuid:s.uuid,taskFilePath:a,reason:"vault task status != Doing"})}return i}o(bD,"detectOrphans");async function SD(n,e,t=$g.exec,r=gD){let i=_D(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(SD,"recoverOrphan");function BY(){return process.env.EXOCORTEX_VAULT??(0,Bg.join)((0,vD.homedir)(),"vault-2025")}o(BY,"defaultVault");function ED(){return new Ie("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",BY()).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,Bg.resolve)(n.vault);if(!(0,wD.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 bD(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 SD(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(ED,"recoverCommand");var d2=require("fs"),Ug=require("path"),Wn=le(br());function UY(n,e){return e.concat([n])}o(UY,"collectAlso");var qY="https://exocortex.my/ontology/find#Alias_sparql",WY="https://exocortex.my/ontology/exo#Asset_label";function Kl(n){if(n&&typeof n=="object"&&"value"in n){let e=n.value;return typeof e=="string"?e:String(e)}return String(n)}o(Kl,"nodeValue");async function GY(n,e){let t=await n.match(void 0,void 0,void 0),r=[];for(let s of t)Kl(s.predicate)!==WY||Kl(s.object)!==e||r.push(Kl(s.subject));if(r.length===0)return null;let i=[];for(let s of r)for(let a of t)Kl(a.predicate)===qY&&Kl(a.subject)===s&&i.push(Kl(a.object));if(i.length===0)return null;if(i.length>1)throw new Vt(`Ambiguous find__Alias "${e}" \u2014 ${i.length} instances define a sparql fragment`,`Ensure exactly one find__Alias asset has exo:Asset_label "${e}"`);return i[0]}o(GY,"resolveAliasFragment");var zY=/^([a-z][a-zA-Z0-9]*)__([A-Za-z0-9_]+)$/,HY="https://exocortex.my/ontology/";function QY(n,e){let t=zY.exec(e);if(t){let i=`<${HY}${t[1]}#${t[2]}>`;return n.replace(/\?value\b/g,i)}let r=e.replace(/\\/g,"\\\\").replace(/"/g,'\\"');return n.replace(/\?value\b/g,`"${r}"`)}o(QY,"bindValueLiteral");function TD(){return new Ie("find").description("Find vault assets via SPARQL \u2014 outputs file paths one per line (RFC 8e83442b T1.1)").option("--vault <path>","Path to Obsidian vault",process.cwd()).option("--also <path>","Additional vault to include (repeatable)",UY,[]).option("--sparql <query>","SPARQL SELECT query (must bind ?path)").option("--class <value>","Filter by class label via find__Alias 'class' (e.g. ems__Task)").action(async n=>{pe.setFormat("text");try{if(n.sparql&&n.class)throw new Vt("--sparql and --class are mutually exclusive","Pass either a raw --sparql query or a find__Alias-backed flag like --class");if(!n.sparql&&!n.class)throw new Vt("one of --sparql <query> or --class <value> is required",'exocortex find --class ems__Task OR exocortex find --sparql "SELECT ?path WHERE { ... }"');let e=(0,Ug.resolve)(n.vault);if(!(0,d2.existsSync)(e))throw new Fe(e);let t=new Lt(e),i=await new Wn.NoteToRDFConverter(t).convertVault(),s=n.also||[];for(let w of s){let T=(0,Ug.resolve)(w);if(!(0,d2.existsSync)(T))throw new Fe(T);let C=new Lt(T),$=await new Wn.NoteToRDFConverter(C).convertVault();i=i.concat($)}let a=new Wn.InMemoryTripleStore;await a.addAll(i);let c;if(n.class){let w=await GY(a,"class");if(w===null)throw new Vt('No find__Alias with exo:Asset_label "class" was found in the vault',"Seed a find__Alias asset (label=class) or fall back to exocortex find --sparql");c=`SELECT ?path WHERE { ${QY(w,n.class)} }`}else c=n.sparql;let l=Ul(c);l=Ya(l);let u=new Wn.ExoQLParser,f=Xa(Ka(e));for(let w of s){let T=Xa(Ka((0,Ug.resolve)(w)));for(let[C,M]of T)f.has(C)||f.set(C,M)}f.size>0&&u.setVaultPrefixes(f);let d=u.parse(l),p=new Wn.ExoQLAlgebraTranslator().translate(d);p.type!=="construct"&&(p=new Wn.AlgebraOptimizer().optimize(p));let S=await new Wn.ExoQLQueryExecutor(a).executeAll(p),v="obsidian://vault/";for(let w of S){let C=w.toJSON().path;if(typeof C!="string"||!C.startsWith(v))continue;let M=C.slice(v.length),$;try{$=decodeURIComponent(M)}catch{$=M}process.stdout.write($+`
761
761
  `)}}catch(e){pe.handle(e),process.exit(5)}})}o(TD,"findCommand");var p2=require("fs"),m2=require("path"),tt=le(br());var RD=le(br()),Ut=le(xD());var ID="obsidian://vault/";function aX(n){let e=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;return{async resolveTargetPath(t){if(!t)throw new Error("Cannot resolve empty targetIRI to a vault path");let r=t;if(r.startsWith(ID))r=decodeURI(r.slice(ID.length));else if(e.test(r)){let i=await n.findFileByUID(r);if(!i)throw new Error(`No vault file found for UID: ${r}`);r=i}if(r.endsWith(".md")||(r=`${r}.md`),!await n.fileExists(r))throw new Error(`Cannot resolve target file for IRI "${t}" (tried "${r}")`);return r}}}o(aX,"createCliPathResolver");var oX=["createAsset","openFile","sparqlSelect","getActiveFileIRI","getActiveFilePath","trashFile","duplicateFile"],h2=class extends Error{constructor(t){super(`Service "${t}" is not implemented in the CLI (no-op stub). dyncommand exec on this service_call grounding cannot change vault state. See CLI parity issues #2865-#2868 for port status.`);this.serviceId=t;this.name="CliServiceNotImplementedError"}static{o(this,"CliServiceNotImplementedError")}};function CD(n){return{async execute(){throw new h2(n)}}}o(CD,"notImplementedService");function OD(n,e){for(let t of oX)n.register(t,CD(t));for(let t of["updateProperty","removeProperty","setStatus"])n.register(t,CD(t));if(e){if(e.fsAdapter){let t=new RD.FrontmatterService,r=aX(e.fsAdapter);n.register("updateProperty",(0,Ut.createUpdatePropertyService)(e.fsAdapter,t,r)),n.register("removeProperty",(0,Ut.createRemovePropertyService)(e.fsAdapter,t,r)),n.register("setStatus",(0,Ut.createSetStatusService)(e.fsAdapter,t,r))}n.register("createRelatedTask",(0,Ut.createCreateRelatedTaskService)(e.vaultAdapter,e.genericAssetCreationService)),n.register("createRelatedProject",(0,Ut.createCreateRelatedProjectService)(e.vaultAdapter,e.genericAssetCreationService)),n.register("archiveAsset",(0,Ut.createArchiveAssetService)(e.vaultAdapter,e.archiveAssetService)),n.register("planForEvening",(0,Ut.createPlanForEveningService)(e.vaultAdapter,e.taskStatusService)),n.register("cleanProperties",(0,Ut.createCleanPropertiesService)(e.vaultAdapter,e.propertyCleanupService)),n.register("renameToUid",(0,Ut.createRenameToUidService)(e.vaultAdapter,e.renameToUidService)),n.register("repairFolder",(0,Ut.createRepairFolderService)(e.vaultAdapter,e.folderRepairService)),n.register("fixMissingLabel",(0,Ut.createFixMissingLabelService)(e.vaultAdapter,e.fixMissingLabelService))}}o(OD,"populateCliServiceRegistry");var cX=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;async function lX(){if(process.stdin.isTTY)return[];let n=[];for await(let t of process.stdin)n.push(t);return Buffer.concat(n).toString("utf-8").split(`
762
762
  `).map(t=>t.trim()).filter(t=>t.length>0)}o(lX,"readStdinLines");function qg(n){if(n&&typeof n=="object"&&"value"in n){let e=n.value;return typeof e=="string"?e:String(e)}return String(n)}o(qg,"nodeValue");async function uX(n,e){let t=new tt.IRI("https://exocortex.my/ontology/exocmd#Command_cliName"),r=await n.match(void 0,t,void 0),i=[];for(let s of r)if(qg(s.object)===e){let l=qg(s.subject).match(/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.md$/i);l&&i.push(l[1])}if(i.length===0)return null;if(i.length>1)throw new Vt(`Ambiguous cliName "${e}" \u2014 resolves to ${i.length} commands: ${i.join(", ")}`,"Use the UUID directly: exocortex apply <uuid> <path>");return i[0]}o(uX,"resolveSlugToUuid");async function fX(n,e){let t=new tt.IRI("https://exocortex.my/ontology/exocmd#Command_destructive"),r=await n.match(void 0,t,void 0);for(let i of r)if(qg(i.subject).includes(e)){let a=qg(i.object);if(a==="true"||a==="True")return!0}return!1}o(fX,"isDestructive");async function dX(n,e,t,r,i){let s=(0,m2.resolve)(n,r);if(!(0,p2.existsSync)(s))return console.error(`\u274C Target file not found: ${r}`),!1;let c=await new tt.CommandResolver(e).loadCommand(t);if(!c)return console.error(`\u274C Command with UID "${t}" not found.`),!1;if(await fX(e,t)&&!i.dryRun&&!i.yes)return console.error(`\u274C Command "${c.name}" is marked destructive. Add --dry-run to preview, or --yes to apply.`),!1;let u=(0,tt.vaultPathToIRI)(r);if(!await new tt.PreconditionEvaluator(e).evaluate(c.precondition,u))return console.error(`\u274C Precondition not satisfied for "${c.name}" on "${r}".`),!1;if(i.dryRun)return console.log(`\u{1F50D} Dry-run: would apply "${c.name}" to "${r}" (precondition passed).`),!0;let h=new tt.ServiceRegistry,p=new Lt(n),y=new tt.GenericAssetCreationService(p),S=new tt.ArchiveAssetService(p),v=new tt.PropertyCleanupService(p),w=new tt.FixMissingLabelService(p),T=new tt.RenameToUidService(p),C=new tt.FolderRepairService(p),M=new tt.TaskStatusService(p,new tt.EffortStatusWorkflow,new tt.StatusTimestampService(p)),$=new hr(n);OD(h,{vaultAdapter:p,fsAdapter:$,genericAssetCreationService:y,archiveAssetService:S,taskStatusService:M,propertyCleanupService:v,fixMissingLabelService:w,renameToUidService:T,folderRepairService:C});let ee=new tt.GroundingExecutor($,$,h),B;if(i.input)try{let P=JSON.parse(i.input);if(typeof P!="object"||P===null||Array.isArray(P))throw new Error("must be a JSON object");B=P}catch(P){let D=P instanceof Error?P.message:String(P);return console.error(`\u274C --input: invalid JSON object (${D})`),!1}let z=await ee.execute(c.grounding,u,r,B);if(z.success){let P=c.successMessage??`Applied "${c.name}" to "${r}".`;return console.log(`\u2705 ${P}`),!0}else return console.error(`\u274C "${c.name}" failed on "${r}": ${z.error}`),!1}o(dX,"executeOnTarget");function PD(){return new Ie("apply").description("Apply an exocmd__Command to one or more vault assets (RFC 8e83442b T1.2). Pass a path arg or pipe paths via stdin.").argument("<cmd>","Command UUID or cliName slug").argument("[path]","Vault-relative path to target asset (omit to read paths from stdin)").option("--vault <path>","Path to Obsidian vault",process.cwd()).option("--dry-run","Preview without writing").option("--yes","Skip destructive-command confirmation").option("--input <json>","JSON userInput for service_call groundings").action(async(n,e,t)=>{pe.setFormat("text");try{let r=(0,m2.resolve)(t.vault);if(!(0,p2.existsSync)(r))throw new Fe(r);let i=new Lt(r),a=await new tt.NoteToRDFConverter(i).convertVault(),c=new tt.InMemoryTripleStore;await c.addAll(a);let l;if(cX.test(n))l=n;else{let h=await uX(c,n);h||(console.error(`\u274C No command found with UUID or cliName "${n}".`),process.exit(3)),l=h}let u;if(e)u=[e];else if(u=await lX(),u.length===0)throw new Vt("No target path provided and stdin is empty.","exocortex apply <uuid> <path> OR exocortex find ... | exocortex apply <uuid>");let f=0,d=0;for(let h of u)await dX(r,c,l,h,t)?f++:d++;u.length>1&&console.log(`
763
- \u{1F4CA} Applied to ${f}/${u.length} target(s) (${d} failed).`),d>0&&process.exit(5)}catch(r){pe.handle(r),process.exit(5)}})}o(PD,"applyCommand");function FD(n){let e=new Ie;return e.name("exocortex").description("CLI tool for Exocortex knowledge management system").version(n??"16.13.3"),e.addCommand(TD()),e.addCommand(PD()),e.addCommand(rF()),e.addCommand(aF()),e.addCommand(PF()),e.addCommand(lF()),e.addCommand(uF()),e.addCommand(mF()),e.addCommand(NF()),e.addCommand(UF()),e.addCommand(GF()),e.addCommand(zF()),e.addCommand(QF()),e.addCommand(sD()),e.addCommand(aD()),e.addCommand(hD()),e.addCommand(ED()),e}o(FD,"createProgram");FD().parse();0&&(module.exports={createProgram});
763
+ \u{1F4CA} Applied to ${f}/${u.length} target(s) (${d} failed).`),d>0&&process.exit(5)}catch(r){pe.handle(r),process.exit(5)}})}o(PD,"applyCommand");function FD(n){let e=new Ie;return e.name("exocortex").description("CLI tool for Exocortex knowledge management system").version(n??"16.13.4"),e.addCommand(TD()),e.addCommand(PD()),e.addCommand(rF()),e.addCommand(aF()),e.addCommand(PF()),e.addCommand(lF()),e.addCommand(uF()),e.addCommand(mF()),e.addCommand(NF()),e.addCommand(UF()),e.addCommand(GF()),e.addCommand(zF()),e.addCommand(QF()),e.addCommand(sD()),e.addCommand(aD()),e.addCommand(hD()),e.addCommand(ED()),e}o(FD,"createProgram");FD().parse();0&&(module.exports={createProgram});
764
764
  /*! Bundled license information:
765
765
 
766
766
  reflect-metadata/Reflect.js:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitelev/exocortex-cli",
3
- "version": "16.13.3",
3
+ "version": "16.13.4",
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": {