@lmctl-ai/lmctl 0.2.433 → 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
@@ -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.433",
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",