@lmctl-ai/lmctl 0.2.432 → 0.2.434

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.
package/dist/lmbee.js CHANGED
@@ -2176,7 +2176,7 @@ ${a}
2176
2176
  WHERE id = ? AND enabled = 1 AND revision = ? AND running_since_ts = ? AND running_systemd_unit = ?`).run("reconciled",s,t.id,t.revision,t.running_since_ts,t.running_systemd_unit),jw(e,t.id,"reconciled: command execution confirmed gone by systemd probe; no exit callback survived the restart");return}e.prepare("UPDATE cron_jobs SET last_fire_status = ?, updated_at = ? WHERE id = ? AND enabled = 1 AND revision = ? AND running_since_ts = ?").run("skipped_overlap",s,t.id,t.revision,t.running_since_ts);return}let p=t.last_checked_ts!==null?Date.parse(t.last_checked_ts):Date.parse(t.created_at);if(p>r){go(e,"UPDATE cron_jobs SET last_checked_ts = ?, last_fire_status = ?, last_fire_error = ?, updated_at = ?",[s,"error",`last_checked_ts (${t.last_checked_ts??t.created_at}) is after the current tick time -- checkpoint reset without firing`,s],t);return}let h=new Date(p),_=new Date(r);if(r-p>_ee){go(e,"UPDATE cron_jobs SET last_checked_ts = ?, last_fire_status = ?, updated_at = ?",[s,"skipped_stale",s],t);return}let g=t.timezone!==null?tD(h,t.timezone):h,w=t.timezone!==null?tD(_,t.timezone):_;if(!PO(m,g,w)){go(e,"UPDATE cron_jobs SET last_checked_ts = ?, updated_at = ?",[s,s],t);return}let y=ap(e,t.id);if(!(y===null||y.enabled===0||y.revision!==t.revision)){if(pee(t.action_kind)){Tee(e,t,s,l,u,d);return}if(t.action_kind==="enqueue")try{let T=JSON.parse(t.action_payload),v={from:T.from??"autopilot",dedupeKey:`cron:${t.id}:${h.toISOString()}`};e.transaction(()=>{let I=e.prepare("SELECT enabled, revision, last_checked_ts FROM cron_jobs WHERE id = ?").get(t.id);return I===void 0||I.enabled===0||I.revision!==t.revision||I.last_checked_ts!==t.last_checked_ts?!1:(o(e,n,T.to,T.prompt,v),e.prepare("UPDATE cron_jobs SET last_checked_ts = ?, last_fired_ts = ?, last_fire_status = ?, last_fire_error = NULL, updated_at = ? WHERE id = ?").run(s,s,"ok",s,t.id),!0)}).immediate()&&l.push(t.title)}catch(T){try{u?.(t.id,T)}catch{}try{go(e,"UPDATE cron_jobs SET last_fire_status = ?, last_fire_error = ?, updated_at = ?",["error",Fn(T),s],t)}catch{}}else{let T=s,v=`lmcron-job-${t.id}-${T.replace(/[:.]/g,"-")}.scope`;if(e.prepare(`UPDATE cron_jobs SET last_checked_ts = ?, last_fired_ts = ?, last_fire_status = ?, last_fire_error = NULL, running_since_ts = ?, running_systemd_unit = ?, updated_at = ?
