@north-light/cli 0.3.434 → 0.3.435

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.
@@ -1623,7 +1623,7 @@ ${i}`}function Kyn(t,e,n){return t.children.filter(i=>Lx(i)&&i.tag==="li").map((
1623
1623
  `)}done(){return this.buffers.join("").replace(/\n{3,}/g,`
1624
1624
 
1625
1625
  `).replace(/[ \t]+\n/g,`
1626
- `).trim()}}});var Xyn=h(()=>{"use strict"});var Zyn=h(()=>{"use strict"});var eAn=h(()=>{"use strict"});var tAn=h(()=>{"use strict"});var nAn=h(()=>{"use strict"});var rAn=h(()=>{"use strict"});var iAn=h(()=>{"use strict"});var oAn=h(()=>{"use strict"});var sAn=h(()=>{"use strict"});var aAn=h(()=>{"use strict"});var cAn=h(()=>{"use strict"});var uAn=h(()=>{"use strict"});var lAn=h(()=>{"use strict"});var dAn=h(()=>{"use strict"});var pAn=h(()=>{"use strict"});var fAn=h(()=>{"use strict"});var mAn=h(()=>{"use strict"});var hAn=h(()=>{"use strict"});var gAn=h(()=>{"use strict"});var yAn=h(()=>{"use strict"});var AAn=h(()=>{"use strict"});var wAn=h(()=>{"use strict"});var xAn=h(()=>{"use strict"});var bAn=h(()=>{"use strict"});var EAn=h(()=>{"use strict"});var _An=h(()=>{"use strict"});var vAn=h(()=>{"use strict"});var SAn=h(()=>{"use strict"});var CAn=h(()=>{"use strict"});var IAn=h(()=>{"use strict"});var TAn=h(()=>{"use strict"});var kAn=h(()=>{"use strict"});var RAn=h(()=>{"use strict"});var DAn=h(()=>{"use strict"});var MAn=h(()=>{"use strict"});var OAn=h(()=>{"use strict"});var Xfe=h(()=>{"use strict";Wwe();hp();Xyn();Lwe();Zyn();eAn();tAn();id();Bwe();nAn();rAn();iAn();oAn();sAn();aAn();cAn();uAn();lAn();$we();dAn();pAn();fAn();mAn();hAn();gAn();Fwe();yAn();AAn();wAn();R9();xAn();bAn();EAn();_An();vAn();SAn();CAn();IAn();TAn();kAn();RAn();DAn();MAn();OAn()});var NAn=h(()=>{"use strict";as()});var PAn=h(()=>{"use strict"});function LAn(t,e){if(t.code==="daemon_restarting")return new lo("daemon_restarting",t.message,Gi.NETWORK,{next:"crtrd is now on the new generation \u2014 retry the command."});if(t.code==="layout_migration_required")return new lo("layout_migration_required",t.message,Gi.NETWORK,{next:"Run `crtr sys migrate` while the runtime is offline, then restart it."});if(t.code==="daemon_unavailable")return new lo("daemon_unavailable",t.message,Gi.NETWORK,{next:"Start it with `crtr sys daemon start`, then retry."});if(t.status===503)return new lo(t.code,t.message,Gi.NETWORK,{next:e??"Retry the command; if it persists, inspect the unavailable service named in the error."});let n=t.details,r=Array.isArray(n?.violations)?n.violations.map(o=>`${String(o.field)} ${String(o.problem)}${o.received!==void 0?` (received ${JSON.stringify(o.received)})`:""}`):[],i=n&&typeof n.error=="string"&&typeof n.message=="string"&&typeof n.next=="string"?n:{error:Qsi[t.status]??t.code,message:r.length>0?`${t.message}: ${r.join("; ")}`:t.message,next:e??(t.status>=500?"This is a crtr bug, not a bad call. Retry; if it persists, report it (the daemon log holds the full cause).":t.status===404?"List nodes with `crtr node inspect list`.":"Inspect the error and adjust the call. See -h for the schema.")};return new af(i,Wsi(i.error,t.status))}function Wsi(t,e){return t==="not_found"||e===404?Gi.NOT_FOUND:t==="ambiguous"?Gi.AMBIGUOUS:Gi.USAGE}var D5s,af,Qsi,Bx=h(()=>{"use strict";Ss();dc();NAn();PAn();Xfe();D5s=256*1024,af=class extends lo{payload;constructor(e,n=Gi.USAGE){super(e.error,e.message,n,{...e}),this.name="InputError",this.payload=e}},Qsi={400:"invalid_request",404:"not_found",409:"conflict",422:"unprocessable"}});import{copyFileSync as Hsi,mkdirSync as eme,existsSync as Zfe,readFileSync as jsi,writeFileSync as FAn,chmodSync as qsi,readdirSync as Gsi,renameSync as sD,realpathSync as H3,unlinkSync as zsi,rmSync as Vsi,linkSync as BAn}from"node:fs";import{homedir as UAn}from"node:os";import{dirname as QAn,join as bs}from"node:path";import{execFile as Ksi,spawn as Ysi,spawnSync as nme}from"node:child_process";function EF(){return bs(UAn(),cC,"host")}function WAn(){return bs(EF(),rme)}function OKe(){return bs(EF(),".source.json")}function Jsi(t){let e=QAn(t);for(let n of[e,bs(e,"..","lib")]){if(!Zfe(n))continue;let r=Gsi(n).find(i=>i.startsWith("libnode.")&&i.endsWith(".dylib"));if(r!==void 0)return bs(n,r)}return null}function $An(t,e,n){let r=`${e}.tmp.${process.pid}.${Math.random().toString(36).slice(2)}`;Hsi(t,r),n!==void 0&&qsi(r,n),sD(r,e)}function MKe(t=OKe()){try{return JSON.parse(jsi(t,"utf8"))}catch{return null}}function Zsi(t){let e=bs(UAn(),cC),n=bs(e,"host.lock");return eme(e,{recursive:!0}),fc(n,t,{timeoutMs:Xsi,timeoutError:()=>new Error(`timed out waiting for branded host lock: ${n}`)})}function eai(t={}){let e=t.configured?.trim();return e?[e]:[t.discovered?.trim()||"-"]}function tai(){if(process.platform!=="darwin")return null;let t=nme("security",["find-identity","-v","-p","codesigning"],{stdio:["pipe","pipe","pipe"]});if(t.status!==0)return null;let n=(t.stdout??"").toString().split(`
1626
+ `).trim()}}});var Xyn=h(()=>{"use strict"});var Zyn=h(()=>{"use strict"});var eAn=h(()=>{"use strict"});var tAn=h(()=>{"use strict"});var nAn=h(()=>{"use strict"});var rAn=h(()=>{"use strict"});var iAn=h(()=>{"use strict"});var oAn=h(()=>{"use strict"});var sAn=h(()=>{"use strict"});var aAn=h(()=>{"use strict"});var cAn=h(()=>{"use strict"});var uAn=h(()=>{"use strict"});var lAn=h(()=>{"use strict"});var dAn=h(()=>{"use strict"});var pAn=h(()=>{"use strict"});var fAn=h(()=>{"use strict"});var mAn=h(()=>{"use strict"});var hAn=h(()=>{"use strict"});var gAn=h(()=>{"use strict"});var yAn=h(()=>{"use strict"});var AAn=h(()=>{"use strict"});var wAn=h(()=>{"use strict"});var xAn=h(()=>{"use strict"});var bAn=h(()=>{"use strict"});var EAn=h(()=>{"use strict"});var _An=h(()=>{"use strict"});var vAn=h(()=>{"use strict"});var SAn=h(()=>{"use strict"});var CAn=h(()=>{"use strict"});var IAn=h(()=>{"use strict"});var TAn=h(()=>{"use strict"});var kAn=h(()=>{"use strict"});var RAn=h(()=>{"use strict"});var DAn=h(()=>{"use strict"});var MAn=h(()=>{"use strict"});var OAn=h(()=>{"use strict"});var Xfe=h(()=>{"use strict";Wwe();hp();Xyn();Lwe();Zyn();eAn();tAn();id();Bwe();nAn();rAn();iAn();oAn();sAn();aAn();cAn();uAn();lAn();$we();dAn();pAn();fAn();mAn();hAn();gAn();Fwe();yAn();AAn();wAn();R9();xAn();bAn();EAn();_An();vAn();SAn();CAn();IAn();TAn();kAn();RAn();DAn();MAn();OAn()});var NAn=h(()=>{"use strict";as()});var PAn=h(()=>{"use strict"});function LAn(t,e){if(t.code==="daemon_restarting")return new lo("daemon_restarting",t.message,Gi.NETWORK,{next:"crtrd is now on the new generation \u2014 retry the command."});if(t.code==="layout_migration_required")return new lo("layout_migration_required",t.message,Gi.NETWORK,{next:"Run `crtr sys migrate` while the runtime is offline, then restart it."});if(t.code==="daemon_unavailable")return new lo("daemon_unavailable",t.message,Gi.NETWORK,{next:"Start it with `crtr sys daemon start`, then retry."});if(t.status===503)return new lo(t.code,t.message,Gi.NETWORK,{next:e??"Retry the command; if it persists, inspect the unavailable service named in the error."});let n=t.details,r=Array.isArray(n?.violations)?n.violations.map(o=>`${String(o.field)} ${String(o.problem)}${o.received!==void 0?` (received ${JSON.stringify(o.received)})`:""}`):[],i=n&&typeof n.error=="string"&&typeof n.message=="string"&&typeof n.next=="string"?n:{error:Qsi[t.status]??t.code,message:r.length>0?`${t.message}: ${r.join("; ")}`:t.message.trim()!==""?t.message:`request refused (HTTP ${t.status}, ${t.code}) with no message`,next:e??(t.status>=500?"This is a crtr bug, not a bad call. Retry; if it persists, report it (the daemon log holds the full cause).":t.status===404?"List nodes with `crtr node inspect list`.":"Inspect the error and adjust the call. See -h for the schema.")};return new af(i,Wsi(i.error,t.status))}function Wsi(t,e){return t==="not_found"||e===404?Gi.NOT_FOUND:t==="ambiguous"?Gi.AMBIGUOUS:Gi.USAGE}var D5s,af,Qsi,Bx=h(()=>{"use strict";Ss();dc();NAn();PAn();Xfe();D5s=256*1024,af=class extends lo{payload;constructor(e,n=Gi.USAGE){super(e.error,e.message,n,{...e}),this.name="InputError",this.payload=e}},Qsi={400:"invalid_request",404:"not_found",409:"conflict",422:"unprocessable"}});import{copyFileSync as Hsi,mkdirSync as eme,existsSync as Zfe,readFileSync as jsi,writeFileSync as FAn,chmodSync as qsi,readdirSync as Gsi,renameSync as sD,realpathSync as H3,unlinkSync as zsi,rmSync as Vsi,linkSync as BAn}from"node:fs";import{homedir as UAn}from"node:os";import{dirname as QAn,join as bs}from"node:path";import{execFile as Ksi,spawn as Ysi,spawnSync as nme}from"node:child_process";function EF(){return bs(UAn(),cC,"host")}function WAn(){return bs(EF(),rme)}function OKe(){return bs(EF(),".source.json")}function Jsi(t){let e=QAn(t);for(let n of[e,bs(e,"..","lib")]){if(!Zfe(n))continue;let r=Gsi(n).find(i=>i.startsWith("libnode.")&&i.endsWith(".dylib"));if(r!==void 0)return bs(n,r)}return null}function $An(t,e,n){let r=`${e}.tmp.${process.pid}.${Math.random().toString(36).slice(2)}`;Hsi(t,r),n!==void 0&&qsi(r,n),sD(r,e)}function MKe(t=OKe()){try{return JSON.parse(jsi(t,"utf8"))}catch{return null}}function Zsi(t){let e=bs(UAn(),cC),n=bs(e,"host.lock");return eme(e,{recursive:!0}),fc(n,t,{timeoutMs:Xsi,timeoutError:()=>new Error(`timed out waiting for branded host lock: ${n}`)})}function eai(t={}){let e=t.configured?.trim();return e?[e]:[t.discovered?.trim()||"-"]}function tai(){if(process.platform!=="darwin")return null;let t=nme("security",["find-identity","-v","-p","codesigning"],{stdio:["pipe","pipe","pipe"]});if(t.status!==0)return null;let n=(t.stdout??"").toString().split(`
1627
1627
  `).map(r=>r.match(/\)\s+[A-Fa-f0-9]{40}\s+"([^"]+)"/)?.[1]??null).filter(r=>r!==null);return n.find(r=>r.startsWith("Apple Development:"))??n.find(r=>r.startsWith("Developer ID Application:"))??n[0]??null}function nai(t,e){let n=nme("codesign",["-s",e,"--deep","--force",t],{stdio:["pipe","pipe","pipe"]});return{ok:n.status===0,stderr:(n.stderr??"").toString().trim()}}function rai(t){if(process.platform!=="darwin")return;let e=eai({configured:process.env.CRTR_CODESIGN_IDENTITY,discovered:tai()}),n="";for(let r of e){let i=nai(t,r);if(i.ok)return;n=i.stderr}throw n&&!n.includes("valid on disk")&&ja({event:"host.codesign.failed",level:"debug",error:n}),new Error(`codesign failed for ${t}: ${n||"codesign did not exit successfully"}`)}function iai(t,e,n=rai){e!==null&&n(e),n(t)}function bF(t,e=5e3){try{return nme(t,["-e",""],{stdio:"ignore",timeout:e}).status===0}catch{return!1}}function oai(t={}){return Zsi(()=>{let e=EF(),n=WAn(),r=H3(t.execPath??process.execPath);if(Zfe(n)&&H3(n)===r){if(bF(n))return n;let f=uai();if(f===null)throw new Error(`branded host cannot start and no working node was found to rebuild it from: ${n}`);r=f}let i=MKe(),o=Jsi(r),s=o!==null?o.split("/").pop():null,a=f=>Zfe(n)&&f!==null&&f.version===2&&(f.libnode===null||Zfe(bs(e,f.libnode))),c=f=>a(f)&&f.source===r&&f.libnode===s;if(c(i)&&bF(n))return n;eme(e,{recursive:!0});let u=bs(e,`.reconcile.${process.pid}.${Math.random().toString(36).slice(2)}`),l=bs(u,"previous");eme(u);let d=!1,p=a(i)&&bF(n);try{let f=bs(u,rme),m=s!==null?bs(u,s):null;if(o!==null&&m!==null&&$An(o,m),$An(r,f,493),iai(f,m),!bF(f))throw new Error(`rebuilt branded host failed its startup check: ${f}`);if(p&&aai(l,n,i),d=!0,m!==null&&sD(m,bs(e,s)),sD(f,n),sai({version:2,source:r,libnode:s}),!c(MKe())||!bF(n))throw new Error(`published branded host tuple failed validation: ${n}`);if(i?.libnode!=null&&i.libnode!==s)try{zsi(bs(e,i.libnode))}catch{}return n}catch(f){throw d&&p&&cai(l,n,i),f}finally{Vsi(u,{recursive:!0,force:!0})}})}function sai(t){let e=OKe(),n=`${e}.tmp.${process.pid}.${Math.random().toString(36).slice(2)}`;FAn(n,JSON.stringify(t)),sD(n,e)}function aai(t,e,n){eme(t),BAn(e,bs(t,rme)),n.libnode!==null&&BAn(bs(EF(),n.libnode),bs(t,n.libnode)),FAn(bs(t,".source.json"),JSON.stringify(n))}function cai(t,e,n){if(n.libnode!==null&&sD(bs(t,n.libnode),bs(EF(),n.libnode)),sD(bs(t,rme),e),sD(bs(t,".source.json"),OKe()),!bF(e))throw new Error(`failed to restore previous branded host tuple: ${e}`)}function tme(t){try{let e=H3(EF());return QAn(H3(t))===e}catch{return!1}}function HAn(){let t=["/opt/homebrew/bin/node","/usr/local/bin/node"];tme(process.execPath)||t.push(process.execPath);for(let i of(process.env.PATH??"").split(":"))i!==""&&t.push(bs(i,"node"));let e=MKe();e!==null&&typeof e.source=="string"&&t.push(e.source);let n=new Set,r=[];for(let i of t){let o;try{o=H3(i)}catch{continue}n.has(o)||tme(o)||(n.add(o),r.push(o))}return r}function qAn(t){return t!==null&&t.trim()===process.versions.modules}function uai(){for(let t of HAn())try{let e=nme(t,jAn,{encoding:"utf8",timeout:5e3,stdio:["ignore","pipe","ignore"]});if(e.status===0&&qAn(e.stdout))return t}catch{}return null}function GAn(t,e,n){return new Promise(r=>{try{Ksi(t,e,{encoding:"utf8",timeout:n},(i,o)=>r(i===null?o:null))}catch{r(null)}})}async function lai(){for(let t of HAn())if(qAn(await GAn(t,jAn,5e3)))return t;return null}function fai(t){if(import.meta.url.endsWith(".ts"))return;let e=Date.now();if(!(e-tp.lastHealAt<pai)){tp.lastHealAt=e;try{let n=`import(${JSON.stringify(import.meta.url)}).then((m) => m.ensureBrandedHost())`,r=Ysi(t,["--input-type=module","-e",n],{detached:!0,stdio:"ignore"});r.on("error",()=>{}),r.unref()}catch{}}}function mai(t){return tp.probing!==null||(tp.probing=(async()=>{try{if(await GAn(t,["-e",""],5e3)!==null){tp.fallback=null;return}let e=await lai();e!==tp.fallback&&e!==null&&ja({event:"host.fallback.node",level:"warn",fields:{host:t,node:e}}),tp.fallback=e,e!==null&&fai(e)}finally{tp.checkedAt=Date.now(),tp.probing=null}})()),tp.probing}function hai(t=process.execPath){return tme(t)?(Date.now()-tp.checkedAt>dai&&tp.probing===null&&mai(t),tp.fallback??t):t}function zAn(){if(process.env.CRTR_BRANDED_HOST==="0"||process.platform!=="darwin"||import.meta.url.endsWith(".ts"))return process.execPath;if(tme(process.execPath))return hai();try{return oai()}catch(t){return ja({event:"host.fallback.node",level:"warn",error:t,fields:{host:WAn(),node:process.execPath}}),process.execPath}}var rme,Xsi,jAn,dai,pai,tp,VAn=h(()=>{"use strict";dc();kf();Mf();rme="crouter";Xsi=3e4;jAn=["-p","process.versions.modules"];dai=15e3,pai=6e4,tp={checkedAt:0,fallback:null,probing:null,lastHealAt:0}});import{existsSync as gai,readFileSync as yai}from"node:fs";import{join as Aai}from"node:path";function wai(){return Vtt()??Aai(Cs(),"crtrd.pid")}function aD(){let t=wai();if(!gai(t))return null;let e=yai(t,"utf8").trim(),n=Number(e);return Number.isFinite(n)&&n>0?n:null}function KAn(){let t=aD();return t!==null&&fy(t)}var YAn=h(()=>{"use strict";Fr();Ob();as()});var NKe=h(()=>{"use strict"});import{spawn as xai,execFileSync as K5s}from"node:child_process";import{createRequire as bai}from"node:module";import{dirname as PKe,join as _F}from"node:path";import{fileURLToPath as Eai,pathToFileURL as LKe}from"node:url";import{existsSync as JAn,lstatSync as _ai,mkdirSync as vai,openSync as XAn,closeSync as ZAn,fstatSync as e0n,readSync as Sai}from"node:fs";function Iai(){let t={...process.env};for(let e of Cai)delete t[e];return t}function Tai(){for(let t=PKe(Eai(import.meta.url));;t=PKe(t)){if(JAn(_F(t,"bin","runtime-generation-manifest.mjs")))return t;if(PKe(t)===t)throw new Error(`cannot locate the crouter generation root from ${import.meta.url}`)}}async function kai(){let t=Tai(),e=LKe(_F(t,"bin","runtime-generation-manifest.mjs")).href,{runtimeHome:n}=await import(e);try{_ai(_F(n(),"selected"))}catch(s){if(s.code!=="ENOENT")throw s;return["--conditions","crtr-src","--import",LKe(bai(import.meta.url).resolve("tsx/esm")).href,_F(t,"src","daemon","crtrd-cli.ts")]}let r=LKe(_F(t,"bin","runtime-selector.mjs")).href,{tryResolveRuntime:i}=await import(r),o=i("daemon");if(!o.ok)throw new Error(`cannot resolve the selected runtime generation's daemon entry: ${o.error}`);return[o.runtime.entryPath]}async function UKe(t=$Ke){let e=Math.min(t,$Ke);return z0({autostart:!1,timeoutMs:e}).probeHealthz(e)}function Rai(t){let e=t instanceof Error?t.message:String(t);if(typeof t!="object"||t===null)return e;let n=t.code,r=t.cause,i=typeof n=="string"?n:r?.code;return typeof i=="string"&&!e.includes(i)?`${e}: ${i}`:e}async function Dai(t=$Ke){let e=await UKe(t);if(e.startup_blocked!==void 0){let n=aD()??process.pid;throw new vF(n,e.startup_blocked)}if(!e.ok)throw new Error("crtrd health check reported not ready")}function QKe(t){return new Promise(e=>{setTimeout(e,t)})}async function Mai(t,e=3e5,n={},r="ready"){let i=n.readPidfile??aD,o=n.isPidAlive??fy,s=n.childExited,a=n.isDaemonServing,c=n.probeDaemonServing??(async m=>{if(a!==void 0){if(await a())return;throw new Error("crtrd health check reported not ready")}await Dai(m)}),u=n.probeDaemonHealth??UKe,l=n.sleepMs??QKe,d=n.now??Date.now,p=null,f=null;return await E9({windowMs:e,pollIntervalMs:FKe,now:d,sleep:l,retry:m=>m!==f,probe:async m=>{let g=i();if(g===null||!o(g)){let w=s?.();throw w!=null&&(w.signal!==null?f=new q3(`daemon ${t} exited before becoming ready (by ${w.signal})`,n.childStderrTail?.()??""):w.code!==0&&(f=new q3(`daemon ${t} exited before becoming ready (with exit code ${w.code??"?"})`,n.childStderrTail?.()??"")),f!==null)?f:new Error(`daemon ${t} has no live pidfile owner`)}if(r==="ready"){try{await c(m)}catch(w){throw w instanceof vF&&(f=w),w}p=g;return}let y=await u(m);if(y.startup_phase==="prepared"){p=g;return}throw y.startup_phase==="blocked"?(f=new vF(g,y.startup_blocked??"on-disk migration is blocked"),f):y.startup_phase==="ready"?(f=new G3(g,y.startup_phase),f):new Error(`daemon ${g} is ${y.startup_phase??"not reporting a startup phase"}; waiting for prepared`)}}),p===t?null:p}async function Oai(t,e=t0n,n={}){let r=n.readPidfile??aD,i=n.isPidAlive??fy,o=n.sleepMs??QKe,s=n.now??Date.now,a=s()+e;for(;s()<=a;){if(!i(t)&&r()!==t)return;await o(FKe)}throw new Error(`daemon ${t} did not exit and release its pidfile within ${e}ms`)}async function Lai(t,e=t0n,n={}){let r=n.isPidAlive??fy,i=n.sleepMs??QKe,o=n.now??Date.now;try{process.kill(t,"SIGTERM")}catch{}try{return await Oai(t,e,n),"terminated"}catch{}try{process.kill(t,"SIGKILL")}catch{}let s=o()+Nai;for(;o()<=s;){if(!r(t))return"killed";await i(FKe)}throw new Error(`daemon ${t} survived both SIGTERM and SIGKILL`)}function Bai(t,e,n=2048){let r;try{r=XAn(t,"r");let{size:i}=e0n(r),o=Math.max(e,i-n),s=i-o;if(s<=0)return"";let a=Buffer.alloc(s);return Sai(r,a,0,s,o),a.toString("utf8").trim()}catch{return""}finally{if(r!==void 0)try{ZAn(r)}catch{}}}async function $ai(t={}){if(process.platform==="linux"&&JAn("/run/crtr/launcher.sock")&&!fy(aD()??-1))throw new Error("crtrd is managed by the root launcher; it cannot self-daemonize");let e=t.targetPhase??"ready",n=aD();if(n!==null&&fy(n))try{let d=await UKe();if(e==="prepared"){if(d.startup_phase==="prepared")return{started:!1,existing_pid:n,startup_phase:d.startup_phase};throw new G3(n,d.startup_phase)}return d.ok?{started:!1,existing_pid:n,...d.startup_phase===void 0?{}:{startup_phase:d.startup_phase}}:{started:!1,existing_pid:n,running:!0,serving:!1,probe_error:d.startup_blocked??"crtrd health check reported not ready",...d.startup_phase===void 0?{}:{startup_phase:d.startup_phase}}}catch(d){if(d instanceof G3)throw d;return{started:!1,existing_pid:n,running:!0,serving:!1,probe_error:Rai(d)}}vai(Cs(),{recursive:!0});let r=await kai(),i=_F(Cs(),"crtrd.err"),o=XAn(i,"a"),s=(()=>{try{return e0n(o).size}catch{return 0}})();x9()===void 0&&aat();let a=xai(zAn(),[...r,"--canvas-home",Cs(),...e==="prepared"?["--prepare"]:[]],{detached:!0,stdio:["ignore",o,o],env:Iai()});ZAn(o);let c=a.pid;if(c===void 0)throw new Error("daemon spawn did not return a pid");let u=null;a.once("exit",(d,p)=>{u={code:d,signal:p}}),a.unref();let l;try{l=await Mai(c,3e5,{childExited:()=>u,childStderrTail:()=>Bai(i,s)},e)}catch(d){let p=W9(nat())===c;if(u===null&&!p&&!(d instanceof vF))try{await Lai(c,Pai)}catch{}throw d}return l!==null?{started:!1,existing_pid:l,startup_phase:e}:{started:!0,pid:c,startup_phase:e}}function WKe(){return Ktt()||process.argv.includes("--no-autostart")}function Qai(t){return Math.min(Fai*2**(t-1),Uai)}function Wai(){j3=void 0,ime=0,ome=0}function n0n(){return j3}function r0n(t={}){let e=t.isDaemonRunning??KAn,n=t.spawnDaemon??$ai,r=t.now??Date.now;if(!WKe()&&!BKe&&!(r()<ome)){if(e()){Wai();return}j3=void 0,BKe=!0,n().then(()=>{j3=void 0,ime=0,ome=0},i=>{i instanceof q3&&(j3=i.message),ime+=1,ome=r()+Qai(ime)}).finally(()=>{BKe=!1})}}var Cai,t0n,FKe,$Ke,q3,vF,G3,Nai,Pai,Fai,Uai,BKe,j3,ime,ome,i0n=h(()=>{"use strict";Fr();Ob();Nwe();VAn();YAn();NKe();Mf();Fr();as();Xfe();LQ();Cai=["CRTR_NODE_ID","CRTR_KIND","CRTR_MODE","CRTR_LIFECYCLE","CRTR_NODE_CWD","CRTR_CONTEXT_DIR","CRTR_CYCLES","CRTR_PROFILE_ID","CRTR_PARENT_NODE_ID","CRTR_FRONT_DOOR","TMUX","TMUX_PANE","CRTR_BROKER_ENGINE","CRTR_PI_BINARY","NODE_OPTIONS"];t0n=2e4,FKe=10,$Ke=1e3;q3=class extends Error{stderrTail;constructor(e,n){super(n===""?e:`${e}