2177
2177
  WHERE id = ? AND enabled = 1 AND revision = ? AND (last_checked_ts IS ?) AND (running_since_ts IS ?)`).run(s,s,"ok",s,v,s,t.id,t.revision,t.last_checked_ts,t.running_since_ts).changes===0)return;let I=lD(e,t,t.action_kind,v,a),N={logDir:c,systemdUnitName:v,onExit:(x,R,k,O)=>{let D=x===0?"ok":"error",S=D==="ok"?null:R?Fn(R):`Command exited with code ${x} -- see ${c??ep()}/${t.id}/ for output`;if(R)try{u?.(t.id,R)}catch{}try{e.prepare("UPDATE cron_jobs SET running_since_ts = NULL, running_systemd_unit = NULL, last_fire_status = ?, last_fire_error = ?, updated_at = ? WHERE id = ? AND running_since_ts = ?").run(D,S,new Date().toISOString(),t.id,T)}catch{}uD(e,I,x,R,k,O,v)}};try{i({id:t.id,action_payload:t.action_payload},N),l.push(t.title)}catch(x){try{u?.(t.id,x)}catch{}try{e.prepare("UPDATE cron_jobs SET last_fire_status = ?, last_fire_error = ?, running_since_ts = NULL, running_systemd_unit = NULL, updated_at = ? WHERE id = ? AND running_since_ts = ?").run("error",Fn(x),s,t.id,T)}catch{}dD(e,I,x)}}}}async function nD(e,t){for(;!e();)await new Promise(n=>setTimeout(n,t))}async function su(e,t,n,r={}){let s=r.enqueueImpl??De,o=r.spawnCommandImpl??Xl,i=r.isUnitStillRunningImpl??aD,a=r.executeRunImpl??Fw,c=r.logDir,l=r.pollMs??250,u=it(e,t);if(Pa(e,t)&&r.onDemand===void 0)return{kind:"skipped_overlap",job:u};if(u.enabled===0)throw new G("DISABLED",`Cron job ${t} is disabled -- enable it first (\`cron enable ${t}\`), or a manual trigger would silently exercise a job the operator turned off on purpose`,4);let d=ve();if(u.action_kind==="command"){if(u.running_since_ts!==null)return u.running_systemd_unit!==null&&i(u.running_systemd_unit)==="confirmed-gone"?(e.prepare(`UPDATE cron_jobs SET running_since_ts = NULL, running_systemd_unit = NULL, last_fire_status = ?, last_fire_error = NULL, updated_at = ?
2178
2178
  WHERE id = ? AND revision = ? AND running_since_ts = ? AND running_systemd_unit = ?`).run("reconciled",d,u.id,u.revision,u.running_since_ts,u.running_systemd_unit),jw(e,u.id,"reconciled: command execution confirmed gone by systemd probe; no exit callback survived the restart"),await su(e,t,n,r)):{kind:"skipped_overlap",job:u};let p=d,h=`lmcron-job-${u.id}-${p.replace(/[:.]/g,"-")}-manual.scope`;if(e.prepare(`UPDATE cron_jobs SET last_fired_ts = ?, last_fire_status = ?, last_fire_error = NULL, running_since_ts = ?, running_systemd_unit = ?, updated_at = ?
2179
- WHERE id = ? AND enabled = 1 AND revision = ? AND running_since_ts IS ?`).run(d,"ok",p,h,d,u.id,u.revision,u.running_since_ts).changes===0)return{kind:"skipped_overlap",job:it(e,t)};let g=lD(e,u,`${u.action_kind}:manual`,h,i),w={logDir:c,systemdUnitName:h,onExit:(E,y,T,v)=>{let A=E===0?"ok":"error",I=A==="ok"?null:y?Fn(y):`Command exited with code ${E} -- see ${c??ep()}/${u.id}/ for output`;try{e.prepare("UPDATE cron_jobs SET running_since_ts = NULL, running_systemd_unit = NULL, last_fire_status = ?, last_fire_error = ?, updated_at = ? WHERE id = ? AND running_since_ts = ?").run(A,I,new Date().toISOString(),u.id,p)}catch{}uD(e,g,E,y,T,v,h)}};try{o({id:u.id,action_payload:u.action_payload},w)}catch(E){dD(e,g,E);try{e.prepare("UPDATE cron_jobs SET last_fire_status = ?, last_fire_error = ?, running_since_ts = NULL, running_systemd_unit = NULL, updated_at = ? WHERE id = ? AND running_since_ts = ?").run("error",Fn(E),d,u.id,p)}catch{}throw new G("SPAWN_FAILED",`manual trigger of job ${t} failed to spawn: ${Fn(E)}`,1)}return await nD(()=>it(e,t).running_since_ts!==p,l),{kind:"fired",job:it(e,t)}}if(u.action_kind==="enqueue"){let p=JSON.parse(u.action_payload);return s(e,n,p.to,p.prompt,{from:p.from??"autopilot"}),e.prepare("UPDATE cron_jobs SET last_fired_ts = ?, last_fire_status = ?, last_fire_error = NULL, updated_at = ? WHERE id = ?").run(d,"ok",d,u.id),{kind:"fired",job:it(e,t)}}let f=JSON.stringify({kind:u.action_kind,payload:u.action_payload,provider:u.provider,model:u.model,workingDirectory:u.working_directory,escalationOwner:u.escalation_owner}),m=e.transaction(()=>{let p=e.prepare("SELECT enabled, revision FROM cron_jobs WHERE id = ?").get(u.id);if(p===void 0||p.enabled===0||p.revision!==u.revision)return null;let h=zl(e,u.id,`${u.action_kind}:manual`,f);if(h.kind==="claimed"){r.onDemand!==void 0&&xO(e,u.id,h.run.id,r.onDemand);let _=r.disableOnClaim?"enabled = 0, ":"";e.prepare(`UPDATE cron_jobs SET ${_}last_fired_ts = ?, last_fire_status = ?, last_fire_error = NULL, updated_at = ? WHERE id = ?`).run(d,"ok",d,u.id)}return h}).immediate();if(m===null)throw new G("CONFLICT",`Cron job ${t} was modified concurrently -- re-run \`cron trigger ${t}\``,5);if(m.kind==="escalation")return{kind:"blocked_escalation",job:it(e,t)};if(m.kind==="overlap")return{kind:"skipped_overlap",job:it(e,t)};try{a({db:e,job:u,run:m.run,runToken:m.token,...r.onDemand!==void 0?{onDemand:r.onDemand}:{},...r.runSpawnPrefixes!==void 0?{spawnPrefixes:r.runSpawnPrefixes}:{},...r.sessionDir!==void 0?{sessionDir:r.sessionDir}:{},...r.runTimeoutMs!==void 0?{timeoutMs:r.runTimeoutMs}:{},...r.runSeedTimeoutMs!==void 0?{seedTimeoutMs:r.runSeedTimeoutMs}:{}})}catch(p){try{Ql(e,m.run.id,`worker dispatch threw: ${Fn(p)}`),kw(e,m.run.id,{ok:!1,summary:`worker dispatch error: ${Fn(p)}`})}catch{}throw new G("SPAWN_FAILED",`manual trigger of job ${t} failed to dispatch: ${Fn(p)}`,1)}if(r.waitForCompletion===!1){let p=u;try{p=it(e,t)}catch(h){console.warn(`[triggerCronJobNow] post-dispatch getCronJob read failed for job ${t}:`,h)}return{kind:"fired",job:p,runId:m.run.id}}return await nD(()=>{let p=xt(e,m.run.id);return p.status!=="pending"&&p.status!=="running"},l),{kind:"fired",job:it(e,t),runId:m.run.id}}function Tee(e,t,n,r,s,o){if(Pa(e,t.id))return;let i=JSON.stringify({kind:t.action_kind,payload:t.action_payload,provider:t.provider,model:t.model,workingDirectory:t.working_directory,escalationOwner:t.escalation_owner}),a=e.transaction(()=>{let c=e.prepare("SELECT enabled, revision, last_checked_ts FROM cron_jobs WHERE id = ?").get(t.id);if(c===void 0||c.enabled===0||c.revision!==t.revision||c.last_checked_ts!==t.last_checked_ts)return null;let l=zl(e,t.id,t.action_kind,i);return l.kind==="claimed"&&e.prepare("UPDATE cron_jobs SET last_checked_ts = ?, last_fired_ts = ?, last_fire_status = ?, last_fire_error = NULL, updated_at = ? WHERE id = ?").run(n,n,"ok",n,t.id),l}).immediate();if(a!==null){if(a.kind==="escalation"){go(e,"UPDATE cron_jobs SET last_fire_status = ?, updated_at = ?",["blocked_escalation",n],t);return}if(a.kind==="overlap"){go(e,"UPDATE cron_jobs SET last_fire_status = ?, updated_at = ?",["skipped_overlap",n],t);return}r.push(t.title);try{o.executeRunImpl({db:e,job:t,run:a.run,runToken:a.token,...o.runSpawnPrefixes!==void 0?{spawnPrefixes:o.runSpawnPrefixes}:{},...o.sessionDir!==void 0?{sessionDir:o.sessionDir}:{},...o.runTimeoutMs!==void 0?{timeoutMs:o.runTimeoutMs}:{},...o.runSeedTimeoutMs!==void 0?{seedTimeoutMs:o.runSeedTimeoutMs}:{}})}catch(c){try{Ql(e,a.run.id,`worker dispatch threw: ${Fn(c)}`),kw(e,a.run.id,{ok:!1,summary:`worker dispatch error: ${Fn(c)}`})}catch{}try{s?.(t.id,c)}catch{}}}}function go(e,t,n,r){e.prepare(`${t} WHERE id = ? AND enabled = 1 AND revision = ? AND (last_checked_ts IS ?)`).run(...n,r.id,r.revision,r.last_checked_ts)}function fD(e,t){let n=e.transaction(()=>{it(e,t);try{e.prepare("UPDATE cron_jobs SET running_since_ts = NULL, running_systemd_unit = NULL WHERE id = ?").run(t)}catch(r){Ha(r)}return ip(e,t),it(e,t)});return ws(n)}import{execFileSync as vee}from"node:child_process";import{existsSync as See,readFileSync as mD}from"node:fs";import{homedir as pD}from"node:os";import{join as hD}from"node:path";function Wa(){return process.env.LMBEE_HEAVY_STATUS??hD(pD(),".lmbee","heavy.status")}function Ga(){return process.env.LMBEE_HEAVY_LOCK??hD(pD(),".lmbee","heavy.lock")}var Ba=class extends Error{};function bee(e){if(typeof e!="object"||e===null)return!1;let t=e;return typeof t.holder=="string"&&typeof t.pid=="number"&&typeof t.command=="string"&&typeof t.startedAt=="string"}function Aee(e){let t;try{t=mD(e,"utf8")}catch{return null}try{let n=JSON.parse(t);return bee(n)?n:null}catch{return null}}function Iee(e,t){return e===null||t===null?e===t:e.holder===t.holder&&e.pid===t.pid&&e.command===t.command&&e.startedAt===t.startedAt}function kee(e){try{let t=mD(`/proc/${e}/stat`,"utf8");return t.slice(t.lastIndexOf(")")+2).trim().split(/\s+/)[0]==="Z"}catch{return!1}}function Ree(e){try{process.kill(e,0)}catch(t){return t.code==="EPERM"}return!kee(e)}function Nee(e,t=vee){if(!See(e))return!1;try{return t("flock",["-n",e,"-c","true"],{stdio:"ignore"}),!1}catch(n){if((n&&typeof n=="object"?n.status:void 0)===1)return!0;let s=n instanceof Error?n.message:String(n);throw new Ba(`heavy-lock probe failed (flock did not run or exited abnormally): ${s}`)}}function Hw(e=Wa(),t=Ga(),n=Aee,r=Nee,s=Ree){for(let o=0;o<3;o++){let i=n(e),a=r(t),c=n(e);if(i!==null&&Iee(i,c)){if(!a)return{held:!1,holder:null};if(s(i.pid))return{held:!0,holder:i}}}return{held:r(t),holder:null}}function vn(e=Wa(),t=Ga(),n=Hw,r){try{return n(e,t)}catch(s){if(!(s instanceof Ba))throw s;return r?.(s),{held:!0,holder:null}}}var dp={observedAt:null,report:null,lastErrorAt:null,lastError:null};function _D(e,t){dp={observedAt:t,report:e,lastErrorAt:null,lastError:null}}function gD(e,t){dp={...dp,lastErrorAt:t,lastError:e}}function ou(){return dp}import{execFile as xee}from"node:child_process";import{promisify as Lee}from"node:util";function Ae(e){if(!Number.isFinite(e)||e<0)return"?";if(e<1e3)return"0s";if(e<6e4)return`${Math.floor(e/1e3)}s`;if(e<36e5)return`${Math.floor(e/6e4)}m`;if(e<864e5*2)return`${Math.floor(e/36e5)}h`;let t=Math.floor(e/864e5),n=Math.floor(e%864e5/36e5);return n===0?`${t}d`:`${t}d ${n}h`}function Le(e,t=Date.now()){let n=Date.parse(e);if(Number.isNaN(n))return"?";let r=t-n;return r<6e4?"just now":`${Ae(r)} ago`}var Cee=Lee(xee);function Oee(e){if(typeof e!="object"||e===null||Array.isArray(e))return!1;let t=e;return(typeof t.target=="string"||t.target===null)&&typeof t.from_identity=="string"}function Dee(e){let t=JSON.parse(e);if(typeof t!="object"||t===null||!Array.isArray(t.running)||!Array.isArray(t.dead)||!Array.isArray(t.idle))throw new Error("unexpected `lmctl running --json` shape: missing running/dead/idle arrays");let n=t;for(let r of["running","dead","idle"])if(!n[r].every(Oee))throw new Error(`unexpected \`lmctl running --json\` shape: a malformed element (bad/missing target or from_identity) in \`${r}\``);return n}async function qe(e=3e4,t={}){let n=t.reconcile===!0?["running","--json","--reconcile"]:["running","--json"],{stdout:r}=await Cee("lmctl",n,{timeout:e});return Dee(r)}function qw(e,t=Date.now()){return{schema_version:e.schema_version,running:e.running.map(n=>({...n,running_for_human:Ae(n.running_for_ms),started_human:Le(n.started_at,t)})),dead:e.dead.map(n=>({...n,age_human:Ae(n.age_ms),started_human:Le(n.started_at,t)})),idle:e.idle.map(n=>({...n,ran_human:Ae(n.ran_ms)}))}}import{readFileSync as $ee}from"node:fs";import{randomUUID as Mee}from"node:crypto";var Bw={staleThresholdMs:2*60*6e4,escalationCooldownMs:60*6e4,digestTimeoutMs:9e4,leaseTimeoutMs:10*6e4,providerQuotaBackoffMs:24*60*6e4,operatorStaleThresholdMs:6e4,operatorEscalationCooldownMs:6e4};function Pee(e){return/usage limit/i.test(e)&&/quota/i.test(e)}function Uee(e){let t=[];for(let n of e)try{t.push({row:n,content:$ee(n.prompt_file,"utf8")})}catch{continue}return t}function Fee(e){let t=e.map(({row:n,content:r})=>`--- from "${n.from_id}", queued ${n.created_ts} ---
2179
+ WHERE id = ? AND enabled = 1 AND revision = ? AND running_since_ts IS ?`).run(d,"ok",p,h,d,u.id,u.revision,u.running_since_ts).changes===0)return{kind:"skipped_overlap",job:it(e,t)};let g=lD(e,u,`${u.action_kind}:manual`,h,i),w={logDir:c,systemdUnitName:h,onExit:(E,y,T,v)=>{let A=E===0?"ok":"error",I=A==="ok"?null:y?Fn(y):`Command exited with code ${E} -- see ${c??ep()}/${u.id}/ for output`;try{e.prepare("UPDATE cron_jobs SET running_since_ts = NULL, running_systemd_unit = NULL, last_fire_status = ?, last_fire_error = ?, updated_at = ? WHERE id = ? AND running_since_ts = ?").run(A,I,new Date().toISOString(),u.id,p)}catch{}uD(e,g,E,y,T,v,h)}};try{o({id:u.id,action_payload:u.action_payload},w)}catch(E){dD(e,g,E);try{e.prepare("UPDATE cron_jobs SET last_fire_status = ?, last_fire_error = ?, running_since_ts = NULL, running_systemd_unit = NULL, updated_at = ? WHERE id = ? AND running_since_ts = ?").run("error",Fn(E),d,u.id,p)}catch{}throw new G("SPAWN_FAILED",`manual trigger of job ${t} failed to spawn: ${Fn(E)}`,1)}return await nD(()=>it(e,t).running_since_ts!==p,l),{kind:"fired",job:it(e,t)}}if(u.action_kind==="enqueue"){let p=JSON.parse(u.action_payload);return s(e,n,p.to,p.prompt,{from:p.from??"autopilot"}),e.prepare("UPDATE cron_jobs SET last_fired_ts = ?, last_fire_status = ?, last_fire_error = NULL, updated_at = ? WHERE id = ?").run(d,"ok",d,u.id),{kind:"fired",job:it(e,t)}}let f=JSON.stringify({kind:u.action_kind,payload:u.action_payload,provider:u.provider,model:u.model,workingDirectory:u.working_directory,escalationOwner:u.escalation_owner}),m=e.transaction(()=>{let p=e.prepare("SELECT enabled, revision FROM cron_jobs WHERE id = ?").get(u.id);if(p===void 0||p.enabled===0||p.revision!==u.revision)return null;let h=zl(e,u.id,`${u.action_kind}:manual`,f);if(h.kind==="claimed"){r.onDemand!==void 0&&xO(e,u.id,h.run.id,r.onDemand);let _=r.disableOnClaim?"enabled = 0, ":"";e.prepare(`UPDATE cron_jobs SET ${_}last_fired_ts = ?, last_fire_status = ?, last_fire_error = NULL, updated_at = ? WHERE id = ?`).run(d,"ok",d,u.id)}return h}).immediate();if(m===null)throw new G("CONFLICT",`Cron job ${t} was modified concurrently -- re-run \`cron trigger ${t}\``,5);if(m.kind==="escalation")return{kind:"blocked_escalation",job:it(e,t)};if(m.kind==="overlap")return{kind:"skipped_overlap",job:it(e,t)};try{a({db:e,job:u,run:m.run,runToken:m.token,...r.onDemand!==void 0?{onDemand:r.onDemand}:{},...r.runSpawnPrefixes!==void 0?{spawnPrefixes:r.runSpawnPrefixes}:{},...r.sessionDir!==void 0?{sessionDir:r.sessionDir}:{},...r.runTimeoutMs!==void 0?{timeoutMs:r.runTimeoutMs}:{},...r.runSeedTimeoutMs!==void 0?{seedTimeoutMs:r.runSeedTimeoutMs}:{}})}catch(p){try{Ql(e,m.run.id,`worker dispatch threw: ${Fn(p)}`),kw(e,m.run.id,{ok:!1,summary:`worker dispatch error: ${Fn(p)}`})}catch{}throw new G("SPAWN_FAILED",`manual trigger of job ${t} failed to dispatch: ${Fn(p)}`,1)}if(r.waitForCompletion===!1){let p=u;try{p=it(e,t)}catch(h){console.warn(`[triggerCronJobNow] post-dispatch getCronJob read failed for job ${t}:`,h)}return{kind:"fired",job:p,runId:m.run.id}}return await nD(()=>{let p=xt(e,m.run.id);return p.status!=="pending"&&p.status!=="running"},l),{kind:"fired",job:it(e,t),runId:m.run.id}}function Tee(e,t,n,r,s,o){if(Pa(e,t.id))return;let i=JSON.stringify({kind:t.action_kind,payload:t.action_payload,provider:t.provider,model:t.model,workingDirectory:t.working_directory,escalationOwner:t.escalation_owner}),a=e.transaction(()=>{let c=e.prepare("SELECT enabled, revision, last_checked_ts FROM cron_jobs WHERE id = ?").get(t.id);if(c===void 0||c.enabled===0||c.revision!==t.revision||c.last_checked_ts!==t.last_checked_ts)return null;let l=zl(e,t.id,t.action_kind,i);return l.kind==="claimed"&&e.prepare("UPDATE cron_jobs SET last_checked_ts = ?, last_fired_ts = ?, last_fire_status = ?, last_fire_error = NULL, updated_at = ? WHERE id = ?").run(n,n,"ok",n,t.id),l}).immediate();if(a!==null){if(a.kind==="escalation"){go(e,"UPDATE cron_jobs SET last_fire_status = ?, updated_at = ?",["blocked_escalation",n],t);return}if(a.kind==="overlap"){go(e,"UPDATE cron_jobs SET last_fire_status = ?, updated_at = ?",["skipped_overlap",n],t);return}r.push(t.title);try{o.executeRunImpl({db:e,job:t,run:a.run,runToken:a.token,...o.runSpawnPrefixes!==void 0?{spawnPrefixes:o.runSpawnPrefixes}:{},...o.sessionDir!==void 0?{sessionDir:o.sessionDir}:{},...o.runTimeoutMs!==void 0?{timeoutMs:o.runTimeoutMs}:{},...o.runSeedTimeoutMs!==void 0?{seedTimeoutMs:o.runSeedTimeoutMs}:{}})}catch(c){try{Ql(e,a.run.id,`worker dispatch threw: ${Fn(c)}`),kw(e,a.run.id,{ok:!1,summary:`worker dispatch error: ${Fn(c)}`})}catch{}try{s?.(t.id,c)}catch{}}}}function go(e,t,n,r){e.prepare(`${t} WHERE id = ? AND enabled = 1 AND revision = ? AND (last_checked_ts IS ?)`).run(...n,r.id,r.revision,r.last_checked_ts)}function fD(e,t){let n=e.transaction(()=>{it(e,t);try{e.prepare("UPDATE cron_jobs SET running_since_ts = NULL, running_systemd_unit = NULL WHERE id = ?").run(t)}catch(r){Ha(r)}return ip(e,t),it(e,t)});return ws(n)}import{execFileSync as vee}from"node:child_process";import{existsSync as See,readFileSync as mD}from"node:fs";import{homedir as pD}from"node:os";import{join as hD}from"node:path";function Wa(){return process.env.LMBEE_HEAVY_STATUS??hD(pD(),".lmbee","heavy.status")}function Ga(){return process.env.LMBEE_HEAVY_LOCK??hD(pD(),".lmbee","heavy.lock")}var Ba=class extends Error{};function bee(e){if(typeof e!="object"||e===null)return!1;let t=e;return typeof t.holder=="string"&&typeof t.pid=="number"&&typeof t.command=="string"&&typeof t.startedAt=="string"}function Aee(e){let t;try{t=mD(e,"utf8")}catch{return null}try{let n=JSON.parse(t);return bee(n)?n:null}catch{return null}}function Iee(e,t){return e===null||t===null?e===t:e.holder===t.holder&&e.pid===t.pid&&e.command===t.command&&e.startedAt===t.startedAt}function kee(e){try{let t=mD(`/proc/${e}/stat`,"utf8");return t.slice(t.lastIndexOf(")")+2).trim().split(/\s+/)[0]==="Z"}catch{return!1}}function Ree(e){try{process.kill(e,0)}catch(t){return t.code==="EPERM"}return!kee(e)}function Nee(e,t=vee){if(!See(e))return!1;try{return t("flock",["-n",e,"-c","true"],{stdio:"ignore"}),!1}catch(n){if((n&&typeof n=="object"?n.status:void 0)===1)return!0;let s=n instanceof Error?n.message:String(n);throw new Ba(`heavy-lock probe failed (flock did not run or exited abnormally): ${s}`)}}function Hw(e=Wa(),t=Ga(),n=Aee,r=Nee,s=Ree){for(let o=0;o<3;o++){let i=n(e),a=r(t),c=n(e);if(i!==null&&Iee(i,c)){if(!a)return{held:!1,holder:null};if(s(i.pid))return{held:!0,holder:i}}}return{held:r(t),holder:null}}function vn(e=Wa(),t=Ga(),n=Hw,r){try{return n(e,t)}catch(s){if(!(s instanceof Ba))throw s;return r?.(s),{held:!0,holder:null}}}var dp={observedAt:null,report:null,lastErrorAt:null,lastError:null};function _D(e,t){dp={observedAt:t,report:e,lastErrorAt:null,lastError:null}}function gD(e,t){dp={...dp,lastErrorAt:t,lastError:e}}function ou(){return dp}import{execFile as xee}from"node:child_process";import{promisify as Lee}from"node:util";function Ae(e){if(!Number.isFinite(e)||e<0)return"?";if(e<1e3)return"0s";if(e<6e4)return`${Math.floor(e/1e3)}s`;if(e<36e5)return`${Math.floor(e/6e4)}m`;if(e<864e5*2)return`${Math.floor(e/36e5)}h`;let t=Math.floor(e/864e5),n=Math.floor(e%864e5/36e5);return n===0?`${t}d`:`${t}d ${n}h`}function Le(e,t=Date.now()){let n=Date.parse(e);if(Number.isNaN(n))return"?";let r=t-n;return r<6e4?"just now":`${Ae(r)} ago`}var Cee=Lee(xee);function Oee(e){if(typeof e!="object"||e===null||Array.isArray(e))return!1;let t=e;return(typeof t.target=="string"||t.target===null)&&typeof t.from_identity=="string"}function Dee(e){let t=JSON.parse(e);if(typeof t!="object"||t===null||!Array.isArray(t.running)||!Array.isArray(t.dead)||!Array.isArray(t.idle))throw new Error("unexpected `lmctl running --json` shape: missing running/dead/idle arrays");let n=t;for(let r of["running","dead","idle"])if(!n[r].every(Oee))throw new Error(`unexpected \`lmctl running --json\` shape: a malformed element (bad/missing target or from_identity) in \`${r}\``);return n}async function qe(e=3e4,t={}){let n=t.reconcile===!0?["running","--json-legacy","--reconcile"]:["running","--json-legacy"],{stdout:r}=await Cee("lmctl",n,{timeout:e});return Dee(r)}function qw(e,t=Date.now()){return{schema_version:e.schema_version,running:e.running.map(n=>({...n,running_for_human:Ae(n.running_for_ms),started_human:Le(n.started_at,t)})),dead:e.dead.map(n=>({...n,age_human:Ae(n.age_ms),started_human:Le(n.started_at,t)})),idle:e.idle.map(n=>({...n,ran_human:Ae(n.ran_ms)}))}}import{readFileSync as $ee}from"node:fs";import{randomUUID as Mee}from"node:crypto";var Bw={staleThresholdMs:2*60*6e4,escalationCooldownMs:60*6e4,digestTimeoutMs:9e4,leaseTimeoutMs:10*6e4,providerQuotaBackoffMs:24*60*6e4,operatorStaleThresholdMs:6e4,operatorEscalationCooldownMs:6e4};function Pee(e){return/usage limit/i.test(e)&&/quota/i.test(e)}function Uee(e){let t=[];for(let n of e)try{t.push({row:n,content:$ee(n.prompt_file,"utf8")})}catch{continue}return t}function Fee(e){let t=e.map(({row:n,content:r})=>`--- from "${n.from_id}", queued ${n.created_ts} ---
2180
2180
  ${r}`);return`You have ${e.length} queued message(s) that couldn't be delivered automatically (presence-gated for a while) -- bundled here as a digest:
2181
2181
 
2182
2182
  ${t.join(`
@@ -2349,7 +2349,7 @@ ${Bt}`;X=o(e.db,C,P,K,Hn,M,St?void 0:!Jt)}else X=o(e.db,C,P,K,void 0,M)}catch(K)
2349
2349
  `)}return"replied"}function lre(e,t,n,r,s){let o=e.now??(()=>new Date().toISOString()),i={v:1,msgId:sre(),to:t,from:{site:e.localSiteId,team:"",alias:"lmauto"},sentAt:o(),payload:JSON.stringify({state:r,...s?{note:s}:{}}),inReplyTo:n},a=Zn(t.site),c=new TextEncoder().encode(Mc(i));e.client.sendMessage({mailbox:a,subject:`lmauto ack ${i.msgId}`,body:{name:"body.txt",contentType:"text/plain; charset=utf-8",bytes:c}}).catch(l=>{process.stderr.write(`[mail] failed to send ack to mailbox ${a} (in_reply_to ${n}): ${l instanceof Error?l.message:String(l)}
2350
2350
  `)})}function Q$(e,t,n,r){if(n.inReplyTo){cre(e,t,n,(r.now??(()=>new Date().toISOString()))());return}let s;try{z$(e,t,n)}catch(i){s=i}let o=r.now??(()=>new Date().toISOString());if(oA(e,n.msgId,o())){let i=s?(s instanceof Error?s.message:String(s)).slice(0,500):void 0;lre(r,n.from,n.msgId,s?"failed":"dispatched",i)}if(s)throw s}var nM=/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,ure=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/,dre="text/plain; charset=utf-8",hT="exec",rM="exec-result";var fre="exec-result";var mre=`
2351
2351
  ... [lmexec output truncated; middle elided, see attachment] ...
2352
- `;function sM(e){return _T(cM(e))}function oM(e){return iM(cM(e))}function _T(e){let t=lM(e),n=uM(t.type,"type",hT),r=dM(t.id,"id"),s=ET(t.command,"command"),o=Ere(t.timeout_s,"timeout_s"),i=gre(t.reply_to,"reply_to"),a=hre(t.from,"from");return{v:1,type:n,id:r,command:s,timeout_s:o,reply_to:i,...a===void 0?{}:{from:a}}}function iM(e){let t=lM(e),n=pre(t.v),r=uM(t.type,"type",rM),s=dM(t.id,"id"),o=wre(t.exit_code,"exit_code"),i=eM(t.stdout,"stdout"),a=eM(t.stderr,"stderr"),c=yre(t.duration_ms,"duration_ms"),l=tM(t.timed_out,"timed_out"),u=tM(t.truncated,"truncated");if(l&&o!==null)throw new Error("invalid exec result: exit_code must be null when timed_out is true");if(!l&&o===null)throw new Error("invalid exec result: exit_code must be a number when timed_out is false");let d={type:r,id:s,exit_code:o,stdout:i,stderr:a,duration_ms:c,timed_out:l,truncated:u};if(n===1)return{v:n,...d};let f=_re(t.sender_trust),m=ET(t.sender,"sender");return{v:n,...d,sender_trust:f,sender:m}}function gT(e){if(!nM.test(e))throw new Error(`invalid exec id: ${e}`);return`${fre} ${e}`}function Z$(e,t,n){let r=Buffer.isBuffer(t)?t:Buffer.from(t,"utf8"),s=n?.capBytes??49152,o=n?.marker??mre;if(!Number.isInteger(s)||s<1)throw new Error("inline cap must be a positive integer");if(r.byteLength<=s)return{inline:r.toString("utf8"),truncated:!1};let i=Buffer.byteLength(o,"utf8");if(i>=s)throw new Error("elision marker must be smaller than the inline cap");let a=r.toString("utf8"),c=s-i,l=Math.ceil(c/2),u=Math.floor(c/2);return{inline:`${Tre(a,l)}${o}${vre(a,u)}`,truncated:!0,attachment:{name:e==="stdout"?"stdout.txt":"stderr.txt",content_type:dre,data:r}}}function aM(e,t){let n=Z$("stdout",e.stdout,t),r=Z$("stderr",e.stderr,t),s=iM({v:2,type:rM,id:e.id,exit_code:e.exit_code,stdout:n.inline,stderr:r.inline,duration_ms:e.duration_ms,timed_out:e.timed_out,truncated:n.truncated||r.truncated,sender_trust:e.sender_trust,sender:e.sender});return{subject:gT(e.id),envelope:s,attachments:[n.attachment,r.attachment].filter(o=>o!==void 0)}}function cM(e){try{return JSON.parse(e)}catch(t){throw new Error(`invalid JSON: ${Sre(t)}`)}}function lM(e){if(!e||typeof e!="object"||Array.isArray(e))throw new Error("expected object");return e}function uM(e,t,n){if(e!==n)throw new Error(`invalid ${t}: expected ${n}`);return n}function pre(e){if(e===void 0||e===1)return 1;if(e===2)return 2;throw new Error("invalid v: expected 1 or 2")}function dM(e,t){if(typeof e!="string"||!nM.test(e))throw new Error(`invalid ${t}: expected UUID v4`);return e}function ET(e,t){if(typeof e!="string"||e.trim().length===0)throw new Error(`invalid ${t}: expected non-empty string`);return e}function hre(e,t){if(e!==void 0)return ET(e,t)}function _re(e){if(e==="admin"||e==="registered"||e==="anonymous")return e;throw new Error("invalid sender_trust: expected admin, registered, or anonymous")}function gre(e,t){if(typeof e!="string"||e.includes("/")||e.includes("\\")||e.includes("..")||e.endsWith(".")||/[\u0000-\u001f\u007f]/.test(e)||!ure.test(e))throw new Error(`invalid ${t}: expected mailbox name`);return e}function eM(e,t){if(typeof e!="string")throw new Error(`invalid ${t}: expected string`);return e}function Ere(e,t){if(typeof e!="number"||!Number.isSafeInteger(e)||e<1)throw new Error(`invalid ${t}: expected positive integer`);return e}function yre(e,t){if(typeof e!="number"||!Number.isSafeInteger(e)||e<0)throw new Error(`invalid ${t}: expected non-negative integer`);return e}function wre(e,t){if(e===null)return null;if(typeof e!="number"||!Number.isSafeInteger(e)||e<0)throw new Error(`invalid ${t}: expected non-negative integer or null`);return e}function tM(e,t){if(typeof e!="boolean")throw new Error(`invalid ${t}: expected boolean`);return e}function Tre(e,t){if(t<=0||e.length===0)return"";let n=0,r="";for(let s of e){let o=Buffer.byteLength(s,"utf8");if(n+o>t)break;r+=s,n+=o}return r}function vre(e,t){if(t<=0||e.length===0)return"";let n=0,r=[],s=Array.from(e);for(let o=s.length-1;o>=0;o-=1){let i=s[o],a=Buffer.byteLength(i,"utf8");if(n+a>t)break;r.push(i),n+=a}return r.reverse().join("")}function Sre(e){return e instanceof Error&&e.message?e.message:String(e)}var bre=/[;&|`$<>(){}\\]/,fM=/[\x00-\x1f\x7f]/;function pM(e){let t=[],n=0,r=e.length;for(;n<r;){for(;n<r&&e[n]===" ";)n+=1;if(n>=r)break;let s;if(e[n]==='"'||e[n]==="'"){let o=e[n];n+=1,s="";let i=n;for(;;){for(;n<r&&e[n]!==o;){if(fM.test(e[n])||o==="'"&&e[n]==="\\")return null;n+=1}if(n>=r)return null;if(s+=e.slice(i,n),o==="'"&&e[n+1]==="\\"&&e[n+2]==="'"&&e[n+3]==="'"){s+="'",n+=4,i=n;continue}n+=1;break}if(n<r&&e[n]!==" ")return null}else{let o=n;for(;n<r&&e[n]!==" ";){if(fM.test(e[n])||bre.test(e[n]))return null;n+=1}if(s=e.slice(o,n),s.includes('"')||s.includes("'"))return null}t.push(s)}return t.length>0?t:null}function hM(e){if(!e.includes("--json"))return"requires --json when run via exec (plain-text output has no machine-readable contract)"}function yT(e,t,n,r,s){let o=new Set,i=[];for(let a=0;a<t.length;a+=1){let c=t[a];if(c==="")return`${e}: an empty argument is not accepted`;if(!c.startsWith("-")){i.push(c);continue}let l=Object.hasOwn(n,c)?n[c]:void 0;if(l===void 0)return`${e} via exec does not accept ${c}: only ${Object.keys(n).join(", ")} and ${r.max===0?"no positionals":"its positional arguments"} are admitted`;if(o.has(c))return`${e}: ${c} given twice`;if(o.add(c),l==="bool")continue;let u=t[a+1];if(u===void 0||u===""||u.startsWith("-"))return`${e} ${c} requires a value that does not start with '-'`;if(l==="positiveInt"&&!/^[1-9][0-9]*$/.test(u))return`${e} ${c} requires a positive integer`;a+=1}return i.length<r.min||i.length>r.max?r.max===0?`${e} via exec takes no positional arguments`:`${e} via exec takes a team and an optional alias (${r.min} or ${r.max} positionals)`:s?.(i)}var Are=/\.(?:lmctl|lmc)$/i,Ire=/^(?:.+)\.(?:lmctl|lmc):[A-Za-z][A-Za-z0-9_-]*$/i,kre=/^[A-Za-z][A-Za-z0-9_-]*$/;function Rre(e){let[t,n]=e,r=Ire.test(t);if(!r&&!Are.test(t))return"tail via exec requires a teamfile (<path>.lmctl or <path>.lmctl:<alias>) as its target, not a session id or other name";if(n!==void 0){if(r)return"tail: an alias was given both as <teamfile>:<alias> and as a second argument";if(!kre.test(n))return"tail: the alias must start with a letter and contain only letters, digits, '_' and '-'"}}function Nre(e){let t=e.slice(2);return t.includes("--watch")?"tail --watch is a long-running stream, not a fit for a single bounded exec call":t.includes("--lines")?yT("tail",t,{"--lines":"positiveInt","--json":"bool","--since":"value"},{min:1,max:2},Rre)??hM(e):"tail requires --lines N when run via exec (unbounded --max-bytes/no-limit output is not allowed)"}function xre(e){return yT("running",e.slice(2),{"--json":"bool","--tree":"bool","--team":"value","--member":"value","--since":"value"},{min:0,max:0})??hM(e)}var Ya=void 0;function Ti(e,t,n,r,s){return o=>yT(e,o.slice(t),n,r,s)}var Lre=Ti("lmbee status",2,{"--json":"bool","--live":"bool"},{min:0,max:0},Ya),Cre=Ti("lmbee teams",2,{"--json":"bool"},{min:0,max:0},Ya),Ore=Ti("lmbee history",2,{"--json":"bool"},{min:0,max:2},e=>{if(e.length===2&&/^[0-9]+$/.test(e[0]))return"lmbee history: a numeric first argument is the limit, so a second argument would be ignored";if(e.length===2&&!/^[0-9]+$/.test(e[1]))return"lmbee history: the second argument is a limit and must be a non-negative integer"}),Dre=Ti("lmbee state list",3,{"--json":"bool","--non-done":"bool"},{min:0,max:0},Ya),$re=Ti("lmbee state get",3,{"--json":"bool"},{min:1,max:1},Ya),Mre=Ti("lmbee state active",3,{"--json":"bool"},{min:0,max:0},Ya),Pre=Ti("lmbee source list",3,{"--json":"bool"},{min:0,max:0},Ya),_M=[{prefix:["lmbee","status"],validate:Lre},{prefix:["lmbee","teams"],validate:Cre},{prefix:["lmbee","history"],validate:Ore},{prefix:["lmbee","state","list"],validate:Dre},{prefix:["lmbee","state","get"],validate:$re},{prefix:["lmbee","state","active"],validate:Mre},{prefix:["lmbee","source","list"],validate:Pre},{prefix:["lmctl","running"],validate:xre},{prefix:["lmctl","tail"],validate:Nre}],gM=[{prefix:["lmbee","send"]},{prefix:["lmbee","state","set"]},{prefix:["lmbee","source","add"]},{prefix:["lmbee","source","remove"]}],$Pe=Object.freeze([..._M,...gM].map(e=>Object.freeze([...e.prefix])));function Ure(e,t){return e.length<t.prefix.length?!1:t.prefix.every((n,r)=>e[r]===n)}function mM(e,t){return t.find(n=>Ure(e,n))}function EM(e,t){if(e[0]==="lmbee"&&(e[1]==="enqueue"||e[1]==="queue")||e[0]==="lmctl"&&e[1]==="queue")return{allowed:!1,code:"command_not_allowed",message:"the former lmbee prompt queue is retired; use lmctl prompt, lmctl cron, mailbox remote execution for cross-site work, or lmchat"};let n=mM(e,_M);if(n){let s=n.validate?.(e);return s?{allowed:!1,code:"command_not_allowed",message:s}:{allowed:!0}}let r=mM(e,gM);if(r){let s=r.validate?.(e);return s?{allowed:!1,code:"command_not_allowed",message:s}:t!=="admin"?{allowed:!1,code:"insufficient_trust",message:`write command requires the operator (admin) trust tier; sender is ${t}`}:{allowed:!0}}return{allowed:!1,code:"command_not_allowed",message:`command is not exec-able from the web: ${e.join(" ")}`}}import{spawn as yM}from"node:child_process";var Fre=5e3,jre="/bin/sh";function wM(e){if(!Number.isInteger(e.timeoutMs)||e.timeoutMs<1)throw new Error("timeoutMs must be a positive integer");let t=e.killGraceMs??Fre;if(!Number.isInteger(t)||t<0)throw new Error("killGraceMs must be a non-negative integer");return{killGraceMs:t,now:e.now??Date.now}}function TM(e,t,n,r){return new Promise((s,o)=>{let i=r(),a=[],c=[],l=!1,u=!1,d,f,m=h=>{u||(u=!0,d&&clearTimeout(d),f&&clearTimeout(f),s(h))},p=h=>{u||(u=!0,d&&clearTimeout(d),f&&clearTimeout(f),o(h))};e.stdout.on("data",h=>{a.push(Buffer.isBuffer(h)?h:Buffer.from(h))}),e.stderr.on("data",h=>{c.push(Buffer.isBuffer(h)?h:Buffer.from(h))}),e.on("error",h=>{p(h)}),e.on("close",h=>{m({exit_code:l?null:typeof h=="number"?h:null,stdout:Buffer.concat(a),stderr:Buffer.concat(c),duration_ms:Math.max(0,Math.round(r()-i)),timed_out:l})}),d=setTimeout(()=>{l=!0,wT(e.pid,"SIGTERM"),n>0?f=setTimeout(()=>{wT(e.pid,"SIGKILL")},n):wT(e.pid,"SIGKILL")},t)})}async function vM(e,t){if(e.trim().length===0)throw new Error("command must be non-empty");let{killGraceMs:n,now:r}=wM(t),s=t.shellPath??jre,o=yM(s,["-c",e],{cwd:t.cwd,env:t.env,detached:!0,stdio:["ignore","pipe","pipe"]});return TM(o,t.timeoutMs,n,r)}async function SM(e,t){if(e.length===0)throw new Error("argv must be non-empty");let{killGraceMs:n,now:r}=wM(t),s=yM(e[0],e.slice(1),{cwd:t.cwd,env:t.env,detached:!0,stdio:["ignore","pipe","pipe"]});return TM(s,t.timeoutMs,n,r)}function wT(e,t){if(e)try{process.kill(-e,t)}catch(n){if(!Hre(n))throw n}}function Hre(e){return!!e&&typeof e=="object"&&"code"in e&&e.code==="ESRCH"}var bM=1e3,Bre=6e4,Wre=20,Gre=1e3;async function IM(e,t){let n=t.runCommand??vM,r=t.runCommandArgv??SM,s=t.sleep??Vre,o=t.pollNow??Date.now,i=t.now??(()=>new Date),a=t.stderr??(d=>process.stderr.write(`${d}
2352
+ `;function sM(e){return _T(cM(e))}function oM(e){return iM(cM(e))}function _T(e){let t=lM(e),n=uM(t.type,"type",hT),r=dM(t.id,"id"),s=ET(t.command,"command"),o=Ere(t.timeout_s,"timeout_s"),i=gre(t.reply_to,"reply_to"),a=hre(t.from,"from");return{v:1,type:n,id:r,command:s,timeout_s:o,reply_to:i,...a===void 0?{}:{from:a}}}function iM(e){let t=lM(e),n=pre(t.v),r=uM(t.type,"type",rM),s=dM(t.id,"id"),o=wre(t.exit_code,"exit_code"),i=eM(t.stdout,"stdout"),a=eM(t.stderr,"stderr"),c=yre(t.duration_ms,"duration_ms"),l=tM(t.timed_out,"timed_out"),u=tM(t.truncated,"truncated");if(l&&o!==null)throw new Error("invalid exec result: exit_code must be null when timed_out is true");if(!l&&o===null)throw new Error("invalid exec result: exit_code must be a number when timed_out is false");let d={type:r,id:s,exit_code:o,stdout:i,stderr:a,duration_ms:c,timed_out:l,truncated:u};if(n===1)return{v:n,...d};let f=_re(t.sender_trust),m=ET(t.sender,"sender");return{v:n,...d,sender_trust:f,sender:m}}function gT(e){if(!nM.test(e))throw new Error(`invalid exec id: ${e}`);return`${fre} ${e}`}function Z$(e,t,n){let r=Buffer.isBuffer(t)?t:Buffer.from(t,"utf8"),s=n?.capBytes??49152,o=n?.marker??mre;if(!Number.isInteger(s)||s<1)throw new Error("inline cap must be a positive integer");if(r.byteLength<=s)return{inline:r.toString("utf8"),truncated:!1};let i=Buffer.byteLength(o,"utf8");if(i>=s)throw new Error("elision marker must be smaller than the inline cap");let a=r.toString("utf8"),c=s-i,l=Math.ceil(c/2),u=Math.floor(c/2);return{inline:`${Tre(a,l)}${o}${vre(a,u)}`,truncated:!0,attachment:{name:e==="stdout"?"stdout.txt":"stderr.txt",content_type:dre,data:r}}}function aM(e,t){let n=Z$("stdout",e.stdout,t),r=Z$("stderr",e.stderr,t),s=iM({v:2,type:rM,id:e.id,exit_code:e.exit_code,stdout:n.inline,stderr:r.inline,duration_ms:e.duration_ms,timed_out:e.timed_out,truncated:n.truncated||r.truncated,sender_trust:e.sender_trust,sender:e.sender});return{subject:gT(e.id),envelope:s,attachments:[n.attachment,r.attachment].filter(o=>o!==void 0)}}function cM(e){try{return JSON.parse(e)}catch(t){throw new Error(`invalid JSON: ${Sre(t)}`)}}function lM(e){if(!e||typeof e!="object"||Array.isArray(e))throw new Error("expected object");return e}function uM(e,t,n){if(e!==n)throw new Error(`invalid ${t}: expected ${n}`);return n}function pre(e){if(e===void 0||e===1)return 1;if(e===2)return 2;throw new Error("invalid v: expected 1 or 2")}function dM(e,t){if(typeof e!="string"||!nM.test(e))throw new Error(`invalid ${t}: expected UUID v4`);return e}function ET(e,t){if(typeof e!="string"||e.trim().length===0)throw new Error(`invalid ${t}: expected non-empty string`);return e}function hre(e,t){if(e!==void 0)return ET(e,t)}function _re(e){if(e==="admin"||e==="registered"||e==="anonymous")return e;throw new Error("invalid sender_trust: expected admin, registered, or anonymous")}function gre(e,t){if(typeof e!="string"||e.includes("/")||e.includes("\\")||e.includes("..")||e.endsWith(".")||/[\u0000-\u001f\u007f]/.test(e)||!ure.test(e))throw new Error(`invalid ${t}: expected mailbox name`);return e}function eM(e,t){if(typeof e!="string")throw new Error(`invalid ${t}: expected string`);return e}function Ere(e,t){if(typeof e!="number"||!Number.isSafeInteger(e)||e<1)throw new Error(`invalid ${t}: expected positive integer`);return e}function yre(e,t){if(typeof e!="number"||!Number.isSafeInteger(e)||e<0)throw new Error(`invalid ${t}: expected non-negative integer`);return e}function wre(e,t){if(e===null)return null;if(typeof e!="number"||!Number.isSafeInteger(e)||e<0)throw new Error(`invalid ${t}: expected non-negative integer or null`);return e}function tM(e,t){if(typeof e!="boolean")throw new Error(`invalid ${t}: expected boolean`);return e}function Tre(e,t){if(t<=0||e.length===0)return"";let n=0,r="";for(let s of e){let o=Buffer.byteLength(s,"utf8");if(n+o>t)break;r+=s,n+=o}return r}function vre(e,t){if(t<=0||e.length===0)return"";let n=0,r=[],s=Array.from(e);for(let o=s.length-1;o>=0;o-=1){let i=s[o],a=Buffer.byteLength(i,"utf8");if(n+a>t)break;r.push(i),n+=a}return r.reverse().join("")}function Sre(e){return e instanceof Error&&e.message?e.message:String(e)}var bre=/[;&|`$<>(){}\\]/,fM=/[\x00-\x1f\x7f]/;function pM(e){let t=[],n=0,r=e.length;for(;n<r;){for(;n<r&&e[n]===" ";)n+=1;if(n>=r)break;let s;if(e[n]==='"'||e[n]==="'"){let o=e[n];n+=1,s="";let i=n;for(;;){for(;n<r&&e[n]!==o;){if(fM.test(e[n])||o==="'"&&e[n]==="\\")return null;n+=1}if(n>=r)return null;if(s+=e.slice(i,n),o==="'"&&e[n+1]==="\\"&&e[n+2]==="'"&&e[n+3]==="'"){s+="'",n+=4,i=n;continue}n+=1;break}if(n<r&&e[n]!==" ")return null}else{let o=n;for(;n<r&&e[n]!==" ";){if(fM.test(e[n])||bre.test(e[n]))return null;n+=1}if(s=e.slice(o,n),s.includes('"')||s.includes("'"))return null}t.push(s)}return t.length>0?t:null}function hM(e){if(!e.includes("--json"))return"requires --json when run via exec (plain-text output has no machine-readable contract)"}function yT(e,t,n,r,s){let o=new Set,i=[];for(let a=0;a<t.length;a+=1){let c=t[a];if(c==="")return`${e}: an empty argument is not accepted`;if(!c.startsWith("-")){i.push(c);continue}let l=Object.hasOwn(n,c)?n[c]:void 0;if(l===void 0)return`${e} via exec does not accept ${c}: only ${Object.keys(n).join(", ")} and ${r.max===0?"no positionals":"its positional arguments"} are admitted`;if(o.has(c))return`${e}: ${c} given twice`;if(o.add(c),l==="bool")continue;let u=t[a+1];if(u===void 0||u===""||u.startsWith("-"))return`${e} ${c} requires a value that does not start with '-'`;if(l==="positiveInt"&&!/^[1-9][0-9]*$/.test(u))return`${e} ${c} requires a positive integer`;a+=1}return i.length<r.min||i.length>r.max?r.max===0?`${e} via exec takes no positional arguments`:`${e} via exec takes a team and an optional alias (${r.min} or ${r.max} positionals)`:s?.(i)}var Are=/\.(?:lmctl|lmc)$/i,Ire=/^(?:.+)\.(?:lmctl|lmc):[A-Za-z][A-Za-z0-9_-]*$/i,kre=/^[A-Za-z][A-Za-z0-9_-]*$/;function Rre(e){let[t,n]=e,r=Ire.test(t);if(!r&&!Are.test(t))return"tail via exec requires a teamfile (<path>.lmctl or <path>.lmctl:<alias>) as its target, not a session id or other name";if(n!==void 0){if(r)return"tail: an alias was given both as <teamfile>:<alias> and as a second argument";if(!kre.test(n))return"tail: the alias must start with a letter and contain only letters, digits, '_' and '-'"}}function Nre(e){let t=e.slice(2);return t.includes("--watch")?"tail --watch is a long-running stream, not a fit for a single bounded exec call":t.includes("--lines")?yT("tail",t,{"--lines":"positiveInt","--json":"bool","--since":"value"},{min:1,max:2},Rre)??hM(e):"tail requires --lines N when run via exec (unbounded --max-bytes/no-limit output is not allowed)"}function xre(e){return yT("running",e.slice(2),{"--json":"bool","--tree":"bool","--team":"value","--member":"value","--since":"value"},{min:0,max:0})??hM(e)}var Ya=void 0;function Ti(e,t,n,r,s){return o=>yT(e,o.slice(t),n,r,s)}var Lre=Ti("lmctl status",2,{"--json":"bool","--live":"bool"},{min:0,max:0},Ya),Cre=Ti("lmctl teams",2,{"--json":"bool"},{min:0,max:0},Ya),Ore=Ti("lmctl history",2,{"--json":"bool"},{min:0,max:2},e=>{if(e.length===2&&/^[0-9]+$/.test(e[0]))return"lmctl history: a numeric first argument is the limit, so a second argument would be ignored";if(e.length===2&&!/^[0-9]+$/.test(e[1]))return"lmctl history: the second argument is a limit and must be a non-negative integer"}),Dre=Ti("lmctl state list",3,{"--json":"bool","--non-done":"bool"},{min:0,max:0},Ya),$re=Ti("lmctl state get",3,{"--json":"bool"},{min:1,max:1},Ya),Mre=Ti("lmctl state active",3,{"--json":"bool"},{min:0,max:0},Ya),Pre=Ti("lmctl source list",3,{"--json":"bool"},{min:0,max:0},Ya),_M=[{prefix:["lmctl","status"],validate:Lre},{prefix:["lmctl","teams"],validate:Cre},{prefix:["lmctl","history"],validate:Ore},{prefix:["lmctl","state","list"],validate:Dre},{prefix:["lmctl","state","get"],validate:$re},{prefix:["lmctl","state","active"],validate:Mre},{prefix:["lmctl","source","list"],validate:Pre},{prefix:["lmctl","running"],validate:xre},{prefix:["lmctl","tail"],validate:Nre}],gM=[{prefix:["lmctl","state","set"]},{prefix:["lmctl","source","add"]},{prefix:["lmctl","source","remove"]}],$Pe=Object.freeze([..._M,...gM].map(e=>Object.freeze([...e.prefix])));function Ure(e,t){return e.length<t.prefix.length?!1:t.prefix.every((n,r)=>e[r]===n)}function mM(e,t){return t.find(n=>Ure(e,n))}function EM(e,t){if(e[0]==="lmbee"&&(e[1]==="enqueue"||e[1]==="queue")||e[0]==="lmctl"&&e[1]==="queue")return{allowed:!1,code:"command_not_allowed",message:"the former lmbee prompt queue is retired; use lmctl prompt, lmctl cron, mailbox remote execution for cross-site work, or lmchat"};let n=mM(e,_M);if(n){let s=n.validate?.(e);return s?{allowed:!1,code:"command_not_allowed",message:s}:{allowed:!0}}let r=mM(e,gM);if(r){let s=r.validate?.(e);return s?{allowed:!1,code:"command_not_allowed",message:s}:t!=="admin"?{allowed:!1,code:"insufficient_trust",message:`write command requires the operator (admin) trust tier; sender is ${t}`}:{allowed:!0}}return{allowed:!1,code:"command_not_allowed",message:`command is not exec-able from the web: ${e.join(" ")}`}}import{spawn as yM}from"node:child_process";var Fre=5e3,jre="/bin/sh";function wM(e){if(!Number.isInteger(e.timeoutMs)||e.timeoutMs<1)throw new Error("timeoutMs must be a positive integer");let t=e.killGraceMs??Fre;if(!Number.isInteger(t)||t<0)throw new Error("killGraceMs must be a non-negative integer");return{killGraceMs:t,now:e.now??Date.now}}function TM(e,t,n,r){return new Promise((s,o)=>{let i=r(),a=[],c=[],l=!1,u=!1,d,f,m=h=>{u||(u=!0,d&&clearTimeout(d),f&&clearTimeout(f),s(h))},p=h=>{u||(u=!0,d&&clearTimeout(d),f&&clearTimeout(f),o(h))};e.stdout.on("data",h=>{a.push(Buffer.isBuffer(h)?h:Buffer.from(h))}),e.stderr.on("data",h=>{c.push(Buffer.isBuffer(h)?h:Buffer.from(h))}),e.on("error",h=>{p(h)}),e.on("close",h=>{m({exit_code:l?null:typeof h=="number"?h:null,stdout:Buffer.concat(a),stderr:Buffer.concat(c),duration_ms:Math.max(0,Math.round(r()-i)),timed_out:l})}),d=setTimeout(()=>{l=!0,wT(e.pid,"SIGTERM"),n>0?f=setTimeout(()=>{wT(e.pid,"SIGKILL")},n):wT(e.pid,"SIGKILL")},t)})}async function vM(e,t){if(e.trim().length===0)throw new Error("command must be non-empty");let{killGraceMs:n,now:r}=wM(t),s=t.shellPath??jre,o=yM(s,["-c",e],{cwd:t.cwd,env:t.env,detached:!0,stdio:["ignore","pipe","pipe"]});return TM(o,t.timeoutMs,n,r)}async function SM(e,t){if(e.length===0)throw new Error("argv must be non-empty");let{killGraceMs:n,now:r}=wM(t),s=yM(e[0],e.slice(1),{cwd:t.cwd,env:t.env,detached:!0,stdio:["ignore","pipe","pipe"]});return TM(s,t.timeoutMs,n,r)}function wT(e,t){if(e)try{process.kill(-e,t)}catch(n){if(!Hre(n))throw n}}function Hre(e){return!!e&&typeof e=="object"&&"code"in e&&e.code==="ESRCH"}var bM=1e3,Bre=6e4,Wre=20,Gre=1e3;async function IM(e,t){let n=t.runCommand??vM,r=t.runCommandArgv??SM,s=t.sleep??Vre,o=t.pollNow??Date.now,i=t.now??(()=>new Date),a=t.stderr??(d=>process.stderr.write(`${d}
2353
2353
  `)),c=t.shouldStop??(()=>!1),l=bM,u=!1;for(ur(a,i,"info","daemon_started",{mailbox:e.mailbox}),e.allowAnonymous&&ur(a,i,"warn","anonymous_execution_enabled",{mailbox:e.mailbox,warning:"REMOTE SHELL OPEN TO EVERY AUTHENTICATED LMMAIL USER"});!c();)try{let d=o(),f=await t.client.listMessages(e.mailbox,{status:"unread",after:0,...e.once?{}:{wait_s:Wre}}),m=Math.max(0,o()-d);for(let p of f.messages){if(c())break;let h=Xre(e,p.sender);if(h==="anonymous"&&!e.allowAnonymous){await t.client.getMessageMetadata(e.mailbox,p.seq),ur(a,i,"warn","message_rejected",{seq:p.seq,sender:p.sender,sender_trust:h,reason:"anonymous_not_allowed"});continue}let _=await t.client.getMessage(e.mailbox,p.seq),g=Buffer.from(await t.client.download(_.body.download_url)).toString("utf8"),w;try{w=sM(g)}catch(A){ur(a,i,"warn","message_rejected",{seq:p.seq,sender:p.sender,sender_trust:h,reason:"malformed_request",error:TT(A)});continue}let E=e.execAllowlist?pM(w.command):void 0,y=e.execAllowlist?E?EM(E,h):{allowed:!1,code:"malformed_command",message:"command could not be safely tokenized into arguments"}:{allowed:!0};if(!y.allowed){ur(a,i,"warn","command_rejected",{id:w.id,sender:p.sender,sender_trust:h,...w.from===void 0?{}:{asserted_from:w.from},code:y.code,seq:p.seq}),await AM(t.client,w.reply_to,{id:w.id,exit_code:126,stdout:"",stderr:JSON.stringify({error:{code:y.code,message:y.message}}),duration_ms:0,timed_out:!1,sender_trust:h,sender:p.sender});continue}ur(a,i,"info","command_started",{id:w.id,sender:p.sender,sender_trust:h,...w.from===void 0?{}:{asserted_from:w.from},seq:p.seq});let T;try{T=E?await r(E,{timeoutMs:Math.min(w.timeout_s,e.timeoutCapSeconds)*1e3}):await n(w.command,{timeoutMs:Math.min(w.timeout_s,e.timeoutCapSeconds)*1e3})}catch(A){ur(a,i,"error","command_failed",{id:w.id,sender:p.sender,sender_trust:h,...w.from===void 0?{}:{asserted_from:w.from},error:TT(A)});continue}let v=await AM(t.client,w.reply_to,{id:w.id,...T,sender_trust:h,sender:p.sender});ur(a,i,"info","command_finished",{id:w.id,sender:p.sender,sender_trust:h,...w.from===void 0?{}:{asserted_from:w.from},duration_ms:T.duration_ms,exit_code:T.exit_code,timed_out:T.timed_out,truncated:v.envelope.truncated})}if(l=bM,e.once||c())break;f.messages.length===0&&m<Gre&&(u||(ur(a,i,"warn","long_poll_unsupported",{elapsed_ms:m,fallback_interval_ms:e.pollIntervalMs}),u=!0),await s(e.pollIntervalMs))}catch(d){if(ur(a,i,"error","api_error",{error:TT(d),retry_ms:l}),c())break;await s(l),l=Math.min(l*2,Bre)}ur(a,i,"info","daemon_stopped",{mailbox:e.mailbox})}function Xre(e,t){return e.adminUsers.has(t)?"admin":e.allowUsers.has(t)?"registered":"anonymous"}async function AM(e,t,n){let r=aM(n);return await e.sendMessage({mailbox:t,subject:r.subject,body:{name:"body.txt",contentType:"text/plain; charset=utf-8",bytes:Buffer.from(JSON.stringify(r.envelope),"utf8")},attachments:r.attachments.map(s=>({name:s.name,contentType:s.content_type,bytes:s.data}))}),r}function ur(e,t,n,r,s){e(JSON.stringify({ts:t().toISOString(),level:n,event:r,...s}))}function Vre(e){return new Promise(t=>setTimeout(t,e))}function TT(e){return e instanceof Error?e.message:String(e)}var Jre=5e3,Yre=300;async function kM(e,t){await e.createMailbox(t,{tolerate409:!0})}function Dp(e){let t=!1,n=!1,r=Promise.resolve(),s=e.stderr??(c=>process.stderr.write(`${c}
2354
2354
  `)),o=e.runDaemonLoopImpl??IM,i={mailbox:e.mailbox,allowUsers:e.allowUsers,adminUsers:e.adminUsers,allowAnonymous:e.allowAnonymous,apiUrl:"",pollIntervalMs:e.pollIntervalMs??Jre,timeoutCapSeconds:e.timeoutCapSeconds??Yre,once:!1,execAllowlist:!0},a={client:e.client,shouldStop:()=>t,stderr:s};return{start(){n||t||(n=!0,r=o(i,a).catch(c=>{s(`[exec-worker] unexpected top-level failure, worker stopped: ${c instanceof Error?c.message:String(c)}`)}))},stop(){t=!0},isRunning:()=>n&&!t,whenIdle:()=>r}}var vT="remote_execute",xM="remote_execute.runtime",Kre="https://lmctl.ai/lmmail",LM=1e4;function wo(e){return(e.LMCTL_LMMAIL_API_URL?.trim()||e.LMMAIL_API_URL?.trim()||Kre).replace(/\/+$/,"")}function ST(e){return(e??"").split(",").map(t=>t.trim()).filter(t=>t.length>0)}function RM(e){return Array.isArray(e)&&e.every(t=>typeof t=="string")?e:null}function Ka(e){let t=e.prepare("SELECT v FROM kv WHERE k = ?").get(vT);if(!t)return null;try{let n=JSON.parse(t.v),r=RM(n.adminUsers),s=RM(n.allowUsers);return n.revision===void 0&&(n.revision=0),typeof n.revision!="number"||!Number.isInteger(n.revision)||n.revision<0||typeof n.enabled!="boolean"||r===null||s===null||typeof n.allowAnonymous!="boolean"||typeof n.apiUrl!="string"||typeof n.updatedAt!="string"?null:{revision:n.revision,enabled:n.enabled,adminUsers:r,allowUsers:s,allowAnonymous:n.allowAnonymous,apiUrl:n.apiUrl,updatedAt:n.updatedAt}}catch{return null}}function zre(e){return e.prepare("SELECT v FROM kv WHERE k = ?").get(vT)!==void 0&&Ka(e)===null}function CM(e,t){e.transaction(()=>{let n=Ka(e),r={...t,revision:(n?.revision??0)+1};e.prepare("INSERT INTO kv(k, v) VALUES (?, ?) ON CONFLICT(k) DO UPDATE SET v = excluded.v").run(vT,JSON.stringify(r))}).immediate()}function Qre(e){let t=e.prepare("SELECT v FROM kv WHERE k = ?").get(xM);if(!t)return null;try{let n=JSON.parse(t.v);return typeof n.pid!="number"||typeof n.running!="boolean"||typeof n.ts!="string"||typeof n.mailbox!="string"?null:{pid:n.pid,running:n.running,mailbox:n.mailbox,lastError:typeof n.lastError=="string"?n.lastError:null,ts:n.ts}}catch{return null}}function NM(e,t){e.prepare("INSERT INTO kv(k, v) VALUES (?, ?) ON CONFLICT(k) DO UPDATE SET v = excluded.v").run(xM,JSON.stringify(t))}var $p=(e,t)=>Ut({apiUrl:dn(e,"the lmmail endpoint"),appkey:t,fetch:ss()});async function OM(e){let t=e.env??process.env;dn(wo(t),"the lmmail endpoint");let n=await e.acquire(),r=[...new Set(e.policy?.adminUsers??[])],s=[...new Set(e.policy?.allowUsers??[])],o=e.policy?.allowAnonymous===!0;if(r.length===0&&s.length===0&&!o){let u=n.envelope?.user_id;if(typeof u!="string"||u.length===0)throw new Error("cannot tell which user id is yours from this appkey (it came from the environment, not a key file); name who may execute with --exec-allow <user_id[,user_id...]> (read-only commands) and/or --exec-admin");s=[u]}let i=wo(t),a=(e.createClient??$p)(i,n.appkey),c=Zn(e.siteId),l=er(e.siteId);return await a.createMailbox(c,{tolerate409:!0}),await a.createMailbox(l,{tolerate409:!0}),CM(e.db,{enabled:!0,adminUsers:r,allowUsers:s,allowAnonymous:o,apiUrl:i,updatedAt:(e.now?.()??new Date).toISOString()}),{siteId:e.siteId,contentMailbox:c,execMailbox:l,apiUrl:i,adminUsers:r,allowUsers:s,allowAnonymous:o}}async function DM(e){let t=e.env??process.env,n=Ka(e.db);CM(e.db,{enabled:!1,adminUsers:n?.adminUsers??[],allowUsers:n?.allowUsers??[],allowAnonymous:n?.allowAnonymous??!1,apiUrl:n?.apiUrl??wo(t),updatedAt:(e.now?.()??new Date).toISOString()});let r=await e.acquire(),s=(e.createClient??$p)(n?.apiUrl??wo(t),r.appkey),o=er(e.siteId);try{let i=await s.deleteMailbox(o);return{siteId:e.siteId,execMailbox:o,mailboxDeleted:!0,messagesDiscarded:i.messages_deleted}}catch(i){if(i instanceof In&&i.status===404)return{siteId:e.siteId,execMailbox:o,mailboxDeleted:!1,messagesDiscarded:0};throw i}}async function $M(e){let t=e.env??process.env,n=Ka(e.db),r=zre(e.db),s=n?.apiUrl??wo(t),o=er(e.siteId),i=null,a=null,c=e.resolveKey();if(c===null)a="no appkey on this machine, so the server was not asked (run `lmbee whoami` to sign in)";else try{i=(await(e.createClient??$p)(s,c.appkey).listMailboxes()).some(_=>_.mailbox_name===o)}catch(h){a=`could not ask the server: ${h instanceof Error?h.message:String(h)}`}let l=(e.readLock??lr)(e.dbPath),u=l.kind==="held"?{running:!0,pid:l.identity.pid}:{running:!1,pid:null},d=Qre(e.db),f=(e.now??Date.now)(),m=!1,p=null;return u.running?d===null?p=n?.enabled?"the daemon has not reported on remote execution yet":null:d.pid!==u.pid?p="the last report is from a previous daemon process":f-Date.parse(d.ts)>3*LM?p="the daemon has stopped reporting (stale heartbeat)":(m=d.running,p=d.lastError!==null?`daemon reports: ${d.lastError}`:null):p="no `lmbee serve` daemon is running, so nothing answers exec requests",{siteId:e.siteId,enabled:n?.enabled??(r?!1:null),settingUnreadable:r,policy:n?{adminUsers:n.adminUsers,allowUsers:n.allowUsers,allowAnonymous:n.allowAnonymous}:null,apiUrl:s,execMailbox:o,execMailboxExists:i,execMailboxNote:a,daemon:u,workerRunning:m,workerNote:p}}function bT(e){let t=[];if(t.push(`remote_execute: ${e.enabled===null?"never enabled":e.enabled?"enabled":"disabled"}${e.settingUnreadable?" (the stored setting is unreadable; treated as disabled)":""}`),t.push(`site: ${e.siteId}`),t.push(`exec mailbox: ${e.execMailbox} (${e.execMailboxExists===null?"unknown":e.execMailboxExists?"exists":"does not exist"}${e.execMailboxNote?`; ${e.execMailboxNote}`:""})`),t.push(`daemon: ${e.daemon.running?`running (pid ${e.daemon.pid})`:"not running"}`),t.push(`worker: ${e.workerRunning?"running":"not running"}${e.workerNote?` (${e.workerNote})`:""}`),e.policy){let n=[e.policy.adminUsers.length?`admin: ${e.policy.adminUsers.join(", ")}`:"",e.policy.allowUsers.length?`allow: ${e.policy.allowUsers.join(", ")}`:"",e.policy.allowAnonymous?"anonymous":""].filter(Boolean).join("; ");t.push(`who may run: ${n||"(nobody)"}`)}return t.push(`server: ${e.apiUrl}`),t.join(`
2355
2355
  `)}function MM(e){let t=e.stderr??(C=>process.stderr.write(`${C}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lmctl-ai/lmctl",
3
- "version": "0.2.432",
3
+ "version": "0.2.434",
4
4
  "description": "A provider-agnostic control plane for teams of AI coding agents — across providers, with independent review and durable memory.",
5
5
  "type": "module",
6
6
  "homepage": "https://lmctl.com",