1628
1628
  ${n}`),this.name="DaemonExitedBeforeReadyError",this.stderrTail=n}},vF=class extends Error{constructor(e,n){super(`daemon ${e} is running but normal startup is blocked: ${n}`),this.name="DaemonStartupBlockedError"}},G3=class extends Error{constructor(e,n){super(n===void 0?`daemon ${e} is serving but did not report the prepared startup phase`:`daemon ${e} reported startup phase ${n}, not prepared`),this.name="DaemonNotPreparedError"}};Nai=2e3,Pai=5e3;Fai=5e3,Uai=6e4,BKe=!1,ime=0,ome=0});import{existsSync as Hai,readFileSync as jai,writeFileSync as fHs,chmodSync as mHs}from"node:fs";import{join as qai}from"node:path";function zai(t){return qai(t===qa()?Eh():t,Gai)}function Vai(t){let e=Th(t);if(!e)return{relayTokens:{}};let n=zai(e);if(!Hai(n))return{relayTokens:{}};try{let r=JSON.parse(jai(n,"utf8")),i=Array.isArray(r.scopedApiTokens)?r.scopedApiTokens.filter(o=>typeof o?.token=="string"&&o.token!==""&&typeof o.grantee=="string"&&/^app:[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(o.grantee)&&Array.isArray(o.scopes)&&typeof o.created=="string"):[];return{relayTokens:r.relayTokens??{},...typeof r.apiToken=="string"&&r.apiToken!==""?{apiToken:r.apiToken}:{},...i.length>0?{scopedApiTokens:i}:{}}}catch{return{relayTokens:{}}}}function o0n(t,e){return Vai(e).relayTokens[t]}var Gai,s0n=h(()=>{"use strict";gp();zi();Gs();Gai="secrets.json"});function z3(t,e="user"){let n=jo(e),r=n.remoteCanvas.targets[t];if(r===void 0){let o=Object.keys(n.remoteCanvas.targets);throw fp(`no remote canvas target named '${t}'`+(o.length>0?` \u2014 configured: ${o.join(", ")}`:" \u2014 none configured yet")+`. Add one with \`crtr canvas config add ${t} --preview <url> --relay-token -\`.`)}let i=o0n(r.relayTokenRef,e);if(i===void 0||i==="")throw fp(`target '${t}' has no stored relay token \u2014 add it with \`crtr canvas config add ${t} --relay-token -\`.`);return{previewEndpoint:r.previewEndpoint,relayToken:i}}var ame=h(()=>{"use strict";Ss();qo();s0n()});function a0n(t,e,n=5e3){let r=/^[\x20-\x7e]+$/.test(e);return async function(o,s){if(!r)return{ok:!1,stdout:"",stderr:"remote source: invalid stored relay token"};let a={kind:"exec",bin:o,args:s},c=new AbortController,u=setTimeout(()=>c.abort(),n),l;try{l=await fetch(new URL("/__crtr/source",t),{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e}`},body:JSON.stringify(a),signal:c.signal})}catch{return c.signal.aborted?{ok:!1,stdout:"",stderr:`remote source: timeout after ${n}ms`}:{ok:!1,stdout:"",stderr:"remote source: network error"}}finally{clearTimeout(u)}return l.ok?await l.json():{ok:!1,stdout:"",stderr:`remote source: HTTP ${l.status} ${l.statusText}`}}}var c0n=h(()=>{"use strict"});function zl(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function Kai(t){if(!zl(t))return!1;let e=t.node;if(!zl(e)||typeof e.node_id!="string"||!Array.isArray(t.reports)||!Array.isArray(t.managers))return!1;let n=t.artifacts;if(!zl(n)||typeof n.report!="number"||typeof n.doc!="number"||typeof n.roadmap!="number"||typeof t.pending_crons!="number")return!1;let r=t.paths;if(!zl(r)||typeof r.context_dir!="string"||"session_file"in r&&r.session_file!==null&&typeof r.session_file!="string"||typeof t.follow_up!="string")return!1;let i=t.fault;if(i!=null){if(!zl(i)||typeof i.link!="string"||typeof i.kind!="string"||typeof i.since!="string")return!1;let o=i.retry;if(!zl(o)||typeof o.disposition!="string")return!1}return!0}function u0n(t){return zl(t)&&typeof t.node_id=="string"&&typeof t.name=="string"&&typeof t.kind=="string"&&typeof t.status=="string"&&typeof t.active=="boolean"}function Yai(t){return zl(t)&&typeof t.from_id=="string"&&typeof t.to_id=="string"&&typeof t.active=="boolean"&&typeof t.created=="string"}function Jai(t){return zl(t)?typeof t.node_id=="string"&&typeof t.name=="string"&&typeof t.kind=="string"&&typeof t.mode=="string"&&typeof t.lifecycle=="string"&&typeof t.status=="string"&&typeof t.cwd=="string"&&typeof t.created=="string":!1}var cme,$x,V3=h(()=>{"use strict";c0n();cme=1e3;$x=class{constructor(e,n){this.previewEndpoint=e;this.relayToken=n;this.exec=a0n(e,n)}previewEndpoint;relayToken;exec;nodeCache=new Map;rosterCache=new Map;topologyCache=null;viewCache=new Map;async execJson(e){let n;try{n=await this.exec("crtr",["--json",...e])}catch{return null}if(!n.ok||n.exitCode!==void 0&&n.exitCode!==0)return null;try{return JSON.parse(n.stdout.trim())}catch{return null}}async fetchShow(e){let n=this.nodeCache.get(e);if(n&&Date.now()-n.at<cme)return n.value;let r=await this.execJson(["node","inspect","show",e]),i=Kai(r)?{...r,fault:r.fault??null,reports:r.reports.filter(u0n),managers:r.managers.filter(u0n)}:null;return this.nodeCache.set(e,{value:i,at:Date.now()}),i}topology(){if(this.topologyCache!==null&&Date.now()-this.topologyCache.at<cme)return this.topologyCache.value;let e=this.loadTopology();return this.topologyCache={value:e,at:Date.now()},e}async loadTopology(){let e=await this.exec("crtr",["--json","canvas","roster"]);if(!e.ok||e.exitCode!==void 0&&e.exitCode!==0)throw new Error("remote canvas topology is unavailable");let n;try{n=JSON.parse(e.stdout.trim())}catch{throw new Error("remote canvas topology is invalid")}if(!zl(n)||!Array.isArray(n.edges)||!n.edges.every(Yai))throw new Error("remote canvas topology is invalid");let r=n.edges,i={subscriptions:new Map,subscribers:new Map};for(let o of r){let s={node_id:o.to_id,active:o.active,created:o.created},a={node_id:o.from_id,active:o.active,created:o.created},c=i.subscriptions.get(o.from_id);c===void 0?i.subscriptions.set(o.from_id,[s]):c.push(s);let u=i.subscribers.get(o.to_id);u===void 0?i.subscribers.set(o.to_id,[a]):u.push(a)}return i}async rawShow(e){return this.fetchShow(e)}async getNode(e){return(await this.fetchShow(e))?.node??null}async getRow(e){let n=(await this.fetchShow(e))?.node;return n?{node_id:n.node_id,name:n.name,kind:n.kind,mode:n.mode,lifecycle:n.lifecycle,status:n.status,cwd:n.cwd,host_kind:n.host_kind??null,profile_id:n.profile_id??null,scopes:n.scopes??null,isolated:n.isolated===!0,parent:n.parent??null,created:n.created,intent:n.intent??null,waiting_for:n.waiting_for??null,frozen_at:n.frozen_at??null,terminal_reason:n.terminal_reason??null,pi_pid:n.pi_pid??null,pi_pid_identity:n.pi_pid_identity??null,window:n.window??null,tmux_session:n.tmux_session??null,pane:n.pane??null,fault:n.fault??null,streaming:n.streaming===!0}:null}async listNodes(e){let n=JSON.stringify(e?.status??null),r=this.rosterCache.get(n);if(r&&Date.now()-r.at<cme)return r.value;let i=["node","inspect","list"];e?.status&&i.push("--status",(Array.isArray(e.status)?e.status:[e.status]).join(","));let o=await this.execJson(i),a=(zl(o)&&Array.isArray(o.nodes)?o.nodes:[]).filter(Jai).map(c=>({...c,isolated:c.isolated===!0}));return this.rosterCache.set(n,{value:a,at:Date.now()}),a}async subscriptionsOf(e){return(await this.topology()).subscriptions.get(e)??[]}async subscribersOf(e){return(await this.topology()).subscribers.get(e)??[]}async view(e){let n=this.viewCache.get(e);if(n&&Date.now()-n.at<cme)return n.value;let r=new Set([e]),i=[],o=(await this.subscriptionsOf(e)).map(s=>s.node_id);for(;o.length>0;){let s=o.shift();if(!r.has(s)){r.add(s),i.push(s);for(let a of await this.subscriptionsOf(s))r.has(a.node_id)||o.push(a.node_id)}}return this.viewCache.set(e,{value:i,at:Date.now()}),i}async ticketCountsForNodes(e){if(e.length===0)return{};let n=await this.execJson(["canvas","attention","map","--nodes",e.join(",")]);return zl(n)&&zl(n.counts)?n.counts:{}}async ticketCountsForView(e){let n=await this.execJson(["canvas","attention","map","--view",e]);return zl(n)&&zl(n.counts)?n.counts:{}}async hasActiveLiveSubscription(e){let n=(await this.subscriptionsOf(e)).filter(r=>r.active);for(let r of n){let i=await this.getRow(r.node_id);if(i&&(i.status==="active"||i.status==="idle"))return!0}return!1}}});import{closeSync as Xai,fstatSync as Zai,openSync as eci,readSync as tci}from"node:fs";import{join as nci}from"node:path";import{gunzipSync as rci}from"node:zlib";function ume(t){return{...t,fault:t.fault??null}}function HKe(t,e){throw t instanceof fn?LAn(t,e):t}function sci(){let t;try{t=eci(nci(Cs(),"crtrd.log"),"r");let{size:e}=Zai(t),n=Math.max(0,e-ici),r=e-n;if(r<=0)return;let i=Buffer.alloc(r);tci(t,i,0,r,n);let s=i.toString("utf8").split(`
1629
1629
  `).filter(a=>a.trim()!=="").slice(-oci).join(`
@@ -1 +1 @@
1
- var m=Object.defineProperty;var s=(e,o)=>m(e,"name",{value:o,configurable:!0});import{defineLeaf as h}from"../../core/command.js";import{usage as d}from"../../core/errors.js";import{DOC_UNSET_FIELDS as u}from"../../api/dto/docs.js";import{cliClient as f}from"../api-client.js";import{parseReplaceBlocks as p}from"./replace-blocks.js";import{FIELD_FLAGS as t,REF_CONSTRAINT as y,fieldsFromInput as b,rethrowDocError as w,renderLinkReport as g,ruleParam as v}from"./shared.js";const q=h({name:"edit",description:"revise a document you have read",whenToUse:"a document you read needs a change to its body or fields",help:{name:"doc edit",summary:"revise a document you have read",guide:"The edit is made from the revision you last read (`crtr canvas read`); pass no revision. If someone edited it after your read, the edit is refused and nothing is overwritten. For a partial edit, pipe one or more literal blocks on stdin with --blocks: <<<<<<< SEARCH, old text, =======, new text, >>>>>>> REPLACE (markers on their own lines). Each SEARCH must match exactly once; empty REPLACE deletes text. Alternatively pipe a whole new body without --blocks, or use --replace JSON for scripts. Choose one mode. Pipe text straight in with a quoted heredoc (`<<'EOF'`); an unquoted one lets the shell expand `$` and backticks in the text, and the mangled text is what gets saved. A field flag replaces that field; omitted fields stay as they are.",params:[{kind:"positional",name:"ref",required:!0,constraint:y},{kind:"flag",name:"rationale",type:"string",required:!0,constraint:"Why this revision is made; recorded on the revision, never in the body."},{kind:"stdin",name:"body",required:!1,constraint:"Whole new body by default; with --blocks, exact SEARCH/REPLACE blocks."},{kind:"flag",name:"blocks",type:"bool",required:!1,constraint:"Interpret stdin as one or more whole-line <<<<<<< SEARCH / ======= / >>>>>>> REPLACE blocks; empty SEARCH is invalid, empty REPLACE deletes."},{kind:"flag",name:"replace",type:"string",required:!1,constraint:'JSON list `[{"old": "\u2026", "new": "\u2026"}]` of exact-text replacements; each `old` must match exactly once in the body you read.'},{kind:"flag",name:"verbatim",type:"bool",required:!1,constraint:"The body is the person's own text relayed unchanged; recorded on the revision."},t.preview("New one-line preview."),t.summary,t.privacy("Who beyond the owner may read it."),v("Replaces the whole rule list."),t.whyItExists,t.unlisted("Sets unlisted; remove it with `--unset unlisted`."),t.lintIgnore,t.extension,{kind:"flag",name:"unset",type:"enum",choices:[...u],required:!1,repeatable:!0,constraint:"Clear one optional field."}],output:[{name:"revision",type:"number",required:!0,constraint:"The new revision number."},{name:"unresolved_links",type:"string[]",required:!1,constraint:"`[[links]]` in the new body that name no document yet."},{name:"remote_links",type:"string[]",required:!1,constraint:"`[[links]]` whose first segment is no owner on this runtime: on another runtime, or misspelled."}],outputKind:"object",effects:["Commits a new revision based on your last read and pushes the edit to the document's watchers."]},run:s(async e=>{const o=e.ref;let n=typeof e.body=="string"&&e.body!==""?e.body:void 0,i;if(e.blocks===!0){if(e.replace!==void 0)throw d("choose --blocks or --replace, not both",{field:"blocks"});i=p(n??""),n=void 0}if(typeof e.replace=="string"){if(n!==void 0)throw d("give a stdin body or --replace, not both",{field:"replace",next:"Drop one of them and rerun."});try{const r=JSON.parse(e.replace);if(!Array.isArray(r)||r.length===0||r.some(a=>typeof a!="object"||a===null||typeof a.old!="string"||typeof a.new!="string"))throw new Error;i=r}catch{throw d('--replace must be a non-empty JSON list of {"old": string, "new": string}',{field:"replace",next:"Fix the JSON and rerun."})}}const l=e.unset===void 0?[]:[].concat(e.unset),c={rationale:e.rationale,...n!==void 0?{body:n}:{},...i!==void 0?{replace:i}:{},...e.verbatim===!0?{verbatim:!0}:{},...b(e),...l.length>0?{unset:l}:{}};try{return{...await f().docs.edit(o,c)}}catch(r){w(r,o)}},"run"),render:s(e=>`<edited name="${String(e.name)}" revision=${String(e.revision)}>${g(e)}`,"render")});export{q as editLeaf};
1
+ var h=Object.defineProperty;var a=(e,o)=>h(e,"name",{value:o,configurable:!0});import{defineLeaf as m}from"../../core/command.js";import{usage as d}from"../../core/errors.js";import{DOC_UNSET_FIELDS as u}from"../../api/dto/docs.js";import{cliClient as f}from"../api-client.js";import{parseReplaceBlocks as y}from"./replace-blocks.js";import{FIELD_FLAGS as t,REF_CONSTRAINT as p,fieldsFromInput as b,rethrowDocError as w,renderLinkReport as v,ruleParam as g}from"./shared.js";const q=m({name:"edit",description:"revise a document you have read",whenToUse:"a document you read needs a change to its body or fields",help:{name:"doc edit",summary:"revise a document you have read",guide:"The edit is made from the revision you last read (`crtr canvas read`); pass no revision. If someone edited it after your read, the edit is refused and nothing is overwritten. For a partial edit, pipe one or more literal blocks on stdin with --blocks: <<<<<<< SEARCH, old text, =======, new text, >>>>>>> REPLACE (markers on their own lines). Each SEARCH must match exactly once; empty REPLACE deletes text. Alternatively pipe a whole new body without --blocks, or use --replace JSON for scripts. Choose one mode. Pipe text straight in with a quoted heredoc (`<<'EOF'`); an unquoted one lets the shell expand `$` and backticks in the text, and the mangled text is what gets saved. A field flag replaces that field; omitted fields stay as they are. A change to fields alone (preview, summary, privacy, rules, why-it-exists, \u2026) takes effect at once, makes no new revision and returns the current revision number unchanged: revisions are versions of the body. Only a body edit records the rationale on a revision.",params:[{kind:"positional",name:"ref",required:!0,constraint:p},{kind:"flag",name:"rationale",type:"string",required:!0,constraint:"Why this revision is made; recorded on the revision, never in the body. A fields-only edit makes no revision, so it records nothing; the rationale is still required."},{kind:"stdin",name:"body",required:!1,constraint:"Whole new body by default; with --blocks, exact SEARCH/REPLACE blocks."},{kind:"flag",name:"blocks",type:"bool",required:!1,constraint:"Interpret stdin as one or more whole-line <<<<<<< SEARCH / ======= / >>>>>>> REPLACE blocks; empty SEARCH is invalid, empty REPLACE deletes."},{kind:"flag",name:"replace",type:"string",required:!1,constraint:'JSON list `[{"old": "\u2026", "new": "\u2026"}]` of exact-text replacements; each `old` must match exactly once in the body you read.'},{kind:"flag",name:"verbatim",type:"bool",required:!1,constraint:"The body is the person's own text relayed unchanged; recorded on the revision."},t.preview("New one-line preview."),t.summary,t.privacy("Who beyond the owner may read it."),g("Replaces the whole rule list."),t.whyItExists,t.unlisted("Sets unlisted; remove it with `--unset unlisted`."),t.lintIgnore,t.extension,{kind:"flag",name:"unset",type:"enum",choices:[...u],required:!1,repeatable:!0,constraint:"Clear one optional field."}],output:[{name:"revision",type:"number",required:!0,constraint:"The new revision number; for a fields-only edit, the current one, unchanged."},{name:"unresolved_links",type:"string[]",required:!1,constraint:"`[[links]]` in the new body that name no document yet."},{name:"remote_links",type:"string[]",required:!1,constraint:"`[[links]]` whose first segment is no owner on this runtime: on another runtime, or misspelled."}],outputKind:"object",effects:["Commits a new revision based on your last read and pushes the edit to the document's watchers."]},run:a(async e=>{const o=e.ref;let n=typeof e.body=="string"&&e.body!==""?e.body:void 0,i;if(e.blocks===!0){if(e.replace!==void 0)throw d("choose --blocks or --replace, not both",{field:"blocks"});i=y(n??""),n=void 0}if(typeof e.replace=="string"){if(n!==void 0)throw d("give a stdin body or --replace, not both",{field:"replace",next:"Drop one of them and rerun."});try{const r=JSON.parse(e.replace);if(!Array.isArray(r)||r.length===0||r.some(s=>typeof s!="object"||s===null||typeof s.old!="string"||typeof s.new!="string"))throw new Error;i=r}catch{throw d('--replace must be a non-empty JSON list of {"old": string, "new": string}',{field:"replace",next:"Fix the JSON and rerun."})}}const l=e.unset===void 0?[]:[].concat(e.unset),c={rationale:e.rationale,...n!==void 0?{body:n}:{},...i!==void 0?{replace:i}:{},...e.verbatim===!0?{verbatim:!0}:{},...b(e),...l.length>0?{unset:l}:{}};try{return{...await f().docs.edit(o,c)}}catch(r){w(r,o)}},"run"),render:a(e=>`<edited name="${String(e.name)}" revision=${String(e.revision)}>${v(e)}`,"render")});export{q as editLeaf};
package/dist/core/io.js CHANGED
@@ -1,7 +1,7 @@
1
- var w=Object.defineProperty;var n=(e,t)=>w(e,"name",{value:t,configurable:!0});import{appendFileSync as x,statSync as E}from"node:fs";import{CrtrError as a}from"./errors.js";import{ExitCode as c}from"../types.js";import{PREVIEW_RESULT_PATH_ENV as m}from"./preview-result-path.js";import{renderError as b}from"./render.js";import{ApiError as T}from"../api/index.js";let d=!1,u;const _=256*1024;function W(e){const t=process.env[m];u=t===void 0||t===""?void 0:{path:e,jsonl:[]}}n(W,"beginPreview");function f(e){const t=process.env[m];if(t===void 0||t==="")return;const s=`${JSON.stringify({path:u?.path??"",...e})}
2
- `;try{if((E(t,{throwIfNoEntry:!1})?.size??0)+Buffer.byteLength(s,"utf8")>_)return;x(t,s,"utf8")}catch{}}n(f,"publishPreview");function k(e){u!==void 0&&(e!=null?f({result:e}):(u.jsonl.length>0||u.error!==void 0)&&f({...u.jsonl.length>0?{jsonl:u.jsonl}:{},...u.error===void 0?{}:{error:u.error}}))}n(k,"publishPreviewResult");function y(e){u?.jsonl.push(e)}n(y,"recordPreviewLine");function B(e){try{const t=JSON.parse(e);t!==null&&typeof t=="object"&&!Array.isArray(t)&&y(t)}catch{}}n(B,"recordPreviewJsonLine");function F(e){u!==void 0&&(u.error=e)}n(F,"recordPreviewError");function G(e){d=e}n(G,"setJsonOutput");function K(){return d}n(K,"isJsonOutput");class h extends a{static{n(this,"InputError")}payload;constructor(t,s=c.USAGE){super(t.error,t.message,s,{...t}),this.name="InputError",this.payload=t}}async function q(){if(process.stdin.isTTY)return"";const e=[];for await(const t of process.stdin)e.push(t);return Buffer.concat(e).toString("utf8")}n(q,"readStdinRaw");async function D(e=200){return process.stdin.isTTY?"":await new Promise(t=>{const s=[];let o=!1;const r=n(()=>{o||(o=!0,clearTimeout(g),process.stdin.removeListener("data",i),process.stdin.removeListener("end",p),process.stdin.removeListener("error",l),process.stdin.pause(),t(Buffer.concat(s).toString("utf8")))},"finish"),i=n(S=>s.push(S),"onData"),p=n(()=>r(),"onEnd"),l=n(()=>r(),"onError"),g=setTimeout(r,e);process.stdin.on("data",i),process.stdin.on("end",p),process.stdin.on("error",l),process.stdin.resume()})}n(D,"peekStdinRaw");function V(e){process.stdout.write(JSON.stringify(e,null,2)+`
1
+ var w=Object.defineProperty;var n=(e,t)=>w(e,"name",{value:t,configurable:!0});import{appendFileSync as x,statSync as E}from"node:fs";import{CrtrError as a}from"./errors.js";import{ExitCode as c}from"../types.js";import{PREVIEW_RESULT_PATH_ENV as m}from"./preview-result-path.js";import{renderError as T}from"./render.js";import{ApiError as b}from"../api/index.js";let d=!1,u;const _=256*1024;function W(e){const t=process.env[m];u=t===void 0||t===""?void 0:{path:e,jsonl:[]}}n(W,"beginPreview");function f(e){const t=process.env[m];if(t===void 0||t==="")return;const s=`${JSON.stringify({path:u?.path??"",...e})}
2
+ `;try{if((E(t,{throwIfNoEntry:!1})?.size??0)+Buffer.byteLength(s,"utf8")>_)return;x(t,s,"utf8")}catch{}}n(f,"publishPreview");function k(e){u!==void 0&&(e!=null?f({result:e}):(u.jsonl.length>0||u.error!==void 0)&&f({...u.jsonl.length>0?{jsonl:u.jsonl}:{},...u.error===void 0?{}:{error:u.error}}))}n(k,"publishPreviewResult");function y(e){u?.jsonl.push(e)}n(y,"recordPreviewLine");function B(e){try{const t=JSON.parse(e);t!==null&&typeof t=="object"&&!Array.isArray(t)&&y(t)}catch{}}n(B,"recordPreviewJsonLine");function q(e){u!==void 0&&(u.error=e)}n(q,"recordPreviewError");function F(e){d=e}n(F,"setJsonOutput");function G(){return d}n(G,"isJsonOutput");class h extends a{static{n(this,"InputError")}payload;constructor(t,s=c.USAGE){super(t.error,t.message,s,{...t}),this.name="InputError",this.payload=t}}async function K(){if(process.stdin.isTTY)return"";const e=[];for await(const t of process.stdin)e.push(t);return Buffer.concat(e).toString("utf8")}n(K,"readStdinRaw");async function D(e=200){return process.stdin.isTTY?"":await new Promise(t=>{const s=[];let o=!1;const r=n(()=>{o||(o=!0,clearTimeout(g),process.stdin.removeListener("data",i),process.stdin.removeListener("end",p),process.stdin.removeListener("error",l),process.stdin.pause(),t(Buffer.concat(s).toString("utf8")))},"finish"),i=n(S=>s.push(S),"onData"),p=n(()=>r(),"onEnd"),l=n(()=>r(),"onError"),g=setTimeout(r,e);process.stdin.on("data",i),process.stdin.on("end",p),process.stdin.on("error",l),process.stdin.resume()})}n(D,"peekStdinRaw");function V(e){process.stdout.write(JSON.stringify(e,null,2)+`
3
3
  `)}n(V,"emit");function Y(e){y(e),process.stdout.write(JSON.stringify(e)+`
4
- `)}n(Y,"emitLine");function M(e){return new Promise(t=>{let s=!1;const o=n(i=>{i.code==="EPIPE"&&r(!1)},"onErr"),r=n(i=>{s||(s=!0,process.stdout.off("error",o),t(i))},"finish");process.stdout.on("error",o);try{process.stdout.write(e,i=>r(i==null))}catch{r(!1)}})}n(M,"writeStdout");function z(e){process.stderr.write(e+`
5
- `)}n(z,"diag");function O(e){if(e instanceof h)return e.payload;const t=e.details!==void 0?e.details:{},s=t.primaryCompleted===!0&&t.result!==null&&typeof t.result=="object"&&!Array.isArray(t.result)?N(t.result):void 0,o=t.next!==void 0?t.next:"Inspect the error and adjust the call. See -h for the schema.",r={error:e.code,message:e.message,received:t.received,field:t.field,...typeof t.http_status=="number"?{http_status:t.http_status}:{}};return s===void 0?{...r,next:o}:{...r,primaryCompleted:!0,result:s,next:o}}n(O,"payloadOf");function N(e){const t=new WeakSet;try{const s=JSON.stringify(e,(o,r)=>{if(typeof r=="bigint")return{$crtrType:"bigint",value:r.toString()};if(typeof r=="number"&&!Number.isFinite(r))return{$crtrType:"number",value:String(r)};if(typeof r>"u"||typeof r=="function"||typeof r=="symbol")return{$crtrType:typeof r};if(r!==null&&typeof r=="object"){if(t.has(r))return{$crtrType:"circular"};t.add(r)}return r});if(s!==void 0){const o=JSON.parse(s);if(o!==null&&typeof o=="object"&&!Array.isArray(o))return o}}catch{}return{$crtrType:"unavailable",message:"The completed primary result could not be represented as JSON."}}n(N,"jsonSafeResult");const R={400:"invalid_request",404:"not_found",409:"conflict",422:"unprocessable"};function A(e,t){if(e.code==="daemon_restarting")return new a("daemon_restarting",e.message,c.NETWORK,{next:"crtrd is now on the new generation \u2014 retry the command."});if(e.code==="layout_migration_required")return new a("layout_migration_required",e.message,c.NETWORK,{next:"Run `crtr sys migrate` while the runtime is offline, then restart it."});if(e.code==="daemon_unavailable")return new a("daemon_unavailable",e.message,c.NETWORK,{next:"Start it with `crtr sys daemon start`, then retry."});if(e.status===503)return new a(e.code,e.message,c.NETWORK,{next:t??"Retry the command; if it persists, inspect the unavailable service named in the error."});const s=e.details,o=Array.isArray(s?.violations)?s.violations.map(i=>`${String(i.field)} ${String(i.problem)}${i.received!==void 0?` (received ${JSON.stringify(i.received)})`:""}`):[],r=s&&typeof s.error=="string"&&typeof s.message=="string"&&typeof s.next=="string"?s:{error:R[e.status]??e.code,message:o.length>0?`${e.message}: ${o.join("; ")}`:e.message,next:t??(e.status>=500?"This is a crtr bug, not a bad call. Retry; if it persists, report it (the daemon log holds the full cause).":e.status===404?"List nodes with `crtr node inspect list`.":"Inspect the error and adjust the call. See -h for the schema.")};return new h(r,P(r.error,e.status))}n(A,"apiErrorToCliError");function P(e,t){return e==="not_found"||t===404?c.NOT_FOUND:e==="ambiguous"?c.AMBIGUOUS:c.USAGE}n(P,"exitForCliCode");function j(e){if(e instanceof T){j(A(e));return}if(e instanceof a){const o=O(e);u!==void 0&&f({error:o});const r=d?JSON.stringify(o,null,2):b(o);process.stdout.write(r+`
4
+ `)}n(Y,"emitLine");function H(e){return new Promise(t=>{let s=!1;const o=n(i=>{i.code==="EPIPE"&&r(!1)},"onErr"),r=n(i=>{s||(s=!0,process.stdout.off("error",o),t(i))},"finish");process.stdout.on("error",o);try{process.stdout.write(e,i=>r(i==null))}catch{r(!1)}})}n(H,"writeStdout");function M(e){process.stderr.write(e+`
5
+ `)}n(M,"diag");function O(e){if(e instanceof h)return e.payload;const t=e.details!==void 0?e.details:{},s=t.primaryCompleted===!0&&t.result!==null&&typeof t.result=="object"&&!Array.isArray(t.result)?N(t.result):void 0,o=t.next!==void 0?t.next:"Inspect the error and adjust the call. See -h for the schema.",r={error:e.code,message:e.message,received:t.received,field:t.field,...typeof t.http_status=="number"?{http_status:t.http_status}:{}};return s===void 0?{...r,next:o}:{...r,primaryCompleted:!0,result:s,next:o}}n(O,"payloadOf");function N(e){const t=new WeakSet;try{const s=JSON.stringify(e,(o,r)=>{if(typeof r=="bigint")return{$crtrType:"bigint",value:r.toString()};if(typeof r=="number"&&!Number.isFinite(r))return{$crtrType:"number",value:String(r)};if(typeof r>"u"||typeof r=="function"||typeof r=="symbol")return{$crtrType:typeof r};if(r!==null&&typeof r=="object"){if(t.has(r))return{$crtrType:"circular"};t.add(r)}return r});if(s!==void 0){const o=JSON.parse(s);if(o!==null&&typeof o=="object"&&!Array.isArray(o))return o}}catch{}return{$crtrType:"unavailable",message:"The completed primary result could not be represented as JSON."}}n(N,"jsonSafeResult");const R={400:"invalid_request",404:"not_found",409:"conflict",422:"unprocessable"};function A(e,t){if(e.code==="daemon_restarting")return new a("daemon_restarting",e.message,c.NETWORK,{next:"crtrd is now on the new generation \u2014 retry the command."});if(e.code==="layout_migration_required")return new a("layout_migration_required",e.message,c.NETWORK,{next:"Run `crtr sys migrate` while the runtime is offline, then restart it."});if(e.code==="daemon_unavailable")return new a("daemon_unavailable",e.message,c.NETWORK,{next:"Start it with `crtr sys daemon start`, then retry."});if(e.status===503)return new a(e.code,e.message,c.NETWORK,{next:t??"Retry the command; if it persists, inspect the unavailable service named in the error."});const s=e.details,o=Array.isArray(s?.violations)?s.violations.map(i=>`${String(i.field)} ${String(i.problem)}${i.received!==void 0?` (received ${JSON.stringify(i.received)})`:""}`):[],r=s&&typeof s.error=="string"&&typeof s.message=="string"&&typeof s.next=="string"?s:{error:R[e.status]??e.code,message:o.length>0?`${e.message}: ${o.join("; ")}`:e.message.trim()!==""?e.message:`request refused (HTTP ${e.status}, ${e.code}) with no message`,next:t??(e.status>=500?"This is a crtr bug, not a bad call. Retry; if it persists, report it (the daemon log holds the full cause).":e.status===404?"List nodes with `crtr node inspect list`.":"Inspect the error and adjust the call. See -h for the schema.")};return new h(r,P(r.error,e.status))}n(A,"apiErrorToCliError");function P(e,t){return e==="not_found"||t===404?c.NOT_FOUND:e==="ambiguous"?c.AMBIGUOUS:c.USAGE}n(P,"exitForCliCode");function j(e){if(e instanceof b){j(A(e));return}if(e instanceof a){const o=O(e);u!==void 0&&f({error:o});const r=d?JSON.stringify(o,null,2):T(o);process.stdout.write(r+`
6
6
  `),process.exitCode=e.exitCode;return}const t=e,s=t!=null&&typeof t.message=="string"?t.message:String(e);process.stderr.write(JSON.stringify({error:"internal",message:s,next:"This is a crtr bug, not a bad call. Retry; if it persists, report it."},null,2)+`
7
- `),process.exitCode=c.GENERAL}n(j,"handle");export{h as InputError,_ as PREVIEW_RESULT_MAX_BYTES,A as apiErrorToCliError,W as beginPreview,z as diag,V as emit,Y as emitLine,j as handle,K as isJsonOutput,D as peekStdinRaw,k as publishPreviewResult,q as readStdinRaw,F as recordPreviewError,B as recordPreviewJsonLine,y as recordPreviewLine,G as setJsonOutput,M as writeStdout};
7
+ `),process.exitCode=c.GENERAL}n(j,"handle");export{h as InputError,_ as PREVIEW_RESULT_MAX_BYTES,A as apiErrorToCliError,W as beginPreview,M as diag,V as emit,Y as emitLine,j as handle,G as isJsonOutput,D as peekStdinRaw,k as publishPreviewResult,K as readStdinRaw,q as recordPreviewError,B as recordPreviewJsonLine,y as recordPreviewLine,F as setJsonOutput,H as writeStdout};
@@ -1 +1 @@
1
- var re=Object.defineProperty;var u=(t,e)=>re(t,"name",{value:e,configurable:!0});import{prepared as P}from"../../../core/sqlite-statements.js";import{ApiError as g}from"../../../api/errors.js";import{DOC_KINDS as q,DOC_UNSET_FIELDS as H}from"../../../api/dto/docs.js";import{PRIVACY_LEVELS_DTO as V}from"../../../api/dto/objects.js";import{withCanvasWrite as k}from"../../../core/canvas/db.js";import{CrtrError as ie}from"../../../core/errors.js";import{emitEvent as se}from"../../../core/events/emit.js";import{canChange as K,spaceOf as ae}from"../../../core/graph/access.js";import{get as A}from"../../../core/graph/bodies.js";import{deleteDocument as ce,documentRecord as F,editDocument as de,heads as I,history as ue,linksIn as U,moveDocument as fe,readBase as le,setDocumentRecord as me,withCurrentNames as pe,writeDocument as he}from"../../../core/graph/documents.js";import{resolveName as X}from"../../../core/graph/names.js";import{getByRowid as M}from"../../../core/graph/objects.js";import{noteRepoDocumentsChanged as we}from"../../../core/graph/repo-sync/index.js";import{checkoutsForCwd as ye}from"../../../core/graph/repo-sync/repos.js";import{lintRules as ve,rulesOf as ge}from"../../../core/graph/rules.js";import{unifiedDiff as _e}from"../../../core/graph/diff.js";import{ownerFromFlag as W,readerFor as E,resolveRef as z}from"../reader.js";function _(t,e,n,o,i={}){return new g(t,e,n,{...i,error:e,message:n,next:o})}u(_,"refuse");const b=u((t,e)=>new g(400,"invalid_request",t,e),"invalid");function D(t){const e=t.body;if(e===void 0)return{};if(typeof e!="object"||e===null||Array.isArray(e))throw b("the request body must be a JSON object");return e}u(D,"bodyOf");const x=u(t=>e=>ye(t,e),"reposFnFor");function C(t,e){if(t instanceof ie){const n=t.details;if(t.code==="read_first")throw _(409,"read_first",t.message,`Read it first with \`crtr canvas read ${e?.id??"<ref>"}\`, then rerun the edit.`,n??{});if(t.code==="conflict")throw new g(409,"name_taken",t.message,n);if(t.code==="forbidden")throw new g(403,"forbidden",t.message,n);if(n?.rule==="repo-public-only")throw _(422,"repo_documents_are_public",t.message,'Own it as `user` and add a rule with `if: {"repo": "<handle>"}` so it loads only in that repo.')}throw t}u(C,"mapGraphError");function B(t,e,n){const o=z(t,e,decodeURIComponent(n));if("remote"in o)throw _(404,"not_found",G(o.remote),"Check the name with `crtr canvas search`.");if("deleted"in o)throw new g(404,"not_found",`${o.deleted.name} is deleted`,{id:o.deleted.id,deleted:!0});if(o.type!=="document")throw b(`${n} is a ${o.type}, not a document`);return o}u(B,"refDocument");function G(t){return`no object named ${t} on this runtime; it may be on another runtime, or the name may be misspelled`}u(G,"remoteMessage");function be(t,e){const n=e.owner===null?null:M(t,e.owner);return n?n.type==="node"?n.id:n.name:""}u(be,"ownerHandle");function j(t,e){const n=be(t,e);return n?`${n}/${e.name}`:e.name}u(j,"canonicalName");function ke(t,e){const n=e.owner===null?null:M(t,e.owner),o=n?{id:n.id,type:n.type,handle:n.type==="node"?n.id:n.name}:null;return{id:e.id,type:e.type,kind:e.kind,owner:o,privacy:e.privacy,name:e.name,preview:e.preview??"",created_at:e.created_at,deleted_at:e.deleted_at}}u(ke,"objectDTO");function Ee(t,e){const n=e.owner===null?null:M(t,e.owner);return n?.type==="repo"?n:null}u(Ee,"repoOwner");function S(t,e,n,o){const i=[...new Map(n.flatMap(r=>{const f=Ee(t,r);return f?[[f.id,f]]:[]})).values()],a=e.class==="node"?e.cwd:o;return{repos:i,...a!==void 0?{cwd:a}:{}}}u(S,"repoChange");function T(t){for(const e of t.repos)try{we(e,t.cwd)}catch(n){se({level:"warn",event:"repo_sync.failed",outcome:"failed",error:n,fields:{repo:e.name,step:"export",reason:n instanceof Error?n.message:String(n)}})}}u(T,"syncChanged");const Y=/^[A-Za-z0-9_-]+(\/[A-Za-z0-9_-]+)*$/;function Oe(t,e){if(t===void 0)return;if(!Array.isArray(t)){e.push("`rules` must be a list");return}const n=t.map(i=>{if(typeof i!="object"||i===null||Array.isArray(i))return i;const{match_frontmatter:a,...r}=i;return"matchFrontmatter"in r?{...r,match_frontmatter:r.matchFrontmatter}:a===void 0?r:{...r,matchFrontmatter:a}}),o=ve(n);if(o){e.push(o.replaceAll("matchFrontmatter","match_frontmatter"));return}return n}u(Oe,"rulesFromDTO");function Z(t,e){const n={},o=u(s=>{const c=t[s];if(c!==void 0){if(typeof c!="string"){e.push(`\`${s}\` must be a string`);return}return c}},"str"),i=o("preview");i!==void 0&&(i.trim()===""||/[\r\n]/.test(i)?e.push("`preview` must be one non-empty line"):n.preview=i);const a=o("summary");a!==void 0&&(n.summary=a);const r=o("why_it_exists");if(r!==void 0&&(n.whyItExists=r),t.privacy!==void 0&&(V.includes(t.privacy)?n.privacy=t.privacy:e.push(`\`privacy\` must be one of ${V.join(", ")}`)),t.unlisted!==void 0&&(typeof t.unlisted!="boolean"?e.push("`unlisted` must be a boolean"):n.unlisted=t.unlisted),t.lint_ignore!==void 0){const s=t.lint_ignore;!Array.isArray(s)||s.some(c=>typeof c!="string")?e.push("`lint_ignore` must be a list of strings"):n.lintIgnore=s}if(t.extensions!==void 0){const s=t.extensions;typeof s!="object"||s===null||Array.isArray(s)||Object.values(s).some(c=>typeof c!="object"||c===null||Array.isArray(c))?e.push("`extensions` must map each plugin to an object of fields"):n.extensions=s}const f=Oe(t.rules,e);return f!==void 0&&(n.rules=f),n}u(Z,"fieldsFrom");function J(t){if(t.length>0)throw b(t.join("; "),{errors:t})}u(J,"failOn");function Q(t,e,n,o){const i=U(n).filter(a=>"remote"in X(t,e,a));return{...o.length>0?{unresolved_links:o}:{},...i.length>0?{remote_links:i}:{}}}u(Q,"linkReport");function $e(t){const e=D(t),n=[],o=e.name;(typeof o!="string"||!Y.test(o))&&n.push("`name` must be segments of letters, digits, `_` or `-` joined by `/`"),typeof e.body!="string"&&n.push("`body` must be a string"),typeof e.preview!="string"&&n.push("`preview` is required");const i=e.kind??"knowledge";q.includes(i)||n.push(i==="report"?"reports are written only by `crtr push`":`\`kind\` must be one of ${q.join(", ")}`);const a=Z(e,n);e.cwd!==void 0&&typeof e.cwd!="string"&&n.push("`cwd` must be a string"),J(n);const r=e,{dto:f,change:s}=k(c=>{const h=E(c,t),d=W(c,h,r.owner,r.cwd);if(!K(c,h,d))throw new g(404,"not_found",`no owner ${d.name} you can write to`);try{const{object:p,unresolved:l}=he(c,h,{...a,owner:d,name:r.name,kind:i,preview:a.preview,privacy:a.privacy??"public"},r.body,x(c));return{dto:{id:p.id,name:j(c,p),...Q(c,h,r.body,l)},change:S(c,h,[p],r.cwd)}}catch(p){C(p)}});return T(s),f}u($e,"write");function Ae(t,e){let n=t;e.forEach(({old:o,new:i},a)=>{const r=o===""?-1:n.indexOf(o);if(r<0)throw _(422,"replace_no_match",`replace[${a}]: old text not found in the revision you read`,"Copy the old text exactly from your last read and rerun.",{index:a});if(n.indexOf(o,r+1)>=0)throw _(422,"replace_ambiguous",`replace[${a}]: old text occurs more than once`,"Include more surrounding text so the old text matches once, and rerun.",{index:a});n=n.slice(0,r)+i+n.slice(r+o.length)})}u(Ae,"checkReplacements");function je(t){const e=D(t),n=[],o=e.body!==void 0,i=e.replace!==void 0;o&&i&&n.push("give `body` or `replace`, not both"),o&&typeof e.body!="string"&&n.push("`body` must be a string");const a=e.replace;i&&(!Array.isArray(a)||a.length===0||a.some(d=>typeof d!="object"||d===null||typeof d.old!="string"||typeof d.new!="string"))&&n.push("`replace` must be a non-empty list of {old, new} strings"),(typeof e.rationale!="string"||e.rationale.trim()==="")&&n.push("`rationale` is required"),e.verbatim!==void 0&&typeof e.verbatim!="boolean"&&n.push("`verbatim` must be a boolean"),e.base!==void 0&&(typeof e.base!="string"||e.base==="")&&n.push("`base` must be a non-empty heads key"),e.base!==void 0&&!o&&!i&&n.push("`base` applies only to a `body` or `replace` edit");const r=Z(e,n),f=e.unset??[];if(!Array.isArray(f)||f.some(d=>!H.includes(d)))n.push(`\`unset\` takes only ${H.join(", ")}`);else for(const d of f)d==="summary"&&(r.summary=null),d==="why_it_exists"&&(r.whyItExists=null),d==="unlisted"&&(r.unlisted=!1),d==="lint_ignore"&&(r.lintIgnore=null),d==="extensions"&&(r.extensions=null),d==="rules"&&(r.rules=[]);!o&&!i&&Object.keys(r).length===0&&n.push("nothing to change: give `body`, `replace`, or a field"),J(n);const s=e,{dto:c,synced:h}=k(d=>{const p=E(d,t),l=B(d,p,t.params.ref),v=j(d,l),$=S(d,p,[l]);try{if(!o&&!i)return me(d,p,l,r),{dto:{id:l.id,name:v,revision:F(d,l).revision},synced:$};const w=s.base??le(d,p,l);if(i&&w!==null){const oe=F(d,l),L=I(d,l);oe.heads_key===w&&L.length===1&&Ae(pe(d,l,A(L[0].body_hash)),s.replace)}const R=s.verbatim===!0,m=o?{body:s.body,verbatim:R}:{replace:s.replace,verbatim:R},y=de(d,p,l,m,s.rationale,w,r,x(d));if("stale"in y)throw _(409,"stale_revision",`${v} changed after your read; it is now at revision ${y.stale.revision}`,`Read it again with \`crtr canvas read ${v}\`, then redo your change on the current text.`,{stale:y.stale});const N=A(I(d,l)[0].body_hash);return{dto:{id:l.id,name:v,revision:y.revision,...Q(d,p,N,y.unresolved)},synced:$}}catch(w){C(w,l)}});return T(h),c}u(je,"edit");function Re(t){const e=D(t);if(e.new_name===void 0&&e.owner===void 0)throw b("give a new name, an owner, or both");if(e.new_name!==void 0&&(typeof e.new_name!="string"||!Y.test(e.new_name)))throw b("`new_name` must be segments of letters, digits, `_` or `-` joined by `/`");const{dto:n,change:o}=k(i=>{const a=E(i,t),r=B(i,a,t.params.ref),f=e.owner===void 0?void 0:W(i,a,e.owner,e.cwd);try{const s=fe(i,a,r,{...e.new_name!==void 0?{name:e.new_name}:{},...f?{owner:f}:{}});return{dto:{id:s.id,name:j(i,s)},change:S(i,a,[r,s],e.cwd)}}catch(s){C(s,r)}});return T(o),n}u(Re,"move");function De(t){const{dto:e,change:n}=k(o=>{const i=E(o,t),a=B(o,i,t.params.ref),r=j(o,a),f=S(o,i,[a]);try{ce(o,i,a,x(o))}catch(s){C(s,a)}return{dto:{id:a.id,name:r},change:f}});return T(n),e}u(De,"remove");function Ce(t){const e=t.query.get("diff"),n=e===null?void 0:Number(e);if(n!==void 0&&!(Number.isInteger(n)&&n>0))throw b("`diff` must be a revision number");return k(o=>{const i=E(o,t),a=z(o,i,decodeURIComponent(t.params.ref));if("remote"in a)throw _(404,"not_found",G(a.remote),"Check the name with `crtr canvas search`.");const r="deleted"in a?a.deleted:a;if(r.type!=="document")throw b(`${r.name} is a ${r.type}, not a document`);const f=ue(o,i,r),s={object:ke(o,r),revisions:f.map(c=>({rev_id:c.rev_id,number:c.number,author_id:c.author,rationale:c.rationale,verbatim:c.verbatim,created_at:c.created_at,parents:c.parents}))};if(n!==void 0){const c=f.find(d=>d.number===n);if(!c)throw new g(404,"not_found",`${r.name} has no revision ${n}`);const h=c.parents[0]===void 0?void 0:f.find(d=>d.rev_id===c.parents[0]);s.diff=_e(h?A(h.body_hash):"",A(c.body_hash))}return s})}u(Ce,"revisionHistory");const ee=1e3,ne=1e3,te=3e3,Se=/^When\b.+\bbecause\b.+/,Te=u(t=>{const e=t.trim();return e===""?0:e.split(/\s+/).length},"words");function Ne(t,e){if(t.some(o=>o.on==="boot"&&o.deliver==="content")&&e>ee)return`body is ${e} words, over the ${ee}-word cap for a boot rule at content (the whole body enters every node's context). Keep the core here and move separate subjects into [[linked]] documents.`;const n=[...new Set(t.filter(o=>o.on!=="boot"&&o.deliver==="content").map(o=>o.on))];return n.length>0&&e>ne?`body is ${e} words, over the ${ne}-word cap for a content rule on ${n.join("/")}. Keep the core here and move separate subjects into [[linked]] documents.`:t.some(o=>o.on==="boot"&&o.deliver==="preview")&&e>te?`body is ${e} words, over the ${te}-word cap for a boot rule at preview. Keep the core here and move separate subjects into [[linked]] documents.`:null}u(Ne,"lengthFinding");function Fe(t){const e=D(t);return k(n=>{const o=E(n,t),i=e.owner===void 0?null:W(n,o,e.owner,e.cwd),a=P(n,"SELECT * FROM objects WHERE type = 'document' AND deleted_at IS NULL AND kind != 'report' ORDER BY name").all(),r=[],f=new Map;for(const s of a){if(i&&s.owner!==i.rowid||!K(n,o,s))continue;const c=F(n,s),h=new Set(c.lint_ignore??[]),d=j(n,s),p=u((m,y,N)=>{h.has(m)||r.push({name:d,severity:y,rule:m,message:N})},"add"),l=ge(n,s),v=I(n,s)[0],$=v?A(v.body_hash):"",w=Ne(l,Te($));w&&p("length","error",w),l.some(m=>m.deliver==="preview")&&!Se.test(s.preview??"")&&p("preview-shape","error",`a rule delivers this document at preview, so the preview must read "When <situation in the reader's work>, read this because <what the reader gains>"`);const R=new Set(P(n,"SELECT written_as FROM edges WHERE type = 'links-to' AND src = ?").all(s.rowid).map(m=>m.written_as));for(const m of U($))R.has(m)||"remote"in X(n,o,m)||p("links","warning",`[[${m}]] names no object in your view`);if(l.some(m=>m.on==="workspace-open"&&m.deliver==="content")){const m=ae(n,s);m.type==="repo"&&!h.has("workspace-open")&&f.set(m.name,[...f.get(m.name)??[],d])}}for(const[s,c]of f)if(!(c.length<2))for(const h of c)r.push({name:h,severity:"warning",rule:"workspace-open",message:`repo ${s} has ${c.length} documents delivered at content on workspace-open (${c.join(", ")}); keep one and link the rest from it`});return{findings:r}})}u(Fe,"lint");const O=u((t,e=200)=>n=>({status:e,body:t(n)}),"ok"),Qe=[{method:"POST",pattern:"/v1/docs",handler:O($e,201)},{method:"PATCH",pattern:"/v1/docs/:ref",handler:O(je)},{method:"POST",pattern:"/v1/docs/:ref/move",handler:O(Re)},{method:"DELETE",pattern:"/v1/docs/:ref",handler:O(De)},{method:"GET",pattern:"/v1/docs/:ref/history",handler:O(Ce)},{method:"POST",pattern:"/v1/docs/lint",handler:O(Fe)}];export{Qe as docRoutes};
1
+ var re=Object.defineProperty;var u=(t,e)=>re(t,"name",{value:e,configurable:!0});import{prepared as P}from"../../../core/sqlite-statements.js";import{ApiError as g}from"../../../api/errors.js";import{DOC_KINDS as q,DOC_UNSET_FIELDS as H}from"../../../api/dto/docs.js";import{PRIVACY_LEVELS_DTO as V}from"../../../api/dto/objects.js";import{withCanvasWrite as k}from"../../../core/canvas/db.js";import{CrtrError as ie}from"../../../core/errors.js";import{emitEvent as se}from"../../../core/events/emit.js";import{canChange as K,spaceOf as ae}from"../../../core/graph/access.js";import{get as A}from"../../../core/graph/bodies.js";import{deleteDocument as ce,documentRecord as F,editDocument as de,heads as I,history as ue,linksIn as U,moveDocument as fe,readBase as le,setDocumentRecord as me,withCurrentNames as pe,writeDocument as he}from"../../../core/graph/documents.js";import{resolveName as X}from"../../../core/graph/names.js";import{getByRowid as M}from"../../../core/graph/objects.js";import{noteRepoDocumentsChanged as we}from"../../../core/graph/repo-sync/index.js";import{checkoutsForCwd as ye}from"../../../core/graph/repo-sync/repos.js";import{lintRules as ve,rulesOf as ge}from"../../../core/graph/rules.js";import{unifiedDiff as _e}from"../../../core/graph/diff.js";import{ownerFromFlag as W,readerFor as E,resolveRef as z}from"../reader.js";function _(t,e,n,o,i={}){return new g(t,e,n,{...i,error:e,message:n,next:o})}u(_,"refuse");const b=u((t,e)=>new g(400,"invalid_request",t,e),"invalid");function D(t){const e=t.body;if(e===void 0)return{};if(typeof e!="object"||e===null||Array.isArray(e))throw b("the request body must be a JSON object");return e}u(D,"bodyOf");const x=u(t=>e=>ye(t,e),"reposFnFor");function C(t,e){if(t instanceof ie){const n=t.details;if(t.code==="read_first")throw _(409,"read_first",t.message,`Read it first with \`crtr canvas read ${e?.id??"<ref>"}\`, then rerun the edit.`,n??{});if(t.code==="conflict")throw new g(409,"name_taken",t.message,n);if(t.code==="forbidden")throw new g(403,"forbidden",t.message,n);if(n?.rule==="repo-public-only")throw _(422,"repo_documents_are_public",t.message,'Own it as `user` and add a rule with `if: {"repo": "<handle>"}` so it loads only in that repo.')}throw t}u(C,"mapGraphError");function B(t,e,n){const o=z(t,e,decodeURIComponent(n));if("remote"in o)throw _(404,"not_found",G(o.remote),"Check the name with `crtr canvas search`.");if("deleted"in o)throw new g(404,"not_found",`${o.deleted.name} is deleted`,{id:o.deleted.id,deleted:!0});if(o.type!=="document")throw b(`${n} is a ${o.type}, not a document`);return o}u(B,"refDocument");function G(t){return`no object named ${t} on this runtime; it may be on another runtime, or the name may be misspelled`}u(G,"remoteMessage");function be(t,e){const n=e.owner===null?null:M(t,e.owner);return n?n.type==="node"?n.id:n.name:""}u(be,"ownerHandle");function j(t,e){const n=be(t,e);return n?`${n}/${e.name}`:e.name}u(j,"canonicalName");function ke(t,e){const n=e.owner===null?null:M(t,e.owner),o=n?{id:n.id,type:n.type,handle:n.type==="node"?n.id:n.name}:null;return{id:e.id,type:e.type,kind:e.kind,owner:o,privacy:e.privacy,name:e.name,preview:e.preview??"",created_at:e.created_at,deleted_at:e.deleted_at}}u(ke,"objectDTO");function Ee(t,e){const n=e.owner===null?null:M(t,e.owner);return n?.type==="repo"?n:null}u(Ee,"repoOwner");function S(t,e,n,o){const i=[...new Map(n.flatMap(r=>{const f=Ee(t,r);return f?[[f.id,f]]:[]})).values()],a=e.class==="node"?e.cwd:o;return{repos:i,...a!==void 0?{cwd:a}:{}}}u(S,"repoChange");function T(t){for(const e of t.repos)try{we(e,t.cwd)}catch(n){se({level:"warn",event:"repo_sync.failed",outcome:"failed",error:n,fields:{repo:e.name,step:"export",reason:n instanceof Error?n.message:String(n)}})}}u(T,"syncChanged");const Y=/^[A-Za-z0-9_-]+(\/[A-Za-z0-9_-]+)*$/;function Oe(t,e){if(t===void 0)return;if(!Array.isArray(t)){e.push("`rules` must be a list");return}const n=t.map(i=>{if(typeof i!="object"||i===null||Array.isArray(i))return i;const{match_frontmatter:a,...r}=i;return"matchFrontmatter"in r?{...r,match_frontmatter:r.matchFrontmatter}:a===void 0?r:{...r,matchFrontmatter:a}}),o=ve(n);if(o){e.push(o.replaceAll("matchFrontmatter","match_frontmatter"));return}return n}u(Oe,"rulesFromDTO");function Z(t,e){const n={},o=u(s=>{const c=t[s];if(c!==void 0){if(typeof c!="string"){e.push(`\`${s}\` must be a string`);return}return c}},"str"),i=o("preview");i!==void 0&&(i.trim()===""||/[\r\n]/.test(i)?e.push("`preview` must be one non-empty line"):n.preview=i);const a=o("summary");a!==void 0&&(n.summary=a);const r=o("why_it_exists");if(r!==void 0&&(n.whyItExists=r),t.privacy!==void 0&&(V.includes(t.privacy)?n.privacy=t.privacy:e.push(`\`privacy\` must be one of ${V.join(", ")}`)),t.unlisted!==void 0&&(typeof t.unlisted!="boolean"?e.push("`unlisted` must be a boolean"):n.unlisted=t.unlisted),t.lint_ignore!==void 0){const s=t.lint_ignore;!Array.isArray(s)||s.some(c=>typeof c!="string")?e.push("`lint_ignore` must be a list of strings"):n.lintIgnore=s}if(t.extensions!==void 0){const s=t.extensions;typeof s!="object"||s===null||Array.isArray(s)||Object.values(s).some(c=>typeof c!="object"||c===null||Array.isArray(c))?e.push("`extensions` must map each plugin to an object of fields"):n.extensions=s}const f=Oe(t.rules,e);return f!==void 0&&(n.rules=f),n}u(Z,"fieldsFrom");function J(t){if(t.length>0)throw b(t.join("; "),{errors:t})}u(J,"failOn");function Q(t,e,n,o){const i=U(n).filter(a=>"remote"in X(t,e,a));return{...o.length>0?{unresolved_links:o}:{},...i.length>0?{remote_links:i}:{}}}u(Q,"linkReport");function $e(t){const e=D(t),n=[],o=e.name;(typeof o!="string"||!Y.test(o))&&n.push("`name` must be segments of letters, digits, `_` or `-` joined by `/`"),typeof e.body!="string"&&n.push("`body` must be a string"),typeof e.preview!="string"&&n.push("`preview` is required");const i=e.kind??"knowledge";q.includes(i)||n.push(i==="report"?"reports are written only by `crtr push`":`\`kind\` must be one of ${q.join(", ")}`);const a=Z(e,n);e.cwd!==void 0&&typeof e.cwd!="string"&&n.push("`cwd` must be a string"),J(n);const r=e,{dto:f,change:s}=k(c=>{const h=E(c,t),d=W(c,h,r.owner,r.cwd);if(!K(c,h,d))throw new g(404,"not_found",`no owner ${d.name} you can write to`);try{const{object:p,unresolved:l}=he(c,h,{...a,owner:d,name:r.name,kind:i,preview:a.preview,privacy:a.privacy??"public"},r.body,x(c));return{dto:{id:p.id,name:j(c,p),...Q(c,h,r.body,l)},change:S(c,h,[p],r.cwd)}}catch(p){C(p)}});return T(s),f}u($e,"write");function Ae(t,e){let n=t;e.forEach(({old:o,new:i},a)=>{const r=o===""?-1:n.indexOf(o);if(r<0)throw _(422,"replace_no_match",`replace[${a}]: old text not found in the revision you read`,"Copy the old text exactly from your last read and rerun.",{index:a});if(n.indexOf(o,r+1)>=0)throw _(422,"replace_ambiguous",`replace[${a}]: old text occurs more than once`,"Include more surrounding text so the old text matches once, and rerun.",{index:a});n=n.slice(0,r)+i+n.slice(r+o.length)})}u(Ae,"checkReplacements");function je(t){const e=D(t),n=[],o=e.body!==void 0,i=e.replace!==void 0;o&&i&&n.push("give `body` or `replace`, not both"),o&&typeof e.body!="string"&&n.push("`body` must be a string");const a=e.replace;i&&(!Array.isArray(a)||a.length===0||a.some(d=>typeof d!="object"||d===null||typeof d.old!="string"||typeof d.new!="string"))&&n.push("`replace` must be a non-empty list of {old, new} strings"),(typeof e.rationale!="string"||e.rationale.trim()==="")&&n.push("`rationale` is required"),e.verbatim!==void 0&&typeof e.verbatim!="boolean"&&n.push("`verbatim` must be a boolean"),e.base!==void 0&&(typeof e.base!="string"||e.base==="")&&n.push("`base` must be a non-empty heads key"),e.base!==void 0&&!o&&!i&&n.push("`base` applies only to a `body` or `replace` edit");const r=Z(e,n),f=e.unset??[];if(!Array.isArray(f)||f.some(d=>!H.includes(d)))n.push(`\`unset\` takes only ${H.join(", ")}`);else for(const d of f)d==="summary"&&(r.summary=null),d==="why_it_exists"&&(r.whyItExists=null),d==="unlisted"&&(r.unlisted=!1),d==="lint_ignore"&&(r.lintIgnore=null),d==="extensions"&&(r.extensions=null),d==="rules"&&(r.rules=[]);n.length===0&&!o&&!i&&Object.keys(r).length===0&&n.push("nothing to change: give `body`, `replace`, or a field"),J(n);const s=e,{dto:c,synced:h}=k(d=>{const p=E(d,t),l=B(d,p,t.params.ref),v=j(d,l),$=S(d,p,[l]);try{if(!o&&!i)return me(d,p,l,r),{dto:{id:l.id,name:v,revision:F(d,l).revision},synced:$};const w=s.base??le(d,p,l);if(i&&w!==null){const oe=F(d,l),L=I(d,l);oe.heads_key===w&&L.length===1&&Ae(pe(d,l,A(L[0].body_hash)),s.replace)}const R=s.verbatim===!0,m=o?{body:s.body,verbatim:R}:{replace:s.replace,verbatim:R},y=de(d,p,l,m,s.rationale,w,r,x(d));if("stale"in y)throw _(409,"stale_revision",`${v} changed after your read; it is now at revision ${y.stale.revision}`,`Read it again with \`crtr canvas read ${v}\`, then redo your change on the current text.`,{stale:y.stale});const N=A(I(d,l)[0].body_hash);return{dto:{id:l.id,name:v,revision:y.revision,...Q(d,p,N,y.unresolved)},synced:$}}catch(w){C(w,l)}});return T(h),c}u(je,"edit");function Re(t){const e=D(t);if(e.new_name===void 0&&e.owner===void 0)throw b("give a new name, an owner, or both");if(e.new_name!==void 0&&(typeof e.new_name!="string"||!Y.test(e.new_name)))throw b("`new_name` must be segments of letters, digits, `_` or `-` joined by `/`");const{dto:n,change:o}=k(i=>{const a=E(i,t),r=B(i,a,t.params.ref),f=e.owner===void 0?void 0:W(i,a,e.owner,e.cwd);try{const s=fe(i,a,r,{...e.new_name!==void 0?{name:e.new_name}:{},...f?{owner:f}:{}});return{dto:{id:s.id,name:j(i,s)},change:S(i,a,[r,s],e.cwd)}}catch(s){C(s,r)}});return T(o),n}u(Re,"move");function De(t){const{dto:e,change:n}=k(o=>{const i=E(o,t),a=B(o,i,t.params.ref),r=j(o,a),f=S(o,i,[a]);try{ce(o,i,a,x(o))}catch(s){C(s,a)}return{dto:{id:a.id,name:r},change:f}});return T(n),e}u(De,"remove");function Ce(t){const e=t.query.get("diff"),n=e===null?void 0:Number(e);if(n!==void 0&&!(Number.isInteger(n)&&n>0))throw b("`diff` must be a revision number");return k(o=>{const i=E(o,t),a=z(o,i,decodeURIComponent(t.params.ref));if("remote"in a)throw _(404,"not_found",G(a.remote),"Check the name with `crtr canvas search`.");const r="deleted"in a?a.deleted:a;if(r.type!=="document")throw b(`${r.name} is a ${r.type}, not a document`);const f=ue(o,i,r),s={object:ke(o,r),revisions:f.map(c=>({rev_id:c.rev_id,number:c.number,author_id:c.author,rationale:c.rationale,verbatim:c.verbatim,created_at:c.created_at,parents:c.parents}))};if(n!==void 0){const c=f.find(d=>d.number===n);if(!c)throw new g(404,"not_found",`${r.name} has no revision ${n}`);const h=c.parents[0]===void 0?void 0:f.find(d=>d.rev_id===c.parents[0]);s.diff=_e(h?A(h.body_hash):"",A(c.body_hash))}return s})}u(Ce,"revisionHistory");const ee=1e3,ne=1e3,te=3e3,Se=/^When\b.+\bbecause\b.+/,Te=u(t=>{const e=t.trim();return e===""?0:e.split(/\s+/).length},"words");function Ne(t,e){if(t.some(o=>o.on==="boot"&&o.deliver==="content")&&e>ee)return`body is ${e} words, over the ${ee}-word cap for a boot rule at content (the whole body enters every node's context). Keep the core here and move separate subjects into [[linked]] documents.`;const n=[...new Set(t.filter(o=>o.on!=="boot"&&o.deliver==="content").map(o=>o.on))];return n.length>0&&e>ne?`body is ${e} words, over the ${ne}-word cap for a content rule on ${n.join("/")}. Keep the core here and move separate subjects into [[linked]] documents.`:t.some(o=>o.on==="boot"&&o.deliver==="preview")&&e>te?`body is ${e} words, over the ${te}-word cap for a boot rule at preview. Keep the core here and move separate subjects into [[linked]] documents.`:null}u(Ne,"lengthFinding");function Fe(t){const e=D(t);return k(n=>{const o=E(n,t),i=e.owner===void 0?null:W(n,o,e.owner,e.cwd),a=P(n,"SELECT * FROM objects WHERE type = 'document' AND deleted_at IS NULL AND kind != 'report' ORDER BY name").all(),r=[],f=new Map;for(const s of a){if(i&&s.owner!==i.rowid||!K(n,o,s))continue;const c=F(n,s),h=new Set(c.lint_ignore??[]),d=j(n,s),p=u((m,y,N)=>{h.has(m)||r.push({name:d,severity:y,rule:m,message:N})},"add"),l=ge(n,s),v=I(n,s)[0],$=v?A(v.body_hash):"",w=Ne(l,Te($));w&&p("length","error",w),l.some(m=>m.deliver==="preview")&&!Se.test(s.preview??"")&&p("preview-shape","error",`a rule delivers this document at preview, so the preview must read "When <situation in the reader's work>, read this because <what the reader gains>"`);const R=new Set(P(n,"SELECT written_as FROM edges WHERE type = 'links-to' AND src = ?").all(s.rowid).map(m=>m.written_as));for(const m of U($))R.has(m)||"remote"in X(n,o,m)||p("links","warning",`[[${m}]] names no object in your view`);if(l.some(m=>m.on==="workspace-open"&&m.deliver==="content")){const m=ae(n,s);m.type==="repo"&&!h.has("workspace-open")&&f.set(m.name,[...f.get(m.name)??[],d])}}for(const[s,c]of f)if(!(c.length<2))for(const h of c)r.push({name:h,severity:"warning",rule:"workspace-open",message:`repo ${s} has ${c.length} documents delivered at content on workspace-open (${c.join(", ")}); keep one and link the rest from it`});return{findings:r}})}u(Fe,"lint");const O=u((t,e=200)=>n=>({status:e,body:t(n)}),"ok"),Qe=[{method:"POST",pattern:"/v1/docs",handler:O($e,201)},{method:"PATCH",pattern:"/v1/docs/:ref",handler:O(je)},{method:"POST",pattern:"/v1/docs/:ref/move",handler:O(Re)},{method:"DELETE",pattern:"/v1/docs/:ref",handler:O(De)},{method:"GET",pattern:"/v1/docs/:ref/history",handler:O(Ce)},{method:"POST",pattern:"/v1/docs/lint",handler:O(Fe)}];export{Qe as docRoutes};
@@ -47,6 +47,6 @@ printf '%s\n' 'Production changes need an explicit approval.' | \
47
47
  crtr doc edit <name> --rationale "Updated the approval rule."
48
48
  ```
49
49
 
50
- `crtr doc edit` replaces the whole body you pipe; it does not append text. For a partial change, use `crtr doc edit <name> --rationale '…' --blocks <<'EOF'` with whole-line `<<<<<<< SEARCH`, `=======`, and `>>>>>>> REPLACE` markers around verbatim old and new text. An empty REPLACE deletes text. Scripts can still use `--replace '[{"old":"…","new":"…"}]'`. Read the document before you edit it; an edit made from an older revision is refused. Use `crtr doc history <name>` to read the revision history. If you want to create a document yourself, use `crtr doc write`; it takes a name, a preview sentence that tells agents when to read it, and the document body on stdin. `--kind knowledge|preference` (default `knowledge`) sets how agents use it, and `--owner node|user|profile|app|repo` chooses who owns it (default: the writing node; `profile:<name>` and `repo:<handle>` name a specific one). New documents are `privacy: public` unless `--privacy friends` or `--privacy private` is supplied; a repository owns only public documents. `crtr doc edit --privacy <level>` changes the level and records the revision.
50
+ `crtr doc edit` replaces the whole body you pipe; it does not append text. For a partial change, use `crtr doc edit <name> --rationale '…' --blocks <<'EOF'` with whole-line `<<<<<<< SEARCH`, `=======`, and `>>>>>>> REPLACE` markers around verbatim old and new text. An empty REPLACE deletes text. Scripts can still use `--replace '[{"old":"…","new":"…"}]'`. Read the document before you edit it; an edit made from an older revision is refused. Use `crtr doc history <name>` to read the revision history. If you want to create a document yourself, use `crtr doc write`; it takes a name, a preview sentence that tells agents when to read it, and the document body on stdin. `--kind knowledge|preference` (default `knowledge`) sets how agents use it, and `--owner node|user|profile|app|repo` chooses who owns it (default: the writing node; `profile:<name>` and `repo:<handle>` name a specific one). New documents are `privacy: public` unless `--privacy friends` or `--privacy private` is supplied; a repository owns only public documents. `crtr doc edit --privacy <level>` changes the level. An edit that changes only fields (privacy, preview, summary, rules, `--why-it-exists`) takes effect at once but makes no new revision: revisions are versions of the body, so the revision number does not move and `crtr doc history` shows nothing for it.
51
51
 
52
52
  Documents are for reusable current truth and durable instructions, not a transcript of one conversation. When a fact changes, update the existing document rather than saving a second version.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north-light/cli",
3
- "version": "0.3.434",
3
+ "version": "0.3.435",
4
4
  "description": "crtr — agent runtime with memory, plugins, and marketplaces",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -137,7 +137,7 @@
137
137
  },
138
138
  "license": "UNLICENSED",
139
139
  "dependencies": {
140
- "@north-light/identity": "0.3.434",
140
+ "@north-light/identity": "0.3.435",
141
141
  "@earendil-works/pi-agent-core": "1.1.0",
142
142
  "@earendil-works/pi-ai": "1.1.0",
143
143
  "@earendil-works/pi-coding-agent": "1.1.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north-light/identity",
3
- "version": "0.3.434",
3
+ "version": "0.3.435",
4
4
  "description": "Northlight access-token verification and scope rules",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/runtime.lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@north-light/cli",
3
- "version": "0.3.434",
3
+ "version": "0.3.435",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@north-light/cli",
9
- "version": "0.3.434",
9
+ "version": "0.3.435",
10
10
  "hasInstallScript": true,
11
11
  "license": "UNLICENSED",
12
12
  "workspaces": [
@@ -18,7 +18,7 @@
18
18
  "@earendil-works/pi-ai": "1.1.0",
19
19
  "@earendil-works/pi-coding-agent": "1.1.0",
20
20
  "@earendil-works/pi-tui": "1.1.0",
21
- "@north-light/identity": "0.3.434",
21
+ "@north-light/identity": "0.3.435",
22
22
  "cron-parser": "^5.6.0",
23
23
  "esbuild": "^0.27.7",
24
24
  "jose": "^6.2.12",
@@ -12095,17 +12095,17 @@
12095
12095
  },
12096
12096
  "packages/crouter-api": {
12097
12097
  "name": "@north-light/api",
12098
- "version": "0.3.434",
12098
+ "version": "0.3.435",
12099
12099
  "license": "UNLICENSED"
12100
12100
  },
12101
12101
  "packages/crouter-env-docker": {
12102
12102
  "name": "@north-light/env-docker",
12103
- "version": "0.3.434",
12103
+ "version": "0.3.435",
12104
12104
  "license": "UNLICENSED"
12105
12105
  },
12106
12106
  "packages/crouter-identity": {
12107
12107
  "name": "@north-light/identity",
12108
- "version": "0.3.434",
12108
+ "version": "0.3.435",
12109
12109
  "license": "UNLICENSED",
12110
12110
  "dependencies": {
12111
12111
  "jose": "^6.2.1"
@@ -12113,20 +12113,20 @@
12113
12113
  },
12114
12114
  "packages/crouter-plugin": {
12115
12115
  "name": "@north-light/plugin",
12116
- "version": "0.3.434",
12116
+ "version": "0.3.435",
12117
12117
  "license": "UNLICENSED",
12118
12118
  "dependencies": {
12119
- "@north-light/api": "0.3.434",
12120
- "@north-light/identity": "0.3.434"
12119
+ "@north-light/api": "0.3.435",
12120
+ "@north-light/identity": "0.3.435"
12121
12121
  }
12122
12122
  },
12123
12123
  "packages/crouter-sdk": {
12124
12124
  "name": "@north-light/sdk",
12125
- "version": "0.3.434",
12125
+ "version": "0.3.435",
12126
12126
  "license": "UNLICENSED",
12127
12127
  "dependencies": {
12128
- "@north-light/api": "0.3.434",
12129
- "@north-light/identity": "0.3.434",
12128
+ "@north-light/api": "0.3.435",
12129
+ "@north-light/identity": "0.3.435",
12130
12130
  "jose": "^6.2.1"
12131
12131
  },
12132
12132
  "bin": {