@lmctl-ai/lmctl 0.2.235 → 0.2.237
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/build-info.json +1 -1
- package/dist/cli/lmscript.js +175 -175
- package/dist/lmbee.js +301 -301
- package/package.json +1 -1
package/dist/lmbee.js
CHANGED
|
@@ -1,70 +1,70 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var
|
|
2
|
+
var ZA=Object.create;var nc=Object.defineProperty;var e$=Object.getOwnPropertyDescriptor;var t$=Object.getOwnPropertyNames;var r$=Object.getPrototypeOf,n$=Object.prototype.hasOwnProperty;var Ht=(e,t)=>()=>(e&&(t=e(e=0)),t);var o$=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Io=(e,t)=>{for(var r in t)nc(e,r,{get:t[r],enumerable:!0})},s$=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of t$(t))!n$.call(e,o)&&o!==r&&nc(e,o,{get:()=>t[o],enumerable:!(n=e$(t,o))||n.enumerable});return e};var Bt=(e,t,r)=>(r=e!=null?ZA(r$(e)):{},s$(t||!e||!e.__esModule?nc(r,"default",{value:e,enumerable:!0}):r,e));var Ct=o$(pt=>{"use strict";function Sa(e){if(!Array.isArray(e))throw new TypeError("Each row and headers must be an array of cells");return Array.from(e,t=>{let r=t==null?"":String(t);if(/[\x00-\x1f\x7f-\x9f]/u.test(r))throw new TypeError("Cells must be single-line text without terminal control characters");return r})}function pO(e){if(e===void 0)return[];if(!Array.isArray(e))throw new TypeError('align must be an array of "left" or "right" per column');return e.map(t=>{if(t!=="left"&&t!=="right")throw new TypeError('align entries must be "left" or "right"');return t})}function Fr(e){let t=0;for(let r of e){let n=r.codePointAt(0);if(!(n>=768&&n<=879||n>=6832&&n<=6911||n>=7616&&n<=7679||n>=8400&&n<=8447||n>=65024&&n<=65039||n>=65056&&n<=65071||n===8203||n>=917760&&n<=917999)){if(n>=4352&&n<=4447||n>=11904&&n<=12350||n>=12353&&n<=13311||n>=13312&&n<=19903||n>=19968&&n<=40959||n>=40960&&n<=42191||n>=44032&&n<=55203||n>=63744&&n<=64255||n>=65072&&n<=65135||n>=65280&&n<=65376||n>=65504&&n<=65510||n>=9728&&n<=10175||n>=126976&&n<=129791||n>=131072&&n<=262141){t+=2;continue}t+=1}}return t}function zw(e,t,r){let n=" ".repeat(Math.max(0,t-Fr(e)));return r?n+e:e+n}function hO(e){if(Array.isArray(e))return{rows:e};if(e!==null&&typeof e=="object"&&Array.isArray(e.rows))return e;throw new TypeError("each grid must be a rows array or { rows, headers }")}function gO(e){if(e===void 0)return"\u2026";if(typeof e!="string"||/[\x00-\x1f\x7f-\x9f]/u.test(e))throw new TypeError("ellipsis must be a single-line string without terminal control characters");return e}function _O(e,t,r="\u2026"){if(Fr(e)<=t)return e;let n=Fr(r)>t?"\u2026":r,o=Fr(n);if(t<=o)return n;let s="",i=0;for(let a of e){let c=Fr(a);if(i+c>t-o)break;s+=a,i+=c}return`${s}${n}`}function wO(e){if(e===void 0)return[];if(!Array.isArray(e))throw new TypeError("max must be an array of per-column width caps");return e.map(t=>{if(t!=null){if(typeof t!="number"||!Number.isInteger(t)||t<1)throw new TypeError("max entries must be positive integers, null, or undefined");return t}})}function Yw(e,{max:t}={}){if(!Array.isArray(e))throw new TypeError("grids must be an array of grids");let r=wO(t),n=[],o=(s,i)=>{n[s]=Math.max(n[s]??0,i)};for(let s of e){let i=hO(s);i.headers!==void 0&&Sa(i.headers).forEach((a,c)=>{o(c,Fr(a))});for(let a of i.rows.map(Sa))a.forEach((c,l)=>{o(l,Fr(c))})}return n.map((s,i)=>{let a=r[i];return a===void 0?s:Math.min(s,a)})}pt.measureColumns=Yw;function yO(e){if(e===void 0)return"";if(typeof e=="number"&&Number.isInteger(e)&&e>=0)return" ".repeat(e);if(typeof e=="string"&&!/[\x00-\x1f\x7f-\x9f]/u.test(e))return e;throw new TypeError("margin must be a number of spaces or a single-line string")}function Qw(e,{widths:t,headers:r,align:n,truncate:o=!0,truncateTrailing:s=!1,margin:i,max:a,ellipsis:c}={}){if(!Array.isArray(e))throw new TypeError("rows must be an array of row arrays");if(t!==void 0&&!Array.isArray(t))throw new TypeError("widths must be an array of column widths");if(t!==void 0&&a!==void 0)throw new TypeError("pass widths or max, not both (max caps a measurement)");let l=yO(i),u=pO(n),d=gO(c),m=t??Yw([{rows:e,headers:r}],{max:a}),f=e.map(Sa);r!==void 0&&f.unshift(Sa(r));let p=f.map(h=>{let g=h.length-1;for(;g>=0&&h[g]==="";)g--;return h.slice(0,g+1).map((_,E)=>{let y=m[E]||0,S=o&&y>0&&(E!==g||s)?_O(_,y,d):_;return u[E]==="right"?zw(S,y,!0):E===g?S:zw(S,y,!1)}).join(" ")}).join(`
|
|
3
3
|
`);return p===""||l===""?p:`${l}${p.split(`
|
|
4
4
|
`).join(`
|
|
5
|
-
${l}`)}`}pt.renderGrid=
|
|
6
|
-
`)}pt.formatTable=
|
|
7
|
-
`?"\\n":r===" "?"\\t":r==="\r"?"\\r":`\\x${r.codePointAt(0).toString(16).padStart(2,"0")}`)}pt.escapeCell=
|
|
8
|
-
`);let a=null;if(t.refresh_token){a=Da(o,"identity.json");let c={user_pool_id:n.COGNITO_USER_POOL_ID?.trim()||"us-east-1_UalgyPyId",client_id:r.clientId,refresh_token:t.refresh_token};await
|
|
9
|
-
`)}return{appkeyPath:s,identityPath:a}}async function
|
|
5
|
+
${l}`)}`}pt.renderGrid=Qw;function Xw(e,{headers:t,align:r,truncate:n,truncateTrailing:o,margin:s,max:i,ellipsis:a}={}){return Qw(e,{headers:t,align:r,truncate:n,truncateTrailing:o,margin:s,max:i,ellipsis:a})}function EO(e,{headers:t,align:r,truncate:n,truncateTrailing:o,margin:s,max:i,ellipsis:a,stream:c=process.stdout}={}){let l=Xw(e,{headers:t,align:r,truncate:n,truncateTrailing:o,margin:s,max:i,ellipsis:a});l&&c.write(`${l}
|
|
6
|
+
`)}pt.formatTable=Xw;pt.printTable=EO;function Kw(e){return e instanceof Date?e.getTime():typeof e=="number"?e:typeof e=="string"&&e.trim()?Date.parse(e):NaN}function bO(e,{now:t=Date.now()}={}){let r=Kw(t);if(!Number.isFinite(r))throw new TypeError("now must be a valid timestamp");let n=Kw(e);if(!Number.isFinite(n))return"unknown";let o=n-r,s=Math.floor(Math.abs(o)/1e3);if(s===0)return"now";for(let[i,a]of[["w",604800],["d",86400],["h",3600],["m",60],["s",1]])if(s>=a)return`${Math.floor(s/a)}${i}${o<0?" ago":""}`}pt.formatRelativeTime=bO;function TO(e){if(typeof e!="number"||!Number.isFinite(e))return"unknown";let t=e<0?"-":"",r=Math.abs(e);if(r<1e3)return String(e);let n=Math.round(r/1e3);return n<1e3?`${t}${n}K`:`${t}${(r/1e6).toFixed(1)}M`}pt.formatCount=TO;var Nu=[["w",604800],["d",86400],["h",3600],["m",60],["s",1]];function SO(e,{maxUnit:t="w",style:r="spaced"}={}){if(typeof e!="number"||!Number.isFinite(e))return"unknown";let n=Nu.findIndex(([a])=>a===t);if(n===-1)throw new TypeError('maxUnit must be one of "w", "d", "h", "m", "s"');if(r!=="spaced"&&r!=="compact")throw new TypeError('style must be "spaced" or "compact"');let o=Math.floor(Math.max(0,e)/1e3);if(r==="compact"){let a=Nu.slice(n).filter(([d])=>d!=="s");if(a.length===0||o<60)return"<1m";let c=[],l=o,u=!1;for(let[d,m]of a){let f=Math.floor(l/m);if(l-=f*m,f>0&&!u){let p=d==="d"||d==="w"?`${f}${d}`:`${Zt(f)}${d}`;c.push({text:p,zero:!1}),u=!0}else u&&c.push({text:`${Zt(f)}${d}`,zero:f===0})}for(;c.length>0&&c[c.length-1].zero;)c.pop();return c.map(d=>d.text).join("")}let s=o,i=[];for(let[a,c]of Nu.slice(n))if(s>=c||a==="s"&&i.length===0){let l=Math.floor(s/c);if(s-=l*c,i.push(`${l}${a}`),i.length===2)break}return i.join(" ")}pt.formatDuration=SO;function Zw(e){return e===void 0?new Date:e instanceof Date?e:typeof e=="number"||typeof e=="string"?new Date(e):new Date(NaN)}function Zt(e){return String(e).padStart(2,"0")}function ey(e){let t=Zw(e);return Number.isNaN(t.getTime())?"unknown":`${Zt(t.getHours())}:${Zt(t.getMinutes())}:${Zt(t.getSeconds())}`}pt.formatClock=ey;function vO(e){let t=Zw(e);return Number.isNaN(t.getTime())?"unknown":`${`${t.getFullYear()}-${Zt(t.getMonth()+1)}-${Zt(t.getDate())}`} ${ey(t)}`}pt.formatLocalTimestamp=vO;function AO(e){return typeof e=="number"&&Number.isFinite(e)?`${Math.round(e*100)}%`:"?%"}pt.formatPercent=AO;function $O(e,{width:t=10,fill:r="#",empty:n=" ",unknown:o="?"}={}){if(typeof t!="number"||!Number.isInteger(t)||t<1)throw new TypeError("width must be a positive integer");for(let[i,a]of[["fill",r],["empty",n],["unknown",o]])if(typeof a!="string"||[...a].length!==1||/[\x00-\x1f\x7f-\x9f]/u.test(a)||Fr(a)!==1)throw new TypeError(`${i} must be a single character with terminal display width 1`);if(typeof e!="number"||!Number.isFinite(e))return o.repeat(t);let s=Math.min(t,Math.max(0,Math.round(e*t)));return`${r.repeat(s)}${n.repeat(t-s)}`}pt.formatBar=$O;function kO(e){if(typeof e!="number"||!Number.isFinite(e))return"unknown";let t=Math.floor(Math.max(0,e)/1e3),r=Math.floor(t/86400);t-=r*86400;let n=Math.floor(t/3600);t-=n*3600;let o=Math.floor(t/60);t-=o*60;let s=`${Zt(n)}:${Zt(o)}:${Zt(t)}`;return r>0?`${r}d ${s}`:s}pt.formatTimer=kO;function xO(e){return(e==null?"":String(e)).replace(/[\x00-\x1f\x7f-\x9f]/gu,r=>r===`
|
|
7
|
+
`?"\\n":r===" "?"\\t":r==="\r"?"\\r":`\\x${r.codePointAt(0).toString(16).padStart(2,"0")}`)}pt.escapeCell=xO});import{createHash as ZP,randomBytes as NT}from"node:crypto";function IT(e=process.env){return{domain:e.LMCTL_AUTH_DOMAIN?.trim()||Ss.domain,clientId:e.LMCTL_CLI_CLIENT_ID?.trim()||Ss.clientId,scope:e.LMCTL_AUTH_SCOPE?.trim()||Ss.scope,ports:Ss.ports,authUrl:(e.LMCTL_AUTH_URL?.trim()||Ss.authUrl).replace(/\/+$/,"")}}function LT(e=NT){let t=e(32).toString("base64url"),r=ZP("sha256").update(t).digest("base64url");return{verifier:t,challenge:r}}function CT(e=NT){return e(16).toString("base64url")}function OT(e){return`http://127.0.0.1:${e}/callback`}function DT(e,t){let r=new URLSearchParams({response_type:"code",client_id:e.clientId,redirect_uri:OT(t.port),scope:e.scope,state:t.state,code_challenge:t.challenge,code_challenge_method:"S256"});return`https://${e.domain}/oauth2/authorize?${r.toString()}`}function MT(e){let t=new URL(e,"http://127.0.0.1");return{code:t.searchParams.get("code")??void 0,state:t.searchParams.get("state")??void 0,error:t.searchParams.get("error")??void 0}}async function PT(e,t,r=fetch){let n=new URLSearchParams({grant_type:"authorization_code",client_id:e.clientId,code:t.code,redirect_uri:OT(t.port),code_verifier:t.verifier}),o=await r(`https://${e.domain}/oauth2/token`,{method:"POST",headers:{"content-type":"application/x-www-form-urlencoded"},body:n.toString()});if(!o.ok)throw new Error(`token exchange failed: HTTP ${o.status} ${await FT(o)}`);let s=await o.json();if(!s.id_token)throw new Error("token exchange returned no id_token");return s}async function UT(e,t,r=fetch){let n=await r(`${e.authUrl}/appkeys`,{method:"POST",headers:{authorization:`Bearer ${t.idToken}`,"content-type":"application/json"},body:JSON.stringify({label:t.label})});if(!n.ok)throw new Error(`appkey mint failed: HTTP ${n.status} ${await FT(n)}`);return await n.json()}async function FT(e){try{return(await e.text()).slice(0,300)}catch{return""}}var Ss,qT=Ht(()=>{Ss={domain:"auth.lmctl.ai",clientId:"lpla33du6p451g9ohb0su9c5u",scope:"openid email profile",ports:[8976,8977,8978,8979],authUrl:"https://lmctl.ai/auth"}});var WT={};Io(WT,{appkeyDir:()=>HT,persistCredentials:()=>BT,runLogin:()=>uU});import{createServer as eU}from"node:http";import{spawn as tU}from"node:child_process";import{hostname as rU}from"node:os";import{mkdir as nU,rename as oU,writeFile as sU}from"node:fs/promises";import{homedir as iU}from"node:os";import{join as Da}from"node:path";function HT(e=process.env){let t=e.XDG_CONFIG_HOME?.trim()||Da(iU(),".config");return Da(t,"lmctl")}async function BT(e,t,r,n=process.env){let o=HT(n);await nU(o,{recursive:!0,mode:448});let s=Da(o,"appkey.json"),i={version:1,appkey:e.appkey,user_id:e.user_id,label:e.label,issued_at:e.created_at};await jT(s,JSON.stringify(i,null,2)+`
|
|
8
|
+
`);let a=null;if(t.refresh_token){a=Da(o,"identity.json");let c={user_pool_id:n.COGNITO_USER_POOL_ID?.trim()||"us-east-1_UalgyPyId",client_id:r.clientId,refresh_token:t.refresh_token};await jT(a,JSON.stringify(c,null,2)+`
|
|
9
|
+
`)}return{appkeyPath:s,identityPath:a}}async function jT(e,t){let r=`${e}.tmp-${process.pid}`;await sU(r,t,{mode:384}),await oU(r,e)}async function aU(e){let t,r=new Promise(o=>t=o),n=eU((o,s)=>{if(!o.url?.startsWith("/callback")){s.writeHead(404).end();return}let i=MT(o.url);s.writeHead(200,{"content-type":"text/html"}).end("<html><body style='font-family:sans-serif'><h3>lmctl login complete.</h3><p>You can close this tab and return to the terminal.</p></body></html>"),t(i)});for(let o of e)if(await cU(n,o))return{server:n,port:o,wait:r};throw new Error(`could not bind any loopback port (${e.join(", ")}); is another login running?`)}function cU(e,t){return new Promise(r=>{let n=()=>{e.removeListener("error",n),r(!1)};e.once("error",n),e.listen(t,"127.0.0.1",()=>{e.removeListener("error",n),r(!0)})})}function lU(e,t){let r=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",n=process.platform==="win32"?["/c","start","",e]:[e];try{let o=tU(r,n,{stdio:"ignore",detached:!0});o.on("error",()=>{}),o.unref()}catch{}t.stdout.write(`
|
|
10
10
|
If your browser didn't open, visit:
|
|
11
11
|
${e}
|
|
12
12
|
|
|
13
|
-
`)}async function
|
|
14
|
-
`),s(m,t);let f=await d;if(f.error)throw new Error(`authorization failed: ${f.error}`);if(!f.code)throw new Error("no authorization code returned");if(f.state!==c)throw new Error("state mismatch (possible CSRF); aborting");let p=await
|
|
13
|
+
`)}async function uU(e={}){let t=e.io??{stdout:process.stdout,stderr:process.stderr},r=e.env??process.env,n=IT(r),o=e.fetchImpl??fetch,s=e.openBrowserFn??lU;if((!("stdin"in process)||!process.stdin.isTTY)&&(r.LMCTL_NONINTERACTIVE||r.CI))return t.stderr.write("error: `lmchat login` needs an interactive browser. On a headless box, run login on a machine with a browser and copy ~/.config/lmctl/appkey.json here (or set LMCTL_APPKEY).\n"),1;let{verifier:i,challenge:a}=LT(),c=CT(),{server:l,port:u,wait:d}=await aU(n.ports);try{let m=DT(n,{port:u,state:c,challenge:a});t.stdout.write(`Opening your browser to sign in with lmctl.ai\u2026
|
|
14
|
+
`),s(m,t);let f=await d;if(f.error)throw new Error(`authorization failed: ${f.error}`);if(!f.code)throw new Error("no authorization code returned");if(f.state!==c)throw new Error("state mismatch (possible CSRF); aborting");let p=await PT(n,{code:f.code,verifier:i,port:u},o),h=await UT(n,{idToken:p.id_token,label:rU()},o),{appkeyPath:g,identityPath:_}=await BT(h,p,n,r);return t.stdout.write(`
|
|
15
15
|
\u2713 Signed in as ${h.user_id}
|
|
16
16
|
\u2713 Appkey saved to ${g} (0600)
|
|
17
17
|
`+(_?`\u2713 Refresh token saved to ${_} (0600, for silent re-mint)
|
|
18
18
|
`:"")+`
|
|
19
19
|
All lmctl tools now use this key automatically.
|
|
20
20
|
`),0}catch(m){return t.stderr.write(`error: ${m instanceof Error?m.message:String(m)}
|
|
21
|
-
`),1}finally{l.close()}}var
|
|
22
|
-
`);let i=null;return t.refresh_token&&(i=Ua(o,"identity.json"),await
|
|
23
|
-
`)),{appkeyPath:s,identityPath:i}}async function
|
|
21
|
+
`),1}finally{l.close()}}var GT=Ht(()=>{qT()});import{createHash as IU,randomBytes as eS}from"node:crypto";function tS(e=process.env){return{domain:e.LMCTL_AUTH_DOMAIN?.trim()||vs.domain,clientId:e.LMCTL_CLI_CLIENT_ID?.trim()||vs.clientId,scope:e.LMCTL_AUTH_SCOPE?.trim()||vs.scope,ports:vs.ports,authUrl:(e.LMCTL_AUTH_URL?.trim()||vs.authUrl).replace(/\/+$/,"")}}function rS(e=eS){let t=e(32).toString("base64url");return{verifier:t,challenge:IU("sha256").update(t).digest("base64url")}}function nS(e=eS){return e(16).toString("base64url")}function oS(e){return`http://127.0.0.1:${e}/callback`}function sS(e,t){let r=new URLSearchParams({response_type:"code",client_id:e.clientId,redirect_uri:oS(t.port),scope:e.scope,state:t.state,code_challenge:t.challenge,code_challenge_method:"S256"});return`https://${e.domain}/oauth2/authorize?${r}`}function iS(e){let t=new URL(e,"http://127.0.0.1");return{code:t.searchParams.get("code")??void 0,state:t.searchParams.get("state")??void 0,error:t.searchParams.get("error")??void 0}}async function aS(e,t,r=fetch){let n=new URLSearchParams({grant_type:"authorization_code",client_id:e.clientId,code:t.code,redirect_uri:oS(t.port),code_verifier:t.verifier}),o=await r(`https://${e.domain}/oauth2/token`,{method:"POST",headers:{"content-type":"application/x-www-form-urlencoded"},body:n.toString()});if(!o.ok)throw new Error(`token exchange failed: HTTP ${o.status} ${await lS(o)}`);let s=await o.json();if(!s.id_token)throw new Error("token exchange returned no id_token");return s}async function cS(e,t,r=fetch){let n=await r(`${e.authUrl}/appkeys`,{method:"POST",headers:{authorization:`Bearer ${t.idToken}`,"content-type":"application/json"},body:JSON.stringify({label:t.label})});if(!n.ok)throw new Error(`appkey mint failed: HTTP ${n.status} ${await lS(n)}`);return n.json()}async function lS(e){try{return(await e.text()).slice(0,300)}catch{return""}}var vs,uS=Ht(()=>{vs={domain:"auth.lmctl.ai",clientId:"lpla33du6p451g9ohb0su9c5u",scope:"openid email profile",ports:[8976,8977,8978,8979],authUrl:"https://lmctl.ai/auth"}});var pS={};Io(pS,{appkeyDir:()=>mS,persistCredentials:()=>fS,runLogin:()=>HU});import{spawn as LU}from"node:child_process";import{mkdir as CU,rename as OU,writeFile as DU}from"node:fs/promises";import{createServer as MU}from"node:http";import{homedir as PU,hostname as UU}from"node:os";import{join as Ua}from"node:path";function mS(e=process.env){return Ua(e.XDG_CONFIG_HOME?.trim()||Ua(PU(),".config"),"lmctl")}async function fS(e,t,r,n=process.env){let o=mS(n);await CU(o,{recursive:!0,mode:448});let s=Ua(o,"appkey.json");await dS(s,JSON.stringify({version:1,appkey:e.appkey,user_id:e.user_id,label:e.label,issued_at:e.created_at},null,2)+`
|
|
22
|
+
`);let i=null;return t.refresh_token&&(i=Ua(o,"identity.json"),await dS(i,JSON.stringify({user_pool_id:n.COGNITO_USER_POOL_ID?.trim()||"us-east-1_UalgyPyId",client_id:r.clientId,refresh_token:t.refresh_token},null,2)+`
|
|
23
|
+
`)),{appkeyPath:s,identityPath:i}}async function dS(e,t){let r=`${e}.tmp-${process.pid}`;await DU(r,t,{mode:384}),await OU(r,e)}async function FU(e){let t,r=new Promise(o=>{t=o}),n=MU((o,s)=>{if(!o.url?.startsWith("/callback")){s.writeHead(404).end();return}let i=iS(o.url);s.writeHead(200,{"content-type":"text/html"}).end("<html><body><h3>lmctl login complete.</h3><p>You can close this tab.</p></body></html>"),t(i)});for(let o of e)if(await qU(n,o))return{server:n,port:o,wait:r};throw new Error(`could not bind any loopback port (${e.join(", ")})`)}function qU(e,t){return new Promise(r=>{let n=()=>{e.removeListener("error",n),r(!1)};e.once("error",n),e.listen(t,"127.0.0.1",()=>{e.removeListener("error",n),r(!0)})})}function jU(e,t){let r=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",n=process.platform==="win32"?["/c","start","",e]:[e];try{let o=LU(r,n,{stdio:"ignore",detached:!0});o.on("error",()=>{}),o.unref()}catch{}t.stdout.write(`
|
|
24
24
|
If your browser didn't open, visit:
|
|
25
25
|
${e}
|
|
26
26
|
|
|
27
|
-
`)}async function
|
|
28
|
-
`),(e.openBrowserFn??
|
|
27
|
+
`)}async function HU(e={}){let t=e.io??{stdout:process.stdout,stderr:process.stderr},r=e.env??process.env;if(!process.stdin.isTTY&&(r.LMCTL_NONINTERACTIVE||r.CI))return t.stderr.write("error: `lmmail login` needs an interactive browser. Run it on a machine with a browser and copy ~/.config/lmctl/appkey.json here.\n"),1;let n=tS(r),{verifier:o,challenge:s}=rS(),i=nS(),{server:a,port:c,wait:l}=await FU(n.ports);try{let u=sS(n,{port:c,state:i,challenge:s});t.stdout.write(`Opening your browser to sign in with lmctl.ai\u2026
|
|
28
|
+
`),(e.openBrowserFn??jU)(u,t);let d=await l;if(d.error)throw new Error(`authorization failed: ${d.error}`);if(!d.code)throw new Error("no authorization code returned");if(d.state!==i)throw new Error("state mismatch (possible CSRF); aborting");let m=await aS(n,{code:d.code,verifier:o,port:c},e.fetchImpl??fetch),f=await cS(n,{idToken:m.id_token,label:UU()},e.fetchImpl??fetch),p=await fS(f,m,n,r);return t.stdout.write(`
|
|
29
29
|
Signed in as ${f.user_id}
|
|
30
30
|
Appkey saved to ${p.appkeyPath} (0600)
|
|
31
31
|
`),0}catch(u){return t.stderr.write(`error: ${u instanceof Error?u.message:String(u)}
|
|
32
|
-
`),1}finally{a.close()}}var
|
|
33
|
-
`);let i=null;return t.refresh_token&&(i=qa(o,"identity.json"),await
|
|
34
|
-
`)),{appkeyPath:s,identityPath:i}}async function
|
|
32
|
+
`),1}finally{a.close()}}var hS=Ht(()=>{uS()});import{createHash as sF,randomBytes as ES}from"node:crypto";function bS(e=process.env){return{domain:e.LMCTL_AUTH_DOMAIN?.trim()||As.domain,clientId:e.LMCTL_CLI_CLIENT_ID?.trim()||As.clientId,scope:e.LMCTL_AUTH_SCOPE?.trim()||As.scope,ports:As.ports,authUrl:(e.LMCTL_AUTH_URL?.trim()||As.authUrl).replace(/\/+$/,"")}}function TS(e=ES){let t=e(32).toString("base64url");return{verifier:t,challenge:sF("sha256").update(t).digest("base64url")}}function SS(e=ES){return e(16).toString("base64url")}function vS(e){return`http://127.0.0.1:${e}/callback`}function AS(e,t){let r=new URLSearchParams({response_type:"code",client_id:e.clientId,redirect_uri:vS(t.port),scope:e.scope,state:t.state,code_challenge:t.challenge,code_challenge_method:"S256"});return`https://${e.domain}/oauth2/authorize?${r}`}function $S(e){let t=new URL(e,"http://127.0.0.1");return{code:t.searchParams.get("code")??void 0,state:t.searchParams.get("state")??void 0,error:t.searchParams.get("error")??void 0}}async function kS(e,t,r=fetch){let n=new URLSearchParams({grant_type:"authorization_code",client_id:e.clientId,code:t.code,redirect_uri:vS(t.port),code_verifier:t.verifier}),o=await r(`https://${e.domain}/oauth2/token`,{method:"POST",headers:{"content-type":"application/x-www-form-urlencoded"},body:n.toString()});if(!o.ok)throw new Error(`token exchange failed: HTTP ${o.status} ${await RS(o)}`);let s=await o.json();if(!s.id_token)throw new Error("token exchange returned no id_token");return s}async function xS(e,t,r=fetch){let n=await r(`${e.authUrl}/appkeys`,{method:"POST",headers:{authorization:`Bearer ${t.idToken}`,"content-type":"application/json"},body:JSON.stringify({label:t.label})});if(!n.ok)throw new Error(`appkey mint failed: HTTP ${n.status} ${await RS(n)}`);return n.json()}async function RS(e){try{return(await e.text()).slice(0,300)}catch{return""}}var As,NS=Ht(()=>{As={domain:"auth.lmctl.ai",clientId:"lpla33du6p451g9ohb0su9c5u",scope:"openid email profile",ports:[8976,8977,8978,8979],authUrl:"https://lmctl.ai/auth"}});var OS={};Io(OS,{appkeyDir:()=>LS,persistCredentials:()=>CS,runLogin:()=>gF});import{spawn as iF}from"node:child_process";import{mkdir as aF,rename as cF,writeFile as lF}from"node:fs/promises";import{createServer as uF}from"node:http";import{homedir as dF,hostname as mF}from"node:os";import{join as qa}from"node:path";function LS(e=process.env){return qa(e.XDG_CONFIG_HOME?.trim()||qa(dF(),".config"),"lmctl")}async function CS(e,t,r,n=process.env){let o=LS(n);await aF(o,{recursive:!0,mode:448});let s=qa(o,"appkey.json");await IS(s,JSON.stringify({version:1,appkey:e.appkey,user_id:e.user_id,label:e.label,issued_at:e.created_at},null,2)+`
|
|
33
|
+
`);let i=null;return t.refresh_token&&(i=qa(o,"identity.json"),await IS(i,JSON.stringify({user_pool_id:n.COGNITO_USER_POOL_ID?.trim()||"us-east-1_UalgyPyId",client_id:r.clientId,refresh_token:t.refresh_token},null,2)+`
|
|
34
|
+
`)),{appkeyPath:s,identityPath:i}}async function IS(e,t){let r=`${e}.tmp-${process.pid}`;await lF(r,t,{mode:384}),await cF(r,e)}async function fF(e){let t,r=new Promise(o=>{t=o}),n=uF((o,s)=>{if(!o.url?.startsWith("/callback")){s.writeHead(404).end();return}let i=$S(o.url);s.writeHead(200,{"content-type":"text/html"}).end("<html><body><h3>lmctl login complete.</h3><p>You can close this tab.</p></body></html>"),t(i)});for(let o of e)if(await pF(n,o))return{server:n,port:o,wait:r};throw new Error(`could not bind any loopback port (${e.join(", ")})`)}function pF(e,t){return new Promise(r=>{let n=()=>{e.removeListener("error",n),r(!1)};e.once("error",n),e.listen(t,"127.0.0.1",()=>{e.removeListener("error",n),r(!0)})})}function hF(e,t){let r=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",n=process.platform==="win32"?["/c","start","",e]:[e];try{let o=iF(r,n,{stdio:"ignore",detached:!0});o.on("error",()=>{}),o.unref()}catch{}t.stdout.write(`
|
|
35
35
|
If your browser didn't open, visit:
|
|
36
36
|
${e}
|
|
37
37
|
|
|
38
|
-
`)}async function
|
|
39
|
-
`),(e.openBrowserFn??
|
|
38
|
+
`)}async function gF(e={}){let t=e.io??{stdout:process.stdout,stderr:process.stderr},r=e.env??process.env;if(!process.stdin.isTTY&&(r.LMCTL_NONINTERACTIVE||r.CI))return t.stderr.write("error: `lmnote login` needs an interactive browser. Run it on a machine with a browser and copy ~/.config/lmctl/appkey.json here.\n"),1;let n=bS(r),{verifier:o,challenge:s}=TS(),i=SS(),{server:a,port:c,wait:l}=await fF(n.ports);try{let u=AS(n,{port:c,state:i,challenge:s});t.stdout.write(`Opening your browser to sign in with lmctl.ai\u2026
|
|
39
|
+
`),(e.openBrowserFn??hF)(u,t);let d=await l;if(d.error)throw new Error(`authorization failed: ${d.error}`);if(!d.code)throw new Error("no authorization code returned");if(d.state!==i)throw new Error("state mismatch (possible CSRF); aborting");let m=await kS(n,{code:d.code,verifier:o,port:c},e.fetchImpl??fetch),f=await xS(n,{idToken:m.id_token,label:mF()},e.fetchImpl??fetch),p=await CS(f,m,n,r);return t.stdout.write(`
|
|
40
40
|
Signed in as ${f.user_id}
|
|
41
41
|
Appkey saved to ${p.appkeyPath} (0600)
|
|
42
42
|
`),0}catch(u){return t.stderr.write(`error: ${u instanceof Error?u.message:String(u)}
|
|
43
|
-
`),1}finally{a.close()}}var
|
|
44
|
-
`);let i=null;return t.refresh_token&&(i=ja(o,"identity.json"),await
|
|
45
|
-
`)),{appkeyPath:s,identityPath:i}}async function
|
|
43
|
+
`),1}finally{a.close()}}var DS=Ht(()=>{NS()});import{createHash as LF,randomBytes as US}from"node:crypto";function FS(e=process.env){return{domain:e.LMCTL_AUTH_DOMAIN?.trim()||Rs.domain,clientId:e.LMCTL_CLI_CLIENT_ID?.trim()||Rs.clientId,scope:e.LMCTL_AUTH_SCOPE?.trim()||Rs.scope,ports:Rs.ports,authUrl:(e.LMCTL_AUTH_URL?.trim()||Rs.authUrl).replace(/\/+$/,"")}}function qS(e=US){let t=e(32).toString("base64url");return{verifier:t,challenge:LF("sha256").update(t).digest("base64url")}}function jS(e=US){return e(16).toString("base64url")}function HS(e){return`http://127.0.0.1:${e}/callback`}function BS(e,t){let r=new URLSearchParams({response_type:"code",client_id:e.clientId,redirect_uri:HS(t.port),scope:e.scope,state:t.state,code_challenge:t.challenge,code_challenge_method:"S256"});return`https://${e.domain}/oauth2/authorize?${r}`}function WS(e){let t=new URL(e,"http://127.0.0.1");return{code:t.searchParams.get("code")??void 0,state:t.searchParams.get("state")??void 0,error:t.searchParams.get("error")??void 0}}async function GS(e,t,r=fetch){let n=new URLSearchParams({grant_type:"authorization_code",client_id:e.clientId,code:t.code,redirect_uri:HS(t.port),code_verifier:t.verifier}),o=await r(`https://${e.domain}/oauth2/token`,{method:"POST",headers:{"content-type":"application/x-www-form-urlencoded"},body:n.toString()});if(!o.ok)throw new Error(`token exchange failed: HTTP ${o.status} ${await JS(o)}`);let s=await o.json();if(!s.id_token)throw new Error("token exchange returned no id_token");return s}async function VS(e,t,r=fetch){let n=await r(`${e.authUrl}/appkeys`,{method:"POST",headers:{authorization:`Bearer ${t.idToken}`,"content-type":"application/json"},body:JSON.stringify({label:t.label})});if(!n.ok)throw new Error(`appkey mint failed: HTTP ${n.status} ${await JS(n)}`);return n.json()}async function JS(e){try{return(await e.text()).slice(0,300)}catch{return""}}var Rs,zS=Ht(()=>{Rs={domain:"auth.lmctl.ai",clientId:"lpla33du6p451g9ohb0su9c5u",scope:"openid email profile",ports:[8976,8977,8978,8979],authUrl:"https://lmctl.ai/auth"}});var XS={};Io(XS,{appkeyDir:()=>YS,persistCredentials:()=>QS,runLogin:()=>BF});import{spawn as CF}from"node:child_process";import{mkdir as OF,rename as DF,writeFile as MF}from"node:fs/promises";import{createServer as PF}from"node:http";import{homedir as UF,hostname as FF}from"node:os";import{join as ja}from"node:path";function YS(e=process.env){return ja(e.XDG_CONFIG_HOME?.trim()||ja(UF(),".config"),"lmctl")}async function QS(e,t,r,n=process.env){let o=YS(n);await OF(o,{recursive:!0,mode:448});let s=ja(o,"appkey.json");await KS(s,JSON.stringify({version:1,appkey:e.appkey,user_id:e.user_id,label:e.label,issued_at:e.created_at},null,2)+`
|
|
44
|
+
`);let i=null;return t.refresh_token&&(i=ja(o,"identity.json"),await KS(i,JSON.stringify({user_pool_id:n.COGNITO_USER_POOL_ID?.trim()||"us-east-1_UalgyPyId",client_id:r.clientId,refresh_token:t.refresh_token},null,2)+`
|
|
45
|
+
`)),{appkeyPath:s,identityPath:i}}async function KS(e,t){let r=`${e}.tmp-${process.pid}`;await MF(r,t,{mode:384}),await DF(r,e)}async function qF(e){let t,r=new Promise(o=>{t=o}),n=PF((o,s)=>{if(!o.url?.startsWith("/callback")){s.writeHead(404).end();return}let i=WS(o.url);s.writeHead(200,{"content-type":"text/html"}).end("<html><body><h3>lmctl login complete.</h3><p>You can close this tab.</p></body></html>"),t(i)});for(let o of e)if(await jF(n,o))return{server:n,port:o,wait:r};throw new Error(`could not bind any loopback port (${e.join(", ")})`)}function jF(e,t){return new Promise(r=>{let n=()=>{e.removeListener("error",n),r(!1)};e.once("error",n),e.listen(t,"127.0.0.1",()=>{e.removeListener("error",n),r(!0)})})}function HF(e,t){let r=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",n=process.platform==="win32"?["/c","start","",e]:[e];try{let o=CF(r,n,{stdio:"ignore",detached:!0});o.on("error",()=>{}),o.unref()}catch{}t.stdout.write(`
|
|
46
46
|
If your browser didn't open, visit:
|
|
47
47
|
${e}
|
|
48
48
|
|
|
49
|
-
`)}async function
|
|
50
|
-
`),(e.openBrowserFn??
|
|
49
|
+
`)}async function BF(e={}){let t=e.io??{stdout:process.stdout,stderr:process.stderr},r=e.env??process.env;if(!process.stdin.isTTY&&(r.LMCTL_NONINTERACTIVE||r.CI))return t.stderr.write("error: `lmsheet login` needs an interactive browser. Run it on a machine with a browser and copy ~/.config/lmctl/appkey.json here.\n"),1;let n=FS(r),{verifier:o,challenge:s}=qS(),i=jS(),{server:a,port:c,wait:l}=await qF(n.ports);try{let u=BS(n,{port:c,state:i,challenge:s});t.stdout.write(`Opening your browser to sign in with lmctl.ai\u2026
|
|
50
|
+
`),(e.openBrowserFn??HF)(u,t);let d=await l;if(d.error)throw new Error(`authorization failed: ${d.error}`);if(!d.code)throw new Error("no authorization code returned");if(d.state!==i)throw new Error("state mismatch (possible CSRF); aborting");let m=await GS(n,{code:d.code,verifier:o,port:c},e.fetchImpl??fetch),f=await VS(n,{idToken:m.id_token,label:FF()},e.fetchImpl??fetch),p=await QS(f,m,n,r);return t.stdout.write(`
|
|
51
51
|
Signed in as ${f.user_id}
|
|
52
52
|
Appkey saved to ${p.appkeyPath} (0600)
|
|
53
53
|
`),0}catch(u){return t.stderr.write(`error: ${u instanceof Error?u.message:String(u)}
|
|
54
|
-
`),1}finally{a.close()}}var
|
|
55
|
-
`);let i=null;return t.refresh_token&&(i=Ha(o,"identity.json"),await
|
|
56
|
-
`)),{appkeyPath:s,identityPath:i}}async function
|
|
54
|
+
`),1}finally{a.close()}}var ZS=Ht(()=>{zS()});import{createHash as YF,randomBytes as sv}from"node:crypto";function iv(e=process.env){return{domain:e.LMCTL_AUTH_DOMAIN?.trim()||Ns.domain,clientId:e.LMCTL_CLI_CLIENT_ID?.trim()||Ns.clientId,scope:e.LMCTL_AUTH_SCOPE?.trim()||Ns.scope,ports:Ns.ports,authUrl:(e.LMCTL_AUTH_URL?.trim()||Ns.authUrl).replace(/\/+$/,"")}}function av(e=sv){let t=e(32).toString("base64url");return{verifier:t,challenge:YF("sha256").update(t).digest("base64url")}}function cv(e=sv){return e(16).toString("base64url")}function lv(e){return`http://127.0.0.1:${e}/callback`}function uv(e,t){let r=new URLSearchParams({response_type:"code",client_id:e.clientId,redirect_uri:lv(t.port),scope:e.scope,state:t.state,code_challenge:t.challenge,code_challenge_method:"S256"});return`https://${e.domain}/oauth2/authorize?${r}`}function dv(e){let t=new URL(e,"http://127.0.0.1");return{code:t.searchParams.get("code")??void 0,state:t.searchParams.get("state")??void 0,error:t.searchParams.get("error")??void 0}}async function mv(e,t,r=fetch){let n=new URLSearchParams({grant_type:"authorization_code",client_id:e.clientId,code:t.code,redirect_uri:lv(t.port),code_verifier:t.verifier}),o=await r(`https://${e.domain}/oauth2/token`,{method:"POST",headers:{"content-type":"application/x-www-form-urlencoded"},body:n.toString()});if(!o.ok)throw new Error(`token exchange failed: HTTP ${o.status} ${await pv(o)}`);let s=await o.json();if(!s.id_token)throw new Error("token exchange returned no id_token");return s}async function fv(e,t,r=fetch){let n=await r(`${e.authUrl}/appkeys`,{method:"POST",headers:{authorization:`Bearer ${t.idToken}`,"content-type":"application/json"},body:JSON.stringify({label:t.label})});if(!n.ok)throw new Error(`appkey mint failed: HTTP ${n.status} ${await pv(n)}`);return n.json()}async function pv(e){try{return(await e.text()).slice(0,300)}catch{return""}}var Ns,hv=Ht(()=>{Ns={domain:"auth.lmctl.ai",clientId:"lpla33du6p451g9ohb0su9c5u",scope:"openid email profile",ports:[8976,8977,8978,8979],authUrl:"https://lmctl.ai/auth"}});var yv={};Io(yv,{appkeyDir:()=>_v,persistCredentials:()=>wv,runLogin:()=>aq});import{spawn as QF}from"node:child_process";import{mkdir as XF,rename as ZF,writeFile as eq}from"node:fs/promises";import{createServer as tq}from"node:http";import{homedir as rq,hostname as nq}from"node:os";import{join as Ha}from"node:path";function _v(e=process.env){return Ha(e.XDG_CONFIG_HOME?.trim()||Ha(rq(),".config"),"lmctl")}async function wv(e,t,r,n=process.env){let o=_v(n);await XF(o,{recursive:!0,mode:448});let s=Ha(o,"appkey.json");await gv(s,JSON.stringify({version:1,appkey:e.appkey,user_id:e.user_id,label:e.label,issued_at:e.created_at},null,2)+`
|
|
55
|
+
`);let i=null;return t.refresh_token&&(i=Ha(o,"identity.json"),await gv(i,JSON.stringify({user_pool_id:n.COGNITO_USER_POOL_ID?.trim()||"us-east-1_UalgyPyId",client_id:r.clientId,refresh_token:t.refresh_token},null,2)+`
|
|
56
|
+
`)),{appkeyPath:s,identityPath:i}}async function gv(e,t){let r=`${e}.tmp-${process.pid}`;await eq(r,t,{mode:384}),await ZF(r,e)}async function oq(e){let t,r=new Promise(o=>{t=o}),n=tq((o,s)=>{if(!o.url?.startsWith("/callback")){s.writeHead(404).end();return}let i=dv(o.url);s.writeHead(200,{"content-type":"text/html"}).end("<html><body><h3>lmctl login complete.</h3><p>You can close this tab.</p></body></html>"),t(i)});for(let o of e)if(await sq(n,o))return{server:n,port:o,wait:r};throw new Error(`could not bind any loopback port (${e.join(", ")})`)}function sq(e,t){return new Promise(r=>{let n=()=>{e.removeListener("error",n),r(!1)};e.once("error",n),e.listen(t,"127.0.0.1",()=>{e.removeListener("error",n),r(!0)})})}function iq(e,t){let r=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",n=process.platform==="win32"?["/c","start","",e]:[e];try{let o=QF(r,n,{stdio:"ignore",detached:!0});o.on("error",()=>{}),o.unref()}catch{}t.stdout.write(`
|
|
57
57
|
If your browser didn't open, visit:
|
|
58
58
|
${e}
|
|
59
59
|
|
|
60
|
-
`)}async function
|
|
61
|
-
`),(e.openBrowserFn??
|
|
60
|
+
`)}async function aq(e={}){let t=e.io??{stdout:process.stdout,stderr:process.stderr},r=e.env??process.env;if(!process.stdin.isTTY&&(r.LMCTL_NONINTERACTIVE||r.CI))return t.stderr.write("error: `lmtext login` needs an interactive browser. Run it on a machine with a browser and copy ~/.config/lmctl/appkey.json here.\n"),1;let n=iv(r),{verifier:o,challenge:s}=av(),i=cv(),{server:a,port:c,wait:l}=await oq(n.ports);try{let u=uv(n,{port:c,state:i,challenge:s});t.stdout.write(`Opening your browser to sign in with lmctl.ai\u2026
|
|
61
|
+
`),(e.openBrowserFn??iq)(u,t);let d=await l;if(d.error)throw new Error(`authorization failed: ${d.error}`);if(!d.code)throw new Error("no authorization code returned");if(d.state!==i)throw new Error("state mismatch (possible CSRF); aborting");let m=await mv(n,{code:d.code,verifier:o,port:c},e.fetchImpl??fetch),f=await fv(n,{idToken:m.id_token,label:nq()},e.fetchImpl??fetch),p=await wv(f,m,n,r);return t.stdout.write(`
|
|
62
62
|
Signed in as ${f.user_id}
|
|
63
63
|
Appkey saved to ${p.appkeyPath} (0600)
|
|
64
64
|
`),0}catch(u){return t.stderr.write(`error: ${u instanceof Error?u.message:String(u)}
|
|
65
|
-
`),1}finally{a.close()}}var
|
|
66
|
-
`)}function ve(e={}){let t=e.env??process.env,r=e.fs??{readFileSync:(c,l)=>s$(c,l)},n=e.homedir??i$,o=t.LMCTL_APPKEY?.trim();if(o&&oc(o))return{appkey:o,source:"env:LMCTL_APPKEY",envelope:null};let s=t.LMCTL_APPKEY_FILE?.trim();if(s){let c=sm(r,s,"env:LMCTL_APPKEY_FILE");if(c)return c}let i=l$(t,n),a=sm(r,i,"file:default");if(a)return a;throw new en}async function am(e,t={}){let r=await m$("/whoami",{method:"GET",headers:{authorization:`Bearer ${e}`}},t,dr);if(r.status===401)return{valid:!1};if(r.status!==200)throw new dr(`appkey validation failed with status ${r.status}`,{status:r.status});let n=await p$(r,"validate appkey response",dr);return{valid:!0,userId:im(n,"user_id","validate appkey response",dr),label:im(n,"label","validate appkey response",dr)}}function sm(e,t,r){let n;try{n=e.readFileSync(t,"utf8")}catch{return null}let o=n.trim();if(o.length===0)return null;if(o.startsWith("{")){let s;try{s=JSON.parse(o)}catch{s=void 0}if(s&&typeof s=="object"){let i=s;return typeof i.appkey=="string"&&oc(i.appkey.trim())?{appkey:i.appkey.trim(),source:r,envelope:i}:null}}return oc(o)?{appkey:o,source:r,envelope:null}:null}function l$(e,t){let r=e.XDG_CONFIG_HOME?.trim()||om(t(),".config");return om(r,"lmctl","appkey.json")}function u$(e){let t=e.env??process.env;return(e.authBaseUrl?.trim()||t.LMCTL_AUTH_BASE_URL?.trim()||a$).replace(/\/+$/,"")}function d$(e,t){if(e.fetchImpl)return e.fetchImpl;if(typeof globalThis.fetch=="function")return(r,n)=>globalThis.fetch(r,n);throw new t("global fetch is unavailable; pass fetchImpl explicitly")}async function m$(e,t,r,n){return await f$(e,t,r,n,r.timeoutMs)}async function f$(e,t,r,n,o,s){let i=d$(r,n),a=`${u$(r)}${e}`,c=o??c$,l={...t},u=new AbortController;l.signal=u.signal;let d=setTimeout(()=>{u.abort()},c);try{return await i(a,l)}catch(m){throw u.signal.aborted?s?s():new n(`auth request timed out for ${e} after ${c}ms`,{cause:m}):m instanceof n?m:new n(`auth request failed for ${e}`,{cause:m})}finally{clearTimeout(d)}}async function p$(e,t,r){let n;try{n=await e.json()}catch(o){throw new r(`${t} was not valid JSON`,{cause:o,status:e.status})}if(!n||typeof n!="object"||Array.isArray(n))throw new r(`${t} must be a JSON object`,{status:e.status});return n}function im(e,t,r,n){let o=e[t];if(typeof o!="string"||o.length===0)throw new n(`${r} missing string field ${t}`);return o}function Ke(e){return async(...t)=>{throw new Error(`lmmail-client fake: ${e} not stubbed`)}}var C1={listMailboxes:Ke("listMailboxes"),createMailbox:Ke("createMailbox"),deleteMailbox:Ke("deleteMailbox"),sendMessage:Ke("sendMessage"),listMessages:Ke("listMessages"),getRecentMessages:Ke("getRecentMessages"),getMessage:Ke("getMessage"),getMessageMetadata:Ke("getMessageMetadata"),getThread:Ke("getThread"),download:Ke("download"),deleteMessage:Ke("deleteMessage"),registerSite:Ke("registerSite"),resolveSite:Ke("resolveSite"),listSites:Ke("listSites"),setSiteName:Ke("setSiteName"),deleteSiteName:Ke("deleteSiteName"),deleteSite:Ke("deleteSite")};var Wt=class extends Error{status;code;responseBody;constructor(t,r,n,o){super(`${t}: HTTP ${r}${o?` ${o}`:n?` ${n}`:""}`),this.name="LmmailHttpError",this.status=r,this.code=o,this.responseBody=n}};function wt(e){let t=e.apiUrl.replace(/\/+$/,"");if(!t)throw new Error("lmmail API URL is required");if(!e.appkey)throw new Error("lmmail appkey is required");let r=e.fetch??fetch,n={authorization:`Bearer ${e.appkey}`};async function o(x={}){return(await T(`${t}/mailboxes${x.withCounts?"?with_counts=1":""}`,{headers:n},"list mailboxes failed")).mailboxes}async function s(x,I={}){let A=await r(`${t}/mailboxes`,{method:"POST",headers:{...n,"content-type":"application/json"},body:JSON.stringify({mailbox_name:x})});if(A.status===409){let H=await A.text().catch(()=>"");if(I.tolerate409!==!1&&dm(H)==="mailbox_exists")return;throw um("create mailbox failed",A.status,H)}await R(A,"create mailbox failed")}async function i(x){return T(`${t}/mailboxes/${encodeURIComponent(x)}`,{method:"DELETE",headers:n},"delete mailbox failed")}async function a(x){let I=x.attachments??[],A=await T(`${t}/mailboxes/${encodeURIComponent(x.mailbox)}/messages`,{method:"POST",headers:{...n,"content-type":"application/json"},body:JSON.stringify({...x.subject===void 0?{}:{subject:x.subject},body:cm(x.body),attachments:I.map(cm)})},"allocate message failed"),H=[{target:A.body,bytes:x.body.bytes},...A.attachments.map((L,w)=>({target:L,bytes:I[w].bytes}))];for(let{target:L,bytes:w}of H){let b=new FormData;for(let[D,W]of Object.entries(L.fields))b.append(D,W);b.append("file",new Blob([new Uint8Array(w)],{type:L.content_type}),L.name);let N=await r(L.upload_url,{method:"POST",body:b});await R(N,`upload failed for ${L.name}`)}return await T(h$(t,A.finalize_url),{method:"POST",headers:n},"finalize message failed"),A.seq}async function c(x,I={}){let A=new URLSearchParams;if(I.status&&A.set("status",I.status),I.after!==void 0&&A.set("after",String(I.after)),I.wait_s!==void 0){if(!Number.isInteger(I.wait_s)||I.wait_s<0||I.wait_s>20)throw new Error("wait_s must be an integer from 0 through 20");A.set("wait_s",String(I.wait_s))}let H=A.size>0?`?${A.toString()}`:"",L=await T(`${t}/mailboxes/${encodeURIComponent(x)}/messages${H}`,{headers:n},"list messages failed");return{messages:L.messages,next_after:L.next_after}}async function l(x={}){let I=new URLSearchParams;if(x.limit!==void 0){if(!Number.isInteger(x.limit)||x.limit<1||x.limit>50)throw new Error("limit must be an integer from 1 through 50");I.set("limit",String(x.limit))}let A=I.size>0?`?${I.toString()}`:"";return T(`${t}/messages/recent${A}`,{headers:n},"get recent messages failed")}async function u(x,I){return T(`${t}/mailboxes/${encodeURIComponent(x)}/messages/${I}`,{headers:n},"get message failed")}async function d(x,I){let A=await u(x,I);return{...A,body:lm(A.body),attachments:A.attachments.map(lm)}}async function m(x,I){return T(`${t}/mailboxes/${encodeURIComponent(x)}/messages/${I}/thread`,{headers:n},"get thread failed")}async function f(x){let I=await r(x);return await R(I,"download failed"),new Uint8Array(await I.arrayBuffer())}async function p(x,I){await T(`${t}/mailboxes/${encodeURIComponent(x)}/messages/${I}`,{method:"DELETE",headers:n},"delete message failed")}async function h(x,I,A){return await T(`${t}/sites`,{method:"POST",headers:{...n,"content-type":"application/json"},body:JSON.stringify({site_name:x,site_uuid:I,mailbox:A})},"register site failed")}async function g(x){return await T(`${t}/sites/${encodeURIComponent(x)}`,{headers:n},"resolve site failed")}async function _(x={}){let I=new URLSearchParams;if(x.cursor!==void 0&&I.set("cursor",x.cursor),x.limit!==void 0){if(!Number.isInteger(x.limit)||x.limit<1||x.limit>50)throw new Error("limit must be an integer from 1 through 50");I.set("limit",String(x.limit))}let A=I.size>0?`?${I.toString()}`:"";return T(`${t}/sites${A}`,{headers:n},"list sites failed")}async function E(x,I){return T(`${t}/sites/name`,{method:"PUT",headers:{...n,"content-type":"application/json"},body:JSON.stringify({site:x,name:I})},"set site name failed")}async function y(x){return T(`${t}/sites/name`,{method:"DELETE",headers:{...n,"content-type":"application/json"},body:JSON.stringify({site:x})},"delete site name failed")}async function S(x){await T(`${t}/sites/${encodeURIComponent(x)}`,{method:"DELETE",headers:n},"delete site failed")}async function T(x,I,A){let H=await r(x,I);await R(H,A);try{return await H.json()}catch(L){throw new Error(`${A}: invalid JSON response: ${g$(L)}`)}}async function R(x,I){if(x.ok)return;let A=await x.text().catch(()=>"");throw um(I,x.status,A)}return{listMailboxes:o,createMailbox:s,deleteMailbox:i,sendMessage:a,listMessages:c,getRecentMessages:l,getMessage:u,getMessageMetadata:d,getThread:m,download:f,deleteMessage:p,registerSite:h,resolveSite:g,listSites:_,setSiteName:E,deleteSiteName:y,deleteSite:S}}function cm(e){return{name:e.name,size:e.bytes.byteLength,content_type:e.contentType}}function lm(e){return{name:e.name,size:e.size,content_type:e.content_type}}function um(e,t,r){return new Wt(e,t,r,dm(r))}function dm(e){try{let t=JSON.parse(e);return typeof t.error=="string"?t.error:void 0}catch{return}}function h$(e,t){return/^https?:\/\//i.test(t)?t:`${e}${t.startsWith("/")?"":"/"}${t}`}function g$(e){return e instanceof Error?e.message:String(e)}import{execFile as G$}from"node:child_process";import{existsSync as V$}from"node:fs";import{join as J$}from"node:path";import{promisify as z$}from"node:util";import{existsSync as mm}from"node:fs";import{createRequire as _$}from"node:module";import{dirname as w$}from"node:path";var sc=null;function y$(){return sc===null&&(sc=_$(import.meta.url)("node:sqlite").DatabaseSync),sc}var E$={1:"SQLITE_ERROR",2:"SQLITE_INTERNAL",3:"SQLITE_PERM",4:"SQLITE_ABORT",5:"SQLITE_BUSY",6:"SQLITE_LOCKED",7:"SQLITE_NOMEM",8:"SQLITE_READONLY",9:"SQLITE_INTERRUPT",10:"SQLITE_IOERR",11:"SQLITE_CORRUPT",12:"SQLITE_NOTFOUND",13:"SQLITE_FULL",14:"SQLITE_CANTOPEN",15:"SQLITE_PROTOCOL",16:"SQLITE_EMPTY",17:"SQLITE_SCHEMA",18:"SQLITE_TOOBIG",19:"SQLITE_CONSTRAINT",20:"SQLITE_MISMATCH",21:"SQLITE_MISUSE",22:"SQLITE_NOLFS",23:"SQLITE_AUTH",24:"SQLITE_FORMAT",25:"SQLITE_RANGE",26:"SQLITE_NOTADB",27:"SQLITE_NOTICE",28:"SQLITE_WARNING"},b$={261:"SQLITE_BUSY_RECOVERY",517:"SQLITE_BUSY_SNAPSHOT",773:"SQLITE_BUSY_TIMEOUT",262:"SQLITE_LOCKED_SHAREDCACHE",518:"SQLITE_LOCKED_VTAB",264:"SQLITE_READONLY_RECOVERY",520:"SQLITE_READONLY_CANTLOCK",776:"SQLITE_READONLY_ROLLBACK",1032:"SQLITE_READONLY_DBMOVED",1288:"SQLITE_READONLY_CANTINIT",1544:"SQLITE_READONLY_DIRECTORY",270:"SQLITE_CANTOPEN_NOTEMPDIR",526:"SQLITE_CANTOPEN_ISDIR",782:"SQLITE_CANTOPEN_FULLPATH",1038:"SQLITE_CANTOPEN_CONVPATH",1294:"SQLITE_CANTOPEN_DIRTYWAL",1550:"SQLITE_CANTOPEN_SYMLINK",275:"SQLITE_CONSTRAINT_CHECK",531:"SQLITE_CONSTRAINT_COMMITHOOK",787:"SQLITE_CONSTRAINT_FOREIGNKEY",1043:"SQLITE_CONSTRAINT_FUNCTION",1299:"SQLITE_CONSTRAINT_NOTNULL",1555:"SQLITE_CONSTRAINT_PRIMARYKEY",1811:"SQLITE_CONSTRAINT_TRIGGER",2067:"SQLITE_CONSTRAINT_UNIQUE",2323:"SQLITE_CONSTRAINT_VTAB",2579:"SQLITE_CONSTRAINT_ROWID",2835:"SQLITE_CONSTRAINT_PINNED",3091:"SQLITE_CONSTRAINT_DATATYPE"};function T$(e){return b$[e]??E$[e&255]??`SQLITE_UNKNOWN_${e}`}var S$="SQLite3 can only bind numbers, strings, bigints, buffers, and null";function Gt(e){if(e!==null&&typeof e=="object"){let t=e;if(typeof t.errcode=="number")throw t.code=T$(t.errcode),e;if(t.code==="ERR_INVALID_ARG_TYPE"&&/cannot be bound/.test(String(t.message)))throw new TypeError(S$);if(t.code==="ERR_INVALID_STATE"&&/database is not open/.test(String(t.message)))throw new TypeError("The database connection is not open")}throw e}function v$(){let e="unable to open database file";return Object.assign(new Error(e),{code:"SQLITE_CANTOPEN",errcode:14,errstr:e})}function fm(e){return e instanceof Uint8Array&&!Buffer.isBuffer(e)?Buffer.from(e.buffer,e.byteOffset,e.byteLength):e}function A$(e){if(e==null)return e;if(Array.isArray(e))return e.map(fm);if(typeof e=="object"){let t={};for(let[r,n]of Object.entries(e))t[r]=fm(n);return t}return e}function $$(e){if(e===null||typeof e!="object"||Array.isArray(e)||e instanceof Uint8Array)return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function qs(e){return e.map((t,r)=>{if(t===void 0)return null;if(r===0&&$$(t)){let n={};for(let[o,s]of Object.entries(t))n[o]=s===void 0?null:s;return n}return t})}var ic=class{handle;pluckMode=!1;arrayMode=!1;constructor(t){this.handle=t,this.handle.setAllowBareNamedParameters(!0),this.handle.setAllowUnknownNamedParameters(!0)}get source(){return this.handle.sourceSQL}run(...t){try{let r=this.handle.run(...qs(t));return{changes:Number(r.changes),lastInsertRowid:Number(r.lastInsertRowid)}}catch(r){Gt(r)}}get(...t){try{return this.project(this.handle.get(...qs(t)))}catch(r){Gt(r)}}all(...t){try{return this.handle.all(...qs(t)).map(r=>this.project(r))}catch(r){Gt(r)}}*iterate(...t){let r;try{r=this.handle.iterate(...qs(t))}catch(n){Gt(n)}for(;;){let n;try{n=r.next()}catch(o){Gt(o)}if(n.done)return;yield this.project(n.value)}}raw(t=!0){return this.arrayMode=t,this.handle.setReturnArrays(t||this.pluckMode),this}pluck(t=!0){return this.pluckMode=t,this.handle.setReturnArrays(t||this.arrayMode),this}project(t){let r=A$(t);return this.pluckMode&&Array.isArray(r)?r[0]:r}},ac=class{name;memory;readonly;handle;savepointId=0;constructor(t,r={}){let n=t===":memory:"||t==="";if(r.readonly===!0&&n)throw new TypeError("In-memory/temporary databases cannot be readonly");if(!n&&!mm(w$(t)))throw new TypeError("Cannot open database because the directory does not exist");if(r.fileMustExist===!0&&!n&&!mm(t))throw v$();this.name=t,this.memory=n,this.readonly=r.readonly===!0;try{this.handle=new(y$())(t,{readOnly:this.readonly,timeout:r.timeout??5e3,enableForeignKeyConstraints:r.foreignKeys??!0})}catch(o){Gt(o)}}get open(){return this.handle.isOpen}get inTransaction(){return this.handle.isTransaction}prepare(t){try{return new ic(this.handle.prepare(t))}catch(r){Gt(r)}}exec(t){try{return this.handle.exec(t),this}catch(r){Gt(r)}}pragma(t,r){let n=this.prepare(`PRAGMA ${t}`);return r?.simple===!0?n.pluck().get():n.all()}transaction(t){let r=o=>(...s)=>this.runTransaction(o,t,s),n=r("BEGIN");return n.default=r("BEGIN"),n.deferred=r("BEGIN DEFERRED"),n.immediate=r("BEGIN IMMEDIATE"),n.exclusive=r("BEGIN EXCLUSIVE"),n}serialize(){try{let t=this.handle.serialize();return Buffer.from(t.buffer,t.byteOffset,t.byteLength)}catch(t){Gt(t)}}close(){if(!this.handle.isOpen)return this;try{return this.handle.close(),this}catch(t){Gt(t)}}runTransaction(t,r,n){if(!this.inTransaction){this.exec(t);try{let s=r(...n);return this.exec("COMMIT"),s}catch(s){if(this.inTransaction)try{this.exec("ROLLBACK")}catch(i){if(!k$(i))throw i}throw s}}let o=`lmbee_sp_${this.savepointId+=1}`;this.exec(`SAVEPOINT ${o}`);try{let s=r(...n);return this.exec(`RELEASE ${o}`),s}catch(s){if(this.inTransaction)try{this.exec(`ROLLBACK TO ${o}`),this.exec(`RELEASE ${o}`)}catch(i){if(!x$(i))throw i}throw s}}};function k$(e){return e instanceof Error&&/cannot rollback - no transaction is active/i.test(e.message)}function x$(e){return e instanceof Error&&/no such savepoint:/i.test(e.message)}var yt=ac;import{existsSync as lc,lstatSync as R$,mkdirSync as N$,readFileSync as wm,realpathSync as pm}from"node:fs";import{basename as I$,dirname as uc,isAbsolute as L$,join as C$,relative as O$,resolve as hm}from"node:path";import{fileURLToPath as D$}from"node:url";var ym=C$(uc(D$(import.meta.url)),"schema.sql");function Lo(e){if(e!==void 0&&e!=="")return e;let t=process.env.LMBEE_DB;if(t)return t;throw new Error("No lmbee database selected: pass an explicit database path or set LMBEE_DB to the intended existing database. The retired ~/.lmbee/state.db default is no longer used.")}function M$(e){if(e.startsWith("~"))throw new Error(`Refusing to open the lmbee database at "${e}": lmbee does not expand "~" in database paths, so this would be created as a literal directory named "~" under the current working directory. Use an absolute path instead (for example ~/.lmbee/state.db). Note for systemd units: Environment= expands neither "~" nor "$HOME", so write the absolute path literally there too.`)}function P$(e,t){if(!(e===":memory:"||lc(e)))throw new Error(`Refusing to create the lmbee database at "${e}": ${t} points at non-existent "${e}", and a typo is indistinguishable from a fresh install. To provision a new database here, \`touch "${e}"\` first, then retry, or point ${t} at an existing database.`)}function U$(e){e.transaction(()=>{let r=e.prepare("PRAGMA table_info(queue)").all();if(r.length===0)return;let n=new Set(r.map(s=>s.name));n.has("subject_id")||e.exec("ALTER TABLE queue ADD COLUMN subject_id TEXT"),n.has("dedupe_key")||e.exec("ALTER TABLE queue ADD COLUMN dedupe_key TEXT"),e.prepare(`SELECT name FROM pragma_index_list('queue') WHERE "unique" = 1 AND partial = 0`).all().some(s=>{let i=e.prepare("SELECT name FROM pragma_index_info(?) ORDER BY seqno").all(s.name);return i.length===1&&i[0].name==="dedupe_key"})||e.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_queue_dedupe_key ON queue(dedupe_key)"),n.has("delivered_via_escalation")||e.exec("ALTER TABLE queue ADD COLUMN delivered_via_escalation INTEGER NOT NULL DEFAULT 0"),n.has("escalation_claimed_ts")||e.exec("ALTER TABLE queue ADD COLUMN escalation_claimed_ts TEXT"),n.has("escalation_claim_token")||e.exec("ALTER TABLE queue ADD COLUMN escalation_claim_token TEXT"),n.has("escalation_only")||e.exec("ALTER TABLE queue ADD COLUMN escalation_only INTEGER NOT NULL DEFAULT 0"),n.has("admission_fingerprint")||e.exec("ALTER TABLE queue ADD COLUMN admission_fingerprint TEXT"),n.has("expects_response")||e.exec("ALTER TABLE queue ADD COLUMN expects_response INTEGER NOT NULL DEFAULT 0"),n.has("to_alias")||e.exec("ALTER TABLE queue ADD COLUMN to_alias TEXT"),n.has("retracted_ts")||e.exec("ALTER TABLE queue ADD COLUMN retracted_ts TEXT"),n.has("retracted_reason")||e.exec("ALTER TABLE queue ADD COLUMN retracted_reason TEXT"),n.has("retraction_notice")||e.exec("ALTER TABLE queue ADD COLUMN retraction_notice INTEGER NOT NULL DEFAULT 0"),n.has("in_reply_to")||e.exec("ALTER TABLE queue ADD COLUMN in_reply_to INTEGER"),n.has("operator_priority")||e.exec("ALTER TABLE queue ADD COLUMN operator_priority INTEGER NOT NULL DEFAULT 0"),n.has("merged_into_id")||e.exec("ALTER TABLE queue ADD COLUMN merged_into_id INTEGER")}).immediate()}function F$(e){e.transaction(()=>{let r=e.prepare("PRAGMA table_info(team_progress)").all();if(r.length===0)return;let n=new Set(r.map(o=>o.name));n.has("last_miniplayer_reply_hash")||e.exec("ALTER TABLE team_progress ADD COLUMN last_miniplayer_reply_hash TEXT"),n.has("blocked_surfaced_ts")||e.exec("ALTER TABLE team_progress ADD COLUMN blocked_surfaced_ts TEXT"),n.has("last_escalation_attempt_ts")||e.exec("ALTER TABLE team_progress ADD COLUMN last_escalation_attempt_ts TEXT"),n.has("escalation_attempt_count")||e.exec("ALTER TABLE team_progress ADD COLUMN escalation_attempt_count INTEGER NOT NULL DEFAULT 0"),n.has("fault_surfaced_ts")||e.exec("ALTER TABLE team_progress ADD COLUMN fault_surfaced_ts TEXT"),n.has("epic_closed_surfaced_ts")||e.exec("ALTER TABLE team_progress ADD COLUMN epic_closed_surfaced_ts TEXT"),n.has("quota_exhausted_last_seen_ts")||e.exec("ALTER TABLE team_progress ADD COLUMN quota_exhausted_last_seen_ts TEXT"),n.has("quota_exhausted_message")||e.exec("ALTER TABLE team_progress ADD COLUMN quota_exhausted_message TEXT"),n.has("miniplayer_verdict_label")||e.exec("ALTER TABLE team_progress ADD COLUMN miniplayer_verdict_label TEXT"),n.has("miniplayer_verdict_reason")||e.exec("ALTER TABLE team_progress ADD COLUMN miniplayer_verdict_reason TEXT"),n.has("miniplayer_verdict_ts")||e.exec("ALTER TABLE team_progress ADD COLUMN miniplayer_verdict_ts TEXT"),n.has("miniplayer_verdict_input_hash")||e.exec("ALTER TABLE team_progress ADD COLUMN miniplayer_verdict_input_hash TEXT"),n.has("miniplayer_verdict_structural_hash")||e.exec("ALTER TABLE team_progress ADD COLUMN miniplayer_verdict_structural_hash TEXT"),n.has("holder_watch_pid")||e.exec("ALTER TABLE team_progress ADD COLUMN holder_watch_pid INTEGER"),n.has("holder_watch_started_at")||e.exec("ALTER TABLE team_progress ADD COLUMN holder_watch_started_at TEXT"),n.has("holder_watch_cpu_ticks")||e.exec("ALTER TABLE team_progress ADD COLUMN holder_watch_cpu_ticks INTEGER"),n.has("holder_watch_observed_at")||e.exec("ALTER TABLE team_progress ADD COLUMN holder_watch_observed_at TEXT"),n.has("holder_watch_low_cpu_streak")||e.exec("ALTER TABLE team_progress ADD COLUMN holder_watch_low_cpu_streak INTEGER"),n.has("hung_holder_flagged_ts")||e.exec("ALTER TABLE team_progress ADD COLUMN hung_holder_flagged_ts TEXT"),n.has("hung_holder_reason")||e.exec("ALTER TABLE team_progress ADD COLUMN hung_holder_reason TEXT"),n.has("last_cli_activity_ts")||e.exec("ALTER TABLE team_progress ADD COLUMN last_cli_activity_ts TEXT")}).immediate()}function q$(e){e.transaction(()=>{let r=e.prepare("PRAGMA table_info(cron_jobs)").all();if(r.length===0)return;let n=new Set(r.map(o=>o.name));n.has("last_fire_error")||e.exec("ALTER TABLE cron_jobs ADD COLUMN last_fire_error TEXT"),n.has("running_systemd_unit")||e.exec("ALTER TABLE cron_jobs ADD COLUMN running_systemd_unit TEXT"),n.has("timezone")||e.exec("ALTER TABLE cron_jobs ADD COLUMN timezone TEXT"),n.has("provider")||e.exec("ALTER TABLE cron_jobs ADD COLUMN provider TEXT"),n.has("model")||e.exec("ALTER TABLE cron_jobs ADD COLUMN model TEXT"),n.has("working_directory")||e.exec("ALTER TABLE cron_jobs ADD COLUMN working_directory TEXT"),n.has("escalation_owner")||e.exec("ALTER TABLE cron_jobs ADD COLUMN escalation_owner TEXT"),n.has("session_teamfile")||e.exec("ALTER TABLE cron_jobs ADD COLUMN session_teamfile TEXT"),n.has("session_alias")||e.exec("ALTER TABLE cron_jobs ADD COLUMN session_alias TEXT"),n.has("session_seeded_at")||e.exec("ALTER TABLE cron_jobs ADD COLUMN session_seeded_at TEXT"),n.has("session_generation")||e.exec("ALTER TABLE cron_jobs ADD COLUMN session_generation INTEGER NOT NULL DEFAULT 0")}).immediate()}function j$(e){e.transaction(()=>{let r=e.prepare("PRAGMA table_info(entities)").all();if(r.length===0)return;let n=new Set(r.map(o=>o.name));n.has("delivered_ts")||e.exec("ALTER TABLE entities ADD COLUMN delivered_ts TEXT"),n.has("review_time")||e.exec("ALTER TABLE entities ADD COLUMN review_time TEXT"),n.has("needs_review")||e.exec("ALTER TABLE entities ADD COLUMN needs_review INTEGER NOT NULL DEFAULT 0 CHECK(needs_review IN (0,1))"),n.has("review_reason")||e.exec("ALTER TABLE entities ADD COLUMN review_reason TEXT"),n.has("review_input_hash")||e.exec("ALTER TABLE entities ADD COLUMN review_input_hash TEXT"),n.has("hold_until")||e.exec("ALTER TABLE entities ADD COLUMN hold_until TEXT"),n.has("hold_reason")||e.exec("ALTER TABLE entities ADD COLUMN hold_reason TEXT"),n.has("blocked_on")||e.exec("ALTER TABLE entities ADD COLUMN blocked_on TEXT")}).immediate()}function H$(e){e.transaction(()=>{let r=e.prepare("PRAGMA table_info(mail_ledger)").all();if(r.length===0)return;let n=new Set(r.map(o=>o.name));n.has("ack_sent_ts")||e.exec("ALTER TABLE mail_ledger ADD COLUMN ack_sent_ts TEXT"),n.has("delivery_error")||e.exec("ALTER TABLE mail_ledger ADD COLUMN delivery_error TEXT"),n.has("delivery_error_ts")||e.exec("ALTER TABLE mail_ledger ADD COLUMN delivery_error_ts TEXT")}).immediate()}function dc(e){let t=process.env.LMBEE_TEST_DB_ROOT;if(!t||e===":memory:")return;let r=[],n=hm(e);for(;R$(n,{throwIfNoEntry:!1})===void 0;){r.unshift(I$(n));let i=uc(n);if(i===n)throw new Error("Cannot resolve test database path");n=i}let o=hm(pm(n),...r),s=O$(pm(t),o);if(s===".."||s.startsWith("../")||s.startsWith("..\\")||L$(s))throw new Error(`Database path is outside the test database root: ${e}`)}function gm(e){let t=o=>e.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(o)!==void 0,r=o=>e.prepare(`PRAGMA table_info(${o})`).all(),n;for(let o of["queue_responses","chat_tasks","chat_messages","chat_message_task_reassignments"])if(t(o)){n=`legacy table '${o}'`;break}if(n===void 0&&t("answers")){let o=new Set(r("answers").map(s=>s.name));o.has("request_queue_id")?n="legacy column 'answers.request_queue_id'":o.has("superseded_at")||(n="legacy 'answers' shape: missing column 'superseded_at'")}if(n===void 0&&t("queue")){let o=r("queue"),s=new Set(o.map(i=>i.name));s.has("team")?n="legacy column 'queue.team'":s.has("to_id")?o.some(i=>i.name==="from_id"&&i.notnull!==1)?n="legacy 'queue' shape: from_id is still nullable":s.has("restart_nudge_sent_ts")&&(n="legacy column 'queue.restart_nudge_sent_ts'"):n="legacy 'queue' shape: missing column 'to_id'"}if(n===void 0&&t("cron_jobs")){let o=e.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'cron_jobs'").get();(o===void 0||!o.sql.includes("'miniplayer'"))&&(n="legacy 'cron_jobs' CHECK constraint predates 'miniplayer'")}if(n===void 0&&t("cron_jobs")){let o=e.prepare("SELECT id, action_payload FROM cron_jobs WHERE action_kind = 'enqueue'").all();for(let s of o){let i;try{i=JSON.parse(s.action_payload)}catch{i=void 0}let a=typeof i=="object"&&i!==null?i.prompt:void 0;if(typeof a!="string"||a.trim().length===0){n=`legacy 'cron_jobs' enqueue payload (id ${s.id}) predates the 'prompt' vocabulary`;break}}}if(n===void 0&&t("team_progress")&&new Set(r("team_progress").map(s=>s.name)).has("last_scan_head")&&(n="legacy column 'team_progress.last_scan_head'"),n===void 0&&t("cron_runs")&&(new Set(r("cron_runs").map(s=>s.name)).has("execution_state")||(n="legacy 'cron_runs' shape: missing column 'execution_state'")),n===void 0&&t("rate_limit_policy_log")){let o=e.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'rate_limit_policy_log'").get();(o===void 0||!o.sql.includes("'confirmed_would_fire_policy_disabled'"))&&(n="legacy 'rate_limit_policy_log' CHECK constraint predates 'confirmed_would_fire_policy_disabled'")}if(n===void 0&&t("rate_limit_policy_arm")&&(new Set(r("rate_limit_policy_arm").map(s=>s.name)).has("armed_used_fraction")||(n="legacy 'rate_limit_policy_arm' shape: missing column 'armed_used_fraction'")),n!==void 0)throw new Error(`Refusing to open this lmbee state.db: abandoned pre-v14 lmbee schema shape (${n}). Per the operator's 2026-10-01 shared-database decision, lmbee now shares lmctl's state.db and every pre-existing lmbee-only database is abandoned -- there is no data migration, ever. Do not remove a shared lmctl database. Check LMBEE_DB and the database ownership; point lmbee at the intended compatible database. Preserve this file for operator review.`)}var js=62;function _m(e){let t=e.pragma("user_version",{simple:!0});if(t<=js)return;let r;if(e.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'schema_meta'").get()!==void 0){let o=new Set(e.prepare("PRAGMA table_info(schema_meta)").all().map(s=>s.name));if(o.has("key")&&o.has("value")){let s=e.prepare("SELECT value FROM schema_meta WHERE key = 'min_reader_version'").get();typeof s?.value=="string"&&(r=s.value)}}let n;if(r===void 0)n="schema_meta.min_reader_version is absent";else if(!/^[1-9]\d*$/.test(r))n=`schema_meta.min_reader_version=${JSON.stringify(r)} is malformed (not a canonical decimal integer)`;else if(Number(r)>js)n=`schema_meta.min_reader_version=${r} declares a breaking floor above ${js}`;else return;throw new Error(`Refusing to open the shared state.db: it was migrated by a newer lmctl with breaking changes (user_version=${t} exceeds the newest lmctl schema version this lmbee build understands, ${js}, and ${n}). Upgrade lmbee to a build that understands the newer lmctl schema before opening this database again. lmbee never writes user_version or schema_meta, so the file is untouched.`)}var cc;function B$(){return cc===void 0&&(cc=[...wm(ym,"utf8").matchAll(/CREATE TABLE IF NOT EXISTS (\w+)/gi)].map(t=>t[1])),cc}function W$(e,t){let r=new Set(e.prepare("SELECT name FROM sqlite_master WHERE type = 'table'").all().map(o=>o.name)),n=B$().filter(o=>!r.has(o));if(n.length!==0)throw new Error(`Refusing a read-only open of "${t}": required lmbee schema is missing (no table${n.length===1?"":"s"}: ${n.join(", ")}), and a read-only handle cannot create it. Run any writable lmbee command (or start the daemon) once against this database to provision it, then retry.`)}function Hs(e,t={}){let r=Lo(e);M$(r);let n=!e&&typeof process.env.LMBEE_DB=="string"&&process.env.LMBEE_DB!=="";if(n&&P$(r,"LMBEE_DB"),dc(r),t.readOnly&&r===":memory:")throw new Error("Refusing a read-only open of ':memory:': an in-memory database starts empty on every open, so the required lmbee schema can never be present and a read-only handle cannot create it.");if(t.readOnly&&r!==":memory:"){if(!lc(r))throw new Error(`Refusing a read-only open of "${r}": the file does not exist, so the required lmbee schema is missing. Run any writable lmbee command (or start the daemon) once against this database to provision it, then retry.`);let a=new yt(r,{readonly:!0,fileMustExist:!0});try{gm(a),_m(a),a.pragma("busy_timeout = 5000"),W$(a,r)}catch(c){throw a.close(),c}return{path:r,db:a,close:()=>a.close()}}if(r!==":memory:"){let a=uc(r);lc(a)||N$(a,{recursive:!0})}let o=new yt(r,n?{fileMustExist:!0}:void 0);try{gm(o),_m(o)}catch(a){throw o.close(),a}o.pragma("journal_mode = WAL"),o.pragma("busy_timeout = 5000");let s=wm(ym,"utf8"),i=o.transaction(()=>{U$(o),F$(o),H$(o),j$(o),q$(o),o.exec(s);let a=o.pragma("table_info(on_demand_launches)");a.some(c=>c.name==="phase")||(o.exec("ALTER TABLE on_demand_launches ADD COLUMN phase TEXT NOT NULL DEFAULT 'reserved' CHECK(phase IN ('reserved', 'dispatching', 'worker_adopted', 'uncertain'))"),o.exec("UPDATE on_demand_launches SET phase = 'uncertain' WHERE state = 'adopted' OR run_id IS NOT NULL")),a.some(c=>c.name==="worker_pid")||o.exec("ALTER TABLE on_demand_launches ADD COLUMN worker_pid INTEGER"),a.some(c=>c.name==="worker_start")||o.exec("ALTER TABLE on_demand_launches ADD COLUMN worker_start TEXT"),a.some(c=>c.name==="receipt_path")||o.exec("ALTER TABLE on_demand_launches ADD COLUMN receipt_path TEXT")});try{i.immediate()}catch(a){throw o.close(),a}return{path:r,db:o,close:()=>o.close()}}function qe(e,t){return e.prepare("SELECT * FROM team_state WHERE team = ?").get(t)??null}function Em(e,t){let r=qe(e,t);return r===null?{kind:"never-observed"}:{kind:"observed",value:r,observedAt:r.last_ts,changedAt:r.changed_ts}}function mr(e,t,r,n){let o=new Date(n).toISOString(),s=qe(e,t),i=s&&s.status===r?s.changed_ts:o;e.prepare(`INSERT INTO team_state(team, status, changed_ts, last_ts) VALUES (?, ?, ?, ?)
|
|
67
|
-
ON CONFLICT(team) DO UPDATE SET status = excluded.status, changed_ts = excluded.changed_ts, last_ts = excluded.last_ts`).run(t,r,i,o)}function ot(e,t,r,n,o={}){e.prepare("INSERT INTO events(ts, scan, team, status, note) VALUES (?, ?, ?, ?, ?)").run(new Date(n).toISOString(),o.scan??null,t,r,o.note??null)}function Bs(e,t,r,n){return e.prepare("SELECT * FROM events WHERE status = ? AND ts >= ? ORDER BY id DESC LIMIT ?").all(t,r,n)}function
|
|
65
|
+
`),1}finally{a.close()}}var Ev=Ht(()=>{hv()});import{spawn as h1}from"node:child_process";import{openSync as g1,mkdirSync as _1,writeFileSync as w1}from"node:fs";import{homedir as y1}from"node:os";import{join as tm}from"node:path";import{mkdirSync as $1,readFileSync as i$,renameSync as k1,writeFileSync as x1}from"node:fs";import{homedir as a$}from"node:os";import{dirname as I1,join as om}from"node:path";var S1=Object.freeze({free:1e6,test:1e7});var en=class extends Error{code="APPKEY_NOT_FOUND";constructor(t="no lmctl appkey found; run `lmchat login` on a machine with a browser, or copy ~/.config/lmctl/appkey.json here, or set LMCTL_APPKEY"){super(t),this.name="AppkeyNotFoundError"}},dr=class extends Error{code="APPKEY_VALIDATION_ERROR";status;constructor(t,r={}){super(t),this.name="AppkeyValidationError",this.status=r.status,this.cause=r.cause}},Us=class extends Error{code="APPKEY_INVALID";source;constructor(t){super(`${t} resolved an invalid lmctl appkey`),this.name="AppkeyInvalidError",this.source=t}},Fs=class extends Error{code="AUTH_API_ERROR";status;constructor(t,r={}){super(t),this.name="AuthApiError",this.status=r.status,this.cause=r.cause}};var c$="https://lmctl.ai/auth",l$=1e4;function oc(e){return e.length>0&&!e.includes(`
|
|
66
|
+
`)}function ve(e={}){let t=e.env??process.env,r=e.fs??{readFileSync:(c,l)=>i$(c,l)},n=e.homedir??a$,o=t.LMCTL_APPKEY?.trim();if(o&&oc(o))return{appkey:o,source:"env:LMCTL_APPKEY",envelope:null};let s=t.LMCTL_APPKEY_FILE?.trim();if(s){let c=sm(r,s,"env:LMCTL_APPKEY_FILE");if(c)return c}let i=u$(t,n),a=sm(r,i,"file:default");if(a)return a;throw new en}async function am(e,t={}){let r=await f$("/whoami",{method:"GET",headers:{authorization:`Bearer ${e}`}},t,dr);if(r.status===401)return{valid:!1};if(r.status!==200)throw new dr(`appkey validation failed with status ${r.status}`,{status:r.status});let n=await h$(r,"validate appkey response",dr);return{valid:!0,userId:im(n,"user_id","validate appkey response",dr),label:im(n,"label","validate appkey response",dr)}}function sm(e,t,r){let n;try{n=e.readFileSync(t,"utf8")}catch{return null}let o=n.trim();if(o.length===0)return null;if(o.startsWith("{")){let s;try{s=JSON.parse(o)}catch{s=void 0}if(s&&typeof s=="object"){let i=s;return typeof i.appkey=="string"&&oc(i.appkey.trim())?{appkey:i.appkey.trim(),source:r,envelope:i}:null}}return oc(o)?{appkey:o,source:r,envelope:null}:null}function u$(e,t){let r=e.XDG_CONFIG_HOME?.trim()||om(t(),".config");return om(r,"lmctl","appkey.json")}function d$(e){let t=e.env??process.env;return(e.authBaseUrl?.trim()||t.LMCTL_AUTH_BASE_URL?.trim()||c$).replace(/\/+$/,"")}function m$(e,t){if(e.fetchImpl)return e.fetchImpl;if(typeof globalThis.fetch=="function")return(r,n)=>globalThis.fetch(r,n);throw new t("global fetch is unavailable; pass fetchImpl explicitly")}async function f$(e,t,r,n){return await p$(e,t,r,n,r.timeoutMs)}async function p$(e,t,r,n,o,s){let i=m$(r,n),a=`${d$(r)}${e}`,c=o??l$,l={...t},u=new AbortController;l.signal=u.signal;let d=setTimeout(()=>{u.abort()},c);try{return await i(a,l)}catch(m){throw u.signal.aborted?s?s():new n(`auth request timed out for ${e} after ${c}ms`,{cause:m}):m instanceof n?m:new n(`auth request failed for ${e}`,{cause:m})}finally{clearTimeout(d)}}async function h$(e,t,r){let n;try{n=await e.json()}catch(o){throw new r(`${t} was not valid JSON`,{cause:o,status:e.status})}if(!n||typeof n!="object"||Array.isArray(n))throw new r(`${t} must be a JSON object`,{status:e.status});return n}function im(e,t,r,n){let o=e[t];if(typeof o!="string"||o.length===0)throw new n(`${r} missing string field ${t}`);return o}function Ye(e){return async(...t)=>{throw new Error(`lmmail-client fake: ${e} not stubbed`)}}var O1={listMailboxes:Ye("listMailboxes"),createMailbox:Ye("createMailbox"),deleteMailbox:Ye("deleteMailbox"),sendMessage:Ye("sendMessage"),listMessages:Ye("listMessages"),getRecentMessages:Ye("getRecentMessages"),getMessage:Ye("getMessage"),getMessageMetadata:Ye("getMessageMetadata"),getThread:Ye("getThread"),download:Ye("download"),deleteMessage:Ye("deleteMessage"),registerSite:Ye("registerSite"),resolveSite:Ye("resolveSite"),listSites:Ye("listSites"),setSiteName:Ye("setSiteName"),deleteSiteName:Ye("deleteSiteName"),deleteSite:Ye("deleteSite")};var Wt=class extends Error{status;code;responseBody;constructor(t,r,n,o){super(`${t}: HTTP ${r}${o?` ${o}`:n?` ${n}`:""}`),this.name="LmmailHttpError",this.status=r,this.code=o,this.responseBody=n}};function wt(e){let t=e.apiUrl.replace(/\/+$/,"");if(!t)throw new Error("lmmail API URL is required");if(!e.appkey)throw new Error("lmmail appkey is required");let r=e.fetch??fetch,n={authorization:`Bearer ${e.appkey}`};async function o(x={}){return(await T(`${t}/mailboxes${x.withCounts?"?with_counts=1":""}`,{headers:n},"list mailboxes failed")).mailboxes}async function s(x,I={}){let A=await r(`${t}/mailboxes`,{method:"POST",headers:{...n,"content-type":"application/json"},body:JSON.stringify({mailbox_name:x})});if(A.status===409){let H=await A.text().catch(()=>"");if(I.tolerate409!==!1&&dm(H)==="mailbox_exists")return;throw um("create mailbox failed",A.status,H)}await R(A,"create mailbox failed")}async function i(x){return T(`${t}/mailboxes/${encodeURIComponent(x)}`,{method:"DELETE",headers:n},"delete mailbox failed")}async function a(x){let I=x.attachments??[],A=await T(`${t}/mailboxes/${encodeURIComponent(x.mailbox)}/messages`,{method:"POST",headers:{...n,"content-type":"application/json"},body:JSON.stringify({...x.subject===void 0?{}:{subject:x.subject},body:cm(x.body),attachments:I.map(cm)})},"allocate message failed"),H=[{target:A.body,bytes:x.body.bytes},...A.attachments.map((L,w)=>({target:L,bytes:I[w].bytes}))];for(let{target:L,bytes:w}of H){let b=new FormData;for(let[D,W]of Object.entries(L.fields))b.append(D,W);b.append("file",new Blob([new Uint8Array(w)],{type:L.content_type}),L.name);let N=await r(L.upload_url,{method:"POST",body:b});await R(N,`upload failed for ${L.name}`)}return await T(g$(t,A.finalize_url),{method:"POST",headers:n},"finalize message failed"),A.seq}async function c(x,I={}){let A=new URLSearchParams;if(I.status&&A.set("status",I.status),I.after!==void 0&&A.set("after",String(I.after)),I.wait_s!==void 0){if(!Number.isInteger(I.wait_s)||I.wait_s<0||I.wait_s>20)throw new Error("wait_s must be an integer from 0 through 20");A.set("wait_s",String(I.wait_s))}let H=A.size>0?`?${A.toString()}`:"",L=await T(`${t}/mailboxes/${encodeURIComponent(x)}/messages${H}`,{headers:n},"list messages failed");return{messages:L.messages,next_after:L.next_after}}async function l(x={}){let I=new URLSearchParams;if(x.limit!==void 0){if(!Number.isInteger(x.limit)||x.limit<1||x.limit>50)throw new Error("limit must be an integer from 1 through 50");I.set("limit",String(x.limit))}let A=I.size>0?`?${I.toString()}`:"";return T(`${t}/messages/recent${A}`,{headers:n},"get recent messages failed")}async function u(x,I){return T(`${t}/mailboxes/${encodeURIComponent(x)}/messages/${I}`,{headers:n},"get message failed")}async function d(x,I){let A=await u(x,I);return{...A,body:lm(A.body),attachments:A.attachments.map(lm)}}async function m(x,I){return T(`${t}/mailboxes/${encodeURIComponent(x)}/messages/${I}/thread`,{headers:n},"get thread failed")}async function f(x){let I=await r(x);return await R(I,"download failed"),new Uint8Array(await I.arrayBuffer())}async function p(x,I){await T(`${t}/mailboxes/${encodeURIComponent(x)}/messages/${I}`,{method:"DELETE",headers:n},"delete message failed")}async function h(x,I,A){return await T(`${t}/sites`,{method:"POST",headers:{...n,"content-type":"application/json"},body:JSON.stringify({site_name:x,site_uuid:I,mailbox:A})},"register site failed")}async function g(x){return await T(`${t}/sites/${encodeURIComponent(x)}`,{headers:n},"resolve site failed")}async function _(x={}){let I=new URLSearchParams;if(x.cursor!==void 0&&I.set("cursor",x.cursor),x.limit!==void 0){if(!Number.isInteger(x.limit)||x.limit<1||x.limit>50)throw new Error("limit must be an integer from 1 through 50");I.set("limit",String(x.limit))}let A=I.size>0?`?${I.toString()}`:"";return T(`${t}/sites${A}`,{headers:n},"list sites failed")}async function E(x,I){return T(`${t}/sites/name`,{method:"PUT",headers:{...n,"content-type":"application/json"},body:JSON.stringify({site:x,name:I})},"set site name failed")}async function y(x){return T(`${t}/sites/name`,{method:"DELETE",headers:{...n,"content-type":"application/json"},body:JSON.stringify({site:x})},"delete site name failed")}async function S(x){await T(`${t}/sites/${encodeURIComponent(x)}`,{method:"DELETE",headers:n},"delete site failed")}async function T(x,I,A){let H=await r(x,I);await R(H,A);try{return await H.json()}catch(L){throw new Error(`${A}: invalid JSON response: ${_$(L)}`)}}async function R(x,I){if(x.ok)return;let A=await x.text().catch(()=>"");throw um(I,x.status,A)}return{listMailboxes:o,createMailbox:s,deleteMailbox:i,sendMessage:a,listMessages:c,getRecentMessages:l,getMessage:u,getMessageMetadata:d,getThread:m,download:f,deleteMessage:p,registerSite:h,resolveSite:g,listSites:_,setSiteName:E,deleteSiteName:y,deleteSite:S}}function cm(e){return{name:e.name,size:e.bytes.byteLength,content_type:e.contentType}}function lm(e){return{name:e.name,size:e.size,content_type:e.content_type}}function um(e,t,r){return new Wt(e,t,r,dm(r))}function dm(e){try{let t=JSON.parse(e);return typeof t.error=="string"?t.error:void 0}catch{return}}function g$(e,t){return/^https?:\/\//i.test(t)?t:`${e}${t.startsWith("/")?"":"/"}${t}`}function _$(e){return e instanceof Error?e.message:String(e)}import{execFile as V$}from"node:child_process";import{existsSync as J$}from"node:fs";import{join as z$}from"node:path";import{promisify as K$}from"node:util";import{existsSync as mm}from"node:fs";import{createRequire as w$}from"node:module";import{dirname as y$}from"node:path";var sc=null;function E$(){return sc===null&&(sc=w$(import.meta.url)("node:sqlite").DatabaseSync),sc}var b$={1:"SQLITE_ERROR",2:"SQLITE_INTERNAL",3:"SQLITE_PERM",4:"SQLITE_ABORT",5:"SQLITE_BUSY",6:"SQLITE_LOCKED",7:"SQLITE_NOMEM",8:"SQLITE_READONLY",9:"SQLITE_INTERRUPT",10:"SQLITE_IOERR",11:"SQLITE_CORRUPT",12:"SQLITE_NOTFOUND",13:"SQLITE_FULL",14:"SQLITE_CANTOPEN",15:"SQLITE_PROTOCOL",16:"SQLITE_EMPTY",17:"SQLITE_SCHEMA",18:"SQLITE_TOOBIG",19:"SQLITE_CONSTRAINT",20:"SQLITE_MISMATCH",21:"SQLITE_MISUSE",22:"SQLITE_NOLFS",23:"SQLITE_AUTH",24:"SQLITE_FORMAT",25:"SQLITE_RANGE",26:"SQLITE_NOTADB",27:"SQLITE_NOTICE",28:"SQLITE_WARNING"},T$={261:"SQLITE_BUSY_RECOVERY",517:"SQLITE_BUSY_SNAPSHOT",773:"SQLITE_BUSY_TIMEOUT",262:"SQLITE_LOCKED_SHAREDCACHE",518:"SQLITE_LOCKED_VTAB",264:"SQLITE_READONLY_RECOVERY",520:"SQLITE_READONLY_CANTLOCK",776:"SQLITE_READONLY_ROLLBACK",1032:"SQLITE_READONLY_DBMOVED",1288:"SQLITE_READONLY_CANTINIT",1544:"SQLITE_READONLY_DIRECTORY",270:"SQLITE_CANTOPEN_NOTEMPDIR",526:"SQLITE_CANTOPEN_ISDIR",782:"SQLITE_CANTOPEN_FULLPATH",1038:"SQLITE_CANTOPEN_CONVPATH",1294:"SQLITE_CANTOPEN_DIRTYWAL",1550:"SQLITE_CANTOPEN_SYMLINK",275:"SQLITE_CONSTRAINT_CHECK",531:"SQLITE_CONSTRAINT_COMMITHOOK",787:"SQLITE_CONSTRAINT_FOREIGNKEY",1043:"SQLITE_CONSTRAINT_FUNCTION",1299:"SQLITE_CONSTRAINT_NOTNULL",1555:"SQLITE_CONSTRAINT_PRIMARYKEY",1811:"SQLITE_CONSTRAINT_TRIGGER",2067:"SQLITE_CONSTRAINT_UNIQUE",2323:"SQLITE_CONSTRAINT_VTAB",2579:"SQLITE_CONSTRAINT_ROWID",2835:"SQLITE_CONSTRAINT_PINNED",3091:"SQLITE_CONSTRAINT_DATATYPE"};function S$(e){return T$[e]??b$[e&255]??`SQLITE_UNKNOWN_${e}`}var v$="SQLite3 can only bind numbers, strings, bigints, buffers, and null";function Gt(e){if(e!==null&&typeof e=="object"){let t=e;if(typeof t.errcode=="number")throw t.code=S$(t.errcode),e;if(t.code==="ERR_INVALID_ARG_TYPE"&&/cannot be bound/.test(String(t.message)))throw new TypeError(v$);if(t.code==="ERR_INVALID_STATE"&&/database is not open/.test(String(t.message)))throw new TypeError("The database connection is not open")}throw e}function A$(){let e="unable to open database file";return Object.assign(new Error(e),{code:"SQLITE_CANTOPEN",errcode:14,errstr:e})}function fm(e){return e instanceof Uint8Array&&!Buffer.isBuffer(e)?Buffer.from(e.buffer,e.byteOffset,e.byteLength):e}function $$(e){if(e==null)return e;if(Array.isArray(e))return e.map(fm);if(typeof e=="object"){let t={};for(let[r,n]of Object.entries(e))t[r]=fm(n);return t}return e}function k$(e){if(e===null||typeof e!="object"||Array.isArray(e)||e instanceof Uint8Array)return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function qs(e){return e.map((t,r)=>{if(t===void 0)return null;if(r===0&&k$(t)){let n={};for(let[o,s]of Object.entries(t))n[o]=s===void 0?null:s;return n}return t})}var ic=class{handle;pluckMode=!1;arrayMode=!1;constructor(t){this.handle=t,this.handle.setAllowBareNamedParameters(!0),this.handle.setAllowUnknownNamedParameters(!0)}get source(){return this.handle.sourceSQL}run(...t){try{let r=this.handle.run(...qs(t));return{changes:Number(r.changes),lastInsertRowid:Number(r.lastInsertRowid)}}catch(r){Gt(r)}}get(...t){try{return this.project(this.handle.get(...qs(t)))}catch(r){Gt(r)}}all(...t){try{return this.handle.all(...qs(t)).map(r=>this.project(r))}catch(r){Gt(r)}}*iterate(...t){let r;try{r=this.handle.iterate(...qs(t))}catch(n){Gt(n)}for(;;){let n;try{n=r.next()}catch(o){Gt(o)}if(n.done)return;yield this.project(n.value)}}raw(t=!0){return this.arrayMode=t,this.handle.setReturnArrays(t||this.pluckMode),this}pluck(t=!0){return this.pluckMode=t,this.handle.setReturnArrays(t||this.arrayMode),this}project(t){let r=$$(t);return this.pluckMode&&Array.isArray(r)?r[0]:r}},ac=class{name;memory;readonly;handle;savepointId=0;constructor(t,r={}){let n=t===":memory:"||t==="";if(r.readonly===!0&&n)throw new TypeError("In-memory/temporary databases cannot be readonly");if(!n&&!mm(y$(t)))throw new TypeError("Cannot open database because the directory does not exist");if(r.fileMustExist===!0&&!n&&!mm(t))throw A$();this.name=t,this.memory=n,this.readonly=r.readonly===!0;try{this.handle=new(E$())(t,{readOnly:this.readonly,timeout:r.timeout??5e3,enableForeignKeyConstraints:r.foreignKeys??!0})}catch(o){Gt(o)}}get open(){return this.handle.isOpen}get inTransaction(){return this.handle.isTransaction}prepare(t){try{return new ic(this.handle.prepare(t))}catch(r){Gt(r)}}exec(t){try{return this.handle.exec(t),this}catch(r){Gt(r)}}pragma(t,r){let n=this.prepare(`PRAGMA ${t}`);return r?.simple===!0?n.pluck().get():n.all()}transaction(t){let r=o=>(...s)=>this.runTransaction(o,t,s),n=r("BEGIN");return n.default=r("BEGIN"),n.deferred=r("BEGIN DEFERRED"),n.immediate=r("BEGIN IMMEDIATE"),n.exclusive=r("BEGIN EXCLUSIVE"),n}serialize(){try{let t=this.handle.serialize();return Buffer.from(t.buffer,t.byteOffset,t.byteLength)}catch(t){Gt(t)}}close(){if(!this.handle.isOpen)return this;try{return this.handle.close(),this}catch(t){Gt(t)}}runTransaction(t,r,n){if(!this.inTransaction){this.exec(t);try{let s=r(...n);return this.exec("COMMIT"),s}catch(s){if(this.inTransaction)try{this.exec("ROLLBACK")}catch(i){if(!x$(i))throw i}throw s}}let o=`lmbee_sp_${this.savepointId+=1}`;this.exec(`SAVEPOINT ${o}`);try{let s=r(...n);return this.exec(`RELEASE ${o}`),s}catch(s){if(this.inTransaction)try{this.exec(`ROLLBACK TO ${o}`),this.exec(`RELEASE ${o}`)}catch(i){if(!R$(i))throw i}throw s}}};function x$(e){return e instanceof Error&&/cannot rollback - no transaction is active/i.test(e.message)}function R$(e){return e instanceof Error&&/no such savepoint:/i.test(e.message)}var yt=ac;import{existsSync as lc,lstatSync as N$,mkdirSync as I$,readFileSync as wm,realpathSync as pm}from"node:fs";import{basename as L$,dirname as uc,isAbsolute as C$,join as O$,relative as D$,resolve as hm}from"node:path";import{fileURLToPath as M$}from"node:url";var ym=O$(uc(M$(import.meta.url)),"schema.sql");function Lo(e){if(e!==void 0&&e!=="")return e;let t=process.env.LMBEE_DB;if(t)return t;throw new Error("No lmbee database selected: pass an explicit database path or set LMBEE_DB to the intended existing database. The retired ~/.lmbee/state.db default is no longer used.")}function P$(e){if(e.startsWith("~"))throw new Error(`Refusing to open the lmbee database at "${e}": lmbee does not expand "~" in database paths, so this would be created as a literal directory named "~" under the current working directory. Use an absolute path instead (for example ~/.lmbee/state.db). Note for systemd units: Environment= expands neither "~" nor "$HOME", so write the absolute path literally there too.`)}function U$(e,t){if(!(e===":memory:"||lc(e)))throw new Error(`Refusing to create the lmbee database at "${e}": ${t} points at non-existent "${e}", and a typo is indistinguishable from a fresh install. To provision a new database here, \`touch "${e}"\` first, then retry, or point ${t} at an existing database.`)}function F$(e){e.transaction(()=>{let r=e.prepare("PRAGMA table_info(queue)").all();if(r.length===0)return;let n=new Set(r.map(s=>s.name));n.has("subject_id")||e.exec("ALTER TABLE queue ADD COLUMN subject_id TEXT"),n.has("dedupe_key")||e.exec("ALTER TABLE queue ADD COLUMN dedupe_key TEXT"),e.prepare(`SELECT name FROM pragma_index_list('queue') WHERE "unique" = 1 AND partial = 0`).all().some(s=>{let i=e.prepare("SELECT name FROM pragma_index_info(?) ORDER BY seqno").all(s.name);return i.length===1&&i[0].name==="dedupe_key"})||e.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_queue_dedupe_key ON queue(dedupe_key)"),n.has("delivered_via_escalation")||e.exec("ALTER TABLE queue ADD COLUMN delivered_via_escalation INTEGER NOT NULL DEFAULT 0"),n.has("escalation_claimed_ts")||e.exec("ALTER TABLE queue ADD COLUMN escalation_claimed_ts TEXT"),n.has("escalation_claim_token")||e.exec("ALTER TABLE queue ADD COLUMN escalation_claim_token TEXT"),n.has("escalation_only")||e.exec("ALTER TABLE queue ADD COLUMN escalation_only INTEGER NOT NULL DEFAULT 0"),n.has("admission_fingerprint")||e.exec("ALTER TABLE queue ADD COLUMN admission_fingerprint TEXT"),n.has("expects_response")||e.exec("ALTER TABLE queue ADD COLUMN expects_response INTEGER NOT NULL DEFAULT 0"),n.has("to_alias")||e.exec("ALTER TABLE queue ADD COLUMN to_alias TEXT"),n.has("retracted_ts")||e.exec("ALTER TABLE queue ADD COLUMN retracted_ts TEXT"),n.has("retracted_reason")||e.exec("ALTER TABLE queue ADD COLUMN retracted_reason TEXT"),n.has("retraction_notice")||e.exec("ALTER TABLE queue ADD COLUMN retraction_notice INTEGER NOT NULL DEFAULT 0"),n.has("in_reply_to")||e.exec("ALTER TABLE queue ADD COLUMN in_reply_to INTEGER"),n.has("operator_priority")||e.exec("ALTER TABLE queue ADD COLUMN operator_priority INTEGER NOT NULL DEFAULT 0"),n.has("merged_into_id")||e.exec("ALTER TABLE queue ADD COLUMN merged_into_id INTEGER")}).immediate()}function q$(e){e.transaction(()=>{let r=e.prepare("PRAGMA table_info(team_progress)").all();if(r.length===0)return;let n=new Set(r.map(o=>o.name));n.has("last_miniplayer_reply_hash")||e.exec("ALTER TABLE team_progress ADD COLUMN last_miniplayer_reply_hash TEXT"),n.has("blocked_surfaced_ts")||e.exec("ALTER TABLE team_progress ADD COLUMN blocked_surfaced_ts TEXT"),n.has("last_escalation_attempt_ts")||e.exec("ALTER TABLE team_progress ADD COLUMN last_escalation_attempt_ts TEXT"),n.has("escalation_attempt_count")||e.exec("ALTER TABLE team_progress ADD COLUMN escalation_attempt_count INTEGER NOT NULL DEFAULT 0"),n.has("fault_surfaced_ts")||e.exec("ALTER TABLE team_progress ADD COLUMN fault_surfaced_ts TEXT"),n.has("epic_closed_surfaced_ts")||e.exec("ALTER TABLE team_progress ADD COLUMN epic_closed_surfaced_ts TEXT"),n.has("quota_exhausted_last_seen_ts")||e.exec("ALTER TABLE team_progress ADD COLUMN quota_exhausted_last_seen_ts TEXT"),n.has("quota_exhausted_message")||e.exec("ALTER TABLE team_progress ADD COLUMN quota_exhausted_message TEXT"),n.has("miniplayer_verdict_label")||e.exec("ALTER TABLE team_progress ADD COLUMN miniplayer_verdict_label TEXT"),n.has("miniplayer_verdict_reason")||e.exec("ALTER TABLE team_progress ADD COLUMN miniplayer_verdict_reason TEXT"),n.has("miniplayer_verdict_ts")||e.exec("ALTER TABLE team_progress ADD COLUMN miniplayer_verdict_ts TEXT"),n.has("miniplayer_verdict_input_hash")||e.exec("ALTER TABLE team_progress ADD COLUMN miniplayer_verdict_input_hash TEXT"),n.has("miniplayer_verdict_structural_hash")||e.exec("ALTER TABLE team_progress ADD COLUMN miniplayer_verdict_structural_hash TEXT"),n.has("holder_watch_pid")||e.exec("ALTER TABLE team_progress ADD COLUMN holder_watch_pid INTEGER"),n.has("holder_watch_started_at")||e.exec("ALTER TABLE team_progress ADD COLUMN holder_watch_started_at TEXT"),n.has("holder_watch_cpu_ticks")||e.exec("ALTER TABLE team_progress ADD COLUMN holder_watch_cpu_ticks INTEGER"),n.has("holder_watch_observed_at")||e.exec("ALTER TABLE team_progress ADD COLUMN holder_watch_observed_at TEXT"),n.has("holder_watch_low_cpu_streak")||e.exec("ALTER TABLE team_progress ADD COLUMN holder_watch_low_cpu_streak INTEGER"),n.has("hung_holder_flagged_ts")||e.exec("ALTER TABLE team_progress ADD COLUMN hung_holder_flagged_ts TEXT"),n.has("hung_holder_reason")||e.exec("ALTER TABLE team_progress ADD COLUMN hung_holder_reason TEXT"),n.has("last_cli_activity_ts")||e.exec("ALTER TABLE team_progress ADD COLUMN last_cli_activity_ts TEXT")}).immediate()}function j$(e){e.transaction(()=>{let r=e.prepare("PRAGMA table_info(cron_jobs)").all();if(r.length===0)return;let n=new Set(r.map(o=>o.name));n.has("last_fire_error")||e.exec("ALTER TABLE cron_jobs ADD COLUMN last_fire_error TEXT"),n.has("running_systemd_unit")||e.exec("ALTER TABLE cron_jobs ADD COLUMN running_systemd_unit TEXT"),n.has("timezone")||e.exec("ALTER TABLE cron_jobs ADD COLUMN timezone TEXT"),n.has("provider")||e.exec("ALTER TABLE cron_jobs ADD COLUMN provider TEXT"),n.has("model")||e.exec("ALTER TABLE cron_jobs ADD COLUMN model TEXT"),n.has("working_directory")||e.exec("ALTER TABLE cron_jobs ADD COLUMN working_directory TEXT"),n.has("escalation_owner")||e.exec("ALTER TABLE cron_jobs ADD COLUMN escalation_owner TEXT"),n.has("session_teamfile")||e.exec("ALTER TABLE cron_jobs ADD COLUMN session_teamfile TEXT"),n.has("session_alias")||e.exec("ALTER TABLE cron_jobs ADD COLUMN session_alias TEXT"),n.has("session_seeded_at")||e.exec("ALTER TABLE cron_jobs ADD COLUMN session_seeded_at TEXT"),n.has("session_generation")||e.exec("ALTER TABLE cron_jobs ADD COLUMN session_generation INTEGER NOT NULL DEFAULT 0")}).immediate()}function H$(e){e.transaction(()=>{let r=e.prepare("PRAGMA table_info(entities)").all();if(r.length===0)return;let n=new Set(r.map(o=>o.name));n.has("delivered_ts")||e.exec("ALTER TABLE entities ADD COLUMN delivered_ts TEXT"),n.has("review_time")||e.exec("ALTER TABLE entities ADD COLUMN review_time TEXT"),n.has("needs_review")||e.exec("ALTER TABLE entities ADD COLUMN needs_review INTEGER NOT NULL DEFAULT 0 CHECK(needs_review IN (0,1))"),n.has("review_reason")||e.exec("ALTER TABLE entities ADD COLUMN review_reason TEXT"),n.has("review_input_hash")||e.exec("ALTER TABLE entities ADD COLUMN review_input_hash TEXT"),n.has("hold_until")||e.exec("ALTER TABLE entities ADD COLUMN hold_until TEXT"),n.has("hold_reason")||e.exec("ALTER TABLE entities ADD COLUMN hold_reason TEXT"),n.has("blocked_on")||e.exec("ALTER TABLE entities ADD COLUMN blocked_on TEXT")}).immediate()}function B$(e){e.transaction(()=>{let r=e.prepare("PRAGMA table_info(mail_ledger)").all();if(r.length===0)return;let n=new Set(r.map(o=>o.name));n.has("ack_sent_ts")||e.exec("ALTER TABLE mail_ledger ADD COLUMN ack_sent_ts TEXT"),n.has("delivery_error")||e.exec("ALTER TABLE mail_ledger ADD COLUMN delivery_error TEXT"),n.has("delivery_error_ts")||e.exec("ALTER TABLE mail_ledger ADD COLUMN delivery_error_ts TEXT")}).immediate()}function dc(e){let t=process.env.LMBEE_TEST_DB_ROOT;if(!t||e===":memory:")return;let r=[],n=hm(e);for(;N$(n,{throwIfNoEntry:!1})===void 0;){r.unshift(L$(n));let i=uc(n);if(i===n)throw new Error("Cannot resolve test database path");n=i}let o=hm(pm(n),...r),s=D$(pm(t),o);if(s===".."||s.startsWith("../")||s.startsWith("..\\")||C$(s))throw new Error(`Database path is outside the test database root: ${e}`)}function gm(e){let t=o=>e.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(o)!==void 0,r=o=>e.prepare(`PRAGMA table_info(${o})`).all(),n;for(let o of["queue_responses","chat_tasks","chat_messages","chat_message_task_reassignments"])if(t(o)){n=`legacy table '${o}'`;break}if(n===void 0&&t("answers")){let o=new Set(r("answers").map(s=>s.name));o.has("request_queue_id")?n="legacy column 'answers.request_queue_id'":o.has("superseded_at")||(n="legacy 'answers' shape: missing column 'superseded_at'")}if(n===void 0&&t("queue")){let o=r("queue"),s=new Set(o.map(i=>i.name));s.has("team")?n="legacy column 'queue.team'":s.has("to_id")?o.some(i=>i.name==="from_id"&&i.notnull!==1)?n="legacy 'queue' shape: from_id is still nullable":s.has("restart_nudge_sent_ts")&&(n="legacy column 'queue.restart_nudge_sent_ts'"):n="legacy 'queue' shape: missing column 'to_id'"}if(n===void 0&&t("cron_jobs")){let o=e.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'cron_jobs'").get();(o===void 0||!o.sql.includes("'miniplayer'"))&&(n="legacy 'cron_jobs' CHECK constraint predates 'miniplayer'")}if(n===void 0&&t("cron_jobs")){let o=e.prepare("SELECT id, action_payload FROM cron_jobs WHERE action_kind = 'enqueue'").all();for(let s of o){let i;try{i=JSON.parse(s.action_payload)}catch{i=void 0}let a=typeof i=="object"&&i!==null?i.prompt:void 0;if(typeof a!="string"||a.trim().length===0){n=`legacy 'cron_jobs' enqueue payload (id ${s.id}) predates the 'prompt' vocabulary`;break}}}if(n===void 0&&t("team_progress")&&new Set(r("team_progress").map(s=>s.name)).has("last_scan_head")&&(n="legacy column 'team_progress.last_scan_head'"),n===void 0&&t("cron_runs")&&(new Set(r("cron_runs").map(s=>s.name)).has("execution_state")||(n="legacy 'cron_runs' shape: missing column 'execution_state'")),n===void 0&&t("rate_limit_policy_log")){let o=e.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'rate_limit_policy_log'").get();(o===void 0||!o.sql.includes("'confirmed_would_fire_policy_disabled'"))&&(n="legacy 'rate_limit_policy_log' CHECK constraint predates 'confirmed_would_fire_policy_disabled'")}if(n===void 0&&t("rate_limit_policy_arm")&&(new Set(r("rate_limit_policy_arm").map(s=>s.name)).has("armed_used_fraction")||(n="legacy 'rate_limit_policy_arm' shape: missing column 'armed_used_fraction'")),n!==void 0)throw new Error(`Refusing to open this lmbee state.db: abandoned pre-v14 lmbee schema shape (${n}). Per the operator's 2026-10-01 shared-database decision, lmbee now shares lmctl's state.db and every pre-existing lmbee-only database is abandoned -- there is no data migration, ever. Do not remove a shared lmctl database. Check LMBEE_DB and the database ownership; point lmbee at the intended compatible database. Preserve this file for operator review.`)}var js=62;function _m(e){let t=e.pragma("user_version",{simple:!0});if(t<=js)return;let r;if(e.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'schema_meta'").get()!==void 0){let o=new Set(e.prepare("PRAGMA table_info(schema_meta)").all().map(s=>s.name));if(o.has("key")&&o.has("value")){let s=e.prepare("SELECT value FROM schema_meta WHERE key = 'min_reader_version'").get();typeof s?.value=="string"&&(r=s.value)}}let n;if(r===void 0)n="schema_meta.min_reader_version is absent";else if(!/^[1-9]\d*$/.test(r))n=`schema_meta.min_reader_version=${JSON.stringify(r)} is malformed (not a canonical decimal integer)`;else if(Number(r)>js)n=`schema_meta.min_reader_version=${r} declares a breaking floor above ${js}`;else return;throw new Error(`Refusing to open the shared state.db: it was migrated by a newer lmctl with breaking changes (user_version=${t} exceeds the newest lmctl schema version this lmbee build understands, ${js}, and ${n}). Upgrade lmbee to a build that understands the newer lmctl schema before opening this database again. lmbee never writes user_version or schema_meta, so the file is untouched.`)}var cc;function W$(){return cc===void 0&&(cc=[...wm(ym,"utf8").matchAll(/CREATE TABLE IF NOT EXISTS (\w+)/gi)].map(t=>t[1])),cc}function G$(e,t){let r=new Set(e.prepare("SELECT name FROM sqlite_master WHERE type = 'table'").all().map(o=>o.name)),n=W$().filter(o=>!r.has(o));if(n.length!==0)throw new Error(`Refusing a read-only open of "${t}": required lmbee schema is missing (no table${n.length===1?"":"s"}: ${n.join(", ")}), and a read-only handle cannot create it. Run any writable lmbee command (or start the daemon) once against this database to provision it, then retry.`)}function Hs(e,t={}){let r=Lo(e);P$(r);let n=!e&&typeof process.env.LMBEE_DB=="string"&&process.env.LMBEE_DB!=="";if(n&&U$(r,"LMBEE_DB"),dc(r),t.readOnly&&r===":memory:")throw new Error("Refusing a read-only open of ':memory:': an in-memory database starts empty on every open, so the required lmbee schema can never be present and a read-only handle cannot create it.");if(t.readOnly&&r!==":memory:"){if(!lc(r))throw new Error(`Refusing a read-only open of "${r}": the file does not exist, so the required lmbee schema is missing. Run any writable lmbee command (or start the daemon) once against this database to provision it, then retry.`);let a=new yt(r,{readonly:!0,fileMustExist:!0});try{gm(a),_m(a),a.pragma("busy_timeout = 5000"),t.requireLmbeeSchema!==!1&&G$(a,r)}catch(c){throw a.close(),c}return{path:r,db:a,close:()=>a.close()}}if(r!==":memory:"){let a=uc(r);lc(a)||I$(a,{recursive:!0})}let o=new yt(r,n?{fileMustExist:!0}:void 0);try{gm(o),_m(o)}catch(a){throw o.close(),a}o.pragma("journal_mode = WAL"),o.pragma("busy_timeout = 5000");let s=wm(ym,"utf8"),i=o.transaction(()=>{F$(o),q$(o),B$(o),H$(o),j$(o),o.exec(s);let a=o.pragma("table_info(on_demand_launches)");a.some(c=>c.name==="phase")||(o.exec("ALTER TABLE on_demand_launches ADD COLUMN phase TEXT NOT NULL DEFAULT 'reserved' CHECK(phase IN ('reserved', 'dispatching', 'worker_adopted', 'uncertain'))"),o.exec("UPDATE on_demand_launches SET phase = 'uncertain' WHERE state = 'adopted' OR run_id IS NOT NULL")),a.some(c=>c.name==="worker_pid")||o.exec("ALTER TABLE on_demand_launches ADD COLUMN worker_pid INTEGER"),a.some(c=>c.name==="worker_start")||o.exec("ALTER TABLE on_demand_launches ADD COLUMN worker_start TEXT"),a.some(c=>c.name==="receipt_path")||o.exec("ALTER TABLE on_demand_launches ADD COLUMN receipt_path TEXT")});try{i.immediate()}catch(a){throw o.close(),a}return{path:r,db:o,close:()=>o.close()}}function qe(e,t){return e.prepare("SELECT * FROM team_state WHERE team = ?").get(t)??null}function Em(e,t){let r=qe(e,t);return r===null?{kind:"never-observed"}:{kind:"observed",value:r,observedAt:r.last_ts,changedAt:r.changed_ts}}function mr(e,t,r,n){let o=new Date(n).toISOString(),s=qe(e,t),i=s&&s.status===r?s.changed_ts:o;e.prepare(`INSERT INTO team_state(team, status, changed_ts, last_ts) VALUES (?, ?, ?, ?)
|
|
67
|
+
ON CONFLICT(team) DO UPDATE SET status = excluded.status, changed_ts = excluded.changed_ts, last_ts = excluded.last_ts`).run(t,r,i,o)}function ot(e,t,r,n,o={}){e.prepare("INSERT INTO events(ts, scan, team, status, note) VALUES (?, ?, ?, ?, ?)").run(new Date(n).toISOString(),o.scan??null,t,r,o.note??null)}function Bs(e,t,r,n){return e.prepare("SELECT * FROM events WHERE status = ? AND ts >= ? ORDER BY id DESC LIMIT ?").all(t,r,n)}function se(e,t){return e.prepare("SELECT * FROM team_progress WHERE team = ?").get(t)??null}function bm(e,t,r,n,o=n){let s=se(e,t),i=s&&s.progress_status===r?s.progress_changed_ts:o;e.prepare(`INSERT INTO team_progress(team, progress_status, progress_changed_ts, last_scan_ts)
|
|
68
68
|
VALUES (?, ?, ?, ?)
|
|
69
69
|
ON CONFLICT(team) DO UPDATE SET
|
|
70
70
|
progress_status = excluded.progress_status,
|
|
@@ -120,84 +120,84 @@ Appkey saved to ${p.appkeyPath} (0600)
|
|
|
120
120
|
quota_exhausted_message = excluded.quota_exhausted_message`).run(t,r,n)}function Hm(e,t){e.prepare("UPDATE team_progress SET quota_exhausted_last_seen_ts = NULL, quota_exhausted_message = NULL WHERE team = ?").run(t)}function Bm(e,t,r){e.prepare(`INSERT INTO team_progress(team, last_escalation_attempt_ts, escalation_attempt_count) VALUES (?, ?, 1)
|
|
121
121
|
ON CONFLICT(team) DO UPDATE SET
|
|
122
122
|
last_escalation_attempt_ts = excluded.last_escalation_attempt_ts,
|
|
123
|
-
escalation_attempt_count = team_progress.escalation_attempt_count + 1`).run(t,r)}var Y$=
|
|
123
|
+
escalation_attempt_count = team_progress.escalation_attempt_count + 1`).run(t,r)}var Y$=K$(V$);function Q$(e){return J$(z$(e,".git"))}async function wc(e,t){try{let r=t.replace(/\.\d{3}Z$/,"Z"),{stdout:n}=await Y$("find",[e,"(","-name",".git","-o","-name","node_modules",")","-prune","-o","-type","f","-newermt",r,"-print","-quit"],{timeout:15e3});return n.trim().length>0}catch{return!1}}async function X$(e,t){if(t===null)return"ACTIVE";for(let r of e)if(await wc(r,t))return"ACTIVE";return e.every(r=>!Q$(r))?"NOT_A_REPO":"UNKNOWN"}async function yc(e,t,r,n=Date.now()){let o=t.folders&&t.folders.length>0?t.folders:[t.repoPath],s=se(e,r),i=await X$(o,s?.last_scan_ts??null);return bm(e,r,i,new Date(n).toISOString(),new Date().toISOString()),se(e,r)}import{existsSync as Ac,readFileSync as Zm,realpathSync as fk,statSync as pk}from"node:fs";import{join as Qm,resolve as Js}from"node:path";var Z$=/^[a-z0-9-]+$/;function Ec(e){if(e.length>128||!Z$.test(e))throw new Error("site-id must match [a-z0-9-]+");return e}function Wm(e){let t=e.split(":");if(t.length!==3)throw new Error("logical address must be site-id:team-id:alias");let[r,n,o]=t;return Ec(r),vn(n,"team-id"),vn(o,"alias"),{site:r,team:n,alias:o}}function vn(e,t,r=!1){if(!r&&!e||e.length>128||e!==e.trim()||ek(e))throw new Error(`${t} must ${r?"":"be non-empty and "}contain no colons or control characters`);return e}function ek(e){if(e.includes(":"))return!0;for(let t of e){let r=t.charCodeAt(0);if(r<=31||r===127)return!0}return!1}import{link as nk,mkdir as ok,readFile as sk,rename as ik,unlink as ak,writeFile as ck}from"node:fs/promises";import{randomUUID as lk}from"node:crypto";import{homedir as tk}from"node:os";import{dirname as rk,join as Gm}from"node:path";function bc(e=process.env){let t=e.LMAUTO_DB?.trim();return t?rk(t):Gm(e.HOME?.trim()||tk(),".lmauto")}function Ws(e=process.env){return Gm(bc(e),"site-uuid")}var Vm=/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,uk={readText:e=>sk(e,"utf8"),mkdir:async e=>{await ok(e,{recursive:!0})},writePrivate:(e,t)=>ck(e,t,{flag:"wx",mode:384}),link:nk,rename:ik,remove:ak};async function Jm(e={}){let t=e.env??process.env,r=e.io??uk,n=Ws(t),o=await Vs(r,n);if(o.value)return o.value;await r.mkdir(bc(t));let s={io:r,randomUuid:e.randomUuid??lk,pid:e.pid??process.pid,sleep:e.sleep??(i=>new Promise(a=>setTimeout(a,i)))};return o.exists?mk(s,n):dk(s,n)}async function dk(e,t){let r=await zm(e,t);try{try{return await e.io.link(r.temporary,t),r.candidate}catch(n){if(n.code!=="EEXIST")throw n;return Tc(e,t)}}finally{await Gs(e.io,r.temporary)}}async function mk(e,t){let r=`${t}.repair.lock`;try{await e.io.writePrivate(r,Buffer.from(`${e.pid}
|
|
124
124
|
`))}catch(i){if(i.code!=="EEXIST")throw i;return Tc(e,t)}let n,o,s=!1;try{n=await zm(e,t),o=`${t}.${e.pid}.${n.candidate}.corrupt`;let i=await Vs(e.io,t);if(i.value)return i.value;if(i.exists)try{await e.io.rename(t,o),s=!0}catch(a){if(a.code!=="ENOENT")throw a}try{return await e.io.link(n.temporary,t),n.candidate}catch(a){if(a.code==="EEXIST")return Tc(e,t);let c=await Vs(e.io,t);throw s&&!c.exists&&(await e.io.rename(o,t),s=!1),a}}finally{n&&await Gs(e.io,n.temporary),s&&o&&await Gs(e.io,o),await Gs(e.io,r)}}async function zm(e,t){let r=e.randomUuid().toLowerCase();if(!Vm.test(r))throw new Error("random UUID generator returned an invalid site identity");let n=`${t}.${e.pid}.${r}.tmp`;return await e.io.writePrivate(n,Buffer.from(`${r}
|
|
125
|
-
`)),{candidate:r,temporary:n}}async function Tc(e,t){for(let r=0;r<100;r+=1){let n=await Vs(e.io,t);if(n.value)return n.value;await e.sleep(10)}throw new Error(`timed out waiting for site identity winner at ${t}`)}async function Vs(e,t){try{let r=(await e.readText(t)).trim();return Vm.test(r)?{exists:!0,value:r.toLowerCase()}:{exists:!0}}catch(r){if(r.code==="ENOENT")return{exists:!1};throw r}}async function Gs(e,t){try{await e.remove(t)}catch(r){if(r.code!=="ENOENT")throw r}}function Sc(e){let t=e;if(typeof e=="string")try{t=JSON.parse(e)}catch{return}if(!t||typeof t!="object"||Array.isArray(t))return;let r=t;if(typeof r.pid!="number"||!Number.isSafeInteger(r.pid)||r.pid<1||typeof r.ownerLabel!="string"||typeof r.startedAt!="string")return;let n=typeof r.pidStartTicks=="number"&&Number.isFinite(r.pidStartTicks)?r.pidStartTicks:null,o=vc(r.bootId)?r.bootId:null;return{pid:r.pid,ownerLabel:r.ownerLabel,startedAt:r.startedAt,pidStartTicks:n,bootId:o}}function vc(e){return typeof e=="string"&&/^[0-9a-f-]{36}$/i.test(e)}function An(e){return`lmauto-site-${e}`}function
|
|
126
|
-
`),null;let l=s||"default",u=a?a.split(",").map(m=>m.trim()).filter(m=>m.length>0):[],d=u.length>0?ef(n,u):[Js(n)];return{channel:"local",name:r,repoPath:n,leadAlias:o,promptName:l,description:i??"",autoNudge:l!=="on-demand",folders:d,coordinator:c==="true"}}function
|
|
125
|
+
`)),{candidate:r,temporary:n}}async function Tc(e,t){for(let r=0;r<100;r+=1){let n=await Vs(e.io,t);if(n.value)return n.value;await e.sleep(10)}throw new Error(`timed out waiting for site identity winner at ${t}`)}async function Vs(e,t){try{let r=(await e.readText(t)).trim();return Vm.test(r)?{exists:!0,value:r.toLowerCase()}:{exists:!0}}catch(r){if(r.code==="ENOENT")return{exists:!1};throw r}}async function Gs(e,t){try{await e.remove(t)}catch(r){if(r.code!=="ENOENT")throw r}}function Sc(e){let t=e;if(typeof e=="string")try{t=JSON.parse(e)}catch{return}if(!t||typeof t!="object"||Array.isArray(t))return;let r=t;if(typeof r.pid!="number"||!Number.isSafeInteger(r.pid)||r.pid<1||typeof r.ownerLabel!="string"||typeof r.startedAt!="string")return;let n=typeof r.pidStartTicks=="number"&&Number.isFinite(r.pidStartTicks)?r.pidStartTicks:null,o=vc(r.bootId)?r.bootId:null;return{pid:r.pid,ownerLabel:r.ownerLabel,startedAt:r.startedAt,pidStartTicks:n,bootId:o}}function vc(e){return typeof e=="string"&&/^[0-9a-f-]{36}$/i.test(e)}function An(e){return`lmauto-site-${e}`}function Km(e){return`${An(e)}-exec`}function Ym(e,t){let r=An(e);if(t!==r)throw new Error(`peer mailbox mismatch for ${e}: registered ${t}, expected ${r}`);return r}function B(e){return e.channel==="local"}function zs(e,t){let r=e.find(n=>n.name===t);return r?B(r)?{key:t,kind:"local",name:r.name,repoPath:r.repoPath,leadAlias:r.leadAlias,channel:r.channel,currentSession:null,historicalCoverage:"unavailable"}:{key:t,kind:"remote",name:r.name,channel:r.channel,peerSite:r.peerSite,alias:r.alias,currentSession:null,historicalCoverage:"unavailable"}:{key:t,kind:"unresolved",currentSession:null,historicalCoverage:"unavailable"}}function Co(e){let t=[];for(let r of e.split(/\r?\n/)){let n=r.trim();if(!n||n.startsWith("#"))continue;let o=n.split(/\t+/).map(h=>h.trim());if(o.length<3)continue;let[s,i,a,c,l,u,d]=o,m=c||"default",f=u?u.split(",").map(h=>h.trim()).filter(h=>h.length>0):[],p=f.length>0?ef(i,f):[Js(i)];t.push({channel:"local",name:s,repoPath:i,leadAlias:a,promptName:m,description:l??"",autoNudge:m!=="on-demand",folders:p,coordinator:d==="true"})}return t}function ef(e,t){let r=new Set,n=[];for(let o of t){let s=Js(e,o);r.has(s)||(r.add(s),n.push(s))}return n}var hk=/^_TEAM_(\s|$)/,gk=/(\w+)=(?:"([^"]*)"|([\S]*))/g;function _k(e){let t={};for(let m of e.matchAll(gk)){let f=m[1];f in t||(t[f]=m[2]!==void 0?m[2]:m[3])}if(t.channel==="lmmail")return wk(t,e);let{name:r,repo:n,lead:o,prompt:s,desc:i,folders:a,coordinator:c}=t;if(!r||!n||!o)return process.stderr.write(`teams-conf: skipping malformed _TEAM_ line (missing name/repo/lead): ${e}
|
|
126
|
+
`),null;let l=s||"default",u=a?a.split(",").map(m=>m.trim()).filter(m=>m.length>0):[],d=u.length>0?ef(n,u):[Js(n)];return{channel:"local",name:r,repoPath:n,leadAlias:o,promptName:l,description:i??"",autoNudge:l!=="on-demand",folders:d,coordinator:c==="true"}}function wk(e,t){let{peer_site:r,team:n,alias:o}=e;if(!r||!n||!o)return process.stderr.write(`teams-conf: skipping malformed remote _TEAM_ line (missing peer_site/team/alias): ${t}
|
|
127
127
|
`),null;for(let[s,i]of[["peer_site",r],["team",n],["alias",o]])try{vn(i,s)}catch(a){return process.stderr.write(`teams-conf: skipping remote _TEAM_ line -- ${a instanceof Error?a.message:String(a)}: ${t}
|
|
128
|
-
`),null}return{channel:"lmmail",name:n,peerSite:r,alias:o}}var
|
|
129
|
-
ON CONFLICT(path) DO UPDATE SET label = excluded.label`).run(t,r,new Date().toISOString())}function kc(e){return e.prepare("SELECT * FROM sources ORDER BY id").all()}function
|
|
130
|
-
`)){if(!
|
|
128
|
+
`),null}return{channel:"lmmail",name:n,peerSite:r,alias:o}}var yk=/^(`{3,}|~{3,})/;function $c(e){let t=[],r=null;for(let n of e.split(/\r?\n/)){let o=n.trim(),s=yk.exec(o);if(s){let a=s[1];r===null?r={char:a[0],len:a.length}:a[0]===r.char&&a.length>=r.len&&o.slice(a.length).trim()===""&&(r=null);continue}if(r!==null||!hk.test(o))continue;let i=_k(o);i&&t.push(i)}return t}function Xm(e){return e.toLowerCase().endsWith(".md")}function Ek(e,t){let r=new Set,n=[];for(let o of[e,...t])if(!(!o||r.has(o))&&(r.add(o),!!Ac(o))){try{if(!pk(o).isFile())continue}catch{continue}n.push(o)}return n}function bk(e,t=[]){let r=Ek(e,t),n=new Map,o=s=>{try{return Zm(s,"utf8")}catch{return null}};for(let s of r){if(!Xm(s))continue;let i=o(s);if(i!==null)for(let a of $c(i))n.has(a.name)||n.set(a.name,a)}for(let s of r){if(Xm(s))continue;let i=o(s);if(i!==null)for(let a of Co(i))n.has(a.name)||n.set(a.name,a)}return[...n.values()]}function Ks(e,t,r){e.prepare(`INSERT INTO sources(path, label, added_ts) VALUES (?, ?, ?)
|
|
129
|
+
ON CONFLICT(path) DO UPDATE SET label = excluded.label`).run(t,r,new Date().toISOString())}function kc(e){return e.prepare("SELECT * FROM sources ORDER BY id").all()}function Ys(e,t){e.prepare("DELETE FROM sources WHERE path = ?").run(t)}function Tk(e){let t=Js(e);return Ac(t)?fk(t):null}function Q(e){let t=Tk(Qm(e.repoPath,`${e.name}.lmctl`));if(t)return t;throw Ac(e.repoPath)?new Error(`resolveTeamfilePath: cannot resolve a teamfile for team "${e.name}" -- expected "${Qm(e.repoPath,`${e.name}.lmctl`)}" to exist. teams.conf has no explicit teamfile-path column -- fix by naming the teamfile "<name>.lmctl" under repo_path.`):new Error(`resolveTeamfilePath: repo_path "${e.repoPath}" for team "${e.name}" does not exist`)}var Sk=/^_MEMBER_(\s|$)/,vk=/(\w+)=(?:"([^"]*)"|([\S]*))/g;function Vt(e,t){return Rc(e).find(r=>r.alias===t)?.provider??null}function xc(e){return Rc(e).filter(t=>t.sessionid!==void 0&&t.sessionid.length>0).length}function tn(e){return Rc(e).filter(t=>t.alias!==void 0).map(t=>({alias:t.alias,provider:t.provider??null}))}function Rc(e){let t;try{t=Zm(Q(e),"utf8")}catch{return[]}let r=[];for(let n of t.split(`
|
|
130
|
+
`)){if(!Sk.test(n.trim()))continue;let o={};for(let s of n.matchAll(vk)){let i=s[1];o[i]=s[2]!==void 0?s[2]:s[3]}r.push({alias:o.alias,provider:o.provider,sessionid:o.sessionid})}return r}function rn(e,t){let r=kc(e).map(n=>n.path);return bk(t,r)}function $n(e){if(typeof e!="string")return null;let t=e.lastIndexOf(":");if(t===-1)return null;let r=e.slice(0,t),n=e.slice(t+1);return!r||!n?null:{teamfilePath:r,alias:n}}function kn(e,t){let r=$n(t);if(r===null||r.alias!==e.leadAlias)return!1;let n;try{n=Q(e)}catch{return!1}return n===r.teamfilePath}function je(e,t){return t.running.some(r=>kn(e,r.target))}function tf(e,t,r){return r.running.some(n=>{let o=$n(n.target);return o!==null&&o.alias===t&&o.teamfilePath===e})}function Ak(e,t,r){let n=new Set(e.filter(u=>je(u,t)).map(u=>u.name)),o=new Set(r??[]),s=r===null,i=[...o].filter(u=>!n.has(u)).sort(),a=[...n].filter(u=>!o.has(u)).sort(),c=s||i.length>0,l=s?"first-run":i.length>0?`active->other: ${i.join(", ")}`:"nochange";return{first:s,active:[...n].sort(),wentIdle:i,newlyActive:a,wake:c,why:l}}function Qs(e){let t=e.prepare("SELECT v FROM kv WHERE k = ?").get("active");return t?JSON.parse(t.v):null}function $k(e,t){e.prepare("INSERT INTO kv(k, v) VALUES ('active', ?) ON CONFLICT(k) DO UPDATE SET v = excluded.v").run(JSON.stringify(t))}function Xs(e,t,r){let n=Ak(t,r,Qs(e));return $k(e,n.active),n}import{randomUUID as Bf}from"node:crypto";import{existsSync as Wf,mkdirSync as Wk,readFileSync as ai,rmSync as Gk,writeFileSync as Gf}from"node:fs";import{homedir as Vk}from"node:os";import{join as Vf,resolve as Hf,sep as Jk}from"node:path";var AH=64*1024;import{readFileSync as Zs,writeFileSync as xk}from"node:fs";function Rk(e,t){return e.prepare("UPDATE queue SET status = 'sent', sent_ts = ? WHERE id = ? AND status = 'pending'").run(new Date().toISOString(),t).changes>0}function rf(e,t){let r=[],n=new Map;for(let s of t){if(s.dedupe_key!==null){r.push(s);continue}let i=JSON.stringify([s.from_id,s.to_id,s.escalation_only,s.to_alias]),a=n.get(i);a?a.push(s):n.set(i,[s])}let o=[...r];for(let s of n.values()){if(s.length===1){o.push(s[0]);continue}let[i,...a]=s,c;try{c=Zs(i.prompt_file,"utf8")}catch{o.push(...s);continue}let l=[],u=!0;for(let d of a)try{l.push(`
|
|
131
131
|
|
|
132
132
|
--- addendum, ${d.created_ts} ---
|
|
133
|
-
${Zs(d.prompt_file,"utf8")}`)}catch{u=!1;break}if(!u){o.push(...s);continue}if(l.length>0){
|
|
133
|
+
${Zs(d.prompt_file,"utf8")}`)}catch{u=!1;break}if(!u){o.push(...s);continue}if(l.length>0){xk(i.prompt_file,c+l.join(""));let d=e.prepare("UPDATE queue SET status = 'merged' WHERE id = ? AND status = 'pending'");for(let m of a)d.run(m.id)}o.push(i)}return o}function Ic(e,t,r){let n=new Map(t.map(c=>[c.name,c])),o=r.teamName?e.prepare("SELECT * FROM queue WHERE status = 'pending' AND escalation_only = 0 AND to_id = ? ORDER BY id").all(r.teamName):e.prepare("SELECT * FROM queue WHERE status = 'pending' AND escalation_only = 0 ORDER BY id").all(),s=rf(e,o),i=new Set,a=0;for(let c of s){let l=c.to_alias===null?c.to_id:`${c.to_id}:${c.to_alias}`;if(i.has(l))continue;i.add(l);let u=n.get(c.to_id);if(!u||r.isTeamBusy(u))continue;if(r.minMemoryPercent!==void 0){let p=r.memoryCheck;if(p&&!p(r.minMemoryPercent))continue}try{Zs(c.prompt_file,"utf8")}catch{continue}if(!Rk(e,c.id))continue;let d;try{d=Zs(c.prompt_file,"utf8")}catch(p){process.stderr.write(`[lmqueue] row #${c.id} claimed 'sent' but its prompt file became unreadable before dispatch -- nothing was actually sent: ${p instanceof Error?p.message:String(p)}
|
|
134
134
|
`),a++;continue}let m=c.to_alias??u.leadAlias,f={teamfilePath:u.teamfilePath,alias:m};a++,!r.onDispatch?.({row:c,team:u,target:f,promptText:d})&&r.send(f,d)}return a}import{randomUUID as of}from"node:crypto";import{mkdtempSync as sf,rmSync as af,writeFileSync as cf}from"node:fs";import{tmpdir as lf}from"node:os";import{join as ei}from"node:path";import{spawn as uf}from"node:child_process";var df=50*6e4,mf=5e3,nn=["systemd-run","--user","--scope","--collect","--quiet","--","lmctl"];async function Jt(e,t,r={}){let n=r.timeoutMs??df,o=r.sigkillGraceMs??mf,s=sf(ei(lf(),"lmauto-send-")),i=ei(s,`${of()}.md`);cf(i,t,{mode:384});let c=[...r.spawnPrefix??nn,"chat",`${e.teamfilePath}:${e.alias}`,"--prompt-file",i,"--json"],[l,...u]=c;return new Promise(d=>{let m=uf(l,u,{detached:!0,stdio:["ignore","pipe","pipe"]});m.unref();let f="",p="",h=!1,g=setTimeout(()=>{if(!h){if(m.pid!==void 0){let y=m.pid;try{process.kill(-y,"SIGTERM")}catch{}setTimeout(()=>{try{process.kill(-y,0)}catch{return}try{process.kill(-y,"SIGKILL")}catch{}},o).unref()}E({kind:"timeout"})}},n);function _(){clearTimeout(g);try{af(s,{recursive:!0,force:!0})}catch{}}function E(y){h||(h=!0,_(),d(y))}m.stdout?.on("data",y=>{let S=y.toString("utf8");p+=S,f+=S;let T=f.split(`
|
|
135
135
|
`);f=T.pop()??"";for(let R of T){let x=nf(R);x&&E(x)}}),m.stderr?.on("data",y=>{p+=y.toString("utf8")}),m.on("error",y=>{E({kind:"error",message:y.message})}),m.on("close",(y,S)=>{if(!h){if(f.trim()){let T=nf(f);if(T){E(T);return}}if(y!==0||S!==null){E({kind:"error",message:`lctl exited ${S?`via signal ${S}`:`with code ${y}`} without a recognized status line: ${p.trim().slice(-2e3)}`});return}E({kind:"no-signal",rawOutput:p.trim()})}})})}function nf(e){let t=e.trim();if(!t)return null;let r;try{r=JSON.parse(t)}catch{return null}if(typeof r!="object"||r===null)return null;let n=r;switch(n.status){case"accepted":return null;case"ok":case"stalled":return{kind:n.status==="stalled"?"stalled":"ok",replyText:typeof n.replyText=="string"?n.replyText:"",messageId:typeof n.message_id=="string"?n.message_id:null,teamChatLogId:typeof n.teamChatLogId=="number"?n.teamChatLogId:null};case"busy":return{kind:"busy",message:typeof n.message=="string"?n.message:"busy"};case"error":case"failed":return{kind:"error",message:typeof n.message=="string"?n.message:"error"};default:return null}}function ff(e,t,r={}){let n=sf(ei(lf(),"lmauto-send-")),o=ei(n,`${of()}.md`);cf(o,t,{mode:384});let i=[...r.spawnPrefix??nn,"chat",`${e.teamfilePath}:${e.alias}`,"--prompt-file",o,"--json"],[a,...c]=i,l=uf(a,c,{detached:!0,stdio:"ignore"});l.unref();function u(){try{af(n,{recursive:!0,force:!0})}catch{}}let d=!1;l.on("exit",()=>{d=!0,clearTimeout(m),u()});let m=setTimeout(()=>{if(d||l.pid===void 0)return;let f=l.pid;try{process.kill(-f,"SIGTERM")}catch{return}setTimeout(()=>{if(!d){try{process.kill(-f,0)}catch{return}try{process.kill(-f,"SIGKILL")}catch{}}},r.sigkillGraceMs??mf).unref()},r.timeoutMs??df);m.unref(),l.on("error",f=>{u(),process.stderr.write(`[send] sendPromptDetached: failed to spawn dispatch to ${e.teamfilePath}:${e.alias}: ${f.message} -- the queue row is already marked sent and will NOT be retried
|
|
136
|
-
`)})}var xn="queue_delivery_paused:";function pf(e,t){return e.prepare("SELECT 1 FROM kv WHERE k = ?").get(xn+t)!==void 0}function hf(e,t){try{let r=JSON.parse(t);return{team:e,pausedAt:typeof r.pausedAt=="string"?r.pausedAt:new Date(0).toISOString(),reason:typeof r.reason=="string"?r.reason:null}}catch{return{team:e,pausedAt:new Date(0).toISOString(),reason:null}}}function gf(e,t){let r=e.prepare("SELECT v FROM kv WHERE k = ?").get(xn+t);return r===void 0?null:hf(t,r.v)}function _f(e){return e.prepare("SELECT k, v FROM kv WHERE k LIKE ?").all(`${xn}%`).map(r=>hf(r.k.slice(xn.length),r.v))}function wf(e,t,r,n){e.prepare("INSERT INTO kv(k, v) VALUES (?, ?) ON CONFLICT(k) DO UPDATE SET v = excluded.v").run(xn+t,JSON.stringify({pausedAt:n,reason:r}))}function yf(e,t){return e.prepare("DELETE FROM kv WHERE k = ?").run(xn+t).changes>0}function
|
|
136
|
+
`)})}var xn="queue_delivery_paused:";function pf(e,t){return e.prepare("SELECT 1 FROM kv WHERE k = ?").get(xn+t)!==void 0}function hf(e,t){try{let r=JSON.parse(t);return{team:e,pausedAt:typeof r.pausedAt=="string"?r.pausedAt:new Date(0).toISOString(),reason:typeof r.reason=="string"?r.reason:null}}catch{return{team:e,pausedAt:new Date(0).toISOString(),reason:null}}}function gf(e,t){let r=e.prepare("SELECT v FROM kv WHERE k = ?").get(xn+t);return r===void 0?null:hf(t,r.v)}function _f(e){return e.prepare("SELECT k, v FROM kv WHERE k LIKE ?").all(`${xn}%`).map(r=>hf(r.k.slice(xn.length),r.v))}function wf(e,t,r,n){e.prepare("INSERT INTO kv(k, v) VALUES (?, ?) ON CONFLICT(k) DO UPDATE SET v = excluded.v").run(xn+t,JSON.stringify({pausedAt:n,reason:r}))}function yf(e,t){return e.prepare("DELETE FROM kv WHERE k = ?").run(xn+t).changes>0}function Nk(e){return{team:e.team,alias:e.alias,holderPid:e.holder_pid,reservedAt:e.reserved_at,leaseUntil:e.lease_until,reason:e.reason}}function Ef(e,t,r,n,o,s,i=6e4){let a=new Date(Date.parse(o)+i).toISOString();return e.prepare(`INSERT INTO session_reservation(team, alias, holder_pid, reserved_at, lease_until, reason)
|
|
137
137
|
VALUES (?, ?, ?, ?, ?, ?)
|
|
138
138
|
ON CONFLICT(team, alias) DO UPDATE SET
|
|
139
139
|
holder_pid = excluded.holder_pid,
|
|
140
140
|
reserved_at = excluded.reserved_at,
|
|
141
141
|
lease_until = excluded.lease_until,
|
|
142
142
|
reason = excluded.reason
|
|
143
|
-
WHERE session_reservation.lease_until <= ?`).run(t,r,n,o,a,s,o).changes===0?null:{team:t,alias:r,holderPid:n,reservedAt:o,leaseUntil:a,reason:s}}function Lc(e,t,r,n=Date.now()){let o=e.prepare("SELECT * FROM session_reservation WHERE team = ? AND alias = ?").get(t,r);return o===void 0?null:Date.parse(o.lease_until)>n?
|
|
143
|
+
WHERE session_reservation.lease_until <= ?`).run(t,r,n,o,a,s,o).changes===0?null:{team:t,alias:r,holderPid:n,reservedAt:o,leaseUntil:a,reason:s}}function Lc(e,t,r,n=Date.now()){let o=e.prepare("SELECT * FROM session_reservation WHERE team = ? AND alias = ?").get(t,r);return o===void 0?null:Date.parse(o.lease_until)>n?Nk(o):null}function ti(e,t,r,n=Date.now()){return Lc(e,t,r,n)!==null}function bf(e,t,r=Date.now()){return e.prepare("SELECT lease_until FROM session_reservation WHERE team = ?").all(t).some(o=>Date.parse(o.lease_until)>r)}function Tf(e,t,r,n){return e.prepare("DELETE FROM session_reservation WHERE team = ? AND alias = ? AND holder_pid = ?").run(t,r,n).changes>0}import{homedir as Ik}from"node:os";import{readFileSync as Lk}from"node:fs";import{join as Ck}from"node:path";function Sf(e){return{LMAUTO_DB:e}}function $r(){return process.env.LMAUTO_DB??Ck(Ik(),".lmbee","state.db")}function Ok(e){return Ws(Sf(e))}function on(e){return An(e)}function Rn(e){return Km(e)}async function ri(e){return Jm({env:Sf(e)})}var Dk="lmbee.site_uuid",Mk=/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;function Pk(e){let t=Ok(e),r=Lk(t,"utf8").trim();if(!Mk.test(r))throw new Error(`Invalid site identity at "${t}"; refusing to repair it during startup`);return r.toLowerCase()}function vf(e,t,r=$r()){let n=Hs(t,{readOnly:!0,requireLmbeeSchema:!1});try{if(!n.db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'kv'").get())throw new Error("Database has no lmbee site identity binding; explicit provisioning is required before mail or configured daemon startup");return Nn(n.db,r,e)}finally{n.close()}}function Nn(e,t=$r(),r){let n=Pk(t),o=e.prepare("SELECT v FROM kv WHERE k = ?").get(Dk);if(!o)throw new Error("Database has no lmbee site identity binding; explicit provisioning is required before mail or configured daemon startup");if(o.v!==n||r!==void 0&&r.toLowerCase()!==n)throw new Error("Database site identity does not match the retained site-uuid or configured LMBEE_SITE_UUID");return n}function Uk(e){return{v:e.v,msg_id:e.msgId,to:e.to,from:e.from,sent_at:e.sentAt,payload:e.payload,...e.inReplyTo!==void 0?{in_reply_to:e.inReplyTo}:{}}}function Fk(e){return{v:e.v,msgId:e.msg_id,to:e.to,from:e.from,sentAt:e.sent_at,payload:e.payload,...e.in_reply_to!==void 0?{inReplyTo:e.in_reply_to}:{}}}var Af=64*1024;function Oo(e){return JSON.stringify(Uk(e))}function kf(e){if(Buffer.byteLength(e,"utf8")>Af)throw new Error(`envelope body exceeds ${Af} bytes`);let t;try{t=JSON.parse(e)}catch(u){throw new Error(`envelope is not valid JSON: ${u instanceof Error?u.message:String(u)}`)}if(typeof t!="object"||t===null||Array.isArray(t))throw new Error("envelope must be a JSON object");let r=t;if(r.v!==1)throw new Error(`unsupported envelope version: ${JSON.stringify(r.v)}`);let n=ni(r,"msg_id"),o=ni(r,"sent_at"),s=ni(r,"payload"),i=$f(r,"to"),a=$f(r,"from"),c=r.in_reply_to===void 0||r.in_reply_to===null?void 0:ni(r,"in_reply_to"),l={v:1,msg_id:n,to:i,from:a,sent_at:o,payload:s,...c!==void 0?{in_reply_to:c}:{}};return Fk(l)}function ni(e,t){let r=t.split(".").pop(),n=e[r];if(typeof n!="string"||n.length===0)throw new Error(`envelope.${t} must be a non-empty string, got ${JSON.stringify(n)}`);return n}function Cc(e,t,r){let n=t.split(".").pop(),o=e[n];if(typeof o!="string"){let s=r?"a string":"a non-empty string";throw new Error(`envelope.${t} must be ${s}, got ${JSON.stringify(o)}`)}try{vn(o,t,r)}catch(s){throw new Error(`envelope.${s instanceof Error?s.message:String(s)}`)}return o}function $f(e,t){let r=t.split(".").pop(),n=e[r];if(typeof n!="object"||n===null||Array.isArray(n))throw new Error(`envelope.${t} must be an object, got ${JSON.stringify(n)}`);let o=n;return{site:Cc(o,`${t}.site`,!1),team:Cc(o,`${t}.team`,!0),alias:Cc(o,`${t}.alias`,!1)}}function xf(e,t,r){if(e.prepare(`INSERT INTO mail_ledger(
|
|
144
144
|
msg_id, seq, state, to_site, to_team, to_alias, from_site, from_team, from_alias,
|
|
145
145
|
sender_user_id, sent_at, payload, received_ts
|
|
146
146
|
) VALUES (?, ?, 'persisted', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
147
|
-
ON CONFLICT(msg_id) DO NOTHING`).run(t.msgId,t.seq,t.to.site,t.to.team,t.to.alias,t.from.site,t.from.team,t.from.alias,t.senderUserId,t.sentAt,t.payload,r).changes>0)return"inserted";let o=Oc(e,t.msgId);return o===null?"inserted":o.seq===t.seq&&o.to_site===t.to.site&&o.to_team===t.to.team&&o.to_alias===t.to.alias&&o.from_site===t.from.site&&o.from_team===t.from.team&&o.from_alias===t.from.alias&&o.sender_user_id===t.senderUserId&&o.sent_at===t.sentAt&&o.payload===t.payload?"duplicate":"conflict"}function
|
|
147
|
+
ON CONFLICT(msg_id) DO NOTHING`).run(t.msgId,t.seq,t.to.site,t.to.team,t.to.alias,t.from.site,t.from.team,t.from.alias,t.senderUserId,t.sentAt,t.payload,r).changes>0)return"inserted";let o=Oc(e,t.msgId);return o===null?"inserted":o.seq===t.seq&&o.to_site===t.to.site&&o.to_team===t.to.team&&o.to_alias===t.to.alias&&o.from_site===t.from.site&&o.from_team===t.from.team&&o.from_alias===t.from.alias&&o.sender_user_id===t.senderUserId&&o.sent_at===t.sentAt&&o.payload===t.payload?"duplicate":"conflict"}function Rf(e){return e.prepare("SELECT * FROM mail_ledger WHERE state = 'persisted' ORDER BY seq").all()}function Oc(e,t){return e.prepare("SELECT * FROM mail_ledger WHERE msg_id = ?").get(t)??null}function Nf(e){return e.prepare("SELECT MAX(seq) as maxSeq FROM mail_ledger").get().maxSeq}function If(e,t,r){return e.prepare("UPDATE mail_ledger SET state = 'dispatched', dispatched_ts = ? WHERE msg_id = ? AND state = 'persisted'").run(r,t).changes>0}function Lf(e,t,r){return e.prepare("UPDATE mail_ledger SET state = 'replied', replied_ts = ? WHERE msg_id = ? AND state = 'dispatched'").run(r,t).changes>0}function In(e,t,r,n){return e.prepare(`UPDATE mail_ledger
|
|
148
148
|
SET state = 'failed', failed_ts = ?, failure_reason = ?, retry_count = retry_count + 1
|
|
149
|
-
WHERE msg_id = ? AND state IN ('persisted', 'dispatched')`).run(n,r,t).changes>0}var Dc={baseMs:6e4,maxMs:30*6e4};function
|
|
149
|
+
WHERE msg_id = ? AND state IN ('persisted', 'dispatched')`).run(n,r,t).changes>0}var Dc={baseMs:6e4,maxMs:30*6e4};function qk(e,t){let r=Math.max(0,e-1);return Math.min(t.baseMs*2**r,t.maxMs)}var sn="PERMANENT: ";function Mc(e){return e.prepare("SELECT * FROM mail_ledger WHERE state = 'failed' AND failed_ts IS NOT NULL ORDER BY seq").all()}function oi(e,t,r=Dc){let n=Date.parse(t);return Mc(e).filter(o=>{if(o.failure_reason?.startsWith(sn))return!1;let s=Date.parse(o.failed_ts);return Number.isFinite(s)?n-s>=qk(o.retry_count,r):!1})}function Cf(e){let t=e.prepare("SELECT state, COUNT(*) as n FROM mail_ledger GROUP BY state").all(),r={persisted:0,dispatched:0,replied:0,failed:0};for(let n of t)r[n.state]=n.n;return r}function Of(e,t){return e.prepare("UPDATE mail_ledger SET state = 'persisted' WHERE msg_id = ? AND state = 'failed'").run(t).changes>0}function Df(e,t,r){return e.prepare("UPDATE mail_ledger SET ack_sent_ts = ? WHERE msg_id = ? AND ack_sent_ts IS NULL").run(r,t).changes>0}function Mf(e,t,r,n){return e.prepare("UPDATE mail_ledger SET delivery_error = ?, delivery_error_ts = ? WHERE msg_id = ?").run(r,n,t).changes>0}function Pf(e){return e.prepare("SELECT COUNT(*) as n FROM mail_ledger WHERE delivery_error IS NOT NULL").get().n}function Pc(e,t,r){e.prepare(`INSERT INTO mail_outbound_ledger(
|
|
150
150
|
msg_id, to_site, to_team, to_alias, from_site, from_team, from_alias, state, sent_ts, queue_id
|
|
151
151
|
) VALUES (?, ?, ?, ?, ?, ?, ?, 'sent', ?, ?)
|
|
152
|
-
ON CONFLICT(msg_id) DO NOTHING`).run(t.msgId,t.to.site,t.to.team,t.to.alias,t.from.site,t.from.team,t.from.alias,r,t.queueId)}function
|
|
152
|
+
ON CONFLICT(msg_id) DO NOTHING`).run(t.msgId,t.to.site,t.to.team,t.to.alias,t.from.site,t.from.team,t.from.alias,r,t.queueId)}function Uf(e,t){return e.prepare("SELECT * FROM mail_outbound_ledger WHERE msg_id = ?").get(t)??null}function Ff(e,t,r){return e.prepare("UPDATE mail_outbound_ledger SET state = 'acked', acked_ts = ? WHERE msg_id = ? AND state = 'sent'").run(r,t).changes>0}function qf(e,t,r){return e.prepare("UPDATE mail_outbound_ledger SET state = 'replied', replied_ts = ? WHERE msg_id = ? AND state IN ('sent', 'acked')").run(r,t).changes>0}function si(e,t){return e.prepare(`SELECT * FROM mail_outbound_ledger
|
|
153
153
|
WHERE to_site = ? AND to_team = ? AND to_alias = ?
|
|
154
|
-
ORDER BY id DESC LIMIT 1`).get(t.site,t.team,t.alias)??null}import{readFileSync as
|
|
155
|
-
`),!1):r.percentAvailable>=e}var C=class extends Error{code;exitCode;constructor(t,r,n=2){super(r),this.code=t,this.exitCode=n}};function ci(){return process.env.LMBEE_QUEUE_DIR?process.env.LMBEE_QUEUE_DIR:
|
|
154
|
+
ORDER BY id DESC LIMIT 1`).get(t.site,t.team,t.alias)??null}import{readFileSync as jk}from"node:fs";var Hk=/^MemTotal:\s+(\d+)\s*kB/m,Bk=/^MemAvailable:\s+(\d+)\s*kB/m;function ii(e){return e===null?null:`memory headroom: ${e.percentAvailable.toFixed(1)}% available (context only, not a wake trigger)`}function Do(e="/proc/meminfo"){let t;try{t=jk(e,"utf8")}catch{return null}let r=Hk.exec(t),n=Bk.exec(t);if(!r||!n)return null;let o=Number(r[1]),s=Number(n[1]);return!Number.isFinite(o)||o<=0||!Number.isFinite(s)||s<0?null:{totalKb:o,availableKb:s,percentAvailable:s/o*100}}var Uc=10;function jf(e=Uc,t=Do){if(e<=0)return!0;let r=t();return r===null?(process.stderr.write(`[memory] could not read /proc/meminfo -- deferring dispatch conservatively (set --min-memory-percent 0 to disable this gate)
|
|
155
|
+
`),!1):r.percentAvailable>=e}var C=class extends Error{code;exitCode;constructor(t,r,n=2){super(r),this.code=t,this.exitCode=n}};function ci(){return process.env.LMBEE_QUEUE_DIR?process.env.LMBEE_QUEUE_DIR:Vf(Vk(),".lmbee","queue")}function zk(e,t,r){Wf(r)||Wk(r,{recursive:!0});let n=Vf(r,`${e}.md`);return Gf(n,t),n}function an(e){if(e==="operator")return{baseId:e,alias:null};let t=e.indexOf(":");return t===-1?{baseId:e,alias:null}:{baseId:e.slice(0,t),alias:e.slice(t+1)}}function we(e,t,r,n,o){if(!o.from)throw new Error("enqueue: options.from is required ('autopilot', 'operator', or a maintainer team name)");let{baseId:s,alias:i}=an(r);if(s==="math"&&o.from==="autopilot"&&o.subject!==void 0&&t.some(d=>d.name==="triage")&&(s="triage",i=null),s!=="operator"&&!t.some(d=>d.name===s))throw new Error(`enqueue: unknown team "${s}"`);let a=new Date().toISOString(),c=o.dedupeKey??null,l=o.expectsResponse??(o.from==="operator"||s==="operator");return e.transaction(()=>{let d=e.prepare(`INSERT INTO queue(from_id, to_id, prompt_file, status, created_ts, subject_id, dedupe_key, escalation_only, expects_response, to_alias, retraction_notice, in_reply_to, operator_priority)
|
|
156
156
|
VALUES (?, ?, '', 'pending', ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
157
|
-
ON CONFLICT(dedupe_key) DO NOTHING`).run(o.from,s,a,o.subject??null,c,o.escalationOnly?1:0,l?1:0,i,o.retractionNotice?1:0,o.inReplyTo??null,o.operatorPriority?1:0);if(d.changes===0){let p=e.prepare("SELECT id FROM queue WHERE dedupe_key = ?").get(c);if(!p)throw new Error(`enqueue: dedupe conflict on "${c}" but the existing row is already gone`);return p.id}let m=Number(d.lastInsertRowid),f=
|
|
157
|
+
ON CONFLICT(dedupe_key) DO NOTHING`).run(o.from,s,a,o.subject??null,c,o.escalationOnly?1:0,l?1:0,i,o.retractionNotice?1:0,o.inReplyTo??null,o.operatorPriority?1:0);if(d.changes===0){let p=e.prepare("SELECT id FROM queue WHERE dedupe_key = ?").get(c);if(!p)throw new Error(`enqueue: dedupe conflict on "${c}" but the existing row is already gone`);return p.id}let m=Number(d.lastInsertRowid),f=zk(m,n,o.queueDir??ci());return e.prepare("UPDATE queue SET prompt_file = ? WHERE id = ?").run(f,m),m}).immediate()}function Fc(e,t,r=30){return t?e.prepare("SELECT * FROM queue WHERE to_id = ? ORDER BY id DESC LIMIT ?").all(t,r):e.prepare("SELECT * FROM queue ORDER BY id DESC LIMIT ?").all(r)}function Jf(e,t,r={}){return r.fromAutopilot?e.prepare("SELECT * FROM queue WHERE to_id = ? AND status = 'pending' AND from_id = 'autopilot' AND subject_id IS NULL ORDER BY id").all(t):e.prepare("SELECT * FROM queue WHERE to_id = ? AND status = 'pending' ORDER BY id").all(t)}function He(e,t,r={}){return r.fromAutopilot?e.prepare("SELECT * FROM queue WHERE to_id = ? AND status IN ('pending', 'escalating') AND from_id = 'autopilot' AND subject_id IS NULL ORDER BY id").all(t):e.prepare("SELECT * FROM queue WHERE to_id = ? AND status IN ('pending', 'escalating') ORDER BY id").all(t)}function li(e,t){let r=e.prepare("SELECT * FROM queue WHERE to_id = ? AND status = 'pending' ORDER BY id").all(t),n=[];for(let o of r){let s=[o.from_id,o.to_id,o.escalation_only,o.to_alias],a=e.prepare("SELECT MIN(id) AS id FROM queue WHERE from_id = ? AND to_id = ? AND escalation_only = ? AND to_alias IS ? AND id > ? AND status != 'merged'").get(...s,o.id).id??Number.MAX_SAFE_INTEGER,c=e.prepare("SELECT * FROM queue WHERE from_id = ? AND to_id = ? AND escalation_only = ? AND to_alias IS ? AND status = 'merged' AND id > ? AND id < ? AND retracted_ts IS NULL").all(...s,o.id,a);n.push(...c)}return n.sort((o,s)=>o.id-s.id),n}function kr(e,t){return e.prepare("SELECT * FROM queue WHERE id = ?").get(t)??null}function zf(e,t){return e.prepare(`SELECT (
|
|
158
158
|
EXISTS(SELECT 1 FROM queue WHERE to_id = ? AND sent_ts IS NOT NULL)
|
|
159
159
|
OR EXISTS(SELECT 1 FROM queue WHERE from_id = ?)
|
|
160
|
-
) AS found`).get(t,t).found===1}var qc=["pending","sent","retrieved","escalating","merged"];function
|
|
160
|
+
) AS found`).get(t,t).found===1}var qc=["pending","sent","retrieved","escalating","merged"];function Kk(e){let{escalation_claim_token:t,prompt_file:r,admission_fingerprint:n,...o}=e;return o}var Yk=50,Mo=200;function jc(e,t={}){let r=t.limit??Yk;if(!Number.isSafeInteger(r)||r<1||r>Mo)throw new C("INVALID_ARGUMENT",`limit must be a positive integer <= ${Mo}`);let n=[],o=[];t.fromId!==void 0&&(n.push("from_id = ?"),o.push(t.fromId)),t.toId!==void 0&&(n.push("to_id = ?"),o.push(t.toId)),t.status!==void 0&&(n.push("status = ?"),o.push(t.status)),t.since!==void 0&&(n.push("created_ts >= ?"),o.push(t.since)),t.until!==void 0&&(n.push("created_ts < ?"),o.push(t.until)),t.after!==void 0&&(n.push("id < ?"),o.push(t.after));let s=n.length>0?`WHERE ${n.join(" AND ")}`:"",i=e.prepare(`SELECT * FROM queue ${s} ORDER BY id DESC LIMIT ?`).all(...o,r+1).map(Kk),a=i.length>r,c=a?i.slice(0,r):i;return{rows:c,meta:{next_cursor:a?c[c.length-1].id:null}}}function Qk(e,t){return e.prepare("UPDATE queue SET status = 'sent', sent_ts = ? WHERE id = ? AND status = 'pending'").run(new Date().toISOString(),t).changes>0}function Xk(e){return`'${e.replaceAll("'","'\\''")}'`}function Zk(e,t,r){return`${e}
|
|
161
161
|
|
|
162
|
-
[Delivery receipt: after reading this prompt, run \`lmbee queue retrieve ${
|
|
163
|
-
`)})}function
|
|
164
|
-
`),In(e,r.msg_id,`${sn}reply-send failed: ${d}`,i())})}function
|
|
165
|
-
`),!0}return
|
|
162
|
+
[Delivery receipt: after reading this prompt, run \`lmbee queue retrieve ${Xk(t)} --id ${r}\` to record that you received queue#${r}.]`}function ex(e,t,r,n,o){let i=(t.now??(()=>new Date().toISOString()))(),a={v:1,msgId:Bf(),to:{site:r.peerSite,team:r.name,alias:r.alias},from:{site:t.localSiteId,team:"",alias:n.from_id},sentAt:i,payload:o};Pc(e,{msgId:a.msgId,to:a.to,from:a.from,queueId:n.id},i);let c=on(r.peerSite),l=new TextEncoder().encode(Oo(a));t.client.sendMessage({mailbox:c,subject:`lmauto delivery ${a.msgId}`,body:{name:"body.txt",contentType:"text/plain; charset=utf-8",bytes:l}}).catch(u=>{process.stderr.write(`[deliver] failed to send remote envelope to mailbox ${c} (team ${r.name}): ${u instanceof Error?u.message:String(u)}
|
|
163
|
+
`)})}function tx(e,t,r,n,o,s=n.leadAlias){let i=t.now??(()=>new Date().toISOString()),a={v:1,msgId:Bf(),to:{site:r.from_site,team:r.from_team,alias:r.from_alias},from:{site:t.localSiteId,team:n.name,alias:s},sentAt:i(),payload:o,inReplyTo:r.msg_id},c=on(r.from_site),l=new TextEncoder().encode(Oo(a));return t.client.sendMessage({mailbox:c,subject:`lmauto reply ${a.msgId}`,body:{name:"body.txt",contentType:"text/plain; charset=utf-8",bytes:l}}).then(()=>{let u=i();Pc(e,{msgId:a.msgId,to:a.to,from:a.from,queueId:null},u),Lf(e,r.msg_id,u)}).catch(u=>{let d=u instanceof Error?u.message:String(u);process.stderr.write(`[deliver] failed to send reply envelope to mailbox ${c} (in_reply_to ${r.msg_id}): ${d}
|
|
164
|
+
`),In(e,r.msg_id,`${sn}reply-send failed: ${d}`,i())})}function rx(e,t,r,n){if(!t.remoteMail)return!1;try{ai(n.prompt_file,"utf8")}catch{return!1}if(!Qk(e,n.id))return!1;let o;try{o=ai(n.prompt_file,"utf8")}catch(s){return process.stderr.write(`[deliver] queue row #${n.id} claimed 'sent' but its prompt file became unreadable before dispatch -- nothing was actually sent: ${s instanceof Error?s.message:String(s)}
|
|
165
|
+
`),!0}return ex(e,t.remoteMail,r,n,o),!0}function nx(e){let t=new Map,r=[];for(let n of e){if(!B(n))continue;let o;try{o=Q(n)}catch{continue}t.set(n.name,n),r.push({name:n.name,teamfilePath:o,leadAlias:n.leadAlias})}return{refs:r,byName:t}}function Hc(e){let t=e.expects_response?" (expects a response)":"";return`--- addendum from ${e.from_id}, ${e.created_ts}${t} ---`}function ox(e,t){let r=new Map;for(let n of t){if(n.dedupe_key!==null)continue;let o=JSON.stringify([n.to_id,n.escalation_only,n.to_alias]),s=r.get(o);s?s.push(n):r.set(o,[n])}for(let n of r.values()){if(n.length<2)continue;let[o,...s]=n;if(e.prepare("UPDATE queue SET status = 'pending' WHERE id = ? AND status = 'pending'").run(o.id).changes===0)continue;let a;try{a=ai(o.prompt_file,"utf8")}catch{continue}let c=[],l=!0;for(let d of s)try{c.push(`
|
|
166
166
|
|
|
167
167
|
${Hc(d)}
|
|
168
|
-
${ai(d.prompt_file,"utf8")}`)}catch{l=!1;break}if(!l||c.length===0)continue;
|
|
169
|
-
`),y.kind==="error"&&
|
|
168
|
+
${ai(d.prompt_file,"utf8")}`)}catch{l=!1;break}if(!l||c.length===0)continue;Gf(o.prompt_file,a+c.join(""));let u=e.prepare("UPDATE queue SET status = 'merged', merged_into_id = ? WHERE id = ? AND status = 'pending'");for(let d of s)u.run(o.id,d.id);n.some(d=>d.expects_response)&&!o.expects_response&&e.prepare("UPDATE queue SET expects_response = 1 WHERE id = ?").run(o.id)}}function xr(e,t){let r=t.send??ff,n=t.sendAwaited??Jt,o=t.memoryCheck??jf,{refs:s,byName:i}=nx(t.teams),a=(t.teamName?e.prepare("SELECT * FROM queue WHERE status = 'pending' AND escalation_only = 0 AND to_id = ? ORDER BY id").all(t.teamName):e.prepare("SELECT * FROM queue WHERE status = 'pending' AND escalation_only = 0 ORDER BY id").all()).filter(d=>i.has(d.to_id));ox(e,a);let c=Ic(e,s,{teamName:t.teamName,isTeamBusy:d=>je(i.get(d.name),t.report)||pf(e,d.name)||bf(e,d.name),minMemoryPercent:t.minMemoryPercent,memoryCheck:o,send:(d,m)=>r(d,m),onDispatch:({row:d,team:m,target:f,promptText:p})=>{let h=d.dedupe_key!==null&&t.remoteMail?Oc(e,d.dedupe_key):null,g=Zk(p,m.name,d.id);if(!h||!t.remoteMail)return r(f,g),!0;let _=t.remoteMail,E=i.get(m.name);return n(f,g).then(y=>{y.kind==="ok"||y.kind==="stalled"?tx(e,_,h,E,y.replyText,f.alias):(process.stderr.write(`[deliver] mail-originated dispatch to ${m.name} (in_reply_to ${h.msg_id}) produced no reply to mail back: ${y.kind}
|
|
169
|
+
`),y.kind==="error"&&Mf(e,h.msg_id,y.message,(_.now??(()=>new Date().toISOString()))()))}).catch(y=>{process.stderr.write(`[deliver] failed to capture reply for mail-originated dispatch to ${m.name} (in_reply_to ${h.msg_id}): ${y instanceof Error?y.message:String(y)}
|
|
170
170
|
`)}),!0}}),l=t.teamName?e.prepare("SELECT * FROM queue WHERE status = 'pending' AND escalation_only = 0 AND to_id = ? ORDER BY id").all(t.teamName):e.prepare("SELECT * FROM queue WHERE status = 'pending' AND escalation_only = 0 ORDER BY id").all(),u=new Set;for(let d of l){let m=d.to_alias===null?d.to_id:`${d.to_id}:${d.to_alias}`;if(u.has(m)||(u.add(m),d.to_id==="operator"))continue;let f=t.teams.find(p=>p.name===d.to_id);if(!f){process.stderr.write(`[deliver] queue row #${d.id} addressed to unregistered team "${d.to_id}" -- left pending
|
|
171
|
-
`);continue}B(f)||
|
|
171
|
+
`);continue}B(f)||rx(e,t,f,d)&&c++}return c}function ui(e,t,r){return r!==void 0?sx(e,t,r):e.transaction(o=>{let s=e.prepare("SELECT * FROM queue WHERE to_id = ? AND status = 'pending' ORDER BY id").all(o);if(s.length===0)return s;let i=new Date().toISOString(),a=e.prepare("UPDATE queue SET status = 'retrieved', retrieved_ts = ? WHERE id = ? AND status = 'pending'"),c=[];for(let l of s)a.run(i,l.id).changes!==0&&(l.status="retrieved",l.retrieved_ts=i,c.push(l));return c})(t)}function sx(e,t,r){if(!Number.isSafeInteger(r)||r<=0)throw new C("INVALID_ARGUMENT",`Queue prompt id must be a positive integer: ${r}`,2);return e.transaction((o,s)=>{let i=e.prepare("SELECT * FROM queue WHERE id = ?").get(s);if(i===void 0)throw new C("NOT_FOUND",`Queue prompt ${s} was not found`,2);if(i.to_id!==o)throw new C("INVALID_ARGUMENT",`Queue prompt ${s} is addressed to "${i.to_id}", not "${o}"`,2);if(i.retracted_ts!==null)throw new C("CONFLICT",`Queue prompt ${s} was retracted: ${i.retracted_reason??"(no reason recorded)"}`,4);if(i.status==="merged"||i.merged_into_id!==null)throw new C("CONFLICT",`Queue prompt ${s} was merged into ${i.merged_into_id??"another prompt"}`,4);if(i.status!=="pending"&&i.status!=="sent"&&i.status!=="retrieved")throw new C("CONFLICT",`Queue prompt ${s} is not eligible for receipt (status: ${i.status})`,4);if(i.status!=="retrieved"){let c=new Date().toISOString();e.prepare("UPDATE queue SET status = 'retrieved', retrieved_ts = COALESCE(retrieved_ts, ?) WHERE id = ? AND status IN ('pending', 'sent')").run(c,s)}let a=e.prepare("SELECT * FROM queue WHERE id = ?").get(s);if(a.status==="retrieved"){let c=a.retrieved_ts??new Date().toISOString();e.prepare(`WITH RECURSIVE descendants(id) AS (
|
|
172
172
|
SELECT id FROM queue WHERE merged_into_id = ? AND to_id = ?
|
|
173
173
|
UNION ALL
|
|
174
174
|
SELECT q.id FROM queue q JOIN descendants d ON q.merged_into_id = d.id WHERE q.to_id = ?
|
|
175
175
|
)
|
|
176
|
-
UPDATE queue SET retrieved_ts = COALESCE(retrieved_ts, ?) WHERE status = 'merged' AND id IN (SELECT id FROM descendants)`).run(s,o,o,c)}return[e.prepare("SELECT * FROM queue WHERE id = ?").get(s)]}).immediate(t,r)}function
|
|
176
|
+
UPDATE queue SET retrieved_ts = COALESCE(retrieved_ts, ?) WHERE status = 'merged' AND id IN (SELECT id FROM descendants)`).run(s,o,o,c)}return[e.prepare("SELECT * FROM queue WHERE id = ?").get(s)]}).immediate(t,r)}function Kf(e,t={}){let r=Hf(t.queueDir??ci()),n=t.retentionMs??7*24*60*6e4,o=t.nowMs??Date.now(),s=new Date(o-n).toISOString(),i=e.prepare(`SELECT id, prompt_file FROM queue
|
|
177
177
|
WHERE (status = 'sent' AND sent_ts IS NOT NULL AND sent_ts < ?)
|
|
178
178
|
OR (status = 'retrieved' AND retrieved_ts IS NOT NULL AND retrieved_ts < ?)
|
|
179
|
-
OR (status = 'merged' AND created_ts < ?)`).all(s,s,s),a=0;for(let c of i){let l=
|
|
179
|
+
OR (status = 'merged' AND created_ts < ?)`).all(s,s,s),a=0;for(let c of i){let l=Hf(c.prompt_file);if(!(l!==r&&!l.startsWith(r+Jk))&&Wf(l))try{Gk(l,{force:!0}),a++}catch{}}return a}import{spawn as mx}from"node:child_process";import{lstatSync as ix,readlinkSync as ax,realpathSync as cx}from"node:fs";import{homedir as lx}from"node:os";import{basename as ux,dirname as Yf,isAbsolute as Xf,join as dx,resolve as Bc}from"node:path";var Rr="_lmauto_status_transition";function me(){return`${new Date().toISOString().replace("Z","000Z")}`}function Ee(e,t){if(!e.trim())throw new C("INVALID_ARGUMENT",`${t} must not be blank`);return e}function Wc(e){let t;try{t=ix(e)}catch{let r=Yf(e);return r===e?e:dx(Wc(r),ux(e))}if(t.isSymbolicLink()){let r=ax(e),n=Xf(r)?r:Bc(Yf(e),r);return Wc(n)}return cx(e)}function Rt(e){let t=e==="~"||e.startsWith("~/")?e.replace(/^~/,lx()):e,r=Xf(t)?Bc(t):Bc(process.cwd(),t);return Wc(r)}function Ln(e){let t=e&&typeof e=="object"&&"code"in e?String(e.code):void 0;if(t!==void 0&&(t.startsWith("SQLITE_BUSY")||t.startsWith("SQLITE_LOCKED")))throw new C("DB_BUSY","Database busy; retry after the current writer completes",5);let r=e instanceof Error?e.message:String(e);if(t!==void 0&&t.startsWith("SQLITE_CONSTRAINT")){let n={MISSING_PARENT:"NOT_FOUND",INVALID_PARENT_KIND:"INVALID_PARENT_KIND",PROJECT_MISMATCH:"PROJECT_MISMATCH",DEPENDENCY_CYCLE:"DEPENDENCY_CYCLE",IMMUTABLE_FIELD:"IMMUTABLE_FIELD",IMMUTABLE_EDGE:"IMMUTABLE_EDGE"};for(let[o,s]of Object.entries(n))if(r.includes(o))throw new C(s,r,s==="NOT_FOUND"?3:2);throw new C("STRUCTURAL_ERROR",r,2)}throw new C("STORAGE_ERROR",r,1)}function At(e){try{return e()}catch(t){if(t instanceof C)throw t;return Ln(t)}}function dt(e,t){return At(()=>e.prepare("SELECT * FROM entities WHERE id = ?").get(t)??null)}function Oe(e,t){let r=dt(e,t);if(r===null)throw new C("NOT_FOUND",`Entity ${t} does not exist`,3);return r}function Zf(e,t,r,n){let o=n!==null?Oe(e,n):null,s={epic:null,task:"epic",subtask:"task"};if(t==="epic"&&o!==null)throw new C("INVALID_PARENT_KIND","An epic cannot have a parent");if(t==="subtask"&&o===null)throw new C("INVALID_PARENT_KIND","A subtask requires a parent task");if(t==="task"&&o!==null&&o.kind!==s.task)throw new C("INVALID_PARENT_KIND","A task's parent must be an epic");if(t==="subtask"&&o!==null&&o.kind!==s.subtask)throw new C("INVALID_PARENT_KIND","A subtask's parent must be a task");if(o!==null&&o.project!==r)throw new C("PROJECT_MISMATCH","Parent and child projects must match");return o}function di(e,t){e.prepare("UPDATE entities SET revision = revision + 1, updated_at = ? WHERE id = ?").run(me(),t)}var Le=1e4;function ep(e,t,r,n){if(!Number.isSafeInteger(n)||n<1||n>Le)throw new C("INVALID_ARGUMENT",`limit must be a positive integer <= ${Le}`);return At(()=>{let o=e.prepare(`${t} ORDER BY id LIMIT ?`).all(...r,n+1),s=o.length>n,i=s?o.slice(0,n):o;return{rows:i,meta:{next_cursor:s?i[i.length-1].id:null}}})}function mt(e,t,r){return At(()=>{let n={},o=[["outgoing","entity_id","depends_on_id"],["incoming","depends_on_id","entity_id"]];for(let[s,i,a]of o)(r===s||r==="both")&&(n[s]=e.prepare(`SELECT e.id, e.title, e.kind, e.project, e.status FROM dependencies d JOIN entities e ON e.id = d.${a} WHERE d.${i} = ? ORDER BY e.id`).all(t));return n})}function tp(e,t){let r=e.transaction(()=>{let n=t.parentId!==void 0?Oe(e,t.parentId):null,o=Ee(t.project??n?.project??"default","project");if(t.owner!==void 0&&t.unassigned)throw new C("INVALID_ARGUMENT","Explicit owner and --unassigned are exclusive");try{Zf(e,t.kind,o,t.parentId??null)}catch(u){if(u instanceof C)throw u;Ln(u)}let s=null,i=null;t.owner!==void 0?(s=Rt(Ee(t.owner.team,"owner team")),i=Ee(t.owner.alias,"owner alias")):n!==null&&!t.unassigned&&(s=n.owner_team_path,i=n.owner_alias);let a=me(),c={kind:t.kind,project:o,parent_id:t.parentId??null,title:Ee(t.title,"title"),description:t.description??"",requirements:t.requirements??"",acceptance_criteria:t.acceptanceCriteria??"",status:Ee((t.status??"todo").trim(),"status"),owner_team_path:s,owner_alias:i,blocked_on:t.blockedOn??null,created_at:a,updated_at:a},l=Object.keys(c);try{let u=e.prepare(`INSERT INTO entities(${l.join(",")}) VALUES (${l.map(()=>"?").join(",")})`).run(...l.map(d=>c[d]));return Oe(e,Number(u.lastInsertRowid))}catch(u){if(u instanceof C)throw u;return Ln(u)}});return At(r)}function Nr(e,t){if(t.owner!==void 0&&t.unassigned)throw new C("INVALID_ARGUMENT","Owner and --unassigned are exclusive");let r=["id > ?"],n=[t.after??0];return t.project!==void 0&&(r.push("project = ?"),n.push(t.project)),t.kind!==void 0&&(r.push("kind = ?"),n.push(t.kind)),t.status!==void 0&&(r.push("status = ?"),n.push(Ee(t.status.trim(),"status"))),t.parentId!==void 0&&(r.push("parent_id = ?"),n.push(t.parentId)),t.owner!==void 0&&(r.push("owner_team_path = ?","owner_alias = ?"),n.push(Rt(t.owner.team),t.owner.alias)),t.unassigned&&r.push("owner_team_path IS NULL"),ep(e,`SELECT * FROM entities WHERE ${r.join(" AND ")}`,n,t.limit??100)}function Ir(e,t){let r=Oe(e,t),n=At(()=>e.prepare("SELECT id FROM entities WHERE parent_id = ? ORDER BY id").all(t).map(s=>s.id)),o=mt(e,t,"both");return{...r,children:n,dependencies:{outgoing:o.outgoing??[],incoming:o.incoming??[]}}}function rp(e,t){return Oe(e,t),At(()=>e.prepare(`WITH RECURSIVE subtree(id) AS (
|
|
180
180
|
SELECT ? UNION ALL SELECT e.id FROM entities e JOIN subtree s ON e.parent_id = s.id
|
|
181
181
|
)
|
|
182
|
-
SELECT e.* FROM entities e JOIN subtree s ON e.id = s.id ORDER BY e.id`).all(t))}function Lr(e,t){let r=
|
|
183
|
-
`),a(null))}function f(h){c||(c=!0,clearTimeout(p),a(h))}let p=setTimeout(()=>{try{d.kill("SIGTERM")}catch{}setTimeout(()=>{if(d.exitCode===null&&d.signalCode===null)try{d.kill("SIGKILL")}catch{}},2e3).unref(),m("timeout")},r);d.stdout.on("data",h=>{l+=h.toString("utf8")}),d.stderr.on("data",h=>{u+=h.toString("utf8")}),d.on("error",h=>m(h.message)),d.on("close",h=>{if(c)return;if(h!==0){m(`exit code ${h}`);return}let g=l.trim();if(!g){m("empty output");return}f(g)}),d.stdin.write(e),d.stdin.end()})}var
|
|
182
|
+
SELECT e.* FROM entities e JOIN subtree s ON e.id = s.id ORDER BY e.id`).all(t))}function Lr(e,t){let r=rp(e,t),n=new Map(r.map(o=>[o.id,{...o,children:[]}]));for(let o of r)o.id!==t&&o.parent_id!==null&&n.get(o.parent_id).children.push(n.get(o.id));return n.get(t)}function Qf(e){let t={total:e.length,by_status:{},by_kind:{},by_delivery:{delivered:0,undelivered:0}};for(let r of e)t.by_status[r.status]=(t.by_status[r.status]??0)+1,t.by_kind[r.kind]=(t.by_kind[r.kind]??0)+1,r.kind!=="epic"&&(r.delivered_ts!=null?t.by_delivery.delivered+=1:t.by_delivery.undelivered+=1);return t}function Cr(e,t={}){if(t.id!==void 0&&t.project!==void 0)throw new C("INVALID_ARGUMENT","summary ID and --project are exclusive");if(t.id!==void 0)return Qf(rp(e,t.id));let r=At(()=>t.project!==void 0?e.prepare("SELECT * FROM entities WHERE project = ?").all(t.project):e.prepare("SELECT * FROM entities").all());return Qf(r)}function mi(e,t,r){let n=e.transaction(()=>{let o=Oe(e,t);if(r.ifRevision!==void 0&&o.revision!==r.ifRevision)throw new C("REVISION_CONFLICT",`Expected revision ${r.ifRevision}; current is ${o.revision}`,4);let s={};r.title!==void 0&&(s.title=Ee(r.title,"title")),r.status!==void 0&&(s.status=Ee(r.status.trim(),"status"));for(let[a,c]of[["description",r.description],["requirements",r.requirements],["acceptance_criteria",r.acceptanceCriteria]])c!==void 0&&(s[a]=c);if(r.owner!==void 0&&r.clearOwner)throw new C("INVALID_ARGUMENT","Explicit owner and --clear-owner are exclusive");if(r.parentId!==void 0||r.clearParent){let a=r.clearParent?null:r.parentId;try{Zf(e,o.kind,o.project,a)}catch(c){if(c instanceof C)throw c;Ln(c)}s.parent_id=a}r.owner!==void 0?(s.owner_team_path=Rt(Ee(r.owner.team,"owner team")),s.owner_alias=Ee(r.owner.alias,"owner alias")):r.clearOwner&&(s.owner_team_path=null,s.owner_alias=null);let i=r.holdUntil!==void 0||r.holdReason!==void 0;if(i&&r.clearHold)throw new C("INVALID_ARGUMENT","A hold (holdUntil/holdReason) and clearHold are exclusive");if(i){if(r.holdUntil===void 0||r.holdReason===void 0)throw new C("INVALID_ARGUMENT","holdUntil and holdReason must be given together");let a=Ee(r.holdUntil,"holdUntil");if(Number.isNaN(Date.parse(a)))throw new C("INVALID_ARGUMENT",`holdUntil "${a}" is not a parseable timestamp`,2);s.hold_until=a,s.hold_reason=Ee(r.holdReason,"holdReason")}else r.clearHold&&(s.hold_until=null,s.hold_reason=null);if(r.blockedOn!==void 0&&r.clearBlockedOn)throw new C("INVALID_ARGUMENT","blockedOn and clearBlockedOn are exclusive");if(r.blockedOn!==void 0?s.blocked_on=Ee(r.blockedOn,"blockedOn"):r.clearBlockedOn&&(s.blocked_on=null),Object.keys(s).length===0)throw new C("INVALID_ARGUMENT","Update requires at least one field");try{e.prepare(`UPDATE entities SET ${Object.keys(s).map(a=>`${a} = ?`).join(",")} WHERE id = ?`).run(...Object.values(s),t)}catch(a){Ln(a)}return s.status!==void 0&&s.status!==o.status&&e.prepare("INSERT INTO notes(entity_id, body, author_team_path, author_alias, created_at) VALUES (?,?,?,?,?)").run(t,JSON.stringify({[Rr]:!0,from:o.status,to:s.status}),null,null,me()),di(e,t),Oe(e,t)});return At(n)}function np(e,t,r){e.prepare("UPDATE entities SET delivered_ts = ? WHERE id = ? AND delivered_ts IS NULL").run(r,t)}function op(e,t,r,n,o){o.needsReview?e.prepare("UPDATE entities SET review_time = ?, needs_review = 1, review_reason = ?, review_input_hash = ? WHERE id = ?").run(r,o.reason,n,t):e.prepare("UPDATE entities SET review_time = ?, needs_review = 0, review_reason = NULL, review_input_hash = ? WHERE id = ?").run(r,n,t)}function zt(e,t,r){let n=e.transaction(()=>{Oe(e,t);let o=r.author!==void 0?Rt(Ee(r.author.team,"author team")):null,s=r.author!==void 0?Ee(r.author.alias,"author alias"):null,i=e.prepare("INSERT INTO notes(entity_id, body, author_team_path, author_alias, created_at) VALUES (?,?,?,?,?)").run(t,Ee(r.body,"body"),o,s,me());return di(e,t),{note:e.prepare("SELECT * FROM notes WHERE id = ?").get(i.lastInsertRowid),revision:Oe(e,t).revision}});return At(n)}function Gc(e,t,r={}){return Oe(e,t),ep(e,"SELECT * FROM notes WHERE entity_id = ? AND id > ?",[t,r.after??0],r.limit??100)}function Kt(e){try{let t=JSON.parse(e);return t!==null&&typeof t=="object"&&!Array.isArray(t)?t:null}catch{return null}}function fi(e,t){let r=e.prepare("SELECT body, created_at FROM notes WHERE entity_id = ? ORDER BY id DESC").all(t);for(let n of r){let o=Kt(n.body);if(o!==null&&o[Rr]===!0)return n.created_at}return null}function Cn(e,t){return At(()=>e.prepare("SELECT * FROM notes WHERE entity_id = ? ORDER BY id DESC").all(t).find(n=>Kt(n.body)===null)??null)}function sp(e,t,r={}){let{rows:n,meta:o}=Gc(e,t,r);return{rows:n.map(s=>({...s,noteType:Kt(s.body)===null?"authored":"system"})),meta:o}}function ip(e,t,r){if(Oe(e,t),Oe(e,r),t===r)throw new C("SELF_DEPENDENCY","An entity cannot depend on itself")}function ap(e,t,r){let n=e.transaction(()=>{ip(e,t,r);let o;try{o=e.prepare("INSERT OR IGNORE INTO dependencies(entity_id, depends_on_id, created_at) VALUES (?,?,?)").run(t,r,me()).changes>0}catch(s){return Ln(s)}return o&&di(e,t),{entity_id:t,depends_on_id:r,changed:o,revision:Oe(e,t).revision}});return At(n)}function cp(e,t,r){let n=e.transaction(()=>{ip(e,t,r);let s=e.prepare("DELETE FROM dependencies WHERE entity_id = ? AND depends_on_id = ?").run(t,r).changes>0;return s&&di(e,t),{entity_id:t,depends_on_id:r,changed:s,revision:Oe(e,t).revision}});return At(n)}var fx=new Set(["todo","in-progress"]),On=new Set(["task","subtask"]),Yt="on-hold";function ue(e){return e.trim().toLowerCase().replace(/[\s_]+/g,"-")}var gi="blocked",Dn=new Set(["done","closed"]);function Et(e){return Dn.has(ue(e))}function yi(e){return e.kind==="epic"&&!Et(e.status)&&ue(e.status)!==Yt}var _i=new Set(["rate-limited","error"]);function Re(e,t,r){let n=e.prepare("SELECT * FROM entities WHERE owner_team_path = ? AND owner_alias = ? ORDER BY id").all(Rt(t),r);return n.length===0?null:{entities:n}}function wi(e,t){return(mt(e,t.id,"outgoing").outgoing??[]).some(n=>ue(n.status)!=="done")}var px=45*6e4;function lp(e,t={}){let r=t.nowMs??Date.now(),n=t.staleInProgressThresholdMs??px,o=t.project!==void 0?e.prepare("SELECT * FROM entities WHERE project = ? ORDER BY id LIMIT ?").all(t.project,Le):e.prepare("SELECT * FROM entities ORDER BY id LIMIT ?").all(Le),s=[];for(let i of o){if(!On.has(i.kind))continue;let a=ue(i.status);if(a===gi){s.push({...i,attentionReason:"blocked"});continue}if(a==="in-progress"){r-new Date(i.updated_at).getTime()>=n&&s.push({...i,attentionReason:"stale_in_progress"});continue}a==="todo"&&(mt(e,i.id,"outgoing").outgoing??[]).length>0&&!wi(e,i)&&s.push({...i,attentionReason:"dependency_ready"})}return s}function zc(e){let t=ue(e);return t==="done"||t===Yt}function hi(e,t){return e.prepare("SELECT * FROM entities WHERE parent_id = ?").all(t).some(n=>!zc(n.status))}function Jc(e,t){return e.transaction(()=>{let n=dt(e,t);if(n===null)return null;let o=e.prepare("SELECT * FROM notes WHERE entity_id = ? ORDER BY id DESC").all(t),s=null,i=null,a=null;for(let c of o){let l=Kt(c.body);if(l!==null){if(l[Rr]===!0){i=c.id,a=c.created_at;break}s===null&&(s=l)}}return{id:n.id,title:n.title,status:n.status,attrs:s,epochId:i,epochTs:a,createdAt:n.created_at,ownerTeamPath:n.owner_team_path,ownerAlias:n.owner_alias}})()}function Po(e,t,r,n=Date.now(),o){let s=o!==void 0?new Map:new Map(t.entities.map(u=>[u.id,u])),a=t.entities.filter(u=>On.has(u.kind)&&!Qt(e,u,s)).filter(u=>_i.has(ue(u.status))),c=o!==void 0?Rt(o.team):null,l=[];for(let u of a){let d=Jc(e,u.id);if(d===null||!_i.has(ue(d.status))||o!==void 0&&(d.ownerTeamPath!==c||d.ownerAlias!==o.alias))continue;let m=typeof d.attrs?.expected_reset_ts=="string"?Date.parse(d.attrs.expected_reset_ts):NaN;if(Number.isNaN(m)){let f=Date.parse(d.epochTs??d.createdAt);if(!Number.isNaN(f)&&n-f<r)continue}else if(m>n)continue;l.push({id:d.id,title:d.title,status:d.status})}return l}function hx(e,t){return e.prepare("SELECT * FROM notes WHERE entity_id = ?").all(t).some(n=>Kt(n.body)===null)}function Qt(e,t,r){let n=t,o=new Set;for(;n!==null&&n.parent_id!==null&&!o.has(n.id);){o.add(n.id);let s=r.get(n.parent_id)??dt(e,n.parent_id);if(s===null)return!1;if(s.kind==="epic")return Et(s.status)||ue(s.status)===Yt;n=s}return!1}function Mn(e,t){let r=new Map(t.entities.map(n=>[n.id,n]));return t.entities.filter(n=>On.has(n.kind)&&ue(n.status)===gi&&!Qt(e,n,r))}var Kc=24*60*6e4,gx="DESIGN-FIRST:";function up(e,t,r=Kc,n=Date.now()){let o=new Map(t.entities.map(s=>[s.id,s]));return t.entities.filter(s=>On.has(s.kind)&&ue(s.status)==="todo"&&s.title.startsWith(gx)&&n-Date.parse(s.updated_at)>=r&&!Qt(e,s,o)&&!wi(e,s)).map(s=>({id:s.id,title:s.title,updatedAt:s.updated_at}))}function dp(e,t,r=Date.now()){let n=new Map(t.entities.map(o=>[o.id,o]));return t.entities.filter(o=>On.has(o.kind)&&o.hold_until!==null&&Date.parse(o.hold_until)<=r&&!Qt(e,o,n)).map(o=>({id:o.id,title:o.title,holdUntil:o.hold_until,holdReason:o.hold_reason}))}function _x(e,t){return e.prepare("SELECT 1 FROM entities WHERE parent_id = ? LIMIT 1").get(t)!==void 0}function wx(e,t){return t.entities.filter(n=>n.kind==="epic"&&!Et(n.status)&&ue(n.status)!==Yt).filter(n=>_x(e,n.id)&&!hi(e,n.id))}function pi(e){return`'${e.replace(/'/g,"'\\''")}'`}var yx=3e4;function Vc(e,t={}){let r=t.timeoutMs??yx,o=[...t.spawnPrefix??["miniplayer"],"run",...t.model!==void 0?["-m",t.model]:[]],[s,...i]=o;return new Promise(a=>{let c=!1,l="",u="",d=mx(s,i,{stdio:["pipe","pipe","pipe"]});function m(h){c||(c=!0,clearTimeout(p),process.stderr.write(`[lmtasks-nudge] miniplayer run failed (${h}), falling back to the generic nudge: ${u.trim().slice(-500)}
|
|
183
|
+
`),a(null))}function f(h){c||(c=!0,clearTimeout(p),a(h))}let p=setTimeout(()=>{try{d.kill("SIGTERM")}catch{}setTimeout(()=>{if(d.exitCode===null&&d.signalCode===null)try{d.kill("SIGKILL")}catch{}},2e3).unref(),m("timeout")},r);d.stdout.on("data",h=>{l+=h.toString("utf8")}),d.stderr.on("data",h=>{u+=h.toString("utf8")}),d.on("error",h=>m(h.message)),d.on("close",h=>{if(c)return;if(h!==0){m(`exit code ${h}`);return}let g=l.trim();if(!g){m("empty output");return}f(g)}),d.stdin.write(e),d.stdin.end()})}var Ex="ollama/qwen2.5:14b",bx=5e3,Tx="deepseek/deepseek-flash";async function Ei(e,t={}){if(t.model!==void 0)return Vc(e,t);let r=await Vc(e,{...t,model:Ex,timeoutMs:t.timeoutMs??bx});return r!==null?r:Vc(e,{...t,model:Tx})}var Sx=15*6e4;function vx(e){let t=e.filter(r=>r.kind==="epic"&&!Et(r.status)&&ue(r.status)!==Yt);return t.length===1?t[0]:null}async function mp(e,t,r={}){let n=r.backoffMs??Sx,o=t.entities[0];o?.owner_team_path!==void 0&&o.owner_team_path!==null&&o.owner_alias!==null&&(t=Re(e,o.owner_team_path,o.owner_alias)??{entities:[]});let s=new Map(t.entities.map(A=>[A.id,A])),i=t.entities.filter(A=>On.has(A.kind)&&!Qt(e,A,s)),a=i.filter(A=>_i.has(ue(A.status))),c=null,l=!1;for(let A of a){let H=Jc(e,A.id);if(H===null||!_i.has(ue(H.status)))continue;l=!0;let L=Date.now(),w=typeof H.attrs?.expected_reset_ts=="string"?Date.parse(H.attrs.expected_reset_ts):NaN;if(!Number.isNaN(w)&&w>L)continue;let b=typeof H.attrs?.last_renudge_ts=="string"?Date.parse(H.attrs.last_renudge_ts):NaN;if(!(!Number.isNaN(b)&&L-b<n)){c=H;break}}if(l){if(c===null)return null;let A=c.id,H=c.epochId;return{message:`Task #${c.id} ("${c.title}") is marked ${c.status} -- not nudging further; report status if this persists.`,onSent:()=>{e.transaction(()=>{let N=Jc(e,A);N===null||N.epochId!==H||zt(e,A,{body:JSON.stringify({...N.attrs??{},last_renudge_ts:new Date().toISOString()})})}).immediate()}}}let u=Mn(e,t),d=u.length>0?`
|
|
184
184
|
|
|
185
|
-
(Also: ${u.length} task(s) marked blocked, including #${u[0].id} ("${u[0].title}") -- pending meta-lead review, no action needed from you on ${u.length===1?"it":"these"} right now.)`:"",m=
|
|
185
|
+
(Also: ${u.length} task(s) marked blocked, including #${u[0].id} ("${u[0].title}") -- pending meta-lead review, no action needed from you on ${u.length===1?"it":"these"} right now.)`:"",m=wx(e,t),f=t.entities[0],p=f?.owner_team_path!==null&&f?.owner_team_path!==void 0&&f?.owner_alias!==null&&f?.owner_alias!==void 0?` --owner-team ${pi(f.owner_team_path)} --owner-alias ${pi(f.owner_alias)}`:"",h=A=>`#${A.id} ("${A.title}") -- \`lmauto tasks create task --parent ${A.id} --title "..."${p}\` to add the next one, or \`lmauto tasks update ${A.id} --status done\` if it's genuinely complete`,g=m.length>0?`
|
|
186
186
|
|
|
187
|
-
(Also: ${m.length} epic(s) have all tasks done: ${m.map(h).join("; ")}.)`:"",_=i.filter(A=>ue(A.status)==="done").map(A=>{let H=[];return wi(e,A)&&H.push("still has an unmet dependency"),hi(e,A.id)&&H.push("still has an incomplete subtask"),{entity:A,reasons:H}}).filter(A=>A.reasons.length>0);if(_.length>0){let{entity:A,reasons:H}=_[0];return{message:`${A.kind==="subtask"?"Subtask":"Task"} #${A.id} ("${A.title}") is marked done but ${H.join(" and ")} -- please double-check and resolve the contradiction (confirm it's genuinely finished, or reopen it if something was missed).`}}let E=i.filter(A=>ue(A.status)==="done"&&!
|
|
187
|
+
(Also: ${m.length} epic(s) have all tasks done: ${m.map(h).join("; ")}.)`:"",_=i.filter(A=>ue(A.status)==="done").map(A=>{let H=[];return wi(e,A)&&H.push("still has an unmet dependency"),hi(e,A.id)&&H.push("still has an incomplete subtask"),{entity:A,reasons:H}}).filter(A=>A.reasons.length>0);if(_.length>0){let{entity:A,reasons:H}=_[0];return{message:`${A.kind==="subtask"?"Subtask":"Task"} #${A.id} ("${A.title}") is marked done but ${H.join(" and ")} -- please double-check and resolve the contradiction (confirm it's genuinely finished, or reopen it if something was missed).`}}let E=i.filter(A=>ue(A.status)==="done"&&!hx(e,A.id));if(E.length>0){let A=E[0];return{message:`Task #${A.id} ("${A.title}") is marked done -- close it out (commit/publish/report as appropriate), then \`lmauto tasks note add ${A.id} --body "<what you did>"\` to confirm, or update its status if it needs to be reopened.`+d+g}}let y=i.filter(A=>fx.has(ue(A.status))&&ue(A.status)!==Yt&&!hi(e,A.id));if(y.length===0){let A=i.filter($=>{let q=ue($.status);return q!==gi&&q!==Yt&&hi(e,$.id)});if(A.length>0){let $=A[0];return{message:`${$.kind==="subtask"?"Subtask":"Task"} #${$.id} ("${$.title}") has an incomplete subtask -- check \`lmauto tasks show ${$.id}\` for what's left.`+d+g}}let H=i.filter($=>ue($.status)===Yt),L=i.filter($=>ue($.status)!==Yt&&ue($.status)!==gi),w=t.entities.some($=>$.kind==="epic"&&!Et($.status)&&ue($.status)!==Yt);if(L.length===0&&!w)return null;if(m.length>1)return{message:`${m.length} of your open epics have all tasks done: ${m.map(h).join("; ")}.`};let b=vx(t.entities),N=t.entities[0],D=N?.owner_team_path,W=N?.owner_alias,ee=D!=null&&W!==null&&W!==void 0?` --owner-team ${pi(D)} --owner-alias ${pi(W)}`:"",ne=b!==null?String(b.id):"<epic-id>",J=b!==null?`lmauto tasks update ${b.id} --status done`:"<lmauto tasks update EPIC_ID --status done>",oe=H.length>0&&u.length>0?"All your non-blocked/non-held tracked tasks are done.":H.length>0?"All your non-held tracked tasks are done.":u.length>0?"All your non-blocked tracked tasks are done.":"All your tracked tasks are done.",k=[];H.length>0&&k.push(`${H.length} other task(s) remain on_hold -- not done, just parked`),u.length>0&&k.push(`${u.length} task(s) remain blocked, pending meta-lead review`);let O=k.length>0?` (${k.join("; ")}; resolve those before treating the epic as complete.)`:"";return b===null&&!w?{message:`${oe}${O}`}:{message:`${oe}${O} Either \`lmauto tasks create task --parent ${ne} --title "..."${ee}\` to add the next one, or if the epic is genuinely complete, \`${J}\`.`}}let S=y.filter(A=>!wi(e,A));if(S.length===0){let A=y[0];return{message:`All ${y.length} of your tracked todo/in-progress task(s) are blocked on an unmet dependency, including #${A.id} ("${A.title}") -- check \`lmauto tasks show ${A.id}\` and report if you're stuck.`+d+g}}let T=S.filter(A=>ue(A.status)==="in-progress"||A.delivered_ts!=null),R=T.length>0?T[0]:S[0],x=R.delivered_ts==null?()=>np(e,R.id,new Date().toISOString()):void 0;if(S.length===1){let A=R.description.trim();return{message:`Continue task #${R.id}: "${R.title}" (status: ${R.status}).${A?`
|
|
188
188
|
|
|
189
189
|
${A}`:""}${d}${g}`,onSent:x}}let I=R.description.trim();return{message:`Continue task #${R.id}: "${R.title}" (status: ${R.status}).${I?`
|
|
190
190
|
|
|
191
191
|
${I}`:""}
|
|
192
192
|
|
|
193
|
-
(${S.length-1} other ready task(s) also available: \`lmauto tasks list --owner-team <path> --owner-alias <alias> --status todo\`.)`+d+g,onSent:x}}var he={idleThresholdMs:45*6e4,cooldownMs:30*6e4};function vx(e,t){return t.running.some(r=>kn(e,r.from_identity))}function cn(e,t){return t.dead.some(r=>kn(e,r.target))&&!je(e,t)}function Kc(e){if(e.isCurrentlyActive)return!1;let t=!e.hasInFlightWorker,r=e.timeSinceLastNudgeMs===null||e.timeSinceLastNudgeMs>e.config.cooldownMs;if(e.isDeadReclaimable)return t&&r;let n=!e.isCoordinator&&e.progressStatus==="UNKNOWN"&&(e.progressAgeMs===null||e.progressAgeMs>=e.config.idleThresholdMs),o=!e.heavyLockMayBeHeldByThisTeam&&e.hasStalePersistentInProgressWork;return t&&r&&(e.neverDispatched||n||o)}function Qc(e,t,r,n){let o;try{o=Q(t)}catch{return!1}let s=Re(e,o,t.leadAlias);if(s===null)return!1;let i=new Map(s.entities.map(a=>[a.id,a]));return s.entities.some(a=>(a.kind==="task"||a.kind==="subtask")&&ue(a.status)==="in-progress"&&!Qt(e,a,i)&&n-Date.parse(a.updated_at)>=r&&!Xc(a,n))}function Xc(e,t){return e.hold_until!==null&&Date.parse(e.hold_until)>t}function Zc(e,t){if(qe(e,t.name)!==null||Jf(e,t.name))return!1;let r;try{r=Q(t)}catch{return!0}return Re(e,r,t.leadAlias)===null}function Ax(e){return Kc({...e,config:{...e.config,idleThresholdMs:0}})}function mp(e){return`last_nudged:${e}`}function el(e,t){return e.prepare("SELECT v FROM kv WHERE k = ?").get(mp(t))?.v??null}function Uo(e,t,r){e.prepare("INSERT INTO kv(k, v) VALUES (?, ?) ON CONFLICT(k) DO UPDATE SET v = excluded.v").run(mp(t),r)}function fp(e,t,r,n,o,s,i){if(qe(e,t.name)?.status==="BLOCKED")return null;let c=Zc(e,t),l=s?.progress_changed_ts==null?null:o-Date.parse(s.progress_changed_ts),u=el(e,t.name),d=u===null?null:o-Date.parse(u);return{isCurrentlyActive:je(t,r),hasInFlightWorker:vx(t,r),neverDispatched:c,progressStatus:s?.progress_status??null,progressAgeMs:l,isDeadReclaimable:cn(t,r),hasStalePersistentInProgressWork:Qc(e,t,n.idleThresholdMs,o),timeSinceLastNudgeMs:d,config:n,isCoordinator:t.coordinator===!0,heavyLockMayBeHeldByThisTeam:i.held&&(i.holder===null||i.holder.holder===t.name)}}function pp(e,t,r,n,o,s,i){let a=fp(e,t,r,o,s,i,n);return a!==null&&Kc(a)}async function tl(e,t,r,n,o=he,s=Date.now()){let i=await yc(e,t,t.name,s);return pp(e,t,r,n,o,s,i)}function rl(e,t,r,n,o=he,s=Date.now()){return pp(e,t,r,n,o,s,ie(e,t.name))}async function Pn(e,t,r,n,o=he,s=Date.now(),i={}){let a=[];for(let c of t){if(!c.autoNudge||ie(e,c.name)?.confirmed_done_ts)continue;(i.readOnly?rl(e,c,r,n,o,s):await tl(e,c,r,n,o,s))&&!ie(e,c.name)?.confirmed_done_ts&&a.push(c.name)}return a}async function hp(e,t,r,n,o=he,s=Date.now()){let i=[],a=[];for(let c of t){if(!c.autoNudge||ie(e,c.name)?.confirmed_done_ts)continue;let l=await yc(e,c,c.name,s);if(ie(e,c.name)?.confirmed_done_ts)continue;let u=fp(e,c,r,o,s,l,n);u!==null&&(Kc(u)&&i.push(c.name),Ax(u)&&a.push(c.name))}return{stalled:i,continueEligible:a}}import{existsSync as gp,readFileSync as _p}from"node:fs";import{dirname as ol,join as wp}from"node:path";import{fileURLToPath as yp}from"node:url";var nl={sha:"unknown",dirty:!0,builtAt:"unknown"};function $x(e){if(typeof e!="object"||e===null)return!1;let t=e;return typeof t.sha=="string"&&typeof t.dirty=="boolean"&&typeof t.builtAt=="string"}function Ep(){let e=ol(yp(import.meta.url));for(let t=0;t<5;t+=1){let r=wp(e,"package.json");if(gp(r))try{let n=JSON.parse(_p(r,"utf8"));if(n&&typeof n=="object"&&typeof n.version=="string")return n.version}catch{}e=ol(e)}return"unknown"}function sl(){let e=wp(ol(yp(import.meta.url)),"..","build-info.json");if(!gp(e))return nl;try{let t=JSON.parse(_p(e,"utf8"));return $x(t)?t:nl}catch{return nl}}var kx="https://ecezfoozb3.execute-api.us-east-1.amazonaws.com/prod";function Nt(e){return(e.LMCTL_LMMAIL_API_URL?.trim()||e.LMMAIL_API_URL?.trim()||kx).replace(/\/+$/,"")}import{createServer as xx}from"http";import{Http2ServerRequest as Sp,constants as Rx}from"http2";import{Http2ServerRequest as il}from"http2";import{Readable as bp}from"stream";import qx from"crypto";var ln=class extends Error{constructor(e,t){super(e,t),this.name="RequestError"}},Nx=e=>e instanceof ln?e:new ln(e.message,{cause:e}),Ix=global.Request,Fo=class extends Ix{constructor(e,t){typeof e=="object"&&qn in e&&(e=e[qn]()),typeof t?.body?.getReader<"u"&&(t.duplex??="half"),super(e,t)}},Lx=e=>{let t=[],r=e.rawHeaders;for(let n=0;n<r.length;n+=2){let{[n]:o,[n+1]:s}=r;o.charCodeAt(0)!==58&&t.push([o,s])}return new Headers(t)},vp=Symbol("wrapBodyStream"),Cx=(e,t,r,n,o)=>{let s={method:e,headers:r,signal:o.signal};if(e==="TRACE"){s.method="GET";let i=new Fo(t,s);return Object.defineProperty(i,"method",{get(){return"TRACE"}}),i}if(!(e==="GET"||e==="HEAD"))if("rawBody"in n&&n.rawBody instanceof Buffer)s.body=new ReadableStream({start(i){i.enqueue(n.rawBody),i.close()}});else if(n[vp]){let i;s.body=new ReadableStream({async pull(a){try{i||=bp.toWeb(n).getReader();let{done:c,value:l}=await i.read();c?a.close():a.enqueue(l)}catch(c){a.error(c)}}})}else s.body=bp.toWeb(n);return new Fo(t,s)},qn=Symbol("getRequestCache"),Ap=Symbol("requestCache"),bi=Symbol("incomingKey"),Ti=Symbol("urlKey"),Ox=Symbol("headersKey"),Fn=Symbol("abortControllerKey"),Dx=Symbol("getAbortController"),qo={get method(){return this[bi].method||"GET"},get url(){return this[Ti]},get headers(){return this[Ox]||=Lx(this[bi])},[Dx](){return this[qn](),this[Fn]},[qn](){return this[Fn]||=new AbortController,this[Ap]||=Cx(this.method,this[Ti],this.headers,this[bi],this[Fn])}};["body","bodyUsed","cache","credentials","destination","integrity","mode","redirect","referrer","referrerPolicy","signal","keepalive"].forEach(e=>{Object.defineProperty(qo,e,{get(){return this[qn]()[e]}})});["arrayBuffer","blob","clone","formData","json","text"].forEach(e=>{Object.defineProperty(qo,e,{value:function(){return this[qn]()[e]()}})});Object.defineProperty(qo,Symbol.for("nodejs.util.inspect.custom"),{value:function(e,t,r){let n={method:this.method,url:this.url,headers:this.headers,nativeRequest:this[Ap]};return`Request (lightweight) ${r(n,{...t,depth:e==null?null:e-1})}`}});Object.setPrototypeOf(qo,Fo.prototype);var Mx=(e,t)=>{let r=Object.create(qo);r[bi]=e;let n=e.url||"";if(n[0]!=="/"&&(n.startsWith("http://")||n.startsWith("https://"))){if(e instanceof il)throw new ln("Absolute URL for :path is not allowed in HTTP/2");try{let a=new URL(n);r[Ti]=a.href}catch(a){throw new ln("Invalid absolute URL",{cause:a})}return r}let o=(e instanceof il?e.authority:e.headers.host)||t;if(!o)throw new ln("Missing host header");let s;if(e instanceof il){if(s=e.scheme,!(s==="http"||s==="https"))throw new ln("Unsupported scheme")}else s=e.socket&&e.socket.encrypted?"https":"http";let i=new URL(`${s}://${o}${n}`);if(i.hostname.length!==o.length&&i.hostname!==o.replace(/:\d+$/,""))throw new ln("Invalid host header");return r[Ti]=i.href,r},cl=Symbol("responseCache"),Un=Symbol("getResponseCache"),un=Symbol("cache"),dl=global.Response,jn=class $p{#t;#e;[Un](){return delete this[un],this[cl]||=new dl(this.#t,this.#e)}constructor(t,r){let n;if(this.#t=t,r instanceof $p){let o=r[cl];if(o){this.#e=o,this[Un]();return}else this.#e=r.#e,n=new Headers(r.#e.headers)}else this.#e=r;(typeof t=="string"||typeof t?.getReader<"u"||t instanceof Blob||t instanceof Uint8Array)&&(this[un]=[r?.status||200,t,n||r?.headers])}get headers(){let t=this[un];return t?(t[2]instanceof Headers||(t[2]=new Headers(t[2]||{"content-type":"text/plain; charset=UTF-8"})),t[2]):this[Un]().headers}get status(){return this[un]?.[0]??this[Un]().status}get ok(){let t=this.status;return t>=200&&t<300}};["body","bodyUsed","redirected","statusText","trailers","type","url"].forEach(e=>{Object.defineProperty(jn.prototype,e,{get(){return this[Un]()[e]}})});["arrayBuffer","blob","clone","formData","json","text"].forEach(e=>{Object.defineProperty(jn.prototype,e,{value:function(){return this[Un]()[e]()}})});Object.defineProperty(jn.prototype,Symbol.for("nodejs.util.inspect.custom"),{value:function(e,t,r){let n={status:this.status,headers:this.headers,ok:this.ok,nativeResponse:this[cl]};return`Response (lightweight) ${r(n,{...t,depth:e==null?null:e-1})}`}});Object.setPrototypeOf(jn,dl);Object.setPrototypeOf(jn.prototype,dl.prototype);async function Px(e){return Promise.race([e,Promise.resolve().then(()=>Promise.resolve(void 0))])}function kp(e,t,r){let n=a=>{e.cancel(a).catch(()=>{})};return t.on("close",n),t.on("error",n),(r??e.read()).then(i,o),e.closed.finally(()=>{t.off("close",n),t.off("error",n)});function o(a){a&&t.destroy(a)}function s(){e.read().then(i,o)}function i({done:a,value:c}){try{if(a)t.end();else if(!t.write(c))t.once("drain",s);else return e.read().then(i,o)}catch(l){o(l)}}}function Ux(e,t){if(e.locked)throw new TypeError("ReadableStream is locked.");return t.destroyed?void 0:kp(e.getReader(),t)}var ll=e=>{let t={};e instanceof Headers||(e=new Headers(e??void 0));let r=[];for(let[n,o]of e)n==="set-cookie"?r.push(o):t[n]=o;return r.length>0&&(t["set-cookie"]=r),t["content-type"]??="text/plain; charset=UTF-8",t},Fx="x-hono-already-sent";typeof global.crypto>"u"&&(global.crypto=qx);var ml=Symbol("outgoingEnded"),Tp=Symbol("incomingDraining"),jx=500,Hx=64*1024*1024,al=e=>{let t=e;if(e.destroyed||t[Tp])return;if(t[Tp]=!0,e instanceof Sp){try{e.stream?.close?.(Rx.NGHTTP2_NO_ERROR)}catch{}return}let r=0,n=()=>{clearTimeout(s),e.off("data",i),e.off("end",n),e.off("error",n)},o=()=>{n();let a=e.socket;a&&!a.destroyed&&a.destroySoon()},s=setTimeout(o,jx);s.unref?.();let i=a=>{r+=a.length,r>Hx&&o()};e.on("data",i),e.on("end",n),e.on("error",n),e.resume()},Bx=()=>new Response(null,{status:400}),xp=e=>new Response(null,{status:e instanceof Error&&(e.name==="TimeoutError"||e.constructor.name==="TimeoutError")?504:500}),ul=(e,t)=>{let r=e instanceof Error?e:new Error("unknown error",{cause:e});r.code==="ERR_STREAM_PREMATURE_CLOSE"?console.info("The user aborted a request."):(console.error(e),t.headersSent||t.writeHead(500,{"Content-Type":"text/plain"}),t.end(`Error: ${r.message}`),t.destroy(r))},Rp=e=>{"flushHeaders"in e&&e.writable&&e.flushHeaders()},Np=async(e,t)=>{let[r,n,o]=e[un],s=!1;if(!o)o={"content-type":"text/plain; charset=UTF-8"};else if(o instanceof Headers)s=o.has("content-length"),o=ll(o);else if(Array.isArray(o)){let i=new Headers(o);s=i.has("content-length"),o=ll(i)}else for(let i in o)if(i.length===14&&i.toLowerCase()==="content-length"){s=!0;break}s||(typeof n=="string"?o["Content-Length"]=Buffer.byteLength(n):n instanceof Uint8Array?o["Content-Length"]=n.byteLength:n instanceof Blob&&(o["Content-Length"]=n.size)),t.writeHead(r,o),typeof n=="string"||n instanceof Uint8Array?t.end(n):n instanceof Blob?t.end(new Uint8Array(await n.arrayBuffer())):(Rp(t),await Ux(n,t)?.catch(i=>ul(i,t))),t[ml]?.()},Wx=e=>typeof e.then=="function",Gx=async(e,t,r={})=>{if(Wx(e))if(r.errorHandler)try{e=await e}catch(o){let s=await r.errorHandler(o);if(!s)return;e=s}else e=await e.catch(xp);if(un in e)return Np(e,t);let n=ll(e.headers);if(e.body){let o=e.body.getReader(),s=[],i=!1,a;if(n["transfer-encoding"]!=="chunked"){let c=2;for(let l=0;l<c;l++){a||=o.read();let u=await Px(a).catch(d=>{console.error(d),i=!0});if(!u){if(l===1){await new Promise(d=>setTimeout(d)),c=3;continue}break}if(a=void 0,u.value&&s.push(u.value),u.done){i=!0;break}}i&&!("content-length"in n)&&(n["content-length"]=s.reduce((l,u)=>l+u.length,0))}t.writeHead(e.status,n),s.forEach(c=>{t.write(c)}),i?t.end():(s.length===0&&Rp(t),await kp(o,t,a))}else n[Fx]||(t.writeHead(e.status,n),t.end());t[ml]?.()},Vx=(e,t={})=>{let r=t.autoCleanupIncoming??!0;return t.overrideGlobalObjects!==!1&&global.Request!==Fo&&(Object.defineProperty(global,"Request",{value:Fo}),Object.defineProperty(global,"Response",{value:jn})),async(n,o)=>{let s,i;try{i=Mx(n,t.hostname);let a=!r||n.method==="GET"||n.method==="HEAD";if(a||(n[vp]=!0,n.on("end",()=>{a=!0}),n instanceof Sp&&(o[ml]=()=>{a||setTimeout(()=>{a||setTimeout(()=>{al(n)})})}),o.on("finish",()=>{a||al(n)})),o.on("close",()=>{i[Fn]&&(n.errored?i[Fn].abort(n.errored.toString()):o.writableFinished||i[Fn].abort("Client connection prematurely closed.")),a||setTimeout(()=>{a||setTimeout(()=>{al(n)})})}),s=e(i,{incoming:n,outgoing:o}),un in s)return Np(s,o)}catch(a){if(s)return ul(a,o);if(t.errorHandler){if(s=await t.errorHandler(i?a:Nx(a)),!s)return}else i?s=xp(a):s=Bx()}try{return await Gx(s,o,t)}catch(a){return ul(a,o)}}},Jx=e=>{let t=e.fetch,r=Vx(t,{hostname:e.hostname,overrideGlobalObjects:e.overrideGlobalObjects,autoCleanupIncoming:e.autoCleanupIncoming});return(e.createServer||xx)(e.serverOptions||{},r)},Ip=(e,t)=>{let r=Jx(e);return r.listen(e?.port??3e3,e.hostname,()=>{let n=r.address();t&&t(n)}),r};var fl=(e,t,r)=>(n,o)=>{let s=-1;return i(0);async function i(a){if(a<=s)throw new Error("next() called multiple times");s=a;let c,l=!1,u;if(e[a]?(u=e[a][0][0],n.req.routeIndex=a):u=a===e.length&&o||void 0,u)try{c=await u(n,()=>i(a+1))}catch(d){if(d instanceof Error&&t)n.error=d,c=await t(d,n),l=!0;else throw d}else n.finalized===!1&&r&&(c=await r(n));return c&&(n.finalized===!1||l)&&(n.res=c),n}};var Lp=Symbol();var Cp=(e,t)=>new Response(e,{headers:{"Content-Type":t.replace(/^[^;]+/,n=>n.toLowerCase())}}).formData();var Op=32,zx=1e4,Si=e=>"headers"in e,Pp=async(e,t=Object.create(null))=>{let{all:r=!1,dot:n=!1}=t,i=(Si(e)?e.headers:e.raw.headers).get("Content-Type")?.split(";")[0].trim().toLowerCase();return i==="multipart/form-data"||i==="application/x-www-form-urlencoded"?Yx(e,{all:r,dot:n}):{}};async function Yx(e,t){if(!Si(e)&&e.bodyCache.formData)return Dp(await e.bodyCache.formData,t);let r=Si(e)?e.headers:e.raw.headers,n=await e.arrayBuffer(),o=Cp(n,r.get("Content-Type")||"");Si(e)||(e.bodyCache.formData=o);let s=await o;return s?Dp(s,t):{}}function Dp(e,t){let r=Object.create(null),n={count:0};return e.forEach((o,s)=>{t.all||s.endsWith("[]")?Kx(r,s,o):r[s]=o}),t.dot&&Object.entries(r).forEach(([o,s])=>{o.includes(".")&&(Qx(r,o,s,n),delete r[o])}),r}var Kx=(e,t,r)=>{e[t]!==void 0?Array.isArray(e[t])?e[t].push(r):e[t]=[e[t],r]:t.endsWith("[]")?e[t]=[r]:e[t]=r},Qx=(e,t,r,n)=>{if(/(?:^|\.)__proto__\./.test(t))return;let o=e,s=t.split(".",Op+2);s.length>Op+1&&Mp(),s.forEach((i,a)=>{a===s.length-1?o[i]=r:((!o[i]||typeof o[i]!="object"||Array.isArray(o[i])||o[i]instanceof File)&&(n.count++>=zx&&Mp(),o[i]=Object.create(null)),o=o[i])})},Mp=()=>{throw new Error("Nesting limit exceeded")};var hl=e=>{let t=e.split("/");return t[0]===""&&t.shift(),t},Up=e=>{let{groups:t,path:r}=Xx(e),n=hl(r);return Zx(n,t)},Xx=e=>{let t=[];return e=e.replace(/\{[^}]+\}/g,(r,n)=>{let o=`@${n}`;return t.push([o,r]),o}),{groups:t,path:e}},Zx=(e,t)=>{for(let r=t.length-1;r>=0;r--){let[n]=t[r];for(let o=e.length-1;o>=0;o--)if(e[o].includes(n)){e[o]=e[o].replace(n,t[r][1]);break}}return e},vi={},Fp=(e,t)=>{if(e==="*")return"*";let r=e.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);if(r){let n=`${e}#${t}`;return vi[n]||(r[2]?vi[n]=t&&t[0]!==":"&&t[0]!=="*"?[n,r[1],new RegExp(`^${r[2]}(?=/${t})`)]:[e,r[1],new RegExp(`^${r[2]}$`)]:vi[n]=[e,r[1],!0]),vi[n]}return null},qp=(e,t)=>{try{return t(e)}catch{return e.replace(/(?:%[0-9A-Fa-f]{2})+/g,r=>{try{return t(r)}catch{return r}})}},eR=e=>qp(e,decodeURI),gl=e=>{let t=e.url,r=t.indexOf("/",t.indexOf(":")+4),n=r;for(;n<t.length;n++){let o=t.charCodeAt(n);if(o===37){let s=t.indexOf("?",n),i=t.indexOf("#",n),a=s===-1?i===-1?void 0:i:i===-1?s:Math.min(s,i),c=t.slice(r,a);return eR(c.includes("%25")?c.replace(/%25/g,"%2525"):c)}else if(o===63||o===35)break}return t.slice(r,n)};var jp=e=>{let t=gl(e);return t.length>1&&t.at(-1)==="/"?t.slice(0,-1):t},Or=(e,t,...r)=>(r.length&&(t=Or(t,...r)),`${e?.[0]==="/"?"":"/"}${e}${t==="/"?"":`${e?.at(-1)==="/"?"":"/"}${t?.[0]==="/"?t.slice(1):t}`}`),Ai=e=>{if(e.charCodeAt(e.length-1)!==63||!e.includes(":"))return null;let t=e.split("/"),r=[],n="";return t.forEach(o=>{if(o!==""&&!/\:/.test(o))n+="/"+o;else if(/\:/.test(o))if(o.charCodeAt(o.length-1)===63){r.length===0&&n===""?r.push("/"):r.push(n);let s=o.slice(0,-1);n+="/"+s,r.push(n)}else n+="/"+o}),r.filter((o,s,i)=>i.indexOf(o)===s)},$i=e=>e.indexOf("%")!==-1?qp(e,tR):e,pl=e=>(e.indexOf("+")!==-1&&(e=e.replace(/\+/g," ")),$i(e)),Hp=(e,t,r)=>{let n=e.indexOf("#",8);n!==-1&&(e=e.slice(0,n));let o;if(!r&&t&&t.indexOf("%")===-1&&t.indexOf("+")===-1){let a=e.indexOf("?",8);if(a===-1)return;for(e.startsWith(t,a+1)||(a=e.indexOf(`&${t}`,a+1));a!==-1;){let c=e.charCodeAt(a+t.length+1);if(c===61){let l=a+t.length+2,u=e.indexOf("&",l);return pl(e.slice(l,u===-1?void 0:u))}else if(c==38||isNaN(c))return"";a=e.indexOf(`&${t}`,a+1)}if(o=/[%+]/.test(e),!o)return}let s=Object.create(null);o??=/[%+]/.test(e);let i=e.indexOf("?",8);for(;i!==-1;){let a=e.indexOf("&",i+1),c=e.indexOf("=",i);c>a&&a!==-1&&(c=-1);let l=e.slice(i+1,c===-1?a===-1?void 0:a:c);if(o&&(l=pl(l)),i=a,l==="")continue;let u;c===-1?u="":(u=e.slice(c+1,a===-1?void 0:a),o&&(u=pl(u))),r?(s[l]&&Array.isArray(s[l])||(s[l]=[]),s[l].push(u)):s[l]??=u}return t?s[t]:s},Bp=Hp,Wp=(e,t)=>Hp(e,t,!0),tR=decodeURIComponent;var Gp=class{raw;#t;#e;routeIndex=0;path;bodyCache={};constructor(e,t="/",r=[[]]){this.raw=e,this.path=t,this.#e=r}param(e){return e?this.#r(e):this.#s()}#r(e){let t=this.#e[0][this.routeIndex]?.[1][e],r=this.#n(t);return r&&$i(r)}#s(){let e={},t=Object.keys(this.#e[0][this.routeIndex]?.[1]??{});for(let r of t){let n=this.#n(this.#e[0][this.routeIndex][1][r]);n!==void 0&&(e[r]=$i(n))}return e}#n(e){return this.#e[1]?this.#e[1][e]:e}query(e){return Bp(this.url,e)}queries(e){return Wp(this.url,e)}header(e){if(e)return this.raw.headers.get(e)??void 0;let t=Object.create(null);return this.raw.headers.forEach((r,n)=>{t[n]=r}),t}async parseBody(e){return Pp(this,e)}#o=e=>{let{bodyCache:t,raw:r}=this,n=t[e];if(n)return n;for(let o in t)return t[o].then(s=>(o==="json"&&(s=JSON.stringify(s)),new Response(s)[e]()));return t[e]=r[e]()};json(){return this.#o("text").then(e=>JSON.parse(e))}text(){return this.#o("text")}arrayBuffer(){return this.#o("arrayBuffer")}bytes(){return this.#o("arrayBuffer").then(e=>new Uint8Array(e))}blob(){return this.#o("blob")}formData(){return this.#o("formData")}addValidatedData(e,t){(this.#t??={})[e]=t}valid(e){return this.#t?.[e]}get url(){return this.raw.url}get method(){return this.raw.method}get[Lp](){return this.#e}get matchedRoutes(){return this.#e[0].map(([[,e]])=>e)}get routePath(){return this.#e[0].map(([[,e]])=>e)[this.routeIndex].path}};var Vp={Stringify:1,BeforeStream:2,Stream:3},rR=(e,t)=>{let r=new String(e);return r.isEscaped=!0,r.callbacks=t,r};var _l=async(e,t,r,n,o)=>{typeof e=="object"&&!(e instanceof String)&&(e instanceof Promise||(e=e.toString()),e instanceof Promise&&(e=await e));let s=e.callbacks;if(!s?.length)return Promise.resolve(e);o?o[0]+=e:o=[e];let i=Promise.all(s.map(a=>a({phase:t,buffer:o,context:n}))).then(a=>Promise.all(a.filter(Boolean).map(c=>_l(c,t,!1,n,o))).then(()=>o[0]));return r?rR(await i,s):i};var nR="text/plain; charset=UTF-8",wl=(e,t)=>({"Content-Type":e,...t}),jo=(e,t)=>new Response(e,t),yl=class{#t;#e;env={};#r;finalized=!1;error;#s;#n;#o;#u;#c;#l;#a;#d;#m;constructor(e,t){this.#t=e,t&&(this.#n=t.executionCtx,this.env=t.env,this.#l=t.notFoundHandler,this.#m=t.path,this.#d=t.matchResult)}get req(){return this.#e??=new Gp(this.#t,this.#m,this.#d),this.#e}get event(){if(this.#n&&"respondWith"in this.#n)return this.#n;throw Error("This context has no FetchEvent")}get executionCtx(){if(this.#n)return this.#n;throw Error("This context has no ExecutionContext")}get res(){return this.#o||=jo(null,{headers:this.#a??=new Headers})}set res(e){if(this.#o&&e){e=jo(e.body,e);for(let[t,r]of this.#o.headers.entries())if(t!=="content-type")if(t==="set-cookie"){let n=this.#o.headers.getSetCookie();e.headers.delete("set-cookie");for(let o of n)e.headers.append("set-cookie",o)}else e.headers.set(t,r)}this.#o=e,this.finalized=!0}render=(...e)=>(this.#c??=t=>this.html(t),this.#c(...e));setLayout=e=>this.#u=e;getLayout=()=>this.#u;setRenderer=e=>{this.#c=e};header=(e,t,r)=>{this.finalized&&(this.#o=jo(this.#o.body,this.#o));let n=this.#o?this.#o.headers:this.#a??=new Headers;t===void 0?n.delete(e):r?.append?n.append(e,t):n.set(e,t)};status=e=>{this.#s=e};set=(e,t)=>{this.#r??=new Map,this.#r.set(e,t)};get=e=>this.#r?this.#r.get(e):void 0;get var(){return this.#r?Object.fromEntries(this.#r):{}}#i(e,t,r){let n=this.#o?new Headers(this.#o.headers):this.#a;if(typeof t=="object"&&t.headers){n??=new Headers;for(let[s,i]of new Headers(t.headers))s==="set-cookie"?n.append(s,i):n.set(s,i)}if(r){if(!n){let s=0;for(let i in r)if(++s>1||typeof r[i]!="string"){n=new Headers;break}}if(n)for(let s in r){let i=r[s];if(typeof i=="string")n.set(s,i);else{n.delete(s);for(let a of i)n.append(s,a)}}}let o=typeof t=="number"?t:t?.status??this.#s;return jo(e,{status:o,headers:n??r})}newResponse=(...e)=>this.#i(...e);body=(e,t,r)=>this.#i(e,t,r);text=(e,t,r)=>!this.#a&&!this.#s&&!t&&!r&&!this.finalized?new Response(e):this.#i(e,t,wl(nR,r));json=(e,t,r)=>this.#i(JSON.stringify(e),t,wl("application/json",r));html=(e,t,r)=>{let n=o=>this.#i(o,t,wl("text/html; charset=UTF-8",r));return typeof e=="object"?_l(e,Vp.Stringify,!1,{}).then(n):n(e)};redirect=(e,t)=>{let r=String(e);return this.header("Location",/[^\x00-\xFF]/.test(r)?encodeURI(r):r),this.newResponse(null,t??302)};notFound=()=>(this.#l??=()=>jo(),this.#l(this))};var Qe="ALL",Jp="all",zp=["get","post","put","delete","options","patch","query"],ki="Can not add a route since the matcher is already built.",xi=class extends Error{};var Yp="__COMPOSED_HANDLER";var oR=e=>e.text("404 Not Found",404),Kp=(e,t)=>{if("getResponse"in e){let r=e.getResponse();return t.newResponse(r.body,r)}return console.error(e),t.text("Internal Server Error",500)},Qp=class Xp{get;post;put;delete;options;patch;query;all;on;use;router;getPath;_basePath="/";#t="/";routes=[];constructor(t={}){[...zp,Jp].forEach(s=>{this[s]=(i,...a)=>(typeof i=="string"?this.#t=i:this.#s(s,this.#t,i),a.forEach(c=>{this.#s(s,this.#t,c)}),this)}),this.on=(s,i,...a)=>{for(let c of[i].flat()){this.#t=c;for(let l of[s].flat())a.map(u=>{this.#s(l.toUpperCase(),this.#t,u)})}return this},this.use=(s,...i)=>(typeof s=="string"?this.#t=s:(this.#t="*",i.unshift(s)),i.forEach(a=>{this.#s(Qe,this.#t,a)}),this);let{strict:n,...o}=t;Object.assign(this,o),this.getPath=n??!0?t.getPath??gl:jp}#e(){let t=new Xp({router:this.router,getPath:this.getPath});return t.errorHandler=this.errorHandler,t.#r=this.#r,t.routes=this.routes,t}#r=oR;errorHandler=Kp;route(t,r){let n=this.basePath(t);return r.routes.map(o=>{let s;r.errorHandler===Kp?s=o.handler:(s=async(i,a)=>(await fl([],r.errorHandler)(i,()=>o.handler(i,a))).res,s[Yp]=o.handler),n.#s(o.method,o.path,s,o.basePath)}),this}basePath(t){let r=this.#e();return r._basePath=Or(this._basePath,t),r}onError=t=>(this.errorHandler=t,this);notFound=t=>(this.#r=t,this);mount(t,r,n){let o,s;n&&(typeof n=="function"?s=n:(s=n.optionHandler,n.replaceRequest===!1?o=c=>c:o=n.replaceRequest));let i=s?c=>{let l=s(c);return Array.isArray(l)?l:[l]}:c=>{let l;try{l=c.executionCtx}catch{}return[c.env,l]};o||=(()=>{let c=Or(this._basePath,t),l=c==="/"?0:c.length;return u=>{let d=new URL(u.url);return d.pathname=this.getPath(u).slice(l)||"/",new Request(d,u)}})();let a=async(c,l)=>{let u=await r(o(c.req.raw),...i(c));if(u)return u;await l()};return this.#s(Qe,Or(t,"*"),a),this}#s(t,r,n,o){t=t.toUpperCase(),r=Or(this._basePath,r);let s={basePath:o!==void 0?Or(this._basePath,o):this._basePath,path:r,method:t,handler:n};this.router.add(t,r,[n,s]),this.routes.push(s)}#n(t,r){if(t instanceof Error)return this.errorHandler(t,r);throw t}#o(t,r,n,o){if(o==="HEAD")return(async()=>new Response(null,await this.#o(t,r,n,"GET")))();let s=this.getPath(t,{env:n}),i=this.router.match(o,s),a=new yl(t,{path:s,matchResult:i,env:n,executionCtx:r,notFoundHandler:this.#r});if(i[0].length===1){let l;try{l=i[0][0][0][0](a,async()=>{a.res=await this.#r(a)})}catch(u){return this.#n(u,a)}return l instanceof Promise?l.then(u=>u||(a.finalized?a.res:this.#r(a))).catch(u=>this.#n(u,a)):l??this.#r(a)}let c=fl(i[0],this.errorHandler,this.#r);return(async()=>{try{let l=await c(a);if(!l.finalized)throw new Error("Context is not finalized. Did you forget to return a Response object or `await next()`?");return l.res}catch(l){return this.#n(l,a)}})()}fetch=(t,...r)=>this.#o(t,r[1],r[0],t.method);request=(t,r,n,o)=>t instanceof Request?this.fetch(r?new Request(t,r):t,n,o):(t=t.toString(),this.fetch(new Request(/^https?:\/\//.test(t)?t:`http://localhost${Or("/",t)}`,r),n,o));fire=()=>{addEventListener("fetch",t=>{t.respondWith(this.#o(t.request,t,void 0,t.request.method))})}};var Ge=()=>Object.create(null);var Ri=[];function El(e,t){let r=this.buildAllMatchers(),n=(o,s)=>{let i=r[o]||r[Qe],a=i[2][s];if(a)return a;let c=s.match(i[0]);if(!c)return[[],Ri];let l=c.indexOf("",1);return[i[1][l],c]};return this.match=n,n(e,t)}var Hn="[^/]+",Mr=".*",pr="(?:|/.*)",Dr=Symbol(),Zp=new Set(".\\+*[^]$()");function sR(e,t){return e.length===1?t.length===1?e<t?-1:1:-1:t.length===1?1:e===Mr||e===pr?t===pr?-1:1:t===Mr||t===pr?-1:e===Hn?1:t===Hn?-1:e.length===t.length?e<t?-1:1:t.length-e.length}var eh=class bl{#t;#e;#r=Ge();insert(t,r,n,o,s){let i=this;for(let a=0,c=t.length;a<c;a++){let l=t[a],u=l.length===1?l==="*"?a===c-1?["","",Mr]:["","",Hn]:null:l==="/*"?["","",pr]:l.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/),d;if(u){let m=u[1],f=u[2]||Hn;if(m&&u[2]&&(f===".*"||(f=f.replace(/^\((?!\?:)(?=[^)]+\)$)/,"(?:"),/\((?!\?:)/.test(f))||f.length===1&&Zp.has(f)))throw Dr;if(d=i.#r[f],!d){if(f!==Mr&&f!==pr){for(let p in i.#r)if((f.length>1||p.length>1)&&p!==Mr&&p!==pr)throw Dr}d=i.#r[f]=new bl}m!==""&&(d.#e??=o.varIndex++,n.push([m,d.#e]))}else if(d=i.#r[l],!d){for(let m in i.#r)if(m.length>1&&m!==Mr&&m!==pr)throw Dr;d=i.#r[l]=new bl}i=d}if(i.#t!==void 0)throw Dr;i.#t=s?-1:r}buildRegExpStr(){let r=Object.keys(this.#r).sort(sR).map(n=>{let o=this.#r[n],s=o.buildRegExpStr();return s===""?"":(typeof o.#e=="number"?`(${n})@${o.#e}`:Zp.has(n)?`\\${n}`:n)+s}).filter(Boolean);return typeof this.#t=="number"&&this.#t!==-1&&r.unshift(`#${this.#t}`),r.length===0?"":r.length===1?r[0]:"(?:"+r.join("|")+")"}};var Tl=class{#t={varIndex:0};#e=new eh;#r=0;paths=Ge();insert(e,t){if(t){this.#e.insert(e.split(""),0,[],this.#t,!0);return}let r=[],n=[],o=e;for(let i=0;;){let a=!1;if(o=o.replace(/\{[^}]+\}/g,c=>{let l=`@\\${i}`;return n[i]=[l,c],i++,a=!0,l}),!a)break}let s=o.match(/(?::[^\/]+)|(?:\/\*$)|./g)||[];for(let i=n.length-1;i>=0;i--){let[a]=n[i];for(let c=s.length-1;c>=0;c--)if(s[c].indexOf(a)!==-1){s[c]=s[c].replace(a,n[i][1]);break}}this.#e.insert(s,this.#r,r,this.#t,!1),this.paths[e]=[this.#r++,r]}buildRegExp(){let e=this.#e.buildRegExpStr();if(e==="")return[/^$/,[],[]];let t=0,r=[],n=[];return e=e.replace(/#(\d+)|@(\d+)|\.\*\$/g,(o,s,i)=>s!==void 0?(r[++t]=Number(s),"$()"):(i!==void 0&&(n[Number(i)]=++t),"")),[new RegExp(`^${e}`),r,n]}};var th=Ge();function rh(e){return th[e]??=new RegExp(`^${e.replace(/\/:[^/{}]+(?:\{\[\^\/]\+})?(?=[/{]|$)|\/?\*$|([.\\+*[^\]$()?{}|])/g,(t,r)=>r?`\\${r}`:t==="/*"?pr:t==="*"?Mr:`/:${Hn}`)}$`)}function Ni(e,t){for(let r of Object.keys(e).sort((n,o)=>o.length-n.length))if(rh(r).test(t))return[...e[r]]}var Ii=class{name="RegExpRouter";#t;#e;#r;constructor(){this.#t={[Qe]:Ge()},this.#e={[Qe]:Ge()},this.#r={[Qe]:new Tl}}#s(e,t){try{this.#r[e].insert(t,!/\*|\/:/.test(t))}catch(r){throw r===Dr?new xi(t):r}}add(e,t,r){let n=this.#t,o=this.#e;if(!n)throw new Error(ki);if(!n[e]){this.#r[e]=new Tl;for(let a of[n,o]){a[e]=Ge();for(let c in a[Qe])a[e][c]=[...a[Qe][c]],this.#s(e,c)}}t==="/*"&&(t="*");let s=e===Qe?Object.keys(n):[e];if(/\*$/.test(t)){let a=rh(t);for(let c of s)n[c][t]||(this.#s(c,t),n[c][t]=Ni(n[c],t)||Ni(n[Qe],t)||[]);for(let c of[n,o])for(let l of s)for(let u in c[l])a.test(u)&&c[l][u].push([r,t]);return}let i=Ai(t)||[t];for(let a of i)for(let c of s)o[c][a]||(this.#s(c,a),o[c][a]=Ni(n[c],a)||Ni(n[Qe],a)||[]),o[c][a].push([r,a])}match=El;buildAllMatchers(){let e=Ge();for(let t of Object.keys(this.#e))e[t]=this.#n(t);return this.#t=this.#e=this.#r=void 0,th=Ge(),e}#n(e){let t=this.#t[e],r=this.#e[e],n=this.#r[e],o=Ge(),s=[],[i,a,c]=n.buildRegExp();for(let l of[t,r])for(let u in l){let d=l[u],m=n.paths[u];if(!m){o[u]=[d.map(([f])=>[f,Ge()]),Ri];continue}s[m[0]]=d.map(([f,p])=>[f,n.paths[p][1].reduceRight((h,[g],_)=>(h[g]=c[m[1][_][1]],h),Ge())])}return[i,a.map(l=>s[l]),o]}};var Sl=class{name="SmartRouter";#t=[];#e=[];constructor(e){this.#t=e.routers}add(e,t,r){if(!this.#e)throw new Error(ki);this.#e.push([e,t,r])}match(e,t){if(!this.#e)throw new Error("Fatal error");let r=this.#t,n=this.#e,o=r.length,s=0,i;for(;s<o;s++){let a=r[s];try{for(let c=0,l=n.length;c<l;c++)a.add(...n[c]);i=a.match(e,t)}catch(c){if(c instanceof xi)continue;throw c}this.match=a.match.bind(a),this.#t=[a],this.#e=void 0;break}if(s===o)throw new Error("Fatal error");return this.name=`SmartRouter + ${this.activeRouter.name}`,i}get activeRouter(){if(this.#e||this.#t.length!==1)throw new Error("No active router has been determined yet.");return this.#t[0]}};var vl=Ge(),iR=0,nh=class oh{#t=[];#e=Ge();#r=[];#s;#n=vl;insert(t,r,n){let o=this,s=Up(r),i=new Set,a=0;for(let c of s){let l=s[++a],u=Fp(c,l)||(l===void 0&&c&&c.indexOf("*")===c.length-1?c:null),d=Array.isArray(u),m=d?u[0]:u||c,f=o.#e[m]||=new oh;u&&!f.#s&&(f.#s=u,o.#r.push(f)),o=f,d&&i.add(u[1])}o.#t.push({[t]:{handler:n,possibleKeys:[...i],score:++iR}})}#o(t,r,n,o,s){for(let i=0,a=r.#t.length;i<a;i++){let c=r.#t[i],l=c[n]||c[Qe];if(l){l.params=Ge(),t.push(l);for(let u=0,d=l.possibleKeys.length;u<d;u++){let m=l.possibleKeys[u];l.params[m]=s?.[m]&&!u?s[m]:o[m]??s?.[m]}}}}search(t,r){let n=[];this.#n=vl;let s=[this],i=hl(r),a=[],c=i.length,l=null;for(let u=0;u<c;u++){let d=i[u],m=u===c-1,f=[];for(let h=0,g=s.length;h<g;h++){let _=s[h],E=_.#e[d];E&&(E.#n=_.#n,m?(E.#e["*"]&&this.#o(n,E.#e["*"],t,_.#n),this.#o(n,E,t,_.#n)):f.push(E));for(let y of _.#r){let S=y.#s,T=_.#n===vl?{}:{..._.#n};if(typeof S=="string"){(S==="*"||d.startsWith(S.slice(0,-1)))&&(this.#o(n,y,t,_.#n),S==="*"&&(y.#n=T,f.push(y)));continue}let[,R,x]=S;if(!(!d&&x===!0)){if(x!==!0){if(!l){l=[];let H=r[0]==="/"?1:0;for(let L=0;L<c;L++)l[L]=H,H+=i[L].length+1}let I=r.slice(l[u]),A=x.exec(I);if(A){T[R]=A[0],this.#o(n,y,t,_.#n,T),A[0].length===I.length&&y.#e["*"]&&this.#o(n,y.#e["*"],t,_.#n,T);for(let H in y.#e){y.#n=T;let L=A[0].match(/\//g)?.length??0;(a[L]||=[]).push(y);break}continue}}(x===!0||x.test(d))&&(T[R]=d,m?(this.#o(n,y,t,T,_.#n),y.#e["*"]&&this.#o(n,y.#e["*"],t,T,_.#n)):(y.#n=T,f.push(y)))}}}let p=a.shift();s=p?f.concat(p):f}return n[1]&&n.sort((u,d)=>u.score-d.score),[n.map(({handler:u,params:d})=>[u,d])]}};var Al=class{name="TrieRouter";#t=new nh;add(e,t,r){for(let n of Ai(t)||[t])this.#t.insert(e,n,r)}match(e,t){return this.#t.search(e,t)}};var dn=class extends Qp{constructor(e={}){super(e),this.router=e.router??new Sl({routers:[new Ii,new Al]})}};import{join as aR}from"node:path";function cR(e){return e||(process.env.LMBEE_TEAMS_CONF?process.env.LMBEE_TEAMS_CONF:aR(process.cwd(),"teams.conf"))}function lR(e,t){let r=process.env.LMBEE_TEAM_NAME;if(r===void 0)return;let n=t.find(o=>o.name===r);if(!(n===void 0||!B(n)))try{Dm(e.db,r,new Date().toISOString())}catch{}}function Li(e={}){let t=Hs(e.dbPath,{readOnly:e.readOnly??!1}),r=cR(e.teamsConfPath),n=rn(t.db,r);return e.readOnly||lR(t,n),{db:t,teamsConfPath:r,teams:n}}import{existsSync as DL,readFileSync as ML,statSync as PL}from"node:fs";import{execFile as uR}from"node:child_process";import{promisify as dR}from"node:util";var Ci=dR(uR),Bo=3,Ho="auto_nudge_redirect:",$l=3,kl=5*60*6e4;function $t(e,t){let r=e.prepare("SELECT v FROM kv WHERE k = ?").get(Ho+t);if(r===void 0)return null;try{let n=JSON.parse(r.v);return typeof n.companionTeam!="string"||n.companionTeam.length===0?null:{companionTeam:n.companionTeam,workerAlias:typeof n.workerAlias=="string"&&n.workerAlias.length>0?n.workerAlias:"Worker",commitThreshold:typeof n.commitThreshold=="number"&&n.commitThreshold>0?n.commitThreshold:$l,hoursThresholdMs:typeof n.hoursThresholdMs=="number"&&n.hoursThresholdMs>0?n.hoursThresholdMs:kl,shiftStartedTs:typeof n.shiftStartedTs=="string"?n.shiftStartedTs:null,shiftStartedSha:typeof n.shiftStartedSha=="string"?n.shiftStartedSha:null,turnsDispatched:typeof n.turnsDispatched=="number"&&n.turnsDispatched>=0?n.turnsDispatched:0,lastReviewedTurn:typeof n.lastReviewedTurn=="number"&&n.lastReviewedTurn>=0?n.lastReviewedTurn:0}}catch{return null}}function xl(e){return e.prepare("SELECT k FROM kv WHERE k LIKE ?").all(Ho+"%").map(r=>r.k.slice(Ho.length))}function Oi(e,t,r){e.prepare("INSERT INTO kv(k, v) VALUES (?, ?) ON CONFLICT(k) DO UPDATE SET v = excluded.v").run(Ho+t,JSON.stringify(r))}function sh(e,t){e.prepare("DELETE FROM kv WHERE k = ?").run(Ho+t)}async function ih(e,t){try{let{stdout:r}=await t("git",["-C",e,"rev-parse","HEAD"],{timeout:1e4});return r.trim()||null}catch{return null}}async function mR(e,t,r){try{let{stdout:n}=await r("git",["-C",e,"rev-list","--count",`${t}..HEAD`],{timeout:1e4}),o=Number.parseInt(n.trim(),10);return Number.isNaN(o)?null:o}catch{return null}}async function ah(e,t,r,n,o,s=Ci){let i=r.shiftStartedTs!==null,a=i?r.shiftStartedSha:await ih(n,s);Oi(e,t,{...r,turnsDispatched:r.turnsDispatched+1,shiftStartedTs:i?r.shiftStartedTs:o,shiftStartedSha:a})}async function ch(e,t,r=Date.now(),n=Ci){let o=[];for(let s of xl(e)){let i=$t(e,s);if(i===null||i.shiftStartedTs===null)continue;let a=t.get(s);if(a===void 0)continue;let c=(r-Date.parse(i.shiftStartedTs))/(60*6e4),l=i.shiftStartedSha!==null?await mR(a,i.shiftStartedSha,n):null,u=i.turnsDispatched<=Bo&&i.turnsDispatched>i.lastReviewedTurn,d=c*60*6e4>=i.hoursThresholdMs,m=l!==null&&l>=i.commitThreshold;(u||d||m)&&o.push({team:s,companionTeam:i.companionTeam,workerAlias:i.workerAlias,commitCount:l,hoursElapsed:c,shiftStartedTs:i.shiftStartedTs,shiftStartedSha:i.shiftStartedSha,isRampUp:u,turnNumber:i.turnsDispatched})}return o}async function lh(e,t,r,n,o=Ci){let s=$t(e,t);if(s===null)return;let i=await ih(r,o);Oi(e,t,{...s,shiftStartedTs:n,shiftStartedSha:i,lastReviewedTurn:s.turnsDispatched})}async function uh(e,t,r=Ci){let n=e.hoursElapsed.toFixed(1),o=e.commitCount===null?"unknown (git check failed)":String(e.commitCount),s=null;if(e.shiftStartedSha!==null)try{let{stdout:a}=await r("git",["-C",t,"log","--oneline",`${e.shiftStartedSha}..HEAD`],{timeout:1e4});s=a.trim()}catch{s=null}let i=s!==null&&s.length>0?`
|
|
193
|
+
(${S.length-1} other ready task(s) also available: \`lmauto tasks list --owner-team <path> --owner-alias <alias> --status todo\`.)`+d+g,onSent:x}}var he={idleThresholdMs:45*6e4,cooldownMs:30*6e4};function Ax(e,t){return t.running.some(r=>kn(e,r.from_identity))}function cn(e,t){return t.dead.some(r=>kn(e,r.target))&&!je(e,t)}function Yc(e){if(e.isCurrentlyActive)return!1;let t=!e.hasInFlightWorker,r=e.timeSinceLastNudgeMs===null||e.timeSinceLastNudgeMs>e.config.cooldownMs;if(e.isDeadReclaimable)return t&&r;let n=!e.isCoordinator&&e.progressStatus==="UNKNOWN"&&(e.progressAgeMs===null||e.progressAgeMs>=e.config.idleThresholdMs),o=!e.heavyLockMayBeHeldByThisTeam&&e.hasStalePersistentInProgressWork;return t&&r&&(e.neverDispatched||n||o)}function Qc(e,t,r,n){let o;try{o=Q(t)}catch{return!1}let s=Re(e,o,t.leadAlias);if(s===null)return!1;let i=new Map(s.entities.map(a=>[a.id,a]));return s.entities.some(a=>(a.kind==="task"||a.kind==="subtask")&&ue(a.status)==="in-progress"&&!Qt(e,a,i)&&n-Date.parse(a.updated_at)>=r&&!Xc(a,n))}function Xc(e,t){return e.hold_until!==null&&Date.parse(e.hold_until)>t}function Zc(e,t){if(qe(e,t.name)!==null||zf(e,t.name))return!1;let r;try{r=Q(t)}catch{return!0}return Re(e,r,t.leadAlias)===null}function $x(e){return Yc({...e,config:{...e.config,idleThresholdMs:0}})}function fp(e){return`last_nudged:${e}`}function el(e,t){return e.prepare("SELECT v FROM kv WHERE k = ?").get(fp(t))?.v??null}function Uo(e,t,r){e.prepare("INSERT INTO kv(k, v) VALUES (?, ?) ON CONFLICT(k) DO UPDATE SET v = excluded.v").run(fp(t),r)}function pp(e,t,r,n,o,s,i){if(qe(e,t.name)?.status==="BLOCKED")return null;let c=Zc(e,t),l=s?.progress_changed_ts==null?null:o-Date.parse(s.progress_changed_ts),u=el(e,t.name),d=u===null?null:o-Date.parse(u);return{isCurrentlyActive:je(t,r),hasInFlightWorker:Ax(t,r),neverDispatched:c,progressStatus:s?.progress_status??null,progressAgeMs:l,isDeadReclaimable:cn(t,r),hasStalePersistentInProgressWork:Qc(e,t,n.idleThresholdMs,o),timeSinceLastNudgeMs:d,config:n,isCoordinator:t.coordinator===!0,heavyLockMayBeHeldByThisTeam:i.held&&(i.holder===null||i.holder.holder===t.name)}}function hp(e,t,r,n,o,s,i){let a=pp(e,t,r,o,s,i,n);return a!==null&&Yc(a)}async function tl(e,t,r,n,o=he,s=Date.now()){let i=await yc(e,t,t.name,s);return hp(e,t,r,n,o,s,i)}function rl(e,t,r,n,o=he,s=Date.now()){return hp(e,t,r,n,o,s,se(e,t.name))}async function Pn(e,t,r,n,o=he,s=Date.now(),i={}){let a=[];for(let c of t){if(!c.autoNudge||se(e,c.name)?.confirmed_done_ts)continue;(i.readOnly?rl(e,c,r,n,o,s):await tl(e,c,r,n,o,s))&&!se(e,c.name)?.confirmed_done_ts&&a.push(c.name)}return a}async function gp(e,t,r,n,o=he,s=Date.now()){let i=[],a=[];for(let c of t){if(!c.autoNudge||se(e,c.name)?.confirmed_done_ts)continue;let l=await yc(e,c,c.name,s);if(se(e,c.name)?.confirmed_done_ts)continue;let u=pp(e,c,r,o,s,l,n);u!==null&&(Yc(u)&&i.push(c.name),$x(u)&&a.push(c.name))}return{stalled:i,continueEligible:a}}import{existsSync as _p,readFileSync as wp}from"node:fs";import{dirname as ol,join as yp}from"node:path";import{fileURLToPath as Ep}from"node:url";var nl={sha:"unknown",dirty:!0,builtAt:"unknown"};function kx(e){if(typeof e!="object"||e===null)return!1;let t=e;return typeof t.sha=="string"&&typeof t.dirty=="boolean"&&typeof t.builtAt=="string"}function bp(){let e=ol(Ep(import.meta.url));for(let t=0;t<5;t+=1){let r=yp(e,"package.json");if(_p(r))try{let n=JSON.parse(wp(r,"utf8"));if(n&&typeof n=="object"&&typeof n.version=="string")return n.version}catch{}e=ol(e)}return"unknown"}function sl(){let e=yp(ol(Ep(import.meta.url)),"..","build-info.json");if(!_p(e))return nl;try{let t=JSON.parse(wp(e,"utf8"));return kx(t)?t:nl}catch{return nl}}var xx="https://ecezfoozb3.execute-api.us-east-1.amazonaws.com/prod";function Nt(e){return(e.LMCTL_LMMAIL_API_URL?.trim()||e.LMMAIL_API_URL?.trim()||xx).replace(/\/+$/,"")}import{createServer as Rx}from"http";import{Http2ServerRequest as vp,constants as Nx}from"http2";import{Http2ServerRequest as il}from"http2";import{Readable as Tp}from"stream";import jx from"crypto";var ln=class extends Error{constructor(e,t){super(e,t),this.name="RequestError"}},Ix=e=>e instanceof ln?e:new ln(e.message,{cause:e}),Lx=global.Request,Fo=class extends Lx{constructor(e,t){typeof e=="object"&&qn in e&&(e=e[qn]()),typeof t?.body?.getReader<"u"&&(t.duplex??="half"),super(e,t)}},Cx=e=>{let t=[],r=e.rawHeaders;for(let n=0;n<r.length;n+=2){let{[n]:o,[n+1]:s}=r;o.charCodeAt(0)!==58&&t.push([o,s])}return new Headers(t)},Ap=Symbol("wrapBodyStream"),Ox=(e,t,r,n,o)=>{let s={method:e,headers:r,signal:o.signal};if(e==="TRACE"){s.method="GET";let i=new Fo(t,s);return Object.defineProperty(i,"method",{get(){return"TRACE"}}),i}if(!(e==="GET"||e==="HEAD"))if("rawBody"in n&&n.rawBody instanceof Buffer)s.body=new ReadableStream({start(i){i.enqueue(n.rawBody),i.close()}});else if(n[Ap]){let i;s.body=new ReadableStream({async pull(a){try{i||=Tp.toWeb(n).getReader();let{done:c,value:l}=await i.read();c?a.close():a.enqueue(l)}catch(c){a.error(c)}}})}else s.body=Tp.toWeb(n);return new Fo(t,s)},qn=Symbol("getRequestCache"),$p=Symbol("requestCache"),bi=Symbol("incomingKey"),Ti=Symbol("urlKey"),Dx=Symbol("headersKey"),Fn=Symbol("abortControllerKey"),Mx=Symbol("getAbortController"),qo={get method(){return this[bi].method||"GET"},get url(){return this[Ti]},get headers(){return this[Dx]||=Cx(this[bi])},[Mx](){return this[qn](),this[Fn]},[qn](){return this[Fn]||=new AbortController,this[$p]||=Ox(this.method,this[Ti],this.headers,this[bi],this[Fn])}};["body","bodyUsed","cache","credentials","destination","integrity","mode","redirect","referrer","referrerPolicy","signal","keepalive"].forEach(e=>{Object.defineProperty(qo,e,{get(){return this[qn]()[e]}})});["arrayBuffer","blob","clone","formData","json","text"].forEach(e=>{Object.defineProperty(qo,e,{value:function(){return this[qn]()[e]()}})});Object.defineProperty(qo,Symbol.for("nodejs.util.inspect.custom"),{value:function(e,t,r){let n={method:this.method,url:this.url,headers:this.headers,nativeRequest:this[$p]};return`Request (lightweight) ${r(n,{...t,depth:e==null?null:e-1})}`}});Object.setPrototypeOf(qo,Fo.prototype);var Px=(e,t)=>{let r=Object.create(qo);r[bi]=e;let n=e.url||"";if(n[0]!=="/"&&(n.startsWith("http://")||n.startsWith("https://"))){if(e instanceof il)throw new ln("Absolute URL for :path is not allowed in HTTP/2");try{let a=new URL(n);r[Ti]=a.href}catch(a){throw new ln("Invalid absolute URL",{cause:a})}return r}let o=(e instanceof il?e.authority:e.headers.host)||t;if(!o)throw new ln("Missing host header");let s;if(e instanceof il){if(s=e.scheme,!(s==="http"||s==="https"))throw new ln("Unsupported scheme")}else s=e.socket&&e.socket.encrypted?"https":"http";let i=new URL(`${s}://${o}${n}`);if(i.hostname.length!==o.length&&i.hostname!==o.replace(/:\d+$/,""))throw new ln("Invalid host header");return r[Ti]=i.href,r},cl=Symbol("responseCache"),Un=Symbol("getResponseCache"),un=Symbol("cache"),dl=global.Response,jn=class kp{#t;#e;[Un](){return delete this[un],this[cl]||=new dl(this.#t,this.#e)}constructor(t,r){let n;if(this.#t=t,r instanceof kp){let o=r[cl];if(o){this.#e=o,this[Un]();return}else this.#e=r.#e,n=new Headers(r.#e.headers)}else this.#e=r;(typeof t=="string"||typeof t?.getReader<"u"||t instanceof Blob||t instanceof Uint8Array)&&(this[un]=[r?.status||200,t,n||r?.headers])}get headers(){let t=this[un];return t?(t[2]instanceof Headers||(t[2]=new Headers(t[2]||{"content-type":"text/plain; charset=UTF-8"})),t[2]):this[Un]().headers}get status(){return this[un]?.[0]??this[Un]().status}get ok(){let t=this.status;return t>=200&&t<300}};["body","bodyUsed","redirected","statusText","trailers","type","url"].forEach(e=>{Object.defineProperty(jn.prototype,e,{get(){return this[Un]()[e]}})});["arrayBuffer","blob","clone","formData","json","text"].forEach(e=>{Object.defineProperty(jn.prototype,e,{value:function(){return this[Un]()[e]()}})});Object.defineProperty(jn.prototype,Symbol.for("nodejs.util.inspect.custom"),{value:function(e,t,r){let n={status:this.status,headers:this.headers,ok:this.ok,nativeResponse:this[cl]};return`Response (lightweight) ${r(n,{...t,depth:e==null?null:e-1})}`}});Object.setPrototypeOf(jn,dl);Object.setPrototypeOf(jn.prototype,dl.prototype);async function Ux(e){return Promise.race([e,Promise.resolve().then(()=>Promise.resolve(void 0))])}function xp(e,t,r){let n=a=>{e.cancel(a).catch(()=>{})};return t.on("close",n),t.on("error",n),(r??e.read()).then(i,o),e.closed.finally(()=>{t.off("close",n),t.off("error",n)});function o(a){a&&t.destroy(a)}function s(){e.read().then(i,o)}function i({done:a,value:c}){try{if(a)t.end();else if(!t.write(c))t.once("drain",s);else return e.read().then(i,o)}catch(l){o(l)}}}function Fx(e,t){if(e.locked)throw new TypeError("ReadableStream is locked.");return t.destroyed?void 0:xp(e.getReader(),t)}var ll=e=>{let t={};e instanceof Headers||(e=new Headers(e??void 0));let r=[];for(let[n,o]of e)n==="set-cookie"?r.push(o):t[n]=o;return r.length>0&&(t["set-cookie"]=r),t["content-type"]??="text/plain; charset=UTF-8",t},qx="x-hono-already-sent";typeof global.crypto>"u"&&(global.crypto=jx);var ml=Symbol("outgoingEnded"),Sp=Symbol("incomingDraining"),Hx=500,Bx=64*1024*1024,al=e=>{let t=e;if(e.destroyed||t[Sp])return;if(t[Sp]=!0,e instanceof vp){try{e.stream?.close?.(Nx.NGHTTP2_NO_ERROR)}catch{}return}let r=0,n=()=>{clearTimeout(s),e.off("data",i),e.off("end",n),e.off("error",n)},o=()=>{n();let a=e.socket;a&&!a.destroyed&&a.destroySoon()},s=setTimeout(o,Hx);s.unref?.();let i=a=>{r+=a.length,r>Bx&&o()};e.on("data",i),e.on("end",n),e.on("error",n),e.resume()},Wx=()=>new Response(null,{status:400}),Rp=e=>new Response(null,{status:e instanceof Error&&(e.name==="TimeoutError"||e.constructor.name==="TimeoutError")?504:500}),ul=(e,t)=>{let r=e instanceof Error?e:new Error("unknown error",{cause:e});r.code==="ERR_STREAM_PREMATURE_CLOSE"?console.info("The user aborted a request."):(console.error(e),t.headersSent||t.writeHead(500,{"Content-Type":"text/plain"}),t.end(`Error: ${r.message}`),t.destroy(r))},Np=e=>{"flushHeaders"in e&&e.writable&&e.flushHeaders()},Ip=async(e,t)=>{let[r,n,o]=e[un],s=!1;if(!o)o={"content-type":"text/plain; charset=UTF-8"};else if(o instanceof Headers)s=o.has("content-length"),o=ll(o);else if(Array.isArray(o)){let i=new Headers(o);s=i.has("content-length"),o=ll(i)}else for(let i in o)if(i.length===14&&i.toLowerCase()==="content-length"){s=!0;break}s||(typeof n=="string"?o["Content-Length"]=Buffer.byteLength(n):n instanceof Uint8Array?o["Content-Length"]=n.byteLength:n instanceof Blob&&(o["Content-Length"]=n.size)),t.writeHead(r,o),typeof n=="string"||n instanceof Uint8Array?t.end(n):n instanceof Blob?t.end(new Uint8Array(await n.arrayBuffer())):(Np(t),await Fx(n,t)?.catch(i=>ul(i,t))),t[ml]?.()},Gx=e=>typeof e.then=="function",Vx=async(e,t,r={})=>{if(Gx(e))if(r.errorHandler)try{e=await e}catch(o){let s=await r.errorHandler(o);if(!s)return;e=s}else e=await e.catch(Rp);if(un in e)return Ip(e,t);let n=ll(e.headers);if(e.body){let o=e.body.getReader(),s=[],i=!1,a;if(n["transfer-encoding"]!=="chunked"){let c=2;for(let l=0;l<c;l++){a||=o.read();let u=await Ux(a).catch(d=>{console.error(d),i=!0});if(!u){if(l===1){await new Promise(d=>setTimeout(d)),c=3;continue}break}if(a=void 0,u.value&&s.push(u.value),u.done){i=!0;break}}i&&!("content-length"in n)&&(n["content-length"]=s.reduce((l,u)=>l+u.length,0))}t.writeHead(e.status,n),s.forEach(c=>{t.write(c)}),i?t.end():(s.length===0&&Np(t),await xp(o,t,a))}else n[qx]||(t.writeHead(e.status,n),t.end());t[ml]?.()},Jx=(e,t={})=>{let r=t.autoCleanupIncoming??!0;return t.overrideGlobalObjects!==!1&&global.Request!==Fo&&(Object.defineProperty(global,"Request",{value:Fo}),Object.defineProperty(global,"Response",{value:jn})),async(n,o)=>{let s,i;try{i=Px(n,t.hostname);let a=!r||n.method==="GET"||n.method==="HEAD";if(a||(n[Ap]=!0,n.on("end",()=>{a=!0}),n instanceof vp&&(o[ml]=()=>{a||setTimeout(()=>{a||setTimeout(()=>{al(n)})})}),o.on("finish",()=>{a||al(n)})),o.on("close",()=>{i[Fn]&&(n.errored?i[Fn].abort(n.errored.toString()):o.writableFinished||i[Fn].abort("Client connection prematurely closed.")),a||setTimeout(()=>{a||setTimeout(()=>{al(n)})})}),s=e(i,{incoming:n,outgoing:o}),un in s)return Ip(s,o)}catch(a){if(s)return ul(a,o);if(t.errorHandler){if(s=await t.errorHandler(i?a:Ix(a)),!s)return}else i?s=Rp(a):s=Wx()}try{return await Vx(s,o,t)}catch(a){return ul(a,o)}}},zx=e=>{let t=e.fetch,r=Jx(t,{hostname:e.hostname,overrideGlobalObjects:e.overrideGlobalObjects,autoCleanupIncoming:e.autoCleanupIncoming});return(e.createServer||Rx)(e.serverOptions||{},r)},Lp=(e,t)=>{let r=zx(e);return r.listen(e?.port??3e3,e.hostname,()=>{let n=r.address();t&&t(n)}),r};var fl=(e,t,r)=>(n,o)=>{let s=-1;return i(0);async function i(a){if(a<=s)throw new Error("next() called multiple times");s=a;let c,l=!1,u;if(e[a]?(u=e[a][0][0],n.req.routeIndex=a):u=a===e.length&&o||void 0,u)try{c=await u(n,()=>i(a+1))}catch(d){if(d instanceof Error&&t)n.error=d,c=await t(d,n),l=!0;else throw d}else n.finalized===!1&&r&&(c=await r(n));return c&&(n.finalized===!1||l)&&(n.res=c),n}};var Cp=Symbol();var Op=(e,t)=>new Response(e,{headers:{"Content-Type":t.replace(/^[^;]+/,n=>n.toLowerCase())}}).formData();var Dp=32,Kx=1e4,Si=e=>"headers"in e,Up=async(e,t=Object.create(null))=>{let{all:r=!1,dot:n=!1}=t,i=(Si(e)?e.headers:e.raw.headers).get("Content-Type")?.split(";")[0].trim().toLowerCase();return i==="multipart/form-data"||i==="application/x-www-form-urlencoded"?Yx(e,{all:r,dot:n}):{}};async function Yx(e,t){if(!Si(e)&&e.bodyCache.formData)return Mp(await e.bodyCache.formData,t);let r=Si(e)?e.headers:e.raw.headers,n=await e.arrayBuffer(),o=Op(n,r.get("Content-Type")||"");Si(e)||(e.bodyCache.formData=o);let s=await o;return s?Mp(s,t):{}}function Mp(e,t){let r=Object.create(null),n={count:0};return e.forEach((o,s)=>{t.all||s.endsWith("[]")?Qx(r,s,o):r[s]=o}),t.dot&&Object.entries(r).forEach(([o,s])=>{o.includes(".")&&(Xx(r,o,s,n),delete r[o])}),r}var Qx=(e,t,r)=>{e[t]!==void 0?Array.isArray(e[t])?e[t].push(r):e[t]=[e[t],r]:t.endsWith("[]")?e[t]=[r]:e[t]=r},Xx=(e,t,r,n)=>{if(/(?:^|\.)__proto__\./.test(t))return;let o=e,s=t.split(".",Dp+2);s.length>Dp+1&&Pp(),s.forEach((i,a)=>{a===s.length-1?o[i]=r:((!o[i]||typeof o[i]!="object"||Array.isArray(o[i])||o[i]instanceof File)&&(n.count++>=Kx&&Pp(),o[i]=Object.create(null)),o=o[i])})},Pp=()=>{throw new Error("Nesting limit exceeded")};var hl=e=>{let t=e.split("/");return t[0]===""&&t.shift(),t},Fp=e=>{let{groups:t,path:r}=Zx(e),n=hl(r);return eR(n,t)},Zx=e=>{let t=[];return e=e.replace(/\{[^}]+\}/g,(r,n)=>{let o=`@${n}`;return t.push([o,r]),o}),{groups:t,path:e}},eR=(e,t)=>{for(let r=t.length-1;r>=0;r--){let[n]=t[r];for(let o=e.length-1;o>=0;o--)if(e[o].includes(n)){e[o]=e[o].replace(n,t[r][1]);break}}return e},vi={},qp=(e,t)=>{if(e==="*")return"*";let r=e.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);if(r){let n=`${e}#${t}`;return vi[n]||(r[2]?vi[n]=t&&t[0]!==":"&&t[0]!=="*"?[n,r[1],new RegExp(`^${r[2]}(?=/${t})`)]:[e,r[1],new RegExp(`^${r[2]}$`)]:vi[n]=[e,r[1],!0]),vi[n]}return null},jp=(e,t)=>{try{return t(e)}catch{return e.replace(/(?:%[0-9A-Fa-f]{2})+/g,r=>{try{return t(r)}catch{return r}})}},tR=e=>jp(e,decodeURI),gl=e=>{let t=e.url,r=t.indexOf("/",t.indexOf(":")+4),n=r;for(;n<t.length;n++){let o=t.charCodeAt(n);if(o===37){let s=t.indexOf("?",n),i=t.indexOf("#",n),a=s===-1?i===-1?void 0:i:i===-1?s:Math.min(s,i),c=t.slice(r,a);return tR(c.includes("%25")?c.replace(/%25/g,"%2525"):c)}else if(o===63||o===35)break}return t.slice(r,n)};var Hp=e=>{let t=gl(e);return t.length>1&&t.at(-1)==="/"?t.slice(0,-1):t},Or=(e,t,...r)=>(r.length&&(t=Or(t,...r)),`${e?.[0]==="/"?"":"/"}${e}${t==="/"?"":`${e?.at(-1)==="/"?"":"/"}${t?.[0]==="/"?t.slice(1):t}`}`),Ai=e=>{if(e.charCodeAt(e.length-1)!==63||!e.includes(":"))return null;let t=e.split("/"),r=[],n="";return t.forEach(o=>{if(o!==""&&!/\:/.test(o))n+="/"+o;else if(/\:/.test(o))if(o.charCodeAt(o.length-1)===63){r.length===0&&n===""?r.push("/"):r.push(n);let s=o.slice(0,-1);n+="/"+s,r.push(n)}else n+="/"+o}),r.filter((o,s,i)=>i.indexOf(o)===s)},$i=e=>e.indexOf("%")!==-1?jp(e,rR):e,pl=e=>(e.indexOf("+")!==-1&&(e=e.replace(/\+/g," ")),$i(e)),Bp=(e,t,r)=>{let n=e.indexOf("#",8);n!==-1&&(e=e.slice(0,n));let o;if(!r&&t&&t.indexOf("%")===-1&&t.indexOf("+")===-1){let a=e.indexOf("?",8);if(a===-1)return;for(e.startsWith(t,a+1)||(a=e.indexOf(`&${t}`,a+1));a!==-1;){let c=e.charCodeAt(a+t.length+1);if(c===61){let l=a+t.length+2,u=e.indexOf("&",l);return pl(e.slice(l,u===-1?void 0:u))}else if(c==38||isNaN(c))return"";a=e.indexOf(`&${t}`,a+1)}if(o=/[%+]/.test(e),!o)return}let s=Object.create(null);o??=/[%+]/.test(e);let i=e.indexOf("?",8);for(;i!==-1;){let a=e.indexOf("&",i+1),c=e.indexOf("=",i);c>a&&a!==-1&&(c=-1);let l=e.slice(i+1,c===-1?a===-1?void 0:a:c);if(o&&(l=pl(l)),i=a,l==="")continue;let u;c===-1?u="":(u=e.slice(c+1,a===-1?void 0:a),o&&(u=pl(u))),r?(s[l]&&Array.isArray(s[l])||(s[l]=[]),s[l].push(u)):s[l]??=u}return t?s[t]:s},Wp=Bp,Gp=(e,t)=>Bp(e,t,!0),rR=decodeURIComponent;var Vp=class{raw;#t;#e;routeIndex=0;path;bodyCache={};constructor(e,t="/",r=[[]]){this.raw=e,this.path=t,this.#e=r}param(e){return e?this.#r(e):this.#s()}#r(e){let t=this.#e[0][this.routeIndex]?.[1][e],r=this.#n(t);return r&&$i(r)}#s(){let e={},t=Object.keys(this.#e[0][this.routeIndex]?.[1]??{});for(let r of t){let n=this.#n(this.#e[0][this.routeIndex][1][r]);n!==void 0&&(e[r]=$i(n))}return e}#n(e){return this.#e[1]?this.#e[1][e]:e}query(e){return Wp(this.url,e)}queries(e){return Gp(this.url,e)}header(e){if(e)return this.raw.headers.get(e)??void 0;let t=Object.create(null);return this.raw.headers.forEach((r,n)=>{t[n]=r}),t}async parseBody(e){return Up(this,e)}#o=e=>{let{bodyCache:t,raw:r}=this,n=t[e];if(n)return n;for(let o in t)return t[o].then(s=>(o==="json"&&(s=JSON.stringify(s)),new Response(s)[e]()));return t[e]=r[e]()};json(){return this.#o("text").then(e=>JSON.parse(e))}text(){return this.#o("text")}arrayBuffer(){return this.#o("arrayBuffer")}bytes(){return this.#o("arrayBuffer").then(e=>new Uint8Array(e))}blob(){return this.#o("blob")}formData(){return this.#o("formData")}addValidatedData(e,t){(this.#t??={})[e]=t}valid(e){return this.#t?.[e]}get url(){return this.raw.url}get method(){return this.raw.method}get[Cp](){return this.#e}get matchedRoutes(){return this.#e[0].map(([[,e]])=>e)}get routePath(){return this.#e[0].map(([[,e]])=>e)[this.routeIndex].path}};var Jp={Stringify:1,BeforeStream:2,Stream:3},nR=(e,t)=>{let r=new String(e);return r.isEscaped=!0,r.callbacks=t,r};var _l=async(e,t,r,n,o)=>{typeof e=="object"&&!(e instanceof String)&&(e instanceof Promise||(e=e.toString()),e instanceof Promise&&(e=await e));let s=e.callbacks;if(!s?.length)return Promise.resolve(e);o?o[0]+=e:o=[e];let i=Promise.all(s.map(a=>a({phase:t,buffer:o,context:n}))).then(a=>Promise.all(a.filter(Boolean).map(c=>_l(c,t,!1,n,o))).then(()=>o[0]));return r?nR(await i,s):i};var oR="text/plain; charset=UTF-8",wl=(e,t)=>({"Content-Type":e,...t}),jo=(e,t)=>new Response(e,t),yl=class{#t;#e;env={};#r;finalized=!1;error;#s;#n;#o;#u;#c;#l;#a;#d;#m;constructor(e,t){this.#t=e,t&&(this.#n=t.executionCtx,this.env=t.env,this.#l=t.notFoundHandler,this.#m=t.path,this.#d=t.matchResult)}get req(){return this.#e??=new Vp(this.#t,this.#m,this.#d),this.#e}get event(){if(this.#n&&"respondWith"in this.#n)return this.#n;throw Error("This context has no FetchEvent")}get executionCtx(){if(this.#n)return this.#n;throw Error("This context has no ExecutionContext")}get res(){return this.#o||=jo(null,{headers:this.#a??=new Headers})}set res(e){if(this.#o&&e){e=jo(e.body,e);for(let[t,r]of this.#o.headers.entries())if(t!=="content-type")if(t==="set-cookie"){let n=this.#o.headers.getSetCookie();e.headers.delete("set-cookie");for(let o of n)e.headers.append("set-cookie",o)}else e.headers.set(t,r)}this.#o=e,this.finalized=!0}render=(...e)=>(this.#c??=t=>this.html(t),this.#c(...e));setLayout=e=>this.#u=e;getLayout=()=>this.#u;setRenderer=e=>{this.#c=e};header=(e,t,r)=>{this.finalized&&(this.#o=jo(this.#o.body,this.#o));let n=this.#o?this.#o.headers:this.#a??=new Headers;t===void 0?n.delete(e):r?.append?n.append(e,t):n.set(e,t)};status=e=>{this.#s=e};set=(e,t)=>{this.#r??=new Map,this.#r.set(e,t)};get=e=>this.#r?this.#r.get(e):void 0;get var(){return this.#r?Object.fromEntries(this.#r):{}}#i(e,t,r){let n=this.#o?new Headers(this.#o.headers):this.#a;if(typeof t=="object"&&t.headers){n??=new Headers;for(let[s,i]of new Headers(t.headers))s==="set-cookie"?n.append(s,i):n.set(s,i)}if(r){if(!n){let s=0;for(let i in r)if(++s>1||typeof r[i]!="string"){n=new Headers;break}}if(n)for(let s in r){let i=r[s];if(typeof i=="string")n.set(s,i);else{n.delete(s);for(let a of i)n.append(s,a)}}}let o=typeof t=="number"?t:t?.status??this.#s;return jo(e,{status:o,headers:n??r})}newResponse=(...e)=>this.#i(...e);body=(e,t,r)=>this.#i(e,t,r);text=(e,t,r)=>!this.#a&&!this.#s&&!t&&!r&&!this.finalized?new Response(e):this.#i(e,t,wl(oR,r));json=(e,t,r)=>this.#i(JSON.stringify(e),t,wl("application/json",r));html=(e,t,r)=>{let n=o=>this.#i(o,t,wl("text/html; charset=UTF-8",r));return typeof e=="object"?_l(e,Jp.Stringify,!1,{}).then(n):n(e)};redirect=(e,t)=>{let r=String(e);return this.header("Location",/[^\x00-\xFF]/.test(r)?encodeURI(r):r),this.newResponse(null,t??302)};notFound=()=>(this.#l??=()=>jo(),this.#l(this))};var Qe="ALL",zp="all",Kp=["get","post","put","delete","options","patch","query"],ki="Can not add a route since the matcher is already built.",xi=class extends Error{};var Yp="__COMPOSED_HANDLER";var sR=e=>e.text("404 Not Found",404),Qp=(e,t)=>{if("getResponse"in e){let r=e.getResponse();return t.newResponse(r.body,r)}return console.error(e),t.text("Internal Server Error",500)},Xp=class Zp{get;post;put;delete;options;patch;query;all;on;use;router;getPath;_basePath="/";#t="/";routes=[];constructor(t={}){[...Kp,zp].forEach(s=>{this[s]=(i,...a)=>(typeof i=="string"?this.#t=i:this.#s(s,this.#t,i),a.forEach(c=>{this.#s(s,this.#t,c)}),this)}),this.on=(s,i,...a)=>{for(let c of[i].flat()){this.#t=c;for(let l of[s].flat())a.map(u=>{this.#s(l.toUpperCase(),this.#t,u)})}return this},this.use=(s,...i)=>(typeof s=="string"?this.#t=s:(this.#t="*",i.unshift(s)),i.forEach(a=>{this.#s(Qe,this.#t,a)}),this);let{strict:n,...o}=t;Object.assign(this,o),this.getPath=n??!0?t.getPath??gl:Hp}#e(){let t=new Zp({router:this.router,getPath:this.getPath});return t.errorHandler=this.errorHandler,t.#r=this.#r,t.routes=this.routes,t}#r=sR;errorHandler=Qp;route(t,r){let n=this.basePath(t);return r.routes.map(o=>{let s;r.errorHandler===Qp?s=o.handler:(s=async(i,a)=>(await fl([],r.errorHandler)(i,()=>o.handler(i,a))).res,s[Yp]=o.handler),n.#s(o.method,o.path,s,o.basePath)}),this}basePath(t){let r=this.#e();return r._basePath=Or(this._basePath,t),r}onError=t=>(this.errorHandler=t,this);notFound=t=>(this.#r=t,this);mount(t,r,n){let o,s;n&&(typeof n=="function"?s=n:(s=n.optionHandler,n.replaceRequest===!1?o=c=>c:o=n.replaceRequest));let i=s?c=>{let l=s(c);return Array.isArray(l)?l:[l]}:c=>{let l;try{l=c.executionCtx}catch{}return[c.env,l]};o||=(()=>{let c=Or(this._basePath,t),l=c==="/"?0:c.length;return u=>{let d=new URL(u.url);return d.pathname=this.getPath(u).slice(l)||"/",new Request(d,u)}})();let a=async(c,l)=>{let u=await r(o(c.req.raw),...i(c));if(u)return u;await l()};return this.#s(Qe,Or(t,"*"),a),this}#s(t,r,n,o){t=t.toUpperCase(),r=Or(this._basePath,r);let s={basePath:o!==void 0?Or(this._basePath,o):this._basePath,path:r,method:t,handler:n};this.router.add(t,r,[n,s]),this.routes.push(s)}#n(t,r){if(t instanceof Error)return this.errorHandler(t,r);throw t}#o(t,r,n,o){if(o==="HEAD")return(async()=>new Response(null,await this.#o(t,r,n,"GET")))();let s=this.getPath(t,{env:n}),i=this.router.match(o,s),a=new yl(t,{path:s,matchResult:i,env:n,executionCtx:r,notFoundHandler:this.#r});if(i[0].length===1){let l;try{l=i[0][0][0][0](a,async()=>{a.res=await this.#r(a)})}catch(u){return this.#n(u,a)}return l instanceof Promise?l.then(u=>u||(a.finalized?a.res:this.#r(a))).catch(u=>this.#n(u,a)):l??this.#r(a)}let c=fl(i[0],this.errorHandler,this.#r);return(async()=>{try{let l=await c(a);if(!l.finalized)throw new Error("Context is not finalized. Did you forget to return a Response object or `await next()`?");return l.res}catch(l){return this.#n(l,a)}})()}fetch=(t,...r)=>this.#o(t,r[1],r[0],t.method);request=(t,r,n,o)=>t instanceof Request?this.fetch(r?new Request(t,r):t,n,o):(t=t.toString(),this.fetch(new Request(/^https?:\/\//.test(t)?t:`http://localhost${Or("/",t)}`,r),n,o));fire=()=>{addEventListener("fetch",t=>{t.respondWith(this.#o(t.request,t,void 0,t.request.method))})}};var Ge=()=>Object.create(null);var Ri=[];function El(e,t){let r=this.buildAllMatchers(),n=(o,s)=>{let i=r[o]||r[Qe],a=i[2][s];if(a)return a;let c=s.match(i[0]);if(!c)return[[],Ri];let l=c.indexOf("",1);return[i[1][l],c]};return this.match=n,n(e,t)}var Hn="[^/]+",Mr=".*",fr="(?:|/.*)",Dr=Symbol(),eh=new Set(".\\+*[^]$()");function iR(e,t){return e.length===1?t.length===1?e<t?-1:1:-1:t.length===1?1:e===Mr||e===fr?t===fr?-1:1:t===Mr||t===fr?-1:e===Hn?1:t===Hn?-1:e.length===t.length?e<t?-1:1:t.length-e.length}var th=class bl{#t;#e;#r=Ge();insert(t,r,n,o,s){let i=this;for(let a=0,c=t.length;a<c;a++){let l=t[a],u=l.length===1?l==="*"?a===c-1?["","",Mr]:["","",Hn]:null:l==="/*"?["","",fr]:l.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/),d;if(u){let m=u[1],f=u[2]||Hn;if(m&&u[2]&&(f===".*"||(f=f.replace(/^\((?!\?:)(?=[^)]+\)$)/,"(?:"),/\((?!\?:)/.test(f))||f.length===1&&eh.has(f)))throw Dr;if(d=i.#r[f],!d){if(f!==Mr&&f!==fr){for(let p in i.#r)if((f.length>1||p.length>1)&&p!==Mr&&p!==fr)throw Dr}d=i.#r[f]=new bl}m!==""&&(d.#e??=o.varIndex++,n.push([m,d.#e]))}else if(d=i.#r[l],!d){for(let m in i.#r)if(m.length>1&&m!==Mr&&m!==fr)throw Dr;d=i.#r[l]=new bl}i=d}if(i.#t!==void 0)throw Dr;i.#t=s?-1:r}buildRegExpStr(){let r=Object.keys(this.#r).sort(iR).map(n=>{let o=this.#r[n],s=o.buildRegExpStr();return s===""?"":(typeof o.#e=="number"?`(${n})@${o.#e}`:eh.has(n)?`\\${n}`:n)+s}).filter(Boolean);return typeof this.#t=="number"&&this.#t!==-1&&r.unshift(`#${this.#t}`),r.length===0?"":r.length===1?r[0]:"(?:"+r.join("|")+")"}};var Tl=class{#t={varIndex:0};#e=new th;#r=0;paths=Ge();insert(e,t){if(t){this.#e.insert(e.split(""),0,[],this.#t,!0);return}let r=[],n=[],o=e;for(let i=0;;){let a=!1;if(o=o.replace(/\{[^}]+\}/g,c=>{let l=`@\\${i}`;return n[i]=[l,c],i++,a=!0,l}),!a)break}let s=o.match(/(?::[^\/]+)|(?:\/\*$)|./g)||[];for(let i=n.length-1;i>=0;i--){let[a]=n[i];for(let c=s.length-1;c>=0;c--)if(s[c].indexOf(a)!==-1){s[c]=s[c].replace(a,n[i][1]);break}}this.#e.insert(s,this.#r,r,this.#t,!1),this.paths[e]=[this.#r++,r]}buildRegExp(){let e=this.#e.buildRegExpStr();if(e==="")return[/^$/,[],[]];let t=0,r=[],n=[];return e=e.replace(/#(\d+)|@(\d+)|\.\*\$/g,(o,s,i)=>s!==void 0?(r[++t]=Number(s),"$()"):(i!==void 0&&(n[Number(i)]=++t),"")),[new RegExp(`^${e}`),r,n]}};var rh=Ge();function nh(e){return rh[e]??=new RegExp(`^${e.replace(/\/:[^/{}]+(?:\{\[\^\/]\+})?(?=[/{]|$)|\/?\*$|([.\\+*[^\]$()?{}|])/g,(t,r)=>r?`\\${r}`:t==="/*"?fr:t==="*"?Mr:`/:${Hn}`)}$`)}function Ni(e,t){for(let r of Object.keys(e).sort((n,o)=>o.length-n.length))if(nh(r).test(t))return[...e[r]]}var Ii=class{name="RegExpRouter";#t;#e;#r;constructor(){this.#t={[Qe]:Ge()},this.#e={[Qe]:Ge()},this.#r={[Qe]:new Tl}}#s(e,t){try{this.#r[e].insert(t,!/\*|\/:/.test(t))}catch(r){throw r===Dr?new xi(t):r}}add(e,t,r){let n=this.#t,o=this.#e;if(!n)throw new Error(ki);if(!n[e]){this.#r[e]=new Tl;for(let a of[n,o]){a[e]=Ge();for(let c in a[Qe])a[e][c]=[...a[Qe][c]],this.#s(e,c)}}t==="/*"&&(t="*");let s=e===Qe?Object.keys(n):[e];if(/\*$/.test(t)){let a=nh(t);for(let c of s)n[c][t]||(this.#s(c,t),n[c][t]=Ni(n[c],t)||Ni(n[Qe],t)||[]);for(let c of[n,o])for(let l of s)for(let u in c[l])a.test(u)&&c[l][u].push([r,t]);return}let i=Ai(t)||[t];for(let a of i)for(let c of s)o[c][a]||(this.#s(c,a),o[c][a]=Ni(n[c],a)||Ni(n[Qe],a)||[]),o[c][a].push([r,a])}match=El;buildAllMatchers(){let e=Ge();for(let t of Object.keys(this.#e))e[t]=this.#n(t);return this.#t=this.#e=this.#r=void 0,rh=Ge(),e}#n(e){let t=this.#t[e],r=this.#e[e],n=this.#r[e],o=Ge(),s=[],[i,a,c]=n.buildRegExp();for(let l of[t,r])for(let u in l){let d=l[u],m=n.paths[u];if(!m){o[u]=[d.map(([f])=>[f,Ge()]),Ri];continue}s[m[0]]=d.map(([f,p])=>[f,n.paths[p][1].reduceRight((h,[g],_)=>(h[g]=c[m[1][_][1]],h),Ge())])}return[i,a.map(l=>s[l]),o]}};var Sl=class{name="SmartRouter";#t=[];#e=[];constructor(e){this.#t=e.routers}add(e,t,r){if(!this.#e)throw new Error(ki);this.#e.push([e,t,r])}match(e,t){if(!this.#e)throw new Error("Fatal error");let r=this.#t,n=this.#e,o=r.length,s=0,i;for(;s<o;s++){let a=r[s];try{for(let c=0,l=n.length;c<l;c++)a.add(...n[c]);i=a.match(e,t)}catch(c){if(c instanceof xi)continue;throw c}this.match=a.match.bind(a),this.#t=[a],this.#e=void 0;break}if(s===o)throw new Error("Fatal error");return this.name=`SmartRouter + ${this.activeRouter.name}`,i}get activeRouter(){if(this.#e||this.#t.length!==1)throw new Error("No active router has been determined yet.");return this.#t[0]}};var vl=Ge(),aR=0,oh=class sh{#t=[];#e=Ge();#r=[];#s;#n=vl;insert(t,r,n){let o=this,s=Fp(r),i=new Set,a=0;for(let c of s){let l=s[++a],u=qp(c,l)||(l===void 0&&c&&c.indexOf("*")===c.length-1?c:null),d=Array.isArray(u),m=d?u[0]:u||c,f=o.#e[m]||=new sh;u&&!f.#s&&(f.#s=u,o.#r.push(f)),o=f,d&&i.add(u[1])}o.#t.push({[t]:{handler:n,possibleKeys:[...i],score:++aR}})}#o(t,r,n,o,s){for(let i=0,a=r.#t.length;i<a;i++){let c=r.#t[i],l=c[n]||c[Qe];if(l){l.params=Ge(),t.push(l);for(let u=0,d=l.possibleKeys.length;u<d;u++){let m=l.possibleKeys[u];l.params[m]=s?.[m]&&!u?s[m]:o[m]??s?.[m]}}}}search(t,r){let n=[];this.#n=vl;let s=[this],i=hl(r),a=[],c=i.length,l=null;for(let u=0;u<c;u++){let d=i[u],m=u===c-1,f=[];for(let h=0,g=s.length;h<g;h++){let _=s[h],E=_.#e[d];E&&(E.#n=_.#n,m?(E.#e["*"]&&this.#o(n,E.#e["*"],t,_.#n),this.#o(n,E,t,_.#n)):f.push(E));for(let y of _.#r){let S=y.#s,T=_.#n===vl?{}:{..._.#n};if(typeof S=="string"){(S==="*"||d.startsWith(S.slice(0,-1)))&&(this.#o(n,y,t,_.#n),S==="*"&&(y.#n=T,f.push(y)));continue}let[,R,x]=S;if(!(!d&&x===!0)){if(x!==!0){if(!l){l=[];let H=r[0]==="/"?1:0;for(let L=0;L<c;L++)l[L]=H,H+=i[L].length+1}let I=r.slice(l[u]),A=x.exec(I);if(A){T[R]=A[0],this.#o(n,y,t,_.#n,T),A[0].length===I.length&&y.#e["*"]&&this.#o(n,y.#e["*"],t,_.#n,T);for(let H in y.#e){y.#n=T;let L=A[0].match(/\//g)?.length??0;(a[L]||=[]).push(y);break}continue}}(x===!0||x.test(d))&&(T[R]=d,m?(this.#o(n,y,t,T,_.#n),y.#e["*"]&&this.#o(n,y.#e["*"],t,T,_.#n)):(y.#n=T,f.push(y)))}}}let p=a.shift();s=p?f.concat(p):f}return n[1]&&n.sort((u,d)=>u.score-d.score),[n.map(({handler:u,params:d})=>[u,d])]}};var Al=class{name="TrieRouter";#t=new oh;add(e,t,r){for(let n of Ai(t)||[t])this.#t.insert(e,n,r)}match(e,t){return this.#t.search(e,t)}};var dn=class extends Xp{constructor(e={}){super(e),this.router=e.router??new Sl({routers:[new Ii,new Al]})}};import{join as cR}from"node:path";function lR(e){return e||(process.env.LMBEE_TEAMS_CONF?process.env.LMBEE_TEAMS_CONF:cR(process.cwd(),"teams.conf"))}function uR(e,t){let r=process.env.LMBEE_TEAM_NAME;if(r===void 0)return;let n=t.find(o=>o.name===r);if(!(n===void 0||!B(n)))try{Dm(e.db,r,new Date().toISOString())}catch{}}function Li(e={}){let t=Hs(e.dbPath,{readOnly:e.readOnly??!1}),r=lR(e.teamsConfPath),n=rn(t.db,r);return e.readOnly||uR(t,n),{db:t,teamsConfPath:r,teams:n}}import{existsSync as ML,readFileSync as PL,statSync as UL}from"node:fs";import{execFile as dR}from"node:child_process";import{promisify as mR}from"node:util";var Ci=mR(dR),Bo=3,Ho="auto_nudge_redirect:",$l=3,kl=5*60*6e4;function $t(e,t){let r=e.prepare("SELECT v FROM kv WHERE k = ?").get(Ho+t);if(r===void 0)return null;try{let n=JSON.parse(r.v);return typeof n.companionTeam!="string"||n.companionTeam.length===0?null:{companionTeam:n.companionTeam,workerAlias:typeof n.workerAlias=="string"&&n.workerAlias.length>0?n.workerAlias:"Worker",commitThreshold:typeof n.commitThreshold=="number"&&n.commitThreshold>0?n.commitThreshold:$l,hoursThresholdMs:typeof n.hoursThresholdMs=="number"&&n.hoursThresholdMs>0?n.hoursThresholdMs:kl,shiftStartedTs:typeof n.shiftStartedTs=="string"?n.shiftStartedTs:null,shiftStartedSha:typeof n.shiftStartedSha=="string"?n.shiftStartedSha:null,turnsDispatched:typeof n.turnsDispatched=="number"&&n.turnsDispatched>=0?n.turnsDispatched:0,lastReviewedTurn:typeof n.lastReviewedTurn=="number"&&n.lastReviewedTurn>=0?n.lastReviewedTurn:0}}catch{return null}}function xl(e){return e.prepare("SELECT k FROM kv WHERE k LIKE ?").all(Ho+"%").map(r=>r.k.slice(Ho.length))}function Oi(e,t,r){e.prepare("INSERT INTO kv(k, v) VALUES (?, ?) ON CONFLICT(k) DO UPDATE SET v = excluded.v").run(Ho+t,JSON.stringify(r))}function ih(e,t){e.prepare("DELETE FROM kv WHERE k = ?").run(Ho+t)}async function ah(e,t){try{let{stdout:r}=await t("git",["-C",e,"rev-parse","HEAD"],{timeout:1e4});return r.trim()||null}catch{return null}}async function fR(e,t,r){try{let{stdout:n}=await r("git",["-C",e,"rev-list","--count",`${t}..HEAD`],{timeout:1e4}),o=Number.parseInt(n.trim(),10);return Number.isNaN(o)?null:o}catch{return null}}async function ch(e,t,r,n,o,s=Ci){let i=r.shiftStartedTs!==null,a=i?r.shiftStartedSha:await ah(n,s);Oi(e,t,{...r,turnsDispatched:r.turnsDispatched+1,shiftStartedTs:i?r.shiftStartedTs:o,shiftStartedSha:a})}async function lh(e,t,r=Date.now(),n=Ci){let o=[];for(let s of xl(e)){let i=$t(e,s);if(i===null||i.shiftStartedTs===null)continue;let a=t.get(s);if(a===void 0)continue;let c=(r-Date.parse(i.shiftStartedTs))/(60*6e4),l=i.shiftStartedSha!==null?await fR(a,i.shiftStartedSha,n):null,u=i.turnsDispatched<=Bo&&i.turnsDispatched>i.lastReviewedTurn,d=c*60*6e4>=i.hoursThresholdMs,m=l!==null&&l>=i.commitThreshold;(u||d||m)&&o.push({team:s,companionTeam:i.companionTeam,workerAlias:i.workerAlias,commitCount:l,hoursElapsed:c,shiftStartedTs:i.shiftStartedTs,shiftStartedSha:i.shiftStartedSha,isRampUp:u,turnNumber:i.turnsDispatched})}return o}async function uh(e,t,r,n,o=Ci){let s=$t(e,t);if(s===null)return;let i=await ah(r,o);Oi(e,t,{...s,shiftStartedTs:n,shiftStartedSha:i,lastReviewedTurn:s.turnsDispatched})}async function dh(e,t,r=Ci){let n=e.hoursElapsed.toFixed(1),o=e.commitCount===null?"unknown (git check failed)":String(e.commitCount),s=null;if(e.shiftStartedSha!==null)try{let{stdout:a}=await r("git",["-C",t,"log","--oneline",`${e.shiftStartedSha}..HEAD`],{timeout:1e4});s=a.trim()}catch{s=null}let i=s!==null&&s.length>0?`
|
|
194
194
|
|
|
195
195
|
Commits this shift:
|
|
196
|
-
${s}`:"";return e.isRampUp?`[auto-nudge-redirect] RAMP-UP turn ${e.turnNumber}/${Bo} for your Worker (${e.companionTeam}:${e.workerAlias}) -- always reviewed during ramp-up, regardless of commits/time. Please review this turn's own work and correct/coach as needed, then note (in a task note or reply) specifically WHAT you had to correct, if anything -- that's the data point that decides whether this coaching transfers to the next team's Worker.${i}`:`[auto-nudge-redirect] Your Worker (${e.companionTeam}:${e.workerAlias}) shift is due for review -- ${o} commit(s), ${n}h elapsed (threshold: commits or hours, whichever came first). Please review the Worker's own work and tie it up.${i}`}import{execFile as gR}from"node:child_process";import{existsSync as _R,readdirSync as ph,readFileSync as hh,statSync as wR}from"node:fs";import{hostname as yR}from"node:os";import{promisify as ER}from"node:util";import{existsSync as fR,statSync as pR}from"node:fs";var K2=15*6e4;function hR(e,t,r={}){let n=r.existsSyncImpl??fR,o=r.statSyncImpl??pR,s=r.nowMs??Date.now();if(!n(e))return!1;if(t===void 0)return!0;try{let i=o(e).mtime.getTime();return s-i<=t}catch{return!1}}function Rl(e,t,r){if(e===null)return!1;let n=Date.parse(e);return Number.isNaN(n)?!1:r-n<=t}function dh(e,t){if(e===null)return null;let r=Date.parse(e);return Number.isNaN(r)?null:t-r}function Bn(e,t,r,n,o={}){if(e!==void 0&&hR(e,t,o))return!0;if(n===void 0)return!1;let s=o.nowMs??Date.now();return Rl(r,n,s)}var bR=ER(gR),TR=45*6e4,gh=100,mh=gh,SR=3;async function vR(e,t=3e4){try{let{stdout:r}=await bR("lmctl",["status",e,"--json"],{timeout:t}),n=JSON.parse(r);return typeof n!="object"||n===null||!Array.isArray(n.members)?null:n}catch{return null}}function Di(e,t){try{let r=hh(`${t}/${e}/stat`,"utf8"),n=r.lastIndexOf(")");if(n===-1)return null;let o=r.slice(n+1).trim().split(/\s+/),s=Number(o[1]),i=Number(o[11]),a=Number(o[12]);return!Number.isFinite(s)||!Number.isFinite(i)||!Number.isFinite(a)?null:{ppid:s,utime:i,stime:a}}catch{return null}}function _h(e,t="/proc"){let r=Di(e,t);return r===null?null:r.utime+r.stime}function fh(e,t){try{let r=hh(`${t}/${e}/io`,"utf8"),n=r.match(/^rchar:\s*(\d+)/m),o=r.match(/^wchar:\s*(\d+)/m);if(!n||!o)return null;let s=Number(n[1]),i=Number(o[1]);return!Number.isFinite(s)||!Number.isFinite(i)?null:s+i}catch{return null}}function Nl(e,t="/proc"){let r=Di(e,t);if(r===null)return null;let n;try{n=ph(t)}catch{return r.utime+r.stime}let o=new Map,s=new Map;for(let l of n){if(!/^\d+$/.test(l))continue;let u=Number(l);if(u===e)continue;let d=Di(u,t);if(d===null)continue;s.set(u,d);let m=o.get(d.ppid);m?m.push(u):o.set(d.ppid,[u])}let i=r.utime+r.stime,a=[...o.get(e)??[]],c=new Set([e]);for(;a.length>0;){let l=a.shift();c.has(l)||(c.add(l),i+=s.get(l).utime+s.get(l).stime,a.push(...o.get(l)??[]))}return i}function wh(e,t="/proc"){let r=fh(e,t);if(r===null)return null;let n;try{n=ph(t)}catch{return r}let o=new Map;for(let c of n){if(!/^\d+$/.test(c))continue;let l=Number(c);if(l===e)continue;let u=Di(l,t);if(u===null)continue;let d=o.get(u.ppid);d?d.push(l):o.set(u.ppid,[l])}let s=r,i=[...o.get(e)??[]],a=new Set([e]);for(;i.length>0;){let c=i.shift();if(a.has(c))continue;a.add(c);let l=fh(c,t);l!==null&&(s+=l),i.push(...o.get(c)??[])}return s}function AR(e,t){if(e.state!=="busy")return null;if(e.inFlight!==null)return e.inFlight.holderPid!==null?{pid:e.inFlight.holderPid,startedAt:e.inFlight.startedAt}:null;if(e.terminalLock!==null)return e.terminalLock.holderHost!==t?null:{pid:e.terminalLock.holderPid,startedAt:e.terminalLock.startedAt};if(e.terminalInvocation!==null){let{holderPid:r,holderHost:n,startedAt:o}=e.terminalInvocation;return r===null||n!==t?null:{pid:r,startedAt:o}}return null}async function $R(e,t,r,n){let o=n.fetchHealthImpl??vR,s=n.readProcStatImpl??Nl,i=n.hostnameImpl??yR,a=n.wallClockThresholdMs??TR,c=n.requiredLowCpuStreak??SR,l=await o(r);if(l===null)return;let u=l.members.find(R=>R.alias===t.leadAlias);if(u===void 0)return;let d=AR(u.liveness,i());if(d===null){let R=ie(e,t.name);(R?.holder_watch_pid!==null&&R?.holder_watch_pid!==void 0||R?.hung_holder_flagged_ts!==null&&R?.hung_holder_flagged_ts!==void 0)&&hc(e,t.name);return}let m=new Date().toISOString(),f=s(d.pid);if(f===null){pc(e,t.name,`${t.leadAlias}'s servicing lock has outlived its holder -- pid ${d.pid} (started ${d.startedAt}) is NOT RUNNING. Lock is leaked, not hung; nothing to kill, only the lock needs releasing.`,m);return}let p=ie(e,t.name);if(!(p?.holder_watch_pid===d.pid&&p?.holder_watch_started_at===d.startedAt)){fc(e,t.name,d.pid,d.startedAt,f,m,0);return}let g=Date.now()-Date.parse(d.startedAt),_=p.holder_watch_cpu_ticks!==null?f-p.holder_watch_cpu_ticks:null,E=_!==null&&_<mh,y=p.holder_watch_low_cpu_streak??0,S=E?y+1:0;if(fc(e,t.name,d.pid,d.startedAt,f,m,S),g<a||S<c)return;let T=Math.round(g/6e4);pc(e,t.name,`${t.leadAlias} has held its servicing lock for ~${T}m with under ${mh/gh}s of CPU time across ${S} consecutive checks -- possibly hung, not just slow.`,m)}async function yh(e,t,r={}){let n=r.existsSyncImpl??_R,o=r.statSyncImpl??wR,s=r.nowMs??Date.now();for(let i of t){if(!B(i))continue;if(r.sessionAliveExemptTeamName!==void 0&&i.name===r.sessionAliveExemptTeamName&&Bn(r.sessionAliveExemptPath,r.sessionAliveFreshnessMs,r.activityFreshnessMs!==void 0?ie(e,i.name)?.last_cli_activity_ts??null:null,r.activityFreshnessMs,{existsSyncImpl:n,statSyncImpl:o,nowMs:s})){hc(e,i.name);continue}let a;try{a=Q(i)}catch{continue}try{await $R(e,i,a,r)}catch{continue}}}var Wo="provider_disabled:";function Eh(e,t){try{let r=JSON.parse(t);return typeof r.disabledAt!="string"?null:{provider:e,disabledAt:r.disabledAt,reason:typeof r.reason=="string"?r.reason:null,expiresAt:typeof r.expiresAt=="string"?r.expiresAt:null}}catch{return null}}function Mi(e,t){let r=e.prepare("SELECT v FROM kv WHERE k = ?").get(Wo+t);return r===void 0?null:Eh(t,r.v)}function Pi(e,t,r={}){let n={provider:t,disabledAt:r.nowIso??new Date().toISOString(),reason:r.reason??null,expiresAt:r.expiresAt??null};e.prepare("INSERT INTO kv(k, v) VALUES (?, ?) ON CONFLICT(k) DO UPDATE SET v = excluded.v").run(Wo+t,JSON.stringify(n))}function bh(e,t){e.prepare("DELETE FROM kv WHERE k = ?").run(Wo+t)}function Go(e){let t=e.prepare("SELECT k, v FROM kv WHERE k LIKE ?").all(`${Wo}%`),r=[];for(let n of t){let o=n.k.slice(Wo.length),s=Eh(o,n.v);s!==null&&r.push(s)}return r}function it(e,t,r=Date.now()){let n;try{n=Mi(e,t)}catch{return{disabled:!0,config:null,failClosed:!0}}return n===null?{disabled:!1,config:null,failClosed:!1}:n.expiresAt!==null&&Date.parse(n.expiresAt)<=r?{disabled:!1,config:null,failClosed:!1}:{disabled:!0,config:n,failClosed:!1}}import{existsSync as kR,readFileSync as xR,readdirSync as RR,statSync as Th}from"node:fs";import{basename as Ui}from"node:path";var Ll="orphan_would_reap",NR=5e3,IR=6e4,LR=100,CR=3,OR=45*6e4;function Sh(e,t){try{let n=xR(`${e}/${t}/cmdline`,"utf8").split("\0").filter(a=>a.length>0),o=n.indexOf("chat");if(o<=0||o+1>=n.length)return null;let s=n[o-1]??"";if(!s.includes("lmctl")&&!s.includes("lctl"))return null;let i=n[o+1];return i.includes(".lmctl:")?i:null}catch{return null}}function vh(e,t){try{return Th(`${e}/${t}`).mtime.getTime()}catch{return null}}function Cl(e){let t;try{t=RR(e)}catch{return[]}let r=[];for(let n of t){if(!/^\d+$/.test(n))continue;let o=Number(n),s=Sh(e,o);if(s===null)continue;let i=vh(e,o);i!==null&&r.push({pid:o,target:s,startedAtMs:i})}return r.sort((n,o)=>n.pid-o.pid),r}function Il(e){let t=e.lastIndexOf(":");return t===-1?null:{teamfilePath:e.slice(0,t),alias:e.slice(t+1)}}function DR(e,t){if(t===null)return!1;let r=Il(e),n=Il(t);return r===null||n===null?!1:r.alias===n.alias&&Ui(r.teamfilePath)===Ui(n.teamfilePath)}function MR(e,t,r){return t.some(s=>s.pid!==e.pid&&s.target===e.target&&(s.startedAtMs>e.startedAtMs||s.startedAtMs===e.startedAtMs&&s.pid>e.pid))?{action:"reap",reason:`target "${e.target}" has a NEWER OS process for the same target -- this one is a leftover from a prior attempt`,requiresCpuCorroboration:!0}:r.running.find(s=>s.kind==="chat"&&DR(e.target,s.target))===void 0?{action:"reap",reason:`target "${e.target}" is not in lctl's own running (chat) bucket at all -- orphaned`,requiresCpuCorroboration:!0}:{action:"skip"}}function PR(e,t,r,n,o,s,i,a){let c=s(t.pid,a);if(c===null)return!1;let l=Mm(e,t.target,t.startedAtMs,t.pid);if(l===null||l.cpu_ticks===null)return gc(e,t.target,t.startedAtMs,t.pid,c,i,0),!1;let m=c-l.cpu_ticks<LR?l.low_cpu_streak+1:0;return gc(e,t.target,t.startedAtMs,t.pid,c,i,m),o-t.startedAtMs<n?!1:m>=r}function UR(e,t){let r=e.find(n=>n.name===t);if(r===void 0||!B(r))return null;try{return Q(r)}catch{return null}}function FR(e,t){let r=Il(t);if(r===null)return t;for(let n of e)if(B(n))try{let o=Q(n);if(Ui(o)===Ui(r.teamfilePath))return n.name}catch{continue}return t}async function qR(e,t,r,n,o){if(Sh(e,t.pid)!==t.target||vh(e,t.pid)!==t.startedAtMs)return!1;try{n(-t.pid,"SIGTERM")}catch{return!1}await o(r);try{n(-t.pid,0)}catch{return!0}try{n(-t.pid,"SIGKILL")}catch{}return!0}async function Ah(e,t,r,n={}){let o=n.procPath??"/proc",s=n.safetyMarginMs??IR,i=n.sigkillGraceMs??NR,a=n.requiredLowCpuStreak??CR,c=n.minCorroborationWallClockMs??OR,l=n.existsSyncImpl??kR,u=n.statSyncImpl??Th,d=n.killImpl??process.kill.bind(process),m=n.sleepImpl??(R=>new Promise(x=>setTimeout(x,R))),f=n.readProcCpuTicksImpl??_h,p=n.insertEventImpl??ot,h=n.dryRun??!1,g=n.nowMs??Date.now(),_=new Date(g).toISOString(),E=n.sessionAliveExemptTeamName!==void 0&&Bn(n.sessionAliveExemptPath,n.sessionAliveFreshnessMs,n.activityFreshnessMs!==void 0?ie(e,n.sessionAliveExemptTeamName)?.last_cli_activity_ts??null:null,n.activityFreshnessMs,{existsSyncImpl:l,statSyncImpl:u,nowMs:g}),y=E?UR(t,n.sessionAliveExemptTeamName):null;E&&y===null&&process.stderr.write(`[orphan-reconciler] sessionAliveExemptTeamName "${n.sessionAliveExemptTeamName}" is configured and its session-alive file exists, but that team could not be resolved -- the exemption is NOT currently protecting it
|
|
197
|
-
`);let S;try{S=Cl(o)}catch{return}Pm(e,S.map(R=>({target:R.target,startedAtMs:R.startedAtMs,pid:R.pid})));let T=S.filter(R=>g-R.startedAtMs>=s);for(let R of S){if(g-R.startedAtMs<s)continue;if(y!==null){let I=R.target.lastIndexOf(":");if(R.target.slice(0,I)===y)continue}let x=
|
|
198
|
-
`)}catch{}continue}try{let I=await
|
|
199
|
-
`)}catch{continue}}}}import{existsSync as
|
|
200
|
-
WHERE NOT EXISTS (SELECT 1 FROM hang_probe_outcome h WHERE h.target = o.target AND h.started_at_ms = o.started_at_ms AND h.pid = o.pid)`).all()}catch{l=[]}for(let u of l)if(!c.has(`${u.target}\0${u.started_at_ms}\0${u.pid}`))try{let d=
|
|
196
|
+
${s}`:"";return e.isRampUp?`[auto-nudge-redirect] RAMP-UP turn ${e.turnNumber}/${Bo} for your Worker (${e.companionTeam}:${e.workerAlias}) -- always reviewed during ramp-up, regardless of commits/time. Please review this turn's own work and correct/coach as needed, then note (in a task note or reply) specifically WHAT you had to correct, if anything -- that's the data point that decides whether this coaching transfers to the next team's Worker.${i}`:`[auto-nudge-redirect] Your Worker (${e.companionTeam}:${e.workerAlias}) shift is due for review -- ${o} commit(s), ${n}h elapsed (threshold: commits or hours, whichever came first). Please review the Worker's own work and tie it up.${i}`}import{execFile as _R}from"node:child_process";import{existsSync as wR,readdirSync as hh,readFileSync as gh,statSync as yR}from"node:fs";import{hostname as ER}from"node:os";import{promisify as bR}from"node:util";import{existsSync as pR,statSync as hR}from"node:fs";var X2=15*6e4;function gR(e,t,r={}){let n=r.existsSyncImpl??pR,o=r.statSyncImpl??hR,s=r.nowMs??Date.now();if(!n(e))return!1;if(t===void 0)return!0;try{let i=o(e).mtime.getTime();return s-i<=t}catch{return!1}}function Rl(e,t,r){if(e===null)return!1;let n=Date.parse(e);return Number.isNaN(n)?!1:r-n<=t}function mh(e,t){if(e===null)return null;let r=Date.parse(e);return Number.isNaN(r)?null:t-r}function Bn(e,t,r,n,o={}){if(e!==void 0&&gR(e,t,o))return!0;if(n===void 0)return!1;let s=o.nowMs??Date.now();return Rl(r,n,s)}var TR=bR(_R),SR=45*6e4,_h=100,fh=_h,vR=3;async function AR(e,t=3e4){try{let{stdout:r}=await TR("lmctl",["status",e,"--json"],{timeout:t}),n=JSON.parse(r);return typeof n!="object"||n===null||!Array.isArray(n.members)?null:n}catch{return null}}function Di(e,t){try{let r=gh(`${t}/${e}/stat`,"utf8"),n=r.lastIndexOf(")");if(n===-1)return null;let o=r.slice(n+1).trim().split(/\s+/),s=Number(o[1]),i=Number(o[11]),a=Number(o[12]);return!Number.isFinite(s)||!Number.isFinite(i)||!Number.isFinite(a)?null:{ppid:s,utime:i,stime:a}}catch{return null}}function wh(e,t="/proc"){let r=Di(e,t);return r===null?null:r.utime+r.stime}function ph(e,t){try{let r=gh(`${t}/${e}/io`,"utf8"),n=r.match(/^rchar:\s*(\d+)/m),o=r.match(/^wchar:\s*(\d+)/m);if(!n||!o)return null;let s=Number(n[1]),i=Number(o[1]);return!Number.isFinite(s)||!Number.isFinite(i)?null:s+i}catch{return null}}function Nl(e,t="/proc"){let r=Di(e,t);if(r===null)return null;let n;try{n=hh(t)}catch{return r.utime+r.stime}let o=new Map,s=new Map;for(let l of n){if(!/^\d+$/.test(l))continue;let u=Number(l);if(u===e)continue;let d=Di(u,t);if(d===null)continue;s.set(u,d);let m=o.get(d.ppid);m?m.push(u):o.set(d.ppid,[u])}let i=r.utime+r.stime,a=[...o.get(e)??[]],c=new Set([e]);for(;a.length>0;){let l=a.shift();c.has(l)||(c.add(l),i+=s.get(l).utime+s.get(l).stime,a.push(...o.get(l)??[]))}return i}function yh(e,t="/proc"){let r=ph(e,t);if(r===null)return null;let n;try{n=hh(t)}catch{return r}let o=new Map;for(let c of n){if(!/^\d+$/.test(c))continue;let l=Number(c);if(l===e)continue;let u=Di(l,t);if(u===null)continue;let d=o.get(u.ppid);d?d.push(l):o.set(u.ppid,[l])}let s=r,i=[...o.get(e)??[]],a=new Set([e]);for(;i.length>0;){let c=i.shift();if(a.has(c))continue;a.add(c);let l=ph(c,t);l!==null&&(s+=l),i.push(...o.get(c)??[])}return s}function $R(e,t){if(e.state!=="busy")return null;if(e.inFlight!==null)return e.inFlight.holderPid!==null?{pid:e.inFlight.holderPid,startedAt:e.inFlight.startedAt}:null;if(e.terminalLock!==null)return e.terminalLock.holderHost!==t?null:{pid:e.terminalLock.holderPid,startedAt:e.terminalLock.startedAt};if(e.terminalInvocation!==null){let{holderPid:r,holderHost:n,startedAt:o}=e.terminalInvocation;return r===null||n!==t?null:{pid:r,startedAt:o}}return null}async function kR(e,t,r,n){let o=n.fetchHealthImpl??AR,s=n.readProcStatImpl??Nl,i=n.hostnameImpl??ER,a=n.wallClockThresholdMs??SR,c=n.requiredLowCpuStreak??vR,l=await o(r);if(l===null)return;let u=l.members.find(R=>R.alias===t.leadAlias);if(u===void 0)return;let d=$R(u.liveness,i());if(d===null){let R=se(e,t.name);(R?.holder_watch_pid!==null&&R?.holder_watch_pid!==void 0||R?.hung_holder_flagged_ts!==null&&R?.hung_holder_flagged_ts!==void 0)&&hc(e,t.name);return}let m=new Date().toISOString(),f=s(d.pid);if(f===null){pc(e,t.name,`${t.leadAlias}'s servicing lock has outlived its holder -- pid ${d.pid} (started ${d.startedAt}) is NOT RUNNING. Lock is leaked, not hung; nothing to kill, only the lock needs releasing.`,m);return}let p=se(e,t.name);if(!(p?.holder_watch_pid===d.pid&&p?.holder_watch_started_at===d.startedAt)){fc(e,t.name,d.pid,d.startedAt,f,m,0);return}let g=Date.now()-Date.parse(d.startedAt),_=p.holder_watch_cpu_ticks!==null?f-p.holder_watch_cpu_ticks:null,E=_!==null&&_<fh,y=p.holder_watch_low_cpu_streak??0,S=E?y+1:0;if(fc(e,t.name,d.pid,d.startedAt,f,m,S),g<a||S<c)return;let T=Math.round(g/6e4);pc(e,t.name,`${t.leadAlias} has held its servicing lock for ~${T}m with under ${fh/_h}s of CPU time across ${S} consecutive checks -- possibly hung, not just slow.`,m)}async function Eh(e,t,r={}){let n=r.existsSyncImpl??wR,o=r.statSyncImpl??yR,s=r.nowMs??Date.now();for(let i of t){if(!B(i))continue;if(r.sessionAliveExemptTeamName!==void 0&&i.name===r.sessionAliveExemptTeamName&&Bn(r.sessionAliveExemptPath,r.sessionAliveFreshnessMs,r.activityFreshnessMs!==void 0?se(e,i.name)?.last_cli_activity_ts??null:null,r.activityFreshnessMs,{existsSyncImpl:n,statSyncImpl:o,nowMs:s})){hc(e,i.name);continue}let a;try{a=Q(i)}catch{continue}try{await kR(e,i,a,r)}catch{continue}}}var Wo="provider_disabled:";function bh(e,t){try{let r=JSON.parse(t);return typeof r.disabledAt!="string"?null:{provider:e,disabledAt:r.disabledAt,reason:typeof r.reason=="string"?r.reason:null,expiresAt:typeof r.expiresAt=="string"?r.expiresAt:null}}catch{return null}}function Mi(e,t){let r=e.prepare("SELECT v FROM kv WHERE k = ?").get(Wo+t);return r===void 0?null:bh(t,r.v)}function Pi(e,t,r={}){let n={provider:t,disabledAt:r.nowIso??new Date().toISOString(),reason:r.reason??null,expiresAt:r.expiresAt??null};e.prepare("INSERT INTO kv(k, v) VALUES (?, ?) ON CONFLICT(k) DO UPDATE SET v = excluded.v").run(Wo+t,JSON.stringify(n))}function Th(e,t){e.prepare("DELETE FROM kv WHERE k = ?").run(Wo+t)}function Go(e){let t=e.prepare("SELECT k, v FROM kv WHERE k LIKE ?").all(`${Wo}%`),r=[];for(let n of t){let o=n.k.slice(Wo.length),s=bh(o,n.v);s!==null&&r.push(s)}return r}function it(e,t,r=Date.now()){let n;try{n=Mi(e,t)}catch{return{disabled:!0,config:null,failClosed:!0}}return n===null?{disabled:!1,config:null,failClosed:!1}:n.expiresAt!==null&&Date.parse(n.expiresAt)<=r?{disabled:!1,config:null,failClosed:!1}:{disabled:!0,config:n,failClosed:!1}}import{existsSync as xR,readFileSync as RR,readdirSync as NR,statSync as Sh}from"node:fs";import{basename as Ui}from"node:path";var Ll="orphan_would_reap",IR=5e3,LR=6e4,CR=100,OR=3,DR=45*6e4;function vh(e,t){try{let n=RR(`${e}/${t}/cmdline`,"utf8").split("\0").filter(a=>a.length>0),o=n.indexOf("chat");if(o<=0||o+1>=n.length)return null;let s=n[o-1]??"";if(!s.includes("lmctl")&&!s.includes("lctl"))return null;let i=n[o+1];return i.includes(".lmctl:")?i:null}catch{return null}}function Ah(e,t){try{return Sh(`${e}/${t}`).mtime.getTime()}catch{return null}}function Cl(e){let t;try{t=NR(e)}catch{return[]}let r=[];for(let n of t){if(!/^\d+$/.test(n))continue;let o=Number(n),s=vh(e,o);if(s===null)continue;let i=Ah(e,o);i!==null&&r.push({pid:o,target:s,startedAtMs:i})}return r.sort((n,o)=>n.pid-o.pid),r}function Il(e){let t=e.lastIndexOf(":");return t===-1?null:{teamfilePath:e.slice(0,t),alias:e.slice(t+1)}}function MR(e,t){if(t===null)return!1;let r=Il(e),n=Il(t);return r===null||n===null?!1:r.alias===n.alias&&Ui(r.teamfilePath)===Ui(n.teamfilePath)}function PR(e,t,r){return t.some(s=>s.pid!==e.pid&&s.target===e.target&&(s.startedAtMs>e.startedAtMs||s.startedAtMs===e.startedAtMs&&s.pid>e.pid))?{action:"reap",reason:`target "${e.target}" has a NEWER OS process for the same target -- this one is a leftover from a prior attempt`,requiresCpuCorroboration:!0}:r.running.find(s=>s.kind==="chat"&&MR(e.target,s.target))===void 0?{action:"reap",reason:`target "${e.target}" is not in lctl's own running (chat) bucket at all -- orphaned`,requiresCpuCorroboration:!0}:{action:"skip"}}function UR(e,t,r,n,o,s,i,a){let c=s(t.pid,a);if(c===null)return!1;let l=Mm(e,t.target,t.startedAtMs,t.pid);if(l===null||l.cpu_ticks===null)return gc(e,t.target,t.startedAtMs,t.pid,c,i,0),!1;let m=c-l.cpu_ticks<CR?l.low_cpu_streak+1:0;return gc(e,t.target,t.startedAtMs,t.pid,c,i,m),o-t.startedAtMs<n?!1:m>=r}function FR(e,t){let r=e.find(n=>n.name===t);if(r===void 0||!B(r))return null;try{return Q(r)}catch{return null}}function qR(e,t){let r=Il(t);if(r===null)return t;for(let n of e)if(B(n))try{let o=Q(n);if(Ui(o)===Ui(r.teamfilePath))return n.name}catch{continue}return t}async function jR(e,t,r,n,o){if(vh(e,t.pid)!==t.target||Ah(e,t.pid)!==t.startedAtMs)return!1;try{n(-t.pid,"SIGTERM")}catch{return!1}await o(r);try{n(-t.pid,0)}catch{return!0}try{n(-t.pid,"SIGKILL")}catch{}return!0}async function $h(e,t,r,n={}){let o=n.procPath??"/proc",s=n.safetyMarginMs??LR,i=n.sigkillGraceMs??IR,a=n.requiredLowCpuStreak??OR,c=n.minCorroborationWallClockMs??DR,l=n.existsSyncImpl??xR,u=n.statSyncImpl??Sh,d=n.killImpl??process.kill.bind(process),m=n.sleepImpl??(R=>new Promise(x=>setTimeout(x,R))),f=n.readProcCpuTicksImpl??wh,p=n.insertEventImpl??ot,h=n.dryRun??!1,g=n.nowMs??Date.now(),_=new Date(g).toISOString(),E=n.sessionAliveExemptTeamName!==void 0&&Bn(n.sessionAliveExemptPath,n.sessionAliveFreshnessMs,n.activityFreshnessMs!==void 0?se(e,n.sessionAliveExemptTeamName)?.last_cli_activity_ts??null:null,n.activityFreshnessMs,{existsSyncImpl:l,statSyncImpl:u,nowMs:g}),y=E?FR(t,n.sessionAliveExemptTeamName):null;E&&y===null&&process.stderr.write(`[orphan-reconciler] sessionAliveExemptTeamName "${n.sessionAliveExemptTeamName}" is configured and its session-alive file exists, but that team could not be resolved -- the exemption is NOT currently protecting it
|
|
197
|
+
`);let S;try{S=Cl(o)}catch{return}Pm(e,S.map(R=>({target:R.target,startedAtMs:R.startedAtMs,pid:R.pid})));let T=S.filter(R=>g-R.startedAtMs>=s);for(let R of S){if(g-R.startedAtMs<s)continue;if(y!==null){let I=R.target.lastIndexOf(":");if(R.target.slice(0,I)===y)continue}let x=PR(R,T,r);if(x.action!=="reap"){_c(e,R.target,R.startedAtMs,R.pid);continue}if(!(x.requiresCpuCorroboration&&!UR(e,R,a,c,g,f,_,o))){if(h){try{try{p(e,qR(t,R.target),Ll,g,{note:`pid ${R.pid} (${R.target}): ${x.reason}`})}catch{}n.onWouldReap?.({pid:R.pid,target:R.target,reason:x.reason}),process.stderr.write(`[orphan-reconciler] WOULD REAP pid ${R.pid} (${R.target}) [dry-run]: ${x.reason}
|
|
198
|
+
`)}catch{}continue}try{let I=await jR(o,R,i,d,m);if(_c(e,R.target,R.startedAtMs,R.pid),!I)continue;n.onReap?.({pid:R.pid,target:R.target,reason:x.reason}),process.stderr.write(`[orphan-reconciler] reaped pid ${R.pid} (${R.target}): ${x.reason}
|
|
199
|
+
`)}catch{continue}}}}import{existsSync as HR}from"node:fs";import{homedir as BR}from"node:os";import{join as WR}from"node:path";function GR(e){return e||(process.env.LCTL_STATE_DB?process.env.LCTL_STATE_DB:WR(BR(),".lmctl","state.db"))}function Wn(e){let t=GR(e);if(!HR(t))throw new Error(`lctl-src state db not found at ${t} -- set LCTL_STATE_DB or check the path`);return new yt(t,{readonly:!0,fileMustExist:!0})}function VR(e){return e==="done"?"done":e==="error"||e==="aborted"?"failed":e==="busy"||e==="running"||e==="cancelled"?"contention":null}function kh(e,t){let r=e.prepare("SELECT status, started_at, ended_at, meta FROM tracked_invocation WHERE kind = 'chat' AND started_at >= ? ORDER BY started_at ASC").all(t),n=[],o=0;for(let s of r){let i=VR(s.status);if(i===null){o++;continue}let a,c,l;try{let f=s.meta!==null?JSON.parse(s.meta):null;a=f?.provider,c=f?.model,l=f?.sessionid}catch{o++;continue}if(typeof a!="string"||a.length===0){o++;continue}let u=Date.parse(s.started_at),d=s.ended_at!==null?Date.parse(s.ended_at):NaN,m=s.ended_at!==null&&!Number.isNaN(u)&&!Number.isNaN(d)?d-u:null;n.push({provider:a,model:typeof c=="string"&&c.length>0?c:null,sessionid:typeof l=="string"&&l.length>0?l:null,outcome:i,startedAtIso:s.started_at,endedAtIso:s.ended_at,durationMs:m!==null&&m>=0?m:null})}return{rows:n,skippedUnattributable:o}}var JR=30*24*60*6e4;function zR(e,t,r){let n;try{n=e(t)}catch{return"unknown"}try{return n.prepare("SELECT status FROM tracked_invocation WHERE holder_pid = ? AND ended_at IS NOT NULL ORDER BY ended_at DESC LIMIT 1").get(r)?.status??"unknown"}catch{return"unknown"}finally{n.close()}}function xh(e,t={}){let r=t.procPath??"/proc",n=t.nowMs??Date.now(),o=new Date(n).toISOString(),s=t.retentionMs??JR,i=t.openLctlDbImpl??Wn,a;try{a=Cl(r)}catch{return}for(let u of a)try{let d=Nl(u.pid,r),m=yh(u.pid,r);Um(e,u.target,u.startedAtMs,u.pid,o,d,m)}catch{}let c=new Set(a.map(u=>`${u.target}\0${u.startedAtMs}\0${u.pid}`)),l;try{l=e.prepare(`SELECT DISTINCT o.target, o.started_at_ms, o.pid FROM hang_probe_observation o
|
|
200
|
+
WHERE NOT EXISTS (SELECT 1 FROM hang_probe_outcome h WHERE h.target = o.target AND h.started_at_ms = o.started_at_ms AND h.pid = o.pid)`).all()}catch{l=[]}for(let u of l)if(!c.has(`${u.target}\0${u.started_at_ms}\0${u.pid}`))try{let d=zR(i,t.lctlStateDbPath,u.pid);qm(e,u.target,u.started_at_ms,u.pid,d,o)}catch{}try{Fm(e,new Date(n-s).toISOString())}catch{}}import{createHash as KR}from"node:crypto";var YR=24*60*6e4,QR=200,XR=new Set(["all_good","needs_review"]),ZR=24*60*6e4;function eN(e,t){let r=e.prepare("SELECT * FROM entities WHERE parent_id = ?").all(t);if(r.length===0)return[];let n=r.map(()=>"?").join(","),o=e.prepare(`SELECT * FROM entities WHERE parent_id IN (${n})`).all(...r.map(s=>s.id));return[...r,...o]}function tN(e,t){return eN(e,t).map(r=>{let n=Cn(e,r.id),o=fi(e,r.id),i=n!==null&&o!==null&&n.created_at<o?null:n;return{id:r.id,title:r.title,status:r.status,latestNoteBody:i?.body??null,latestNoteId:i?.id??null}})}function rN(e,t){let r=JSON.stringify([e.status,e.title,e.description,t.map(n=>[n.id,n.status,n.latestNoteId])]);return KR("sha256").update(r,"utf8").digest("hex")}function nN(e,t){let r=t.length===0?"(no child tasks/subtasks yet)":t.map(n=>`#${n.id}: ${n.title} [${n.status}]${n.latestNoteBody?` -- latest note: ${n.latestNoteBody}`:""}`).join(`
|
|
201
201
|
`);return`You are reviewing whether a software project's epic is healthy or needs the meta-lead's attention.
|
|
202
202
|
|
|
203
203
|
Epic: ${e.title} [${e.status}]
|
|
@@ -216,10 +216,10 @@ Do NOT classify needs_review solely because an epic has no children yet, has few
|
|
|
216
216
|
"todo" with nothing else wrong -- incompleteness alone is never a red flag. Only flag a REAL problem among
|
|
217
217
|
whatever children currently exist (stalled/blocked, inconsistent, stuck).
|
|
218
218
|
|
|
219
|
-
Respond with EXACTLY one line of strict JSON, no other text before or after: {"label": "<all_good or needs_review>", "reason": "<short human-readable reason, under 200 characters>"}`}function
|
|
220
|
-
`)){if(n.length===0)continue;if(n===
|
|
221
|
-
${n.replace(/^ {2}/,"")}`);continue}let o=
|
|
222
|
-
${n}`:t.push({ts:null,role:"unknown",text:n})}}return{turns:t,truncated:r}}async function Fi(e,t,r={}){let n=r.spawnPrefix??["lmctl"],o=[...n.slice(1),"tail",e,t,"--lines",String(r.lines??40)];r.since&&o.push("--since",r.since);let s=n[0],i;try{({stdout:i}=await
|
|
219
|
+
Respond with EXACTLY one line of strict JSON, no other text before or after: {"label": "<all_good or needs_review>", "reason": "<short human-readable reason, under 200 characters>"}`}function oN(e){if(e===null)return null;let t;try{t=JSON.parse(e.trim())}catch{return null}if(typeof t!="object"||t===null)return null;let r=t;if(typeof r.label!="string"||!XR.has(r.label)||typeof r.reason!="string"||r.reason.trim().length===0)return null;let n=r.reason.replace(/\s+/g," ").trim();return n.length===0?null:{label:r.label,reason:n.slice(0,QR)}}async function sN(e,t,r,n){let o=n.decompositionGraceMs??ZR;if(r.length===0&&Date.now()-Date.parse(t.created_at)<o)return;let s=rN(t,r),i=n.cooldownMs??YR,a=t.review_input_hash!==s,c=!t.review_time||Date.now()-Date.parse(t.review_time)>=i;if(!(a||c))return;let l=await Ei(nN(t,r),{...n.spawnPrefix!==void 0?{spawnPrefix:n.spawnPrefix}:{},...n.timeoutMs!==void 0?{timeoutMs:n.timeoutMs}:{}}),u=oN(l);if(u===null)return;let d=new Date().toISOString();op(e,t.id,d,s,u.label==="needs_review"?{needsReview:!0,reason:u.reason}:{needsReview:!1})}async function Rh(e,t,r={}){for(let n of t){if(!B(n))continue;let o;try{o=Q(n)}catch{continue}let s=Re(e,o,n.leadAlias);if(s!==null)for(let i of s.entities.filter(yi)){let a=tN(e,i.id);try{await sN(e,i,a,r)}catch{continue}}}}import{createHash as dN}from"node:crypto";import{execFile as iN}from"node:child_process";import{promisify as aN}from"node:util";var Nh=aN(iN),cN=/^(?:(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) )?([A-Za-z0-9_]+): (.*)$/,lN="\u2026 [truncated older output \u2014 raise with --max-bytes]";function uN(e){let t=[],r=!1;for(let n of e.split(`
|
|
220
|
+
`)){if(n.length===0)continue;if(n===lN){r=!0;continue}if(/^\s/.test(n)){let s=t[t.length-1];s&&(s.text+=`
|
|
221
|
+
${n.replace(/^ {2}/,"")}`);continue}let o=cN.exec(n);if(o)t.push({ts:o[1]??null,role:o[2],text:o[3]});else{let s=t[t.length-1];s?s.text+=`
|
|
222
|
+
${n}`:t.push({ts:null,role:"unknown",text:n})}}return{turns:t,truncated:r}}async function Fi(e,t,r={}){let n=r.spawnPrefix??["lmctl"],o=[...n.slice(1),"tail",e,t,"--lines",String(r.lines??40)];r.since&&o.push("--since",r.since);let s=n[0],i;try{({stdout:i}=await Nh(s,o,{timeout:r.timeoutMs??3e4,maxBuffer:16*1024*1024}))}catch(a){let c=a.stderr;throw typeof c=="string"&&c.trim().length>0?new Error(`lmctl tail: ${c.trim()}`):a}return uN(i)}async function qi(e,t,r={}){let n=r.spawnPrefix??["lmctl"],o=[...n.slice(1),"tail",e,t,"--json","--lines",String(r.lines??40)];r.since&&o.push("--since",r.since);let s=n[0],i;try{({stdout:i}=await Nh(s,o,{timeout:r.timeoutMs??3e4,maxBuffer:16*1024*1024}))}catch(a){let c=a.stderr;throw typeof c=="string"&&c.trim().length>0?new Error(`lmctl tail: ${c.trim()}`):a}return JSON.parse(i)}var mN=200,fN=new Set(["genuinely_done","blocked","stalled_needs_nudge","produced_output_no_report"]),pN=2*60*6e4;function hN(e,t,r){let n=Re(e,t,r);return n===null?[]:n.entities.filter(o=>!zc(o.status)).map(o=>({id:o.id,title:o.title,status:o.status}))}function gN(e,t,r,n){let o=Re(e,t,r);return o===null?[]:o.entities.filter(s=>(s.kind==="task"||s.kind==="subtask")&&Xc(s,n)).map(s=>({id:s.id,title:s.title,holdUntil:s.hold_until}))}function Ih(e,t,r=null,n=[]){let o=dN("sha256").update(`${Buffer.byteLength(e,"utf8")}:`,"utf8").update(e,"utf8");for(let i of t)o.update(`\0${i.id}:${i.status}`,"utf8");r!==null&&(r.progress_status!==null||r.progress_changed_ts!==null)&&o.update(`\0progress:${r.progress_status??""}:${r.progress_changed_ts??""}`,"utf8");for(let i of n)o.update(`\0held:${i.id}:${i.holdUntil}`,"utf8");return o.digest("hex")}function _N(e,t,r,n,o=[]){let s=r.length===0?"(none -- this team has no non-terminal tasks in the tracker right now)":r.map(l=>`#${l.id}: ${l.title} [${l.status}]`).join(`
|
|
223
223
|
`),i=n===null||n.progress_status===null?"no scan yet -- no independent evidence available":`${n.progress_status}${n.progress_changed_ts?`, last changed ${n.progress_changed_ts}`:""}`,a=o.length===0?null:o.map(l=>`#${l.id}: ${l.title}, held until ${l.holdUntil}`).join(`
|
|
224
224
|
`),c=a===null?"":`
|
|
225
225
|
This team currently has task(s) DELIBERATELY HELD until a future time (this is a scheduled
|
|
@@ -255,23 +255,23 @@ If the file-scan progress signal says ACTIVE with a recent change, treat that as
|
|
|
255
255
|
evidence of recent execution even if the transcript alone reads as stalled or dead -- the transcript
|
|
256
256
|
may belong to a member who did none of the actual work.
|
|
257
257
|
|
|
258
|
-
Respond with EXACTLY one line of strict JSON, no other text before or after: {"label": "<one of the four exact labels above>", "reason": "<short human-readable reason, under 200 characters>"}`}function
|
|
259
|
-
`),i=
|
|
260
|
-
WHERE conversation_id = ? AND generation = ? AND job_id = ? AND phase = 'reserved' AND receipt_path = ?`).run(r,new Date().toISOString(),n.conversationId,n.generation,t,n.receiptPath).changes!==1)throw new Error("On-demand generation no longer owns this dispatch")}function
|
|
261
|
-
AND job_id = ? AND run_id = ? AND phase = 'dispatching'`).get(n.conversationId,n.generation,t,r)!==void 0}var P=class extends Error{code;exitCode;constructor(t,r,n=2){super(r),this.code=t,this.exitCode=n}};function Dl(e){let t;try{if(typeof e!="string")throw new Error("expected a cron expression string");let r=e.trim().split(/\s+/);if(r.length!==5)throw new Error("expected five fields: minute hour day-of-month month day-of-week");t="minute";let n=Jo(r[0],0,59);t="hour";let o=Jo(r[1],0,23);t="dayOfMonth";let s=Jo(r[2],1,31);t="month";let i=Jo(r[3],1,12);t="dayOfWeek";let a=Jo(r[4],0,7,l=>l===7?0:l);return{ok:!0,schedule:{__brand:"CronSchedule",minute:n,hour:o,dayOfMonth:s,month:i,dayOfWeek:a}}}catch(r){let n=r instanceof Error?r.message:String(r);return{ok:!1,error:t?{message:n,field:t}:{message:n}}}}function Jo(e,t,r,n=o=>o){if(e.length===0)throw new Error("empty field");let o=new Set;for(let s of e.split(",")){if(s.length===0)throw new Error(`invalid list in "${e}"`);let i=s.split("/");if(i.length>2)throw new Error(`invalid step in "${s}"`);let a=i[0],c=i[1]===void 0?1:Ol(i[1],1,r-t+1,s),l=a.split("-");if(l.length>2)throw new Error(`invalid range in "${s}"`);let u=a==="*"?t:Ol(l[0],t,r,s),d=a==="*"?r:l[1]!==void 0?Ol(l[1],t,r,s):i[1]?r:u;if(u>d)throw new Error(`range starts after it ends in "${s}"`);for(let m=u;m<=d;m+=c)o.add(n(m))}return{values:o,wildcard:e.split(",").some(s=>s.split("/")[0]==="*")}}function Ol(e,t,r,n){if(!/^\d+$/.test(e))throw new Error(`expected an integer in "${n}"`);let o=Number(e);if(!Number.isSafeInteger(o)||o<t||o>r)throw new Error(`value ${e} is outside ${t}-${r}`);return o}function
|
|
262
|
-
`)},d??
|
|
263
|
-
`),p(null,h)}),c.on("exit",h=>{p(h)})}import{createHash as
|
|
264
|
-
VALUES (?, ?, 'pending', 'active', ?, ?, ?, ?)`).run(t,
|
|
265
|
-
WHERE id = ? AND status = 'pending'`).run(JSON.stringify(r),n,me(),me(),t))}function es(e,t,r,n){e.prepare("UPDATE cron_runs SET execution_identity = ?, pid = ?, updated_at = ? WHERE id = ?").run(JSON.stringify(r),n,me(),t)}function
|
|
258
|
+
Respond with EXACTLY one line of strict JSON, no other text before or after: {"label": "<one of the four exact labels above>", "reason": "<short human-readable reason, under 200 characters>"}`}function wN(e){if(e===null)return null;let t;try{t=JSON.parse(e.trim())}catch{return null}if(typeof t!="object"||t===null)return null;let r=t;if(typeof r.label!="string"||!fN.has(r.label)||typeof r.reason!="string"||r.reason.trim().length===0)return null;let n=r.reason.replace(/\s+/g," ").trim();return n.length===0?null:{label:r.label,reason:n.slice(0,mN)}}function yN(e){if(e.length===1){let[t]=e;return`holding for #${t.id} ("${t.title}") until ${t.holdUntil} -- deliberately scheduled, not stalled`}return`holding for ${e.length} task(s), until ${e.map(t=>t.holdUntil).join(", ")} -- deliberately scheduled, not stalled`}async function EN(e,t,r,n){let o=n.fetchTailJsonImpl??qi,s,i,a;try{s=(await o(r,t.leadAlias,{lines:20})).messages.map(y=>`${y.role}: ${typeof y.content=="string"?y.content:JSON.stringify(y.content)}`).join(`
|
|
259
|
+
`),i=hN(e,r,t.leadAlias),a=gN(e,r,t.leadAlias,Date.now())}catch{return}let c=se(e,t.name),l=Ih(s,i,c,a),u=Ih("",i,c,a),d=n.cooldownMs??pN,m=c?.miniplayer_verdict_input_hash!==l,f=c?.miniplayer_verdict_structural_hash!==u,p=!c?.miniplayer_verdict_ts||Date.now()-Date.parse(c.miniplayer_verdict_ts)>=d;if(!(f||m&&p))return;let h=await Ei(_N(t.name,s,i,c,a),{...n.spawnPrefix!==void 0?{spawnPrefix:n.spawnPrefix}:{},...n.timeoutMs!==void 0?{timeoutMs:n.timeoutMs}:{}}),g=wN(h);if(g===null)return;let _=g.label==="stalled_needs_nudge"&&a.length>0&&i.length===0?{label:"blocked",reason:yN(a)}:g;$m(e,t.name,_.label,_.reason,new Date().toISOString(),l,u)}async function Lh(e,t,r,n={}){for(let o of t){let s=r.find(a=>a.name===o);if(s===void 0||!B(s))continue;let i;try{i=Q(s)}catch{continue}try{await EN(e,s,i,n)}catch{continue}}}import{execFileSync as gI}from"node:child_process";function Xt(e,t){let r=Number(e.pragma("busy_timeout",{simple:!0}));e.pragma("busy_timeout = 0");try{return t()}finally{e.pragma(`busy_timeout = ${r}`)}}function Vo(e,t){return e.prepare("SELECT 1 FROM on_demand_launches WHERE job_id = ?").get(t)!==void 0}function Ch(e,t,r,n){if(e.prepare(`UPDATE on_demand_launches SET phase = 'dispatching', run_id = ?, updated_at = ?
|
|
260
|
+
WHERE conversation_id = ? AND generation = ? AND job_id = ? AND phase = 'reserved' AND receipt_path = ?`).run(r,new Date().toISOString(),n.conversationId,n.generation,t,n.receiptPath).changes!==1)throw new Error("On-demand generation no longer owns this dispatch")}function Oh(e,t,r,n){return e.prepare(`SELECT 1 FROM on_demand_launches WHERE conversation_id = ? AND generation = ?
|
|
261
|
+
AND job_id = ? AND run_id = ? AND phase = 'dispatching'`).get(n.conversationId,n.generation,t,r)!==void 0}var P=class extends Error{code;exitCode;constructor(t,r,n=2){super(r),this.code=t,this.exitCode=n}};function Dl(e){let t;try{if(typeof e!="string")throw new Error("expected a cron expression string");let r=e.trim().split(/\s+/);if(r.length!==5)throw new Error("expected five fields: minute hour day-of-month month day-of-week");t="minute";let n=Jo(r[0],0,59);t="hour";let o=Jo(r[1],0,23);t="dayOfMonth";let s=Jo(r[2],1,31);t="month";let i=Jo(r[3],1,12);t="dayOfWeek";let a=Jo(r[4],0,7,l=>l===7?0:l);return{ok:!0,schedule:{__brand:"CronSchedule",minute:n,hour:o,dayOfMonth:s,month:i,dayOfWeek:a}}}catch(r){let n=r instanceof Error?r.message:String(r);return{ok:!1,error:t?{message:n,field:t}:{message:n}}}}function Jo(e,t,r,n=o=>o){if(e.length===0)throw new Error("empty field");let o=new Set;for(let s of e.split(",")){if(s.length===0)throw new Error(`invalid list in "${e}"`);let i=s.split("/");if(i.length>2)throw new Error(`invalid step in "${s}"`);let a=i[0],c=i[1]===void 0?1:Ol(i[1],1,r-t+1,s),l=a.split("-");if(l.length>2)throw new Error(`invalid range in "${s}"`);let u=a==="*"?t:Ol(l[0],t,r,s),d=a==="*"?r:l[1]!==void 0?Ol(l[1],t,r,s):i[1]?r:u;if(u>d)throw new Error(`range starts after it ends in "${s}"`);for(let m=u;m<=d;m+=c)o.add(n(m))}return{values:o,wildcard:e.split(",").some(s=>s.split("/")[0]==="*")}}function Ol(e,t,r,n){if(!/^\d+$/.test(e))throw new Error(`expected an integer in "${n}"`);let o=Number(e);if(!Number.isSafeInteger(o)||o<t||o>r)throw new Error(`value ${e} is outside ${t}-${r}`);return o}function bN(e,t){let r=e;if(!r.minute.values.has(t.getMinutes())||!r.hour.values.has(t.getHours())||!r.month.values.has(t.getMonth()+1))return!1;let n=r.dayOfMonth.values.has(t.getDate()),o=r.dayOfWeek.values.has(t.getDay());return r.dayOfMonth.wildcard?o:r.dayOfWeek.wildcard?n:n||o}function Dh(e,t,r){let n=t.getTime(),o=r.getTime();if(o<n)throw new RangeError("untilInclusive must not precede sinceExclusive");for(let s=(Math.floor(n/6e4)+1)*6e4;s<=o;s+=6e4)if(bN(e,new Date(s)))return!0;return!1}import{spawn as TN}from"node:child_process";import{closeSync as SN,existsSync as vN,mkdirSync as AN,openSync as $N,readdirSync as kN,unlinkSync as xN}from"node:fs";import{homedir as RN}from"node:os";import{join as ji}from"node:path";var Mh=["systemd-run","--user","--scope","--collect","--quiet"],NN=10,Ph=50*6e4,IN=5e3;function Hi(){return process.env.LMBEE_CRON_LOG_DIR?process.env.LMBEE_CRON_LOG_DIR:ji(RN(),".lmbee","cron-logs")}function LN(e,t){try{let r=kN(e).sort();for(let n of r.slice(0,Math.max(0,r.length-t)))try{xN(ji(e,n))}catch{}}catch{}}function CN(e,t){return[...t.spawnPrefix??(t.systemdUnitName!==void 0?[...Mh,"--unit",t.systemdUnitName,"--"]:[...Mh,"--"]),"sh","-c",e]}function zo(e,t={}){let r=ji(t.logDir??Hi(),String(e.id));vN(r)||AN(r,{recursive:!0});let n=ji(r,`${new Date().toISOString().replace(/[:.]/g,"-")}.log`),o=$N(n,"a"),s=CN(e.action_payload,t),[i,...a]=s,c;try{c=TN(i,a,{detached:!0,stdio:["ignore",o,o],...t.cwd!==void 0?{cwd:t.cwd}:{},...t.env!==void 0?{env:t.env}:{}})}finally{SN(o)}c.unref();let l=c.pid??null,u=!1,d=t.timeoutMs===void 0?Ph:t.timeoutMs,m=t.sigkillGraceMs??IN,f=d===null?void 0:setTimeout(()=>{if(u)return;let h=c.pid;if(h!==void 0){try{process.kill(-h,"SIGTERM")}catch{}setTimeout(()=>{try{process.kill(-h,0)}catch{return}try{process.kill(-h,"SIGKILL")}catch{}},m).unref()}process.stderr.write(`[lmcron] job ${e.id} timed out after ${d}ms, sending SIGTERM
|
|
262
|
+
`)},d??Ph);f?.unref();let p=(h,g)=>{u||(u=!0,f!==void 0&&clearTimeout(f),LN(r,NN),t.onExit?.(h,g,l,n))};c.on("error",h=>{process.stderr.write(`[lmcron] job ${e.id} spawn error: ${h.message}
|
|
263
|
+
`),p(null,h)}),c.on("exit",h=>{p(h)})}import{createHash as ON,randomUUID as DN}from"node:crypto";var mn=16*1024,Yo=16*1024,Ml=512,Bi=100,Pl=4096,Ul=1024*1024,Qo="('pending','running')",MN="execution_state != 'gone' OR (status = 'escalated' AND escalation_resolved_at IS NULL)";function Xo(e){let{run_token_hash:t,...r}=e;return r}function Uh(e){return ON("sha256").update(e,"utf8").digest("hex")}function kt(e){try{return e()}catch(t){if(t instanceof P)throw t;if(t instanceof C)throw new P(t.code,t.message,t.exitCode);let r=t&&typeof t=="object"&&"code"in t?String(t.code):void 0,n=t instanceof Error?t.message:String(t);throw r!==void 0&&(r.startsWith("SQLITE_BUSY")||r.startsWith("SQLITE_LOCKED"))?new P("DB_BUSY","Database busy; retry after the current writer completes",5):r!==void 0&&r.startsWith("SQLITE_CONSTRAINT")?new P("STRUCTURAL_ERROR",n,2):new P("STORAGE_ERROR",n,1)}}function Fh(e,t){return kt(()=>e.prepare("SELECT * FROM cron_runs WHERE id = ?").get(t)??null)}function Be(e,t){let r=Fh(e,t);if(r===null)throw new P("NOT_FOUND",`Cron run ${t} does not exist`,3);return r}function PN(e,t){return e.prepare("SELECT * FROM cron_runs WHERE run_token_hash = ?").get(t)??null}function It(e,t){return kt(()=>e.prepare(`SELECT * FROM cron_runs WHERE job_id = ? AND (${MN}) ORDER BY id DESC LIMIT 1`).get(t)??null)}function Zo(e,t,r,n){return kt(()=>{let o=It(e,t);if(o!==null)return o.status==="escalated"?{kind:"escalation",run:o}:{kind:"overlap",run:o};let s=DN(),i=me();try{let a=e.prepare(`INSERT INTO cron_runs(job_id, run_token_hash, status, execution_state, trigger_kind, config_snapshot, created_at, updated_at)
|
|
264
|
+
VALUES (?, ?, 'pending', 'active', ?, ?, ?, ?)`).run(t,Uh(s),r,n,i,i);return{kind:"claimed",run:Be(e,Number(a.lastInsertRowid)),token:s}}catch(a){let c=a&&typeof a=="object"&&"code"in a?String(a.code):void 0;if(c!==void 0&&c.startsWith("SQLITE_CONSTRAINT")){let l=It(e,t);if(l!==null)return l.status==="escalated"?{kind:"escalation",run:l}:{kind:"overlap",run:l}}throw a}})}function Gn(e,t,r,n){kt(()=>e.prepare(`UPDATE cron_runs SET status = 'running', execution_identity = ?, pid = ?, started_at = ?, updated_at = ?
|
|
265
|
+
WHERE id = ? AND status = 'pending'`).run(JSON.stringify(r),n,me(),me(),t))}function es(e,t,r,n){e.prepare("UPDATE cron_runs SET execution_identity = ?, pid = ?, updated_at = ? WHERE id = ?").run(JSON.stringify(r),n,me(),t)}function UN(e,t){kt(()=>e.prepare(`UPDATE cron_runs SET execution_state = 'gone', execution_gone_at = ?, execution_uncertain_reason = NULL, updated_at = ?
|
|
266
266
|
WHERE id = ? AND execution_state != 'gone'`).run(me(),me(),t))}function ts(e,t,r){kt(()=>e.prepare(`UPDATE cron_runs SET execution_state = 'uncertain', execution_uncertain_reason = ?, updated_at = ?
|
|
267
|
-
WHERE id = ? AND execution_state != 'gone'`).run(r.slice(0,1024),me(),t))}function
|
|
267
|
+
WHERE id = ? AND execution_state != 'gone'`).run(r.slice(0,1024),me(),t))}function Ko(e,t,r){let n=Ee(e,t);if(Buffer.byteLength(n,"utf8")>r)throw new P("INVALID_ARGUMENT",`${t} exceeds ${r} bytes`);return n}function FN(e){if(e===void 0)return[];if(!Array.isArray(e))throw new P("INVALID_ARGUMENT","artifacts must be an array");if(e.length>Bi)throw new P("INVALID_ARGUMENT",`at most ${Bi} artifacts are allowed`);return e.map(t=>{if(typeof t!="string")throw new P("INVALID_ARGUMENT","artifacts must be strings");return Ko(t,"artifact",Pl)})}function qh(e,t){if(e.status!=="succeeded"&&e.status!=="failed"&&e.status!=="escalated")throw new P("INVALID_ARGUMENT",'status must be "succeeded", "failed", or "escalated"');let r=Ko(e.summary,"summary",mn),n=FN(e.artifacts),o=null,s=null,i=null;if(e.status==="escalated"){o=Ko(e.action??"","requested action",Yo),i=e.reason!==void 0?Ko(e.reason,"escalation reason",Yo):r;let a=e.owner!==void 0?Ko(e.owner,"owner",Ml):t;if(a===null||a.trim().length===0)throw new P("INVALID_ARGUMENT","an escalation requires an owner or a job with a configured default escalation owner");s=a}return{status:e.status,summary:r,artifacts:JSON.stringify(n),escalationAction:o,escalationOwner:s,escalationReason:i}}function jh(e,t){return e.status===t.status&&e.summary===t.summary&&e.artifacts===t.artifacts&&e.escalation_action===t.escalationAction&&e.escalation_owner===t.escalationOwner&&e.escalation_reason===t.escalationReason}function Hh(e){try{let t=JSON.parse(e.config_snapshot);return typeof t.escalationOwner=="string"&&t.escalationOwner.trim().length>0?t.escalationOwner:null}catch{return null}}function Fl(e,t,r){let n=qh(r,Hh(t)),o=me();if(e.prepare(`UPDATE cron_runs SET status = ?, summary = ?, artifacts = ?, escalation_reason = ?, escalation_action = ?,
|
|
268
268
|
escalation_owner = ?, reported_at = ?, finished_at = ?, updated_at = ?
|
|
269
|
-
WHERE id = ? AND status IN ${Qo} AND reported_at IS NULL`).run(n.status,n.summary,n.artifacts,n.escalationReason,n.escalationAction,n.escalationOwner,o,o,o,t.id).changes===0){let i=Be(e,t.id);if(
|
|
269
|
+
WHERE id = ? AND status IN ${Qo} AND reported_at IS NULL`).run(n.status,n.summary,n.artifacts,n.escalationReason,n.escalationAction,n.escalationOwner,o,o,o,t.id).changes===0){let i=Be(e,t.id);if(jh(i,n))return i;throw new P("CONFLICTING_REPORT",`Cron run ${t.id} already has a different terminal report`,4)}return Be(e,t.id)}function Bh(e,t,r){return kt(()=>{let n=PN(e,Uh(t));if(n===null)throw new P("NOT_FOUND","No cron run matches the supplied report token",3);if(n.reported_at!==null||n.status!=="pending"&&n.status!=="running"){let o=qh(r,Hh(n));if(jh(n,o))return n;throw new P("CONFLICTING_REPORT",`Cron run ${n.id} already has a different terminal report`,4)}return Fl(e,n,r)})}function pr(e,t,r){let n=e.transaction(()=>{let o=Be(e,t);o.reported_at===null&&(o.status==="pending"||o.status==="running")&&r.report!==void 0&&Fl(e,o,r.report);let s=Be(e,t);if(s.reported_at===null&&(s.status==="pending"||s.status==="running")&&r.fallback!==void 0){let i=r.fallback.ok?"succeeded":"failed";e.prepare(`UPDATE cron_runs SET status = ?, summary = ?, finished_at = ?, updated_at = ? WHERE id = ? AND status IN ${Qo} AND reported_at IS NULL`).run(i,r.fallback.summary.slice(0,mn),me(),me(),t)}return UN(e,t),Be(e,t)});return kt(()=>n.immediate())}function Wh(e,t,r){let n=e.transaction(()=>{let o=Be(e,t);o.reported_at===null&&(o.status==="pending"||o.status==="running")&&r.report!==void 0&&Fl(e,o,r.report);let s=Be(e,t);if(s.reported_at===null&&(s.status==="pending"||s.status==="running")&&r.fallback!==void 0){let i=r.fallback.ok?"succeeded":"failed";e.prepare(`UPDATE cron_runs SET status = ?, summary = ?, finished_at = ?, updated_at = ? WHERE id = ? AND status IN ${Qo} AND reported_at IS NULL`).run(i,r.fallback.summary.slice(0,mn),me(),me(),t)}return Be(e,t)});return kt(()=>n.immediate())}function ql(e,t,r){return kt(()=>{let n=Fh(e,t);if(n===null)return null;if(n.reported_at!==null||n.status!=="pending"&&n.status!=="running")return n;let o=r.ok?"succeeded":"failed";return e.prepare(`UPDATE cron_runs SET status = ?, summary = ?, finished_at = ?, updated_at = ? WHERE id = ? AND status IN ${Qo} AND reported_at IS NULL`).run(o,r.summary.slice(0,mn),me(),me(),n.id),Be(e,n.id)})}function Gh(e,t,r={}){let n=e.transaction(()=>{let o=Be(e,t),s=r.resolution!==void 0?r.resolution.trim():"",i=r.actor!==void 0?r.actor.trim():"",a=r.note!==void 0?r.note.trim():"",c=!1;if(o.execution_state!=="gone"){if(r.confirmStopped!==!0)throw new P("EXECUTION_FENCED",`Cron run ${t} execution state is "${o.execution_state}"; verify the process is gone and retry with --confirm-stopped`,4);e.prepare(`UPDATE cron_runs SET execution_state = 'gone', execution_gone_at = ?, execution_uncertain_reason = NULL,
|
|
270
270
|
execution_confirmation_note = ?, updated_at = ? WHERE id = ? AND execution_state != 'gone'`).run(me(),a||s||"confirmed stopped by operator",me(),t),c=!0}o.status==="escalated"&&o.escalation_resolved_at===null&&(e.prepare(`UPDATE cron_runs SET escalation_resolved_at = ?, escalation_resolution = ?, escalation_resolution_actor = ?,
|
|
271
271
|
escalation_resolution_note = ?, updated_at = ? WHERE id = ? AND escalation_resolved_at IS NULL`).run(me(),s||"resolved",i||"operator",a||s||"resolved",me(),t),c=!0);let l=Be(e,t);if(l.reported_at===null&&(l.status==="pending"||l.status==="running")&&(e.prepare(`UPDATE cron_runs SET status = 'failed', summary = ?, finished_at = ?, updated_at = ?
|
|
272
|
-
WHERE id = ? AND status IN ${Qo} AND reported_at IS NULL`).run(`reconciled by operator without a worker report: ${a||s||"execution confirmed stopped"}`.slice(0,mn),me(),me(),t),c=!0),!c)throw new P("INVALID_ARGUMENT",`Cron run ${t} has no fenced execution or unresolved escalation to resolve`);let u=me();return e.prepare("UPDATE cron_jobs SET last_checked_ts = ?, updated_at = ? WHERE id = ? AND (last_checked_ts IS NULL OR last_checked_ts < ?)").run(u,u,o.job_id,u),Be(e,t)});return kt(()=>n.immediate())}function Wi(e,t){if(!Number.isSafeInteger(t.limit)||t.limit<1||t.limit>Le)throw new P("INVALID_ARGUMENT",`limit must be a positive integer <= ${Le}`);return kt(()=>{let r=["id > ?"],n=[t.after];t.jobId!==void 0&&(r.push("job_id = ?"),n.push(t.jobId)),t.status!==void 0&&(r.push("status = ?"),n.push(t.status));let o=e.prepare(`SELECT * FROM cron_runs WHERE ${r.join(" AND ")} ORDER BY id LIMIT ?`).all(...n,t.limit+1),s=o.length>t.limit,i=s?o.slice(0,t.limit):o;return{rows:i,next_cursor:s?i[i.length-1].id:null}})}import{spawn as jl}from"node:child_process";import{fileURLToPath as
|
|
273
|
-
`),!1}}function bt(e,t,r,n){
|
|
274
|
-
`)}}function Hl(e,t,r){if(e===null)throw new Error(`${r}: disabling timeout is supported only for script workers`);let n=e??t;if(!Number.isFinite(n)||n<=0||n>
|
|
272
|
+
WHERE id = ? AND status IN ${Qo} AND reported_at IS NULL`).run(`reconciled by operator without a worker report: ${a||s||"execution confirmed stopped"}`.slice(0,mn),me(),me(),t),c=!0),!c)throw new P("INVALID_ARGUMENT",`Cron run ${t} has no fenced execution or unresolved escalation to resolve`);let u=me();return e.prepare("UPDATE cron_jobs SET last_checked_ts = ?, updated_at = ? WHERE id = ? AND (last_checked_ts IS NULL OR last_checked_ts < ?)").run(u,u,o.job_id,u),Be(e,t)});return kt(()=>n.immediate())}function Wi(e,t){if(!Number.isSafeInteger(t.limit)||t.limit<1||t.limit>Le)throw new P("INVALID_ARGUMENT",`limit must be a positive integer <= ${Le}`);return kt(()=>{let r=["id > ?"],n=[t.after];t.jobId!==void 0&&(r.push("job_id = ?"),n.push(t.jobId)),t.status!==void 0&&(r.push("status = ?"),n.push(t.status));let o=e.prepare(`SELECT * FROM cron_runs WHERE ${r.join(" AND ")} ORDER BY id LIMIT ?`).all(...n,t.limit+1),s=o.length>t.limit,i=s?o.slice(0,t.limit):o;return{rows:i,next_cursor:s?i[i.length-1].id:null}})}import{spawn as jl}from"node:child_process";import{fileURLToPath as qN}from"node:url";import{createHash as jN}from"node:crypto";import{existsSync as HN,mkdirSync as BN,mkdtempSync as WN,readFileSync as GN,rmSync as Vh,writeFileSync as Qh}from"node:fs";import{homedir as VN,tmpdir as JN}from"node:os";import{isAbsolute as zN,join as os,resolve as fn}from"node:path";var KN=["lmctl"],YN=["miniplayer"],QN=10*6e4,XN=50*6e4,ZN=50*6e4,Jh=24*60*6e4,Xh=5e3,Gi=1024*1024;function rs(){return{text:"",overflow:!1}}function ns(e,t){if(e.overflow)return;let r=e.text+t.toString("utf8");r.length>Gi?(e.text=r.slice(0,Gi),e.overflow=!0):e.text=r}function Xe(e){return e instanceof Error?e.message:String(e)}function eI(e,t,r){try{ts(e,t,r)}catch{}}function Ve(e,t,r){try{return pr(e,t,r),!0}catch(n){return process.stderr.write(`[lmcron] run ${t} completion could not be committed (fence retained): ${Xe(n)}
|
|
273
|
+
`),!1}}function bt(e,t,r,n){eI(e,t,r);try{Wh(e,t,n)}catch(o){process.stderr.write(`[lmcron] run ${t} outcome could not be persisted (fence retained): ${Xe(o)}
|
|
274
|
+
`)}}function Hl(e,t,r){if(e===null)throw new Error(`${r}: disabling timeout is supported only for script workers`);let n=e??t;if(!Number.isFinite(n)||n<=0||n>Jh)throw new Error(`${r} must be a positive number of milliseconds <= ${Jh}`);return n}var zh=new Set(["claude","codex","opencode","lmplayer","gemini","copilot","qwen","agy","kimi","dsh","hermes","ClaudeMock"]),tI=/^[A-Za-z0-9][A-Za-z0-9._:@/+~-]*$/;function Wl(e){if(!zh.has(e))throw new P("INVALID_ARGUMENT",`provider "${e}" is not one of lmctl's supported providers (${[...zh].join(", ")})`);return e}function Gl(e){if(!tI.test(e))throw new P("INVALID_ARGUMENT",`model "${e}" is not a safe lmctl model token (no whitespace, quotes, '=' or control characters)`);return e}function Vi(e){if(!zN(e))throw new P("INVALID_ARGUMENT",`sessiondir "${e}" must be an absolute path`);if(/["\u0000-\u001f\u007f]/.test(e))throw new P("INVALID_ARGUMENT",`sessiondir contains a quote, newline, or control character that lmctl cannot represent: ${JSON.stringify(e)}`);return e}function rI(e){let t=["_MEMBER_",`alias=${e.alias}`,`provider=${Wl(e.provider)}`];return e.model!==null&&e.model!==void 0&&t.push(`model=${Gl(e.model)}`),t.push(`sessiondir="${Vi(e.sessiondir)}"`),t.join(" ")}function nI(e){let t=e.name,r=t!==void 0&&t.length>0?fn(t):":memory:";return jN("sha256").update(r,"utf8").digest("hex").slice(0,16)}function oI(){return process.env.LMBEE_CRON_SESSION_DIR?process.env.LMBEE_CRON_SESSION_DIR:os(VN(),".lmbee","cron-sessions")}function sI(e){return`'${e.replace(/'/g,"'\\''")}'`}function iI(e){let t=e.name;return t!==void 0&&t.length>0&&t!==":memory:"?`LMBEE_DB=${sI(fn(t))} `:""}function aI(e,t,r){let n=iI(r);return`${e}
|
|
275
275
|
|
|
276
276
|
---
|
|
277
277
|
When you have finished, report the outcome exactly once by running this command (the token is
|
|
@@ -281,7 +281,7 @@ run-specific; do not change it):
|
|
|
281
281
|
|
|
282
282
|
Use --status failed if the work did not succeed, or --status escalated together with
|
|
283
283
|
--requested-action "requested operator action" and optionally --owner NAME if a human decision is
|
|
284
|
-
required. Never report succeeded unless the work actually succeeded.`}function
|
|
284
|
+
required. Never report succeeded unless the work actually succeeded.`}function cI(e,t){return`${e}
|
|
285
285
|
|
|
286
286
|
---
|
|
287
287
|
Respond with EXACTLY one line of strict JSON and no other text, using this run token verbatim:
|
|
@@ -290,41 +290,41 @@ Respond with EXACTLY one line of strict JSON and no other text, using this run t
|
|
|
290
290
|
|
|
291
291
|
For an escalation use {"run_token":"...","status":"escalated","summary":"...","escalation":{"owner":"...","reason":"...","requestedAction":"..."}}.
|
|
292
292
|
Escalation reason and requestedAction are required. Never claim succeeded unless the work actually
|
|
293
|
-
succeeded.`}var
|
|
293
|
+
succeeded.`}var lI=new Set(["run_token","status","summary","artifacts","escalation"]),uI=new Set(["owner","reason","requestedAction"]);function Zh(e,t){if(e===null)return{ok:!1,reason:"no output"};if(Buffer.byteLength(e,"utf8")>Ul)return{ok:!1,reason:`result exceeds ${Ul} bytes`};let r=e.trim();if(r.length===0)return{ok:!1,reason:"empty output"};let n;try{n=JSON.parse(r)}catch{return{ok:!1,reason:"output is not a single JSON object"}}if(typeof n!="object"||n===null||Array.isArray(n))return{ok:!1,reason:"output is not a JSON object"};let o=n;for(let c of Object.keys(o))if(!lI.has(c))return{ok:!1,reason:`unknown field "${c}"`};if(o.run_token!==t)return{ok:!1,reason:"run token missing or mismatched"};let s=o.status;if(s!=="succeeded"&&s!=="failed"&&s!=="escalated")return{ok:!1,reason:"status must be succeeded, failed, or escalated"};if(typeof o.summary!="string"||o.summary.trim().length===0)return{ok:!1,reason:"summary must be a nonblank string"};if(Buffer.byteLength(o.summary,"utf8")>mn)return{ok:!1,reason:"summary is too large"};let i=[];if(o.artifacts!==void 0){if(!Array.isArray(o.artifacts)||o.artifacts.length>Bi)return{ok:!1,reason:"artifacts must be an array of at most 100 strings"};for(let c of o.artifacts)if(typeof c!="string"||c.trim().length===0||Buffer.byteLength(c,"utf8")>Pl)return{ok:!1,reason:"each artifact must be a nonblank string of at most 4096 bytes"};i=o.artifacts}let a={status:s,summary:o.summary.trim(),artifacts:i};if(s==="escalated"){let c=o.escalation;if(typeof c!="object"||c===null||Array.isArray(c))return{ok:!1,reason:"an escalated result requires an escalation object"};let l=c;for(let u of Object.keys(l))if(!uI.has(u))return{ok:!1,reason:`unknown escalation field "${u}"`};if(typeof l.reason!="string"||l.reason.trim().length===0||Buffer.byteLength(l.reason,"utf8")>Yo)return{ok:!1,reason:"escalation.reason is required and bounded"};if(typeof l.requestedAction!="string"||l.requestedAction.trim().length===0||Buffer.byteLength(l.requestedAction,"utf8")>Yo)return{ok:!1,reason:"escalation.requestedAction is required and bounded"};if(a.reason=l.reason.trim(),a.action=l.requestedAction.trim(),l.owner!==void 0){if(typeof l.owner!="string"||l.owner.trim().length===0||l.owner.length>Ml)return{ok:!1,reason:"escalation.owner must be a nonblank string of at most 512 chars"};a.owner=l.owner.trim()}}return{ok:!0,result:a}}function dI(e,t,r){let n=t.session_alias??"Worker";if(t.working_directory===null||t.provider===null)throw new P("INVALID_ARGUMENT",`session job ${t.id} requires provider and an absolute working_directory`);let o=os(r??oI(),nI(e)),s=t.session_generation??0,i=t.session_teamfile??os(o,`job-${t.id}-g${s}.lmctl`);if(t.session_teamfile!==null)return{teamfile:t.session_teamfile,alias:n};if(HN(i))return e.prepare("UPDATE cron_jobs SET session_teamfile = ?, session_alias = ?, updated_at = ? WHERE id = ?").run(i,n,new Date().toISOString(),t.id),{teamfile:i,alias:n};BN(o,{recursive:!0});let a=rI({alias:n,provider:t.provider,model:t.model,sessiondir:t.working_directory});return Qh(i,`#teamfile: ${i}
|
|
294
294
|
# private single-member session for lmbee cron job ${t.id} (generation ${s})
|
|
295
295
|
|
|
296
296
|
${a}
|
|
297
|
-
`,{mode:384}),e.prepare("UPDATE cron_jobs SET session_teamfile = ?, session_alias = ?, updated_at = ? WHERE id = ?").run(i,n,new Date().toISOString(),t.id),{teamfile:i,alias:n}}function Vl(e){try{return process.kill(-e,0),!0}catch{return!1}}function Bl(e,t){if(e.pid===void 0)return;let r=e.pid;try{process.kill(-r,"SIGTERM")}catch{return}setTimeout(()=>{try{process.kill(-r,0)}catch{return}try{process.kill(-r,"SIGKILL")}catch{}},t).unref()}function
|
|
298
|
-
`)){let i=s.trim();if(i.length===0)continue;let a;try{a=JSON.parse(i)}catch{continue}if(typeof a!="object"||a===null)continue;let c=a,l=typeof c.message=="string"?c.message:String(c.status);c.status==="ok"&&typeof c.replyText=="string"?t=c.replyText:c.status==="stalled"?r=l:c.status==="busy"?n=l:(c.status==="error"||c.status==="failed")&&(o=l)}return r!==null?{kind:"stalled",message:r}:n!==null?{kind:"busy",message:n}:o!==null?{kind:"error",message:o}:t!==null?{kind:"completed",text:t}:{kind:"none"}}function Jl(e,t){try{let r=
|
|
297
|
+
`,{mode:384}),e.prepare("UPDATE cron_jobs SET session_teamfile = ?, session_alias = ?, updated_at = ? WHERE id = ?").run(i,n,new Date().toISOString(),t.id),{teamfile:i,alias:n}}function Vl(e){try{return process.kill(-e,0),!0}catch{return!1}}function Bl(e,t){if(e.pid===void 0)return;let r=e.pid;try{process.kill(-r,"SIGTERM")}catch{return}setTimeout(()=>{try{process.kill(-r,0)}catch{return}try{process.kill(-r,"SIGKILL")}catch{}},t).unref()}function mI(e){let t=null,r=null,n=null,o=null;for(let s of e.split(`
|
|
298
|
+
`)){let i=s.trim();if(i.length===0)continue;let a;try{a=JSON.parse(i)}catch{continue}if(typeof a!="object"||a===null)continue;let c=a,l=typeof c.message=="string"?c.message:String(c.status);c.status==="ok"&&typeof c.replyText=="string"?t=c.replyText:c.status==="stalled"?r=l:c.status==="busy"?n=l:(c.status==="error"||c.status==="failed")&&(o=l)}return r!==null?{kind:"stalled",message:r}:n!==null?{kind:"busy",message:n}:o!==null?{kind:"error",message:o}:t!==null?{kind:"completed",text:t}:{kind:"none"}}function Jl(e,t){try{let r=GN(e,"utf8").trim();return r.length>t?r.slice(-t):r}catch{return""}}var fI=500,Kh=75;function Yh(e){let{db:t,job:r,run:n}=e,o=e.onDemand===void 0?r.action_payload:[process.execPath,qN(new URL("./on-demand-worker.cjs",import.meta.url)),fn(t.name),e.onDemand.conversationId,String(e.onDemand.generation),String(r.id),String(n.id),r.action_payload,e.onDemand.receiptPath].map(s=>`'${s.replaceAll("'","'\\''")}'`).join(" ");try{Gn(t,n.id,{kind:"script",cwd:r.working_directory},null)}catch(s){Ve(t,n.id,{fallback:{ok:!1,summary:`script setup failed before spawn: ${Xe(s)}`}});return}try{zo({id:r.id,action_payload:o},{...e.logDir!==void 0?{logDir:e.logDir}:{},...r.working_directory!==null?{cwd:r.working_directory}:{},...e.spawnPrefixes?.script!==void 0?{spawnPrefix:e.spawnPrefixes.script}:{},...e.timeoutMs!==void 0?{timeoutMs:e.timeoutMs}:{},...e.sigkillGraceMs!==void 0?{sigkillGraceMs:e.sigkillGraceMs}:{},...t.name!==void 0&&t.name!==":memory:"?{env:{...process.env,LMBEE_DB:fn(t.name)}}:{},onExit:(s,i,a,c)=>{let l=()=>{if(i!==void 0){Ve(t,n.id,{fallback:{ok:!1,summary:`script spawn error: ${i.message}`}});return}let u=s===0||s===Kh,d=Jl(c,fI),m=s===Kh?`script no-op (exit ${s})${d?`: ${d}`:""}`:`script exited with code ${s}${d?`: ${d}`:""}`;a!==null&&Vl(a)?bt(t,n.id,"process group still alive after exit",{fallback:{ok:u,summary:m}}):Ve(t,n.id,{fallback:{ok:u,summary:m}})};if(e.onDemand===void 0)return l();try{Xt(t,l)}catch{}}})}catch(s){Ve(t,n.id,{fallback:{ok:!1,summary:`script spawn error: ${Xe(s)}`}})}}function pI(e){let{db:t,job:r,run:n}=e,o,s,i,a;try{o=Hl(e.timeoutMs,QN,"timeoutMs"),s=e.sigkillGraceMs??Xh,i=[...e.spawnPrefixes?.miniplayer??YN,"run",...r.model!==null?["-m",r.model]:[]],a=cI(r.action_payload,e.runToken)}catch(g){Ve(t,n.id,{fallback:{ok:!1,summary:`miniplayer setup failed before spawn: ${Xe(g)}`}});return}let[c,...l]=i,u;try{u=jl(c,l,{detached:!0,stdio:["pipe","pipe","pipe"],...r.working_directory!==null?{cwd:r.working_directory}:{},...t.name!==void 0&&t.name!==":memory:"?{env:{...process.env,LMBEE_DB:fn(t.name)}}:{}})}catch(g){Ve(t,n.id,{fallback:{ok:!1,summary:`miniplayer spawn error: ${Xe(g)}`}});return}u.unref();let d=rs(),m=rs(),f=!1,p=!1,h=setTimeout(()=>{f||(f=!0,Bl(u,s),bt(t,n.id,`miniplayer timed out after ${o}ms`,{fallback:{ok:!1,summary:`miniplayer timed out after ${o}ms`}}))},o);h.unref(),u.on("spawn",()=>p=!0),u.stdout?.on("data",g=>ns(d,g)),u.stderr?.on("data",g=>ns(m,g)),u.stdin?.on("error",()=>{}),u.on("error",g=>{if(f)return;f=!0,clearTimeout(h);let _={fallback:{ok:!1,summary:`miniplayer spawn error: ${g.message}`}};p?bt(t,n.id,`miniplayer post-spawn error: ${g.message}`,_):Ve(t,n.id,_)}),u.on("close",(g,_)=>{if(f)return;f=!0,clearTimeout(h);let E=u.pid??null,y=E!==null&&Vl(E),S=d.overflow?{ok:!1,reason:`output exceeded the ${Gi}-byte capture limit`}:Zh(d.text,e.runToken),T=S.ok?{report:S.result}:{fallback:{ok:!1,summary:`miniplayer produced no valid structured result (${S.reason})`+(g!==0||_!==null?`; exit ${_??g}: ${m.text.trim().slice(-300)}`:"")}};y?bt(t,n.id,"miniplayer process group still alive after wrapper exit",T):d.overflow?bt(t,n.id,"miniplayer output exceeded the capture limit; result not trusted",T):Ve(t,n.id,T)});try{Gn(t,n.id,{kind:"miniplayer",model:r.model},u.pid??null)}catch(g){process.stderr.write(`[lmcron] miniplayer run ${n.id} state write failed after spawn: ${Xe(g)}
|
|
299
299
|
`)}try{u.stdin?.write(a),u.stdin?.end()}catch(g){process.stderr.write(`[lmcron] miniplayer run ${n.id} stdin write failed: ${Xe(g)}
|
|
300
|
-
`)}}function
|
|
301
|
-
`)}try{es(t,n.id,{kind:"session",phase:"dispatch",teamfile:a,alias:c},A.pid??null)}catch{}};if(r.session_seeded_at!==null){l();return}let d=[...e.spawnPrefixes?.seed??
|
|
300
|
+
`)}}function hI(e){let{db:t,job:r,run:n}=e,o,s,i;try{o=Hl(e.timeoutMs,XN,"timeoutMs"),s=Hl(e.seedTimeoutMs,ZN,"seedTimeoutMs"),i=e.sigkillGraceMs??Xh}catch(y){Ve(t,n.id,{fallback:{ok:!1,summary:`session setup failed before spawn: ${Xe(y)}`}});return}let a,c;try{({teamfile:a,alias:c}=dI(t,r,e.sessionDir))}catch(y){Ve(t,n.id,{fallback:{ok:!1,summary:`session teamfile creation failed: ${Xe(y)}`}});return}let l=()=>{let y=e.spawnPrefixes?.chat??nn,S,T,R;try{let W=aI(r.action_payload,e.runToken,t);S=WN(os(JN(),"lmbee-cron-session-")),T=os(S,`${n.id}.md`),Qh(T,W,{mode:384}),R=[...y,"chat",`${a}:${c}`,"--prompt-file",T,"--json"]}catch(W){Ve(t,n.id,{fallback:{ok:!1,summary:`session dispatch setup failed before spawn: ${Xe(W)}`}});return}let[x,...I]=R,A;try{A=jl(x,I,{detached:!0,stdio:["ignore","pipe","pipe"],...r.working_directory!==null?{cwd:r.working_directory}:{},...t.name!==void 0&&t.name!==":memory:"?{env:{...process.env,LMBEE_DB:fn(t.name)}}:{}})}catch(W){try{Vh(S,{recursive:!0,force:!0})}catch{}Ve(t,n.id,{fallback:{ok:!1,summary:`session dispatch spawn error: ${Xe(W)}`}});return}A.unref();let H=rs(),L=rs(),w=!1,b=!1,N=()=>{try{Vh(S,{recursive:!0,force:!0})}catch{}},D=setTimeout(()=>{w||(w=!0,Bl(A,i),bt(t,n.id,`session timed out after ${o}ms`,{fallback:{ok:!1,summary:`session timed out after ${o}ms`}}))},o);D.unref(),A.on("spawn",()=>b=!0),A.stdout?.on("data",W=>ns(H,W)),A.stderr?.on("data",W=>ns(L,W)),A.on("error",W=>{if(w)return;w=!0,clearTimeout(D);let ee={fallback:{ok:!1,summary:`session dispatch spawn error: ${W.message}`}};b?bt(t,n.id,`session post-spawn error: ${W.message}`,ee):(N(),Ve(t,n.id,ee))}),A.on("close",W=>{if(w)return;w=!0,clearTimeout(D);let ee=A.pid??null,ne=ee!==null&&Vl(ee),J=H.overflow?{kind:"overflow"}:mI(H.text),oe=J.kind==="completed"?Zh(J.text,e.runToken):null,k=J.kind==="completed"&&!ne&&!H.overflow,O=oe!==null&&oe.ok?{report:oe.result}:{fallback:{ok:!1,summary:(J.kind==="completed"?"session ended without a valid report":J.kind==="stalled"?"session stalled (native turn still running)":J.kind==="busy"?"session was busy; not started":J.kind==="error"?`session provider error: ${J.message}`:J.kind==="overflow"?`session output exceeded the ${Gi}-byte capture limit`:"session ended without positive completion")+(W!==0?` (exit ${W}: ${L.text.trim().slice(-300)})`:"")}};if(k){if(oe!==null&&!oe.ok){N(),Ve(t,n.id,O);return}if(Ve(t,n.id,O)){N();return}return}let $=J.kind==="stalled"?`session stalled (native turn still running): ${J.message}`:J.kind==="busy"?`session busy (a live worker may own it): ${J.message}`:J.kind==="error"?`session provider error (termination unconfirmed): ${J.message}`:J.kind==="overflow"?"session output exceeded the capture limit; result not trusted":ne?"session process group still alive after wrapper exit":`session wrapper exited without positive completion (code ${W})`;bt(t,n.id,$,O)});try{Gn(t,n.id,{kind:"session",provider:r.provider,model:r.model,teamfile:a,alias:c},A.pid??null)}catch(W){process.stderr.write(`[lmcron] session run ${n.id} state write failed after spawn: ${Xe(W)}
|
|
301
|
+
`)}try{es(t,n.id,{kind:"session",phase:"dispatch",teamfile:a,alias:c},A.pid??null)}catch{}};if(r.session_seeded_at!==null){l();return}let d=[...e.spawnPrefixes?.seed??KN,"seed",a],m=d[0],f=d.slice(1),p;try{p=jl(m,f,{detached:!0,stdio:["ignore","ignore","pipe"],...t.name!==void 0&&t.name!==":memory:"?{env:{...process.env,LMBEE_DB:fn(t.name)}}:{}})}catch(y){Ve(t,n.id,{fallback:{ok:!1,summary:`session seed spawn error: ${Xe(y)}`}});return}p.unref();let h=rs(),g=!1,_=!1,E=setTimeout(()=>{g||(g=!0,Bl(p,i),bt(t,n.id,`session seed timed out after ${s}ms; provider initialization may still be running`,{fallback:{ok:!1,summary:`session seed timed out after ${s}ms`}}))},s);E.unref(),p.on("spawn",()=>_=!0),p.stderr?.on("data",y=>ns(h,y)),p.on("error",y=>{if(g)return;g=!0,clearTimeout(E);let S={fallback:{ok:!1,summary:`session seed spawn error: ${y.message}`}};_?bt(t,n.id,`session seed post-spawn error: ${y.message}`,S):Ve(t,n.id,S)}),p.on("close",y=>{if(!g){if(g=!0,clearTimeout(E),y!==0){bt(t,n.id,`session seed failed (exit ${y}); provider initialization may still be running`,{fallback:{ok:!1,summary:`session seed failed (exit ${y}): ${h.text.trim().slice(-300)}`}});return}try{t.prepare("UPDATE cron_jobs SET session_seeded_at = ?, updated_at = ? WHERE id = ?").run(new Date().toISOString(),new Date().toISOString(),r.id)}catch(S){bt(t,n.id,`session seeded but recording identity failed: ${Xe(S)}`,{fallback:{ok:!1,summary:"session seeded but recording seed state failed; will recover on retry"}});return}l()}});try{es(t,n.id,{kind:"session",phase:"seed",teamfile:a,alias:c},p.pid??null)}catch{}}function zl(e){if(Vo(e.db,e.job.id)){if(e.onDemand===void 0||!Oh(e.db,e.job.id,e.run.id,e.onDemand))return;Xt(e.db,()=>Yh(e));return}try{switch(e.job.action_kind){case"script":Yh(e);return;case"miniplayer":pI(e);return;case"session":hI(e);return;default:Ve(e.db,e.run.id,{fallback:{ok:!1,summary:`unsupported run worker kind: ${e.job.action_kind}`}})}}catch(t){bt(e.db,e.run.id,`unexpected worker dispatch failure: ${Xe(t)}`,{fallback:{ok:!1,summary:`worker dispatch error: ${Xe(t)}`}})}}function _I(e){return e==="enqueue"||e==="command"||e==="script"||e==="session"||e==="miniplayer"}function wI(e){return e==="script"||e==="session"||e==="miniplayer"}function Tt(e){return e instanceof Error?e.message:String(e)}function Vn(e){let t=e&&typeof e=="object"&&"code"in e?String(e.code):void 0;if(t!==void 0&&(t.startsWith("SQLITE_BUSY")||t.startsWith("SQLITE_LOCKED")))throw new P("DB_BUSY","Database busy; retry after the current writer completes",5);let r=e instanceof Error?e.message:String(e);throw t!==void 0&&t.startsWith("SQLITE_CONSTRAINT")?new P("STRUCTURAL_ERROR",r,2):new P("STORAGE_ERROR",r,1)}function hr(e){try{return e()}catch(t){if(t instanceof P)throw t;if(t instanceof C)throw new P(t.code,t.message,t.exitCode);return Vn(t)}}function Ji(e,t){e.prepare("UPDATE cron_jobs SET revision = revision + 1, updated_at = ? WHERE id = ?").run(me(),t)}function zi(e,t){return hr(()=>e.prepare("SELECT * FROM cron_jobs WHERE id = ?").get(t)??null)}function Ce(e,t){let r=zi(e,t);if(r===null)throw new P("NOT_FOUND",`Cron job ${t} does not exist`,3);return r}function yI(e){let t;try{t=JSON.parse(e)}catch{throw new P("INVALID_ARGUMENT","enqueue action_payload must be valid JSON")}if(typeof t!="object"||t===null)throw new P("INVALID_ARGUMENT","enqueue action_payload must be a JSON object");let{to:r,prompt:n,from:o}=t;if(typeof r!="string"||r.trim().length===0)throw new P("INVALID_ARGUMENT",'enqueue action_payload requires a nonblank "to"');if(typeof n!="string"||n.trim().length===0)throw new P("INVALID_ARGUMENT",'enqueue action_payload requires a nonblank "prompt"');if(o!==void 0&&(typeof o!="string"||o.trim().length===0))throw new P("INVALID_ARGUMENT",'enqueue action_payload "from", if given, must be a nonblank string')}function rg(e,t){Ee(t,"action_payload"),e==="enqueue"&&yI(t)}function ng(e){let{actionKind:t}=e;if(t==="session"){if(e.provider===void 0||e.provider===null||e.provider.trim().length===0)throw new P("INVALID_ARGUMENT","a session job requires a nonblank provider");if(Wl(e.provider),e.workingDirectory===void 0||e.workingDirectory===null||e.workingDirectory.trim().length===0)throw new P("INVALID_ARGUMENT","a session job requires an absolute working_directory (--cwd)");Vi(e.workingDirectory)}else if(e.provider!==void 0&&e.provider!==null&&e.provider.trim().length>0)throw new P("INVALID_ARGUMENT",`provider is only valid for session jobs (not ${t})`);if(e.model!==void 0&&e.model!==null&&e.model.trim().length===0)throw new P("INVALID_ARGUMENT","model, if given, must be nonblank");if(e.model!==void 0&&e.model!==null&&e.model.trim().length>0&&t!=="session"&&t!=="miniplayer")throw new P("INVALID_ARGUMENT",`model is only valid for session/miniplayer jobs (not ${t})`);if(e.model!==void 0&&e.model!==null&&e.model.trim().length>0&&Gl(e.model),e.workingDirectory!==void 0&&e.workingDirectory!==null&&e.workingDirectory.trim().length>0&&t==="enqueue")throw new P("INVALID_ARGUMENT","working_directory is not valid for enqueue jobs");if(e.workingDirectory!==void 0&&e.workingDirectory!==null&&e.workingDirectory.trim().length===0)throw new P("INVALID_ARGUMENT","working_directory, if given, must be nonblank");if(e.escalationOwner!==void 0&&e.escalationOwner!==null&&e.escalationOwner.trim().length===0)throw new P("INVALID_ARGUMENT","escalation_owner, if given, must be nonblank")}function og(e){let t=Ee(e,"timezone");try{new Intl.DateTimeFormat(void 0,{timeZone:t})}catch{throw new P("INVALID_ARGUMENT",`timezone "${t}" is not a recognized IANA zone name`)}return t}function sg(e){let t=Dl(e);if(!t.ok){let r=t.error.field?` (field: ${t.error.field})`:"";throw new P("INVALID_SCHEDULE",`${t.error.message}${r}`)}}function Jn(e,t){let r=e.transaction(()=>{if(t.id!==void 0&&(!Number.isSafeInteger(t.id)||t.id<1))throw new P("INVALID_ARGUMENT","id, if given, must be a positive safe integer");let n=Ee(t.title,"title");if(!_I(t.actionKind))throw new P("INVALID_ARGUMENT",'action_kind must be "enqueue", "command", "script", "session", or "miniplayer"');sg(t.scheduleExpr),rg(t.actionKind,t.actionPayload),ng({actionKind:t.actionKind,provider:t.provider??null,model:t.model??null,workingDirectory:t.workingDirectory??null,escalationOwner:t.escalationOwner??null});let o=t.timezone!==void 0?og(t.timezone):null,s=me();try{let i=e.prepare(t.id!==void 0?`INSERT INTO cron_jobs(id, title, schedule_expr, action_kind, action_payload, provider, model,
|
|
302
302
|
working_directory, escalation_owner, enabled, timezone, created_at, updated_at)
|
|
303
303
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`:`INSERT INTO cron_jobs(title, schedule_expr, action_kind, action_payload, provider, model,
|
|
304
304
|
working_directory, escalation_owner, enabled, timezone, created_at, updated_at)
|
|
305
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(...t.id!==void 0?[t.id]:[],n,t.scheduleExpr,t.actionKind,t.actionPayload,t.provider??null,t.model??null,t.workingDirectory??null,t.escalationOwner??null,t.enabled===!1?0:1,o,s,s);return Ce(e,Number(i.lastInsertRowid))}catch(i){Vn(i)}});return
|
|
306
|
-
session_generation = session_generation + 1 WHERE id = ?`).run(t),Ji(e,t),Ce(e,t)});return
|
|
305
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(...t.id!==void 0?[t.id]:[],n,t.scheduleExpr,t.actionKind,t.actionPayload,t.provider??null,t.model??null,t.workingDirectory??null,t.escalationOwner??null,t.enabled===!1?0:1,o,s,s);return Ce(e,Number(i.lastInsertRowid))}catch(i){Vn(i)}});return hr(()=>r.immediate())}function Ki(e,t){if(!Number.isSafeInteger(t.limit)||t.limit<1||t.limit>Le)throw new P("INVALID_ARGUMENT",`limit must be a positive integer <= ${Le}`);return hr(()=>{let r=["id > ?"],n=[t.after];t.enabled!==void 0&&(r.push("enabled = ?"),n.push(t.enabled?1:0));let o=e.prepare(`SELECT * FROM cron_jobs WHERE ${r.join(" AND ")} ORDER BY id LIMIT ?`).all(...n,t.limit+1),s=o.length>t.limit,i=s?o.slice(0,t.limit):o;return{rows:i,meta:{next_cursor:s?i[i.length-1].id:null}}})}function ig(e,t,r){let n=e.transaction(()=>{let o=Ce(e,t);if(r.ifRevision!==void 0&&o.revision!==r.ifRevision)throw new P("REVISION_CONFLICT",`Expected revision ${r.ifRevision}; current is ${o.revision}`,4);let s={};if(r.title!==void 0&&(s.title=Ee(r.title,"title")),r.scheduleExpr!==void 0&&(sg(r.scheduleExpr),s.schedule_expr=r.scheduleExpr),r.actionPayload!==void 0&&(rg(o.action_kind,r.actionPayload),s.action_payload=r.actionPayload),r.timezone!==void 0&&(s.timezone=r.timezone===null?null:og(r.timezone)),o.session_teamfile!==null&&(r.provider!==void 0&&r.provider!==o.provider||r.model!==void 0&&r.model!==o.model||r.workingDirectory!==void 0&&r.workingDirectory!==o.working_directory))throw new P("SESSION_IMMUTABLE","provider/model/cwd cannot change while a session is seeded; run `cron reset-session` first",2);if(r.provider!==void 0&&(s.provider=r.provider),r.model!==void 0&&(s.model=r.model),(r.provider!==void 0||r.model!==void 0)&&ng({actionKind:o.action_kind,provider:r.provider??o.provider,model:r.model??o.model,workingDirectory:r.workingDirectory!==void 0?r.workingDirectory:o.working_directory}),r.workingDirectory!==void 0){if(o.action_kind==="enqueue")throw new P("INVALID_ARGUMENT","working_directory is not valid for enqueue jobs");if(r.workingDirectory===null){if(o.action_kind==="session")throw new P("INVALID_ARGUMENT","a session job requires an absolute working_directory");s.working_directory=null}else{let i=Ee(r.workingDirectory,"working_directory");o.action_kind==="session"&&Vi(i),s.working_directory=i}}if(r.escalationOwner!==void 0&&(s.escalation_owner=r.escalationOwner===null?null:Ee(r.escalationOwner,"escalation_owner")),Object.keys(s).length===0)throw new P("INVALID_ARGUMENT","Update requires at least one field");try{e.prepare(`UPDATE cron_jobs SET ${Object.keys(s).map(i=>`${i} = ?`).join(",")} WHERE id = ?`).run(...Object.values(s),t)}catch(i){Vn(i)}return Ji(e,t),Ce(e,t)});return hr(n)}function ag(e,t,r){let n=e.transaction(()=>{Ce(e,t);try{e.prepare("UPDATE cron_jobs SET enabled = ? WHERE id = ?").run(r?1:0,t)}catch(o){Vn(o)}return Ji(e,t),Ce(e,t)});return hr(()=>n.immediate())}function cg(e,t){let r=e.transaction(()=>{let n=Ce(e,t);if(It(e,t)!==null)throw new P("EXECUTION_FENCED",`Cron job ${t} has a fenced execution or unresolved escalation; resolve it before removing the job`,4);try{e.prepare("DELETE FROM cron_jobs WHERE id = ?").run(t)}catch(o){Vn(o)}return n});return hr(r)}function lg(e,t){let r=e.transaction(()=>{if(Ce(e,t).action_kind!=="session")throw new P("INVALID_ARGUMENT",`Cron job ${t} is not a session job`);if(It(e,t)!==null)throw new P("SESSION_ACTIVE",`Cron job ${t} has an active run; resolve it before resetting the session`,4);return e.prepare(`UPDATE cron_jobs SET session_teamfile = NULL, session_seeded_at = NULL, session_alias = NULL,
|
|
306
|
+
session_generation = session_generation + 1 WHERE id = ?`).run(t),Ji(e,t),Ce(e,t)});return hr(r)}var EI=24*60*60*1e3;function ug(e,t=gI){try{return t("systemctl",["--user","is-active","--quiet",e]),"active"}catch(r){return r.status===3?"confirmed-gone":"unknown"}}async function dg(e,t,r,n={}){let o=n.enqueueImpl??we,s=n.spawnCommandImpl??zo,i=n.isUnitStillRunningImpl??ug,a=new Date(r).toISOString(),c=[],l=hr(()=>e.prepare("SELECT * FROM cron_jobs WHERE enabled = 1 ORDER BY id").all());for(let u of l)try{vI(e,u,t,r,a,o,s,i,n.logDir,c,n.onJobError,{...n.runSpawnPrefixes!==void 0?{runSpawnPrefixes:n.runSpawnPrefixes}:{},...n.sessionDir!==void 0?{sessionDir:n.sessionDir}:{},...n.runTimeoutMs!==void 0?{runTimeoutMs:n.runTimeoutMs}:{},...n.runSeedTimeoutMs!==void 0?{runSeedTimeoutMs:n.runSeedTimeoutMs}:{},executeRunImpl:n.executeRunImpl??zl})}catch(d){try{n.onJobError?.(u.id,d)}catch{}try{Pr(e,"UPDATE cron_jobs SET last_fire_status = ?, last_fire_error = ?, updated_at = ?",["error",Tt(d),a],u)}catch{}}return c}function eg(e,t){let r=new Intl.DateTimeFormat("en-US",{timeZone:t,hourCycle:"h23",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"}).formatToParts(e),n=o=>Number(r.find(s=>s.type===o).value);return new Date(n("year"),n("month")-1,n("day"),n("hour"),n("minute"),n("second"))}var bI=500;function TI(e){return JSON.stringify({kind:"command",payload:e.action_payload,provider:e.provider,model:e.model,workingDirectory:e.working_directory,escalationOwner:e.escalation_owner})}function SI(e){if(e.execution_identity===null)return null;try{let t=JSON.parse(e.execution_identity);return typeof t.systemdUnit=="string"?t.systemdUnit:null}catch{return null}}function Kl(e,t,r){let n=It(e,t);if(n!==null)try{pr(e,n.id,{fallback:{ok:!1,summary:r}})}catch{}}function mg(e,t,r,n,o){try{let s=TI(t),i=Zo(e,t.id,r,s);if(i.kind!=="claimed"){let a=SI(i.run);a!==null&&o(a)==="confirmed-gone"&&(Kl(e,t.id,"reconciled: previous command execution confirmed gone before a new fire"),i=Zo(e,t.id,r,s))}return i.kind!=="claimed"?null:(Gn(e,i.run.id,{kind:"command",systemdUnit:n},null),i.run.id)}catch{return null}}function fg(e,t,r,n,o,s,i){if(t!==null)try{if(o!==null)try{es(e,t,{kind:"command",systemdUnit:i},o)}catch{}let a=Jl(s,bI),c=n?`command spawn error: ${n.message}`:`command exited with code ${r}${a?`: ${a}`:""}`;pr(e,t,{fallback:{ok:n===void 0&&r===0,summary:c}})}catch{}}function pg(e,t,r){if(t!==null)try{pr(e,t,{fallback:{ok:!1,summary:`command spawn failed: ${Tt(r)}`}})}catch{}}function vI(e,t,r,n,o,s,i,a,c,l,u,d){let m=Dl(t.schedule_expr);if(!m.ok){Pr(e,"UPDATE cron_jobs SET last_fire_status = ?, last_fire_error = ?, updated_at = ?",["error",`Unparseable schedule_expr: ${m.error.message}`,o],t);return}let f=m.schedule;if(t.action_kind==="command"&&t.running_since_ts!==null){if(t.running_systemd_unit!==null&&a(t.running_systemd_unit)==="confirmed-gone"){e.prepare(`UPDATE cron_jobs SET running_since_ts = NULL, running_systemd_unit = NULL, last_fire_status = ?,
|
|
307
307
|
last_fire_error = NULL, updated_at = ?
|
|
308
|
-
WHERE id = ? AND enabled = 1 AND revision = ? AND running_since_ts = ? AND running_systemd_unit = ?`).run("reconciled",o,t.id,t.revision,t.running_since_ts,t.running_systemd_unit),
|
|
309
|
-
WHERE id = ? AND enabled = 1 AND revision = ? AND (last_checked_ts IS ?) AND (running_since_ts IS ?)`).run(o,o,"ok",o,R,o,t.id,t.revision,t.last_checked_ts,t.running_since_ts).changes===0)return;let I=
|
|
310
|
-
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),
|
|
311
|
-
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:Ce(e,t)};let _=
|
|
308
|
+
WHERE id = ? AND enabled = 1 AND revision = ? AND running_since_ts = ? AND running_systemd_unit = ?`).run("reconciled",o,t.id,t.revision,t.running_since_ts,t.running_systemd_unit),Kl(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",o,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>n){Pr(e,"UPDATE cron_jobs SET last_checked_ts = ?, last_fire_status = ?, last_fire_error = ?, updated_at = ?",[o,"error",`last_checked_ts (${t.last_checked_ts??t.created_at}) is after the current tick time -- checkpoint reset without firing`,o],t);return}let h=new Date(p),g=new Date(n);if(n-p>EI){Pr(e,"UPDATE cron_jobs SET last_checked_ts = ?, last_fire_status = ?, updated_at = ?",[o,"skipped_stale",o],t);return}let _=t.timezone!==null?eg(h,t.timezone):h,E=t.timezone!==null?eg(g,t.timezone):g;if(!Dh(f,_,E)){Pr(e,"UPDATE cron_jobs SET last_checked_ts = ?, updated_at = ?",[o,o],t);return}let S=zi(e,t.id);if(!(S===null||S.enabled===0||S.revision!==t.revision)){if(wI(t.action_kind)){AI(e,t,o,l,u,d);return}if(t.action_kind==="enqueue")try{let T=JSON.parse(t.action_payload),R={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:(s(e,r,T.to,T.prompt,R),e.prepare("UPDATE cron_jobs SET last_checked_ts = ?, last_fired_ts = ?, last_fire_status = ?, last_fire_error = NULL, updated_at = ? WHERE id = ?").run(o,o,"ok",o,t.id),!0)}).immediate()&&l.push(t.title)}catch(T){try{u?.(t.id,T)}catch{}try{Pr(e,"UPDATE cron_jobs SET last_fire_status = ?, last_fire_error = ?, updated_at = ?",["error",Tt(T),o],t)}catch{}}else{let T=o,R=`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 = ?
|
|
309
|
+
WHERE id = ? AND enabled = 1 AND revision = ? AND (last_checked_ts IS ?) AND (running_since_ts IS ?)`).run(o,o,"ok",o,R,o,t.id,t.revision,t.last_checked_ts,t.running_since_ts).changes===0)return;let I=mg(e,t,t.action_kind,R,a),A={logDir:c,systemdUnitName:R,onExit:(H,L,w,b)=>{let N=H===0?"ok":"error",D=N==="ok"?null:L?Tt(L):`Command exited with code ${H} -- see ${c??Hi()}/${t.id}/ for output`;if(L)try{u?.(t.id,L)}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(N,D,new Date().toISOString(),t.id,T)}catch{}fg(e,I,H,L,w,b,R)}};try{i({id:t.id,action_payload:t.action_payload},A),l.push(t.title)}catch(H){try{u?.(t.id,H)}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",Tt(H),o,t.id,T)}catch{}pg(e,I,H)}}}}async function tg(e,t){for(;!e();)await new Promise(r=>setTimeout(r,t))}async function ss(e,t,r,n={}){let o=n.enqueueImpl??we,s=n.spawnCommandImpl??zo,i=n.isUnitStillRunningImpl??ug,a=n.executeRunImpl??zl,c=n.logDir,l=n.pollMs??250,u=Ce(e,t);if(Vo(e,t)&&n.onDemand===void 0)return{kind:"skipped_overlap",job:u};if(u.enabled===0)throw new P("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=me();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 = ?
|
|
310
|
+
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),Kl(e,u.id,"reconciled: command execution confirmed gone by systemd probe; no exit callback survived the restart"),await ss(e,t,r,n)):{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 = ?
|
|
311
|
+
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:Ce(e,t)};let _=mg(e,u,`${u.action_kind}:manual`,h,i),E={logDir:c,systemdUnitName:h,onExit:(y,S,T,R)=>{let x=y===0?"ok":"error",I=x==="ok"?null:S?Tt(S):`Command exited with code ${y} -- see ${c??Hi()}/${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(x,I,new Date().toISOString(),u.id,p)}catch{}fg(e,_,y,S,T,R,h)}};try{s({id:u.id,action_payload:u.action_payload},E)}catch(y){pg(e,_,y);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",Tt(y),d,u.id,p)}catch{}throw new P("SPAWN_FAILED",`manual trigger of job ${t} failed to spawn: ${Tt(y)}`,1)}return await tg(()=>Ce(e,t).running_since_ts!==p,l),{kind:"fired",job:Ce(e,t)}}if(u.action_kind==="enqueue"){let p=JSON.parse(u.action_payload);return o(e,r,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:Ce(e,t)}}let m=JSON.stringify({kind:u.action_kind,payload:u.action_payload,provider:u.provider,model:u.model,workingDirectory:u.working_directory,escalationOwner:u.escalation_owner}),f=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=Zo(e,u.id,`${u.action_kind}:manual`,m);if(h.kind==="claimed"){n.onDemand!==void 0&&Ch(e,u.id,h.run.id,n.onDemand);let g=n.disableOnClaim?"enabled = 0, ":"";e.prepare(`UPDATE cron_jobs SET ${g}last_fired_ts = ?, last_fire_status = ?, last_fire_error = NULL, updated_at = ? WHERE id = ?`).run(d,"ok",d,u.id)}return h}).immediate();if(f===null)throw new P("CONFLICT",`Cron job ${t} was modified concurrently -- re-run \`cron trigger ${t}\``,5);if(f.kind==="escalation")return{kind:"blocked_escalation",job:Ce(e,t)};if(f.kind==="overlap")return{kind:"skipped_overlap",job:Ce(e,t)};try{a({db:e,job:u,run:f.run,runToken:f.token,...n.onDemand!==void 0?{onDemand:n.onDemand}:{},...n.runSpawnPrefixes!==void 0?{spawnPrefixes:n.runSpawnPrefixes}:{},...n.sessionDir!==void 0?{sessionDir:n.sessionDir}:{},...n.runTimeoutMs!==void 0?{timeoutMs:n.runTimeoutMs}:{},...n.runSeedTimeoutMs!==void 0?{seedTimeoutMs:n.runSeedTimeoutMs}:{}})}catch(p){try{ts(e,f.run.id,`worker dispatch threw: ${Tt(p)}`),ql(e,f.run.id,{ok:!1,summary:`worker dispatch error: ${Tt(p)}`})}catch{}throw new P("SPAWN_FAILED",`manual trigger of job ${t} failed to dispatch: ${Tt(p)}`,1)}if(n.waitForCompletion===!1){let p=u;try{p=Ce(e,t)}catch(h){console.warn(`[triggerCronJobNow] post-dispatch getCronJob read failed for job ${t}:`,h)}return{kind:"fired",job:p,runId:f.run.id}}return await tg(()=>{let p=Be(e,f.run.id);return p.status!=="pending"&&p.status!=="running"},l),{kind:"fired",job:Ce(e,t),runId:f.run.id}}function AI(e,t,r,n,o,s){if(Vo(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=Zo(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(r,r,"ok",r,t.id),l}).immediate();if(a!==null){if(a.kind==="escalation"){Pr(e,"UPDATE cron_jobs SET last_fire_status = ?, updated_at = ?",["blocked_escalation",r],t);return}if(a.kind==="overlap"){Pr(e,"UPDATE cron_jobs SET last_fire_status = ?, updated_at = ?",["skipped_overlap",r],t);return}n.push(t.title);try{s.executeRunImpl({db:e,job:t,run:a.run,runToken:a.token,...s.runSpawnPrefixes!==void 0?{spawnPrefixes:s.runSpawnPrefixes}:{},...s.sessionDir!==void 0?{sessionDir:s.sessionDir}:{},...s.runTimeoutMs!==void 0?{timeoutMs:s.runTimeoutMs}:{},...s.runSeedTimeoutMs!==void 0?{seedTimeoutMs:s.runSeedTimeoutMs}:{}})}catch(c){try{ts(e,a.run.id,`worker dispatch threw: ${Tt(c)}`),ql(e,a.run.id,{ok:!1,summary:`worker dispatch error: ${Tt(c)}`})}catch{}try{o?.(t.id,c)}catch{}}}}function Pr(e,t,r,n){e.prepare(`${t} WHERE id = ? AND enabled = 1 AND revision = ? AND (last_checked_ts IS ?)`).run(...r,n.id,n.revision,n.last_checked_ts)}function hg(e,t){let r=e.transaction(()=>{Ce(e,t);try{e.prepare("UPDATE cron_jobs SET running_since_ts = NULL, running_systemd_unit = NULL WHERE id = ?").run(t)}catch(n){Vn(n)}return Ji(e,t),Ce(e,t)});return hr(r)}import{execFileSync as $I}from"node:child_process";import{existsSync as kI,readFileSync as gg}from"node:fs";import{homedir as _g}from"node:os";import{join as wg}from"node:path";function Kn(){return process.env.LMBEE_HEAVY_STATUS??wg(_g(),".lmbee","heavy.status")}function Yn(){return process.env.LMBEE_HEAVY_LOCK??wg(_g(),".lmbee","heavy.lock")}var zn=class extends Error{};function xI(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 RI(e){let t;try{t=gg(e,"utf8")}catch{return null}try{let r=JSON.parse(t);return xI(r)?r:null}catch{return null}}function NI(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 II(e){try{let t=gg(`/proc/${e}/stat`,"utf8");return t.slice(t.lastIndexOf(")")+2).trim().split(/\s+/)[0]==="Z"}catch{return!1}}function LI(e){try{process.kill(e,0)}catch(t){return t.code==="EPERM"}return!II(e)}function CI(e,t=$I){if(!kI(e))return!1;try{return t("flock",["-n",e,"-c","true"],{stdio:"ignore"}),!1}catch(r){if((r&&typeof r=="object"?r.status:void 0)===1)return!0;let o=r instanceof Error?r.message:String(r);throw new zn(`heavy-lock probe failed (flock did not run or exited abnormally): ${o}`)}}function Yl(e=Kn(),t=Yn(),r=RI,n=CI,o=LI){for(let s=0;s<3;s++){let i=r(e),a=n(t),c=r(e);if(i!==null&&NI(i,c)){if(!a)return{held:!1,holder:null};if(o(i.pid))return{held:!0,holder:i}}}return{held:n(t),holder:null}}function ft(e=Kn(),t=Yn(),r=Yl,n){try{return r(e,t)}catch(o){if(!(o instanceof zn))throw o;return n?.(o),{held:!0,holder:null}}}var Yi={observedAt:null,report:null,lastErrorAt:null,lastError:null};function yg(e,t){Yi={observedAt:t,report:e,lastErrorAt:null,lastError:null}}function Eg(e,t){Yi={...Yi,lastErrorAt:t,lastError:e}}function is(){return Yi}import{execFile as OI}from"node:child_process";import{promisify as DI}from"node:util";function fe(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),r=Math.floor(e%864e5/36e5);return r===0?`${t}d`:`${t}d ${r}h`}function ge(e,t=Date.now()){let r=Date.parse(e);if(Number.isNaN(r))return"?";let n=t-r;return n<6e4?"just now":`${fe(n)} ago`}var MI=DI(OI);function PI(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 UI(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 r=t;for(let n of["running","dead","idle"])if(!r[n].every(PI))throw new Error(`unexpected \`lmctl running --json\` shape: a malformed element (bad/missing target or from_identity) in \`${n}\``);return r}async function ke(e=3e4){let{stdout:t}=await MI("lmctl",["running","--json"],{timeout:e});return UI(t)}function Ql(e,t=Date.now()){return{schema_version:e.schema_version,running:e.running.map(r=>({...r,running_for_human:fe(r.running_for_ms),started_human:ge(r.started_at,t)})),dead:e.dead.map(r=>({...r,stale_for_human:fe(r.stale_for_ms),started_human:ge(r.started_at,t)})),idle:e.idle.map(r=>({...r,ran_human:fe(r.ran_ms)}))}}import{readFileSync as FI}from"node:fs";import{randomUUID as qI}from"node:crypto";var Xl={staleThresholdMs:2*60*6e4,escalationCooldownMs:60*6e4,digestTimeoutMs:9e4,leaseTimeoutMs:10*6e4,providerQuotaBackoffMs:24*60*6e4,operatorStaleThresholdMs:6e4,operatorEscalationCooldownMs:6e4};function jI(e){return/usage limit/i.test(e)&&/quota/i.test(e)}function HI(e){let t=[];for(let r of e)try{t.push({row:r,content:FI(r.prompt_file,"utf8")})}catch{continue}return t}function BI(e){let t=e.map(({row:r,content:n})=>`--- from "${r.from_id}", queued ${r.created_ts} ---
|
|
312
312
|
${n}`);return`You have ${e.length} queued message(s) that couldn't be delivered automatically (presence-gated for a while) -- bundled here as a digest:
|
|
313
313
|
|
|
314
314
|
${t.join(`
|
|
315
315
|
|
|
316
|
-
`)}`}function
|
|
317
|
-
WHERE status = 'escalating' AND (escalation_claimed_ts IS NULL OR escalation_claimed_ts < ?)`).run(n)}function
|
|
316
|
+
`)}`}function WI(e,t,r){let n=new Date(r-t).toISOString();e.prepare(`UPDATE queue SET status = 'pending', escalation_claimed_ts = NULL, escalation_claim_token = NULL
|
|
317
|
+
WHERE status = 'escalating' AND (escalation_claimed_ts IS NULL OR escalation_claimed_ts < ?)`).run(n)}function GI(e,t){let r=new Set,n=new Date().toISOString(),o=qI();return e.transaction(()=>{for(let i of t)e.prepare("UPDATE queue SET status = 'escalating', escalation_claimed_ts = ?, escalation_claim_token = ? WHERE id = ? AND status = 'pending'").run(n,o,i).changes>0&&r.add(i)}).immediate(),{claimed:r,token:o}}function Qi(e,t,r,n,o){let s=new Date().toISOString(),i=!1;e.transaction(()=>{for(let c of t)(n?e.prepare(`UPDATE queue SET status = 'sent', sent_ts = ?, delivered_via_escalation = 1, escalation_claimed_ts = NULL, escalation_claim_token = NULL
|
|
318
318
|
WHERE id = ? AND status = 'escalating' AND escalation_claim_token = ?`).run(s,c,r):e.prepare(`UPDATE queue SET status = 'pending', escalation_claimed_ts = NULL, escalation_claim_token = NULL
|
|
319
|
-
WHERE id = ? AND status = 'escalating' AND escalation_claim_token = ?`).run(c,r)).changes>0&&(i=!0);i&&o?.()}).immediate()}async function
|
|
319
|
+
WHERE id = ? AND status = 'escalating' AND escalation_claim_token = ?`).run(c,r)).changes>0&&(i=!0);i&&o?.()}).immediate()}async function bg(e,t,r=Xl,n=Date.now(),o={}){let s=o.sendAwaited??Jt,i=[];WI(e,r.leaseTimeoutMs,n);let a=e.prepare("SELECT * FROM queue WHERE status = 'pending' ORDER BY to_id, id").all(),c=new Map;for(let u of a){let d=c.get(u.to_id);d?d.push(u):c.set(u.to_id,[u])}let l=[...c.entries()].sort(([,u],[,d])=>{let m=u.some(p=>p.operator_priority===1)?0:1,f=d.some(p=>p.operator_priority===1)?0:1;return m-f});for(let[u,d]of l){let m=t.find(L=>L.name===u);if(m===void 0)continue;let f=d.some(L=>L.operator_priority===1),p=f?r.operatorStaleThresholdMs:r.staleThresholdMs,h=f?r.operatorEscalationCooldownMs:r.escalationCooldownMs,g=d[0];if(n-Date.parse(g.created_ts)<p)continue;let E=se(e,u),y=E?.last_escalation_attempt_ts?Date.parse(E.last_escalation_attempt_ts):null;if(y!==null&&n-y<h)continue;let S=E?.quota_exhausted_last_seen_ts?Date.parse(E.quota_exhausted_last_seen_ts):null;if(S!==null){let L=y!==null?Math.max(S,y):S;if(n-L<r.providerQuotaBackoffMs)continue}if(ti(e,u,m.leadAlias,n))continue;let T;try{T=Q(m)}catch{continue}let R=HI(d);if(R.length===0)continue;let{claimed:x,token:I}=GI(e,R.map(L=>L.row.id)),A=R.filter(L=>x.has(L.row.id));if(A.length===0)continue;let H=!1;try{let L=BI(A);Bm(e,u,new Date().toISOString());let w=await s({teamfilePath:T,alias:m.leadAlias},L,{timeoutMs:r.digestTimeoutMs});if(w.kind==="ok"||w.kind==="stalled")Qi(e,x,I,!0,()=>Hm(e,u)),H=!0,i.push(u);else if(w.kind==="error"&&jI(w.message)){let b=new Date().toISOString();Qi(e,x,I,!1,()=>jm(e,u,b,w.message)),H=!0}else Qi(e,x,I,!1),H=!0}catch{}finally{if(!H)try{Qi(e,x,I,!1)}catch{}}}return i}var Zl={minStaleMs:12e5,maxTotalAgeMs:144e5};function Tg(e,t,r=Zl,n=Date.now()){return[]}var eu={staleMs:72e5,maxAgeMs:864e5,cooldownMs:36e5};function Sg(e,t,r,n=eu,o=Date.now()){return[]}import{execFile as YI}from"node:child_process";import{promisify as QI}from"node:util";var VI=["ok","provider_unavailable","auth_expired","not_applicable","reader_throttled"];function JI(e){return typeof e=="string"&&VI.includes(e)}function tu(e){return typeof e=="object"&&e!==null}function zI(e){if(!tu(e))return null;let t=e.bucket_id,r=e.used_fraction;if(typeof t!="string"||t.length===0||typeof r!="number"||!Number.isFinite(r))return null;let n={bucket_id:t,used_fraction:r};return typeof e.window_type=="string"&&(n.window_type=e.window_type),typeof e.group_name=="string"&&(n.group_name=e.group_name),typeof e.resets_at=="number"&&Number.isFinite(e.resets_at)&&(n.resets_at=e.resets_at),typeof e.resets_at_iso=="string"&&(n.resets_at_iso=e.resets_at_iso),typeof e.is_exhausted=="boolean"&&(n.is_exhausted=e.is_exhausted),"raw_value"in e&&(n.raw_value=e.raw_value),typeof e.raw_scale=="string"&&(n.raw_scale=e.raw_scale),n}function KI(e){if(!tu(e))return null;let t=e.provider,r=e.status,n=e.read_at;if(typeof t!="string"||t.length===0||!JI(r)||typeof n!="number"||!Number.isFinite(n))return null;let o={provider:t,status:r,read_at:n};return typeof e.source=="string"&&(o.source=e.source),Array.isArray(e.buckets)&&(o.buckets=e.buckets.map(zI).filter(s=>s!==null)),typeof e.reason=="string"&&(o.reason=e.reason),typeof e.detail=="string"&&(o.detail=e.detail),typeof e.retry_after_seconds=="number"&&(o.retry_after_seconds=e.retry_after_seconds),o}function vg(e){let t;try{t=JSON.parse(e)}catch{return null}return!tu(t)||!Array.isArray(t.readings)?null:t.readings.map(KI).filter(r=>r!==null)}var XI=QI(YI);function Ag(){return process.env.LMBEE_RATE_LIMIT_BIN??"lmctl"}async function ZI(e=Ag(),t=XI){try{let{stdout:r}=await t(e,["ratelimit","--json"]);return vg(r)}catch{return null}}function e0(e){return e==null?null:typeof e=="string"?e:JSON.stringify(e)}function t0(e,t,r){let n=e.prepare(`INSERT INTO rate_limit_readings (provider, status, source, read_at, reason, detail, retry_after_seconds, inserted_at)
|
|
320
320
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(t.provider,t.status,t.source??null,t.read_at,t.reason??null,t.detail??null,t.retry_after_seconds??null,r);if(t.status!=="ok")return;let o=n.lastInsertRowid,s=e.prepare(`INSERT INTO rate_limit_bucket_samples
|
|
321
321
|
(reading_id, provider, bucket_id, window_type, group_name, used_fraction, resets_at, resets_at_iso, raw_value, raw_scale, is_exhausted, read_at)
|
|
322
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);for(let i of t.buckets??[]){if(typeof i.resets_at!="number")continue;let a=i.window_type==="five_hour"||i.window_type==="weekly"?i.window_type:"unknown";s.run(o,t.provider,i.bucket_id,a,i.group_name??null,i.used_fraction??0,i.resets_at,i.resets_at_iso??null,
|
|
322
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);for(let i of t.buckets??[]){if(typeof i.resets_at!="number")continue;let a=i.window_type==="five_hour"||i.window_type==="weekly"?i.window_type:"unknown";s.run(o,t.provider,i.bucket_id,a,i.group_name??null,i.used_fraction??0,i.resets_at,i.resets_at_iso??null,e0(i.raw_value),i.raw_scale??null,i.is_exhausted===!0?1:i.is_exhausted===!1?0:null,t.read_at)}}var $g="rate_limit_collect:last_run_ms",r0=5*6e4;function n0(e,t,r){let n=e.prepare("SELECT v FROM kv WHERE k = ?").get($g);if(n===void 0)return!0;let o=Number(n.v);return Number.isFinite(o)?t-o>=r:!0}function o0(e,t){e.prepare("INSERT INTO kv(k, v) VALUES (?, ?) ON CONFLICT(k) DO UPDATE SET v = excluded.v").run($g,String(t))}async function kg(e,t={}){let r=t.nowMs??Date.now(),n=t.cooldownMs??r0;if(!n0(e,r,n))return{outcome:"skipped-cooldown"};let s=await(t.fetchImpl??ZI)(t.binPath??Ag());if(s===null)return{outcome:"fetch-failed"};let i=Math.floor(r/1e3);return e.transaction(c=>{for(let l of c)t0(e,l,i)})(s),o0(e,r),{outcome:"collected",readingsStored:s.length}}var ru={five_hour:9e5,weekly:36e5},Xi={five_hour:"five_hour_15m",weekly:"weekly_1h"};function Zi(e,t){if(e.length<3)return{kind:"insufficient_data",reason:`only ${e.length} sample(s), need >= 3`};let r=[...e].sort((_,E)=>_.readAt-E.readAt),n=r[0],o=r[r.length-1],s=(o.readAt-n.readAt)*1e3;if(s<6e5)return{kind:"insufficient_data",reason:`samples span only ${Math.round(s/1e3)}s, need >= ${6e5/1e3}s`};let i=t-o.readAt*1e3;if(i>9e5)return{kind:"insufficient_data",reason:`freshest sample is ${Math.round(i/1e3)}s old, exceeds ${9e5/1e3}s staleness limit`};let a=r.length,c=r.reduce((_,E)=>_+E.readAt,0)/a,l=r.reduce((_,E)=>_+E.usedFraction,0)/a,u=0,d=0;for(let _ of r){let E=_.readAt-c;u+=E*(_.usedFraction-l),d+=E*E}if(d===0)return{kind:"insufficient_data",reason:"samples have no time spread"};let m=u/d;if(m<=0)return{kind:"no_forecast"};let h=(1-(l-m*c+m*o.readAt))/m;return{kind:"forecast",forecastAtMs:o.readAt*1e3+h*1e3,burnFractionPerMin:m*60,latestReadAtMs:o.readAt*1e3}}function xg(e,t,r){return e.kind!=="forecast"?!1:e.forecastAtMs-r<=ru[t]}var s0=new Set(["claude:week-scoped-Fable","codex:codex_bengalfox-5h","codex:codex_bengalfox-weekly"]);function Rg(e,t){return s0.has(`${e}:${t}`)}var i0=ru.weekly;function a0(e){let t=[...e].sort((o,s)=>o.readAt-s.readAt),r=t[0],n=t[t.length-1];return{count:t.length,spanMinutes:Math.round((n.readAt-r.readAt)/60*10)/10,latestUsedFraction:n.usedFraction}}function c0(e){return new Date(e*1e3).toISOString()}function l0(e,t,r,n,o,s){let i=new Date(n.forecastAtMs).toISOString(),a=Math.round((n.forecastAtMs-s)/6e4),c=Math.round(n.burnFractionPerMin*100*100)/100;return`auto-disable: ${e} bucket=${t} (${r}) forecast reaches 100% at ${i} (~${a}m); burn rate ${c}%/min over ${o.count} samples spanning ${o.spanMinutes}m; current used_fraction=${o.latestUsedFraction}; rule=${Xi[r]}`}function Qn(e,t,r,n,o,s,i){e.prepare("INSERT INTO rate_limit_policy_log (ts, provider, bucket_id, window_type, outcome, detail) VALUES (?, ?, ?, ?, ?, ?)").run(t,r,n,o,s,i)}function ea(e,t,r,n){e.prepare("DELETE FROM rate_limit_policy_arm WHERE provider = ? AND bucket_id = ? AND resets_at = ?").run(t,r,n)}function u0(e,t,r,n){return e.prepare("SELECT rule, armed_at, armed_latest_read_at, armed_used_fraction, forecast_at FROM rate_limit_policy_arm WHERE provider = ? AND bucket_id = ? AND resets_at = ?").get(t,r,n)??null}function d0(e,t,r,n,o,s,i,a,c){e.prepare(`INSERT INTO rate_limit_policy_arm (provider, bucket_id, resets_at, rule, armed_at, armed_latest_read_at, armed_used_fraction, forecast_at)
|
|
323
323
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
324
324
|
ON CONFLICT(provider, bucket_id, resets_at) DO UPDATE SET
|
|
325
325
|
rule = excluded.rule, armed_at = excluded.armed_at, armed_latest_read_at = excluded.armed_latest_read_at,
|
|
326
|
-
armed_used_fraction = excluded.armed_used_fraction, forecast_at = excluded.forecast_at`).run(t,r,n,o,s,i,a,c)}function
|
|
327
|
-
FROM rate_limit_bucket_samples WHERE provider = ? AND bucket_id = ? AND resets_at = ? AND read_at >= ? ORDER BY read_at ASC`).all(c,l,m,p),g=h.map(I=>({readAt:I.readAt,usedFraction:I.usedFraction})),_=Zi(g,r);if(_.kind==="insufficient_data"){a.push({provider:c,bucketId:l,windowType:u,outcome:"insufficient-data",detail:_.reason});continue}let E=
|
|
326
|
+
armed_used_fraction = excluded.armed_used_fraction, forecast_at = excluded.forecast_at`).run(t,r,n,o,s,i,a,c)}function Ng(e,t={}){let r=t.nowMs??Date.now(),n=t.dryRun??!0,o=t.checkProviderDisabledImpl??it,s=t.setProviderDisableImpl??Pi,i=e.prepare("SELECT DISTINCT provider, bucket_id AS bucketId, window_type AS windowType FROM rate_limit_bucket_samples WHERE window_type IN ('five_hour', 'weekly')").all(),a=[];for(let{provider:c,bucketId:l,windowType:u}of i){if(Rg(c,l)){a.push({provider:c,bucketId:l,windowType:u,outcome:"excluded-non-representative",detail:"scoped sub-limit or retired bucket -- never independently disable-eligible"});continue}let m=e.prepare("SELECT MAX(resets_at) AS resetsAt FROM rate_limit_bucket_samples WHERE provider = ? AND bucket_id = ?").get(c,l).resetsAt;if(m===null)continue;let f=e.prepare("SELECT resets_at AS resetsAt, rule FROM rate_limit_policy_arm WHERE provider = ? AND bucket_id = ? AND resets_at != ?").all(c,l,m);for(let I of f)ea(e,c,l,I.resetsAt),Qn(e,r,c,l,u,"disarmed",`window rolled over (resets_at advanced from ${I.resetsAt} to ${m}) while armed under rule=${I.rule} -- orphaned arm swept, never confirmed`);let p=Math.floor((r-18e5)/1e3),h=e.prepare(`SELECT id AS readingId, used_fraction AS usedFraction, read_at AS readAt, resets_at_iso AS resetsAtIso
|
|
327
|
+
FROM rate_limit_bucket_samples WHERE provider = ? AND bucket_id = ? AND resets_at = ? AND read_at >= ? ORDER BY read_at ASC`).all(c,l,m,p),g=h.map(I=>({readAt:I.readAt,usedFraction:I.usedFraction})),_=Zi(g,r);if(_.kind==="insufficient_data"){a.push({provider:c,bucketId:l,windowType:u,outcome:"insufficient-data",detail:_.reason});continue}let E=u0(e,c,l,m);if(_.kind==="no_forecast"||!xg(_,u,r)){E!==null&&(ea(e,c,l,m),Qn(e,r,c,l,u,"disarmed",`forecast no longer crosses the ${Xi[u]} threshold`)),a.push({provider:c,bucketId:l,windowType:u,outcome:_.kind==="no_forecast"?"no-forecast":"below-threshold",detail:""});continue}let y=g[g.length-1].usedFraction;if(E===null){d0(e,c,l,m,Xi[u],r,_.latestReadAtMs,y,_.forecastAtMs);let I=`armed on first crossing, forecast ${new Date(_.forecastAtMs).toISOString()}`;Qn(e,r,c,l,u,"armed",I),a.push({provider:c,bucketId:l,windowType:u,outcome:"armed",detail:I});continue}if(_.latestReadAtMs<=E.armed_latest_read_at){a.push({provider:c,bucketId:l,windowType:u,outcome:"still-armed",detail:"awaiting a newer sample to confirm"});continue}if(y<=E.armed_used_fraction){a.push({provider:c,bucketId:l,windowType:u,outcome:"still-armed",detail:`newer sample available (used_fraction=${y}) but no increase over the armed reference (${E.armed_used_fraction}) -- awaiting real movement to confirm`});continue}let S=o(e,c,r),T=a0(g),R=l0(c,l,u,_,T,r);if(S.disabled){let I=S.config?`reason=${JSON.stringify(S.config.reason)}, expiresAt=${S.config.expiresAt??"indefinite"}`:"fail-closed (read error)",A=`would have fired (${R}) but ${c} is already disabled (${I}) -- deferring, never shortening or overwriting an existing hold`;Qn(e,r,c,l,u,"confirmed_deferred_existing_disable",A),a.push({provider:c,bucketId:l,windowType:u,outcome:"confirmed-deferred",detail:A});continue}if(n){ea(e,c,l,m);let I=`would have fired (policy step is disabled -- collection only): ${R}`;Qn(e,r,c,l,u,"confirmed_would_fire_policy_disabled",I),a.push({provider:c,bucketId:l,windowType:u,outcome:"confirmed-would-fire",detail:I});continue}let x=u==="weekly"?new Date(r+i0).toISOString():h[h.length-1]?.resetsAtIso??c0(m);s(e,c,{reason:R,expiresAt:x}),ea(e,c,l,m),Qn(e,r,c,l,u,"confirmed_fired",R),a.push({provider:c,bucketId:l,windowType:u,outcome:"confirmed-fired",detail:R})}return m0(e,r,a),a}var Ig="rate_limit_policy_heartbeat";function m0(e,t,r){let n={};for(let s of r)n[s.outcome]=(n[s.outcome]??0)+1;let o={lastRunAtMs:t,seriesEvaluated:r.length,outcomeCounts:n};e.prepare("INSERT INTO kv(k, v) VALUES (?, ?) ON CONFLICT(k) DO UPDATE SET v = excluded.v").run(Ig,JSON.stringify(o))}function ra(e){let t=e.prepare("SELECT v FROM kv WHERE k = ?").get(Ig);if(t===void 0)return null;try{return JSON.parse(t.v)}catch{return null}}var f0=15*6e4;function Lg(e,t=Date.now(),r=f0){let n=e.prepare("SELECT MAX(read_at) AS readAt FROM rate_limit_bucket_samples").get();if(n.readAt===null||t-n.readAt*1e3>r)return null;let s=ra(e);if(s===null)return{status:"never-run",reason:"rate-limit policy has never completed an evaluation while collection is active",ageMs:1/0};let i=t-s.lastRunAtMs;return i>r?{status:"stale",reason:`rate-limit policy last ran ${Math.round(i/6e4)}m ago while collection is active`,ageMs:i}:null}var p0=.85;function Cg(e,t=p0){return e.prepare(`SELECT s.provider AS provider, s.bucket_id AS bucketId, s.window_type AS windowType, s.used_fraction AS usedFraction, s.resets_at_iso AS resetsAtIso
|
|
328
328
|
FROM rate_limit_bucket_samples s
|
|
329
329
|
INNER JOIN (
|
|
330
330
|
SELECT provider, bucket_id, MAX(read_at) AS maxReadAt
|
|
@@ -332,7 +332,7 @@ ${t.join(`
|
|
|
332
332
|
WHERE window_type = 'weekly'
|
|
333
333
|
GROUP BY provider, bucket_id
|
|
334
334
|
) latest ON latest.provider = s.provider AND latest.bucket_id = s.bucket_id AND latest.maxReadAt = s.read_at
|
|
335
|
-
WHERE s.window_type = 'weekly'`).all().filter(n=>!
|
|
335
|
+
WHERE s.window_type = 'weekly'`).all().filter(n=>!Rg(n.provider,n.bucketId)&&n.usedFraction>=t)}var nu="auto_scan_paused";function Ur(e){let t=e.prepare("SELECT v FROM kv WHERE k = ?").get(nu);if(t===void 0)return null;try{let r=JSON.parse(t.v);return{paused_at:typeof r.paused_at=="string"?r.paused_at:"unknown",actor:typeof r.actor=="string"?r.actor:null,note:typeof r.note=="string"?r.note:null,resume_after:typeof r.resume_after=="string"?r.resume_after:null}}catch{return{paused_at:"unknown",actor:null,note:null,resume_after:null}}}var h0=3*24*60*6e4;function Og(e,t=Date.now()){let r=Ur(e);if(r===null)return null;let n=Date.parse(r.paused_at);if(Number.isNaN(n))return{status:"unevaluable",state:r,reason:"corrupt-paused-at"};let o=t-n;if(r.resume_after!==null){let s=Date.parse(r.resume_after);return Number.isNaN(s)?{status:"unevaluable",state:r,reason:"corrupt-resume-after"}:t>=s?{status:"stale",state:r,ageMs:o,resumeAfterPassed:!0}:null}return o>=h0?{status:"stale",state:r,ageMs:o,resumeAfterPassed:!1}:null}function Dg(e,t){e.prepare("INSERT INTO kv(k, v) VALUES (?, ?) ON CONFLICT(k) DO UPDATE SET v = excluded.v").run(nu,JSON.stringify(t))}function Mg(e){e.prepare("DELETE FROM kv WHERE k = ?").run(nu)}var g0=/usage limit|rate limit|too many requests|quota exceeded|insufficient_quota/i;function na(e,t,r=36e5,n=Date.now()){let o=e.idle.find(i=>i.target===t);if(o===void 0||o.error===null||o.error===void 0||!g0.test(o.error))return!1;let s=Date.parse(o.ended_at);return Number.isFinite(s)?n-s<r:!1}import{existsSync as ou,mkdirSync as _0,readFileSync as w0,writeFileSync as y0}from"node:fs";import{homedir as E0}from"node:os";import{join as Pg}from"node:path";var b0=`# Autopilot check-in -- advance your work, then report status
|
|
336
336
|
|
|
337
337
|
You are being polled. Advance the work you have established (see your own durable memory for what that
|
|
338
338
|
is) -- do a REAL unit of work this turn, not just a status echo. Before reporting DONE or going idle,
|
|
@@ -348,29 +348,29 @@ On the VERY LAST LINE, emit ONE flag ONLY when it applies:
|
|
|
348
348
|
- BLOCKED -- you need a decision/escalation, or are holding on a go-ahead before proceeding.
|
|
349
349
|
- DONE -- everything is complete AND verified AND committed+pushed+tested, nothing pending.
|
|
350
350
|
If neither applies, reply normally describing what you advanced and omit the flag.
|
|
351
|
-
`;function oa(e){return e||(process.env.LMBEE_PROMPTS_DIR?process.env.LMBEE_PROMPTS_DIR:
|
|
351
|
+
`;function oa(e){return e||(process.env.LMBEE_PROMPTS_DIR?process.env.LMBEE_PROMPTS_DIR:Pg(E0(),".lmbee","prompts"))}function Ug(e,t){return Pg(e,`${t}.md`)}function T0(e){ou(e)||_0(e,{recursive:!0});let t=Ug(e,"default");ou(t)||y0(t,b0)}function S0(e,t){let r=Ug(e,t);if(!ou(r))if(t==="default")T0(e);else throw new Error(`loadPromptTemplate: no prompt file for "${t}" at ${r} -- prepare it (S1) before this team can be auto-nudged`);return w0(r,"utf8")}function sa(e,t){return S0(e,t.promptName)}import{existsSync as v0,readFileSync as qg,rmSync as A0}from"node:fs";import{resolve as Fg,sep as $0}from"node:path";function xt(e,t){if(t!==null)return{lifecycle:"finished",lifecycleBasis:"answer",pulledAt:e.sent_ts??e.retrieved_ts,answeredAt:t.answered_at};if(e.retracted_ts!==null)return{lifecycle:"finished",lifecycleBasis:"retracted",pulledAt:e.sent_ts??e.retrieved_ts,answeredAt:null};if(e.status==="merged")return{lifecycle:"finished",lifecycleBasis:"merged",pulledAt:null,answeredAt:null};if(e.in_reply_to!=null){let r=e.status==="sent"||e.status==="retrieved";return{lifecycle:r?"finished":"queued",lifecycleBasis:"reply",pulledAt:r?e.sent_ts??e.retrieved_ts:null,answeredAt:null}}return!e.expects_response&&(e.status==="sent"||e.status==="retrieved")?{lifecycle:"finished",lifecycleBasis:"informational",pulledAt:e.sent_ts??e.retrieved_ts,answeredAt:null}:e.status==="retrieved"?{lifecycle:"processing",lifecycleBasis:"confirmed",pulledAt:e.retrieved_ts,answeredAt:null}:e.status==="sent"?{lifecycle:"processing",lifecycleBasis:"dispatched",pulledAt:e.sent_ts,answeredAt:null}:{lifecycle:"queued",lifecycleBasis:"dispatched",pulledAt:null,answeredAt:null}}function De(e,t){return e.prepare("SELECT * FROM answers WHERE prompt_queue_id = ? AND superseded_at IS NULL").get(t)??null}function jg(e,t){return e.prepare("SELECT * FROM answers WHERE prompt_queue_id = ? ORDER BY created_at ASC, id ASC").all(t)}var k0=`q.status != 'merged'
|
|
352
352
|
AND q.retracted_ts IS NULL
|
|
353
353
|
AND NOT EXISTS (SELECT 1 FROM answers r WHERE r.prompt_queue_id = q.id)
|
|
354
|
-
AND NOT ((q.expects_response = 0 OR q.in_reply_to IS NOT NULL) AND q.status IN ('sent', 'retrieved'))`;function
|
|
354
|
+
AND NOT ((q.expects_response = 0 OR q.in_reply_to IS NOT NULL) AND q.status IN ('sent', 'retrieved'))`;function Hg(e,t){return e.prepare(`SELECT q.* FROM queue q
|
|
355
355
|
WHERE q.to_id = ?
|
|
356
|
-
AND ${
|
|
357
|
-
ORDER BY q.id`).all(t)}function
|
|
358
|
-
`)[0]??""}catch{}for(let c of r)a.includes(c)&&n.add(c)}let o=e.prepare("SELECT * FROM queue WHERE (from_id = ? OR to_id = ?) AND created_ts > ? AND id != ? ORDER BY created_ts ASC"),s=new Set([t.id]),i=[];for(let a of n)for(let c of o.all(a,a,t.created_ts,t.id))s.has(c.id)||(s.add(c.id),i.push({row:c,matchedTeam:a}));return i.sort((a,c)=>Date.parse(a.row.created_ts)-Date.parse(c.row.created_ts)),i.slice(0,
|
|
356
|
+
AND ${k0}
|
|
357
|
+
ORDER BY q.id`).all(t)}function Bg(e,t,r){let n=new Date(r-t.maxAgeMs).toISOString(),o=["status IN ('sent', 'retrieved')","from_id != 'autopilot'","COALESCE(sent_ts, retrieved_ts) >= ?"],s=[n];t.fromId!==void 0&&(o.push("from_id = ?"),s.push(t.fromId));let i=e.prepare(`SELECT * FROM queue WHERE ${o.join(" AND ")}`).all(...s),a=[];for(let c of i){let l=xt(c,De(e,c.id));if(l.lifecycle!=="processing"||l.pulledAt===null)continue;let u=r-Date.parse(l.pulledAt);u>=t.minAgeMs&&u<=t.maxAgeMs&&a.push({row:c,ageMs:u})}return a.sort((c,l)=>l.ageMs-c.ageMs),a}function Wg(e,t,r){let n=e.prepare("SELECT * FROM queue WHERE from_id = 'operator' AND to_id = ? AND status IN ('pending', 'escalating', 'sent', 'retrieved')").all(t),o=[];for(let s of n)xt(s,De(e,s.id)).lifecycle!=="finished"&&o.push({row:s,ageMs:r-Date.parse(s.created_ts)});return o.sort((s,i)=>i.ageMs-s.ageMs),o}function su(e,t){let r=[t.from_id,t.to_id,t.escalation_only,t.to_alias],o=e.prepare("SELECT MIN(id) AS id FROM queue WHERE from_id = ? AND to_id = ? AND escalation_only = ? AND to_alias IS ? AND id > ? AND status != 'merged'").get(...r,t.id).id??Number.MAX_SAFE_INTEGER;return e.prepare("SELECT * FROM queue WHERE from_id = ? AND to_id = ? AND escalation_only = ? AND to_alias IS ? AND status = 'merged' AND id > ? AND id < ?").all(...r,t.id,o)}function iu(e,t){if(t.status!=="merged")return null;if(t.merged_into_id!==null){let o=e.prepare("SELECT * FROM queue WHERE id = ?").get(t.merged_into_id);if(o)return o}let r=e.prepare("SELECT * FROM queue WHERE to_id = ? AND status != 'merged' AND id < ? ORDER BY id").all(t.to_id,t.id),n=`--- addendum, ${t.created_ts} ---`;for(let o of r){let s;try{s=qg(o.prompt_file,"utf8")}catch{continue}if(s.includes(n))return o}return null}function pn(e,t){return 1+su(e,t).length}function as(e,t){return(t.retracted_ts!==null?1:0)+su(e,t).filter(n=>n.retracted_ts!==null).length}function Gg(e,t,r,n,o={}){let s=Ee(n,"reason");return e.transaction(()=>{let a=e.prepare("SELECT * FROM queue WHERE id = ?").get(t);if(a===void 0)throw new C("NOT_FOUND",`Queue prompt ${t} does not exist`,3);if(a.from_id!==r)throw new C("INVALID_ARGUMENT",`Queue prompt ${t} was not sent by "${r}" -- cannot retract another team's claim`,2);if(a.retracted_ts!==null)throw new C("CONFLICT",`Queue prompt ${t} was already retracted: ${a.retracted_reason??"(no reason recorded)"}`,4);if(a.status!=="merged"){let f=su(e,a).filter(p=>p.retracted_ts===null);if(f.length>0)throw new C("INVALID_ARGUMENT",`Queue prompt ${t} has ${f.length} still-live merged escalation(s) (ids: ${f.map(p=>p.id).join(", ")}) folded into it -- retract those individually first, or the whole coalesced thread would silently disappear`,2)}let c=De(e,t)!==null;if(!c&&a.status==="pending"){ot(e,r,"queue_retracted_deleted",Date.parse(me()),{note:`queue#${t} (was ${a.from_id} -> ${a.to_id}, sent ${a.created_ts}, never retrieved): ${s}`}),e.prepare("DELETE FROM queue WHERE id = ?").run(t);let f=Fg(ci()),p=Fg(a.prompt_file);if((p===f||p.startsWith(f+$0))&&v0(p))try{A0(p,{force:!0})}catch{}return{kind:"deleted",id:t,reason:s}}let l=me();e.prepare("UPDATE queue SET retracted_ts = ?, retracted_reason = ? WHERE id = ?").run(l,s,t);let u=e.prepare("SELECT * FROM queue WHERE id = ?").get(t);if(c||u.status==="merged"||o.noNotice===!0)return{kind:"retracted",row:u};let d=u.to_alias===null?u.to_id:`${u.to_id}:${u.to_alias}`,m=we(e,[{name:u.to_id}],d,`RETRACTED: queue#${t} -- ${s}`,{from:u.from_id,expectsResponse:!1,retractionNotice:!0});return{kind:"retracted-with-notice",row:u,noticeId:m}}).immediate()}function cs(e,t){let r=e.prepare("SELECT * FROM queue WHERE to_id = 'operator' AND status IN ('pending', 'escalating', 'sent', 'retrieved')").all(),n=[];for(let o of r)xt(o,De(e,o.id)).lifecycle!=="finished"&&n.push({row:o,ageMs:t-Date.parse(o.created_ts)});return n.sort((o,s)=>s.ageMs-o.ageMs),n}var x0=5;function R0(e,t,r){let n=new Set([t.from_id,t.to_id]);if(r.length>0){let a="";try{a=qg(t.prompt_file,"utf8").split(`
|
|
358
|
+
`)[0]??""}catch{}for(let c of r)a.includes(c)&&n.add(c)}let o=e.prepare("SELECT * FROM queue WHERE (from_id = ? OR to_id = ?) AND created_ts > ? AND id != ? ORDER BY created_ts ASC"),s=new Set([t.id]),i=[];for(let a of n)for(let c of o.all(a,a,t.created_ts,t.id))s.has(c.id)||(s.add(c.id),i.push({row:c,matchedTeam:a}));return i.sort((a,c)=>Date.parse(a.row.created_ts)-Date.parse(c.row.created_ts)),i.slice(0,x0)}function hn(e,t,r,n=[]){let o=e.prepare("SELECT * FROM queue WHERE to_id = ? AND status IN ('pending', 'escalating', 'sent', 'retrieved') AND retraction_notice = 0 AND in_reply_to IS NULL").all(t),s=[];for(let i of o){if(xt(i,De(e,i.id)).lifecycle==="finished")continue;let c=e.prepare("SELECT 1 FROM queue WHERE from_id = ? AND to_id = ? AND created_ts > ? LIMIT 1").get(t,i.from_id,i.created_ts)!==void 0,l=R0(e,i,n);s.push({row:i,ageMs:r-Date.parse(i.created_ts),hasReplyTrafficSince:c,laterRelatedTraffic:l})}return s.sort((i,a)=>a.ageMs-i.ageMs),s}function Vg(e,t,r){let n=e.prepare("SELECT * FROM queue WHERE to_id = ? AND status = 'sent' AND escalation_only = 0").all(t),o=[];for(let s of n)xt(s,De(e,s.id)).lifecycleBasis==="dispatched"&&o.push({row:s,ageMs:r-Date.parse(s.sent_ts??s.created_ts)});return o.sort((s,i)=>i.ageMs-s.ageMs),o}function Jg(e,t,r){let n=Ee(r,"reason"),s=e.transaction(()=>{let i=e.prepare("SELECT * FROM queue WHERE id = ?").get(t);if(i===void 0)throw new C("NOT_FOUND",`Queue prompt ${t} does not exist`,3);if(i.status!=="sent")throw new C("INVALID_ARGUMENT",`Queue prompt ${t} is not in a redeliverable state (status: ${i.status}) -- only a dispatched-but-unconfirmed ('sent') row can be redelivered`,2);if(i.escalation_only)throw new C("INVALID_ARGUMENT",`Queue prompt ${t} is an operator-escalation row -- redelivery does not apply to that lane`,2);if(De(e,t)!==null)throw new C("CONFLICT",`Queue prompt ${t} already has a recorded answer -- nothing to redeliver`,4);if(i.retracted_ts!==null)throw new C("CONFLICT",`Queue prompt ${t} was retracted: ${i.retracted_reason??"(no reason recorded)"} -- nothing to redeliver`,4);return e.prepare("UPDATE queue SET status = 'pending', sent_ts = NULL WHERE id = ?").run(t),e.prepare("SELECT * FROM queue WHERE id = ?").get(t)}).immediate();return ot(e,s.to_id,"redelivery-requeued",Date.parse(me()),{note:`queue#${t}: ${n}`}),s}function ia(e,t,r,n){let o=e.prepare("SELECT * FROM queue WHERE from_id = ?").all(t),s=[];for(let i of o){let a=De(e,i.id);if(a===null)continue;let c=n-Date.parse(a.answered_at);Number.isNaN(c)||c>r||s.push({row:i,answer:a,ageMs:c})}return s.sort((i,a)=>i.ageMs-a.ageMs),s}function zg(e,t,r){e.prepare("UPDATE queue SET status = 'retrieved', retrieved_ts = COALESCE(retrieved_ts, ?) WHERE id = ?").run(r,t)}function Kg(e,t,r){let n=t.subject_id!==null?/^task:(\d+)$/.exec(t.subject_id):null;if(n!==null)try{let o=Number(n[1]),s=dt(e,o);s!==null&&s.blocked_on===t.to_id&&(mi(e,o,{clearBlockedOn:!0}),zt(e,o,{body:`blocked_on ("${t.to_id}") auto-cleared: escalation #${r} was answered.`}))}catch{}}function gn(e,t,r,n){let o=Ee(n,"answer");return e.transaction(()=>{let i=e.prepare("SELECT * FROM queue WHERE id = ?").get(t);if(i===void 0)throw new C("NOT_FOUND",`Queue prompt ${t} does not exist`,3);if(i.to_id!==r)throw new C("INVALID_ARGUMENT",`Queue prompt ${t} is not addressed to "${r}" -- cannot answer on another team's behalf`,2);if(i.status!=="pending"&&i.status!=="escalating"&&i.status!=="sent"&&i.status!=="retrieved")throw new C("INVALID_ARGUMENT",`Queue prompt ${t} is not in an answerable state (status: ${i.status}) -- cannot finish a prompt that is not currently open`,2);if(i.retracted_ts!==null)throw new C("INVALID_ARGUMENT",`Queue prompt ${t} was retracted by its sender (${i.retracted_reason??"no reason recorded"}) -- cannot answer a withdrawn prompt`,2);if(De(e,t)!==null)throw new C("CONFLICT",`Queue prompt ${t} already has a recorded answer`,4);let c=me();try{return e.prepare("INSERT INTO answers(prompt_queue_id, answer_text, answered_at, created_at) VALUES (?, ?, ?, ?)").run(t,o,c,c),zg(e,t,c),Kg(e,i,t),De(e,t)}catch(l){if(l instanceof C)throw l;let u=l&&typeof l=="object"&&"code"in l?String(l.code):void 0;throw u!==void 0&&u.startsWith("SQLITE_CONSTRAINT")?new C("CONFLICT",`Queue prompt ${t} already has a recorded answer`,4):new C("STORAGE_ERROR",l instanceof Error?l.message:String(l),1)}}).immediate()}function Yg(e,t,r,n){let o=Ee(n,"reason");return e.transaction(()=>{let i=e.prepare("SELECT * FROM queue WHERE id = ?").get(t);if(i===void 0)throw new C("NOT_FOUND",`Queue prompt ${t} does not exist`,3);if(i.to_id!=="operator")throw new C("INVALID_ARGUMENT",`Queue prompt ${t} is addressed to "${i.to_id}", not "operator" -- proxy resolution only exists for the operator's own un-owned inbox; ${i.to_id} must answer for itself via \`queue answer\``,2);if(i.status!=="pending"&&i.status!=="escalating"&&i.status!=="sent"&&i.status!=="retrieved")throw new C("INVALID_ARGUMENT",`Queue prompt ${t} is not in an answerable state (status: ${i.status}) -- cannot resolve a prompt that is not currently open`,2);if(i.retracted_ts!==null)throw new C("INVALID_ARGUMENT",`Queue prompt ${t} was retracted by its sender (${i.retracted_reason??"no reason recorded"}) -- cannot resolve a withdrawn prompt`,2);if(De(e,t)!==null)throw new C("CONFLICT",`Queue prompt ${t} already has a recorded answer`,4);let c=me();try{return e.prepare("INSERT INTO answers(prompt_queue_id, answer_text, answered_at, created_at) VALUES (?, ?, ?, ?)").run(t,`[resolved by proxy ${r}]: ${o}`,c,c),zg(e,t,c),Kg(e,i,t),De(e,t)}catch(l){if(l instanceof C)throw l;let u=l&&typeof l=="object"&&"code"in l?String(l.code):void 0;throw u!==void 0&&u.startsWith("SQLITE_CONSTRAINT")?new C("CONFLICT",`Queue prompt ${t} already has a recorded answer`,4):new C("STORAGE_ERROR",l instanceof Error?l.message:String(l),1)}}).immediate()}function Qg(e,t,r,n){let o=Ee(n,"answer");return e.transaction(()=>{let i=e.prepare("SELECT * FROM queue WHERE id = ?").get(t);if(i===void 0)throw new C("NOT_FOUND",`Queue prompt ${t} does not exist`,3);if(i.to_id!==r)throw new C("INVALID_ARGUMENT",`Queue prompt ${t} is not addressed to "${r}" -- cannot amend an answer on another team's behalf`,2);if(i.retracted_ts!==null)throw new C("INVALID_ARGUMENT",`Queue prompt ${t} was retracted by its sender (${i.retracted_reason??"no reason recorded"}) -- cannot amend an answer to a withdrawn prompt`,2);return Zg(e,t,o)}).immediate()}function Xg(e,t,r,n){let o=Ee(n,"reason");return e.transaction(()=>{let i=e.prepare("SELECT * FROM queue WHERE id = ?").get(t);if(i===void 0)throw new C("NOT_FOUND",`Queue prompt ${t} does not exist`,3);if(i.to_id!=="operator")throw new C("INVALID_ARGUMENT",`Queue prompt ${t} is addressed to "${i.to_id}", not "operator" -- proxy amendment only exists for the operator's own un-owned inbox; ${i.to_id} must amend for itself via \`queue answer --amend\``,2);if(i.retracted_ts!==null)throw new C("INVALID_ARGUMENT",`Queue prompt ${t} was retracted by its sender (${i.retracted_reason??"no reason recorded"}) -- cannot amend a resolution to a withdrawn prompt`,2);return Zg(e,t,`[resolved by proxy ${r}]: ${o}`)}).immediate()}function Zg(e,t,r){let n=De(e,t);if(n===null)throw new C("INVALID_ARGUMENT",`Queue prompt ${t} has no current answer to amend -- use \`queue answer\`/\`queue resolve\` for a first answer`,2);let o=me();return e.prepare("UPDATE answers SET superseded_at = ? WHERE id = ?").run(o,n.id),e.prepare("INSERT INTO answers(prompt_queue_id, answer_text, answered_at, created_at) VALUES (?, ?, ?, ?)").run(t,r,o,o),De(e,t)}var N0=/standing by|standby|\bready\b|on-call/i,I0=4*60*6e4,t_=5;function L0(e,t){if(e.length===0)return"";let r=e.slice(0,t_),n=r.map(({row:o,ageMs:s})=>` #${o.id} from ${o.from_id} (${fe(s)} ago) -- \`lmbee queue answer ${o.id} "<your reply>" --from ${t}\``);return e.length>r.length&&n.push(` ...and ${e.length-r.length} more (\`lmbee queue inbox ${t}\` lists all of them)`),`
|
|
359
359
|
|
|
360
360
|
(Also: you have ${e.length} request(s) awaiting a DURABLE response -- replying in chat/prose alone does NOT close these, only \`queue answer\` does:
|
|
361
361
|
${n.join(`
|
|
362
362
|
`)}
|
|
363
|
-
)`}var
|
|
364
|
-
`)[0]??"";return t.length>
|
|
363
|
+
)`}var e_=140,C0=4*60*6e4;function O0(e){let t=e.trim().split(`
|
|
364
|
+
`)[0]??"";return t.length>e_?`${t.slice(0,e_)}\u2026`:t}function D0(e){if(e.length===0)return"";let t=e.slice(0,t_).map(({row:r,answer:n,ageMs:o})=>` #${r.id} to ${r.to_id} (${fe(o)} ago) -- "${O0(n.answer_text)}"`);return e.length>t.length&&t.push(` ...and ${e.length-t.length} more`),`
|
|
365
365
|
|
|
366
366
|
(Also: ${e.length} of your own request(s) received an answer recently:
|
|
367
367
|
${t.join(`
|
|
368
368
|
`)}
|
|
369
|
-
)`}async function
|
|
370
|
-
`),null}}function
|
|
371
|
-
`)})}let u=new Set(n.stalledTeamNames??await Pn(e,t,r,n.heavyLock??l(),o,s)),d=[];function m(h){let g=qe(e,h.name);if(g===null||g.status==="BLOCKED"||
|
|
372
|
-
`)}}try{T?.()}catch(
|
|
373
|
-
`)}Uo(e,h.name,new Date().toISOString()),d.push(h.name)}}return d}import{readFileSync as
|
|
369
|
+
)`}async function M0(e,t){try{let r=Q(e),{turns:n}=await t(r,e.leadAlias,{lines:6}),o=[...n].reverse().find(s=>s.role==="assistant");return o?{text:o.text,ts:o.ts}:null}catch(r){return process.stderr.write(`[auto-continue] tail check failed for ${e.name} (treating as no reply available): ${r instanceof Error?r.message:String(r)}
|
|
370
|
+
`),null}}function P0(e,t,r){if(e===null)return!0;let n=Date.parse(e.replace(" ","T"));return Number.isFinite(n)?r-n>=t:!0}async function r_(e,t,r,n={}){let o=n.config??he,s=n.nowMs??Date.now(),i=n.fetchTailImpl??Fi,a=oa(n.promptsDir),c=n.readHeavyLockStatusImpl??ft;function l(){return c(n.heavyLockStatusPath,n.heavyLockPath,void 0,h=>{process.stderr.write(`[auto-continue] heavy-lock probe failed, treating conservatively as held: ${h.message}
|
|
371
|
+
`)})}let u=new Set(n.stalledTeamNames??await Pn(e,t,r,n.heavyLock??l(),o,s)),d=[];function m(h){let g=qe(e,h.name);if(g===null||g.status==="BLOCKED"||se(e,h.name)?.confirmed_done_ts||He(e,h.name,{fromAutopilot:!0}).length>0)return!1;let _=l();if(_.held&&(_.holder===null||_.holder.holder===h.name))return!1;try{let E=`${Q(h)}:${h.leadAlias}`;if(na(r,E,n.providerExhaustionBackoffMs))return!1}catch{}return!0}let f=n.clearAutoNudgeSuspendedImpl??Rm,p=n.recordAutoNudgeSuspendedImpl??xm;for(let h of t)if(!u.has(h.name)){f(e,h.name);continue}for(let h of t){if(!u.has(h.name)||(f(e,h.name),!m(h)))continue;let g=await M0(h,i);if(g!==null&&N0.test(g.text)&&!P0(g.ts,n.standbyStaleMs??I0,s)){p(e,h.name,"standby_reply_active",`last reply matches the standby pattern and is not yet stale: "${g.text.slice(0,200)}"`,new Date(s).toISOString());continue}if(!m(h))continue;let _=n.loadTeamTaskStateImpl??Re,E=n.deriveTaskAwareNudgeImpl??mp,y=null;try{y=_(e,Q(h),h.leadAlias)}catch{}let S,T;if(y!==null){let ne=await E(e,y,{backoffMs:o.cooldownMs});if(ne===null||(S=ne.message,T=ne.onSent,!m(h)))continue}else try{S=sa(a,h)}catch{continue}let x=(n.findOwedResponsesImpl??hn)(e,h.name,s);S+=L0(x,h.name);let A=(n.findRecentlyAnsweredForSenderImpl??ia)(e,h.name,C0,s);S+=D0(A);let L=(n.loadAutoNudgeRedirectImpl??$t)(e,h.name),w=L===null?h.name:`${L.companionTeam}:${L.workerAlias}`,b=L===null?h.name:L.companionTeam,N=L===null?h.leadAlias:L.workerAlias,D=L===null?h.repoPath:t.find(ne=>ne.name===b)?.repoPath??h.repoPath,ee=(n.resolveMemberProviderImpl??Vt)({repoPath:D,name:b},N);if(!(ee!==null&&(n.checkProviderDisabledImpl??it)(e,ee,s).disabled)){if(we(e,t,w,S,{from:"autopilot"}),L!==null){let ne=n.recordRedirectedDispatchImpl??ch;try{await ne(e,h.name,L,h.repoPath,new Date(s).toISOString())}catch(J){process.stderr.write(`[auto-continue] failed to record redirected dispatch for ${h.name}'s redirect to ${L.companionTeam}:${L.workerAlias} (nudge already sent, continuing): ${J instanceof Error?J.message:String(J)}
|
|
372
|
+
`)}}try{T?.()}catch(ne){process.stderr.write(`[auto-continue] onSent bookkeeping failed for ${h.name} (nudge already sent, continuing): ${ne instanceof Error?ne.message:String(ne)}
|
|
373
|
+
`)}Uo(e,h.name,new Date().toISOString()),d.push(h.name)}}return d}import{readFileSync as U0}from"node:fs";function n_(e){return`last_maintainer_wake:${e}`}function F0(e,t){return e.prepare("SELECT v FROM kv WHERE k = ?").get(n_(t))?.v??null}function q0(e,t,r){e.prepare("INSERT INTO kv(k, v) VALUES (?, ?) ON CONFLICT(k) DO UPDATE SET v = excluded.v").run(n_(t),r)}function j0(e,t,r,n){for(let o of t)if(o.autoNudge&&o.name!==n&&!se(e,o.name)?.confirmed_done_ts&&!je(o,r))return!0;return!1}function o_(e,t,r,n,o=a=>U0(a,"utf8"),s=Date.now(),i){let a=t.find(m=>m.name===n.teamName);if(!a||!B(a)||!(i??j0(e,t.filter(B),r,n.teamName))||je(a,r)||He(e,n.teamName,{fromAutopilot:!0}).length>0)return!1;let l=n.cooldownMs??he.cooldownMs,u=F0(e,n.teamName);if(u!==null&&s-Date.parse(u)<=l)return!1;let d;try{d=o(n.promptFile)}catch{return!1}return we(e,t,n.teamName,d,{from:"autopilot"}),q0(e,n.teamName,new Date(s).toISOString()),!0}function aa(e){return`blocked:${e}`}function s_(e,t,r,n){let o=r.map(s=>{let i=Cn(e,s.id),a=i!==null?`note: "${i.body}"`:"no note recorded";return`#${s.id} ("${s.title}", ${a})`});return`Team "${t}" has ${r.length} task(s) awaiting ${n}: ${o.join(", ")} -- \`lmauto tasks show <id>\` for full context. Resolve then \`lmauto tasks update <id> --status todo\` (or \`in_progress\`) to unblock, or escalate to the operator.`}async function i_(e,t,r,n,o=he,s=Date.now()){if(!n.some(a=>a.name===r))return[];let i=[];for(let a of t){if(a.name===r)continue;let c=se(e,a.name),l=c?.blocked_surfaced_ts?Date.parse(c.blocked_surfaced_ts):null;if(l!==null&&s-l<=o.cooldownMs)continue;let u;try{u=Q(a)}catch{continue}let d=Re(e,u,a.leadAlias);if(d===null)continue;let m=Mn(e,d);if(m.length===0)continue;let f=[],p=new Map;for(let g of m)if(g.blocked_on!=="operator"){if(g.blocked_on===null){f.push(g);continue}if(n.some(_=>_.name===g.blocked_on)){let _=p.get(g.blocked_on)??[];_.push(g),p.set(g.blocked_on,_)}else f.push(g)}let h=!1;f.length>0&&(new Set(He(e,r).map(_=>_.subject_id).filter(_=>_!==null)).has(aa(a.name))||(we(e,n,r,s_(e,a.name,f,"your decision"),{from:"autopilot",subject:aa(a.name)}),h=!0));for(let[g,_]of p)new Set(He(e,g).map(y=>y.subject_id).filter(y=>y!==null)).has(aa(a.name))||(we(e,n,g,s_(e,a.name,_,"your decision"),{from:"autopilot",subject:aa(a.name)}),h=!0);h&&(Sm(e,a.name,new Date().toISOString()),i.push(a.name))}return i}var H0=30*6e4;function B0(e){return`unresolvable-teamfile:${e}`}async function a_(e,t,r,n,o=he,s=Date.now(),i=H0,a=()=>new Date().toISOString()){if(!n.some(l=>l.name===r))return[];let c=[];for(let l of t){if(l.name===r)continue;try{Q(l),Lm(e,l.name);continue}catch{}Im(e,l.name,a());let u=Cm(e,l.name);if(u===null)continue;let d=s-Date.parse(u.first_observed_ts);if(d<i)continue;let m=u.surfaced_ts!==null?Date.parse(u.surfaced_ts):null;if(m!==null&&s-m<=o.cooldownMs)continue;let f=B0(l.name);if(He(e,r).map(_=>_.subject_id).filter(_=>_!==null).includes(f))continue;let h=Math.round(d/6e4),g=`[status-engine] Team "${l.name}" has had an unresolvable teamfile for over ${h} minutes -- expected "${l.name}.lmctl" under repo_path "${l.repoPath}" to exist. Every other per-team check silently skips this team until the registry entry or teamfile is fixed. \`lmauto teams\` to review the current registry.`;we(e,n,r,g,{from:"autopilot",subject:f}),Om(e,l.name,a()),c.push(l.name)}return c}var au="epic_closed_surfaced_ts";function ca(e,t){return e.transaction(()=>{let n=dt(e,t);if(n===null)return null;let o=e.prepare("SELECT * FROM notes WHERE entity_id = ? ORDER BY id DESC").all(t),s=!1;for(let i of o){let a=Kt(i.body);if(a!==null){if(a[Rr]===!0)break;typeof a[au]=="string"&&(s=!0)}}return{entity:n,status:n.status,alreadySurfacedThisEpisode:s}})()}function c_(e){return`epic-closed:${e}`}async function l_(e,t,r,n,o=he,s=Date.now(),i={}){let a=n.find(u=>u.name===r);if(!a)return[];if(!B(a))return[];let c=new Set(He(e,r).map(u=>u.subject_id).filter(u=>u!==null)),l=[];for(let u of t){if(u.name===r||c.has(c_(u.name)))continue;let d=se(e,u.name),m=d?.epic_closed_surfaced_ts?Date.parse(d.epic_closed_surfaced_ts):null;if(m!==null&&s-m<=o.cooldownMs)continue;let f;try{f=Q(u)}catch{continue}let p=Re(e,f,u.leadAlias);if(p===null)continue;let h=p.entities.filter(y=>y.kind==="epic"&&Dn.has(ue(y.status)));if(h.length===0)continue;i.beforeRevalidate?.();let g=Rt(Q(u)),_=!1;e.transaction(()=>{let y=[];for(let x of h){let I=ca(e,x.id);if(I===null)continue;let A=I.entity;Dn.has(ue(A.status))&&(A.owner_team_path!==g||A.owner_alias!==u.leadAlias||I.alreadySurfacedThisEpisode||y.push(A))}if(y.length===0)return;let S=y.map(x=>`#${x.id} ("${x.title}")`),T=`Team "${u.name}" closed ${y.length} epic(s): ${S.join(", ")} -- review with \`lmauto tasks show <id>\`. If more work remains, add task(s) + \`lmauto tasks update <id> --status open\` to reopen; otherwise no action needed, it stays closed.`;we(e,n,r,T,{from:"autopilot",subject:c_(u.name),escalationOnly:!0});let R=new Date().toISOString();for(let x of y)zt(e,x.id,{body:JSON.stringify({[au]:R})});Am(e,u.name,R),_=!0}).immediate(),_&&l.push(u.name)}return l}function u_(e){return`done-check:${e}`}var m_="consistency_alert_ts";function d_(e,t){return e.transaction(()=>{let n=dt(e,t);if(n===null)return null;let o=e.prepare("SELECT * FROM notes WHERE entity_id = ? ORDER BY id DESC").all(t),s=null,i=n.updated_at,a=!1;for(let c of o){let l=Kt(c.body);if(l!==null){if(l[Rr]===!0){s=c.id,typeof l.to=="string"&&ue(l.to)==="done"&&(i=c.created_at);break}typeof l[m_]=="string"&&(a=!0)}}return{entity:n,status:n.status,epochId:s,doneTransitionIso:i,alreadyAlertedThisEpisode:a}})()}async function W0(e,t,r){let n=new Date(Date.parse(t)-r).toISOString();for(let o of e)if(await wc(o,n))return!0;return!1}async function f_(e,t,r,n,o=he,s={}){let i=s.hasEvidenceAroundDoneImpl??W0,a=n.find(u=>u.name===r);if(!a)return[];if(!B(a))return[];let c=new Set(He(e,r).map(u=>u.subject_id).filter(u=>u!==null)),l=[];for(let u of t){if(u.name===r||c.has(u_(u.name)))continue;let d;try{d=Q(u)}catch{continue}let m=Re(e,d,u.leadAlias);if(m===null)continue;let f=new Map(m.entities.map(T=>[T.id,T])),p=m.entities.filter(T=>(T.kind==="task"||T.kind==="subtask")&&ue(T.status)==="done"&&!Qt(e,T,f));if(p.length===0)continue;let h=u.folders&&u.folders.length>0?u.folders:[u.repoPath],g=[];for(let T of p){let R=d_(e,T.id);if(R===null||R.alreadyAlertedThisEpisode)continue;await i(h,R.doneTransitionIso,o.idleThresholdMs)||g.push({entity:T,epochId:R.epochId})}if(g.length===0)continue;let _=Rt(d),E=new Date().toISOString(),y=!1;e.transaction(()=>{let T=[];for(let{entity:I,epochId:A}of g){let H=d_(e,I.id);if(H===null)continue;let L=H.entity;ue(L.status)==="done"&&(L.owner_team_path!==_||L.owner_alias!==u.leadAlias||Qt(e,L,new Map)||H.epochId!==A||H.alreadyAlertedThisEpisode||T.push(L))}if(T.length===0)return;let R=T.map(I=>`#${I.id} ("${I.title}")`),x=`Team "${u.name}" reported ${T.length} task(s) done with no commit/file-write found in its tracked path(s) around that time: ${R.join(", ")} -- please verify (\`lmauto tasks show <id>\` for details). This is a soft signal only; no action is needed if the work is genuinely fileless (design/coordination, or landed outside the team's tracked folders).`;we(e,n,r,x,{from:"autopilot",subject:u_(u.name),escalationOnly:!0});for(let I of T)zt(e,I.id,{body:JSON.stringify({[m_]:E})});y=!0}).immediate(),y&&l.push(u.name)}return l}function p_(e){return`fault:${e}`}async function h_(e,t,r,n,o=he,s=Date.now(),i={}){if(!n.some(l=>l.name===r))return[];let a=new Set(He(e,r).map(l=>l.subject_id).filter(l=>l!==null)),c=[];for(let l of t){if(l.name===r||a.has(p_(l.name)))continue;let u=se(e,l.name),d=u?.fault_surfaced_ts?Date.parse(u.fault_surfaced_ts):null;if(d!==null&&s-d<=o.cooldownMs)continue;let m;try{m=Q(l)}catch{continue}let f=Re(e,m,l.leadAlias);if(f===null)continue;let p=Po(e,f,o.cooldownMs,s);if(p.length===0)continue;i.beforeRevalidate?.();let h=!1;e.transaction(()=>{let _=[];for(let S of p){let T=dt(e,S.id);if(T===null)continue;let R=Po(e,{entities:[T]},o.cooldownMs,s,{team:Q(l),alias:l.leadAlias});R.length!==0&&_.push(R[0])}if(_.length===0)return;let E=_.map(S=>{let T=Cn(e,S.id),R=T!==null?`note: "${T.body}"`:"no note recorded";return`#${S.id} ("${S.title}", ${S.status}, ${R})`}),y=`Team "${l.name}" has ${_.length} task(s) stuck in a fault state past expected recovery: ${E.join(", ")} -- \`lmauto tasks show <id>\` for full context. The team is still being nudged with a back-off template on its own cadence; this is a distinct heads-up that the fault has persisted, not a request to intervene on the team's behalf.`;we(e,n,r,y,{from:"autopilot",subject:p_(l.name)}),vm(e,l.name,new Date().toISOString()),h=!0}).immediate(),h&&c.push(l.name)}return c}function g_(e,t,r,n,o,s=288e5){let i=new Date(o-n).toISOString(),a=new Date(o-s).toISOString();return e.prepare(`SELECT EXISTS(
|
|
374
374
|
SELECT 1 FROM tracked_invocation
|
|
375
375
|
WHERE target_teamfile = ? AND target_alias = ?
|
|
376
376
|
AND (
|
|
@@ -378,20 +378,20 @@ ${t.join(`
|
|
|
378
378
|
OR started_at >= ?
|
|
379
379
|
OR ended_at >= ?
|
|
380
380
|
)
|
|
381
|
-
) AS found`).get(t,r,a,i,i).found===1}function
|
|
382
|
-
`).filter(n=>n.trim().length>0).length}catch{return null}}import{execFile as
|
|
383
|
-
`).map(t=>t.trim()).filter(t=>t.startsWith("warning:")||t.startsWith("error:"))}import{existsSync as cu}from"node:fs";function lu(e,t,r=new Set){if(t.owner_team_path!==null)return{ownerTeamPath:t.owner_team_path,ownerAlias:t.owner_alias,explicit:!0};if(t.parent_id===null||r.has(t.id))return null;r.add(t.id);let n=dt(e,t.parent_id);if(n===null)return null;let o=lu(e,n,r);return o===null?null:{...o,explicit:!1}}function ua(e,t){if(t===null)return null;for(let r of e)if(B(r))try{if(Q(r)===t)return r.name}catch{continue}return null}function
|
|
384
|
-
`).filter(n=>n.length>0)}catch{return null}}async function du(e,t,r){try{let{stdout:n}=await r("git",["-C",e,"show",`HEAD:${t}`],{timeout:1e4,maxBuffer:ma});return n}catch{return null}}async function
|
|
381
|
+
) AS found`).get(t,r,a,i,i).found===1}function __(e){return`unknown:${e}`}async function w_(e,t,r,n,o=he,s=Date.now(),i=Wn){if(!n.some(l=>l.name===r))return[];let a;function c(){return a??=i(),a}try{return await G0(e,t,r,n,o,s,c)}finally{a!==void 0&&a.close()}}async function G0(e,t,r,n,o,s,i){let a=new Map(n.map(u=>[u.name,u])),c=new Set(He(e,r).map(u=>u.subject_id).filter(u=>u!==null)),l=[];for(let u of t){if(u===r||c.has(__(u))||c.has(u))continue;let d=se(e,u),m=d?.surfaced_ts?Date.parse(d.surfaced_ts):null;if(m!==null&&s-m<=o.cooldownMs)continue;let f=a.get(u);if(f?.repoPath!==void 0&&f?.leadAlias!==void 0){let S;try{S=Q({name:u,repoPath:f.repoPath})}catch{S=""}if(S!==""&&g_(i(),S,f.leadAlias,o.idleThresholdMs,s))continue}let p=a.get(u),h=p?.repoPath!==void 0&&p?.leadAlias!==void 0,g=h?Zc(e,{name:u,repoPath:p.repoPath,leadAlias:p.leadAlias}):qe(e,u)===null,_=d===null||d.progress_status==="ACTIVE",E=!g&&h&&_&&Qc(e,{name:u,repoPath:p.repoPath,leadAlias:p.leadAlias},o.idleThresholdMs,s);if(!g&&!E)continue;let y=g?`[status-engine] Team "${u}" is registered but has never been dispatched to -- needs S1 prep / a first dispatch, not a "no progress" investigation.`:`[status-engine] Team "${u}" has an in-progress lmtasks entity with no recent activity for over ${Math.round(o.idleThresholdMs/6e4)} minutes, though its own file-scan progress does not itself show stalled evidence (no scan yet, or last reported ACTIVE). This is OBJECTIVE lmtasks-activity evidence only -- please investigate (\`lmauto oversee ${u}\`) and either re-prep/re-dispatch it or confirm it is truly done.`;we(e,n,r,y,{from:"autopilot",subject:__(u)}),Tm(e,u,new Date().toISOString()),l.push(u)}return l}import{execFile as V0}from"node:child_process";import{promisify as J0}from"node:util";function ls(e){switch(e.kind){case"provider_disabled":return`provider ${e.provider} disabled (no dispatch attempted)`;case"parked":return"parked, confirmed done (no dispatch attempted)";case"presence_gated":return"a session is currently held (actively observed right now)";case"auto_nudge_disabled":return"auto-nudge disabled for this team (on-demand)";case"fleet_scan_paused":return"fleet-wide auto-scan paused";case"provider_exhausted_backoff":return`provider ${e.provider} in quota backoff (no dispatch attempted)`;case"no_continuous_observer":return"nothing has classified this team since (no continuous observer)"}}function la(e,t,r,n,o={}){let s=o.resolveMemberProviderImpl??Vt,i=o.checkProviderDisabledImpl??it,a=o.isProviderExhaustedImpl??na,c=o.allLocalTeams??[t],l=$t(e,t.name),u=l===null?t.name:l.companionTeam,d=l===null?t.leadAlias:l.workerAlias,m=l===null?t.repoPath:c.find(p=>p.name===u)?.repoPath??t.repoPath,f=s({repoPath:m,name:u},d);if(f!==null&&i(e,f,n).disabled)return{kind:"provider_disabled",provider:f};if(se(e,t.name)?.confirmed_done_ts)return{kind:"parked"};if(je(t,r))return{kind:"presence_gated"};if(!t.autoNudge)return{kind:"auto_nudge_disabled"};if(Ur(e)!==null)return{kind:"fleet_scan_paused"};try{let p=`${Q(t)}:${t.leadAlias}`;if(a(r,p))return{kind:"provider_exhausted_backoff",provider:s(t,t.leadAlias)??"unknown"}}catch{}return{kind:"no_continuous_observer"}}var y_=J0(V0),z0=new Set(["ENV-ERROR","NO-OUTPUT"]),K0=24*60*6e4,Y0=3;async function us(e,t,r=y_){try{return await r("lmctl",["tail",e,t,"--lines","1"],{timeout:1e4}),{sessionResolves:!0,provider:null,detail:"dispatch completes, session resolves; cause unknown"}}catch(n){let o=n&&typeof n=="object"&&"stderr"in n?String(n.stderr).trim():"",s=/session not found/i.test(o),i=/provider=([\w.-]+)/.exec(o);return{sessionResolves:!s,provider:s?i?.[1]??null:null,detail:o.length>0?o:"lmctl tail failed with no output"}}}async function E_(e,t,r,n,o,s={}){let i=s.execImpl??y_,a=s.whyNotObservedImpl??la,c=s.flappingWindowMs??K0,l=s.flappingOccurrenceThreshold??Y0,u=s.listRecentEventsByStatusImpl??Bs,d=[],m=[];for(let f of t){let p=Em(e,f.name);if(p.kind==="never-observed")continue;let h=a(e,f,r,n,s.whyNotObservedOptions);if(h.kind==="presence_gated")continue;let{value:g,observedAt:_,changedAt:E}=p,y=n-Date.parse(_),S=new Date(n-c).toISOString(),T=[...u(e,"ENV-ERROR",S,100),...u(e,"NO-OUTPUT",S,100)].filter(A=>A.team===f.name).sort((A,H)=>Date.parse(H.ts)-Date.parse(A.ts)),R=T.length>=l,x=z0.has(g.status)&&!Number.isNaN(y)&&y>=o;if(!x&&!R)continue;if(R&&!x){let A=T[0],H={kind:"flapping",team:f.name,mostRecentStatus:A.status,mostRecentAt:A.ts,occurrenceCount:T.length,windowMs:c};h.kind==="no_continuous_observer"?d.push(H):m.push({team:f.name,status:A.status,changedAt:A.ts,observedAt:_,ageMs:y,suspension:h});continue}let I=g.status;if(h.kind==="no_continuous_observer"){let A=null;if(I==="NO-OUTPUT")try{A=await us(Q(f),f.leadAlias,i)}catch{A=null}d.push({kind:"continuous",team:f.name,status:I,changedAt:E,observedAt:_,ageMs:y,cause:A})}else m.push({team:f.name,status:I,changedAt:E,observedAt:_,ageMs:y,suspension:h})}return d.sort((f,p)=>f.kind==="continuous"&&p.kind==="continuous"?p.ageMs-f.ageMs:0),m.sort((f,p)=>p.ageMs-f.ageMs),{unreachable:d,notObserved:m}}import{execFile as Q0}from"node:child_process";import{promisify as X0}from"node:util";var Z0=X0(Q0);async function b_(e,t=Z0){try{let{stdout:r}=await t("git",["-C",e,"status","--porcelain"],{timeout:1e4});return r.split(`
|
|
382
|
+
`).filter(n=>n.trim().length>0).length}catch{return null}}import{execFile as eL}from"node:child_process";import{promisify as tL}from"node:util";var rL=tL(eL);async function S_(e,t=rL){try{let{stderr:r}=await t("lmctl",["lint",e],{timeout:15e3});return T_(r)}catch(r){let n=r&&typeof r=="object"&&"stderr"in r?String(r.stderr):"",o=T_(n);return o.length>0?o:null}}function T_(e){return e.split(`
|
|
383
|
+
`).map(t=>t.trim()).filter(t=>t.startsWith("warning:")||t.startsWith("error:"))}import{existsSync as cu}from"node:fs";function lu(e,t,r=new Set){if(t.owner_team_path!==null)return{ownerTeamPath:t.owner_team_path,ownerAlias:t.owner_alias,explicit:!0};if(t.parent_id===null||r.has(t.id))return null;r.add(t.id);let n=dt(e,t.parent_id);if(n===null)return null;let o=lu(e,n,r);return o===null?null:{...o,explicit:!1}}function ua(e,t){if(t===null)return null;for(let r of e)if(B(r))try{if(Q(r)===t)return r.name}catch{continue}return null}function v_(e){return e.prepare("SELECT * FROM entities WHERE kind = 'epic' AND owner_team_path IS NULL").all().filter(r=>!Et(r.status))}function A_(e,t,r=cu){return ua(e,t)!==null?"registered":r(t)?"on_demand":"dangling"}function $_(e,t,r={}){let n=r.existsSyncImpl??cu,o=e.prepare("SELECT * FROM entities WHERE kind IN ('task', 'subtask')").all(),s=[];for(let i of o){if(Et(i.status))continue;let a=lu(e,i);if(a===null){s.push({entity:i,reason:i.parent_id===null?"no owner, and no parent epic to inherit from":"no owner, and its parent epic has none to inherit either"});continue}A_(t,a.ownerTeamPath,n)==="dangling"&&s.push({entity:i,reason:a.explicit?`owner "${a.ownerTeamPath}" does not resolve to any known team (no registered entry, no on-disk teamfile)`:`inherited owner "${a.ownerTeamPath}" (from its epic) does not resolve to any known team`})}return s}function k_(e){return e.prepare("SELECT * FROM entities WHERE status = 'blocked'").all().filter(r=>(mt(e,r.id,"outgoing").outgoing??[]).length===0)}function nL(e,t){return e.prepare("SELECT 1 FROM queue WHERE to_id = ? LIMIT 1").get(t)!==void 0}function x_(e,t,r,n=cu){let o=lu(e,r);if(o===null)return{ownerKind:"dangling",everContacted:null};let s=A_(t,o.ownerTeamPath,n);if(s==="dangling")return{ownerKind:s,everContacted:null};if(s==="on_demand")return{ownerKind:s,everContacted:!1};let i=ua(t,o.ownerTeamPath);return{ownerKind:s,everContacted:nL(e,i)}}function N_(e,t){let r=mt(e,t,"outgoing").outgoing??[];return new Set(r.filter(n=>!Et(n.status)).map(n=>n.id))}function da(e,t,r=new Set){if(r.has(t))return[];r.add(t);let o=(mt(e,t,"outgoing").outgoing??[]).filter(a=>!Et(a.status)),s=[];for(let a of o)(mt(e,a.id,"outgoing").outgoing??[]).filter(u=>!Et(u.status)).length===0?s.push(Oe(e,a.id)):s.push(...da(e,a.id,r));let i=new Set;return s.filter(a=>i.has(a.id)?!1:(i.add(a.id),!0))}function oL(e,t){let r=new Set([t]),n=(mt(e,t,"incoming").incoming??[]).map(s=>s.id),o=[];for(;n.length>0;){let s=n.pop();if(r.has(s))continue;r.add(s);let i=Oe(e,s);Et(i.status)||(o.push(i),n.push(...(mt(e,s,"incoming").incoming??[]).map(a=>a.id)))}return o}function R_(e){let t=e.trim().toLowerCase();return t==="todo"?0:t==="in_progress"||t==="in-progress"?1:2}function I_(e,t,r){let n=new Map;for(let s of t)for(let i of da(e,s.id))n.set(i.id,i);let o=[];for(let s of n.values()){let i=oL(e,s.id),a=new Set;for(let l of i){let u=ua(r,l.owner_team_path);u!==null&&a.add(u)}let c=x_(e,r,s);o.push({entity:s,downstreamCount:i.length,downstreamTeams:[...a].sort(),ownerKind:c.ownerKind,everContacted:c.everContacted})}return o.sort((s,i)=>{if(s.downstreamTeams.length!==i.downstreamTeams.length)return i.downstreamTeams.length-s.downstreamTeams.length;if(s.downstreamCount!==i.downstreamCount)return i.downstreamCount-s.downstreamCount;let a=R_(s.entity.status)-R_(i.entity.status);return a!==0?a:s.entity.id-i.entity.id}),o}import{execFile as sL}from"node:child_process";import{readFileSync as iL}from"node:fs";import{basename as aL,resolve as cL}from"node:path";import{promisify as lL}from"node:util";var uu=lL(sL),uL=[/\.env\.(example|sample|template)$/i],dL=[/\.pem$/,/\.key$/,/(^|\/)id_rsa$/,/(^|\/)id_ed25519$/,/(^|\/)id_ecdsa$/],mL=[/(^|\/)\.env(\..+)?$/,/(^|\/)\.mcp\.json$/,/(^|\/)\.netrc$/,/(^|\/)\.npmrc$/],C_=[/\b(?:api[_-]?key|app[_-]?key|secret|token|password|passwd|access[_-]?key)\b\s*[:=]\s*['"]?[A-Za-z0-9+/_.\-]{12,}/i,/\bsk-[A-Za-z0-9]{20,}\b/,/\bghp_[A-Za-z0-9]{30,}\b/,/\bAKIA[0-9A-Z]{16}\b/,/\bBearer\s+[A-Za-z0-9\-_.]{20,}/],fL=[...C_,/\b_(?:authToken|auth|password)\b\s*[:=]\s*['"]?[A-Za-z0-9+/_.\-]{8,}/i,/\bmachine\s+\S+[\s\S]{0,200}?\blogin\s+\S+[\s\S]{0,200}?\bpassword\s+\S+/i,/\bAWS_SECRET_ACCESS_KEY\b\s*[:=]?\s*['"]?[A-Za-z0-9+/]{20,}/i],ma=20*1024*1024;async function O_(e,t){try{let{stdout:r}=await t("git",["-C",e,"ls-files"],{timeout:1e4,maxBuffer:ma});return r.split(`
|
|
384
|
+
`).filter(n=>n.length>0)}catch{return null}}async function du(e,t,r){try{let{stdout:n}=await r("git",["-C",e,"show",`HEAD:${t}`],{timeout:1e4,maxBuffer:ma});return n}catch{return null}}async function D_(e,t=uu){let r=await O_(e,t);if(r===null)return null;let n=a=>!uL.some(c=>c.test(a)),o=r.filter(a=>dL.some(c=>c.test(a))&&n(a)),s=r.filter(a=>mL.some(c=>c.test(a))&&n(a)),i=[];for(let a of s){let c=await du(e,a,t);c!==null&&fL.some(l=>l.test(c))&&i.push(a)}return[...o,...i]}async function M_(e,t=uu){let r=await O_(e,t);if(r===null)return null;let n=r.filter(s=>s.endsWith(".lmctl")),o=[];for(let s of n){let i=await du(e,s,t);if(i===null)continue;let a=C_.reduce((c,l)=>c+(l.test(i)?1:0),0);a>0&&o.push({path:s,matchCount:a})}return o}var pL=[/(^|\/)template\.lmctl$/i,/(^|\/)examples\/.*\.lmctl$/i],L_=/_MEMBER_\b|\bsessionid\s*=\s*\S/;async function P_(e,t=uu){try{let[r,n]=await Promise.all([t("git",["-C",e,"ls-files"],{timeout:1e4,maxBuffer:ma}),t("git",["-C",e,"ls-files","--others","--exclude-standard"],{timeout:1e4,maxBuffer:ma})]),o=u=>!pL.some(d=>d.test(u)),s=u=>aL(u).includes(".lmctl")&&o(u),i=r.stdout.split(`
|
|
385
385
|
`).filter(u=>u.length>0&&s(u)),a=n.stdout.split(`
|
|
386
|
-
`).filter(u=>u.length>0&&s(u)),c=[];for(let u of i){let d=await du(e,u,t);d!==null&&
|
|
387
|
-
`),o=n.findIndex(l=>/Active account: true/.test(l));if(o===-1)return null;let a=n.slice(0,o).reverse().find(l=>/Logged in to .* account /.test(l))?.match(/account\s+(\S+)/)?.[1]??null;if(a===null)return null;let c;try{c=t(
|
|
386
|
+
`).filter(u=>u.length>0&&s(u)),c=[];for(let u of i){let d=await du(e,u,t);d!==null&&L_.test(d)&&c.push(u)}let l=[];for(let u of a){let d;try{d=iL(cL(e,u),"utf8")}catch{continue}L_.test(d)&&l.push(u)}return{tracked:c,unprotected:l}}catch{return null}}import{execFile as hL}from"node:child_process";import{statSync as U_}from"node:fs";import{homedir as gL}from"node:os";import{join as F_}from"node:path";import{promisify as _L}from"node:util";var mu=_L(hL);var wL="mike.ma@lmctl.com",fu="mike-lmctl";async function q_(e,t=mu){let r,n;try{r=(await t("git",["-C",e,"config","user.name"],{timeout:1e4})).stdout.trim()||null}catch{r=null}try{n=(await t("git",["-C",e,"config","user.email"],{timeout:1e4})).stdout.trim()||null}catch{n=null}return r===null&&n===null?null:{name:r,email:n,matchesPolicy:n===wL}}var yL=6e4,fa;async function pa(e=mu,t=Date.now(),r=U_){let n=e===mu&&r===U_;if(n&&fa!==void 0&&t-fa.atMs<yL)return fa.result;let o=await bL(e,r);return n&&(fa={result:o,atMs:t}),o}function EL(){let e=process.env.GH_CONFIG_DIR;return e?F_(e,"hosts.yml"):F_(gL(),".config","gh","hosts.yml")}async function bL(e,t){let r;try{r=(await e("gh",["auth","status"],{timeout:1e4})).stdout}catch(l){let u=l&&typeof l=="object"&&"stdout"in l?String(l.stdout):"";if(u.length===0)return null;r=u}let n=r.split(`
|
|
387
|
+
`),o=n.findIndex(l=>/Active account: true/.test(l));if(o===-1)return null;let a=n.slice(0,o).reverse().find(l=>/Logged in to .* account /.test(l))?.match(/account\s+(\S+)/)?.[1]??null;if(a===null)return null;let c;try{c=t(EL()).mtime.toISOString()}catch{c=null}return{account:a,matchesPolicy:a===fu,hostsFileChangedAt:c}}var TL=7*24*60*6e4,SL=500,vL=3*60*6e4,AL=3*60*6e4,ds=4*60*6e4,$L=24*60*6e4,kL=48*60*6e4,xL=24*60*6e4,RL=20,hu=24*60*6e4;function NL(e,t){let r=fe(t);return`${t>hu?`possible ${e}`:e} as of ${r} ago (not re-observed)`}var IL=7*24*60*6e4,LL=24*60*6e4;function CL(e,t,r,n,o){if(e?.confirmed_done_ts)return{kind:"confirmed-done",confirmedDoneTs:e.confirmed_done_ts};if(r!==null){let i=n-Date.parse(r);if(Number.isFinite(i)&&i<=LL)return null}else return o!==void 0&&xc(o)===0?{kind:"unseeded"}:{kind:"never-active"};if(t===null)return{kind:"no-state"};if(t.status!=="ACTIVE")return{kind:"self-report",status:t.status,changedTs:t.changed_ts};let s=n-Date.parse(t.changed_ts);return!Number.isFinite(s)||s>IL?{kind:"self-report",status:t.status,changedTs:t.changed_ts}:null}function OL(e,t){let r=e.teams.filter(B);return t===void 0?r:r.filter(n=>n.name===t)}function DL(e,t,r){let n=r(e);if(n.length===0)return null;let o=[],s=[];for(let i of n)i.provider!==null&&t.has(i.provider)?o.push({alias:i.alias,provider:i.provider}):s.push({alias:i.alias,provider:i.provider});return{totalMembers:n.length,quiescedMembers:o,liveMembers:s}}async function ha(e,t={}){let r=e.db.db,n=t.config??he,o=t.nowMs??Date.now(),s=OL(e,t.team),i=t.awaitingReviewThresholdMs??Kc,a=[],c=[],l=[],u=[],d=[],m=new Set(cs(r,o).map(F=>F.row.subject_id).filter(F=>F!==null)),f=[],p=[],h=[],g=[],_=[],E=[],y=t.countDirtyGitFilesImpl??b_,S=[],T=t.lintTeamfileWarningsImpl??S_,R=[],x=[],I=[],A=[],H=[],L=t.findNeverTrackFilesImpl??D_,w=t.findSecretBearingTeamfilesImpl??M_,b=t.checkTeamfileTrackingImpl??P_,N=t.checkRepoGitIdentityImpl??q_,D=t.resolveMemberProviderImpl??Vt,W=t.listTeamMembersImpl??tn,ee=[],ne=!1;try{ee=Go(r).filter(F=>it(r,F.provider,o).disabled)}catch{ne=!0}let J=Lg(r,o),oe=Cg(r),k=null;try{k=Og(r,o)}catch{k=null}let O=new Set(ee.map(F=>F.provider)),$=[],q=e.teams.filter(B),U=e.teams.map(F=>F.name);for(let F of s){let _e;try{_e=Q(F)}catch{continue}let Fe=await T(_e);Fe!==null&&Fe.length>0&&S.push({team:F.name,warnings:Fe});let ut=await L(F.repoPath);ut!==null&&ut.length>0&&R.push({team:F.name,files:ut});let Sn=await w(F.repoPath);Sn!==null&&Sn.length>0&&x.push({team:F.name,files:Sn});let Ft=await b(F.repoPath);Ft!==null&&(Ft.tracked.length>0&&I.push({team:F.name,files:Ft.tracked}),Ft.unprotected.length>0&&A.push({team:F.name,files:Ft.unprotected}));let Xr=await N(F.repoPath);Xr!==null&&!Xr.matchesPolicy&&H.push({team:F.name,identity:{name:Xr.name,email:Xr.email}});let qt=O.size>0?DL(F,O,W):null;if(O.size>0){let ce=$t(r,F.name),jt=ce===null?F.name:ce.companionTeam,rc=ce===null?F.leadAlias:ce.workerAlias,Ro=ce===null?F.repoPath:q.find(No=>No.name===jt)?.repoPath??F.repoPath,Zr=D({repoPath:Ro,name:jt},rc);if(Zr!==null&&O.has(Zr)){let No=ee.find(XA=>XA.provider===Zr)?.expiresAt??null;$.push({team:F.name,provider:Zr,expiresAt:No,totalMembers:qt?.totalMembers??1,liveMembers:qt?.liveMembers??[]})}}let ec=hn(r,F.name,o,U);ec.length>0&&l.push({team:F.name,rows:ec,...qt!==null&&qt.quiescedMembers.length>0?{quiescedMembers:qt.quiescedMembers,totalMembers:qt.totalMembers}:{}});let rm=ec.filter(ce=>ce.row.status==="sent"||ce.row.status==="retrieved");if(rm.length>0){let ce=r.prepare("SELECT MAX(created_ts) AS ts FROM queue WHERE from_id = ?").get(F.name),jt=CL(se(r,F.name),qe(r,F.name),ce.ts,o,F);jt!==null&&d.push({team:F.name,rows:rm,reason:jt})}let nm=ia(r,F.name,ds,o);nm.length>0&&u.push({team:F.name,rows:nm});let Ar=Re(r,_e,F.leadAlias);if(Ar===null)continue;for(let ce of Mn(r,Ar)){let jt;try{let Ro=N_(r,ce.id),Zr=da(r,ce.id).filter(No=>!Ro.has(No.id));Zr.length>0&&(jt=Zr)}catch{jt=void 0}let rc=fi(r,ce.id);a.push({team:F.name,entity:ce,blockedSinceTs:rc,...jt!==void 0?{roots:jt}:{}}),ce.blocked_on==="operator"?m.has(`task:${ce.id}`)||c.push({team:F.name,entity:ce,blockedOn:"operator",reason:"operator-uncorrelated"}):ce.blocked_on!==null&&!e.teams.some(Ro=>Ro.name===ce.blocked_on)&&c.push({team:F.name,entity:ce,blockedOn:ce.blocked_on,reason:"team-unresolvable"})}for(let ce of Po(r,Ar,n.cooldownMs,o))f.push({team:F.name,entity:ce});for(let ce of up(r,Ar,i,o))p.push({team:F.name,task:ce});for(let ce of dp(r,Ar,o))h.push({team:F.name,task:ce});for(let ce of Ar.entities)ce.kind==="epic"&&ce.needs_review===1&&yi(ce)&&g.push({team:F.name,entity:ce});for(let ce of Ar.entities)ce.kind!=="epic"||!Dn.has(ue(ce.status))||ca(r,ce.id)?.alreadySurfacedThisEpisode||_.push({team:F.name,entity:ce});let tc=Ar.entities.filter(ce=>ue(ce.status)==="todo");if(tc.length>0){let ce=await y(F.repoPath);ce!==null&&ce>0&&E.push({team:F.name,dirtyCount:ce,todoCount:tc.length,exampleEntity:tc[0]})}}let G=await(t.fetchReportImpl??ke)(),ie=t.heavyLockImpl?t.heavyLockImpl():ft(void 0,void 0,void 0,()=>{}),be=await Pn(r,s,G,ie,n,o,{readOnly:!0}),ae=new Set($.map(F=>F.team)),M=be.filter(F=>!ae.has(F)),j=t.findPersistentDispatchFailuresImpl??E_,{unreachable:Y,notObserved:z}=await j(r,s,G,o,ds),re=[];for(let F of M){let _e=se(r,F);if(_e?.miniplayer_verdict_label&&_e.miniplayer_verdict_reason&&_e.miniplayer_verdict_ts){let Fe=qe(r,F),ut=_e.miniplayer_verdict_label!=="genuinely_done"&&Fe?.status==="DONE"?{changedTs:Fe.changed_ts}:void 0;re.push({team:F,label:_e.miniplayer_verdict_label,reason:_e.miniplayer_verdict_reason,ts:_e.miniplayer_verdict_ts,...ut!==void 0?{selfReportedDone:ut}:{}})}}let te=[];for(let F of s){let _e=se(r,F.name);_e?.hung_holder_flagged_ts&&_e.hung_holder_reason&&te.push({team:F.name,reason:_e.hung_holder_reason,flaggedTs:_e.hung_holder_flagged_ts})}let de=Nm(r).map(F=>({team:F.team,reason:F.reason,detail:F.detail,suspendedAt:F.suspended_at})),xe=t.blockedSelfReportUrgentThresholdMs??$L,Se=t.blockedSelfReportUnconfirmedThresholdMs??kL,K=[];for(let F of s){let _e=qe(r,F.name);if(_e?.status==="BLOCKED"){let Fe=o-Date.parse(_e.changed_ts),ut=Fe>=Se;K.push({team:F.name,changedTs:_e.changed_ts,ageMs:Fe,urgent:!ut&&Fe>=xe,unconfirmed:ut})}}K.sort((F,_e)=>_e.ageMs-F.ageMs);let Te=t.orphanReapCandidateWindowMs??TL,ze=new Date(o-Te).toISOString(),Ut=Bs(r,Ll,ze,SL).filter(F=>t.team===void 0||F.team===t.team).map(F=>({team:F.team,ts:F.ts,reason:F.note??"(no reason recorded)"})),V=t.maintainer===void 0?null:[...He(r,t.maintainer),...li(r,t.maintainer)].sort((F,_e)=>F.id-_e.id).filter(F=>F.from_id!=="autopilot"),ye=t.maintainer===void 0?[]:Wg(r,t.maintainer,o).map(F=>({row:F.row,constituentCount:pn(r,F.row)})),lt=t.maintainer===void 0?[]:cs(r,o).map(F=>{let _e=pn(r,F.row),Fe=as(r,F.row),ut=F.ageMs>=ds||_e>=2&&F.row.sent_ts===null;return{row:F.row,constituentCount:_e,retractedCount:Fe,urgent:ut}}),rt=t.maintainerStaleThresholdMs??vL,_t=[];if(t.maintainer!==void 0&&V!==null){let _e=se(r,t.maintainer)?.last_cli_activity_ts??null,Fe=mh(_e,o),ut=!Rl(_e,rt,o),Sn=V[0],Ft=Sn?o-Date.parse(Sn.created_ts):null,Xr=Ft!==null&&Ft>rt;if(ut||Xr){let qt=[];ut&&qt.push(_e===null?"no CLI activity ever recorded":`no CLI activity in ${fe(Fe)}`),Xr&&qt.push(`oldest queued item is ${fe(Ft)} old`),_t.push({team:t.maintainer,reason:qt.join("; "),ageMs:Fe===null?1/0:Math.max(Fe,Ft??0)})}}let Ke;if(t.team===void 0)Ke=a.map(F=>F.entity);else{Ke=[];for(let F of e.teams.filter(B)){let _e;try{_e=Q(F)}catch{continue}let Fe=Re(r,_e,F.leadAlias);Fe!==null&&Ke.push(...Mn(r,Fe))}}let Tn=I_(r,Ke,e.teams),Sr=v_(r),ur=$_(r,e.teams),nt=k_(r),vr=[];for(let F of e.teams.filter(B)){try{Q(F)}catch{continue}xc(F)===0&&vr.push({team:F.name,repoPath:F.repoPath})}let xo=t.stuckProcessingThresholdMs??AL,Ps=t.stuckProcessingMaxAgeMs??xL,Za=t.maintainer!==void 0&&t.stuckProcessingFleetWide!==!0?t.maintainer:void 0,QA=Bg(r,{minAgeMs:xo,maxAgeMs:Ps,fromId:Za},o).map(F=>({queueId:F.row.id,fromId:F.row.from_id,toId:F.row.to_id,ageMs:F.ageMs,constituentCount:pn(r,F.row)}));return{blocked:a,blockedOnUnresolved:c,owedAnswers:l,recentlyAnsweredForSender:u,parkedTeamsWithOwedPrompts:d,awaitingDecision:f,awaitingReview:p,stalled:M,stalledVerdicts:re,hungHolders:te,autoNudgeSuspended:de,blockedSelfReports:K,flaggedEpics:g,closedEpicsToReview:_,orphanReapCandidates:Ut,maintainerStale:_t,blockingRoots:Tn,epicsWithoutOwner:Sr,unresolvableOwnerEntities:ur,untrackedBlockers:nt,unseededTeams:vr,stuckProcessing:QA,inbox:V,memory:(t.readMemoryAvailabilityImpl??Do)(),operatorPrompts:ye,operatorEscalations:lt,uncommittedWork:E,teamfileLintWarnings:S,expiredHolds:h,neverTrackFiles:R,secretBearingTeamfiles:x,trackedTeamfiles:I,unprotectedTeamfiles:A,gitIdentityMismatches:H,activeGhAccount:await(t.checkActiveGhAccountImpl??pa)(),disabledProviders:ee,providerDisableReadFailed:ne,quiescedByProviderDisable:$,staleAutoScanPause:k,persistentDispatchFailures:Y,notObserved:z,rateLimitPolicyHealth:J,rateLimitLevelWarnings:oe}}function pu(e){return` ${e.team}: #${e.entity.id} ("${e.entity.title}")`}function j_(e){return e.length===0?"":`
|
|
388
388
|
later traffic worth checking before ruling on this (not proof it was answered): ${e.map(r=>`#${r.row.id} ${r.row.from_id}->${r.row.to_id} (${ge(r.row.created_ts)}, via ${r.matchedTeam})`).join("; ")}`}function ms(e,t={}){if(t.json)return JSON.stringify(e);let r=[];if(e.operatorPrompts.length>0){let c=Date.now(),l=e.operatorPrompts.map(m=>` #${m.row.id} -- sent ${fe(c-Date.parse(m.row.created_ts))} ago, unanswered`+(m.constituentCount>1?` (${m.constituentCount} merged into this one)`:"")),u=e.operatorPrompts.reduce((m,f)=>m+f.constituentCount,0),d=u===e.operatorPrompts.length?`${e.operatorPrompts.length}`:`${u} in ${e.operatorPrompts.length} thread${e.operatorPrompts.length===1?"":"s"}`;r.push(`OPERATOR MESSAGE, UNANSWERED (${d}):
|
|
389
389
|
${l.join(`
|
|
390
390
|
`)}`)}if(e.operatorEscalations.length>0){let c=Date.now(),l=f=>{let p=f.constituentCount>1?` (${f.constituentCount} merged into this one${f.retractedCount>0?`, ${f.retractedCount} retracted`:""})`:"";return` #${f.row.id} from ${f.row.from_id} -- sent ${fe(c-Date.parse(f.row.created_ts))} ago, unanswered${p}`},u=f=>{let p=f.reduce((h,g)=>h+g.constituentCount,0);return p===f.length?`${f.length}`:`${p} in ${f.length} thread${f.length===1?"":"s"}`},d=e.operatorEscalations.filter(f=>f.urgent),m=e.operatorEscalations.filter(f=>!f.urgent);d.length>0&&r.push(`ESCALATED TO OPERATOR, URGENT (${u(d)}) -- past 4h old or an undelivered pileup:
|
|
391
391
|
${d.map(l).join(`
|
|
392
392
|
`)}`),m.length>0&&r.push(`ESCALATED TO OPERATOR, UNANSWERED (${u(m)}):
|
|
393
393
|
${m.map(l).join(`
|
|
394
|
-
`)}`)}if(e.persistentDispatchFailures.length>0){let c=e.persistentDispatchFailures.map(l=>{if(l.kind==="flapping"){let d=fe(l.windowMs);return` ${l.team}: flapping -- ${l.occurrenceCount} occurrences of ${l.mostRecentStatus} in the last ${d}, most recently at ${l.mostRecentAt}`}let u=
|
|
394
|
+
`)}`)}if(e.persistentDispatchFailures.length>0){let c=e.persistentDispatchFailures.map(l=>{if(l.kind==="flapping"){let d=fe(l.windowMs);return` ${l.team}: flapping -- ${l.occurrenceCount} occurrences of ${l.mostRecentStatus} in the last ${d}, most recently at ${l.mostRecentAt}`}let u=NL(l.status,l.ageMs);if(l.status==="NO-OUTPUT"&&l.cause!==null){let d=l.cause.sessionResolves?"dispatch completes, session resolves; cause unknown":`session not found${l.cause.provider?` (provider=${l.cause.provider})`:""}; member needs a refresh`;return` ${l.team}: ${u} -- ${d}`}return` ${l.team}: ${u}`});r.push(`UNREACHABLE (${e.persistentDispatchFailures.length}):
|
|
395
395
|
${c.join(`
|
|
396
396
|
`)}`)}if(e.notObserved.length>0){let c=e.notObserved.map(l=>{let u=fe(l.ageMs),d=l.ageMs>hu?`possible ${l.status}`:l.status;return` ${l.team}: last checked ${u} ago, ${d} then -- ${ls(l.suspension)}`});r.push(`NOT OBSERVED (${e.notObserved.length}):
|
|
397
397
|
${c.join(`
|
|
@@ -419,7 +419,7 @@ ${c.join(`
|
|
|
419
419
|
${c.join(`
|
|
420
420
|
`)}`)}if(e.blockedOnUnresolved.length>0){let c=e.blockedOnUnresolved.map(l=>{let u=l.reason==="operator-uncorrelated"?"claims blocked on the operator, no matching unresolved escalation found":`claims blocked on team "${l.blockedOn}", which is not currently registered`;return` ${l.team}: #${l.entity.id} ("${l.entity.title}") -- ${u}`});r.push(`BLOCKED-ON CLAIM UNRESOLVED (${e.blockedOnUnresolved.length}) -- nothing is currently re-prompting anyone about ${e.blockedOnUnresolved.length===1?"this task":"these tasks"}, look directly:
|
|
421
421
|
${c.join(`
|
|
422
|
-
`)}`)}if(e.owedAnswers.length>0){let c=[...e.owedAnswers].sort((m,f)=>{let p=m.rows.some(g=>!g.hasReplyTrafficSince)?0:1,h=f.rows.some(g=>!g.hasReplyTrafficSince)?0:1;return p-h}),l=c.filter(m=>m.rows.some(f=>!f.hasReplyTrafficSince)).length,u=c.length-l,d=c.map(m=>{let f=m.rows.filter(g=>!g.hasReplyTrafficSince),p=m.rows.filter(g=>g.hasReplyTrafficSince),h=[];if(f.length>0){let g=f.filter(E=>E.row.status!=="retrieved"),_=f.filter(E=>E.row.status==="retrieved");if(g.length>0){let E=g[0];h.push(`${g.length} NEVER RECEIVED (undelivered-to-inbox, not a decision delay) -- oldest #${E.row.id} from ${E.row.from_id} (${fe(E.ageMs)} ago), status ${E.row.status}`+
|
|
422
|
+
`)}`)}if(e.owedAnswers.length>0){let c=[...e.owedAnswers].sort((m,f)=>{let p=m.rows.some(g=>!g.hasReplyTrafficSince)?0:1,h=f.rows.some(g=>!g.hasReplyTrafficSince)?0:1;return p-h}),l=c.filter(m=>m.rows.some(f=>!f.hasReplyTrafficSince)).length,u=c.length-l,d=c.map(m=>{let f=m.rows.filter(g=>!g.hasReplyTrafficSince),p=m.rows.filter(g=>g.hasReplyTrafficSince),h=[];if(f.length>0){let g=f.filter(E=>E.row.status!=="retrieved"),_=f.filter(E=>E.row.status==="retrieved");if(g.length>0){let E=g[0];h.push(`${g.length} NEVER RECEIVED (undelivered-to-inbox, not a decision delay) -- oldest #${E.row.id} from ${E.row.from_id} (${fe(E.ageMs)} ago), status ${E.row.status}`+j_(E.laterRelatedTraffic))}if(_.length>0){let E=_[0];h.push(`${_.length} unanswered -- no reply traffic from ${m.team} since the prompt, oldest #${E.row.id} from ${E.row.from_id} (${fe(E.ageMs)} ago)`+j_(E.laterRelatedTraffic))}}if(p.length>0){let g=p.map(_=>`#${_.row.id}`).join(", ");h.push(`${p.length} likely answered in prose (reply traffic exists since the prompt), row(s) unclosed: needs queue answer ${g}`)}if(m.quiescedMembers!==void 0&&m.totalMembers!==void 0){let g=new Map;for(let E of m.quiescedMembers){let y=g.get(E.provider)??[];y.push(E.alias),g.set(E.provider,y)}let _=[...g.entries()].map(([E,y])=>`${E}: ${y.join(", ")}`).join("; ");h.push(`${m.quiescedMembers.length}/${m.totalMembers} members quiesced by a disabled provider (${_})`)}return` ${m.team}: ${h.join("; ")}`});r.push(`TEAMS OWING A DURABLE ANSWER (${l} owed, ${u} unclosed-but-answered) -- for the RECIPIENT, a prose/chat reply alone does not close these; for reading fleet health, reply traffic since the prompt means likely answered:
|
|
423
423
|
${d.join(`
|
|
424
424
|
`)}`)}if(e.recentlyAnsweredForSender.length>0){let c=e.recentlyAnsweredForSender.map(l=>{let u=l.rows[0],d=u.answer.answer_text.trim().split(`
|
|
425
425
|
`)[0].slice(0,140);return` ${l.team}: ${l.rows.length} answer(s) received, newest #${u.row.id} to ${u.row.to_id} (${fe(u.ageMs)} ago) -- "${d}"`});r.push(`ANSWERS RECEIVED, NOT YET NOTICED (${e.recentlyAnsweredForSender.length}):
|
|
@@ -458,7 +458,7 @@ ${c.join(`
|
|
|
458
458
|
${c.join(`
|
|
459
459
|
`)}`)}if(e.unseededTeams.length>0){let c=e.unseededTeams.map(l=>` ${l.team} (${l.repoPath}) -- seed it (\`lctl seed\`), not a nudge or state set`);r.push(`UNSEEDED (${e.unseededTeams.length}) -- no sessionid on any _MEMBER_ line, nothing can ever reach these:
|
|
460
460
|
${c.join(`
|
|
461
|
-
`)}`)}if(e.stuckProcessing.length>0){let c=e.stuckProcessing.slice(0,
|
|
461
|
+
`)}`)}if(e.stuckProcessing.length>0){let c=e.stuckProcessing.slice(0,RL),l=c.map(m=>` #${m.queueId} ${m.fromId} -> ${m.toId} -- processing for ${fe(m.ageMs)}, no answer`+(m.constituentCount>1?` (${m.constituentCount} merged into this one)`:"")),u=e.stuckProcessing.length-c.length,d=u>0?`
|
|
462
462
|
...and ${u} more (use --json for the full list)`:"";r.push(`stuck processing (${e.stuckProcessing.length}):
|
|
463
463
|
${l.join(`
|
|
464
464
|
`)}${d}`)}if(e.maintainerStale.length>0){let c=e.maintainerStale.map(l=>` ${l.team}: ${l.reason}`);r.push(`maintainer stale (${e.maintainerStale.length}):
|
|
@@ -471,106 +471,106 @@ ${e.inbox.map(c=>` #${c.id} from ${c.from_id}`).join(`
|
|
|
471
471
|
|
|
472
472
|
${o}`;if(e.activeGhAccount===null||e.activeGhAccount.matchesPolicy)return s;let i=e.activeGhAccount.hostsFileChangedAt!==null?` (hosts.yml last changed ${e.activeGhAccount.hostsFileChangedAt})`:"";return`${`!!! ACTIVE GH ACCOUNT POLICY MISMATCH: "${e.activeGhAccount.account}" is active on this machine -- every future github.com push authenticates as this account, for every repo.${i} !!!`}
|
|
473
473
|
|
|
474
|
-
${s}`}async function
|
|
474
|
+
${s}`}async function H_(e,t,r,n={}){let o={db:{path:"",db:e,close:()=>{}},teamsConfPath:"",teams:[...t]},s=await ha(o,{maintainer:r,...n.config!==void 0?{config:n.config}:{},...n.nowMs!==void 0?{nowMs:n.nowMs}:{},...n.awaitingReviewThresholdMs!==void 0?{awaitingReviewThresholdMs:n.awaitingReviewThresholdMs}:{},...n.maintainerStaleThresholdMs!==void 0?{maintainerStaleThresholdMs:n.maintainerStaleThresholdMs}:{},...n.fetchReportImpl!==void 0?{fetchReportImpl:n.fetchReportImpl}:{},...n.heavyLockImpl!==void 0?{heavyLockImpl:n.heavyLockImpl}:{},...n.findNeverTrackFilesImpl!==void 0?{findNeverTrackFilesImpl:n.findNeverTrackFilesImpl}:{},...n.findSecretBearingTeamfilesImpl!==void 0?{findSecretBearingTeamfilesImpl:n.findSecretBearingTeamfilesImpl}:{},...n.checkRepoGitIdentityImpl!==void 0?{checkRepoGitIdentityImpl:n.checkRepoGitIdentityImpl}:{},...n.checkActiveGhAccountImpl!==void 0?{checkActiveGhAccountImpl:n.checkActiveGhAccountImpl}:{},...n.resolveMemberProviderImpl!==void 0?{resolveMemberProviderImpl:n.resolveMemberProviderImpl}:{},...n.lintTeamfileWarningsImpl!==void 0?{lintTeamfileWarningsImpl:n.lintTeamfileWarningsImpl}:{}}),i=(n.readMemoryAvailabilityImpl??Do)(),a=s.blocked.length===0&&s.awaitingDecision.length===0&&s.awaitingReview.length===0&&s.stalled.length===0&&s.hungHolders.length===0&&s.flaggedEpics.length===0&&s.closedEpicsToReview.length===0&&(s.inbox===null||s.inbox.length===0)&&s.operatorPrompts.length===0&&s.operatorEscalations.length===0&&s.uncommittedWork.length===0&&s.expiredHolds.length===0&&s.neverTrackFiles.length===0&&s.secretBearingTeamfiles.length===0&&s.gitIdentityMismatches.length===0&&(s.activeGhAccount===null||s.activeGhAccount.matchesPolicy)&&!s.providerDisableReadFailed&&s.quiescedByProviderDisable.length===0&&s.blockedOnUnresolved.length===0&&s.staleAutoScanPause===null&&s.persistentDispatchFailures.every(u=>u.kind!=="continuous")&&s.parkedTeamsWithOwedPrompts.length===0&&s.rateLimitPolicyHealth===null,c=ii(i),l=c===null?ms(s):`${ms(s)}
|
|
475
475
|
|
|
476
|
-
${c}`;return{attention:s,memory:i,isEmpty:a,rendered:l}}var
|
|
476
|
+
${c}`;return{attention:s,memory:i,isEmpty:a,rendered:l}}var FL=18e5,qL={watch:{first:!1,active:[],wentIdle:[],newlyActive:[],wake:!1,why:"nochange"},stalled:[],maintainerWoken:!1,autoContinued:[],surfacedUnknown:[],surfacedBlocked:[],surfacedDoneConsistency:[],surfacedUnresolvableTeamfiles:[],surfacedFault:[],surfacedClosedEpics:[],escalated:[],autoRedelivered:[],woken:[],firedCronJobs:[],rateLimitCollected:null,rateLimitPolicyEvaluations:[]};function B_(e){let t=e.fetchReport??ke,r=e.readHeavyLockStatusImpl??ft,n=e.heavyLockStatusPath??Kn(),o=e.heavyLockPath??Yn(),s=e.maintainerWakeImpl??o_,i=e.autoContinueImpl??r_,a=e.surfaceUnknownImpl??w_,c=e.surfaceBlockedImpl??i_,l=e.surfaceDoneConsistencyImpl??f_,u=e.surfaceUnresolvableTeamfilesImpl??a_,d=e.surfaceFaultImpl??h_,m=e.surfaceClosedEpicsImpl??l_,f=e.escalateImpl??bg,p=e.autoRedeliverImpl??Tg,h=e.wakeImpl??Sg,g=e.evaluateCronJobsImpl??dg,_=e.miniplayerVerifyImpl??Lh,E=e.hungHolderCheckImpl??Eh,y=e.epicReviewImpl??Rh,S=e.orphanReconcilerImpl??$h,T=e.hangProbeCollectImpl??xh,R=e.rateLimitCollectImpl??kg,x=e.rateLimitPolicyImpl??Ng,I=e.assembleWakeReportImpl??H_,A=e.existsSyncImpl??ML,H=e.statSyncImpl??UL,L=e.config??he,w=e.escalation??Xl,b=e.autoRedeliver??Zl,N=e.wake??eu,D=e.intervalMs??FL,W=null,ee=!1;async function ne(){if(ee)return qL;ee=!0;try{let J=e.getTeams(),oe=J.filter(B),k;try{k=await t(),yg(k,new Date().toISOString())}catch(V){throw Eg(V instanceof Error?V.message:String(V),new Date().toISOString()),V}let O=Date.now(),$=r(n,o,void 0,V=>{e.onError?.(V)}),q=Xs(e.db,oe,k),{stalled:U,continueEligible:Z}=await gp(e.db,oe,k,$,L,O);if(e.miniplayerVerify)try{await _(e.db,U,oe,e.miniplayerVerify)}catch(V){e.onError?.(V)}let G=new Set(U);for(let V of oe)!G.has(V.name)&&se(e.db,V.name)?.miniplayer_verdict_label&&km(e.db,V.name);if(e.hungHolderCheck)try{let V=e.maintainerWake?.sessionAlivePath!==void 0||e.maintainerWake?.activityFreshnessMs!==void 0?{sessionAliveExemptTeamName:e.maintainerWake.teamName,sessionAliveExemptPath:e.maintainerWake.sessionAlivePath,sessionAliveFreshnessMs:e.maintainerWake.sessionAliveFreshnessMs,activityFreshnessMs:e.maintainerWake.activityFreshnessMs}:{};await E(e.db,oe,{...V,...e.hungHolderCheck})}catch(V){e.onError?.(V)}if(e.orphanReconciler)try{let V=e.maintainerWake?.sessionAlivePath!==void 0||e.maintainerWake?.activityFreshnessMs!==void 0?{sessionAliveExemptTeamName:e.maintainerWake.teamName,sessionAliveExemptPath:e.maintainerWake.sessionAlivePath,sessionAliveFreshnessMs:e.maintainerWake.sessionAliveFreshnessMs,activityFreshnessMs:e.maintainerWake.activityFreshnessMs}:{};await S(e.db,J,k,{...V,...e.orphanReconciler})}catch(V){e.onError?.(V)}if(e.hangProbeCollect)try{T(e.db,e.hangProbeCollect)}catch(V){e.onError?.(V)}if(e.autoNudgeRedirectReview)try{let V=e.findDueAutoNudgeReviewsImpl??lh,ye=new Map(oe.map(nt=>[nt.name,nt.repoPath])),lt=new Map(oe.map(nt=>[nt.name,nt])),rt=await V(e.db,ye,O),_t=e.buildReviewMessageImpl??dh,Ke=e.resetShiftImpl??uh,Tn=e.enqueueImpl??we,Sr=e.checkProviderDisabledImpl??it,ur=e.resolveMemberProviderImpl??Vt;for(let nt of rt)try{let vr=ye.get(nt.team);if(vr===void 0)continue;let xo=lt.get(nt.team),Ps=xo===void 0?null:ur(xo,xo.leadAlias);if(Ps!==null&&Sr(e.db,Ps,O).disabled)continue;let Za=await _t(nt,vr);Tn(e.db,J,nt.team,Za,{from:"autopilot"}),await Ke(e.db,nt.team,vr,new Date(O).toISOString())}catch(vr){e.onError?.(vr)}}catch(V){e.onError?.(V)}if(e.epicReview)try{await y(e.db,J,e.epicReview)}catch(V){e.onError?.(V)}let ie=!1;if(e.maintainerWake)try{let V={cooldownMs:L.cooldownMs,...e.maintainerWake};if(V.sessionAlivePath!==void 0){let ye=Bn(V.sessionAlivePath,V.sessionAliveFreshnessMs,V.activityFreshnessMs!==void 0?se(e.db,V.teamName)?.last_cli_activity_ts??null:null,V.activityFreshnessMs,{existsSyncImpl:A,statSyncImpl:H,nowMs:O}),lt,rt;try{let Ke=await I(e.db,J,V.teamName,{nowMs:O,config:L,fetchReportImpl:async()=>k,heavyLockImpl:()=>$,...V.maintainerStaleThresholdMs!==void 0?{maintainerStaleThresholdMs:V.maintainerStaleThresholdMs}:{}});lt=Ke.rendered,rt=Ke.isEmpty}catch(Ke){e.onError?.(Ke),lt="wake-report assembly failed this tick -- waking conservatively; check server logs for the error.",rt=!1}let _t=Ke=>`${PL(Ke,"utf8")}
|
|
477
477
|
|
|
478
478
|
---
|
|
479
|
-
${lt}`;
|
|
480
|
-
`)}return"replied"}function
|
|
481
|
-
`)})}function
|
|
479
|
+
${lt}`;ie=s(e.db,oe,k,V,_t,O,ye?void 0:!rt)}else ie=s(e.db,oe,k,V,void 0,O)}catch(V){e.onError?.(V)}let be=[];if(e.autoContinue&&Ur(e.db)===null)try{be=await i(e.db,oe,k,{config:L,...e.autoContinue,nowMs:O,stalledTeamNames:Z,heavyLockStatusPath:n,heavyLockPath:o,readHeavyLockStatusImpl:r})}catch(V){e.onError?.(V)}let ae=[];if(e.maintainerWake)try{ae=await a(e.db,U,e.maintainerWake.teamName,J,L,O)}catch(V){e.onError?.(V)}let M=[];if(e.maintainerWake)try{M=await c(e.db,oe,e.maintainerWake.teamName,J,L,O)}catch(V){e.onError?.(V)}let j=[];if(e.maintainerWake)try{j=await l(e.db,oe,e.maintainerWake.teamName,J,L)}catch(V){e.onError?.(V)}let Y=[];if(e.maintainerWake)try{Y=await d(e.db,oe,e.maintainerWake.teamName,J,L,O)}catch(V){e.onError?.(V)}let z=[];if(e.maintainerWake)try{z=await m(e.db,oe,e.maintainerWake.teamName,J,L,O)}catch(V){e.onError?.(V)}let re=[];if(e.maintainerWake)try{re=await u(e.db,oe,e.maintainerWake.teamName,J,L,O)}catch(V){e.onError?.(V)}let te=[];try{te=await g(e.db,J,O,{onJobError:(V,ye)=>e.onError?.(ye)})}catch(V){e.onError?.(V)}let de=[];try{de=await f(e.db,oe,w,O)}catch(V){e.onError?.(V)}let xe=[];try{xe=p(e.db,oe,b,O)}catch(V){e.onError?.(V)}let Se=[];try{Se=h(e.db,oe,k,N,O)}catch(V){e.onError?.(V)}let K=null,Te=[],ze=e.rateLimitPolicy??e.rateLimitAutomation,We=e.rateLimitCollect??ze;if(We!==void 0){let V=Date.now();try{K=await R(e.db,{nowMs:V,...We})}catch(ye){e.onError?.(ye)}try{Te=x(e.db,{nowMs:V,...ze,dryRun:ze===void 0})}catch(ye){e.onError?.(ye)}}let Ut={watch:q,stalled:U,maintainerWoken:ie,autoContinued:be,surfacedUnknown:ae,surfacedBlocked:M,surfacedDoneConsistency:j,surfacedUnresolvableTeamfiles:re,surfacedFault:Y,surfacedClosedEpics:z,escalated:de,autoRedelivered:xe,woken:Se,firedCronJobs:te,rateLimitCollected:K,rateLimitPolicyEvaluations:Te};return e.onTick?.(Ut),Ut}catch(J){throw e.onError?.(J),J}finally{ee=!1}}return{start(){W||(W=setInterval(()=>{ne().catch(()=>{})},D),W.unref())},stop(){W&&(clearInterval(W),W=null)},runTickNow:ne,isRunning:()=>W!==null,isTicking:()=>ee}}import{closeSync as jL,linkSync as HL,openSync as BL,readdirSync as WL,readFileSync as _a,readlinkSync as GL,realpathSync as VL,renameSync as W_,unlinkSync as _u,writeSync as JL}from"node:fs";import{dirname as zL,join as KL}from"node:path";var Xn=class extends Error{holder;lockPath;constructor(t,r){super(`site lock held by "${t.ownerLabel}" (pid ${t.pid}, started ${t.startedAt}) at ${r} -- only one process (standalone \`lmauto serve\` or \`lmt site start\`) may run lmauto's scheduler against this DB at a time`),this.holder=t,this.lockPath=r,this.name="SiteLockHeldError"}};function fs(e){return e===":memory:"?null:`${e}.lock`}function z_(e){let t=ps(e);return t.kind==="held"?t.identity:null}function G_(e){let t;try{t=_a(e,"utf8")}catch(o){return o.code==="ENOENT"?{kind:"free"}:{kind:"unknown"}}let r=Sc(t);if(!r)return{kind:"unknown"};let n={...r,bootId:r.bootId??null};return gu(n)?{kind:"held",identity:n}:{kind:"free"}}function YL(e,t){let r;try{r=VL(t)}catch{return!1}let n;try{n=WL(`/proc/${e}/fd`)}catch{return!1}for(let o of n)try{if(GL(`/proc/${e}/fd/${o}`)===r)return!0}catch{}return!1}function ps(e){let t=fs(e);if(t===null)return{kind:"free"};let r=G_(t);if(r.kind==="held")return r;let n=KL(zL(e),"site.lock");if(n===t)return r;let o=G_(n);return o.kind==="held"&&YL(o.identity.pid,e)?o:r}function ga(e){try{let t=Sc(_a(e,"utf8"));return t?{...t,bootId:t.bootId??null}:null}catch{return null}}function K_(){try{let e=_a("/proc/sys/kernel/random/boot_id","utf8").trim();return vc(e)?e:null}catch{return null}}function Y_(e){try{let t=_a(`/proc/${e}/stat`,"utf8"),o=t.slice(t.lastIndexOf(")")+2).trim().split(/\s+/)[19];if(o===void 0)return null;let s=Number(o);return Number.isFinite(s)?s:null}catch{return null}}function gu(e){let t;try{process.kill(e.pid,0),t=!0}catch(n){t=n.code==="EPERM"}if(!t)return!1;if(e.bootId!==null){let n=K_();if(n!==null&&n!==e.bootId)return!1}if(e.pidStartTicks===null)return!0;let r=Y_(e.pid);return r===null?!0:r===e.pidStartTicks}function V_(e,t){let r=`${e}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`,n=BL(r,"wx");try{JL(n,JSON.stringify(t))}finally{jL(n)}try{return HL(r,e),!0}catch(o){if(o.code!=="EEXIST")throw o;return!1}finally{_u(r)}}function wa(e,t){let r={pid:process.pid,ownerLabel:t,startedAt:new Date().toISOString(),pidStartTicks:Y_(process.pid),bootId:K_()};if(V_(e,r))return J_(e,r);let n=ga(e);if(n!==null&&gu(n))throw new Xn(n,e);let o=`${e}.reclaim.${process.pid}.${Math.random().toString(36).slice(2)}`,s=!1;try{W_(e,o);let a=ga(o);n===null&&a===null||n!==null&&a!==null&&a.pid===n.pid&&a.startedAt===n.startedAt?(_u(o),s=!0):W_(o,e)}catch{}if(s&&V_(e,r))return J_(e,r);let i=ga(e);throw i!==null&&gu(i)?new Xn(i,e):new Error(`failed to acquire site lock at ${e} (lost a reclaim race)`)}function J_(e,t){let r=!1;return{release(){if(!r){r=!0;try{let n=ga(e);n!==null&&n.pid===t.pid&&n.startedAt===t.startedAt&&_u(e)}catch{}}}}}import{closeSync as wu,existsSync as QL,fstatSync as XL,mkdirSync as ZL,openSync as Q_,readFileSync as X_,renameSync as eC,unlinkSync as tC,writeSync as rC}from"node:fs";import{dirname as Z_,join as nC}from"node:path";import{createHash as oC,randomBytes as sC}from"node:crypto";var iC=32;function Zn(e){return e===":memory:"?null:nC(Z_(e),"localweb-passcode")}function aC(){return sC(iC).toString("base64url")}function yu(e,t){let r=Z_(e);QL(r)||ZL(r,{recursive:!0});let n=`${e}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`,o;try{o=Q_(n,"wx",384);let s=Buffer.from(t,"utf8"),i=0;for(;i<s.length;){let a=rC(o,s,i,s.length-i);if(a<=0)throw new Error("passcode file write made no progress");i+=a}wu(o),o=void 0,eC(n,e)}catch(s){if(o!==void 0)try{wu(o)}catch{}try{tC(n)}catch{}throw s}}function ew(e){let t;try{t=Q_(e,"r")}catch(r){if(r.code==="ENOENT")return null;throw r}try{let r=XL(t,{bigint:!0}),n=X_(t,"utf8"),o=oC("sha256").update(`${r.dev}:${r.ino}:${r.ctimeNs}:${r.mtimeNs}:${r.size}:`).update(n,"utf8").digest("base64url");return{passcode:n,generation:o}}finally{wu(t)}}function tw(e){try{return X_(e,"utf8")}catch(t){if(t.code==="ENOENT")return null;throw t}}function ya(e){let t=aC();return yu(e,t),t}import{randomUUID as cC}from"node:crypto";function Eu(e){return`remote:${e.from.team?`${e.from.site}:${e.from.team}:${e.from.alias}`:`${e.from.site}:${e.from.alias}`}`}function rw(e,t,r){let n=t.find(o=>o.name===r.to.team);if(!n)throw new Error(`no local team registered for remote envelope's to.team "${r.to.team}"`);if(!B(n))throw new Error(`remote envelope addressed to "${r.to.team}", which is itself a remote (channel=lmmail) team -- not locally dispatchable`);we(e,t,n.name,r.payload,{from:Eu(r),dedupeKey:r.msgId})}var lC=new Set(["dispatched","queued","failed"]);function uC(e){let t;try{t=JSON.parse(e)}catch{return!1}if(typeof t!="object"||t===null||Array.isArray(t))return!1;let r=t.state;return typeof r=="string"&&lC.has(r)}var dC="reply-surfaced:";function mC(e,t,r,n){let o=r.inReplyTo;if(!o)throw new Error("recordReplyOrAck: envelope has no in_reply_to");let s=Uf(e,o);if(!s)return"orphan";if(uC(r.payload))return Ff(e,o,n),"acked";qf(e,o,n);let i=t.find(a=>B(a)&&a.name===s.from_alias);if(i)try{we(e,t,i.name,r.payload,{from:Eu(r),dedupeKey:`${dC}${r.msgId}`})}catch(a){process.stderr.write(`[mail] failed to surface reply to ${i.name}'s inbox (in_reply_to ${o}): ${a instanceof Error?a.message:String(a)}
|
|
480
|
+
`)}return"replied"}function fC(e,t,r,n,o){let s=e.now??(()=>new Date().toISOString()),i={v:1,msgId:cC(),to:t,from:{site:e.localSiteId,team:"",alias:"lmauto"},sentAt:s(),payload:JSON.stringify({state:n,...o?{note:o}:{}}),inReplyTo:r},a=on(t.site),c=new TextEncoder().encode(Oo(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 ${r}): ${l instanceof Error?l.message:String(l)}
|
|
481
|
+
`)})}function nw(e,t,r,n){if(r.inReplyTo){mC(e,t,r,(n.now??(()=>new Date().toISOString()))());return}let o;try{rw(e,t,r)}catch(i){o=i}let s=n.now??(()=>new Date().toISOString());if(Df(e,r.msgId,s())){let i=o?(o instanceof Error?o.message:String(o)).slice(0,500):void 0;fC(n,r.from,r.msgId,o?"failed":"dispatched",i)}if(o)throw o}var aw=/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,pC=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/,hC="text/plain; charset=utf-8",bu="exec",cw="exec-result";var gC="exec-result";var _C=`
|
|
482
482
|
... [lmexec output truncated; middle elided, see attachment] ...
|
|
483
|
-
`;function
|
|
484
|
-
`)),c=t.shouldStop??(()=>!1),l
|
|
485
|
-
`)),s=e.runDaemonLoopImpl??
|
|
486
|
-
VALUES (?, ?, 1, ?, NULL, 'claimed', ?, ?, ?, ?, ?)`).run(n,o,p.id,i.pid,i.start,h,h,g),{kind:"claimed",conversationId:n,requestHash:o,jobId:p.id,generation:1,receiptPath:g}}).immediate();return l.forEach(Ta),m}catch(d){throw c.forEach(Ta),
|
|
483
|
+
`;function lw(e){return Tu(fw(e))}function uw(e){return dw(fw(e))}function Tu(e){let t=pw(e),r=hw(t.type,"type",bu),n=gw(t.id,"id"),o=vu(t.command,"command"),s=TC(t.timeout_s,"timeout_s"),i=bC(t.reply_to,"reply_to"),a=yC(t.from,"from");return{v:1,type:r,id:n,command:o,timeout_s:s,reply_to:i,...a===void 0?{}:{from:a}}}function dw(e){let t=pw(e),r=wC(t.v),n=hw(t.type,"type",cw),o=gw(t.id,"id"),s=vC(t.exit_code,"exit_code"),i=sw(t.stdout,"stdout"),a=sw(t.stderr,"stderr"),c=SC(t.duration_ms,"duration_ms"),l=iw(t.timed_out,"timed_out"),u=iw(t.truncated,"truncated");if(l&&s!==null)throw new Error("invalid exec result: exit_code must be null when timed_out is true");if(!l&&s===null)throw new Error("invalid exec result: exit_code must be a number when timed_out is false");let d={type:n,id:o,exit_code:s,stdout:i,stderr:a,duration_ms:c,timed_out:l,truncated:u};if(r===1)return{v:r,...d};let m=EC(t.sender_trust),f=vu(t.sender,"sender");return{v:r,...d,sender_trust:m,sender:f}}function Su(e){if(!aw.test(e))throw new Error(`invalid exec id: ${e}`);return`${gC} ${e}`}function ow(e,t,r){let n=Buffer.isBuffer(t)?t:Buffer.from(t,"utf8"),o=r?.capBytes??49152,s=r?.marker??_C;if(!Number.isInteger(o)||o<1)throw new Error("inline cap must be a positive integer");if(n.byteLength<=o)return{inline:n.toString("utf8"),truncated:!1};let i=Buffer.byteLength(s,"utf8");if(i>=o)throw new Error("elision marker must be smaller than the inline cap");let a=n.toString("utf8"),c=o-i,l=Math.ceil(c/2),u=Math.floor(c/2);return{inline:`${AC(a,l)}${s}${$C(a,u)}`,truncated:!0,attachment:{name:e==="stdout"?"stdout.txt":"stderr.txt",content_type:hC,data:n}}}function mw(e,t){let r=ow("stdout",e.stdout,t),n=ow("stderr",e.stderr,t),o=dw({v:2,type:cw,id:e.id,exit_code:e.exit_code,stdout:r.inline,stderr:n.inline,duration_ms:e.duration_ms,timed_out:e.timed_out,truncated:r.truncated||n.truncated,sender_trust:e.sender_trust,sender:e.sender});return{subject:Su(e.id),envelope:o,attachments:[r.attachment,n.attachment].filter(s=>s!==void 0)}}function fw(e){try{return JSON.parse(e)}catch(t){throw new Error(`invalid JSON: ${kC(t)}`)}}function pw(e){if(!e||typeof e!="object"||Array.isArray(e))throw new Error("expected object");return e}function hw(e,t,r){if(e!==r)throw new Error(`invalid ${t}: expected ${r}`);return r}function wC(e){if(e===void 0||e===1)return 1;if(e===2)return 2;throw new Error("invalid v: expected 1 or 2")}function gw(e,t){if(typeof e!="string"||!aw.test(e))throw new Error(`invalid ${t}: expected UUID v4`);return e}function vu(e,t){if(typeof e!="string"||e.trim().length===0)throw new Error(`invalid ${t}: expected non-empty string`);return e}function yC(e,t){if(e!==void 0)return vu(e,t)}function EC(e){if(e==="admin"||e==="registered"||e==="anonymous")return e;throw new Error("invalid sender_trust: expected admin, registered, or anonymous")}function bC(e,t){if(typeof e!="string"||e.includes("/")||e.includes("\\")||e.includes("..")||e.endsWith(".")||/[\u0000-\u001f\u007f]/.test(e)||!pC.test(e))throw new Error(`invalid ${t}: expected mailbox name`);return e}function sw(e,t){if(typeof e!="string")throw new Error(`invalid ${t}: expected string`);return e}function TC(e,t){if(typeof e!="number"||!Number.isSafeInteger(e)||e<1)throw new Error(`invalid ${t}: expected positive integer`);return e}function SC(e,t){if(typeof e!="number"||!Number.isSafeInteger(e)||e<0)throw new Error(`invalid ${t}: expected non-negative integer`);return e}function vC(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 iw(e,t){if(typeof e!="boolean")throw new Error(`invalid ${t}: expected boolean`);return e}function AC(e,t){if(t<=0||e.length===0)return"";let r=0,n="";for(let o of e){let s=Buffer.byteLength(o,"utf8");if(r+s>t)break;n+=o,r+=s}return n}function $C(e,t){if(t<=0||e.length===0)return"";let r=0,n=[],o=Array.from(e);for(let s=o.length-1;s>=0;s-=1){let i=o[s],a=Buffer.byteLength(i,"utf8");if(r+a>t)break;n.push(i),r+=a}return n.reverse().join("")}function kC(e){return e instanceof Error&&e.message?e.message:String(e)}var xC=/[;&|`$<>(){}\\]/,_w=/[\x00-\x1f\x7f]/;function yw(e){let t=[],r=0,n=e.length;for(;r<n;){for(;r<n&&e[r]===" ";)r+=1;if(r>=n)break;let o;if(e[r]==='"'||e[r]==="'"){let s=e[r];r+=1,o="";let i=r;for(;;){for(;r<n&&e[r]!==s;){if(_w.test(e[r])||s==="'"&&e[r]==="\\")return null;r+=1}if(r>=n)return null;if(o+=e.slice(i,r),s==="'"&&e[r+1]==="\\"&&e[r+2]==="'"&&e[r+3]==="'"){o+="'",r+=4,i=r;continue}r+=1;break}if(r<n&&e[r]!==" ")return null}else{let s=r;for(;r<n&&e[r]!==" ";){if(_w.test(e[r])||xC.test(e[r]))return null;r+=1}if(o=e.slice(s,r),o.includes('"')||o.includes("'"))return null}t.push(o)}return t.length>0?t:null}function Au(e){if(!e.includes("--json"))return"requires --json when run via exec (plain-text output has no machine-readable contract)"}function RC(e){return e.includes("--watch")?"tail --watch is a long-running stream, not a fit for a single bounded exec call":e.includes("--lines")?Au(e):"tail requires --lines N when run via exec (unbounded --max-bytes/no-limit output is not allowed)"}var NC=[{prefix:["lmbee","status"]},{prefix:["lmbee","teams"]},{prefix:["lmbee","queue","list"]},{prefix:["lmbee","queue","get"]},{prefix:["lmbee","queue","inbox"]},{prefix:["lmbee","history"]},{prefix:["lmbee","state","list"]},{prefix:["lmbee","state","get"]},{prefix:["lmbee","state","active"]},{prefix:["lmbee","source","list"]},{prefix:["lmctl","health"],validate:Au},{prefix:["lmctl","running"],validate:Au},{prefix:["lmctl","tail"],validate:RC}],IC=[{prefix:["lmbee","enqueue"]},{prefix:["lmbee","send"]},{prefix:["lmbee","nudge"]},{prefix:["lmbee","state","set"]},{prefix:["lmbee","queue","deliver"]},{prefix:["lmbee","queue","retrieve"]},{prefix:["lmbee","queue","gc"]},{prefix:["lmbee","source","add"]},{prefix:["lmbee","source","remove"]}];function LC(e,t){return e.length<t.prefix.length?!1:t.prefix.every((r,n)=>e[n]===r)}function ww(e,t){return t.find(r=>LC(e,r))}function Ew(e,t){let r=ww(e,NC);if(r){let o=r.validate?.(e);return o?{allowed:!1,code:"command_not_allowed",message:o}:{allowed:!0}}let n=ww(e,IC);if(n){let o=n.validate?.(e);return o?{allowed:!1,code:"command_not_allowed",message:o}: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 bw}from"node:child_process";var CC=5e3,OC="/bin/sh";function Tw(e){if(!Number.isInteger(e.timeoutMs)||e.timeoutMs<1)throw new Error("timeoutMs must be a positive integer");let t=e.killGraceMs??CC;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 Sw(e,t,r,n){return new Promise((o,s)=>{let i=n(),a=[],c=[],l=!1,u=!1,d,m,f=h=>{u||(u=!0,d&&clearTimeout(d),m&&clearTimeout(m),o(h))},p=h=>{u||(u=!0,d&&clearTimeout(d),m&&clearTimeout(m),s(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=>{f({exit_code:l?null:typeof h=="number"?h:null,stdout:Buffer.concat(a),stderr:Buffer.concat(c),duration_ms:Math.max(0,Math.round(n()-i)),timed_out:l})}),d=setTimeout(()=>{l=!0,$u(e.pid,"SIGTERM"),r>0?m=setTimeout(()=>{$u(e.pid,"SIGKILL")},r):$u(e.pid,"SIGKILL")},t)})}async function vw(e,t){if(e.trim().length===0)throw new Error("command must be non-empty");let{killGraceMs:r,now:n}=Tw(t),o=t.shellPath??OC,s=bw(o,["-c",e],{cwd:t.cwd,env:t.env,detached:!0,stdio:["ignore","pipe","pipe"]});return Sw(s,t.timeoutMs,r,n)}async function Aw(e,t){if(e.length===0)throw new Error("argv must be non-empty");let{killGraceMs:r,now:n}=Tw(t),o=bw(e[0],e.slice(1),{cwd:t.cwd,env:t.env,detached:!0,stdio:["ignore","pipe","pipe"]});return Sw(o,t.timeoutMs,r,n)}function $u(e,t){if(e)try{process.kill(-e,t)}catch(r){if(!DC(r))throw r}}function DC(e){return!!e&&typeof e=="object"&&"code"in e&&e.code==="ESRCH"}var $w=1e3,PC=6e4,UC=20,FC=1e3;async function xw(e,t){let r=t.runCommand??vw,n=t.runCommandArgv??Aw,o=t.sleep??jC,s=t.pollNow??Date.now,i=t.now??(()=>new Date),a=t.stderr??(d=>process.stderr.write(`${d}
|
|
484
|
+
`)),c=t.shouldStop??(()=>!1),l=$w,u=!1;for(Lt(a,i,"info","daemon_started",{mailbox:e.mailbox}),e.allowAnonymous&&Lt(a,i,"warn","anonymous_execution_enabled",{mailbox:e.mailbox,warning:"REMOTE SHELL OPEN TO EVERY AUTHENTICATED LMMAIL USER"});!c();)try{let d=s(),m=await t.client.listMessages(e.mailbox,{status:"unread",after:0,...e.once?{}:{wait_s:UC}}),f=Math.max(0,s()-d);for(let p of m.messages){if(c())break;let h=qC(e,p.sender);if(h==="anonymous"&&!e.allowAnonymous){await t.client.getMessageMetadata(e.mailbox,p.seq),Lt(a,i,"warn","message_rejected",{seq:p.seq,sender:p.sender,sender_trust:h,reason:"anonymous_not_allowed"});continue}let g=await t.client.getMessage(e.mailbox,p.seq),_=Buffer.from(await t.client.download(g.body.download_url)).toString("utf8"),E;try{E=lw(_)}catch(x){Lt(a,i,"warn","message_rejected",{seq:p.seq,sender:p.sender,sender_trust:h,reason:"malformed_request",error:ku(x)});continue}let y=e.execAllowlist?yw(E.command):void 0,S=e.execAllowlist?y?Ew(y,h):{allowed:!1,code:"malformed_command",message:"command could not be safely tokenized into arguments"}:{allowed:!0};if(!S.allowed){Lt(a,i,"warn","command_rejected",{id:E.id,sender:p.sender,sender_trust:h,...E.from===void 0?{}:{asserted_from:E.from},code:S.code,seq:p.seq}),await kw(t.client,E.reply_to,{id:E.id,exit_code:126,stdout:"",stderr:JSON.stringify({error:{code:S.code,message:S.message}}),duration_ms:0,timed_out:!1,sender_trust:h,sender:p.sender});continue}Lt(a,i,"info","command_started",{id:E.id,sender:p.sender,sender_trust:h,...E.from===void 0?{}:{asserted_from:E.from},seq:p.seq});let T;try{T=y?await n(y,{timeoutMs:Math.min(E.timeout_s,e.timeoutCapSeconds)*1e3}):await r(E.command,{timeoutMs:Math.min(E.timeout_s,e.timeoutCapSeconds)*1e3})}catch(x){Lt(a,i,"error","command_failed",{id:E.id,sender:p.sender,sender_trust:h,...E.from===void 0?{}:{asserted_from:E.from},error:ku(x)});continue}let R=await kw(t.client,E.reply_to,{id:E.id,...T,sender_trust:h,sender:p.sender});Lt(a,i,"info","command_finished",{id:E.id,sender:p.sender,sender_trust:h,...E.from===void 0?{}:{asserted_from:E.from},duration_ms:T.duration_ms,exit_code:T.exit_code,timed_out:T.timed_out,truncated:R.envelope.truncated})}if(l=$w,e.once||c())break;m.messages.length===0&&f<FC&&(u||(Lt(a,i,"warn","long_poll_unsupported",{elapsed_ms:f,fallback_interval_ms:e.pollIntervalMs}),u=!0),await o(e.pollIntervalMs))}catch(d){if(Lt(a,i,"error","api_error",{error:ku(d),retry_ms:l}),c())break;await o(l),l=Math.min(l*2,PC)}Lt(a,i,"info","daemon_stopped",{mailbox:e.mailbox})}function qC(e,t){return e.adminUsers.has(t)?"admin":e.allowUsers.has(t)?"registered":"anonymous"}async function kw(e,t,r){let n=mw(r);return await e.sendMessage({mailbox:t,subject:n.subject,body:{name:"body.txt",contentType:"text/plain; charset=utf-8",bytes:Buffer.from(JSON.stringify(n.envelope),"utf8")},attachments:n.attachments.map(o=>({name:o.name,contentType:o.content_type,bytes:o.data}))}),n}function Lt(e,t,r,n,o){e(JSON.stringify({ts:t().toISOString(),level:r,event:n,...o}))}function jC(e){return new Promise(t=>setTimeout(t,e))}function ku(e){return e instanceof Error?e.message:String(e)}var HC=5e3,BC=300;async function Rw(e,t){await e.createMailbox(t,{tolerate409:!0})}function Nw(e){let t=!1,r=!1,n=Promise.resolve(),o=e.stderr??(c=>process.stderr.write(`${c}
|
|
485
|
+
`)),s=e.runDaemonLoopImpl??xw,i={mailbox:e.mailbox,allowUsers:e.allowUsers,adminUsers:e.adminUsers,allowAnonymous:e.allowAnonymous,apiUrl:"",pollIntervalMs:e.pollIntervalMs??HC,timeoutCapSeconds:e.timeoutCapSeconds??BC,once:!1,execAllowlist:!0},a={client:e.client,shouldStop:()=>t,stderr:o};return{start(){r||t||(r=!0,n=s(i,a).catch(c=>{o(`[exec-worker] unexpected top-level failure, worker stopped: ${c instanceof Error?c.message:String(c)}`)}))},stop(){t=!0},isRunning:()=>r&&!t,whenIdle:()=>n}}var WC=64*1024;function Iw(e){return{v:1,msgId:e.msg_id,to:{site:e.to_site,team:e.to_team,alias:e.to_alias},from:{site:e.from_site,team:e.from_team,alias:e.from_alias},sentAt:e.sent_at,payload:e.payload}}async function xu(e,t,r,n,o,s){if(r.to.site!==t.localSiteId){In(e,r.msgId,`${sn}addressed to a different site: ${r.to.site}`,o()),s.rejected++;return}if(!t.allowlist.includes(n)){In(e,r.msgId,`sender not allowlisted: ${n}`,o()),s.rejected++;return}try{await t.dispatch(r,n),If(e,r.msgId,o()),s.dispatched++}catch(i){In(e,r.msgId,i instanceof Error?i.message:String(i),o()),s.failed++}}async function Lw(e,t,r,n){let o=n.now??(()=>new Date().toISOString()),s=n.maxBodyBytes??WC,i={recovered:0,retriedFailed:0,listed:0,recorded:0,dispatched:0,rejected:0,failed:0,stoppedEarly:!1};for(let d of Rf(e))i.recovered++,await xu(e,n,Iw(d),d.sender_user_id,o,i);let a=n.retryPolicy??Dc;for(let d of oi(e,o(),a))Of(e,d.msg_id)&&(i.retriedFailed++,await xu(e,n,Iw(d),d.sender_user_id,o,i));let c=Nf(e)??0,{messages:l}=await t.listMessages(r,{after:c});i.listed=l.length;let u=[...l].sort((d,m)=>d.seq-m.seq);for(let d of u){let m;try{m=await t.getMessage(r,d.seq)}catch{i.stoppedEarly=!0;break}if(m.body.size>s){i.stoppedEarly=!0;break}let f;try{f=await t.download(m.body.download_url)}catch{i.stoppedEarly=!0;break}let p;try{p=kf(Buffer.from(f).toString("utf8"))}catch{i.stoppedEarly=!0;break}let h=o(),g=xf(e,{msgId:p.msgId,seq:d.seq,to:p.to,from:p.from,senderUserId:m.sender,sentAt:p.sentAt,payload:p.payload},h);if(g!=="duplicate"){if(g==="conflict"){i.rejected++;continue}i.recorded++,await xu(e,n,p,m.sender,o,i)}}return i}async function Cw(e,t){await e.createMailbox(t,{tolerate409:!0})}var GC=6e4,VC={recovered:0,retriedFailed:0,listed:0,recorded:0,dispatched:0,rejected:0,failed:0,stoppedEarly:!1};function Ow(e){let t=e.intervalMs??GC,r=null,n=!1;async function o(){if(n)return VC;n=!0;try{let s=await Lw(e.db,e.client,e.mailbox,e.worker);return e.onPoll?.(s),s}catch(s){throw e.onError?.(s),s}finally{n=!1}}return{start(){r||(r=setInterval(()=>{o().catch(()=>{})},t),r.unref())},stop(){r&&(clearInterval(r),r=null)},pollNow:o,isRunning:()=>r!==null,isPolling:()=>n}}var JC=5e3;function Dw(e){let t=e.intervalMs??JC,r=e.fetchReport??ke,n=e.deliverImpl??xr,o=null,s=!1;async function i(){if(s)return 0;s=!0;try{let a=e.getTeams(),c=await r(),l=n(e.db,{teams:a,report:c,...e.remoteMail?{remoteMail:e.remoteMail}:{},...e.minMemoryPercent!==void 0?{minMemoryPercent:e.minMemoryPercent}:{}});return e.onDeliver?.(l),l}catch(a){throw e.onError?.(a),a}finally{s=!1}}return{start(){o||(o=setInterval(()=>{i().catch(()=>{})},t),o.unref())},stop(){o&&(clearInterval(o),o=null)},deliverNow:i,isRunning:()=>o!==null,isDelivering:()=>s}}import{createHash as zC,randomUUID as KC}from"node:crypto";import{readFileSync as qw,mkdtempSync as YC,writeFileSync as QC,renameSync as XC,rmSync as jw,rmdirSync as ZC}from"node:fs";import{tmpdir as eO}from"node:os";import{join as Mw,dirname as Pw,basename as Uw}from"node:path";import{isAbsolute as Fw,resolve as ba}from"node:path";function Hw(e){try{let t=qw(`/proc/${e}/stat`,"utf8");return t.slice(t.lastIndexOf(")")+2).trim().split(/\s+/)[19]??null}catch{return null}}function tO(e,t){try{process.kill(e,0)}catch(n){if(n.code==="ESRCH"||n.code!=="EPERM")return!1}let r=Hw(e);return r===null||r===t}function rO(e){return{...e,db:ba(e.db),script:ba(e.script),localScope:e.localScope.trim()}}function nO(e,t){return zC("sha256").update(JSON.stringify({conversationId:t,db:e.db,localScope:e.localScope,script:e.script,args:e.args})).digest("hex")}function oO(e,t){if(!Fw(t.db)||ba(t.db)!==ba(e))throw new P("INVALID_ARGUMENT","db must select the running daemon database");let r=t.conversationId?.trim()||KC();if(t.localScope.trim()==="")throw new P("INVALID_ARGUMENT","local_scope is required");if(!Fw(t.script))throw new P("INVALID_ARGUMENT","script must be an absolute path");if(!t.args.every(o=>typeof o=="string"))throw new P("INVALID_ARGUMENT","args must be strings");let n=rO(t);return{conversationId:r,requestHash:nO(n,r),normalizedInput:n}}function sO(e,t){return[process.env.LMSCRIPT_BIN||"lmscript",e.script,e.db,e.localScope,t,...e.args].map(r=>`'${r.replaceAll("'","'\\''")}'`).join(" ")}function Ea(e,t){return e.prepare("SELECT * FROM on_demand_launches WHERE conversation_id = ?").get(t)??null}function Bw(e){return e===null||typeof e!="object"||!("code"in e)?!1:String(e.code).startsWith("SQLITE_BUSY")||String(e.code).startsWith("SQLITE_LOCKED")}function Ww(e){let t=Mw(YC(Mw(eO(),"lmbee-adoption-")),"receipt.json");return e.push(t),t}function Ta(e){if(!(e===null||Uw(e)!=="receipt.json"||!Uw(Pw(e)).startsWith("lmbee-adoption-")))try{jw(e,{force:!0}),ZC(Pw(e))}catch{}}function iO(e){let t=e.receiptPath+".tmp-"+process.pid,r={adopted:!1,conversationId:e.conversationId,generation:e.generation,jobId:e.jobId,runId:null};try{QC(t,JSON.stringify(r),{mode:384,flag:"wx"}),XC(t,e.receiptPath)}finally{try{jw(t,{force:!0})}catch{}}}function aO(e){try{return e===null?null:JSON.parse(qw(e,"utf8"))}catch{return null}}function Ru(e){let t=aO(e.receipt_path);return t?.adopted===!1&&t.conversationId===e.conversation_id&&t.generation===e.generation&&t.jobId===e.job_id&&t.runId===e.run_id}function cO(e,t,r,n,o){if(t.phase==="worker_adopted"&&t.run_id!==null)return o.push(t.receipt_path),{kind:"adopted",conversationId:t.conversation_id,jobId:t.job_id,runId:t.run_id};let s=Ru(t);if(t.phase==="dispatching"&&t.run_id!==null&&s&&(pr(e,t.run_id,{fallback:{ok:!1,summary:"worker refused before payload"}}),e.prepare("UPDATE on_demand_launches SET phase = 'reserved', state = 'retryable', run_id = NULL WHERE conversation_id = ? AND generation = ?").run(t.conversation_id,t.generation),t={...t,phase:"reserved",state:"retryable",run_id:null}),t.phase!=="reserved"||It(e,t.job_id)!==null)return{kind:"busy",conversationId:t.conversation_id,jobId:t.job_id,outcome:"unknown"};if(t.state==="claimed"&&tO(t.owner_pid,t.owner_start)&&!s)return{kind:"busy",conversationId:t.conversation_id,jobId:t.job_id,outcome:"not_sent"};e.prepare("UPDATE cron_jobs SET enabled = 1, updated_at = ? WHERE id = ?").run(new Date().toISOString(),t.job_id);let i=t.generation+1,a=Ww(n);return e.prepare("UPDATE on_demand_launches SET generation = ?, receipt_path = ?, run_id = NULL, state = 'claimed', owner_pid = ?, owner_start = ?, updated_at = ? WHERE conversation_id = ? AND generation = ? AND phase = 'reserved'").run(i,a,r.pid,r.start,new Date().toISOString(),t.conversation_id,t.generation),o.push(t.receipt_path),{kind:"claimed",conversationId:t.conversation_id,requestHash:t.request_hash,jobId:t.job_id,generation:i,receiptPath:a}}function lO(e,t,r){let{conversationId:n,requestHash:o,normalizedInput:s}=oO(t,r),i={pid:process.pid,start:Hw(process.pid)??"unavailable"},a=sO(s,n),c=[],l=[],u=Number(e.pragma("busy_timeout",{simple:!0}));e.pragma("busy_timeout = 0");try{let m=e.transaction(()=>{let f=Ea(e,n);if(f!==null){if(f.request_hash!==o)throw new P("CONFLICT",`conversationid ${n} is already bound to a different on-demand request`);return cO(e,f,i,c,l)}let p=Jn(e,{title:`on-demand conversation ${n}`,scheduleExpr:"0 0 31 2 *",actionKind:"script",actionPayload:a,enabled:!0}),h=new Date().toISOString(),g=Ww(c);return e.prepare(`INSERT INTO on_demand_launches(conversation_id, request_hash, generation, job_id, run_id, state, owner_pid, owner_start, created_at, updated_at, receipt_path)
|
|
486
|
+
VALUES (?, ?, 1, ?, NULL, 'claimed', ?, ?, ?, ?, ?)`).run(n,o,p.id,i.pid,i.start,h,h,g),{kind:"claimed",conversationId:n,requestHash:o,jobId:p.id,generation:1,receiptPath:g}}).immediate();return l.forEach(Ta),m}catch(d){throw c.forEach(Ta),Bw(d)?new P("DB_BUSY","Database busy; on-demand start was not sent",5):d}finally{e.pragma(`busy_timeout = ${Math.max(0,Math.trunc(u))}`)}}async function Gw(e,t,r,n){let o;try{o=lO(e,t,n)}catch(c){if(c instanceof P&&c.code==="DB_BUSY")return{conversationid:n.conversationId?.trim()||"",job_id:null,status:"busy",outcome:"not_sent"};throw c}if(o.kind==="busy")return{conversationid:o.conversationId,job_id:o.jobId,status:"busy",outcome:o.outcome};if(o.kind==="adopted")return{conversationid:o.conversationId,job_id:o.jobId,run_id:o.runId};let s=o.receiptPath,i=c=>({conversationid:o.conversationId,job_id:o.jobId,status:"busy",outcome:c}),a;try{a=await Xt(e,()=>ss(e,o.jobId,r,{runTimeoutMs:null,waitForCompletion:!1,disableOnClaim:!0,onDemand:{conversationId:o.conversationId,generation:o.generation,receiptPath:s}}))}catch(c){let l=!1;try{let u=Xt(e,()=>Ea(e,o.conversationId));l=u?.phase==="reserved"&&u.generation===o.generation&&u.run_id===null,l&&(iO(o),Xt(e,()=>e.prepare("UPDATE on_demand_launches SET state = 'retryable' WHERE conversation_id = ? AND generation = ? AND phase = 'reserved'").run(o.conversationId,o.generation)))}catch{}if(Bw(c)||c instanceof P&&c.code==="DB_BUSY")return i(l?"not_sent":"unknown");if(!l)return i("unknown");throw c}if(a.kind!=="fired"||a.runId===void 0)return i("unknown");for(;;){let c;try{c=Xt(e,()=>Ea(e,o.conversationId))}catch{return i("unknown")}if(c?.phase==="worker_adopted"&&c.run_id!==null)return Ta(s),{conversationid:o.conversationId,job_id:o.jobId,run_id:c.run_id};if(c?.phase==="dispatching"&&c.generation===o.generation&&Ru(c)){try{Xt(e,()=>e.transaction(()=>{let l=Ea(e,o.conversationId);l?.phase!=="dispatching"||l.generation!==o.generation||!Ru(l)||(pr(e,a.runId,{fallback:{ok:!1,summary:"worker refused before payload"}}),e.prepare("UPDATE on_demand_launches SET phase = 'reserved', state = 'retryable', run_id = NULL, receipt_path = NULL WHERE conversation_id = ? AND generation = ?").run(o.conversationId,o.generation))}).immediate()),Ta(s)}catch{}return i("not_sent")}try{let l=Xt(e,()=>Be(e,a.runId));if(l.execution_state==="gone"||l.execution_state==="uncertain")return i("unknown")}catch{return i("unknown")}await new Promise(l=>setTimeout(l,5))}}import{readFileSync as kM}from"node:fs";var uO=10*6e4,dO=60*6e4;function Vw(e,t,r={},n=Date.now()){let o=r.ackDeadlineMs??uO,s=r.replyThresholdMs??dO,i=[];for(let a of t){let c=si(e,{site:a.peerSite,team:a.name,alias:a.alias});if(!c)continue;let l=Date.parse(c.sent_ts);if(c.state==="sent"){n-l>=o&&i.push(a.name);continue}c.state!=="replied"&&n-l>=s&&i.push(a.name)}return i}var mO=[/^\S+'s turn has finished and exited; resubmit/i,/^resubmit .*lmctl chat/i];function fO(e){let t=e.split(/\r?\n/).filter(n=>n.trim().length>0).filter(n=>!mO.some(o=>o.test(n.trim()))),r=(t[t.length-1]??"").trim();return r==="BLOCKED"?"BLOCKED":r==="DONE"?"DONE":null}function Jw(e){if(e.trim()==="")return{status:"NO-OUTPUT",wake:"env"};let t=fO(e);return t==="BLOCKED"?{status:"BLOCKED",wake:"blocked"}:t==="DONE"?{status:"DONE",wake:null}:{status:"IDLE",wake:null}}function eo(e){switch(e.kind){case"ok":return Jw(e.replyText);case"stalled":{let t=Jw(e.replyText);return t.status==="BLOCKED"||t.status==="DONE"?t:{status:"NO-OUTPUT",wake:"env"}}case"busy":return{status:"RUNNING(busy)",wake:null};case"timeout":case"no-signal":return{status:"NO-OUTPUT",wake:"env"};case"error":return{status:"ENV-ERROR",wake:"env"}}}var to=Bt(Ct(),1);function Ae(e,t){return{error:{code:e,message:t}}}var ty=1e4;function Iu(e,t,r){let n=20;if(r!==void 0){let s=typeof r=="number"?r:r.trim()===""?NaN:Number(r);if(!Number.isSafeInteger(s)||s<0||s>ty)return Ae("invalid_limit",`invalid limit "${r}" -- must be an integer from 0 to ${ty}`);n=s}return{events:t?e.db.db.prepare("SELECT * FROM events WHERE team = ? ORDER BY id DESC LIMIT ?").all(t,n):e.db.db.prepare("SELECT * FROM events ORDER BY id DESC LIMIT ?").all(n)}}function ry(e,t,r,n={}){let o=Iu(e,t,r);return n.json?JSON.stringify(o):"error"in o?o.error.message:(0,to.formatTable)([["ID","TS","TEAM","STATUS","NOTE"],...o.events.map(s=>[String(s.id),ge(s.ts),(0,to.escapeCell)(s.team),(0,to.escapeCell)(s.status),(0,to.escapeCell)(s.note??"")])])}var ny=Bt(Ct(),1);function Lu(e){let t=e.db.db,r=Cf(t),n=Mc(t),o=n.filter(c=>c.failure_reason?.startsWith(sn)).length,s=n.length-o,i=oi(t,new Date().toISOString()).length,a=Pf(t);return{counts:r,retryEligibleCount:s,permanentCount:o,dueNowCount:i,deliveryErrorCount:a}}function oy(e,t={}){let r=Lu(e);if(t.json)return JSON.stringify(r);let n=[["persisted (awaiting dispatch)",String(r.counts.persisted)],["dispatched",String(r.counts.dispatched)],["replied",String(r.counts.replied)],["failed -- retry-eligible (backoff pending)",String(r.retryEligibleCount)],["failed -- permanent (never retried)",String(r.permanentCount)]],o=(0,ny.formatTable)([["STATE","COUNT"],...n]),s=r.deliveryErrorCount>0?`
|
|
487
487
|
${r.deliveryErrorCount} row(s) with a recorded delivery error (invocation failed to spawn -- see delivery_error)`:"";return`${o}
|
|
488
|
-
${r.dueNowCount} failed row(s) due for retry now${s}`}import{closeSync as
|
|
488
|
+
${r.dueNowCount} failed row(s) due for retry now${s}`}import{closeSync as BO,existsSync as WO,openSync as GO,readFileSync as Hu,readSync as VO,realpathSync as JO,statSync as zO}from"node:fs";var RO="member_health:";function Cu(e,t){return`${RO}${e}:${t}`}function sy(e,t,r,n){let o={kind:n.kind,observedAt:n.nowIso??new Date().toISOString(),remedy:n.remedy};e.prepare("INSERT INTO kv(k, v) VALUES (?, ?) ON CONFLICT(k) DO UPDATE SET v = excluded.v").run(Cu(t,r),JSON.stringify(o))}function hs(e,t,r){let n=e.prepare("SELECT v FROM kv WHERE k = ?").get(Cu(t,r));if(n===void 0)return null;try{let o=JSON.parse(n.v);return o.kind!=="evicted"||typeof o.observedAt!="string"||typeof o.remedy!="string"?null:{kind:"evicted",observedAt:o.observedAt,remedy:o.remedy}}catch{return null}}function iy(e,t,r){e.prepare("DELETE FROM kv WHERE k = ?").run(Cu(t,r))}function ay(e,t){let r=t.title.trim();if(r.length===0)throw new Error("prompt: task title must not be blank");let n=new Date().toISOString(),o=e.prepare("INSERT INTO prompt_tasks(title, description, created_at) VALUES (?, ?, ?)").run(r,t.description??"",n);return e.prepare("SELECT * FROM prompt_tasks WHERE id = ?").get(o.lastInsertRowid)}function gs(e,t){return e.prepare("SELECT * FROM prompt_tasks WHERE id = ?").get(t)??null}function cy(e,t){let r=t.prompt.trim();if(r.length===0)throw new Error("prompt: prompt must not be blank");let n=new Date().toISOString(),o=e.prepare("INSERT INTO task_prompts(task_id, from_id, to_id, prompt, created_at) VALUES (?, ?, ?, ?, ?)").run(t.taskId,t.fromId,t.toId,r,n);return e.prepare("SELECT * FROM task_prompts WHERE id = ?").get(o.lastInsertRowid)}function ly(e,t){return e.prepare("SELECT * FROM task_prompts WHERE task_id = ? ORDER BY id ASC").all(t)}function uy(e,t){return e.prepare("SELECT * FROM task_prompts WHERE to_id = ? AND retrieved_ts IS NULL ORDER BY id ASC").all(t)}function dy(e,t){return e.transaction(n=>{let o=e.prepare("SELECT * FROM task_prompts WHERE to_id = ? AND retrieved_ts IS NULL ORDER BY id").all(n);if(o.length===0)return o;let s=new Date().toISOString(),i=e.prepare("UPDATE task_prompts SET retrieved_ts = ? WHERE id = ? AND retrieved_ts IS NULL");for(let a of o)i.run(s,a.id),a.retrieved_ts=s;return o})(t)}function my(e,t){return e.prepare("SELECT task_id FROM task_prompts WHERE from_id = ? OR to_id = ? ORDER BY id DESC LIMIT 1").get(t,t)?.task_id??null}function fy(e,t){let r=e.prepare("SELECT * FROM task_prompts WHERE id = ?").get(t.promptId);if(r===void 0)throw new Error(`prompt: prompt #${t.promptId} does not exist`);if(gs(e,t.toTaskId)===null)throw new Error(`prompt: --task ${t.toTaskId} does not refer to an existing prompt task`);return e.transaction(()=>{e.prepare("INSERT INTO prompt_task_reassignments(prompt_id, from_task_id, to_task_id, reassigned_by, reassigned_at) VALUES (?, ?, ?, ?, ?)").run(t.promptId,r.task_id,t.toTaskId,t.reassignedBy,new Date().toISOString()),e.prepare("UPDATE task_prompts SET task_id = ? WHERE id = ?").run(t.toTaskId,t.promptId)}).immediate(),e.prepare("SELECT * FROM task_prompts WHERE id = ?").get(t.promptId)}function py(e,t){return e.prepare("SELECT * FROM prompt_task_reassignments WHERE prompt_id = ? ORDER BY id ASC").all(t)}function hy(e,t){return e.prepare(`SELECT task_id, MAX(created_at) AS last_message_at, COUNT(*) AS message_count
|
|
489
489
|
FROM task_prompts
|
|
490
490
|
WHERE task_id IS NOT NULL AND (from_id = ? OR to_id = ?)
|
|
491
491
|
GROUP BY task_id
|
|
492
|
-
ORDER BY last_message_at DESC`).all(t,t).map(n=>{let o=gs(e,n.task_id);if(o===null)throw new Error(`prompt: task #${n.task_id} referenced by task_prompts but missing from prompt_tasks`);return{task:o,lastPromptAt:n.last_message_at,promptCount:n.message_count}})}import{readFileSync as
|
|
493
|
-
ON CONFLICT(name) DO UPDATE SET teamfile_path = excluded.teamfile_path, alias = excluded.alias, updated_at = excluded.updated_at`).run(t,r,n,o)}function va(e,t){return t===Du?null:e.prepare("SELECT teamfile_path AS teamfilePath, alias FROM logical_names WHERE name = ?").get(t)??null}function
|
|
492
|
+
ORDER BY last_message_at DESC`).all(t,t).map(n=>{let o=gs(e,n.task_id);if(o===null)throw new Error(`prompt: task #${n.task_id} referenced by task_prompts but missing from prompt_tasks`);return{task:o,lastPromptAt:n.last_message_at,promptCount:n.message_count}})}import{readFileSync as NO}from"node:fs";function IO(e,t){return t?e.prepare("SELECT * FROM queue WHERE status = 'merged' AND merged_into_id IS NULL AND to_id = ? ORDER BY id").all(t):e.prepare("SELECT * FROM queue WHERE status = 'merged' AND merged_into_id IS NULL ORDER BY id").all()}function LO(e,t){let r=e.prepare("SELECT * FROM queue WHERE to_id = ? AND status IN ('sent', 'retrieved') ORDER BY id").all(t.to_id),n=Hc(t);for(let o of r){let s;try{s=NO(o.prompt_file,"utf8")}catch{continue}if(s.includes(n))return o}return null}function Ou(e,t){return IO(e,t).map(r=>({row:r,verifiedTarget:LO(e,r)}))}function gy(e,t){let r=Ou(e,t),n=e.prepare("UPDATE queue SET merged_into_id = ? WHERE id = ?"),o=0,s=[];for(let{row:i,verifiedTarget:a}of r)a?(n.run(a.id,i.id),o++):s.push(i);return{repaired:o,unverified:s}}function _y(e,t){let r=t?e.prepare("SELECT * FROM queue WHERE status = 'merged' AND merged_into_id IS NOT NULL AND expects_response = 1 AND to_id = ? ORDER BY id").all(t):e.prepare("SELECT * FROM queue WHERE status = 'merged' AND merged_into_id IS NOT NULL AND expects_response = 1 ORDER BY id").all(),n=[];for(let o of r){let s=e.prepare("SELECT * FROM queue WHERE id = ?").get(o.merged_into_id);s===void 0||s.expects_response||n.push({row:o,canonical:s})}return n}var Du="operator";function CO(e){if(e===Du)throw new Error(`logical_names: "${Du}" is reserved for the real operator entity (epic #162's #164) -- never a re-routable logical name`)}function wy(e,t,r,n,o=new Date().toISOString()){CO(t),e.prepare(`INSERT INTO logical_names(name, teamfile_path, alias, updated_at) VALUES (?, ?, ?, ?)
|
|
493
|
+
ON CONFLICT(name) DO UPDATE SET teamfile_path = excluded.teamfile_path, alias = excluded.alias, updated_at = excluded.updated_at`).run(t,r,n,o)}function va(e,t){return t===Du?null:e.prepare("SELECT teamfile_path AS teamfilePath, alias FROM logical_names WHERE name = ?").get(t)??null}function yy(e){return e.prepare("SELECT name, teamfile_path AS teamfilePath, alias, updated_at AS updatedAt FROM logical_names ORDER BY name").all()}function Ey(e,t){e.prepare("DELETE FROM logical_names WHERE name = ?").run(t)}function _s(e,t,r){let n=va(e,r);if(n===null)return null;for(let o of t){if(!B(o))continue;let s;try{s=Q(o)}catch{continue}if(s===n.teamfilePath)return{team:o.name,alias:n.alias}}return null}import{existsSync as OO,mkdirSync as DO,readFileSync as MO,renameSync as PO,writeFileSync as UO}from"node:fs";import{homedir as FO}from"node:os";import{dirname as qO,join as by}from"node:path";function Mu(e){let{row:t,answer:r}=e;return t.retracted_ts!==null?"RETRACTED":t.merged_into_id!==null?`MERGED->#${t.merged_into_id}`:r!==null?"ANSWERED":t.retrieved_ts!==null?"READ, no answer":t.status==="sent"?"NEVER RECEIVED":t.status.toUpperCase()}function Pu(e,t,r){let n=`
|
|
494
494
|
SELECT q.*, r.id AS ans_id, r.answered_at AS ans_answered_at, r.answer_text AS ans_text,
|
|
495
495
|
(SELECT COUNT(*) FROM answers s WHERE s.prompt_queue_id = q.id AND s.superseded_at IS NOT NULL) AS ans_superseded
|
|
496
496
|
FROM queue q
|
|
497
497
|
LEFT JOIN answers r ON r.prompt_queue_id = q.id AND r.superseded_at IS NULL
|
|
498
498
|
WHERE q.from_id = ?
|
|
499
|
-
`,o=[t];return r&&r.length>0&&(n+=` AND q.id IN (${r.map(()=>"?").join(",")})`,o.push(...r)),n+=" ORDER BY q.id DESC",e.prepare(n).all(...o).map(i=>({row:i,answer:i.ans_id===null?null:{id:i.ans_id,answeredAt:i.ans_answered_at,text:i.ans_text,supersededCount:i.ans_superseded}}))}function
|
|
499
|
+
`,o=[t];return r&&r.length>0&&(n+=` AND q.id IN (${r.map(()=>"?").join(",")})`,o.push(...r)),n+=" ORDER BY q.id DESC",e.prepare(n).all(...o).map(i=>({row:i,answer:i.ans_id===null?null:{id:i.ans_id,answeredAt:i.ans_answered_at,text:i.ans_text,supersededCount:i.ans_superseded}}))}function Ty(e){return e.filter(t=>t.answer===null&&t.row.retracted_ts===null&&t.row.merged_into_id===null)}function Sy(e,t){let r=t??process.env.LMBEE_SENDER_PULL_SEEN_DIR??by(FO(),".lmbee","sender-pull-seen");return by(r,`${e}.json`)}function Uu(e){try{let t=JSON.parse(MO(e,"utf8"));return new Map(Object.entries(t).map(([r,n])=>[Number(r),n]))}catch{return new Map}}function vy(e,t){let r=qO(e);OO(r)||DO(r,{recursive:!0});let n={};for(let[s,i]of t)n[String(s)]=i;let o=`${e}.tmp`;UO(o,JSON.stringify(n,null,1)),PO(o,e)}var jO=["team","escalation_attempt_count","last_escalation_attempt_ts","quota_exhausted_last_seen_ts","quota_exhausted_message"],Fu=jO.join(", ");function HO(e,t){return e.prepare(`SELECT ${Fu} FROM team_progress WHERE team = ?`).get(t)??null}function Ay(e,t){let r=e-Date.parse(t);return Number.isFinite(r)?r:null}function $y(e,t,r){function n(f,p){return t?e.prepare(`SELECT to_id, ${p} AS ts FROM queue WHERE status = ? AND to_id = ?`).all(f,t):e.prepare(`SELECT to_id, ${p} AS ts FROM queue WHERE status = ?`).all(f)}function o(f){let p=new Map;for(let h of f){let g=p.get(h.to_id);g?g.push(h.ts):p.set(h.to_id,[h.ts])}return p}let s=f=>{let p=f.reduce((h,g)=>h===null||g!==null&&g<h?g:h,null);return p===null?null:Ay(r,p)},i=f=>{let p=f.filter(g=>g!==null);if(p.length===0)return 0;let h=s(p);return h===null||!f.includes(null)?h:Math.max(0,h)},a=o(n("pending","created_ts")),c=o(n("escalating","escalation_claimed_ts")),l=f=>({escalationAttemptCount:f?.escalation_attempt_count??0,lastEscalationAttemptTs:f?.last_escalation_attempt_ts??null,quotaExhaustedLastSeenAgeMs:f?.quota_exhausted_last_seen_ts?Ay(r,f.quota_exhausted_last_seen_ts):null,quotaExhaustedMessage:f?.quota_exhausted_message??null}),u=new Set([...a.keys(),...c.keys()]),d=[...u].map(f=>{let p=a.get(f)??[],h=c.get(f)??[];return{toId:f,pendingCount:p.length,oldestPendingAgeMs:p.length>0?s(p):null,escalatingCount:h.length,oldestEscalatingAgeMs:h.length>0?i(h):null,...l(HO(e,f))}}),m=t?e.prepare(`SELECT ${Fu} FROM team_progress WHERE team = ? AND escalation_attempt_count > 0`).all(t):e.prepare(`SELECT ${Fu} FROM team_progress WHERE escalation_attempt_count > 0`).all();for(let f of m)u.has(f.team)||d.push({toId:f.team,pendingCount:0,oldestPendingAgeMs:null,escalatingCount:0,oldestEscalatingAgeMs:null,...l(f)});return d.sort((f,p)=>(p.oldestPendingAgeMs??-1)-(f.oldestPendingAgeMs??-1)),d}var er=Bt(Ct(),1);var KO=[".md",".txt",".json",".log",".yaml",".yml",".csv",".html",".htm",".xml"];function YO(e){if(/\s/.test(e)||!(e.startsWith("/")||e.startsWith("./")||KO.some(r=>e.toLowerCase().endsWith(r))))return!1;try{return WO(e)}catch{return!1}}function QO(e,t){return new Error(`${e}: prompt body looks like a file path that exists on disk: "${t}"
|
|
500
500
|
Did you mean @${t} ?
|
|
501
|
-
Pass --literal if you really meant to send the path as text.`)}function qr(e,t,r){if(t.startsWith("@"))return Hu(t.slice(1),"utf8");if(!r&&YO(t))throw
|
|
502
|
-
`:"",h=a&&B(a)?
|
|
503
|
-
`:"",E=p+h+_;if(a&&B(a))try{let S=await(n.fetchReport??ke)();if(je(a,S))return`${E}queued#${d} -> ${t} (pending; ${o} is presence-gated right now -- it won't push-deliver until that interactive session ends. ${o} can pull it early with \`queue retrieve ${o}\`, or you can check back later with \`queue deliver ${o}\`)`}catch{}return`${E}queued#${d} -> ${t} (${i})`}function
|
|
504
|
-
`}function
|
|
501
|
+
Pass --literal if you really meant to send the path as text.`)}function qr(e,t,r){if(t.startsWith("@"))return Hu(t.slice(1),"utf8");if(!r&&YO(t))throw QO(e,t);return t}async function Ny(e,t,r,n){let{baseId:o,alias:s}=an(t);if(o!=="operator"&&!e.teams.some(y=>y.name===o)){let y=_s(e.db.db,e.teams,o);y!==null&&(o=y.team,s=s??y.alias,t=s!==null?`${o}:${s}`:o)}let i=`pending; the cron will deliver it -- or run: queue deliver ${o}`,a=e.teams.find(y=>y.name===o);if(a&&B(a)){let y=s??a.leadAlias,S=tn(a);if(S.length>0&&!S.some(T=>T.alias===y))throw new Error(`enqueue: "${y}" is not a configured member of team "${o}" -- actual members: ${S.map(T=>T.alias).join(", ")}`)}if(n.inReplyTo!==void 0&&kr(e.db.db,n.inReplyTo)===null)throw new Error(`enqueue: --in-reply-to ${n.inReplyTo} does not refer to an existing queue prompt`);let c=n.isInteractiveTerminal??(process.stdin.isTTY===!0&&process.stdout.isTTY===!0),l=n.from==="operator"&&c,u=qr("enqueue",r,n.literal),d=we(e.db.db,e.teams,t,u,{from:n.from,...n.expectsResponse!==void 0?{expectsResponse:n.expectsResponse}:{},...n.inReplyTo!==void 0?{inReplyTo:n.inReplyTo}:{},...l?{operatorPriority:!0}:{}}),f=(n.readSiteLockStateImpl??ps)(e.db.path),p=f.kind==="free"?"warning: no lmbee daemon appears to be running against this database -- queue delivery, mail polling, and anti-churn nudging are all offline; this prompt will sit undelivered until `lmbee serve` is started (or deliver it manually with `queue deliver`).\n":f.kind==="unknown"?`warning: could not confirm whether an lmbee daemon is running against this database (the site lock could not be read) -- this is not evidence it is down.
|
|
502
|
+
`:"",h=a&&B(a)?XO(e,a,s??a.leadAlias,t):"",_=(n.inReplyTo===void 0?kr(e.db.db,d):null)?.expects_response===1&&!ZO(u)?`warning: expects-response is set but this prompt does not look like it is asking a question (no "?") -- consider --expects-response false if this is informational.
|
|
503
|
+
`:"",E=p+h+_;if(a&&B(a))try{let S=await(n.fetchReport??ke)();if(je(a,S))return`${E}queued#${d} -> ${t} (pending; ${o} is presence-gated right now -- it won't push-deliver until that interactive session ends. ${o} can pull it early with \`queue retrieve ${o}\`, or you can check back later with \`queue deliver ${o}\`)`}catch{}return`${E}queued#${d} -> ${t} (${i})`}function XO(e,t,r,n){let o;try{o=Q(t)}catch{return""}let s=Vt(t,r),i=s!==null?it(e.db.db,s):null,a=hs(e.db.db,o,r);if((i===null||!i.disabled)&&a===null)return"";let c=[];if(i!==null&&i.disabled){let m=i.config?.expiresAt?`disabled until ${i.config.expiresAt}`:"disabled indefinitely";c.push(`${n} is on ${s}, ${m}`)}a!==null&&c.push(`${n} was last observed evicted at ${a.observedAt} -- remedy: ${a.remedy}`);let l=m=>m.alias===r||m.provider===null||it(e.db.db,m.provider).disabled?!1:hs(e.db.db,o,m.alias)===null,u=tn(t).filter(l).map(m=>m.alias),d=u.length>0?`live seats on this team: ${u.join(", ")}`:"no other known-live seats on this team";return`warning: ${c.join("; ")}; ${d}.
|
|
504
|
+
`}function ZO(e){return e.includes("?")}function Bu(e,t){return{queue:Fc(e.db.db,t)}}function Iy(e,t,r={}){if(r.json)return JSON.stringify(Bu(e,t));let n=Fc(e.db.db,t).map(o=>[String(o.id),(0,er.escapeCell)(o.from_id),(0,er.escapeCell)(o.to_id),(0,er.escapeCell)(o.status),ge(o.created_ts),o.sent_ts!==null?ge(o.sent_ts):o.retrieved_ts!==null?ge(o.retrieved_ts):"-"]);return(0,er.formatTable)([["ID","FROM","TO","STATUS","CREATED","SENT/RETRIEVED"],...n])}function ro(e,t){return kr(e.db.db,t)}function Ly(e,t,r={}){let n=ro(e,t);return r.json?JSON.stringify(n?{queue:n}:Ae("queue_not_found",`no queue entry ${t}`)):n?`queue#${n.id} ${n.from_id} -> ${n.to_id} [${n.status}] prompt=${n.prompt_file} created ${n.created_ts} sent ${n.sent_ts??"-"} retrieved ${n.retrieved_ts??"-"}`:`no queue entry ${t}`}var qu=64*1024;function ky(e){if(e===null)return null;let t=Buffer.byteLength(e.answer_text,"utf8");if(t<=qu)return{...e,byteLength:t,totalBytes:t,truncated:!1};let r=Buffer.from(e.answer_text,"utf8").subarray(0,qu).toString("utf8");for(;Buffer.byteLength(r,"utf8")>qu;)r=r.slice(0,-1);return{...e,answer_text:r,byteLength:Buffer.byteLength(r,"utf8"),totalBytes:t,truncated:!0}}function ws(e,t){let r=kr(e.db.db,t);if(r===null)return null;let n=De(e.db.db,t),o=jg(e.db.db,t).map(s=>ky(s)).filter(s=>s!==null);return{id:r.id,createdAt:r.created_ts,answer:ky(n),answerHistory:o,mergedInto:r.status==="merged"?iu(e.db.db,r)?.id??null:null,...xt(r,n)}}function Cy(e,t,r={}){let n=ws(e,t);if(r.json)return JSON.stringify(n?{state:n}:Ae("queue_not_found",`no queue entry ${t}`));if(n===null)return`no queue entry ${t}`;let o;if(n.answerHistory.length>1){let i=n.answerHistory.map(a=>{let c=a.superseded_at!==null?`superseded ${a.superseded_at}`:"current";return` answered ${a.answered_at} (${c}): ${a.answer_text}${a.truncated?` \u2026 [truncated, ${a.totalBytes} bytes total]`:""}`});o=`
|
|
505
505
|
answer history (${i.length} answers, amended ${i.length-1}x):
|
|
506
506
|
${i.join(`
|
|
507
507
|
`)}`}else o=n.answer?`
|
|
508
|
-
answer: ${n.answer.answer_text}${n.answer.truncated?` \u2026 [truncated, ${n.answer.totalBytes} bytes total]`:""}`:"";let s=n.mergedInto!==null?` -> #${n.mergedInto}`:"";return`queue#${n.id} [${n.lifecycle}/${n.lifecycleBasis}${s}] created ${n.createdAt} pulled ${n.pulledAt??"-"}${o}`}function
|
|
509
|
-
`),exitCode:u}}function
|
|
508
|
+
answer: ${n.answer.answer_text}${n.answer.truncated?` \u2026 [truncated, ${n.answer.totalBytes} bytes total]`:""}`:"";let s=n.mergedInto!==null?` -> #${n.mergedInto}`:"";return`queue#${n.id} [${n.lifecycle}/${n.lifecycleBasis}${s}] created ${n.createdAt} pulled ${n.pulledAt??"-"}${o}`}function Oy(e,t,r,n,o={}){let s=qr("queue answer",n,o.literal),i=_s(e.db.db,e.teams,r),a=i!==null?i.team:r;try{let c=o.amend?Qg(e.db.db,t,a,s):gn(e.db.db,t,a,s);return{output:o.json?JSON.stringify({answer:c}):o.amend?`amended queue#${t} (answer#${c.id}, recorded ${c.answered_at}, superseding a prior answer)`:`answered queue#${t} (answer#${c.id}, recorded ${c.answered_at})`,exitCode:0}}catch(c){if(c instanceof C)return{output:o.json?JSON.stringify(Ae(c.code,c.message)):`${c.code}: ${c.message}`,exitCode:c.exitCode};throw c}}function Dy(e,t,r,n,o={}){let s=qr("queue answer",n,o.literal),i=_s(e.db.db,e.teams,r),a=i!==null?i.team:r,c=t.map(m=>{try{let f=gn(e.db.db,m,a,s);return{id:m,ok:!0,answerId:f.id,answeredAt:f.answered_at}}catch(f){if(f instanceof C)return{id:m,ok:!1,code:f.code,message:f.message};throw f}}),u=c.filter(m=>!m.ok).length>0?1:0;return o.json?{output:JSON.stringify({outcomes:c}),exitCode:u}:{output:c.map(m=>m.ok?`answered queue#${m.id} (answer#${m.answerId}, recorded ${m.answeredAt})`:`queue#${m.id}: ${m.code}: ${m.message}`).join(`
|
|
509
|
+
`),exitCode:u}}function My(e,t,r,n,o={}){let s=qr("queue resolve",n,o.literal);try{let i=o.amend?Xg(e.db.db,t,r,s):Yg(e.db.db,t,r,s);return{output:o.json?JSON.stringify({answer:i}):o.amend?`amended resolution for queue#${t} as proxy for operator (answer#${i.id}, recorded ${i.answered_at}, superseding a prior resolution)`:`resolved queue#${t} as proxy for operator (answer#${i.id}, recorded ${i.answered_at})`,exitCode:0}}catch(i){if(i instanceof C)return{output:o.json?JSON.stringify(Ae(i.code,i.message)):`${i.code}: ${i.message}`,exitCode:i.exitCode};throw i}}function Py(e,t,r,n,o={}){try{let s=Gg(e.db.db,t,r,n,{noNotice:o.noNotice});return o.json?{output:JSON.stringify(s),exitCode:0}:{output:s.kind==="deleted"?`deleted queue#${t} (never retrieved): ${s.reason}`:s.kind==="retracted-with-notice"?`retracted queue#${t}: ${s.row.retracted_reason} -- fresh notice sent as queue#${s.noticeId} (was already retrieved, unanswered)`:`retracted queue#${t}: ${s.row.retracted_reason}${o.noNotice?" -- no notice sent (--no-notice)":""}`,exitCode:0}}catch(s){if(s instanceof C)return{output:o.json?JSON.stringify(Ae(s.code,s.message)):`${s.code}: ${s.message}`,exitCode:s.exitCode};throw s}}function Uy(e,t,r={}){let n=Date.now(),o=Vg(e.db.db,t,n);if(r.json)return{output:JSON.stringify({candidates:o}),exitCode:0};if(o.length===0)return{output:`${t}: no redelivery candidates (nothing dispatched-but-unconfirmed)`,exitCode:0};let s=o.map(i=>` #${i.row.id} from ${i.row.from_id}, sent ${fe(i.ageMs)} ago -- \`lmbee queue redeliver ${i.row.id} --reason "<why>"\``);return{output:`${t}: ${o.length} redelivery candidate(s) (dispatched, never confirmed -- a refreshed session has no record of these):
|
|
510
510
|
${s.join(`
|
|
511
|
-
`)}`,exitCode:0}}function
|
|
511
|
+
`)}`,exitCode:0}}function Fy(e,t,r,n={}){try{let o=Jg(e.db.db,t,r);return{output:n.json?JSON.stringify({row:o}):`requeued queue#${t} for redelivery (status: ${o.status})`,exitCode:0}}catch(o){if(o instanceof C)return{output:n.json?JSON.stringify(Ae(o.code,o.message)):`${o.code}: ${o.message}`,exitCode:o.exitCode};throw o}}function qy(e,t,r,n={}){let o=new Date().toISOString();return wf(e.db.db,t,r??null,o),{output:n.json?JSON.stringify({team:t,pausedAt:o,reason:r??null}):`${t}: queue delivery paused${r?` (${r})`:""} -- manual lctl chat/nudge/enqueue unaffected; \`lmbee queue resume ${t}\` to lift`,exitCode:0}}function jy(e,t,r={}){let n=yf(e.db.db,t);return{output:r.json?JSON.stringify({team:t,wasPaused:n}):n?`${t}: queue delivery resumed`:`${t}: queue delivery was not paused`,exitCode:0}}function Hy(e,t,r={}){if(t!==void 0){let s=gf(e.db.db,t);return r.json?{output:JSON.stringify({team:t,paused:s!==null,state:s}),exitCode:0}:s===null?{output:`${t}: queue delivery is not paused`,exitCode:0}:{output:`${t}: queue delivery PAUSED since ${s.pausedAt}${s.reason?` (${s.reason})`:""}`,exitCode:0}}let n=_f(e.db.db);if(r.json)return{output:JSON.stringify({paused:n}),exitCode:0};if(n.length===0)return{output:"no teams have queue delivery paused",exitCode:0};let o=n.map(s=>` ${s.team}: paused since ${s.pausedAt}${s.reason?` (${s.reason})`:""}`);return{output:`queue delivery paused (${n.length}):
|
|
512
512
|
${o.join(`
|
|
513
|
-
`)}`,exitCode:0}}function Aa(e,t={}){let{rows:r,meta:n}=jc(e.db.db,t);return{rows:r.map(o=>({...o,...xt(o,De(e.db.db,o.id))})),meta:n}}function Wu(e,t={}){return jc(e.db.db,t)}var ju=32*1024;function jr(e,t){let r=kr(e.db.db,t);if(!r)return null;let n=new Date().toISOString(),o=u=>({id:t,status:u,text:null,byteLength:null,truncated:!1,sourceModifiedAt:null,fetchedAt:n}),s=u=>u.code==="ENOENT",i;try{i=
|
|
513
|
+
`)}`,exitCode:0}}function Aa(e,t={}){let{rows:r,meta:n}=jc(e.db.db,t);return{rows:r.map(o=>({...o,...xt(o,De(e.db.db,o.id))})),meta:n}}function Wu(e,t={}){return jc(e.db.db,t)}var ju=32*1024;function jr(e,t){let r=kr(e.db.db,t);if(!r)return null;let n=new Date().toISOString(),o=u=>({id:t,status:u,text:null,byteLength:null,truncated:!1,sourceModifiedAt:null,fetchedAt:n}),s=u=>u.code==="ENOENT",i;try{i=JO(r.prompt_file)}catch(u){return o(s(u)?"missing":"unreadable")}let a,c;try{let u=zO(i);if(!u.isFile())return o("unreadable");a=u.size,c=u.mtime.toISOString()}catch(u){return o(s(u)?"missing":"unreadable")}let l;try{l=GO(i,"r")}catch{return o("unreadable")}try{let u=Buffer.alloc(ju),d=VO(l,u,0,ju,0);return{id:t,status:"available",text:u.subarray(0,d).toString("utf8"),byteLength:d,truncated:a>ju,sourceModifiedAt:c,fetchedAt:n}}catch{return o("unreadable")}finally{BO(l)}}async function By(e,t,r={}){let o=await(r.fetchReport??ke)();return`queue deliver: dispatched ${xr(e.db.db,{teams:e.teams,teamName:t,report:o})} pending prompt(s)`}function Wy(e,t,r={}){let n=ui(e.db.db,t,r.id),o=r.id===void 0?dy(e.db.db,t):[];if(n.length===0&&o.length===0)return`queue retrieve ${t}: nothing pending`;let s=n.map(c=>{let l;try{l=Hu(c.prompt_file,"utf8")}catch{l="(could not read prompt file)"}return`#${c.id} from ${c.from_id} (${c.created_ts}):
|
|
514
514
|
${l}`}),i=o.map(c=>`[task-prompt] #${c.id} from ${c.from_id} (${c.created_at}):
|
|
515
515
|
${c.prompt}`),a=n.length+o.length;return`queue retrieve ${t}${r.id===void 0?"":` #${r.id}`}: ${a} prompt(s)
|
|
516
516
|
|
|
517
517
|
${[...s,...i].join(`
|
|
518
518
|
|
|
519
|
-
`)}`}function
|
|
519
|
+
`)}`}function eD(e,t){if(t==="operator"||e.teams.some(n=>n.name===t))return t;let r=_s(e.db.db,e.teams,t);if(r!==null)return r.team;throw new Error(`queue inbox: "${t}" is not a registered team, "operator", or a resolvable logical name`)}function Gu(e,t){let r=eD(e,t),n=[...Hg(e.db.db,r),...li(e.db.db,r)];n.sort((s,i)=>s.id-i.id);let o=uy(e.db.db,r);return{pending:n,taskPrompts:o}}function Gy(e,t,r={}){let n=Gu(e,t),o=r.promptsOnly===!0?n.pending.filter(a=>a.in_reply_to===null):n.pending;if(r.json)return JSON.stringify({pending:o,taskPrompts:n.taskPrompts});let s=o.length+n.taskPrompts.length;if(s===0)return`queue inbox ${t}: nothing pending (queue or task prompts)`;let i=o.map(a=>{let c=a.in_reply_to!==null?`PROMPT -> #${a.in_reply_to}`:"PROMPT";if(a.status==="merged"){let d=iu(e.db.db,a),m=d!==null?` -> #${d.id}`:"";return{ts:a.created_ts,text:`[queue] #${a.id} from ${a.from_id} (${ge(a.created_ts)}) ${c} status=merged${m} prompt=${a.prompt_file}`}}let l=xt(a,De(e.db.db,a.id)),u=l.lifecycle==="queued"?"Queued":l.lifecycle==="processing"?"Processing":"Finished";return{ts:a.created_ts,text:`[queue] #${a.id} from ${a.from_id} (${ge(a.created_ts)}) ${c} status=${u} prompt=${a.prompt_file}`}});for(let a of n.taskPrompts){let c=a.task_id!==null?`task #${a.task_id}`:"no task";i.push({ts:a.created_at,text:`[task-prompt] #${a.id} from ${a.from_id} (${ge(a.created_at)}) ${c}: ${a.prompt}`})}return i.sort((a,c)=>a.ts.localeCompare(c.ts)),`queue inbox ${t}: ${s} pending (${o.length} queue, ${n.taskPrompts.length} task prompts)
|
|
520
520
|
${i.map(a=>a.text).join(`
|
|
521
|
-
`)}`}function
|
|
521
|
+
`)}`}function Vy(e,t,r={}){let n=hn(e.db.db,t,Date.now(),e.teams.map(s=>s.name));if(r.idsOnly)return n.map(s=>s.row.id).join(",");if(r.json)return JSON.stringify({owed:n});if(n.length===0)return`${t}: nothing owed`;let o=n.map(s=>` #${s.row.id} from ${s.row.from_id}, ${fe(s.ageMs)} ago${s.hasReplyTrafficSince?" (likely answered in prose, row still open)":""}`);return`${t}: ${n.length} owed answer(s):
|
|
522
522
|
${o.join(`
|
|
523
|
-
`)}`}function
|
|
523
|
+
`)}`}function Jy(e,t,r={}){let n=hn(e.db.db,t,Date.now()).filter(s=>s.hasReplyTrafficSince);if(r.idsOnly)return n.map(s=>s.row.id).join(",");if(r.json)return JSON.stringify({likelyAnswered:n});if(n.length===0)return`${t}: nothing likely-answered-but-unclosed`;let o=n.map(s=>` #${s.row.id} from ${s.row.from_id}, ${fe(s.ageMs)} ago`);return`${t}: ${n.length} row(s) with reply traffic since the prompt, unclosed -- reply traffic is not proof of an answer, review before closing:
|
|
524
524
|
${o.join(`
|
|
525
525
|
`)}
|
|
526
|
-
close with: queue answer ${n.map(s=>s.row.id).join(",")} <text|@file> --from ${t}`}function
|
|
526
|
+
close with: queue answer ${n.map(s=>s.row.id).join(",")} <text|@file> --from ${t}`}function xy(e){if(!e)return"";let t=Date.now()-Date.parse(e);if(!Number.isFinite(t))return"";let r=Math.floor(t/6e4);if(r<60)return`${r}m`;let n=Math.floor(t/36e5);return n<24?`${n}h`:`${Math.floor(t/864e5)}d`}var Ry=600;function zy(e,t,r={}){let n=r.seenPath??Sy(t);if(r.mark!==void 0){let c=Uu(n),l=Array.isArray(r.mark)?r.mark:Pu(e.db.db,t).filter(d=>d.answer!==null&&!c.has(d.row.id)).map(d=>d.row.id),u=new Date().toISOString();for(let d of l)c.set(d,u);return vy(n,c),`marked ${l.length} pulled`}let o=Uu(n),s=r.ids!==void 0&&r.ids.length>0,i=Pu(e.db.db,t,r.ids);if(!s&&!r.all&&(i=r.open?Ty(i):i.filter(c=>c.answer!==null&&!o.has(c.row.id))),r.json)return JSON.stringify(i.map(c=>({id:c.row.id,to:c.row.to_id,alias:c.row.to_alias,state:Mu(c),answeredAt:c.answer?.answeredAt??null,superseded:c.answer?.supersededCount??0,pulled:o.has(c.row.id),answer:c.answer?.text??null})));if(i.length===0)return`queue pull(${t}): nothing to pull`;let a=[];for(let c of i){let l=`#${c.row.id} -> ${c.row.to_id} ${Mu(c)}`;if(c.answer!==null?(l+=` answered ${xy(c.answer.answeredAt)} ago`,c.answer.supersededCount>0&&(l+=` (${c.answer.supersededCount} superseded)`),o.has(c.row.id)&&(l+=" [already pulled]")):(c.row.sent_ts??c.row.created_ts)&&(l+=` sent ${xy(c.row.sent_ts??c.row.created_ts)} ago`),a.push(l),c.answer!==null&&c.answer.text){let u=c.answer.text.trim();!r.full&&u.length>Ry&&(u=`${u.slice(0,Ry)}
|
|
527
527
|
... (--full for the rest)`),a.push(u.split(`
|
|
528
528
|
`).map(d=>` ${d}`).join(`
|
|
529
529
|
`)),a.push("")}}return!s&&!r.all&&!r.open&&a.push(`-- ${i.length} unpulled answer(s). \`--mark\` to clear, \`--full\` for whole text.`),a.join(`
|
|
530
|
-
`).replace(/\n+$/,"")}function Vu(e,t,r=Date.now()){return{stats
|
|
530
|
+
`).replace(/\n+$/,"")}function Vu(e,t,r=Date.now()){return{stats:$y(e.db.db,t,r)}}function tD(e){let t=e/36e5;return t<24?`${Math.round(t)}h ago`:`${Math.round(t/24)}d ago`}function Ky(e,t,r={}){let n=Vu(e,t);if(r.json)return JSON.stringify(n);if(n.stats.length===0)return t?`queue stats ${t}: nothing pending`:"queue stats: nothing pending anywhere";let o=n.stats.map(s=>[(0,er.escapeCell)(s.toId),String(s.pendingCount),s.oldestPendingAgeMs!==null?fe(s.oldestPendingAgeMs):"-",String(s.escalatingCount),s.oldestEscalatingAgeMs!==null?fe(s.oldestEscalatingAgeMs):"-",String(s.escalationAttemptCount),s.lastEscalationAttemptTs!==null?ge(s.lastEscalationAttemptTs):"-",s.quotaExhaustedLastSeenAgeMs!==null?tD(s.quotaExhaustedLastSeenAgeMs):"-"]);return(0,er.formatTable)([["TO","PENDING","OLDEST AGE","ESCALATING","ESCALATING AGE","ESCALATION ATTEMPTS","LAST ESCALATION","QUOTA EXHAUSTED"],...o])}function Yy(e,t){let r=(t??7)*24*60*6e4;return`queue gc: removed ${Kf(e.db.db,{retentionMs:r})} prompt file(s) older than ${t??7} day(s)`}function rD(e,t,r){let n=_y(e.db.db,t);if(r)return JSON.stringify(n.map(({row:s,canonical:i})=>({id:s.id,from:s.from_id,to:s.to_id,created_ts:s.created_ts,merged_into_id:i.id})));if(n.length===0)return`queue doctor${t?` ${t}`:""} --swallowed: no expects_response rows silently absorbed by a false-canonical merge`;let o=[`queue doctor${t?` ${t}`:""} --swallowed: ${n.length} expects_response row(s) folded into a canonical that itself reads as "nothing owed" -- REPORT ONLY, triage each before repairing anything:`,""];for(let{row:s,canonical:i}of n){let a="(prompt file unreadable)";try{a=Hu(s.prompt_file,"utf8").split(`
|
|
531
531
|
`)[0]??""}catch{}o.push(` #${s.id} from ${s.from_id} to ${s.to_id}, ${ge(s.created_ts)} -- merged into #${i.id}: "${a}"`)}return o.join(`
|
|
532
|
-
`)}function
|
|
532
|
+
`)}function Qy(e,t,r={}){if(r.swallowed===!0)return rD(e,t,r.json);if(r.repair===!0){let l=gy(e.db.db,t);if(r.json)return JSON.stringify({repaired:l.repaired,unverified:l.unverified.map(d=>d.id)});let u=[`queue doctor${t?` ${t}`:""}: repaired ${l.repaired} row(s) with a verified merge target`];return l.unverified.length>0&&(u.push(`${l.unverified.length} row(s) could NOT be verified (left untouched, original content still in their own prompt_file):`),u.push(...l.unverified.map(d=>` #${d.id} from ${d.from_id} to ${d.to_id} (${d.created_ts}) prompt=${d.prompt_file}`))),u.join(`
|
|
533
533
|
`)}let n=Ou(e.db.db,t);if(r.json)return JSON.stringify(n.map(({row:l,verifiedTarget:u})=>({id:l.id,from:l.from_id,to:l.to_id,created_ts:l.created_ts,verifiedTarget:u?.id??null})));if(n.length===0)return`queue doctor${t?` ${t}`:""}: no orphan-merged rows (status='merged' AND merged_into_id IS NULL)`;let o=n.filter(l=>l.verifiedTarget!==null),s=n.filter(l=>l.verifiedTarget===null),i=new Map;for(let{row:l,verifiedTarget:u}of n){let d=i.get(l.to_id)??{verified:0,unverified:0};u!==null?d.verified++:d.unverified++,i.set(l.to_id,d)}let a=[...i.entries()].sort((l,u)=>u[1].unverified-l[1].unverified||u[1].verified-l[1].verified),c=[`queue doctor${t?` ${t}`:""}: ${n.length} orphan-merged row(s) -- ${o.length} verified delivered (run --repair to record), ${s.length} genuine unknown(s)`,...(0,er.formatTable)([["RECIPIENT","VERIFIED","UNVERIFIED"],...a.map(([l,u])=>[(0,er.escapeCell)(l),String(u.verified),String(u.unverified)])]).split(`
|
|
534
534
|
`)];return s.length>0&&(c.push("","Unverified rows (no delivered target found anywhere; original content still in their own prompt_file):"),c.push(...s.map(({row:l})=>` #${l.id} from ${l.from_id} to ${l.to_id} (${l.created_ts}) prompt=${l.prompt_file}`))),c.join(`
|
|
535
|
-
`)}import{readFileSync as
|
|
536
|
-
active: ${r.active.length?r.active.join(","):"(none)"}`}function
|
|
537
|
-
${s}`}function
|
|
538
|
-
WARNING: ${a.leadAlias}'s own session does not resolve -- session not found${l}. Reopening alone will NOT make this team reachable; run \`lmctl refresh ${t}.lmctl ${a.leadAlias}\` first.`}}catch{}return i}function
|
|
535
|
+
`)}import{readFileSync as nD,statSync as oD}from"node:fs";var no=Bt(Ct(),1);function $a(e,t,r){let n;try{n=oD(t)}catch{return{output:`error: source not found: ${t}`,ok:!1}}if(!n.isFile())return{output:`error: source must be a regular file (a teams.conf-style TSV or a teams.md), not a directory: ${t}`,ok:!1};let o=t.toLowerCase(),s=o.endsWith(".md");if(!s&&!o.endsWith(".conf"))return{output:`error: source must end in .conf or .md: ${t}`,ok:!1};let i;try{i=nD(t,"utf8")}catch(l){return{output:`error: could not read source ${t}: ${l instanceof Error?l.message:String(l)}`,ok:!1}}let a=s?$c(i):Co(i);if(a.length===0)return{output:`error: source parsed to zero teams, not registered: ${t}`,ok:!1};Ks(e.db.db,t,r??null);let c=a.map(l=>l.name).join(", ");return{output:`source added: ${t} (${a.length} team${a.length===1?"":"s"}: ${c})`,ok:!0}}function Ju(e){return{defaultTeamsConfPath:e.teamsConfPath,sources:kc(e.db.db)}}function Xy(e,t={}){let r=Ju(e);if(t.json)return JSON.stringify(r);let n=["-",(0,no.escapeCell)(r.defaultTeamsConfPath),"(default, always scanned)"],o=r.sources.map(s=>[String(s.id),(0,no.escapeCell)(s.path),(0,no.escapeCell)(s.label??"")]);return(0,no.formatTable)([["ID","PATH","LABEL"],n,...o])}function Zy(e,t){return Ys(e.db.db,t),`source removed: ${t}`}import{execFile as sD}from"node:child_process";import{promisify as iD}from"node:util";var oo=Bt(Ct(),1);var aD=iD(sD);function eE(e,t){return{team:t,state:qe(e.db.db,t),progress:se(e.db.db,t),last_nudged:el(e.db.db,t)}}function zu(e){let t=e.teams.map(n=>eE(e,n.name)),r=Qs(e.db.db)??[];return{teams:t,active:r}}function Ku(e,t){return{team:eE(e,t)}}var cD=new Set(["DONE"]);function tE(e,t={}){let r=zu(e),n=t.nonDone?r.teams.filter(i=>!cD.has(i.state?.status??"")):r.teams;if(t.json)return JSON.stringify({...r,teams:n});let o=n.map(i=>[(0,oo.escapeCell)(i.team),(0,oo.escapeCell)(i.state?.status??"?"),i.state?.changed_ts?ge(i.state.changed_ts):"-",i.state?.last_ts?ge(i.state.last_ts):"-",(0,oo.escapeCell)(i.progress?.progress_status??"?"),i.progress?.confirmed_done_ts?"yes":"-"]);return`${(0,oo.formatTable)([["TEAM","STATUS(self-report)","CHANGED","LAST","PROGRESS","CONFIRMED-DONE"],...o])}
|
|
536
|
+
active: ${r.active.length?r.active.join(","):"(none)"}`}function rE(e,t,r={}){let{team:n}=Ku(e,t);if(r.json)return JSON.stringify({team:n});let o=n.state?`self-report: ${n.state.status} (changed ${n.state.changed_ts}, last ${n.state.last_ts})`:"self-report: (no state)",s=`progress: ${n.progress?.progress_status??"(never scanned)"}`+(n.progress?.confirmed_done_ts?` -- MAINTAINER-CONFIRMED DONE at ${n.progress.confirmed_done_ts}`:"");return`${t}: ${o}
|
|
537
|
+
${s}`}function nE(e,t,r,n,o=Date.now()){return mr(e.db.db,t,r,o),ot(e.db.db,t,r,o,{note:n||"manual state set"}),`state set ${t} -> ${r}`}function oE(e,t,r,n=Date.now()){let o=new Date(n).toISOString();return mc(e.db.db,t,o),ot(e.db.db,t,"confirmed-done",n,{note:r||"maintainer confirmed done"}),`${t}: confirmed done at ${o} -- stalled-flagging and auto-nudge suppressed until new work or \`state reopen ${t}\``}async function sE(e,t,r,n=Date.now(),o=aD){let s=se(e.db.db,t)?.confirmed_done_ts!=null;mc(e.db.db,t,null),ot(e.db.db,t,"reopened",n,{note:r||"maintainer reopened"});let i=s?`${t}: reopened -- confirmed-done cleared`:`${t}: reopened -- was not confirmed-done, nothing to clear`,a=e.teams.find(c=>c.name===t);if(a===void 0||!B(a))return i;try{let c=await us(Q(a),a.leadAlias,o);if(!c.sessionResolves){let l=c.provider?` (provider=${c.provider})`:"";return`${i}
|
|
538
|
+
WARNING: ${a.leadAlias}'s own session does not resolve -- session not found${l}. Reopening alone will NOT make this team reachable; run \`lmctl refresh ${t}.lmctl ${a.leadAlias}\` first.`}}catch{}return i}function Yu(e){return{active:Qs(e.db.db)??[]}}function iE(e,t={}){let r=Yu(e);return t.json?JSON.stringify(r):`active: ${r.active.length?r.active.join(","):"(none)"}`}var so=Bt(Ct(),1);function lD(e,t){return B(e)?je(e,t)?"Running":cn(e,t)?"Dead(reclaimable)":"Idle":"remote -- delivery only"}async function Qu(e,t={}){let r=null;t.live&&(r=await(t.fetchReport??ke)());let n=e.teams.map(u=>{let d=qe(e.db.db,u.name),m=Jf(e.db.db,u.name).length,f={team:u.name,status:d?.status??null,changedTs:d?.changed_ts??null,pending:m};return t.live&&r&&(f.live=lD(u,r)),f}),s=await(t.checkActiveGhAccountImpl??pa)(),i=s!==null&&!s.matchesPolicy?s:null,c=(t.readSiteLockStateImpl??ps)(e.db.path),l=c.kind==="held"?{running:!0,pid:c.identity.pid,ownerLabel:c.identity.ownerLabel,startedAt:c.identity.startedAt,unconfirmed:!1}:{running:!1,pid:null,ownerLabel:null,startedAt:null,unconfirmed:c.kind==="unknown"};return{live:t.live===!0,teams:n,ghAccountMismatch:i,daemon:l}}async function aE(e,t={}){let r=await Qu(e,t);if(t.json)return JSON.stringify(r);let n=r.live?["TEAM","LAST-STATUS","CHANGED","PENDING","LIVE"]:["TEAM","LAST-STATUS","CHANGED","PENDING"],o=r.teams.map(a=>{let c=[(0,so.escapeCell)(a.team),(0,so.escapeCell)(a.status??"?"),a.changedTs===null?"-":ge(a.changedTs),String(a.pending)];return r.live?[...c,(0,so.escapeCell)(a.live??"")]:c}),s=(0,so.formatTable)([n,...o]),i=[];return i.push(r.daemon.unconfirmed?"!!! DAEMON STATE COULD NOT BE CONFIRMED -- the site lock could not be read (a transient error, or a race with a concurrent lock operation). This is NOT evidence the daemon is down -- do not act on it as if it were; re-run status, or check `systemctl --user status lmbee.service`. !!!":r.daemon.running?`daemon: running (pid ${r.daemon.pid}, ${r.daemon.ownerLabel}, started ${r.daemon.startedAt})`:"!!! DAEMON NOT RUNNING -- queue delivery, mail polling, and anti-churn nudging are all OFFLINE. A prompt accepted by `enqueue` will sit undelivered until `lmbee serve` is started. !!!"),r.ghAccountMismatch!==null&&i.push(`!!! GH ACCOUNT POLICY MISMATCH: "${r.ghAccountMismatch.account}" is the active account on this machine -- policy requires "${fu}". DO NOT PUSH until this is switched back. !!!`),i.push(s),i.join(`
|
|
539
539
|
|
|
540
|
-
`)}var Hr=Bt(Ct(),1);function Xu(e){return{teams:e.teams}}function
|
|
540
|
+
`)}var Hr=Bt(Ct(),1);function Xu(e){return{teams:e.teams}}function cE(e,t={}){if(t.json)return JSON.stringify(Xu(e));let r=e.teams.map(n=>B(n)?[(0,Hr.escapeCell)(n.name),(0,Hr.escapeCell)(n.leadAlias),(0,Hr.escapeCell)(n.promptName),(0,Hr.escapeCell)(n.description)]:[(0,Hr.escapeCell)(n.name),"(remote)","--","--"]);return(0,Hr.formatTable)([["TEAM","LEAD","PROMPT","WHAT-IT-DOES"],...r])}function uD(e){let t=e.LMCTL_AUTH_URL?.trim()||e.LMCTL_AUTH_BASE_URL?.trim();return t?t.replace(/\/+$/,""):void 0}async function Zu(e={}){let t=e.env??process.env,r=e.resolveAppkeyImpl??ve,n=e.validateAppkeyImpl??am,o=uD(t),s;try{s=r({env:t})}catch(a){return{data:Ae("no_appkey",a instanceof Error?a.message:String(a)),exitCode:3}}let i;try{i=await n(s.appkey,{env:t,...o!==void 0?{authBaseUrl:o}:{}})}catch(a){return{data:Ae("auth_unreachable",`could not validate appkey: ${a instanceof Error?a.message:String(a)}`),exitCode:4}}return i.valid?{data:{userId:i.userId,label:i.label,appkeySource:s.source},exitCode:0}:{data:Ae("invalid_appkey",`appkey is invalid (source: ${s.source})`),exitCode:3}}async function lE(e={}){let{data:t,exitCode:r}=await Zu(e);return e.json?{output:JSON.stringify(t),exitCode:r}:"error"in t?{output:t.error.message,exitCode:r}:{output:`user_id: ${t.userId}
|
|
541
541
|
label: ${t.label}
|
|
542
|
-
appkey source: ${t.appkeySource}`,exitCode:r}}import{execFile as
|
|
542
|
+
appkey source: ${t.appkeySource}`,exitCode:r}}import{execFile as dD}from"node:child_process";import{promisify as mD}from"node:util";var fD=mD(dD);async function uE(e,t=3e4){let r=e.trim().split(/\s+/).filter(Boolean),{stdout:n}=await fD("lmctl",["status",...r,"--json"],{timeout:t}),o;try{o=JSON.parse(n)}catch(s){throw new Error(`unexpected \`lmctl status --json\` output (not valid JSON): ${s instanceof Error?s.message:String(s)}`)}if(typeof o!="object"||o===null||Array.isArray(o))throw new Error("unexpected `lmctl status --json` shape: expected a JSON object");return o}import{execFile as pD}from"node:child_process";import{existsSync as hD}from"node:fs";import{promisify as gD}from"node:util";var _D=gD(pD),ka=class extends Error{constructor(){super("LMBI_SUBSCRIPTION_CLI is not set -- point it at lmbi's own reviewed subscription-report-cli.js (see the lmbi subscription contract for the current staged path) before running this command."),this.name="SubscriptionCliNotConfiguredError"}};async function ed(e){let t=e.cliPath??process.env.LMBI_SUBSCRIPTION_CLI;if(t===void 0||t==="")throw new ka;let r=e.execFileImpl??_D,{stdout:n}=await r("node",[t,e.configPath,"--json"],{timeout:e.timeoutMs??3e4});return JSON.parse(n)}async function dE(e={}){let t=e.configPath??process.env.LMBI_SUBSCRIPTION_CONFIG_PATH;if(t===void 0||t===""||!hD(t))return{status:200,body:{needs_configuration:!0}};try{return{status:200,body:await ed({configPath:t,cliPath:e.cliPath,execFileImpl:e.execFileImpl})}}catch(r){return r instanceof ka?{status:500,body:{error:r.message}}:{status:502,body:{error:r instanceof Error?r.message:String(r)}}}}import{createHash as gE,randomBytes as ED,timingSafeEqual as bD}from"node:crypto";var mE=e=>{let t=e.env.server?e.env.server:e.env,r=t.incoming.socket.remoteAddress,n=t.incoming.socket.remotePort,o=t.incoming.socket.remoteFamily;return{remote:{address:r,port:n,addressType:o==="IPv4"?"IPv4":o==="IPv6"?"IPv6":void 0}}};import{createHash as fE}from"node:crypto";import{basename as wD}from"node:path";function v(e){return String(e??"").replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t])}var pE="body{font:1rem/1.45 system-ui,sans-serif;margin:1rem;color:#111;background:#fff}main,header,footer{max-width:90rem}h1{font-size:1.5rem;margin:.7rem 0}h2{font-size:1.2rem;margin:1rem 0 .4rem}p{margin:.5rem 0}a{color:#0645ad;overflow-wrap:anywhere}table{border-collapse:collapse;width:100%;min-width:44rem}th,td{text-align:left;vertical-align:top;padding:.35rem .5rem;border:1px solid #bbb;overflow-wrap:anywhere}caption{text-align:left;font-weight:bold}.table-scroll,section{max-width:100%;overflow-x:auto}form{display:flex;flex-wrap:wrap;gap:.5rem;align-items:end;margin:.7rem 0}label{display:flex;flex-direction:column;max-width:100%}input,select,textarea,button{font:inherit;max-width:100%;box-sizing:border-box}textarea{flex:1 1 100%}pre{white-space:pre-wrap;overflow-wrap:anywhere}details,li,dd{overflow-wrap:anywhere}dd{margin-left:1rem}article{border-top:1px solid #bbb;padding:.5rem 0}.warning{border-left:3px solid #754b00;padding-left:.5rem}footer{margin-top:2rem}.status-chip{display:inline-block;padding:.15rem .55rem;border-radius:1rem;border:1px solid transparent;font-size:.85rem;font-weight:600;line-height:1.4}.status-queued{background:#dbeafe;color:#1e3a8a;border-color:#93c5fd}.status-replied{background:#dcfce7;color:#14532d;border-color:#86efac}.status-processing{background:#fef3c7;color:#78350f;border-color:#fcd34d}.status-muted{background:#f3f4f6;color:#374151;border-color:#d1d5db}@media(max-width:500px){body{margin:.75rem}th,td{padding:.25rem}}",yD=`default-src 'none'; style-src 'sha256-${fE("sha256").update(pE).digest("base64")}'; form-action 'self'`;function Ne(e,t){return`<a href="${v(e)}">${v(t)}</a>`}function io(e,t,r){return t.length?`<div class="table-scroll" role="region" aria-label="${v(r)}" tabindex="0"><table><caption>${v(r)}</caption><thead><tr>${e.map(n=>`<th scope="col">${v(n)}</th>`).join("")}</tr></thead><tbody>${t.map(n=>`<tr>${n.map(o=>`<td>${o}</td>`).join("")}</tr>`).join("")}</tbody></table></div>`:"<p>No matching records.</p>"}function pe(e){return`<time datetime="${v(e)}" title="${v(e)}">${v(ge(e))}</time>`}function Me(e,t,r=200){return e.header("Cache-Control","no-store"),e.header("X-Content-Type-Options","nosniff"),e.html(t,r)}function $e(e,t,r,n={},o=[],s=!1){let i=r.replace(/\/$/,""),a=s&&i!=="",c=yD+`; base-uri '${a?"self":"none"}'`+(o.length?`; script-src ${o.map(d=>`'sha256-${fE("sha256").update(d).digest("base64")}'`).join(" ")}; connect-src 'self'`:""),l=Object.entries(n).map(([d,m])=>` ${d}="${v(m)}"`).join(""),u=[[i||"/","Home"],[`${i}/tasks`,"Tasks"],[`${i}/running`,"Running"],[`${i}/cron`,"Cron"],[`${i}/comm/math`,"Prompts"],[`${i}/operator`,"Operator"]];return`<!doctype html><html lang="en"><head><meta charset="utf-8">
|
|
543
543
|
<meta name="viewport" content="width=device-width, initial-scale=1"><meta http-equiv="Content-Security-Policy" content="${v(c)}"><title>${v(e)} \u2014 lmauto</title>
|
|
544
544
|
${a?`<base href="${v(i)}/" />`:""}
|
|
545
|
-
<style>${fE}</style></head><body><a href="#main">Skip to content</a><header><p>Local operations / lmauto</p><nav aria-label="Main">${u.map(([d,m])=>Ne(d,m)).join(" | ")}</nav></header><main${l} id="main"><h1>${v(e)}</h1>${t}</main><footer><p>Times are relative to this page load. Refresh for current data.</p></footer></body></html>`}function Br(e){let t=new Map;for(let r of e)if(B(r))try{t.set(Q(r),r.name)}catch{}return t}function pE(e,t,r){function n(s,i=!0){if(s===null)return"\u2014";let a=$n(s);if(!a)return v(s);let{teamfilePath:c,alias:l}=a,u=`${_D(c)}:${l}`,d=t.get(c);if(i&&d)return`<a href="${v(`${r}/sessions/${encodeURIComponent(d)}/${encodeURIComponent(l)}`)}" title="${v(s)}">${v(u)}</a>`;let m=i?`${s} \u2014 Not in the current local team registry -- no session page available`:s;return`<span title="${v(m)}">${v(u)}</span>`}function o(s,i,a){return`<section><h2>${s}</h2><table><thead><tr>${i.map(c=>`<th scope="col">${c}</th>`).join("")}</tr></thead><tbody>${a.length?a.map(c=>`<tr>${c.map(l=>`<td>${l}</td>`).join("")}</tr>`).join(""):`<tr><td colspan="${i.length}">No ${s.toLowerCase()} invocations.</td></tr>`}</tbody></table></section>`}return"<p>Running shows work still in progress. Dead means its process stopped abnormally while work was still in progress; session data remains intact and may be resumed. Idle means the invocation finished, successfully or with a recorded error; an Idle error status describes that finished result, not an ongoing crash. A target is <teamfile>.lmctl:<role>: the team\u2019s configuration file and the member role executing, such as Lead or Coder. From names what started the invocation: another member\u2019s identity, or operator for a person acting directly, not through an agent. Only targets whose team can be resolved in the current local registry link to a session page; other targets remain unlinked. Full identities are available in the labels\u2019 tooltips.</p>"+o("Running",["Target","From","Started","Running for"],e.running.map(s=>[n(s.target),n(s.from_identity,!1),v(s.started_human),v(s.running_for_human)]))+o("Dead",["Target","From","Started","Stale for"],e.dead.map(s=>[n(s.target),n(s.from_identity,!1),v(s.started_human),v(s.stale_for_human)]))+o("Idle",["Target","From","Status","Ended","Idle for","Ran for"],e.idle.map(s=>[n(s.target),n(s.from_identity,!1),v(s.status),v(ge(s.ended_at)),v(fe(s.idle_ms)),v(s.ran_human)]))}var xa="localweb_session",bD=8*1024,TD=1024,SD=30*24*60*60,vD=10,AD=6e4,$D=6e4,kD=1024;function TE(e,t){let r=xD(t.mountPath),n=`${r}/login`||"/login",o=`${r}/`||"/",s=r||"/",i=t.allowedOrigins,a=new Map,c=new Map,l=t.remoteKey??MD,u,d=()=>{let m;try{m=t.readAuthority()}catch{m=null}return!m||!m.passcode||!m.generation?(a.clear(),u=void 0,null):(u!==void 0&&m.generation!==u&&a.clear(),u=m.generation,m)};e.use("*",async(m,f)=>{m.header("Cache-Control","no-store");let p=RD(m.req.path,r);if(m.req.method==="GET"&&(p==="/healthz"||p==="/login")||m.req.method==="POST"&&p==="/login"){await f();return}let h=m.req.header("origin");if(h!==void 0&&!i.includes(h))return m.json({error:"origin not allowed"},403);let g=d();if(g===null)return ys(m,p,n,r,"unavailable");let _=m.req.header("authorization");if(_!==void 0){let y=l(m),S=Date.now();if(yE(c,y,S))return ys(m,p,n,r,"locked_out");let T=_.startsWith("Bearer ")?_.slice(7):"";if(!wE(T,g.passcode))return EE(c,y,S),ys(m,p,n,r);bE(c,y),await f();return}let E=_E(m.req.header("cookie"));if(E===null||a.get(E)!==g.generation)return ys(m,p,n,r,E===null?"missing":"expired");if(CD(m.req.method)&&!gE(m.req.url,m.req.header("host"),h,i))return ys(m,p,n,r);await f()}),e.get("/healthz",m=>m.json({ok:!0})),e.get("/login",m=>m.html(ND(AE(m,n,r),r))),e.post("/login",async m=>{if(!gE(m.req.url,m.req.header("host"),m.req.header("origin"),i))return td(m,n,r);let f=l(m),p=Date.now();if(yE(c,f,p))return ID(m,r);let h=d();if(h===null)return td(m,n,r);let g=await LD(m.req.raw).catch(()=>null);if(g===null||!wE(g,h.passcode))return EE(c,f,p),td(m,n,r);bE(c,f),a.size>=TD&&a.delete(a.keys().next().value);let _=yD(32).toString("base64url");return a.set(_,h.generation),m.header("Set-Cookie",OD(_,s,new URL(m.req.url).protocol==="https:")),m.redirect(vE(m,r)??o,303)}),e.post("/logout",m=>{let f=_E(m.req.header("cookie"));return f!==null&&a.delete(f),m.header("Set-Cookie",DD(s,new URL(m.req.url).protocol==="https:")),m.redirect(n,303)})}function xD(e=""){if(e===""||e==="/")return"";let t=e.endsWith("/")?e.slice(0,-1):e;if(!/^\/[A-Za-z0-9_./~-]+$/.test(t)||t.startsWith("//"))throw new Error("Invalid mount path");return t}function RD(e,t){return t&&(e===t||e.startsWith(`${t}/`))?e.slice(t.length)||"/":e}function ys(e,t,r,n,o="required"){let s=o==="locked_out"?429:401;if(t==="/api"||t.startsWith("/api/"))return e.json({error:o==="locked_out"?"too many failed attempts":"unauthorized"},s);let i={unavailable:"Authentication is not currently available.",missing:"You are not logged in yet.",expired:"Your session expired. Log in again to continue.",required:"Authentication required.",locked_out:"Too many failed attempts from this source. Try again shortly."}[o],a=e.req.method==="GET"?SE(`${n}${t}${new URL(e.req.url).search}`,n):null,c=a===null?r:`${r}?next=${encodeURIComponent(a)}`,l=o==="locked_out"?`<p>${i}</p>`:`<p>${i}</p><p><a href="${v(c)}">Log in</a></p>`;return e.html($e("Authentication required",l,n),s)}function ND(e,t){return $e("LocalWeb login",`<form method="post" action="${v(e)}"><label>Passcode<input type="password" name="passcode" autocomplete="current-password" required></label><button type="submit">Log in</button></form>`,t)}function td(e,t,r){return e.html($e("Login failed",`<p>Invalid credentials.</p><a href="${v(AE(e,t,r))}">Try again</a>`,r),401)}function ID(e,t){return e.html($e("Login failed","<p>Too many failed attempts from this source. Try again shortly.</p>",t),429)}function SE(e,t){if(!e||e.length>4096||!e.startsWith("/")||e.startsWith("//")||/[\\\x00-\x20\x7f]/.test(e))return null;let r="http://localweb.invalid";try{let n=new URL(e,r),o=decodeURIComponent(n.pathname);if(n.origin!==r||o.includes("//")||/[\\\x00-\x1f\x7f]/.test(o))return null;let s=new URL(o,r),i=a=>!t||a===t||a.startsWith(`${t}/`);return s.origin!==r||s.pathname.includes("//")||!i(n.pathname)||!i(s.pathname)?null:`${n.pathname}${n.search}${n.hash}`}catch{return null}}function vE(e,t){let r=new URL(e.req.url).searchParams.getAll("next");return r.length===1?SE(r[0],t):null}function AE(e,t,r){let n=vE(e,r);return n===null?t:`${t}?next=${encodeURIComponent(n)}`}async function LD(e){if(!e.headers.get("content-type")?.toLowerCase().startsWith("application/x-www-form-urlencoded"))throw new Error("invalid form");let t=e.body?.getReader();if(!t)throw new Error("missing form");let r=[],n=0;for(;;){let{done:s,value:i}=await t.read();if(s)break;if(n+=i.byteLength,n>bD)throw await t.cancel(),new Error("form too large");r.push(i)}let o=new URLSearchParams(Buffer.concat(r).toString("utf8"));if(o.getAll("passcode").length!==1||[...o.keys()].some(s=>s!=="passcode"))throw new Error("invalid form");return o.get("passcode")??""}function gE(e,t,r,n){if(r===void 0||!n.includes(r))return!1;let o=new URL(e),s=t??o.host;return r===`${o.protocol}//${s}`&&n.includes(`${o.protocol}//${o.host}`)}function CD(e){return e!=="GET"&&e!=="HEAD"&&e!=="OPTIONS"}function _E(e){let t=(e??"").split(";").map(r=>r.trim()).filter(r=>r.startsWith(`${xa}=`)).map(r=>r.slice(xa.length+1));return t.length===1&&/^[A-Za-z0-9_-]{43}$/.test(t[0])?t[0]:null}function OD(e,t,r){return`${xa}=${e}; Path=${t}; HttpOnly; SameSite=Strict; Max-Age=${SD}${r?"; Secure":""}`}function DD(e,t){return`${xa}=; Path=${e}; HttpOnly; SameSite=Strict; Max-Age=0${t?"; Secure":""}`}function wE(e,t){let r=hE("sha256").update(e,"utf8").digest(),n=hE("sha256").update(t,"utf8").digest();return ED(r,n)}function MD(e){try{return dE(e).remote.address??"unknown"}catch{return"unknown"}}function yE(e,t,r){let n=e.get(t);return n!==void 0&&r<n.lockedUntilMs}function EE(e,t,r){let n=e.get(t);if(n===void 0||r-n.windowStartMs>AD){e.size>=kD&&e.delete(e.keys().next().value),e.set(t,{count:1,windowStartMs:r,lockedUntilMs:0});return}n.count+=1,n.count>=vD&&(n.lockedUntilMs=r+$D)}function bE(e,t){e.delete(t)}import{createHash as PD}from"node:crypto";var $E=64*1024,UD=new Set(["math"]);function FD(e,t){return PD("sha256").update(e,"utf8").update("\0","utf8").update(t,"utf8").digest("hex")}function Ra(e,t,r){let n=r.to?.trim(),o=r.prompt??"",s=r.dedupeKey?.trim();if(!n)throw new C("INVALID_ARGUMENT","to is required",2);if(!s)throw new C("INVALID_ARGUMENT","dedupeKey is required",2);if(o.trim().length===0)throw new C("INVALID_ARGUMENT","prompt is required",2);if(Buffer.byteLength(o,"utf8")>$E)throw new C("INVALID_ARGUMENT",`prompt exceeds the ${$E}-byte comm-flow cap`,2);if(!UD.has(n))throw new C("INVALID_ARGUMENT",`"${n}" is not a comm-flow-enabled target`,2);let i=t.find(l=>l.name===n);if(i===void 0||!B(i))throw new C("INVALID_ARGUMENT",`"${n}" is not a registered local team`,2);let a=FD(n,o);return e.transaction(()=>{let l=e.prepare("SELECT id, admission_fingerprint FROM queue WHERE dedupe_key = ?").get(s);if(l){if(l.admission_fingerprint===a)return{queueId:l.id,replayed:!0};throw new C("CONFLICT",`dedupeKey "${s}" was already used for a different prompt`,4)}let u=we(e,t,n,o,{from:"operator",dedupeKey:s});return e.prepare("UPDATE queue SET admission_fingerprint = ? WHERE id = ?").run(a,u),{queueId:u,replayed:!1}}).immediate()}import{existsSync as qD,readFileSync as jD}from"node:fs";import{dirname as xE,join as rd}from"node:path";import{fileURLToPath as RE}from"node:url";var HD=rd(xE(RE(import.meta.url)),"public"),BD={"/legacy":{file:"index.html",contentType:"text/html; charset=utf-8"},"/legacy/":{file:"index.html",contentType:"text/html; charset=utf-8"},"/legacy/index.html":{file:"index.html",contentType:"text/html; charset=utf-8"},"/legacy/app.js":{file:"app.js",contentType:"text/javascript; charset=utf-8"},"/legacy/styles.css":{file:"styles.css",contentType:"text/css; charset=utf-8"}},WD=rd(xE(RE(import.meta.url)),"vendor-webui"),GD={"/":{file:"index.html",contentType:"text/html; charset=utf-8"},"/index.html":{file:"index.html",contentType:"text/html; charset=utf-8"},"/local.js":{file:"local.js",contentType:"text/javascript; charset=utf-8"},"/styles.css":{file:"styles.css",contentType:"text/css; charset=utf-8"}};function VD(e){return e.endsWith("/")?e.slice(0,-1):e}function JD(e,t){let r=e.replace(/<head[^>]*>/i,n=>`${n}
|
|
546
|
-
<base href="${t}" />`);if(r===e)throw new Error("injectBaseHref: no <head> tag found in index.html -- cannot inject <base href>");return r}function
|
|
547
|
-
WHERE a.target = ? AND d.status = ? ORDER BY d.decided_at DESC`).all(t.affects,r):e.prepare("SELECT * FROM decisions WHERE status = ? ORDER BY decided_at DESC").all(r),o=e.prepare("SELECT target FROM decision_affects WHERE decision_id = ? ORDER BY target");return n.map(s=>({...s,affects:o.all(s.id).map(i=>i.target)}))}function
|
|
545
|
+
<style>${pE}</style></head><body><a href="#main">Skip to content</a><header><p>Local operations / lmauto</p><nav aria-label="Main">${u.map(([d,m])=>Ne(d,m)).join(" | ")}</nav></header><main${l} id="main"><h1>${v(e)}</h1>${t}</main><footer><p>Times are relative to this page load. Refresh for current data.</p></footer></body></html>`}function Br(e){let t=new Map;for(let r of e)if(B(r))try{t.set(Q(r),r.name)}catch{}return t}function hE(e,t,r){function n(s,i=!0){if(s===null)return"\u2014";let a=$n(s);if(!a)return v(s);let{teamfilePath:c,alias:l}=a,u=`${wD(c)}:${l}`,d=t.get(c);if(i&&d)return`<a href="${v(`${r}/sessions/${encodeURIComponent(d)}/${encodeURIComponent(l)}`)}" title="${v(s)}">${v(u)}</a>`;let m=i?`${s} \u2014 Not in the current local team registry -- no session page available`:s;return`<span title="${v(m)}">${v(u)}</span>`}function o(s,i,a){return`<section><h2>${s}</h2><table><thead><tr>${i.map(c=>`<th scope="col">${c}</th>`).join("")}</tr></thead><tbody>${a.length?a.map(c=>`<tr>${c.map(l=>`<td>${l}</td>`).join("")}</tr>`).join(""):`<tr><td colspan="${i.length}">No ${s.toLowerCase()} invocations.</td></tr>`}</tbody></table></section>`}return"<p>Running shows work still in progress. Dead means its process stopped abnormally while work was still in progress; session data remains intact and may be resumed. Idle means the invocation finished, successfully or with a recorded error; an Idle error status describes that finished result, not an ongoing crash. A target is <teamfile>.lmctl:<role>: the team\u2019s configuration file and the member role executing, such as Lead or Coder. From names what started the invocation: another member\u2019s identity, or operator for a person acting directly, not through an agent. Only targets whose team can be resolved in the current local registry link to a session page; other targets remain unlinked. Full identities are available in the labels\u2019 tooltips.</p>"+o("Running",["Target","From","Started","Running for"],e.running.map(s=>[n(s.target),n(s.from_identity,!1),v(s.started_human),v(s.running_for_human)]))+o("Dead",["Target","From","Started","Stale for"],e.dead.map(s=>[n(s.target),n(s.from_identity,!1),v(s.started_human),v(s.stale_for_human)]))+o("Idle",["Target","From","Status","Ended","Idle for","Ran for"],e.idle.map(s=>[n(s.target),n(s.from_identity,!1),v(s.status),v(ge(s.ended_at)),v(fe(s.idle_ms)),v(s.ran_human)]))}var xa="localweb_session",TD=8*1024,SD=1024,vD=30*24*60*60,AD=10,$D=6e4,kD=6e4,xD=1024;function SE(e,t){let r=RD(t.mountPath),n=`${r}/login`||"/login",o=`${r}/`||"/",s=r||"/",i=t.allowedOrigins,a=new Map,c=new Map,l=t.remoteKey??PD,u,d=()=>{let m;try{m=t.readAuthority()}catch{m=null}return!m||!m.passcode||!m.generation?(a.clear(),u=void 0,null):(u!==void 0&&m.generation!==u&&a.clear(),u=m.generation,m)};e.use("*",async(m,f)=>{m.header("Cache-Control","no-store");let p=ND(m.req.path,r);if(m.req.method==="GET"&&(p==="/healthz"||p==="/login")||m.req.method==="POST"&&p==="/login"){await f();return}let h=m.req.header("origin");if(h!==void 0&&!i.includes(h))return m.json({error:"origin not allowed"},403);let g=d();if(g===null)return ys(m,p,n,r,"unavailable");let _=m.req.header("authorization");if(_!==void 0){let y=l(m),S=Date.now();if(EE(c,y,S))return ys(m,p,n,r,"locked_out");let T=_.startsWith("Bearer ")?_.slice(7):"";if(!yE(T,g.passcode))return bE(c,y,S),ys(m,p,n,r);TE(c,y),await f();return}let E=wE(m.req.header("cookie"));if(E===null||a.get(E)!==g.generation)return ys(m,p,n,r,E===null?"missing":"expired");if(OD(m.req.method)&&!_E(m.req.url,m.req.header("host"),h,i))return ys(m,p,n,r);await f()}),e.get("/healthz",m=>m.json({ok:!0})),e.get("/login",m=>m.html(ID($E(m,n,r),r))),e.post("/login",async m=>{if(!_E(m.req.url,m.req.header("host"),m.req.header("origin"),i))return td(m,n,r);let f=l(m),p=Date.now();if(EE(c,f,p))return LD(m,r);let h=d();if(h===null)return td(m,n,r);let g=await CD(m.req.raw).catch(()=>null);if(g===null||!yE(g,h.passcode))return bE(c,f,p),td(m,n,r);TE(c,f),a.size>=SD&&a.delete(a.keys().next().value);let _=ED(32).toString("base64url");return a.set(_,h.generation),m.header("Set-Cookie",DD(_,s,new URL(m.req.url).protocol==="https:")),m.redirect(AE(m,r)??o,303)}),e.post("/logout",m=>{let f=wE(m.req.header("cookie"));return f!==null&&a.delete(f),m.header("Set-Cookie",MD(s,new URL(m.req.url).protocol==="https:")),m.redirect(n,303)})}function RD(e=""){if(e===""||e==="/")return"";let t=e.endsWith("/")?e.slice(0,-1):e;if(!/^\/[A-Za-z0-9_./~-]+$/.test(t)||t.startsWith("//"))throw new Error("Invalid mount path");return t}function ND(e,t){return t&&(e===t||e.startsWith(`${t}/`))?e.slice(t.length)||"/":e}function ys(e,t,r,n,o="required"){let s=o==="locked_out"?429:401;if(t==="/api"||t.startsWith("/api/"))return e.json({error:o==="locked_out"?"too many failed attempts":"unauthorized"},s);let i={unavailable:"Authentication is not currently available.",missing:"You are not logged in yet.",expired:"Your session expired. Log in again to continue.",required:"Authentication required.",locked_out:"Too many failed attempts from this source. Try again shortly."}[o],a=e.req.method==="GET"?vE(`${n}${t}${new URL(e.req.url).search}`,n):null,c=a===null?r:`${r}?next=${encodeURIComponent(a)}`,l=o==="locked_out"?`<p>${i}</p>`:`<p>${i}</p><p><a href="${v(c)}">Log in</a></p>`;return e.html($e("Authentication required",l,n),s)}function ID(e,t){return $e("LocalWeb login",`<form method="post" action="${v(e)}"><label>Passcode<input type="password" name="passcode" autocomplete="current-password" required></label><button type="submit">Log in</button></form>`,t)}function td(e,t,r){return e.html($e("Login failed",`<p>Invalid credentials.</p><a href="${v($E(e,t,r))}">Try again</a>`,r),401)}function LD(e,t){return e.html($e("Login failed","<p>Too many failed attempts from this source. Try again shortly.</p>",t),429)}function vE(e,t){if(!e||e.length>4096||!e.startsWith("/")||e.startsWith("//")||/[\\\x00-\x20\x7f]/.test(e))return null;let r="http://localweb.invalid";try{let n=new URL(e,r),o=decodeURIComponent(n.pathname);if(n.origin!==r||o.includes("//")||/[\\\x00-\x1f\x7f]/.test(o))return null;let s=new URL(o,r),i=a=>!t||a===t||a.startsWith(`${t}/`);return s.origin!==r||s.pathname.includes("//")||!i(n.pathname)||!i(s.pathname)?null:`${n.pathname}${n.search}${n.hash}`}catch{return null}}function AE(e,t){let r=new URL(e.req.url).searchParams.getAll("next");return r.length===1?vE(r[0],t):null}function $E(e,t,r){let n=AE(e,r);return n===null?t:`${t}?next=${encodeURIComponent(n)}`}async function CD(e){if(!e.headers.get("content-type")?.toLowerCase().startsWith("application/x-www-form-urlencoded"))throw new Error("invalid form");let t=e.body?.getReader();if(!t)throw new Error("missing form");let r=[],n=0;for(;;){let{done:s,value:i}=await t.read();if(s)break;if(n+=i.byteLength,n>TD)throw await t.cancel(),new Error("form too large");r.push(i)}let o=new URLSearchParams(Buffer.concat(r).toString("utf8"));if(o.getAll("passcode").length!==1||[...o.keys()].some(s=>s!=="passcode"))throw new Error("invalid form");return o.get("passcode")??""}function _E(e,t,r,n){if(r===void 0||!n.includes(r))return!1;let o=new URL(e),s=t??o.host;return r===`${o.protocol}//${s}`&&n.includes(`${o.protocol}//${o.host}`)}function OD(e){return e!=="GET"&&e!=="HEAD"&&e!=="OPTIONS"}function wE(e){let t=(e??"").split(";").map(r=>r.trim()).filter(r=>r.startsWith(`${xa}=`)).map(r=>r.slice(xa.length+1));return t.length===1&&/^[A-Za-z0-9_-]{43}$/.test(t[0])?t[0]:null}function DD(e,t,r){return`${xa}=${e}; Path=${t}; HttpOnly; SameSite=Strict; Max-Age=${vD}${r?"; Secure":""}`}function MD(e,t){return`${xa}=; Path=${e}; HttpOnly; SameSite=Strict; Max-Age=0${t?"; Secure":""}`}function yE(e,t){let r=gE("sha256").update(e,"utf8").digest(),n=gE("sha256").update(t,"utf8").digest();return bD(r,n)}function PD(e){try{return mE(e).remote.address??"unknown"}catch{return"unknown"}}function EE(e,t,r){let n=e.get(t);return n!==void 0&&r<n.lockedUntilMs}function bE(e,t,r){let n=e.get(t);if(n===void 0||r-n.windowStartMs>$D){e.size>=xD&&e.delete(e.keys().next().value),e.set(t,{count:1,windowStartMs:r,lockedUntilMs:0});return}n.count+=1,n.count>=AD&&(n.lockedUntilMs=r+kD)}function TE(e,t){e.delete(t)}import{createHash as UD}from"node:crypto";var kE=64*1024,FD=new Set(["math"]);function qD(e,t){return UD("sha256").update(e,"utf8").update("\0","utf8").update(t,"utf8").digest("hex")}function Ra(e,t,r){let n=r.to?.trim(),o=r.prompt??"",s=r.dedupeKey?.trim();if(!n)throw new C("INVALID_ARGUMENT","to is required",2);if(!s)throw new C("INVALID_ARGUMENT","dedupeKey is required",2);if(o.trim().length===0)throw new C("INVALID_ARGUMENT","prompt is required",2);if(Buffer.byteLength(o,"utf8")>kE)throw new C("INVALID_ARGUMENT",`prompt exceeds the ${kE}-byte comm-flow cap`,2);if(!FD.has(n))throw new C("INVALID_ARGUMENT",`"${n}" is not a comm-flow-enabled target`,2);let i=t.find(l=>l.name===n);if(i===void 0||!B(i))throw new C("INVALID_ARGUMENT",`"${n}" is not a registered local team`,2);let a=qD(n,o);return e.transaction(()=>{let l=e.prepare("SELECT id, admission_fingerprint FROM queue WHERE dedupe_key = ?").get(s);if(l){if(l.admission_fingerprint===a)return{queueId:l.id,replayed:!0};throw new C("CONFLICT",`dedupeKey "${s}" was already used for a different prompt`,4)}let u=we(e,t,n,o,{from:"operator",dedupeKey:s});return e.prepare("UPDATE queue SET admission_fingerprint = ? WHERE id = ?").run(a,u),{queueId:u,replayed:!1}}).immediate()}import{existsSync as jD,readFileSync as HD}from"node:fs";import{dirname as RE,join as rd}from"node:path";import{fileURLToPath as NE}from"node:url";var BD=rd(RE(NE(import.meta.url)),"public"),WD={"/legacy":{file:"index.html",contentType:"text/html; charset=utf-8"},"/legacy/":{file:"index.html",contentType:"text/html; charset=utf-8"},"/legacy/index.html":{file:"index.html",contentType:"text/html; charset=utf-8"},"/legacy/app.js":{file:"app.js",contentType:"text/javascript; charset=utf-8"},"/legacy/styles.css":{file:"styles.css",contentType:"text/css; charset=utf-8"}},GD=rd(RE(NE(import.meta.url)),"vendor-webui"),VD={"/":{file:"index.html",contentType:"text/html; charset=utf-8"},"/index.html":{file:"index.html",contentType:"text/html; charset=utf-8"},"/local.js":{file:"local.js",contentType:"text/javascript; charset=utf-8"},"/styles.css":{file:"styles.css",contentType:"text/css; charset=utf-8"}};function JD(e){return e.endsWith("/")?e.slice(0,-1):e}function zD(e,t){let r=e.replace(/<head[^>]*>/i,n=>`${n}
|
|
546
|
+
<base href="${t}" />`);if(r===e)throw new Error("injectBaseHref: no <head> tag found in index.html -- cannot inject <base href>");return r}function xE(e,t,r,n){for(let o of Object.keys(r))e.get(o,s=>{let i=r[o];if(!i)return s.notFound();let a=rd(t,i.file);if(!jD(a))return s.notFound();let c=HD(a);return n!==void 0&&i.contentType.startsWith("text/html")&&(c=zD(c.toString("utf8"),n)),s.body(c,200,{"content-type":i.contentType})})}function IE(e,t={}){let r=JD(t.mountPath??""),n=t.webDistDir??GD;xE(e,n,VD,r!==""?`${r}/`:void 0),xE(e,BD,WD,`${r}/legacy/`)}import{createHash as sd,createHmac as eM,randomBytes as nd,timingSafeEqual as tM}from"node:crypto";import{basename as rM}from"node:path";import{existsSync as KD}from"node:fs";import{homedir as YD}from"node:os";import{join as QD}from"node:path";function XD(e){return e||(process.env.LMTEAM_DB_PATH?process.env.LMTEAM_DB_PATH:QD(YD(),".lmteam","lmteam.db"))}function Na(e){let t=XD(e);if(!KD(t))throw new Error(`lmteam database not found at ${t} -- set LMTEAM_DB_PATH or check the path`);return new yt(t,{readonly:!0,fileMustExist:!0})}function LE(e,t={}){let r=t.status??"stands",n=t.affects?e.prepare(`SELECT d.* FROM decisions d JOIN decision_affects a ON a.decision_id = d.id
|
|
547
|
+
WHERE a.target = ? AND d.status = ? ORDER BY d.decided_at DESC`).all(t.affects,r):e.prepare("SELECT * FROM decisions WHERE status = ? ORDER BY decided_at DESC").all(r),o=e.prepare("SELECT target FROM decision_affects WHERE decision_id = ? ORDER BY target");return n.map(s=>({...s,affects:o.all(s.id).map(i=>i.target)}))}function CE(e){return e.prepare("SELECT * FROM asks WHERE status = 'open' ORDER BY raised_at ASC").all()}function OE(e,t){return e.prepare("SELECT * FROM asks WHERE id = ?").get(t)??null}function DE(e){return e.prepare("SELECT * FROM blocked WHERE status = 'open' ORDER BY raised_at ASC").all()}function ZD(){let e=!1,t=0,r=new Set,n=$=>!e&&!document.hidden&&$===t,o=$=>document.getElementById($),s=($,q)=>{let U=o($);U&&(U.textContent=q)},i=($,q="")=>{let U=document.createElement($);return U.textContent=q,U},a=$=>$!==null&&typeof $=="object"&&!Array.isArray($),c=$=>Number.isSafeInteger($)&&Number($)>0,l=$=>typeof $=="string"&&Number.isFinite(Date.parse($)),u=$=>$===null||l($);async function d($,q,U,Z){r.add(U);let G,ie,be=new Promise((j,Y)=>{G=()=>{ie?.cancel().catch(()=>{}),Y(new Error("Request cancelled or timed out"))},U.signal.addEventListener("abort",G,{once:!0})}),ae=setTimeout(()=>U.abort(),15e3),M=async()=>{U.signal.throwIfAborted();let j=await fetch($,{method:Z===void 0?"GET":"POST",signal:U.signal,credentials:"same-origin",cache:"no-store",redirect:"error",headers:{Accept:q==="json"?"application/json":"text/html",...Z===void 0?{}:{"Content-Type":"application/x-www-form-urlencoded"}},...Z===void 0?{}:{body:Z}});if(U.signal.throwIfAborted(),j.status!==200||j.redirected||!j.headers.get("content-type")?.includes(q==="json"?"application/json":"text/html")){let de;if(q==="html"&&!j.redirected&&j.headers.get("content-type")?.includes("text/html")){let Se=await j.text().catch(()=>""),K=/<h1>[^<]*<\/h1>\s*<p>([^<]*)<\/p>/.exec(Se);K&&K[1]&&(de=K[1].replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'"))}else j.body?.cancel().catch(()=>{});let xe=new Error(de??"Unexpected server response");throw xe.status=j.status,xe}let Y=j.body?.getReader();if(ie=Y,!Y)throw new Error("Missing response body");let z=new TextDecoder,re=0,te="";try{for(;;){let de=await Y.read();if(U.signal.throwIfAborted(),de.done)break;if(re+=de.value.byteLength,re>(q==="json"?262144:2e6))throw new Error("Response exceeds safety limit");te+=z.decode(de.value,{stream:!0})}return te+z.decode()}catch(de){throw Y.cancel().catch(()=>{}),de}};try{return await Promise.race([M(),be])}finally{clearTimeout(ae),U.signal.removeEventListener("abort",G),r.delete(U)}}function m($,q){if(!a($)||$.id!==q||!l($.createdAt)||!u($.pulledAt)||!u($.answeredAt))throw new Error("Invalid queue state");let U=$.lifecycle,Z=$.lifecycleBasis,G=$.answer;if(!(U==="queued"?Z==="dispatched":U==="processing"?Z==="confirmed"||Z==="dispatched":U==="finished"&&["answer","merged","informational"].includes(String(Z))))throw new Error("Invalid lifecycle evidence");if(Z==="answer"){if(!a(G)||!c(G.id)||G.prompt_queue_id!==q||typeof G.answer_text!="string"||!l(G.answered_at)||G.answered_at!==$.answeredAt||!l(G.created_at)||typeof G.truncated!="boolean")throw new Error("Invalid correlated answer");let be=new TextEncoder().encode(G.answer_text).length;if(!Number.isSafeInteger(G.byteLength)||G.byteLength!==be||be>65536||!Number.isSafeInteger(G.totalBytes)||Number(G.totalBytes)<be||(G.truncated?Number(G.totalBytes)<=be:G.totalBytes!==be))throw new Error("Invalid response coverage")}else if(G!==null||$.answeredAt!==null)throw new Error("Unexpected answer");if(U==="queued"&&$.pulledAt!==null)throw new Error("Unexpected handling time");return $}let f=o("comm-state"),p=Number(f?.dataset.queueId),h=f?.dataset.mount??"",g,_=null,E=0,y=f?.dataset.lifecycle==="finished";function S(){if(clearTimeout(g),!(!f||!c(p)||e||document.hidden||y||_)){if(E>=60){s("comm-poll-notice","Automatic checks paused after 60 reads. Use Refresh state to check again.");return}g=setTimeout(()=>void T(),Math.min(1e3*1.5**E,1e4))}}async function T(){if(!f||_||e||document.hidden||y||E>=60)return;let $=new AbortController,q=t;_=$,E++;try{let U=await d(`${h}/api/queue/${p}/state`,"json",$);if(!n(q))return;let Z=m(JSON.parse(U),p),G=Z.lifecycleBasis,ie=Z.answer,be=Z.lifecycle==="queued"?"Queued":Z.lifecycle==="processing"?"Processing":G==="merged"?"Combined":G==="informational"?"Informational":"Replied",ae=Z.lifecycle==="queued"?"Queued \u2014 waiting for handling":Z.lifecycle==="processing"?G==="confirmed"?"Processing \u2014 picked up by inbox":"Processing \u2014 delivery attempted; read not confirmed":G==="merged"?"Finished \u2014 combined with another prompt":G==="informational"?"Finished \u2014 informational, no answer expected":"Finished \u2014 answer recorded",M=G==="merged"?"No separate answer: prompt combined into another prompt.":"No answer expected: this was an informational send.",j=f.dataset.sender??"sender not recorded",Y=f.dataset.recipient??"inbox not recorded",z=ie?`Answer recorded in the ${Y} inbox for prompt #${p} from ${j}.`:Z.lifecycle==="finished"?M:`No answer recorded for prompt #${p} from ${j} to ${Y}.`,re=i("span",be);re.className=`status-chip status-${Z.lifecycle==="finished"?ie?"replied":"muted":Z.lifecycle}`,re.title=ae,f.replaceChildren(re,i("span",` \xB7 ${ae}`)),f.dataset.lifecycle=Z.lifecycle,f.dataset.lifecycleBasis=G,s("comm-receipt-summary",ie?"An answer is recorded below.":Z.lifecycle==="finished"?M:"No answer recorded yet."),s("comm-response-status",z),s("comm-response-none",!ie&&Z.lifecycle!=="finished"?"No correlated answer recorded yet. Refresh to check again.":""),s("comm-response-meta",ie?`Recorded ${ie.answered_at} \xB7 answer #${ie.id} to prompt #${ie.prompt_queue_id}`:""),s("comm-response",ie?.answer_text??"");let te=o("comm-response");te&&(te.hidden=!ie),s("comm-response-truncation",ie?ie.truncated?`Truncated: ${ie.byteLength} of ${ie.totalBytes} bytes. No continuation endpoint is available.`:`${ie.byteLength} bytes returned.`:""),s("comm-reply-time",ie?.answered_at??"not recorded"),s("comm-handling-observation",`Latest handling evidence: ${Z.pulledAt??"not recorded"}${Z.pulledAt?G==="confirmed"?" (picked up)":G==="dispatched"?" (delivery attempted)":" (transport or pickup time)":""}`),s("comm-poll-notice",`State checked ${new Date().toISOString()}.`),y=Z.lifecycle==="finished"}catch(U){n(q)&&s("comm-poll-notice",`State unavailable; displayed records may be stale. ${U instanceof Error?U.message:String(U)}. Use Refresh state.`)}finally{_===$&&(_=null),S()}}let R=o("comm-composer-container"),x=o("comm-draft-form"),I=null,A=!1,H=!1,L=!1,w=null,b=null,N=$=>Array.from($.querySelectorAll("input, textarea")),D=($,q)=>{let U=N($).filter(Z=>Z.name===q);if(U.length!==1)throw new Error("Invalid review fields");return U[0]};function W($,q){let U=N($).map(Z=>({input:Z,value:Z.value}));w=$,b=$.querySelector('button[type="submit"]'),$.addEventListener("submit",Z=>{if(H||e||document.hidden){Z.preventDefault();return}for(let G of U)G.input.value=G.value;H=!0,L=!0,q&&(q.disabled=!0),b&&(b.disabled=!0),s("comm-send-status","Submitting through the browser. If the outcome is uncertain, return here and retry this same confirmation.")})}let ee=o("comm-confirm-form");if(ee&&W(ee,o("comm-edit-button")),x?.addEventListener("submit",$=>{L&&$.preventDefault()}),R&&x&&o("compose")){let $=Array.from(R.childNodes),q=x.querySelector('textarea[name="prompt"]'),U=x.querySelector('button[type="submit"]');x.addEventListener("submit",async Z=>{if(!q||(Z.preventDefault(),I||L||e||document.hidden))return;let G=q.value.replace(/\r\n?/g,`
|
|
548
548
|
`);if(!G.trim()||new TextEncoder().encode(G.replace(/\n/g,`\r
|
|
549
|
-
`)).length>65536){s("comm-composer-notice","Enter a nonblank prompt of at most 64 KiB UTF-8.");return}let
|
|
550
|
-
`));return V.toString()},
|
|
549
|
+
`)).length>65536){s("comm-composer-notice","Enter a nonblank prompt of at most 64 KiB UTF-8.");return}let ie=t,be=new AbortController;I=be,A=!1,U&&(U.disabled=!0),s("comm-composer-notice","Reviewing prompt\u2026");try{let ae=new URL(x.action,window.location.href),M=o("compose")?.dataset.base;if(!M||ae.origin!==new URL(window.location.href).origin||ae.pathname!==`${M}/review`||ae.search||ae.hash)throw new Error("Unexpected review destination");let j=()=>{let V=new URLSearchParams;for(let ye of N(x))ye.name&&!ye.disabled&&V.append(ye.name,ye.value.replace(/\r\n|\r|\n/g,`\r
|
|
550
|
+
`));return V.toString()},Y;try{Y=await d(ae.href,"html",be,j())}catch(V){if((V instanceof Error?V.status:void 0)!==409||!n(ie))throw V;s("comm-composer-notice","Session renewing\u2026");let lt=await d(window.location.href,"html",be);if(!n(ie))return;let rt=new DOMParser().parseFromString(lt,"text/html").getElementById("comm-draft-form"),_t="";try{rt&&(_t=D(rt,"csrf").value)}catch{}if(!_t)throw V;D(x,"csrf").value=_t,Y=await d(ae.href,"html",be,j())}if(!n(ie))return;let re=new DOMParser().parseFromString(Y,"text/html").getElementById("comm-confirm-form");if(!re)throw new Error("Review unavailable; use the native review form after reloading");let te=new URL(re.getAttribute("action")??"",ae.href),de=D(re,"confirmation").value;if(re.method.toLowerCase()!=="post"||te.origin!==ae.origin||te.pathname!==`${M}/prompts`||te.search||te.hash||!de||de.length>4096||D(re,"prompt").value!==G)throw new Error("Review did not match the exact prompt");let xe=i("div");xe.id="comm-review-panel",xe.append(i("p","Review prompt to math:Lead"),i("pre",G));let Se=document.createElement("form");Se.id="comm-confirm-form",Se.method="post",Se.action=te.href;let K=document.createElement("input");K.type="hidden",K.name="confirmation",K.value=de;let Te=document.createElement("textarea");Te.name="prompt",Te.hidden=!0,Te.value=G;let ze=document.createElement("button");ze.type="submit",ze.id="comm-confirm-submit",ze.textContent="Confirm and queue";let We=document.createElement("button");We.type="button",We.id="comm-edit-button",We.textContent="Edit prompt";let Ut=i("p");Ut.id="comm-send-status",Ut.setAttribute("role","status"),Se.append(K,Te,ze),xe.append(Se,We,Ut),We.addEventListener("click",()=>{L||We.disabled||(q.value=G,R.replaceChildren(...$),w=null)}),W(Se,We),R.replaceChildren(xe)}catch(ae){n(ie)&&s("comm-composer-notice",`Review unavailable: ${ae instanceof Error?ae.message:String(ae)}. Draft retained; retry review or reload to renew the form. The native flow also works without JavaScript.`)}finally{I===be&&(I=null,U&&!e&&!document.hidden&&(U.disabled=!1),!e&&!document.hidden&&A&&s("comm-composer-notice","Review interrupted; draft retained. Review again when ready."))}})}function ne(){I&&(A=!0),t++,clearTimeout(g);for(let $ of r)$.abort()}let J=()=>{if(!I&&!L){let $=x?.querySelector('button[type="submit"]');$&&($.disabled=!1),A&&s("comm-composer-notice","Review interrupted; draft retained. Review again when ready.")}S()},oe=()=>{document.hidden?ne():J()},k=()=>{e=!0,ne()},O=$=>{$.persisted&&(e=!1,w&&H&&(H=!1,b&&(b.disabled=!1,b.textContent="Retry this same confirmation"),s("comm-send-status","Outcome may be uncertain. Retry only this same confirmation, or check the inbox.")),J())};return document.addEventListener("visibilitychange",oe),window.addEventListener("pagehide",k),window.addEventListener("pageshow",O),S(),()=>{k(),document.removeEventListener("visibilitychange",oe),window.removeEventListener("pagehide",k),window.removeEventListener("pageshow",O)}}var Ia=`(function () {
|
|
551
551
|
function __name(value) { return value; }
|
|
552
|
-
return (${
|
|
553
|
-
})();`;var
|
|
554
|
-
`)){let $=O.trim();if($)return $}return""}let _=80,E=2e3;function y(k,O){return k.length>O?`${k.slice(0,O)}\u2026`:k}function S(k){let O=g(k);return O?y(O,_):"(empty prompt)"}function T(k){return y(k.trim(),E)}function R(k){let O=jr(r,k),$=`Prompt #${k}`;return!O||O.status!=="available"||O.text===null?`<a href="${o}/prompts/${k}">${v($)}</a>`:`<a href="${o}/prompts/${k}" title="${v(T(O.text))}">${v(S(O.text))}</a>`}function x(k){return k.lifecycle==="queued"?"queued":k.lifecycle==="processing"?"processing":p(k.lifecycleBasis)?"muted":"replied"}function I(k){return k.lifecycle==="queued"?"Queued":k.lifecycle==="processing"?"Processing":k.lifecycleBasis==="merged"?"Combined":k.lifecycleBasis==="informational"?"Informational":k.lifecycleBasis==="retracted"?"Retracted":"Replied"}function A(k){return`<span class="status-chip status-${x(k)}" title="${v(H(k))}">${v(I(k))}</span>`}function H(k){return k.lifecycle==="queued"?"Queued \u2014 waiting for handling":k.lifecycle==="finished"?k.lifecycleBasis==="merged"?"Finished \u2014 combined with another prompt":k.lifecycleBasis==="informational"?"Finished \u2014 informational, no answer expected":k.lifecycleBasis==="retracted"?"Finished \u2014 retracted, no answer expected":"Finished \u2014 answer recorded":k.lifecycleBasis==="confirmed"?"Processing \u2014 picked up by inbox":"Processing \u2014 delivery attempted; read not confirmed"}function L(k){if(k==="operator")return"Operator";let O=$n(k);if(O){let q=r.teams.find(U=>{if(!B(U))return!1;try{return Q(U)===O.teamfilePath}catch{return!1}});return q?`<a href="${v(`${n}/sessions/${encodeURIComponent(q.name)}/${encodeURIComponent(O.alias)}`)}" title="${v(k)}">${v(`${q.name}:${O.alias}`)}</a>`:`<span title="${v(k)}">${v(`${
|
|
552
|
+
return (${ZD.toString()})();
|
|
553
|
+
})();`;var ME=$e("","","").match(/<style>([\s\S]*?)<\/style>/),nM=sd("sha256").update(ME?ME[1]:"").digest("base64"),oM=sd("sha256").update(Ia).digest("base64"),sM=`default-src 'none'; style-src 'sha256-${nM}'; form-action 'self'; base-uri 'none'; frame-ancestors 'none'; script-src 'sha256-${oM}'; connect-src 'self'`,od="lmbee_comm_browser",iM=64*1024,aM=256*1024,ao=class extends Error{};function PE(e){let t=new dn,{context:r}=e,n=(e.mountPath??"").replace(/\/$/,"");if(n&&(!/^\/[A-Za-z0-9_./~-]+$/.test(n)||n.startsWith("//")))throw new Error("Invalid mount path");let o=`${n}/comm/math`,s=e.now??Date.now,i=nd(32),a=new Map,c=k=>sd("sha256").update(k).digest("hex"),l=k=>eM("sha256",i).update(k).digest("base64url"),u=k=>{let O=Buffer.from(JSON.stringify(k)).toString("base64url");return`${O}.${l(O)}`};function d(k){let O=k.split(".");if(O.length!==2||k.length>4096)throw new Error("Invalid confirmation. Review the prompt again.");let $=Buffer.from(l(O[0])),q=Buffer.from(O[1]);if($.length!==q.length||!tM($,q))throw new Error("Invalid confirmation. Review the prompt again.");return JSON.parse(Buffer.from(O[0],"base64url").toString("utf8"))}function m(k,O=!1){let $=(k.req.header("cookie")??"").split(";").map(U=>U.trim()).filter(U=>U.startsWith(`${od}=`));if($.length===1)try{let U=d($[0].slice(od.length+1));if(typeof U.browser=="string"&&/^[a-f0-9]{48}$/.test(U.browser))return U.browser}catch{}if(!O)throw new Error("Browser confirmation expired. Open the Math inbox and review again.");let q=nd(24).toString("hex");return k.header("Set-Cookie",`${od}=${u({browser:q})}; Path=${o}; HttpOnly; SameSite=Strict${new URL(k.req.url).protocol==="https:"?"; Secure":""}`),q}function f(){let k=r.teams.find(O=>O.name==="math");if(!k||!B(k)||k.leadAlias!=="Lead")throw new Error("The local math Lead inbox is unavailable.");return`${Q(k)}:Lead`}function p(k){return k==="merged"||k==="informational"||k==="retracted"}function h(k){return k.answeredAt?`<a href="${o}/prompts/${k.id}#comm-response">Answer to #${k.id}</a> \xB7 ${pe(k.answeredAt)}`:k.lifecycleBasis==="merged"?"No separate answer (merged)":k.lifecycleBasis==="informational"?"No answer expected (informational)":k.lifecycleBasis==="retracted"?`No answer expected (retracted): ${v(k.retracted_reason??"no reason recorded")}`:"No answer recorded"}function g(k){for(let O of k.split(`
|
|
554
|
+
`)){let $=O.trim();if($)return $}return""}let _=80,E=2e3;function y(k,O){return k.length>O?`${k.slice(0,O)}\u2026`:k}function S(k){let O=g(k);return O?y(O,_):"(empty prompt)"}function T(k){return y(k.trim(),E)}function R(k){let O=jr(r,k),$=`Prompt #${k}`;return!O||O.status!=="available"||O.text===null?`<a href="${o}/prompts/${k}">${v($)}</a>`:`<a href="${o}/prompts/${k}" title="${v(T(O.text))}">${v(S(O.text))}</a>`}function x(k){return k.lifecycle==="queued"?"queued":k.lifecycle==="processing"?"processing":p(k.lifecycleBasis)?"muted":"replied"}function I(k){return k.lifecycle==="queued"?"Queued":k.lifecycle==="processing"?"Processing":k.lifecycleBasis==="merged"?"Combined":k.lifecycleBasis==="informational"?"Informational":k.lifecycleBasis==="retracted"?"Retracted":"Replied"}function A(k){return`<span class="status-chip status-${x(k)}" title="${v(H(k))}">${v(I(k))}</span>`}function H(k){return k.lifecycle==="queued"?"Queued \u2014 waiting for handling":k.lifecycle==="finished"?k.lifecycleBasis==="merged"?"Finished \u2014 combined with another prompt":k.lifecycleBasis==="informational"?"Finished \u2014 informational, no answer expected":k.lifecycleBasis==="retracted"?"Finished \u2014 retracted, no answer expected":"Finished \u2014 answer recorded":k.lifecycleBasis==="confirmed"?"Processing \u2014 picked up by inbox":"Processing \u2014 delivery attempted; read not confirmed"}function L(k){if(k==="operator")return"Operator";let O=$n(k);if(O){let q=r.teams.find(U=>{if(!B(U))return!1;try{return Q(U)===O.teamfilePath}catch{return!1}});return q?`<a href="${v(`${n}/sessions/${encodeURIComponent(q.name)}/${encodeURIComponent(O.alias)}`)}" title="${v(k)}">${v(`${q.name}:${O.alias}`)}</a>`:`<span title="${v(k)}">${v(`${rM(O.teamfilePath)}:${O.alias}`)}</span>`}let $=r.teams.find(q=>q.name===k);return $&&B($)?`<a href="${v(`${n}/sessions/${encodeURIComponent($.name)}/${encodeURIComponent($.leadAlias)}`)}" title="${v(`Current configured lead for inbox ${k}`)}">${v(`${$.name}:${$.leadAlias}`)}</a>`:`${v(k)}${$?" (remote inbox)":" (not in the current team list)"}`}function w(){let k=r.teams.find(O=>O.name==="math");if(!k||!B(k))return'<section aria-label="Assigned work"><h2>Assigned work</h2><p>Math\u2019s current local actor is unavailable, so its assigned work cannot be resolved.</p></section>';try{let O=Nr(r.db.db,{owner:{team:Q(k),alias:k.leadAlias},limit:5});return`<section aria-label="Assigned work"><h2>Assigned work</h2><p>Work owned by ${L("math")}. Open an item to follow its epic, parent task, or subtasks.</p>${O.rows.length?`<ul>${O.rows.map($=>`<li><a href="${n}/tasks/${$.id}">${v(`${$.kind} #${$.id}: ${$.title}`)}</a> \u2014 ${v($.status)}</li>`).join("")}</ul><p>Up to five assigned items shown.</p>`:"<p>No assigned work returned for this actor.</p>"}</section>`}catch{return'<section aria-label="Assigned work"><h2>Assigned work</h2><p>Current work ownership is unavailable. Prompt and answer records below remain readable.</p></section>'}}let b="<details><summary>About these records</summary><p>Actor links open each team\u2019s current configured lead; records identify inboxes and sender labels, not exact historical sessions. Assigned work is current ownership, not proof of execution or a prompt\u2019s topic. A delivery attempt does not confirm the inbox read a prompt. A recorded answer does not establish delivery back to the sender or task success.</p></details>";function N(k,O,$,q=200){return k.html($e(O,`${$}<script>${Ia}</script>`,n,{},[Ia]),q)}function D(k,O="",$=""){return`<div id="comm-composer-container"><p id="comm-composer-notice">${v($)}</p><form id="comm-draft-form" method="post" action="${o}/review"><input type="hidden" name="csrf" value="${v(u({browser:k,purpose:"review"}))}"><label for="prompt">Prompt for math Lead (maximum 64 KiB UTF-8)</label><textarea id="prompt" name="prompt" rows="8" required>
|
|
555
555
|
${v(O)}</textarea><button type="submit">Review prompt</button></form></div>`}function W(k,O){return`<form method="post" action="${o}/prompts"><input type="hidden" name="confirmation" value="${v(O)}"><textarea name="prompt" hidden>
|
|
556
|
-
${v(k)}</textarea><button type="submit">Retry this same confirmation</button></form>`}let ee=500;function
|
|
556
|
+
${v(k)}</textarea><button type="submit">Retry this same confirmation</button></form>`}let ee=500;function ne(k){let O=k.req.query("ask");if(O!==void 0&&/^[1-9]\d*$/.test(O)){try{let q=Na(),U;try{U=OE(q,Number(O))}finally{q.close()}if(U){let Z=U.downstream?v(U.downstream):"Not recorded";return`<div id="comm-reply-context" aria-label="Replying to"><p><strong>Replying to ask:</strong> ${v(U.subject)}</p><p>${v(U.reason)}</p><p><strong>Downstream:</strong> ${Z}</p></div>`}}catch{}return""}let $=k.req.query("reply_to");if($!==void 0&&/^[1-9]\d*$/.test($)){let q=ro(r,Number($));if(q){let U=jr(r,q.id),Z=U?.status==="available"&&U.text!==null?y(U.text.trim(),ee):"(preview unavailable)";return`<div id="comm-reply-context" aria-label="Replying to"><p><strong>Replying to</strong> a prompt from ${L(q.from_id)}, ${pe(q.created_ts)}:</p><pre>${v(Z)}</pre></div>`}}return""}async function J(k){if(!k.req.header("content-type")?.toLowerCase().startsWith("application/x-www-form-urlencoded"))throw new Error("Expected a browser form.");let O=k.req.raw.body?.getReader();if(!O)throw new Error("Missing form.");let $=0,q=[];for(;;){let{done:Z,value:G}=await O.read();if(Z)break;if($+=G.byteLength,$>aM)throw await O.cancel(),new Error("Form exceeds the size limit.");q.push(G)}let U=new URLSearchParams(Buffer.concat(q).toString("utf8"));for(let Z of U.keys())if(U.getAll(Z).length!==1)throw new Error("Duplicate form field.");return U}function oe(k){let O=k.get("prompt")??"";if(!O.trim()||Buffer.byteLength(O)>iM)throw new Error("Enter a nonblank prompt of at most 64 KiB UTF-8.");return O}return t.use("/comm/math/*",async(k,O)=>{k.header("Cache-Control","no-store"),k.header("Content-Security-Policy",sM),k.header("Referrer-Policy","same-origin"),k.header("X-Content-Type-Options","nosniff");let $=new URL(k.req.url),q=`${$.protocol}//${k.req.header("host")??$.host}`,U=k.req.header("sec-fetch-site");if(!e.allowedOrigins.includes(q)||U&&U!=="same-origin"&&U!=="none"||k.req.header("origin")!==void 0&&k.req.header("origin")!==q||k.req.method==="POST"&&k.req.header("origin")!==q)return N(k,"Request rejected","<p>Use this browser\u2019s local Math inbox page.</p>",403);await O()}),t.get("/comm/math",k=>{let O="<p>Sending is not enabled on this surface.</p>";if(e.enabled)try{f(),O=D(m(k,!0))}catch(U){O=`<p>${v(U.message)}</p>`}let $=k.req.query("after");if($!==void 0&&(!/^[1-9]\d*$/.test($)||!Number.isSafeInteger(Number($))))return N(k,"Invalid page","<p>Invalid prompt cursor.</p>",400);let q=Aa(r,{toId:"math",limit:20,...$?{after:Number($)}:{}});return N(k,"Math inbox",`<p>Prompts to ${L("math")} and the answers recorded against them. Select a prompt to follow the exchange; use assigned work to explore the tasks this actor owns.</p>${b}<p><a href="${o}">Refresh inbox</a> \xB7 <a href="#compose">Write a prompt</a> \xB7 <a href="${n}/sessions/math/Lead">Math session</a></p><section id="compose" aria-label="Write a prompt" data-mount="${v(n)}" data-base="${v(o)}"><h2>Write a prompt</h2><p>Start a new prompt to ${L("math")}. Review the exact text before queueing it.</p>${ne(k)}${O}</section>${w()}<section id="history" aria-label="Prompts and answers"><h2>Incoming prompts and answers</h2><p>Only prompts addressed to Math appear here. <a href="${n}/sessions/math/Lead#comm-sequence">See incoming and outgoing exchanges</a> in the session timeline.</p><p>Newest 20 matching prompts first. Queued means waiting; processing records a pull or dispatch attempt; finished means an answer was recorded, an informational send expected no answer, or prompts from the same sender to the same recipient were combined to avoid separate deliveries. Finished for a combined prompt does not mean separate work was done, and no separate answer is expected. The combined prompt ID is not recorded, so no link is available.</p><table><thead><tr><th>Prompt</th><th>Actors</th><th>Handling</th><th>Queued</th><th>Answer</th></tr></thead><tbody>${q.rows.map(U=>`<tr data-queue-id="${U.id}"><td>${R(U.id)}</td><td>${L(U.from_id)} \u2192 ${L(U.to_id)}</td><td>${A(U)} \xB7 ${v(H(U))}</td><td>${pe(U.created_ts)}</td><td>${h(U)}</td></tr>`).join("")}</tbody></table><p>Task links for these prompts: not recorded.</p>${q.meta.next_cursor?`<a href="${o}?after=${q.meta.next_cursor}">Older prompts</a>`:""}</section>`)}),t.post("/comm/math/review",async k=>{if(!e.enabled)return N(k,"Sending unavailable","<p>Sending is not enabled.</p>",403);let O="",$="";try{let q=await J(k);O=q.get("prompt")??"";let U;try{U=m(k)}catch(ie){throw new ao(ie.message)}$=U;let Z;try{Z=d(q.get("csrf")??"")}catch(ie){throw new ao(ie.message)}if(Z.browser!==U||Z.purpose!=="review")throw new ao("Review form no longer matches this browser session. Reloading will renew it.");O=oe(q);let G={browser:U,digest:c(O),target:f(),key:`localweb:${nd(24).toString("hex")}`,expires:s()+3e5};return N(k,"Review prompt to math",`<div id="comm-review-panel"><p>New prompt: Operator \u2192 ${L("math")}. Task link: none.</p><p>Queue one prompt for math to handle on its next pull. Processing may wait; the agent may use its existing file/network permissions.</p><p>Recipient: <a href="${v(`${n}/sessions/math/Lead`)}" title="${v(G.target)}">math:Lead</a></p><pre id="comm-review-preview">
|
|
557
557
|
${v(O)}</pre><form id="comm-confirm-form" method="post" action="${o}/prompts"><input type="hidden" name="confirmation" value="${v(u(G))}"><textarea name="prompt" hidden>
|
|
558
558
|
${v(O)}</textarea><button id="comm-confirm-submit" type="submit">Confirm and queue</button></form><button type="button" id="comm-edit-button">Edit prompt</button><p id="comm-send-status" role="status"></p><details><summary>Edit prompt</summary>${D(U,O)}</details><p>Confirmation expires in five minutes. If a submission result is uncertain, retry this same confirmation; do not create a new prompt.</p></div>`)}catch(q){let U=q instanceof ao?409:400;return N(k,"Review unavailable",`<p>${v(q.message)}</p>${$?D($,O):`<pre>
|
|
559
|
-
${v(O)}</pre>`}<a href="${o}">Math inbox</a>`,U)}}),t.post("/comm/math/prompts",async k=>{if(!e.enabled)return N(k,"Sending unavailable","<p>Sending is not enabled.</p>",403);let O="",$="",q=!1;try{let U=await J(k);O=U.get("prompt")??"",$=U.get("confirmation")??"";let Z=m(k);O=
|
|
560
|
-
${v(O)}</pre>${W(O,$)}`,429);let M=Ra(r.db.db,r.teams,{to:"math",prompt:O,dedupeKey:G.key});return M.replayed||(
|
|
561
|
-
${v(O)}</pre>${q?W(O,$):""}<p>No new confirmation key was issued. For an uncertain result, retain the original confirmation and check the inbox before sending again. A server restart invalidates pending confirmations; known receipt URLs remain readable.</p><a href="${o}">Math inbox</a>`,400)}}),t.get("/comm/math/prompts/:id",k=>{let O=k.req.param("id"),$=Number(O);if(!/^[1-9]\d*$/.test(O)||!Number.isSafeInteger($))return N(k,"Not found","<p>Invalid prompt ID.</p>",404);let q=ro(r,$);if(!q||q.to_id!=="math")return N(k,"Not found","<p>No Math inbox prompt at this address.</p>",404);let U=ws(r,$),Z=jr(r,$),G=U.answer,
|
|
562
|
-
${v(Z.text)}</pre><p>${Z.truncated?"Preview truncated.":"Saved prompt text; availability may change."}</p>`:"<p>Prompt preview unavailable.</p>"}</article><article data-queue-id="${$}" data-event="response"><h3>Answer</h3><p id="comm-poll-notice" role="status" aria-live="polite">Live updates while this page is visible.</p><p id="comm-response-status">${
|
|
563
|
-
${v(G.answer_text)}</pre><p id="comm-response-truncation">${G.truncated?`Truncated: ${G.byteLength} of ${G.totalBytes} bytes. No continuation endpoint is available.`:`${G.byteLength} bytes returned.`}</p>`:`<p id="comm-response-meta"></p><pre id="comm-response" hidden></pre><p id="comm-response-truncation"></p><p id="comm-response-none">${ae?"":"No correlated answer recorded yet. Refresh to check again."}</p>`}</article></section><div id="assigned-work">${w()}</div>`)}),t}import{basename as aM}from"node:path";var id=50,cM=e=>e.trim().toLowerCase().replace(/[\s_]+/g,"-"),ad=e=>["blocked","error","on-hold","rate-limited"].includes(cM(e));function jE(e){if(!/^[1-9]\d*$/.test(e)||!Number.isSafeInteger(Number(e)))throw new C("INVALID_ARGUMENT","Invalid positive integer ID");return Number(e)}function lM(e){let t={},r=new Set(["q","project","status","kind","team","attention","sort","page"]);for(let[n,o]of new URL(e).searchParams){if(!r.has(n)||Object.hasOwn(t,n)||o.length>256||/[\x00-\x1f\x7f]/.test(o))throw new C("INVALID_ARGUMENT","Invalid or duplicate task filter");t[n]=o}if(t.page&&jE(t.page)>Le)throw new C("INVALID_ARGUMENT","Page exceeds safety limit");if(t.attention&&t.attention!=="1")throw new C("INVALID_ARGUMENT","attention must be 1");if(t.sort&&!["id","updated"].includes(t.sort))throw new C("INVALID_ARGUMENT","Unknown task sort");if(t.kind&&!["epic","task","subtask"].includes(t.kind))throw new C("INVALID_ARGUMENT","Unknown task kind");return t}function PE(e,t){let r=new URLSearchParams(Object.entries(t).filter(([,n])=>n!==""));return e+(r.size?`?${r}`:"")}function uM(e,t,r,n){let o=e.filter(f=>(!t.q||`${f.id} ${f.title} ${f.description} ${f.requirements} ${f.acceptance_criteria}`.toLowerCase().includes(t.q.toLowerCase()))&&(!t.attention||ad(f.status))&&(!n||f.owner_team_path===n));o.sort(t.sort==="updated"?(f,p)=>Date.parse(p.updated_at)-Date.parse(f.updated_at)||f.id-p.id:(f,p)=>f.id-p.id);let s=Number(t.page||1),i=o.slice((s-1)*id,s*id),a=new Map(e.map(f=>[f.id,f])),c=f=>{if(f===null)return;let p=a.get(f)??r(f);return a.set(f,p),p},l=new Map(i.map(f=>[f.id,{...f,context:!1}]));for(let f of i){let p=c(f.parent_id),h=new Set([f.id]);for(;p&&!h.has(p.id);)h.add(p.id),l.has(p.id)||l.set(p.id,{...p,context:!0}),p=c(p.parent_id)}let u=new Map;for(let f of l.values()){let p=f.parent_id!==null&&l.has(f.parent_id)?f.parent_id:null,h=u.get(p)??[];h.push(f),u.set(p,h)}let d=[],m=f=>{for(let p of u.get(f)??[])d.push(p),m(p.id)};return m(null),{rows:d,total:o.length,pageNumber:s,more:o.length>s*id,byId:a}}function co(e,t){return Ne(`${t}/tasks/${e.id}`,`#${e.id} ${e.title}`)}function HE(e,t,r){if(e.owner_team_path===null)return"Unassigned";let n=`${aM(e.owner_team_path)}:${e.owner_alias}`,o=`${e.owner_team_path}:${e.owner_alias}`,s=t.get(e.owner_team_path);return s&&e.owner_alias?`<a href="${v(`${r}/sessions/${encodeURIComponent(s)}/${encodeURIComponent(e.owner_alias)}`)}" title="${v(o)}">${v(n)}</a>`:`<span title="${v(o)}">${v(n)}</span>`}function BE(e){if(e.blocked_on!==null){let t=e.blocked_on==="operator"?"Operator":e.blocked_on;return`<span class="status-chip status-processing" title="blocked_on names who this task is waiting on; independent of the recorded status text">Blocked on ${v(t)}</span>`}if(e.hold_until!==null){let t=Date.parse(e.hold_until)<=Date.now(),r=e.hold_reason?` \u2014 ${v(e.hold_reason)}`:"";return t?`<span class="status-chip status-processing" title="Hold expired ${v(e.hold_until)}; not auto-cleared, needs the owning team to resolve it">Hold expired, evidence due${r}</span>`:`<span class="status-chip status-muted">On hold until ${pe(e.hold_until)}${r}</span>`}return"\u2014"}function UE(e,t,r,n,o="Task ledger"){return io(["Task / hierarchy","Project","Recorded status","Blocked / hold","Recorded owner","Updated","Presentation"],e.map(s=>{let i=[],a=s.parent_id===null?void 0:t.get(s.parent_id),c=new Set([s.id]);for(;a&&!c.has(a.id);)c.add(a.id),i.unshift(a),a=a.parent_id===null?void 0:t.get(a.parent_id);let l=i.map(u=>co(u,r)).join(" / ");return[`${l?`${l}<br>`:""}${co(s,r)}${s.context?" <strong>(ancestor context)</strong>":""}<br>${v(s.kind)}`,v(s.project),v(s.status),BE(s),HE(s,n,r),pe(s.updated_at),s.kind==="epic"?"Not applicable":s.delivered_ts?`First presented ${pe(s.delivered_ts)}`:"Not recorded"]}),o)}function FE(e,t,r){let n=["q","project","status"].map(i=>`<label>${{q:"Search",project:"Project",status:"Exact recorded status"}[i]}<input name="${i}" value="${v(e[i]??"")}" maxlength="256"></label>`).join(""),o=(i,a,c)=>`<label>${a}<select name="${i}">${c.map(([l,u])=>`<option value="${v(l)}"${e[i]===l?" selected":""}>${v(u)}</option>`).join("")}</select></label>`,s=[["",`All teams (${t.length} own work in this scope)`],...t.map(i=>[i,i])];return`<form method="get" action="${v(r)}/tasks">${n}${o("kind","Kind",[["","All kinds"],["epic","Epic"],["task","Task"],["subtask","Subtask"]])}${o("team","Owning team",s)}${o("sort","Sort",[["id","ID"],["updated","Updated"]])}<label>Attention only<input type="checkbox" name="attention" value="1"${e.attention?" checked":""}></label><button>Filter tasks</button> ${Ne(`${r}/tasks`,"Clear filters")}</form>`}function qE(e){return`<p>${e.total} entities in this scope: ${e.by_kind.epic??0} epics, ${e.by_kind.task??0} tasks, ${e.by_kind.subtask??0} subtasks.</p>`}function WE(e,t,r=""){let n=r.replace(/\/$/,""),o=(i,a,c,l=200)=>Me(i,$e(a,c,n,{"data-page":"tasks"}),l),s=(i,a)=>{let c=a instanceof C?a.code==="NOT_FOUND"?404:a.code==="DB_BUSY"?503:a.code==="STORAGE_ERROR"?500:a.code==="CONFLICT"?409:400:500;return o(i,"Tasks unavailable",`<p>${v(a instanceof Error?a.message:String(a))}</p>${Ne(`${n}/tasks`,"Task ledger")}`,c)};e.get("/tasks",i=>{try{let a=lM(i.req.url),c;if(a.team){let p=t.teams.find(h=>h.name===a.team&&B(h));if(!p||!B(p))throw new C("INVALID_ARGUMENT","Unknown local owning team");c=Q(p)}let l=Nr(t.db.db,{...a.project?{project:a.project}:{},...a.kind?{kind:a.kind}:{},...a.status?{status:a.status}:{},limit:Le}),u=Br(t.teams),d=[...new Set(l.rows.map(p=>p.owner_team_path).filter(p=>p!==null).map(p=>u.get(p)).filter(p=>p!==void 0))].sort();if(l.meta.next_cursor!==null)return o(i,"Tasks",'<p class="warning">This scope exceeds 10,000 entities. Choose a project, kind, or status to narrow it; an incomplete board is not shown.</p>'+FE(a,d,n),503);let m=uM(l.rows,a,p=>Ir(t.db.db,p),c),f=`<nav aria-label="Task pages">${m.pageNumber>1?Ne(PE(`${n}/tasks`,{...a,page:String(m.pageNumber-1)}),"Previous page"):""} ${m.more?Ne(PE(`${n}/tasks`,{...a,page:String(m.pageNumber+1)}),"Next page"):""}</nav>`;return o(i,"Tasks",'<p data-testid="page-intro">Epics group tasks, and tasks can contain subtasks; follow a title to read its details and children. Status and owner are recorded values; Updated means content activity; Attention means blocked, error, on-hold, or rate-limited; First presentation means when the item was first shown to an agent to work on, not completion. Blocked / hold is separate from the recorded status text: it shows when a task is structurally waiting on a specific team or operator, or deliberately parked until a date, even while its own status reads as ordinary active work.</p>'+qE({total:l.rows.length,by_kind:l.rows.reduce((p,h)=>(p[h.kind]=(p[h.kind]??0)+1,p),{})})+FE(a,d,n)+`<p>${m.total} matching entities. Page ${m.pageNumber}, up to 50 matches plus labeled ancestor context; presentation does not mean completion.</p>`+f+UE(m.rows,m.byId,n,u)+f)}catch(a){return s(i,a)}}),e.get("/tasks/:id",i=>{try{let a=jE(i.req.param("id")),c=Ir(t.db.db,a),l=Lr(t.db.db,a),u=[],d=c.parent_id,m=new Set([a]);for(;d!==null&&!m.has(d);){m.add(d);let T=Ir(t.db.db,d);u.unshift(T),d=T.parent_id}let f=Br(t.teams),p=new Map([...u,c,...l.children].map(T=>[T.id,T])),h=T=>T.length?`<ul>${T.map(R=>`<li>${co(R,n)} \u2014 ${v(R.status)}</li>`).join("")}</ul>`:"<p>None recorded.</p>",g=`<nav aria-label="Breadcrumb">${Ne(`${n}/tasks`,"Task ledger")} / ${u.map(T=>Ne(`${n}/tasks/${T.id}`,`#${T.id} ${T.title} (status: ${T.status})`)).join(" / ")}${u.length?" / ":""}<span aria-current="page">#${c.id} ${v(c.title)}</span></nav>`,_=u.at(-1),E=u.find(T=>T.kind==="epic"),S=`<p data-testid="work-context">${c.kind==="epic"?"This is an epic with no parent.":c.kind==="task"?E?`This is a task in epic ${co(E,n)}.`:"This is a task with no parent epic.":`This is a subtask${_?` of task ${co(_,n)}`:""}${E?`, part of epic ${co(E,n)}.`:"; no parent epic is recorded."}`}</p><p data-testid="page-intro">This page describes one work item and its recorded status and owner. Follow the breadcrumb to its parent or epic, or a child title to drill down; Updated records content activity, not completion.</p>`+g+`<p>Kind: ${v(c.kind)}; project: ${v(c.project)}; recorded status: <strong>${v(c.status)}</strong>.</p><p>Recorded owner: ${HE(c,f,n)}.</p><p>Blocked / hold: ${BE(c)}</p>`+["description","requirements","acceptance_criteria"].map(T=>`<h2>${{description:"Description",requirements:"Requirements",acceptance_criteria:"Acceptance criteria"}[T]}</h2><pre>${v(c[T]||"Not supplied")}</pre>`).join("")+qE(Cr(t.db.db,{id:a}))+"<h2>Children</h2>"+UE(l.children,p,n,f,"Immediate children")+"<h2>Depends on</h2>"+h(c.dependencies.outgoing)+"<h2>Required by</h2>"+h(c.dependencies.incoming)+`<h2>Times</h2><p>Created ${pe(c.created_at)}; updated ${pe(c.updated_at)}.</p><p>First presentation: ${c.kind==="epic"?"Not applicable":c.delivered_ts?pe(c.delivered_ts):"Not recorded"}. Presentation does not mean completion.</p>`;return o(i,`Task #${c.id}: ${c.title}`,S)}catch(a){return s(i,a)}})}import{basename as dM}from"node:path";var GE=50,VE='<p data-testid="page-intro">A cron job is work scheduled to run automatically; this page reviews its saved configuration and recorded results. An unresolved escalated run is waiting for a person to help, while execution uncertain means the process has not been confirmed stopped.</p>',mM={ok:"OK (last-fire bookkeeping)",error:"Error",skipped_overlap:"Skipped: earlier execution still guarded",skipped_stale:"Skipped: scheduled window too old",reconciled:"Process gone; outcome unknown",blocked_escalation:"Skipped: unresolved escalation at last check"},at=e=>e===null?"Not recorded":pe(e),Ze=e=>e===null?"Not configured":v(e),JE=e=>e.last_fire_status===null?"Not recorded":`${v(mM[e.last_fire_status]??e.last_fire_status)} <small>(${v(e.last_fire_status)})</small>`;function zE(e){let t=e.req.queries("after");if(t===void 0)return 0;let r=t[0]??"";if(t.length!==1||!/^(0|[1-9]\d*)$/.test(r)||!Number.isSafeInteger(Number(r)))throw new P("INVALID_ARGUMENT","after must be a nonnegative integer");return Number(r)}function YE(e,t,r){if(e.session_teamfile===null||e.session_alias===null)return"Not configured";let n=`${e.session_teamfile}:${e.session_alias}`,o=`${dM(e.session_teamfile)}:${e.session_alias}`,s=t.get(e.session_teamfile);return s?`<a href="${v(`${r}/sessions/${encodeURIComponent(s)}/${encodeURIComponent(e.session_alias)}`)}" title="${v(n)}">${v(o)}</a>`:`<span title="${v(n)}">${v(o)}</span> (not in the current local registry)`}function KE(e,t){let r=[];return(e.last_fire_status==="error"||e.last_fire_error)&&r.push("Recorded fire error"),e.last_fire_status==="blocked_escalation"&&r.push("Last check blocked by escalation"),e.last_fire_status==="reconciled"&&r.push("Previous execution outcome unknown"),t?.status==="escalated"&&t.escalation_resolved_at===null&&r.push(`Run #${t.id}: escalated \u2014 waiting for a person`),t?.execution_state==="uncertain"&&r.push(`Run #${t.id}: execution uncertain`),t?.status==="failed"&&r.push(`Run #${t.id}: failed; execution still guarded`),r}function cd(e){return`<dl>${e.map(([t,r])=>`<dt>${v(t)}</dt><dd>${r}</dd>`).join("")}</dl>`}function fM(e){if(e===null)return"<p>No artifacts recorded.</p>";try{let t=JSON.parse(e);if(Array.isArray(t)&&t.every(r=>typeof r=="string"))return t.length?`<ul>${t.map(r=>`<li>${v(r)}</li>`).join("")}</ul>`:"<p>No artifacts recorded.</p>"}catch{}return`<pre>${v(e)}</pre>`}function pM(e){let t=e.status==="escalated",r=t&&e.escalation_resolved_at===null,n=e.status==="failed"||r||e.execution_state==="uncertain",o=`${e.status}${t?r?" \u2014 waiting for a person":" \u2014 escalation resolved":""}`,s=t||e.escalation_reason!==null||e.escalation_resolved_at!==null?"<h4>Escalation</h4>"+cd([["Reason",Ze(e.escalation_reason)],["Requested action",Ze(e.escalation_action)],["Owner",Ze(e.escalation_owner)],["Resolved at",at(e.escalation_resolved_at)],["Resolution",Ze(e.escalation_resolution)],["Resolved by",Ze(e.escalation_resolution_actor)],["Resolution note",Ze(e.escalation_resolution_note)]]):"";return`<article id="run-${e.id}"${n?' class="warning"':""}><h3>Run #${e.id}: ${v(o)}</h3>`+cd([["Execution state",v(e.execution_state)],["Trigger",v(e.trigger_kind)],["Created",at(e.created_at)],["Started",at(e.started_at)],["Finished",at(e.finished_at)],["Result reported",at(e.reported_at)],["Last updated",at(e.updated_at)],["Execution reference",Ze(e.execution_identity)],["Process ID",Ze(e.pid)],["Execution uncertainty reason",Ze(e.execution_uncertain_reason)],["Execution confirmed gone",at(e.execution_gone_at)],["Confirmation note",Ze(e.execution_confirmation_note)]])+`<h4>Summary</h4><pre>${v(e.summary??"No summary recorded.")}</pre><h4>Artifacts (recorded paths or references)</h4>`+fM(e.artifacts)+s+"</article>"}function QE(e,t,r=""){let n=r.replace(/\/$/,""),o=(a,c,l,u=200)=>Me(a,$e(c,l,n),u),s=(a,c)=>{let l=c instanceof P?c.code==="NOT_FOUND"?404:c.code==="DB_BUSY"?503:c.code==="INVALID_ARGUMENT"?400:500:500;return o(a,"Cron review unavailable",`<p>${v(c instanceof Error?c.message:String(c))}</p>${Ne(`${n}/cron`,"Cron jobs")}`,l)},i=(a,c,l)=>`<nav aria-label="Cron pages">${c?Ne(a,"First page"):""} ${l!==null?Ne(`${a}?after=${l}`,"Next page"):""}</nav>`;e.get("/cron",a=>{try{let c=zE(a),l=Yi(t.db.db,{limit:GE,after:c}),u=Br(t.teams),d=l.rows.map(f=>({job:f,flags:KE(f,It(t.db.db,f.id))})),m=(f,p)=>io(["Job","Schedule / timezone","Action kind","Enabled","Last fire status","Last fired","Scheduler last looked at","Last fire error","Session"],f.map(({job:h,flags:g})=>[Ne(`${n}/cron/${h.id}`,`#${h.id} ${h.title}`)+(g.length?`<p class="warning"><strong>${g.map(v).join("<br>")}</strong></p>`:""),`<code>${v(h.schedule_expr)}</code><br>${v(h.timezone??"Host-local timezone")}`,v(h.action_kind),h.enabled?"Enabled":"Disabled",JE(h),at(h.last_fired_ts),at(h.last_checked_ts),h.last_fire_error===null?"None recorded":`<pre>${v(h.last_fire_error)}</pre>`,YE(h,u,n)]),p);return o(a,"Cron jobs",VE+"<p>Saved jobs, up to 50 per page in ID order. Times below are stored scheduler records; OK is not proof of successful AI work. A retained error can predate a later skipped check.</p><h2>Failures and review flags</h2>"+m(d.filter(f=>f.flags.length>0),"Jobs with review flags on this page")+"<h2>Other jobs</h2>"+m(d.filter(f=>f.flags.length===0),"Other jobs on this page")+i(`${n}/cron`,c,l.meta.next_cursor))}catch(c){return s(a,c)}}),e.get("/cron/:id",a=>{try{let c=a.req.param("id");if(!/^[1-9]\d*$/.test(c)||!Number.isSafeInteger(Number(c)))throw new P("INVALID_ARGUMENT","Invalid positive job ID");let l=zE(a),u=Ce(t.db.db,Number(c)),d=Wi(t.db.db,{jobId:u.id,limit:GE,after:l}),m=It(t.db.db,u.id),f=KE(u,m),p=cd([["Title",v(u.title)],["Schedule expression",`<code>${v(u.schedule_expr)}</code>`],["Timezone",v(u.timezone??"Host-local timezone")],["Action kind",v(u.action_kind)],["Enabled",u.enabled?"Enabled":"Disabled"],["Provider",Ze(u.provider)],["Model",Ze(u.model)],["Working directory",Ze(u.working_directory)],["Escalation owner",Ze(u.escalation_owner)],["Session",YE(u,Br(t.teams),n)],["Session teamfile",Ze(u.session_teamfile)],["Session alias",Ze(u.session_alias)],["Session seeded at",at(u.session_seeded_at)],["Session generation",v(u.session_generation)],["Scheduler last looked at",at(u.last_checked_ts)],["Last fired",at(u.last_fired_ts)],["Last fire status",JE(u)],["Last fire error",u.last_fire_error===null?"None recorded":`<pre>${v(u.last_fire_error)}</pre>`],["Recorded execution since",at(u.running_since_ts)],["Recorded systemd unit",Ze(u.running_systemd_unit)],["Created",at(u.created_at)],["Updated",at(u.updated_at)],["Revision",v(u.revision)]]),h=m?`<p>${Ne(`${n}/cron/${u.id}?after=${m.id-1}#run-${m.id}`,`Inspect guarded run #${m.id}`)} \u2014 ${v(m.status)}, execution ${v(m.execution_state)}.</p>`:"",g=l?"<p>No more run records after this cursor.</p>":"<p>No run history recorded. Command or script jobs may have last-fire records without run history; an empty history is not itself an error.</p>";return o(a,`Cron job #${u.id}: ${u.title}`,VE+`<p>${Ne(`${n}/cron`,"All cron jobs")}</p>`+(f.length?`<p class="warning"><strong>${f.map(v).join("<br>")}</strong></p>`:"")+h+"<h2>Configuration</h2>"+p+`<h3>Action payload (command, script, prompt, or enqueue data)</h3><pre>${v(u.action_payload)}</pre><h2>Run history</h2><p>Up to 50 recorded runs, oldest ID first. Outcome and process state are separate: active is recorded as active, uncertain is not confirmed stopped, and gone is confirmed stopped.</p>`+(d.rows.length?d.rows.map(pM).join(""):g)+i(`${n}/cron/${u.id}`,l,d.next_cursor))}catch(c){return s(a,c)}})}function hM(e,t){return t===null&&e.retracted_ts===null&&(e.status==="pending"||e.status==="escalating"||e.status==="sent"||e.status==="retrieved")}var ZE=64*1024;async function gM(e){if(!e.req.header("content-type")?.toLowerCase().startsWith("application/x-www-form-urlencoded"))throw new C("INVALID_ARGUMENT","Expected a browser form.");let t=e.req.raw.body?.getReader();if(!t)throw new C("INVALID_ARGUMENT","Missing form.");let r=0,n=[];for(;;){let{done:i,value:a}=await t.read();if(i)break;if(r+=a.byteLength,r>ZE)throw await t.cancel(),new C("INVALID_ARGUMENT","Form exceeds the size limit.");n.push(a)}let s=new URLSearchParams(Buffer.concat(n).toString("utf8")).getAll("answer");if(s.length!==1)throw new C("INVALID_ARGUMENT","Missing or duplicate answer field.");return s[0]}function eb(e,t){let r=[t.from_id,t.to_id,t.escalation_only,t.to_alias],o=e.prepare("SELECT MIN(id) AS id FROM queue WHERE from_id = ? AND to_id = ? AND escalation_only = ? AND to_alias IS ? AND id > ? AND status != 'merged'").get(...r,t.id).id??Number.MAX_SAFE_INTEGER;return e.prepare("SELECT * FROM queue WHERE from_id = ? AND to_id = ? AND escalation_only = ? AND to_alias IS ? AND status = 'merged' AND id > ? AND id < ?").all(...r,t.id,o)}function tb(e,t){let r=[];t.retracted_ts!==null&&t.retracted_reason&&r.push(t.retracted_reason);let n=eb(e,t);for(let o of n)o.retracted_ts!==null&&o.retracted_reason&&r.push(o.retracted_reason);return r}function ld(e,t=Date.now()){return cs(e,t).map(n=>{let o=n.row,s=pn(e,o),i=as(e,o),a=n.ageMs>=ds||s>=2&&o.sent_ts===null,c=tb(e,o);return{row:o,constituentCount:s,retractedCount:i,urgent:a,retractedReasons:c}})}function rb(e){return e===1?"1 of 1":`${e} merged into this one`}function _M(e){return e==="merged"||e==="informational"||e==="retracted"}function wM(e){return e.lifecycle==="queued"?"queued":e.lifecycle==="processing"?"processing":_M(e.lifecycleBasis)?"muted":"replied"}function yM(e){return e.lifecycle==="queued"?"Queued":e.lifecycle==="processing"?"Processing":e.lifecycleBasis==="merged"?"Combined":e.lifecycleBasis==="informational"?"Informational":e.lifecycleBasis==="retracted"?"Retracted":"Replied"}function nb(e){return`<span class="status-chip status-${wM(e)}" title="${v(ud(e))}">${v(yM(e))}</span>`}function ud(e){return e.lifecycle==="queued"?"Queued \u2014 waiting for handling":e.lifecycle==="processing"?e.lifecycleBasis==="confirmed"?"Processing \u2014 picked up by inbox":"Processing \u2014 delivery attempted; read not confirmed":e.lifecycle==="finished"?e.lifecycleBasis==="retracted"?"Finished \u2014 retracted":e.lifecycleBasis==="merged"?"Finished \u2014 combined with another prompt":e.lifecycleBasis==="informational"?"Finished \u2014 informational, no answer expected":"Finished \u2014 answer recorded":`${e.lifecycle} (${e.lifecycleBasis})`}function EM(e){return`<dl>${e.map(([t,r])=>`<dt>${v(t)}</dt><dd>${r}</dd>`).join("")}</dl>`}function bM(e){return e.length===0?"<p>No standing decisions recorded.</p>":e.map(t=>{let r=t.would_change_it?`<p><strong>Would change this:</strong> ${v(t.would_change_it)}</p>`:"<p><strong>Would change this:</strong> Not recorded.</p>",n=t.affects.length>0?t.affects.map(v).join(", "):"Not recorded";return`<article aria-label="Decision #${t.id}"><h3>${v(t.subject)}</h3><p>${v(t.decision)}</p>${r}<details><summary>Reasoning</summary><p>${v(t.reasoning)}</p></details><p>Decided by ${v(t.decided_by)}, ${pe(t.decided_at)}. Affects: ${n}.</p></article>`}).join("")}function TM(e){return e.length===0?"<p>Nothing blocking math right now.</p>":e.map(t=>`<article aria-label="Blocked #${t.id}"><h3>!!! ${v(t.title)}</h3><p>Category: ${v(t.category)}.</p>${t.detail?`<p>${v(t.detail)}</p>`:""}<p>Raised by ${v(t.raised_by)}, ${pe(t.raised_at)}.</p></article>`).join("")}function SM(e,t){return e.length===0?"<p>No open judgment calls for the operator.</p>":e.map(r=>{let n=r.downstream?`<p><strong>Downstream:</strong> ${v(r.downstream)}</p>`:"<p><strong>Downstream:</strong> Not recorded.</p>";return`<article aria-label="Ask #${r.id}"><h3>${v(r.subject)}</h3><p>${v(r.reason)}</p>${n}<p>Status: Open. Raised by ${v(r.raised_by)}, ${pe(r.raised_at)}.</p><p><a href="${v(t)}/comm/math?ask=${r.id}#compose">Discuss this with math</a></p></article>`}).join("")}function XE(e,t,r,n){if(e.length===0)return`<p>No ${t.toLowerCase()}.</p>`;let o=["Prompt","From","Age","Constituents","Retractions","Lifecycle"],s=e.map(i=>{let a=i.row,c=De(n,a.id),l=xt(a,c),u=`<a href="${v(r)}/operator/${a.id}">#${a.id}</a>`,d=v(a.from_id),m=pe(a.created_ts),f=rb(i.constituentCount),p=i.retractedCount>0?`${i.retractedCount} retracted${i.retractedReasons.length>0?`: ${i.retractedReasons.map(g=>`\u201C${v(g)}\u201D`).join("; ")}`:""}`:"\u2014",h=`${nb(l)} \xB7 ${v(ud(l))}`;return[u,d,m,f,p,h]});return io(o,s,t)}function ob(e,t,r=""){let n=r.replace(/\/$/,"");e.get("/operator",o=>{try{let s=ld(t.db.db,Date.now()),i=s.filter(g=>g.urgent),a=s.filter(g=>!g.urgent),c='<p data-testid="page-intro">What needs the operator, what math has already decided for them to review, and a way to reach math directly. Blocked means math is technically incapable of proceeding (re-auth, billing, account identity) -- rare and urgent. Escalations are requests a team sent that genuinely need a decision, shown whether or not anyone is currently monitoring them; urgent means waiting over four hours, or never delivered despite repeated sends. Constituents counts how many separate escalations were folded into one message; Retractions counts how many of those the sender has since withdrawn, with their stated reason. Asks are judgment calls only the operator can make, routine, not urgent -- problem statement, then what it affects downstream, then who raised it. Decisions are rulings math has already made, for review, not approval.</p>',l=`<section class="warning" aria-label="Urgent escalations"><h2>Urgent escalations</h2>${XE(i,"Urgent escalations",n,t.db.db)}</section>`,u=`<section aria-label="Routine escalations"><h2>Routine escalations</h2>${XE(a,"Routine escalations",n,t.db.db)}</section>`,d=`<section aria-label="Send a message"><h2>Send a message</h2><p>Start a new request to math. This reuses the same queue and composer as <a href="${v(n)}/comm/math">the Math inbox</a> -- one write path, not a second one.</p><p><a href="${v(n)}/comm/math#compose">Write a message to math</a></p></section>`,m,f,p;try{let g=Na(),_,E,y;try{_=OE(g),E=LE(g),y=IE(g)}finally{g.close()}m=`<section class="warning" aria-label="Blocked"><h2>Blocked</h2>${TM(_)}</section>`,f=`<section aria-label="Asks"><h2>Asks</h2>${SM(E,n)}</section>`,p=`<section aria-label="Decisions"><h2>Decisions</h2><p>Rulings math has already made, in force now (superseded and reversed decisions are excluded). Nothing here waits on you -- read, and ping math if you disagree.</p>${bM(y)}</section>`}catch(g){let _=`<p class="warning">lmteam data unavailable: ${v(g instanceof Error?g.message:String(g))}</p>`;m=`<section class="warning" aria-label="Blocked"><h2>Blocked</h2>${_}</section>`,f=`<section aria-label="Asks"><h2>Asks</h2>${_}</section>`,p=`<section aria-label="Decisions"><h2>Decisions</h2>${_}</section>`}let h=`${c}${m}${l}${f}${d}${u}${p}`;return Me(o,$e("Operator inbox",h,n,{"data-page":"operator"},[],!0))}catch(s){return Me(o,$e("Operator inbox unavailable",`<p>${v(s instanceof Error?s.message:String(s))}</p>`,n,{},[],!0),500)}}),e.get("/operator/:id",o=>{let s=o.req.param("id"),i=Number(s);if(!s||!/^[1-9]\d*$/.test(s)||!Number.isSafeInteger(i))return Me(o,$e("Invalid escalation ID",`<p>Invalid escalation ID.</p><p><a href="${v(n)}/operator">Operator inbox</a></p>`,n,{},[],!0),400);try{let a=kr(t.db.db,i);if(!a||a.to_id!=="operator")return Me(o,$e("Not found",`<p>No operator escalation at this address.</p><p><a href="${v(n)}/operator">Operator inbox</a></p>`,n,{},[],!0),404);let c=jr(t,i),l=De(t.db.db,i),u=xt(a,l),d=pn(t.db.db,a),m=as(t.db.db,a),f=tb(t.db.db,a),p=[["From",v(a.from_id)],["To",v(a.to_id)],["Queued",pe(a.created_ts)],["Lifecycle",`${nb(u)} \xB7 ${v(ud(u))}`],["Constituents",v(rb(d))],["Delivery attempted",a.sent_ts?pe(a.sent_ts):"not recorded"],["Picked up",a.retrieved_ts?pe(a.retrieved_ts):"not recorded"],["Subject",a.subject_id?v(a.subject_id):"none"]];m>0&&p.push(["Retractions",`${m} retracted${f.length>0?`: ${f.map(S=>`\u201C${v(S)}\u201D`).join("; ")}`:""}`]),a.retracted_ts!==null&&(p.push(["Retracted at",pe(a.retracted_ts)]),p.push(["Retraction reason",v(a.retracted_reason??"(none)")]));let h="";c?.status==="available"?h=`<pre>${v(c.text)}</pre><p>${c.truncated?`Preview truncated (${c.byteLength} bytes).`:`Full content (${c.byteLength} bytes).`}</p>`:h=`<p>Prompt preview unavailable (${v(c?.status??"missing")}).</p>`;let g="";l?g=`<section><h2>Answer</h2><p>Recorded ${pe(l.answered_at)}</p><pre>${v(l.answer_text)}</pre></section>`:hM(a,l)&&(g=`<section aria-label="Answer"><h2>Answer</h2><form method="post" action="${v(n)}/operator/${i}/answer"><label for="answer">Answer text</label><textarea id="answer" name="answer" rows="8" maxlength="${ZE}" required></textarea><button>Send answer</button></form></section>`);let _=eb(t.db.db,a),E="";_.length>0&&(E=`<section><h3>Merged constituents (${_.length})</h3><p>Additional escalations folded into this message:</p><ul>${_.map(S=>`<li><a href="${v(n)}/operator/${S.id}">#${S.id}</a> from ${v(S.from_id)} (queued ${pe(S.created_ts)})${S.retracted_ts?` \u2014 <strong>Retracted</strong>: \u201C${v(S.retracted_reason)}\u201D`:""}</li>`).join("")}</ul></section>`);let y=`<p><a href="${v(n)}/operator">Operator inbox</a></p>
|
|
559
|
+
${v(O)}</pre>`}<a href="${o}">Math inbox</a>`,U)}}),t.post("/comm/math/prompts",async k=>{if(!e.enabled)return N(k,"Sending unavailable","<p>Sending is not enabled.</p>",403);let O="",$="",q=!1;try{let U=await J(k);O=U.get("prompt")??"",$=U.get("confirmation")??"";let Z=m(k);O=oe(U);let G=d($);if(G.browser!==Z||G.digest!==c(O)||!Number.isFinite(G.expires)||!/^localweb:[a-f0-9]{48}$/.test(G.key))throw new Error("Confirmation does not match this browser and prompt.");let ie=r.db.db.prepare("SELECT id, admission_fingerprint FROM queue WHERE dedupe_key = ?").get(G.key);if(ie){if(ie.admission_fingerprint!==c(`math\0${O}`))throw new Error("Confirmation conflicts with an existing admission.");return k.redirect(`${o}/prompts/${ie.id}`,303)}if(G.expires<s()||G.target!==f())throw new Error("Confirmation expired or changed. Check the inbox before reviewing again; a previous uncertain admission may already exist.");q=!0;let be=s()-6e4;for(let[j,Y]of a)Y.start<be&&a.delete(j);let ae=a.get(Z)??{start:s(),count:0};if(ae.count>=10)return N(k,"Please wait",`<p>Ten prompts were queued this minute. Wait before retrying this unchanged confirmation.</p><pre>
|
|
560
|
+
${v(O)}</pre>${W(O,$)}`,429);let M=Ra(r.db.db,r.teams,{to:"math",prompt:O,dedupeKey:G.key});return M.replayed||(ae.count++,a.set(Z,ae)),k.redirect(`${o}/prompts/${M.queueId}`,303)}catch(U){return N(k,"Prompt not confirmed",`<p>${v(U.message)}</p><pre>
|
|
561
|
+
${v(O)}</pre>${q?W(O,$):""}<p>No new confirmation key was issued. For an uncertain result, retain the original confirmation and check the inbox before sending again. A server restart invalidates pending confirmations; known receipt URLs remain readable.</p><a href="${o}">Math inbox</a>`,400)}}),t.get("/comm/math/prompts/:id",k=>{let O=k.req.param("id"),$=Number(O);if(!/^[1-9]\d*$/.test(O)||!Number.isSafeInteger($))return N(k,"Not found","<p>Invalid prompt ID.</p>",404);let q=ro(r,$);if(!q||q.to_id!=="math")return N(k,"Not found","<p>No Math inbox prompt at this address.</p>",404);let U=ws(r,$),Z=jr(r,$),G=U.answer,ie=U.lifecycle==="finished"&&p(U.lifecycleBasis),be=v(q.retracted_reason??"no reason recorded"),ae=U.lifecycleBasis==="informational"?"This was an informational send; no answer is expected.":U.lifecycleBasis==="retracted"?`This prompt was retracted by its sender: ${be}. No answer is expected.`:"This prompt was combined into another prompt. The combined prompt ID is not recorded, so no link is available.",M=U.lifecycleBasis==="informational"?"No answer expected: this was an informational send.":U.lifecycleBasis==="retracted"?`No answer expected: this prompt was retracted. Reason: ${be}.`:"No separate answer: prompt combined into another prompt.";if(G&&G.prompt_queue_id!==$)return N(k,"Answer unavailable","<p>Answer correlation mismatch.</p>",503);let j="";if(e.enabled)try{f(),j=`<section id="compose" aria-label="Write a prompt" data-mount="${v(n)}" data-base="${v(o)}"><h2>Write another prompt</h2><p>Start a new prompt to ${L("math")}. Review the exact text before queueing it.</p>${D(m(k,!0))}</section>`}catch{}return N(k,`Math prompt #${$}`,`<p>Prompt #${$}: ${L(q.from_id)} \u2192 ${L(q.to_id)}. <span id="comm-receipt-summary">${G?"An answer is recorded below.":ie?ae:"No answer recorded yet."}</span></p>${b}<p>Work: no task association is recorded for this prompt. <a href="#assigned-work">Browse Math\u2019s current assigned work</a>.</p><p id="comm-state" role="status" aria-live="polite" data-sender="${v(q.from_id)}" data-recipient="${v(q.to_id)}" data-queue-id="${$}" data-mount="${v(n)}" data-lifecycle="${U.lifecycle}" data-lifecycle-basis="${U.lifecycleBasis}">${A(U)} \xB7 ${v(H(U))}</p><p><a href="${o}/prompts/${$}">Refresh state</a> \xB7 <a href="${o}">Math inbox</a></p>${j}<section aria-label="Prompt and answer sequence"><h2>Prompt and answer sequence</h2><article data-queue-id="${$}" data-event="request"><h3>Prompt text</h3><p>${L(q.from_id)} \u2192 ${L(q.to_id)} \xB7 queued ${pe(U.createdAt)}</p><details><summary>Prompt times</summary><p id="comm-handling-observation">Delivery attempted ${q.sent_ts?pe(q.sent_ts):"not recorded"} \xB7 Picked up ${q.retrieved_ts?pe(q.retrieved_ts):"not recorded"} </p><p>Answer recorded <span id="comm-reply-time">${G?pe(G.answered_at):"not recorded"}</span></p></details>${Z?.status==="available"?`<pre>
|
|
562
|
+
${v(Z.text)}</pre><p>${Z.truncated?"Preview truncated.":"Saved prompt text; availability may change."}</p>`:"<p>Prompt preview unavailable.</p>"}</article><article data-queue-id="${$}" data-event="response"><h3>Answer</h3><p id="comm-poll-notice" role="status" aria-live="polite">Live updates while this page is visible.</p><p id="comm-response-status">${ie?M:`${G?"Answer recorded":"Waiting for an answer"} in the ${L(q.to_id)} inbox for prompt #${$} from ${L(q.from_id)}.`}</p>${G?`<p id="comm-response-meta">Recorded ${pe(G.answered_at)} \xB7 answer #${G.id} to prompt #${G.prompt_queue_id}</p><pre id="comm-response">
|
|
563
|
+
${v(G.answer_text)}</pre><p id="comm-response-truncation">${G.truncated?`Truncated: ${G.byteLength} of ${G.totalBytes} bytes. No continuation endpoint is available.`:`${G.byteLength} bytes returned.`}</p>`:`<p id="comm-response-meta"></p><pre id="comm-response" hidden></pre><p id="comm-response-truncation"></p><p id="comm-response-none">${ie?"":"No correlated answer recorded yet. Refresh to check again."}</p>`}</article></section><div id="assigned-work">${w()}</div>`)}),t}import{basename as cM}from"node:path";var id=50,lM=e=>e.trim().toLowerCase().replace(/[\s_]+/g,"-"),ad=e=>["blocked","error","on-hold","rate-limited"].includes(lM(e));function HE(e){if(!/^[1-9]\d*$/.test(e)||!Number.isSafeInteger(Number(e)))throw new C("INVALID_ARGUMENT","Invalid positive integer ID");return Number(e)}function uM(e){let t={},r=new Set(["q","project","status","kind","team","attention","sort","page"]);for(let[n,o]of new URL(e).searchParams){if(!r.has(n)||Object.hasOwn(t,n)||o.length>256||/[\x00-\x1f\x7f]/.test(o))throw new C("INVALID_ARGUMENT","Invalid or duplicate task filter");t[n]=o}if(t.page&&HE(t.page)>Le)throw new C("INVALID_ARGUMENT","Page exceeds safety limit");if(t.attention&&t.attention!=="1")throw new C("INVALID_ARGUMENT","attention must be 1");if(t.sort&&!["id","updated"].includes(t.sort))throw new C("INVALID_ARGUMENT","Unknown task sort");if(t.kind&&!["epic","task","subtask"].includes(t.kind))throw new C("INVALID_ARGUMENT","Unknown task kind");return t}function UE(e,t){let r=new URLSearchParams(Object.entries(t).filter(([,n])=>n!==""));return e+(r.size?`?${r}`:"")}function dM(e,t,r,n){let o=e.filter(f=>(!t.q||`${f.id} ${f.title} ${f.description} ${f.requirements} ${f.acceptance_criteria}`.toLowerCase().includes(t.q.toLowerCase()))&&(!t.attention||ad(f.status))&&(!n||f.owner_team_path===n));o.sort(t.sort==="updated"?(f,p)=>Date.parse(p.updated_at)-Date.parse(f.updated_at)||f.id-p.id:(f,p)=>f.id-p.id);let s=Number(t.page||1),i=o.slice((s-1)*id,s*id),a=new Map(e.map(f=>[f.id,f])),c=f=>{if(f===null)return;let p=a.get(f)??r(f);return a.set(f,p),p},l=new Map(i.map(f=>[f.id,{...f,context:!1}]));for(let f of i){let p=c(f.parent_id),h=new Set([f.id]);for(;p&&!h.has(p.id);)h.add(p.id),l.has(p.id)||l.set(p.id,{...p,context:!0}),p=c(p.parent_id)}let u=new Map;for(let f of l.values()){let p=f.parent_id!==null&&l.has(f.parent_id)?f.parent_id:null,h=u.get(p)??[];h.push(f),u.set(p,h)}let d=[],m=f=>{for(let p of u.get(f)??[])d.push(p),m(p.id)};return m(null),{rows:d,total:o.length,pageNumber:s,more:o.length>s*id,byId:a}}function co(e,t){return Ne(`${t}/tasks/${e.id}`,`#${e.id} ${e.title}`)}function BE(e,t,r){if(e.owner_team_path===null)return"Unassigned";let n=`${cM(e.owner_team_path)}:${e.owner_alias}`,o=`${e.owner_team_path}:${e.owner_alias}`,s=t.get(e.owner_team_path);return s&&e.owner_alias?`<a href="${v(`${r}/sessions/${encodeURIComponent(s)}/${encodeURIComponent(e.owner_alias)}`)}" title="${v(o)}">${v(n)}</a>`:`<span title="${v(o)}">${v(n)}</span>`}function WE(e){if(e.blocked_on!==null){let t=e.blocked_on==="operator"?"Operator":e.blocked_on;return`<span class="status-chip status-processing" title="blocked_on names who this task is waiting on; independent of the recorded status text">Blocked on ${v(t)}</span>`}if(e.hold_until!==null){let t=Date.parse(e.hold_until)<=Date.now(),r=e.hold_reason?` \u2014 ${v(e.hold_reason)}`:"";return t?`<span class="status-chip status-processing" title="Hold expired ${v(e.hold_until)}; not auto-cleared, needs the owning team to resolve it">Hold expired, evidence due${r}</span>`:`<span class="status-chip status-muted">On hold until ${pe(e.hold_until)}${r}</span>`}return"\u2014"}function FE(e,t,r,n,o="Task ledger"){return io(["Task / hierarchy","Project","Recorded status","Blocked / hold","Recorded owner","Updated","Presentation"],e.map(s=>{let i=[],a=s.parent_id===null?void 0:t.get(s.parent_id),c=new Set([s.id]);for(;a&&!c.has(a.id);)c.add(a.id),i.unshift(a),a=a.parent_id===null?void 0:t.get(a.parent_id);let l=i.map(u=>co(u,r)).join(" / ");return[`${l?`${l}<br>`:""}${co(s,r)}${s.context?" <strong>(ancestor context)</strong>":""}<br>${v(s.kind)}`,v(s.project),v(s.status),WE(s),BE(s,n,r),pe(s.updated_at),s.kind==="epic"?"Not applicable":s.delivered_ts?`First presented ${pe(s.delivered_ts)}`:"Not recorded"]}),o)}function qE(e,t,r){let n=["q","project","status"].map(i=>`<label>${{q:"Search",project:"Project",status:"Exact recorded status"}[i]}<input name="${i}" value="${v(e[i]??"")}" maxlength="256"></label>`).join(""),o=(i,a,c)=>`<label>${a}<select name="${i}">${c.map(([l,u])=>`<option value="${v(l)}"${e[i]===l?" selected":""}>${v(u)}</option>`).join("")}</select></label>`,s=[["",`All teams (${t.length} own work in this scope)`],...t.map(i=>[i,i])];return`<form method="get" action="${v(r)}/tasks">${n}${o("kind","Kind",[["","All kinds"],["epic","Epic"],["task","Task"],["subtask","Subtask"]])}${o("team","Owning team",s)}${o("sort","Sort",[["id","ID"],["updated","Updated"]])}<label>Attention only<input type="checkbox" name="attention" value="1"${e.attention?" checked":""}></label><button>Filter tasks</button> ${Ne(`${r}/tasks`,"Clear filters")}</form>`}function jE(e){return`<p>${e.total} entities in this scope: ${e.by_kind.epic??0} epics, ${e.by_kind.task??0} tasks, ${e.by_kind.subtask??0} subtasks.</p>`}function GE(e,t,r=""){let n=r.replace(/\/$/,""),o=(i,a,c,l=200)=>Me(i,$e(a,c,n,{"data-page":"tasks"}),l),s=(i,a)=>{let c=a instanceof C?a.code==="NOT_FOUND"?404:a.code==="DB_BUSY"?503:a.code==="STORAGE_ERROR"?500:a.code==="CONFLICT"?409:400:500;return o(i,"Tasks unavailable",`<p>${v(a instanceof Error?a.message:String(a))}</p>${Ne(`${n}/tasks`,"Task ledger")}`,c)};e.get("/tasks",i=>{try{let a=uM(i.req.url),c;if(a.team){let p=t.teams.find(h=>h.name===a.team&&B(h));if(!p||!B(p))throw new C("INVALID_ARGUMENT","Unknown local owning team");c=Q(p)}let l=Nr(t.db.db,{...a.project?{project:a.project}:{},...a.kind?{kind:a.kind}:{},...a.status?{status:a.status}:{},limit:Le}),u=Br(t.teams),d=[...new Set(l.rows.map(p=>p.owner_team_path).filter(p=>p!==null).map(p=>u.get(p)).filter(p=>p!==void 0))].sort();if(l.meta.next_cursor!==null)return o(i,"Tasks",'<p class="warning">This scope exceeds 10,000 entities. Choose a project, kind, or status to narrow it; an incomplete board is not shown.</p>'+qE(a,d,n),503);let m=dM(l.rows,a,p=>Ir(t.db.db,p),c),f=`<nav aria-label="Task pages">${m.pageNumber>1?Ne(UE(`${n}/tasks`,{...a,page:String(m.pageNumber-1)}),"Previous page"):""} ${m.more?Ne(UE(`${n}/tasks`,{...a,page:String(m.pageNumber+1)}),"Next page"):""}</nav>`;return o(i,"Tasks",'<p data-testid="page-intro">Epics group tasks, and tasks can contain subtasks; follow a title to read its details and children. Status and owner are recorded values; Updated means content activity; Attention means blocked, error, on-hold, or rate-limited; First presentation means when the item was first shown to an agent to work on, not completion. Blocked / hold is separate from the recorded status text: it shows when a task is structurally waiting on a specific team or operator, or deliberately parked until a date, even while its own status reads as ordinary active work.</p>'+jE({total:l.rows.length,by_kind:l.rows.reduce((p,h)=>(p[h.kind]=(p[h.kind]??0)+1,p),{})})+qE(a,d,n)+`<p>${m.total} matching entities. Page ${m.pageNumber}, up to 50 matches plus labeled ancestor context; presentation does not mean completion.</p>`+f+FE(m.rows,m.byId,n,u)+f)}catch(a){return s(i,a)}}),e.get("/tasks/:id",i=>{try{let a=HE(i.req.param("id")),c=Ir(t.db.db,a),l=Lr(t.db.db,a),u=[],d=c.parent_id,m=new Set([a]);for(;d!==null&&!m.has(d);){m.add(d);let T=Ir(t.db.db,d);u.unshift(T),d=T.parent_id}let f=Br(t.teams),p=new Map([...u,c,...l.children].map(T=>[T.id,T])),h=T=>T.length?`<ul>${T.map(R=>`<li>${co(R,n)} \u2014 ${v(R.status)}</li>`).join("")}</ul>`:"<p>None recorded.</p>",g=`<nav aria-label="Breadcrumb">${Ne(`${n}/tasks`,"Task ledger")} / ${u.map(T=>Ne(`${n}/tasks/${T.id}`,`#${T.id} ${T.title} (status: ${T.status})`)).join(" / ")}${u.length?" / ":""}<span aria-current="page">#${c.id} ${v(c.title)}</span></nav>`,_=u.at(-1),E=u.find(T=>T.kind==="epic"),S=`<p data-testid="work-context">${c.kind==="epic"?"This is an epic with no parent.":c.kind==="task"?E?`This is a task in epic ${co(E,n)}.`:"This is a task with no parent epic.":`This is a subtask${_?` of task ${co(_,n)}`:""}${E?`, part of epic ${co(E,n)}.`:"; no parent epic is recorded."}`}</p><p data-testid="page-intro">This page describes one work item and its recorded status and owner. Follow the breadcrumb to its parent or epic, or a child title to drill down; Updated records content activity, not completion.</p>`+g+`<p>Kind: ${v(c.kind)}; project: ${v(c.project)}; recorded status: <strong>${v(c.status)}</strong>.</p><p>Recorded owner: ${BE(c,f,n)}.</p><p>Blocked / hold: ${WE(c)}</p>`+["description","requirements","acceptance_criteria"].map(T=>`<h2>${{description:"Description",requirements:"Requirements",acceptance_criteria:"Acceptance criteria"}[T]}</h2><pre>${v(c[T]||"Not supplied")}</pre>`).join("")+jE(Cr(t.db.db,{id:a}))+"<h2>Children</h2>"+FE(l.children,p,n,f,"Immediate children")+"<h2>Depends on</h2>"+h(c.dependencies.outgoing)+"<h2>Required by</h2>"+h(c.dependencies.incoming)+`<h2>Times</h2><p>Created ${pe(c.created_at)}; updated ${pe(c.updated_at)}.</p><p>First presentation: ${c.kind==="epic"?"Not applicable":c.delivered_ts?pe(c.delivered_ts):"Not recorded"}. Presentation does not mean completion.</p>`;return o(i,`Task #${c.id}: ${c.title}`,S)}catch(a){return s(i,a)}})}import{basename as mM}from"node:path";var VE=50,JE='<p data-testid="page-intro">A cron job is work scheduled to run automatically; this page reviews its saved configuration and recorded results. An unresolved escalated run is waiting for a person to help, while execution uncertain means the process has not been confirmed stopped.</p>',fM={ok:"OK (last-fire bookkeeping)",error:"Error",skipped_overlap:"Skipped: earlier execution still guarded",skipped_stale:"Skipped: scheduled window too old",reconciled:"Process gone; outcome unknown",blocked_escalation:"Skipped: unresolved escalation at last check"},at=e=>e===null?"Not recorded":pe(e),Ze=e=>e===null?"Not configured":v(e),zE=e=>e.last_fire_status===null?"Not recorded":`${v(fM[e.last_fire_status]??e.last_fire_status)} <small>(${v(e.last_fire_status)})</small>`;function KE(e){let t=e.req.queries("after");if(t===void 0)return 0;let r=t[0]??"";if(t.length!==1||!/^(0|[1-9]\d*)$/.test(r)||!Number.isSafeInteger(Number(r)))throw new P("INVALID_ARGUMENT","after must be a nonnegative integer");return Number(r)}function YE(e,t,r){if(e.session_teamfile===null||e.session_alias===null)return"Not configured";let n=`${e.session_teamfile}:${e.session_alias}`,o=`${mM(e.session_teamfile)}:${e.session_alias}`,s=t.get(e.session_teamfile);return s?`<a href="${v(`${r}/sessions/${encodeURIComponent(s)}/${encodeURIComponent(e.session_alias)}`)}" title="${v(n)}">${v(o)}</a>`:`<span title="${v(n)}">${v(o)}</span> (not in the current local registry)`}function QE(e,t){let r=[];return(e.last_fire_status==="error"||e.last_fire_error)&&r.push("Recorded fire error"),e.last_fire_status==="blocked_escalation"&&r.push("Last check blocked by escalation"),e.last_fire_status==="reconciled"&&r.push("Previous execution outcome unknown"),t?.status==="escalated"&&t.escalation_resolved_at===null&&r.push(`Run #${t.id}: escalated \u2014 waiting for a person`),t?.execution_state==="uncertain"&&r.push(`Run #${t.id}: execution uncertain`),t?.status==="failed"&&r.push(`Run #${t.id}: failed; execution still guarded`),r}function cd(e){return`<dl>${e.map(([t,r])=>`<dt>${v(t)}</dt><dd>${r}</dd>`).join("")}</dl>`}function pM(e){if(e===null)return"<p>No artifacts recorded.</p>";try{let t=JSON.parse(e);if(Array.isArray(t)&&t.every(r=>typeof r=="string"))return t.length?`<ul>${t.map(r=>`<li>${v(r)}</li>`).join("")}</ul>`:"<p>No artifacts recorded.</p>"}catch{}return`<pre>${v(e)}</pre>`}function hM(e){let t=e.status==="escalated",r=t&&e.escalation_resolved_at===null,n=e.status==="failed"||r||e.execution_state==="uncertain",o=`${e.status}${t?r?" \u2014 waiting for a person":" \u2014 escalation resolved":""}`,s=t||e.escalation_reason!==null||e.escalation_resolved_at!==null?"<h4>Escalation</h4>"+cd([["Reason",Ze(e.escalation_reason)],["Requested action",Ze(e.escalation_action)],["Owner",Ze(e.escalation_owner)],["Resolved at",at(e.escalation_resolved_at)],["Resolution",Ze(e.escalation_resolution)],["Resolved by",Ze(e.escalation_resolution_actor)],["Resolution note",Ze(e.escalation_resolution_note)]]):"";return`<article id="run-${e.id}"${n?' class="warning"':""}><h3>Run #${e.id}: ${v(o)}</h3>`+cd([["Execution state",v(e.execution_state)],["Trigger",v(e.trigger_kind)],["Created",at(e.created_at)],["Started",at(e.started_at)],["Finished",at(e.finished_at)],["Result reported",at(e.reported_at)],["Last updated",at(e.updated_at)],["Execution reference",Ze(e.execution_identity)],["Process ID",Ze(e.pid)],["Execution uncertainty reason",Ze(e.execution_uncertain_reason)],["Execution confirmed gone",at(e.execution_gone_at)],["Confirmation note",Ze(e.execution_confirmation_note)]])+`<h4>Summary</h4><pre>${v(e.summary??"No summary recorded.")}</pre><h4>Artifacts (recorded paths or references)</h4>`+pM(e.artifacts)+s+"</article>"}function XE(e,t,r=""){let n=r.replace(/\/$/,""),o=(a,c,l,u=200)=>Me(a,$e(c,l,n),u),s=(a,c)=>{let l=c instanceof P?c.code==="NOT_FOUND"?404:c.code==="DB_BUSY"?503:c.code==="INVALID_ARGUMENT"?400:500:500;return o(a,"Cron review unavailable",`<p>${v(c instanceof Error?c.message:String(c))}</p>${Ne(`${n}/cron`,"Cron jobs")}`,l)},i=(a,c,l)=>`<nav aria-label="Cron pages">${c?Ne(a,"First page"):""} ${l!==null?Ne(`${a}?after=${l}`,"Next page"):""}</nav>`;e.get("/cron",a=>{try{let c=KE(a),l=Ki(t.db.db,{limit:VE,after:c}),u=Br(t.teams),d=l.rows.map(f=>({job:f,flags:QE(f,It(t.db.db,f.id))})),m=(f,p)=>io(["Job","Schedule / timezone","Action kind","Enabled","Last fire status","Last fired","Scheduler last looked at","Last fire error","Session"],f.map(({job:h,flags:g})=>[Ne(`${n}/cron/${h.id}`,`#${h.id} ${h.title}`)+(g.length?`<p class="warning"><strong>${g.map(v).join("<br>")}</strong></p>`:""),`<code>${v(h.schedule_expr)}</code><br>${v(h.timezone??"Host-local timezone")}`,v(h.action_kind),h.enabled?"Enabled":"Disabled",zE(h),at(h.last_fired_ts),at(h.last_checked_ts),h.last_fire_error===null?"None recorded":`<pre>${v(h.last_fire_error)}</pre>`,YE(h,u,n)]),p);return o(a,"Cron jobs",JE+"<p>Saved jobs, up to 50 per page in ID order. Times below are stored scheduler records; OK is not proof of successful AI work. A retained error can predate a later skipped check.</p><h2>Failures and review flags</h2>"+m(d.filter(f=>f.flags.length>0),"Jobs with review flags on this page")+"<h2>Other jobs</h2>"+m(d.filter(f=>f.flags.length===0),"Other jobs on this page")+i(`${n}/cron`,c,l.meta.next_cursor))}catch(c){return s(a,c)}}),e.get("/cron/:id",a=>{try{let c=a.req.param("id");if(!/^[1-9]\d*$/.test(c)||!Number.isSafeInteger(Number(c)))throw new P("INVALID_ARGUMENT","Invalid positive job ID");let l=KE(a),u=Ce(t.db.db,Number(c)),d=Wi(t.db.db,{jobId:u.id,limit:VE,after:l}),m=It(t.db.db,u.id),f=QE(u,m),p=cd([["Title",v(u.title)],["Schedule expression",`<code>${v(u.schedule_expr)}</code>`],["Timezone",v(u.timezone??"Host-local timezone")],["Action kind",v(u.action_kind)],["Enabled",u.enabled?"Enabled":"Disabled"],["Provider",Ze(u.provider)],["Model",Ze(u.model)],["Working directory",Ze(u.working_directory)],["Escalation owner",Ze(u.escalation_owner)],["Session",YE(u,Br(t.teams),n)],["Session teamfile",Ze(u.session_teamfile)],["Session alias",Ze(u.session_alias)],["Session seeded at",at(u.session_seeded_at)],["Session generation",v(u.session_generation)],["Scheduler last looked at",at(u.last_checked_ts)],["Last fired",at(u.last_fired_ts)],["Last fire status",zE(u)],["Last fire error",u.last_fire_error===null?"None recorded":`<pre>${v(u.last_fire_error)}</pre>`],["Recorded execution since",at(u.running_since_ts)],["Recorded systemd unit",Ze(u.running_systemd_unit)],["Created",at(u.created_at)],["Updated",at(u.updated_at)],["Revision",v(u.revision)]]),h=m?`<p>${Ne(`${n}/cron/${u.id}?after=${m.id-1}#run-${m.id}`,`Inspect guarded run #${m.id}`)} \u2014 ${v(m.status)}, execution ${v(m.execution_state)}.</p>`:"",g=l?"<p>No more run records after this cursor.</p>":"<p>No run history recorded. Command or script jobs may have last-fire records without run history; an empty history is not itself an error.</p>";return o(a,`Cron job #${u.id}: ${u.title}`,JE+`<p>${Ne(`${n}/cron`,"All cron jobs")}</p>`+(f.length?`<p class="warning"><strong>${f.map(v).join("<br>")}</strong></p>`:"")+h+"<h2>Configuration</h2>"+p+`<h3>Action payload (command, script, prompt, or enqueue data)</h3><pre>${v(u.action_payload)}</pre><h2>Run history</h2><p>Up to 50 recorded runs, oldest ID first. Outcome and process state are separate: active is recorded as active, uncertain is not confirmed stopped, and gone is confirmed stopped.</p>`+(d.rows.length?d.rows.map(hM).join(""):g)+i(`${n}/cron/${u.id}`,l,d.next_cursor))}catch(c){return s(a,c)}})}function gM(e,t){return t===null&&e.retracted_ts===null&&(e.status==="pending"||e.status==="escalating"||e.status==="sent"||e.status==="retrieved")}var eb=64*1024;async function _M(e){if(!e.req.header("content-type")?.toLowerCase().startsWith("application/x-www-form-urlencoded"))throw new C("INVALID_ARGUMENT","Expected a browser form.");let t=e.req.raw.body?.getReader();if(!t)throw new C("INVALID_ARGUMENT","Missing form.");let r=0,n=[];for(;;){let{done:i,value:a}=await t.read();if(i)break;if(r+=a.byteLength,r>eb)throw await t.cancel(),new C("INVALID_ARGUMENT","Form exceeds the size limit.");n.push(a)}let s=new URLSearchParams(Buffer.concat(n).toString("utf8")).getAll("answer");if(s.length!==1)throw new C("INVALID_ARGUMENT","Missing or duplicate answer field.");return s[0]}function tb(e,t){let r=[t.from_id,t.to_id,t.escalation_only,t.to_alias],o=e.prepare("SELECT MIN(id) AS id FROM queue WHERE from_id = ? AND to_id = ? AND escalation_only = ? AND to_alias IS ? AND id > ? AND status != 'merged'").get(...r,t.id).id??Number.MAX_SAFE_INTEGER;return e.prepare("SELECT * FROM queue WHERE from_id = ? AND to_id = ? AND escalation_only = ? AND to_alias IS ? AND status = 'merged' AND id > ? AND id < ?").all(...r,t.id,o)}function rb(e,t){let r=[];t.retracted_ts!==null&&t.retracted_reason&&r.push(t.retracted_reason);let n=tb(e,t);for(let o of n)o.retracted_ts!==null&&o.retracted_reason&&r.push(o.retracted_reason);return r}function ld(e,t=Date.now()){return cs(e,t).map(n=>{let o=n.row,s=pn(e,o),i=as(e,o),a=n.ageMs>=ds||s>=2&&o.sent_ts===null,c=rb(e,o);return{row:o,constituentCount:s,retractedCount:i,urgent:a,retractedReasons:c}})}function nb(e){return e===1?"1 of 1":`${e} merged into this one`}function wM(e){return e==="merged"||e==="informational"||e==="retracted"}function yM(e){return e.lifecycle==="queued"?"queued":e.lifecycle==="processing"?"processing":wM(e.lifecycleBasis)?"muted":"replied"}function EM(e){return e.lifecycle==="queued"?"Queued":e.lifecycle==="processing"?"Processing":e.lifecycleBasis==="merged"?"Combined":e.lifecycleBasis==="informational"?"Informational":e.lifecycleBasis==="retracted"?"Retracted":"Replied"}function ob(e){return`<span class="status-chip status-${yM(e)}" title="${v(ud(e))}">${v(EM(e))}</span>`}function ud(e){return e.lifecycle==="queued"?"Queued \u2014 waiting for handling":e.lifecycle==="processing"?e.lifecycleBasis==="confirmed"?"Processing \u2014 picked up by inbox":"Processing \u2014 delivery attempted; read not confirmed":e.lifecycle==="finished"?e.lifecycleBasis==="retracted"?"Finished \u2014 retracted":e.lifecycleBasis==="merged"?"Finished \u2014 combined with another prompt":e.lifecycleBasis==="informational"?"Finished \u2014 informational, no answer expected":"Finished \u2014 answer recorded":`${e.lifecycle} (${e.lifecycleBasis})`}function bM(e){return`<dl>${e.map(([t,r])=>`<dt>${v(t)}</dt><dd>${r}</dd>`).join("")}</dl>`}function TM(e){return e.length===0?"<p>No standing decisions recorded.</p>":e.map(t=>{let r=t.would_change_it?`<p><strong>Would change this:</strong> ${v(t.would_change_it)}</p>`:"<p><strong>Would change this:</strong> Not recorded.</p>",n=t.affects.length>0?t.affects.map(v).join(", "):"Not recorded";return`<article aria-label="Decision #${t.id}"><h3>${v(t.subject)}</h3><p>${v(t.decision)}</p>${r}<details><summary>Reasoning</summary><p>${v(t.reasoning)}</p></details><p>Decided by ${v(t.decided_by)}, ${pe(t.decided_at)}. Affects: ${n}.</p></article>`}).join("")}function SM(e){return e.length===0?"<p>Nothing blocking math right now.</p>":e.map(t=>`<article aria-label="Blocked #${t.id}"><h3>!!! ${v(t.title)}</h3><p>Category: ${v(t.category)}.</p>${t.detail?`<p>${v(t.detail)}</p>`:""}<p>Raised by ${v(t.raised_by)}, ${pe(t.raised_at)}.</p></article>`).join("")}function vM(e,t){return e.length===0?"<p>No open judgment calls for the operator.</p>":e.map(r=>{let n=r.downstream?`<p><strong>Downstream:</strong> ${v(r.downstream)}</p>`:"<p><strong>Downstream:</strong> Not recorded.</p>";return`<article aria-label="Ask #${r.id}"><h3>${v(r.subject)}</h3><p>${v(r.reason)}</p>${n}<p>Status: Open. Raised by ${v(r.raised_by)}, ${pe(r.raised_at)}.</p><p><a href="${v(t)}/comm/math?ask=${r.id}#compose">Discuss this with math</a></p></article>`}).join("")}function ZE(e,t,r,n){if(e.length===0)return`<p>No ${t.toLowerCase()}.</p>`;let o=["Prompt","From","Age","Constituents","Retractions","Lifecycle"],s=e.map(i=>{let a=i.row,c=De(n,a.id),l=xt(a,c),u=`<a href="${v(r)}/operator/${a.id}">#${a.id}</a>`,d=v(a.from_id),m=pe(a.created_ts),f=nb(i.constituentCount),p=i.retractedCount>0?`${i.retractedCount} retracted${i.retractedReasons.length>0?`: ${i.retractedReasons.map(g=>`\u201C${v(g)}\u201D`).join("; ")}`:""}`:"\u2014",h=`${ob(l)} \xB7 ${v(ud(l))}`;return[u,d,m,f,p,h]});return io(o,s,t)}function sb(e,t,r=""){let n=r.replace(/\/$/,"");e.get("/operator",o=>{try{let s=ld(t.db.db,Date.now()),i=s.filter(g=>g.urgent),a=s.filter(g=>!g.urgent),c='<p data-testid="page-intro">What needs the operator, what math has already decided for them to review, and a way to reach math directly. Blocked means math is technically incapable of proceeding (re-auth, billing, account identity) -- rare and urgent. Escalations are requests a team sent that genuinely need a decision, shown whether or not anyone is currently monitoring them; urgent means waiting over four hours, or never delivered despite repeated sends. Constituents counts how many separate escalations were folded into one message; Retractions counts how many of those the sender has since withdrawn, with their stated reason. Asks are judgment calls only the operator can make, routine, not urgent -- problem statement, then what it affects downstream, then who raised it. Decisions are rulings math has already made, for review, not approval.</p>',l=`<section class="warning" aria-label="Urgent escalations"><h2>Urgent escalations</h2>${ZE(i,"Urgent escalations",n,t.db.db)}</section>`,u=`<section aria-label="Routine escalations"><h2>Routine escalations</h2>${ZE(a,"Routine escalations",n,t.db.db)}</section>`,d=`<section aria-label="Send a message"><h2>Send a message</h2><p>Start a new request to math. This reuses the same queue and composer as <a href="${v(n)}/comm/math">the Math inbox</a> -- one write path, not a second one.</p><p><a href="${v(n)}/comm/math#compose">Write a message to math</a></p></section>`,m,f,p;try{let g=Na(),_,E,y;try{_=DE(g),E=CE(g),y=LE(g)}finally{g.close()}m=`<section class="warning" aria-label="Blocked"><h2>Blocked</h2>${SM(_)}</section>`,f=`<section aria-label="Asks"><h2>Asks</h2>${vM(E,n)}</section>`,p=`<section aria-label="Decisions"><h2>Decisions</h2><p>Rulings math has already made, in force now (superseded and reversed decisions are excluded). Nothing here waits on you -- read, and ping math if you disagree.</p>${TM(y)}</section>`}catch(g){let _=`<p class="warning">lmteam data unavailable: ${v(g instanceof Error?g.message:String(g))}</p>`;m=`<section class="warning" aria-label="Blocked"><h2>Blocked</h2>${_}</section>`,f=`<section aria-label="Asks"><h2>Asks</h2>${_}</section>`,p=`<section aria-label="Decisions"><h2>Decisions</h2>${_}</section>`}let h=`${c}${m}${l}${f}${d}${u}${p}`;return Me(o,$e("Operator inbox",h,n,{"data-page":"operator"},[],!0))}catch(s){return Me(o,$e("Operator inbox unavailable",`<p>${v(s instanceof Error?s.message:String(s))}</p>`,n,{},[],!0),500)}}),e.get("/operator/:id",o=>{let s=o.req.param("id"),i=Number(s);if(!s||!/^[1-9]\d*$/.test(s)||!Number.isSafeInteger(i))return Me(o,$e("Invalid escalation ID",`<p>Invalid escalation ID.</p><p><a href="${v(n)}/operator">Operator inbox</a></p>`,n,{},[],!0),400);try{let a=kr(t.db.db,i);if(!a||a.to_id!=="operator")return Me(o,$e("Not found",`<p>No operator escalation at this address.</p><p><a href="${v(n)}/operator">Operator inbox</a></p>`,n,{},[],!0),404);let c=jr(t,i),l=De(t.db.db,i),u=xt(a,l),d=pn(t.db.db,a),m=as(t.db.db,a),f=rb(t.db.db,a),p=[["From",v(a.from_id)],["To",v(a.to_id)],["Queued",pe(a.created_ts)],["Lifecycle",`${ob(u)} \xB7 ${v(ud(u))}`],["Constituents",v(nb(d))],["Delivery attempted",a.sent_ts?pe(a.sent_ts):"not recorded"],["Picked up",a.retrieved_ts?pe(a.retrieved_ts):"not recorded"],["Subject",a.subject_id?v(a.subject_id):"none"]];m>0&&p.push(["Retractions",`${m} retracted${f.length>0?`: ${f.map(S=>`\u201C${v(S)}\u201D`).join("; ")}`:""}`]),a.retracted_ts!==null&&(p.push(["Retracted at",pe(a.retracted_ts)]),p.push(["Retraction reason",v(a.retracted_reason??"(none)")]));let h="";c?.status==="available"?h=`<pre>${v(c.text)}</pre><p>${c.truncated?`Preview truncated (${c.byteLength} bytes).`:`Full content (${c.byteLength} bytes).`}</p>`:h=`<p>Prompt preview unavailable (${v(c?.status??"missing")}).</p>`;let g="";l?g=`<section><h2>Answer</h2><p>Recorded ${pe(l.answered_at)}</p><pre>${v(l.answer_text)}</pre></section>`:gM(a,l)&&(g=`<section aria-label="Answer"><h2>Answer</h2><form method="post" action="${v(n)}/operator/${i}/answer"><label for="answer">Answer text</label><textarea id="answer" name="answer" rows="8" maxlength="${eb}" required></textarea><button>Send answer</button></form></section>`);let _=tb(t.db.db,a),E="";_.length>0&&(E=`<section><h3>Merged constituents (${_.length})</h3><p>Additional escalations folded into this message:</p><ul>${_.map(S=>`<li><a href="${v(n)}/operator/${S.id}">#${S.id}</a> from ${v(S.from_id)} (queued ${pe(S.created_ts)})${S.retracted_ts?` \u2014 <strong>Retracted</strong>: \u201C${v(S.retracted_reason)}\u201D`:""}</li>`).join("")}</ul></section>`);let y=`<p><a href="${v(n)}/operator">Operator inbox</a></p>
|
|
564
564
|
<p data-testid="page-intro">One escalation addressed to the operator. Constituents counts how many separate escalations were folded into this message; Retractions, if shown, counts how many of those the sender has since withdrawn, with their stated reason.</p>
|
|
565
|
-
<section aria-label="Escalation metadata"><h2>Metadata</h2>${
|
|
565
|
+
<section aria-label="Escalation metadata"><h2>Metadata</h2>${bM(p)}</section>
|
|
566
566
|
<article aria-label="Prompt content"><h2>Prompt content</h2>${h}</article>
|
|
567
567
|
${g}
|
|
568
|
-
${E}`;return Me(o,$e(`Operator escalation #${i}`,y,n,{"data-page":"operator-detail"},[],!0))}catch(a){return Me(o,$e("Operator escalation unavailable",`<p>${v(a instanceof Error?a.message:String(a))}</p>`,n,{},[],!0),500)}}),e.post("/operator/:id/answer",async o=>{let s=o.req.param("id"),i=Number(s);if(!s||!/^[1-9]\d*$/.test(s)||!Number.isSafeInteger(i))return Me(o,$e("Invalid escalation ID",`<p>Invalid escalation ID.</p><p><a href="${v(n)}/operator">Operator inbox</a></p>`,n,{},[],!0),400);try{let a=await
|
|
568
|
+
${E}`;return Me(o,$e(`Operator escalation #${i}`,y,n,{"data-page":"operator-detail"},[],!0))}catch(a){return Me(o,$e("Operator escalation unavailable",`<p>${v(a instanceof Error?a.message:String(a))}</p>`,n,{},[],!0),500)}}),e.post("/operator/:id/answer",async o=>{let s=o.req.param("id"),i=Number(s);if(!s||!/^[1-9]\d*$/.test(s)||!Number.isSafeInteger(i))return Me(o,$e("Invalid escalation ID",`<p>Invalid escalation ID.</p><p><a href="${v(n)}/operator">Operator inbox</a></p>`,n,{},[],!0),400);try{let a=await _M(o);return gn(t.db.db,i,"operator",a),o.redirect(`${n}/operator/${i}`,303)}catch(a){let c=a instanceof C?a.code==="NOT_FOUND"?404:a.code==="CONFLICT"?409:400:500;return Me(o,$e("Answer not recorded",`<p>${v(a instanceof Error?a.message:String(a))}</p><p><a href="${v(n)}/operator/${i}">Back to escalation #${i}</a></p>`,n,{},[],!0),c)}})}function ib(e,t,r=""){let n=r.replace(/\/$/,"");e.get("/",o=>{try{let s=new Date().toISOString(),i=Cr(t.db.db),a=Object.entries(i.by_status).reduce((_,[E,y])=>_+(ad(E)?y:0),0),c=ld(t.db.db,Date.now()).filter(_=>_.urgent),l=c.length>0?`<section class="warning" role="alert" data-testid="operator-urgent-alert"><p><strong>Urgent operator attention required:</strong> ${Ne(`${n}/operator`,`${c.length} urgent escalation${c.length===1?"":"s"} awaiting operator answer`)}.</p></section>`:"",u=is(),d=["epic","task","subtask"].map(_=>Ne(`${n}/tasks?kind=${_}`,`${i.by_kind[_]??0} ${_}s`)).join(", "),m=u.report===null?"<p>Activity has not yet been observed; running, dead, and idle counts are unknown.</p>":`<p>As of ${u.observedAt?pe(u.observedAt):"an unknown time"}, from the last successful scheduled observation: ${u.report.running.length} running, ${u.report.dead.length} dead, ${u.report.idle.length} idle invocation records.</p>`,f=u.lastError?`<p class="warning">Observer failed${u.lastErrorAt?` ${pe(u.lastErrorAt)}`:""}: ${v(u.lastError)}. ${u.report?"The counts retain the last successful observation.":"No successful observation is available."}</p>`:"",p=t.teams.filter(B),h="";if(u.report!==null){let _=u.report,E=[..._.running,..._.dead,..._.idle],y=p.filter(S=>!E.some(T=>kn(S,T.target)));if(y.length>0){let S=y.map(T=>`<li>${v(T.name)}: ${v(ls(la(t.db.db,T,_,Date.now(),{allLocalTeams:p})))}</li>`).join("");h=`<p>${y.length} local team${y.length===1?"":"s"} in no running, dead, or idle record above \u2014 absent, not necessarily stalled; each line names the specific reason nobody has looked recently, when one is known:</p><ul>${S}</ul>`}}let g=`${l}<p data-testid="page-intro">Work is organized as epics \u2192 tasks \u2192 subtasks in the ${Ne(`${n}/tasks`,"task board")}; actors are sessions that receive prompts and produce answers, visible through ${Ne(`${n}/running`,"activity and session links")} and the ${Ne(`${n}/comm/math`,"Math inbox")}. Recorded ownership connects work to an actor, while a recorded answer does not by itself mean the work is complete.</p>
|
|
569
569
|
<section><h2>Work</h2><p>Task-ledger counts read when this page loaded ${pe(s)}: ${i.total} work items \u2014 ${d}.</p>
|
|
570
570
|
<p>${Ne(`${n}/tasks?attention=1`,`${a} work items needing attention`)} across all kinds: recorded statuses blocked, error, on-hold, or rate-limited.</p></section>
|
|
571
571
|
<section><h2>Actors and activity</h2><p>${t.teams.length} teams in the current registry at page load. Teams group actors; the counts below describe invocation records, not a team or session roster.</p>
|
|
572
572
|
${m}${f}<p>${Ne(`${n}/running`,"Open Running / Dead / Idle")}. Running means work in flight, Dead means its process stopped, and Idle means a finished invocation.</p>
|
|
573
|
-
${h}<p>This page loaded ${pe(s)}; the activity snapshot is separate and may be older. Refreshing this page does not trigger a new activity scan.</p></section>`;return Me(o,$e("Overview",g,n,{},[],!0))}catch(s){return Me(o,$e("Overview unavailable",`<p>${v(s instanceof Error?s.message:String(s))}</p>`,n,{},[],!0),500)}})}function
|
|
573
|
+
${h}<p>This page loaded ${pe(s)}; the activity snapshot is separate and may be older. Refreshing this page does not trigger a new activity scan.</p></section>`;return Me(o,$e("Overview",g,n,{},[],!0))}catch(s){return Me(o,$e("Overview unavailable",`<p>${v(s instanceof Error?s.message:String(s))}</p>`,n,{},[],!0),500)}})}function AM(e,t,r){return`${r.replace(/\/$/,"")}/api/session/${encodeURIComponent(e)}/${encodeURIComponent(t)}?limit=20`}function ab(e,t,r,n={}){let o=r.replace(/\/$/,"");if(o&&(!o.startsWith("/")||o.startsWith("//")||/[?#\\]/.test(o)))throw new Error("Invalid mount path");let s=n.commPageEnabled===!0?`<a href="${v(o)}/comm/math">Math inbox \u2014 review and send</a>`:"",i=n.commEnabled===!0&&e==="math"&&t==="Lead";return`<section id="session-detail" data-canonical-teamfile="${v(n.canonicalTeamfile??"")}" data-comm-page-enabled="${n.commPageEnabled===!0}" data-comm-enabled="${i}" data-team="${v(e)}" data-alias="${v(t)}" data-mount="${v(o)}" data-history="${v(AM(e,t,o))}">
|
|
574
574
|
<p>Session: <strong>${v(e)}:${v(t)}</strong>. ${t==="Lead"?"Role: lead.":"Role not recorded."} lmauto hosts this page; the session\u2019s team is ${v(e)}.</p>
|
|
575
575
|
<p id="session-purpose">Team purpose is not loaded in this HTML view; JavaScript loads it automatically.</p>
|
|
576
576
|
<p><a href="${v(o)}/running">Observed activity</a> \xB7 <a href="${v(o)}/tasks">Work items</a></p>
|
|
@@ -588,48 +588,48 @@ ${s?`<p>This timeline shows incoming and outgoing exchanges. ${s} opens requests
|
|
|
588
588
|
<script>(function () {
|
|
589
589
|
// tsx preserves names using an injected helper; keep serialized source self-contained.
|
|
590
590
|
function __name(value) { return value; }
|
|
591
|
-
return (${
|
|
592
|
-
})();</script>`}function
|
|
593
|
-
${z.answer.truncated?`Truncated response; ${z.answer.totalBytes} total bytes. No continuation endpoint available.`:""}`):l("comm-response",z.lifecycleBasis==="merged"?"No separate answer: prompt merged into another prompt.":z.lifecycleBasis==="informational"?"No answer expected: this was an informational prompt.":z.lifecycleBasis==="retracted"?"No answer expected: this prompt was retracted.":"Outcome unknown: no reply recorded. This does not establish failure or unread work."),z.lifecycle!=="finished"&&++_<60?p=setTimeout(()=>void k(),5e3):z.lifecycle!=="finished"&&l("comm-state",`Queue #${M}: observation stalled \u2014 automatic checks paused after 60 reads; last state ${N(z)}. Check again manually. This does not establish execution failure.`)}catch(z){j===g&&S(
|
|
594
|
-
[Prompt preview truncated]`:""}`:`Prompt preview ${xe.status}; content unavailable.`)}catch(te){
|
|
595
|
-
[Reply excerpt; open the full exchange for available text.]`:""),_t=!0}catch(
|
|
596
|
-
${re.prompt}`),c("comm-review").hidden=!1,
|
|
597
|
-
`)}),D=await Pn(t.db.db,t.teams.filter(B),b,N,r,void 0,{readOnly:!0}),W=Gw(t.db.db,t.teams.filter(ee=>!B(ee)),n);return w.json({stalled:D,remoteStalled:W})});function f(w){let b=t.teams.find(D=>D.name===w);if(!b)return{error:`unknown team "${w}"`,status:404};if(!B(b))return{error:`team "${w}" is a remote team (channel=lmmail) -- not reachable via lctl`,status:400};let N;try{N=Q(b)}catch(D){return{error:D instanceof Error?D.message:String(D),status:500}}return{teamfilePath:N}}function p(w,b,N,D){return d(w,b,{lines:N?Number(N):20,...D?{since:D}:{}})}let h=(e.mountPath??"").replace(/\/$/,"");m.get("/running",w=>{try{let b=is(),N=b.report===null?"<p>Activity has not yet been observed; running, dead, and idle counts are unknown.</p>":`<p>Cached observation taken ${b.observedAt?pe(b.observedAt):"at an unknown time"}. Refreshing this page does not run a new activity scan.</p>`,D=b.lastError?`<p class="warning">Observer failed${b.lastErrorAt?` ${pe(b.lastErrorAt)}`:""}: ${v(b.lastError)}. ${b.report?"Showing the last successful observation.":"No successful observation is available."}</p>`:"",W=b.report===null?"":pE(Ql(b.report),Br(t.teams),h);return Me(w,$e("Running","<p>This page loaded just now; activity data comes from a separate scheduled observation and may be older.</p>"+N+D+W,h))}catch(b){return Me(w,$e("Running unavailable",`<p>${v(b instanceof Error?b.message:String(b))}</p>`,h),502)}}),m.get("/sessions/:team/:alias",w=>{let b=w.req.param("team"),N=w.req.param("alias"),D=`Session: ${b} / ${N}`,W={"data-page":"session","data-team":b,"data-alias":N},ee=f(b);if("error"in ee)return Me(w,$e(D,`<p role="alert">${v(ee.error)}</p>`,h,W),ee.status);let oe=ib(b,N,h,{canonicalTeamfile:ee.teamfilePath,commPageEnabled:!0}),J=Array.from(oe.matchAll(/<script>([\s\S]*?)<\/script>/g),se=>se[1]);return Me(w,$e(D,oe,h,W,J))}),m.get("/api/session/:team/:alias",async w=>{let b=w.req.param("team"),N=w.req.param("alias"),D=f(b);if("error"in D)return w.json({error:D.error},D.status);let{teamfilePath:W}=D,ee=w.req.query("since"),oe=w.req.query("limit");try{let J=await p(W,N,oe,ee);return w.json(J)}catch(J){return w.json({error:J instanceof Error?J.message:String(J)},404)}}),m.get("/api/transcript",async w=>{let b=w.req.query("team");if(!b)return w.json({error:"team is required"},400);let N=t.teams.find(J=>J.name===b);if(!N)return w.json({error:`unknown team "${b}"`},404);if(!B(N))return w.json({error:`team "${b}" is a remote team (channel=lmmail) -- not reachable via lctl`},400);let D=w.req.query("alias")??N.leadAlias,W;try{W=Q(N)}catch(J){return w.json({error:J instanceof Error?J.message:String(J)},500)}let ee=w.req.query("lines"),oe=w.req.query("since");try{let J=await u(W,D,{...ee?{lines:Number(ee)}:{},...oe?{since:oe}:{}});return w.json({team:b,alias:D,...J})}catch(J){return w.json({error:J instanceof Error?J.message:String(J)},502)}}),m.get("/api/queue",w=>{let b=w.req.query("to");return w.json(Bu(t,b))}),m.get("/api/queue/stats",w=>{try{let b=x(w.req.query("to"),"to");return w.json(Vu(t,b))}catch(b){return _(w,b)}});let g=w=>{try{let b=w.req.query(),N={fromId:x(b.from,"from"),toId:x(b.to,"to"),status:A(b.status),since:H(b.since,"since"),until:H(b.until,"until"),after:y(b.after,"after"),limit:y(b.limit,"limit",200)};return w.json(Aa(t,N))}catch(b){return _(w,b)}};m.get("/api/queue/prompts",g),m.get("/api/queue/:id",w=>{let b=Number(w.req.param("id")),N=ro(t,b);return N?w.json({queue:N}):w.json(Ae("queue_not_found",`no queue entry ${b}`),404)}),m.get("/api/queue/:id/state",w=>{let b=Number(w.req.param("id")),N=ws(t,b);return N?w.json(N):w.json(Ae("queue_not_found",`no queue entry ${b}`),404)}),m.post("/api/queue/:id/answer",async w=>{try{let b=T(w.req.param("id"),"id"),N=await w.req.json().catch(()=>({})),D=x(N.from,"from"),W=x(N.text,"text");if(D===void 0||W===void 0)return w.json(Ae("invalid_argument","from and text are required"),400);let ee=gn(t.db.db,b,D,W);return w.json({answer:ee},202)}catch(b){return _(w,b)}}),m.get("/api/queue/:id/preview",w=>{try{let b=T(w.req.param("id"),"id"),N=jr(t,b);return N?w.json(N):w.json(Ae("queue_not_found",`no queue entry ${b}`),404)}catch(b){return _(w,b)}}),m.post("/api/enqueue",async w=>{let b=await w.req.json().catch(()=>({})),N=b.prompt;if(!b.to||!N||!b.from)return w.json({error:"to, prompt, and from are required"},400);if(b.from==="autopilot")return w.json({error:"from: 'autopilot' is reserved for the tool's own automated enqueues"},400);try{let D=e.publish===!0&&b.from==="operator",W=we(t.db.db,t.teams,b.to,N,{from:b.from,...D?{operatorPriority:!0}:{}});return w.json({id:W})}catch(D){return w.json({error:D instanceof Error?D.message:String(D)},400)}}),m.post("/api/comm/send",async w=>{try{let b=await w.req.json().catch(()=>({})),N=x(b.to,"to"),D=x(b.prompt,"prompt"),W=x(b.dedupeKey,"dedupeKey");if(N===void 0||D===void 0||W===void 0)return w.json(Ae("invalid_argument","to, prompt, and dedupeKey are required"),400);let ee=Ra(t.db.db,t.teams,{to:N,prompt:D,dedupeKey:W});return w.json(ee,ee.replayed?200:202)}catch(b){return _(w,b)}}),m.post("/api/queue/deliver",async w=>{let b=await o(),N=xr(t.db.db,{teams:t.teams,report:b,...e.remoteMail?{remoteMail:e.remoteMail}:{}});return w.json({delivered:N})}),m.post("/api/queue/retrieve",async w=>{let b=await w.req.json().catch(()=>({}));if(!b.to)return w.json({error:"to is required"},400);if(b.id!==void 0&&(!Number.isInteger(b.id)||b.id<=0))return w.json({error:"id must be a positive integer"},400);try{let D=ui(t.db.db,b.to,b.id).map(W=>{let ee;try{ee=$M(W.prompt_file,"utf8")}catch{ee="(could not read prompt file)"}return{...W,content:ee}});return w.json({retrieved:D})}catch(N){return _(w,N)}}),m.get("/api/inbox",w=>{let b=w.req.query("to");return b?w.json(Gu(t,b)):w.json(Ae("to_required","to is required"),400)});function _(w,b){if(b instanceof C){let N=b.code==="NOT_FOUND"?404:b.code==="CONFLICT"?409:b.code==="DB_BUSY"?503:b.code==="STORAGE_ERROR"?500:400;return w.json(Ae(b.code,b.message),N)}return w.json(Ae("internal_error",b instanceof Error?b.message:String(b)),500)}let E=new Set(["epic","task","subtask"]);function y(w,b,N){if(w===void 0)return;let D=Number(w);if(!/^[1-9]\d*$/.test(w)||!Number.isSafeInteger(D)||N!==void 0&&D>N)throw new C("INVALID_ARGUMENT",N!==void 0?`${b} must be a positive integer <= ${N}`:`${b} must be a positive integer`);return D}function S(w,b){if(w===void 0)return;let N=Number(w);if(!/^\d+$/.test(w)||!Number.isSafeInteger(N))throw new C("INVALID_ARGUMENT",`${b} must be a nonnegative integer`);return N}function T(w,b){let N=Number(w);if(!/^[1-9]\d*$/.test(w)||!Number.isSafeInteger(N))throw new C("INVALID_ARGUMENT",`${b} must be a positive integer`);return N}function R(w){if(w!==void 0){if(!E.has(w))throw new C("INVALID_ARGUMENT","kind must be 'epic', 'task', or 'subtask'");return w}}function x(w,b){if(w!==void 0){if(w.trim()==="")throw new C("INVALID_ARGUMENT",`${b} must not be blank`);return w}}function I(w,b){if(w!==void 0){if(w==="1"||w==="true")return!0;if(w==="0"||w==="false")return!1;throw new C("INVALID_ARGUMENT",`${b} must be '1'/'true' or '0'/'false'`)}}function A(w){if(w!==void 0){if(!qc.includes(w))throw new C("INVALID_ARGUMENT",`status must be one of: ${qc.join(", ")}`);return w}}function H(w,b){if(w===void 0)return;let N=w.trim()===""?NaN:Date.parse(w);if(Number.isNaN(N))throw new C("INVALID_ARGUMENT",`${b} must be a valid ISO8601 date-time string`);return new Date(N).toISOString()}function L(w,b){let N=x(w,"ownerTeam"),D=x(b,"ownerAlias");if(!(N===void 0&&D===void 0)){if(N===void 0||D===void 0)throw new C("INVALID_ARGUMENT","ownerTeam and ownerAlias must both be given");return{team:N,alias:D}}}return m.get("/api/tasks",w=>{let b=w.req.query();try{let N={project:x(b.project,"project"),kind:R(b.kind),status:x(b.status,"status"),parentId:y(b.parentId,"parentId"),owner:L(b.ownerTeam,b.ownerAlias),unassigned:I(b.unassigned,"unassigned"),limit:y(b.limit,"limit",Le),after:S(b.after,"after")};return w.json(Nr(t.db.db,N))}catch(N){return _(w,N)}}),m.get("/api/tasks/summary",w=>{try{let b=y(w.req.query("id"),"id"),N=x(w.req.query("project"),"project");return w.json(Cr(t.db.db,{id:b,project:N}))}catch(b){return _(w,b)}}),m.get("/api/tasks/:id",w=>{try{let b=T(w.req.param("id"),"id");return w.json(Ir(t.db.db,b))}catch(b){return _(w,b)}}),m.get("/api/tasks/:id/tree",w=>{try{let b=T(w.req.param("id"),"id");return w.json(Lr(t.db.db,b))}catch(b){return _(w,b)}}),m.get("/api/tasks/:id/notes",w=>{try{let b=T(w.req.param("id"),"id"),N=S(w.req.query("after"),"after"),D=y(w.req.query("limit"),"limit",Le);return w.json(op(t.db.db,b,{limit:D,after:N}))}catch(b){return _(w,b)}}),m.post("/api/send",async w=>{let b=await w.req.json().catch(()=>({})),N=b.prompt;if(!b.team||!N)return w.json({error:"team and prompt are required"},400);let D=t.teams.find(J=>J.name===b.team);if(!D)return w.json({error:`unknown team "${b.team}"`},404);if(!B(D))return w.json({error:`team "${b.team}" is a remote team (channel=lmmail) -- not reachable via lctl`},400);let W=await s({teamfilePath:Q(D),alias:D.leadAlias},N),ee=eo(W),oe=Date.now();return mr(t.db.db,D.name,ee.status,oe),ot(t.db.db,D.name,ee.status,oe,{note:"web send"}),w.json({status:ee.status,outcome:W})}),m.get("/api/history",w=>{let b=w.req.query("team"),N=w.req.query("limit"),D=Iu(t,b,N);return"error"in D?w.json(D,400):w.json(D)}),m.get("/api/sources",w=>w.json(Ju(t))),m.get("/api/mail/status",w=>w.json(Lu(t))),m.get("/api/subscriptions",async w=>{let{status:b,body:N}=await uE();return w.json(N,b)}),m.get("/api/whoami",async w=>{let{data:b,exitCode:N}=await i();return"error"in b?w.json(b,N===4?502:400):w.json(b)}),m.get("/api/running",async w=>w.json(await o())),m.get("/api/running/humanized",async w=>w.json(Ql(await o()))),m.get("/api/running/observed",w=>w.json(is())),m.get("/api/heavy-lock",w=>{try{return w.json(Kl(c,l))}catch(b){if(b instanceof zn)return w.json(Ae("heavy_lock_probe_failed",b.message),502);throw b}}),m.get("/api/health",async w=>{let b=w.req.query("target");if(!b)return w.json(Ae("target_required","target is required"),400);try{let N=await a(b);return w.json(N)}catch(N){return w.json(Ae("health_fetch_failed",N instanceof Error?N.message:String(N)),502)}}),m.post("/api/sources",async w=>{let b=await w.req.json().catch(()=>({}));if(!b.path)return w.json({error:"path is required"},400);let N=$a(t,b.path,b.label??void 0);return N.ok?(t.teams=rn(t.db.db,t.teamsConfPath),w.json({ok:!0})):w.json({error:N.output},400)}),m.delete("/api/sources",w=>{let b=w.req.query("path");return b?(Ks(t.db.db,b),t.teams=rn(t.db.db,t.teamsConfPath),w.json({ok:!0})):w.json({error:"path is required"},400)}),m}function dd(e){return e.teams=rn(e.db.db,e.teamsConfPath),e.teams}var kM=4173,xM="127.0.0.1";function cb(e){if(process.env.LMBEE_SITE_UUID!==void 0)try{let h=Nn(e.context.db.db,void 0,process.env.LMBEE_SITE_UUID);if(e.remoteMail&&e.remoteMail.localSiteId!==h)throw new Error("Remote mail site identity conflicts with the database binding")}catch(h){return Promise.reject(h)}let t=e.port??kM,r=e.hostname??xM,n=e.publish??!1;if(!["127.0.0.1","::1","localhost"].includes(r)&&!n)return Promise.reject(new Error("LocalWeb refuses a non-loopback bind without --publish (which also requires passcode auth)"));let o=r==="::1"?"[::1]":r,s=fs(e.context.db.path),i=null;if(s!==null)try{i=wa(s,e.lockOwnerLabel??"lmbee-serve")}catch(h){return Promise.reject(h)}let a=t===0?[]:[`http://${o}:${t}`,`http://localhost:${t}`,`http://[::1]:${t}`],c=e.remoteMail?{client:e.remoteMail.client,localSiteId:e.remoteMail.localSiteId}:void 0,l,u,d,m,f=null,p=null;try{let h=e.passcodeFilePath??Zn(e.context.db.path);n&&h!==null&&ya(h),l=ab({context:e.context,allowedOrigins:a,publish:n,passcodeFilePath:h,...e.config!==void 0?{config:e.config}:{},...e.fetchReport!==void 0?{fetchReport:e.fetchReport}:{},...e.mountPath!==void 0?{mountPath:e.mountPath}:{},...e.webDistDir!==void 0?{webDistDir:e.webDistDir}:{},...c?{remoteMail:c}:{},...e.remoteStalledConfig!==void 0?{remoteStalledConfig:e.remoteStalledConfig}:{}});let g=e.mountPath?.endsWith("/")?e.mountPath.slice(0,-1):e.mountPath;if(g?u=new dn().route(g,l).get(`${g}/`,async _=>{let E=new URL(_.req.url);E.pathname="/",E.search="";let y=await l.fetch(new Request(E,{method:"GET",headers:_.req.raw.headers}));return y.ok?_.redirect(g,302):y}):u=l,d=H_({db:e.context.db.db,getTeams:()=>dd(e.context),...e.intervalMs!==void 0?{intervalMs:e.intervalMs}:{},...e.config!==void 0?{config:e.config}:{},...e.fetchReport!==void 0?{fetchReport:e.fetchReport}:{},...e.maintainerWake!==void 0?{maintainerWake:e.maintainerWake}:{},...e.autoContinue!==void 0?{autoContinue:e.autoContinue}:{},...e.miniplayerVerify!==void 0?{miniplayerVerify:e.miniplayerVerify}:{},...e.hungHolderCheck!==void 0?{hungHolderCheck:e.hungHolderCheck}:{},...e.epicReview!==void 0?{epicReview:e.epicReview}:{},...e.orphanReconciler!==void 0?{orphanReconciler:e.orphanReconciler}:{},...e.hangProbeCollect!==void 0?{hangProbeCollect:e.hangProbeCollect}:{},...e.autoNudgeRedirectReview!==void 0?{autoNudgeRedirectReview:e.autoNudgeRedirectReview}:{},...e.rateLimitCollect!==void 0?{rateLimitCollect:e.rateLimitCollect}:{},...e.rateLimitPolicy!==void 0?{rateLimitPolicy:e.rateLimitPolicy}:{},...e.rateLimitAutomation!==void 0?{rateLimitAutomation:e.rateLimitAutomation}:{},onTick:_=>{process.stderr.write(`[cron] tick: watch=${_.watch.why}, ${_.stalled.length} stalled (${_.stalled.join(", ")||"none"})${_.maintainerWoken?", maintainer woken":""}${_.autoContinued.length?`, auto-continued (${_.autoContinued.join(", ")})`:""}
|
|
591
|
+
return (${$M.toString()})();
|
|
592
|
+
})();</script>`}function $M(){let e=document.getElementById("session-detail"),{team:t="",alias:r="",mount:n="",history:o="",canonicalTeamfile:s="",commEnabled:i="false",commPageEnabled:a="false"}=e.dataset,c=M=>document.getElementById(M),l=(M,j)=>{c(M).textContent=j},u=(M,j)=>{let Y=document.createElement(M);return Y.textContent=j,Y},d=new Map,m=!1,f=0,p,h=null,g=0,_=0,E=null,y=null,S=M=>!m&&!document.hidden&&M===f,T=()=>{},R=[],x=!1;function I(M){let j=u("span",M),Y=R.find(z=>z.name===M);if(!Y){let z=x?"Recorded label; current actor unresolved":"Recorded label; current team list unavailable";return j.title=`${M} \u2014 ${z}`,/[\\/]/.test(M)&&(j.textContent=M.split(/[\\/]/).at(-1).replace(/\.lmctl(?=:|$)/,"")),j}if(Y.channel==="lmmail")return j.textContent+=" (remote inbox)",j;if(Y.channel==="local"&&Y.leadAlias&&M!=="operator"){let z=u("a",`${Y.name}:${Y.leadAlias}`);z.title="Current configured inbox lead; not a historical sender session",j.textContent="",z.href=`${n}/sessions/${encodeURIComponent(Y.name)}/${encodeURIComponent(Y.leadAlias)}`,j.append(z)}return j}function A(M,j){let Y=u("span","");return Y.append(I(M),u("span"," \u2192 "),I(j)),Y}let H=M=>`${n}/sessions/${encodeURIComponent(t)}/${encodeURIComponent(r)}?queue=${M}`,L=M=>M instanceof Error?M.message:String(M);async function w(M,j){let Y=new AbortController;d.set(Y,j===void 0);let z=setTimeout(()=>Y.abort(),15e3);try{let re=await fetch(M,{method:j===void 0?"GET":"POST",signal:Y.signal,credentials:"same-origin",cache:"no-store",redirect:"error",headers:{Accept:"application/json",...j===void 0?{}:{"Content-Type":"application/json"}},...j===void 0?{}:{body:JSON.stringify(j)}});if(!re.ok)throw new Error(`HTTP ${re.status}; request unsuccessful`);if(!re.headers.get("content-type")?.includes("application/json"))throw new Error("Expected JSON response");let te=re.body.getReader(),de=new TextDecoder,xe=0,Se="";for(;;){let K=await te.read();if(K.done)break;if(xe+=K.value.byteLength,xe>2e6)throw await te.cancel(),new Error("Response exceeds 2 MB limit");Se+=de.decode(K.value,{stream:!0})}return JSON.parse(Se+de.decode())}finally{clearTimeout(z),d.delete(Y)}}function b(M){return M==="merged"||M==="informational"||M==="retracted"}function N(M,j=!1){if(j){if(M.lifecycle==="queued")return"queued";if(M.lifecycle==="finished")return M.lifecycleBasis==="merged"?"finished \xB7 merged into an earlier message":M.lifecycleBasis==="informational"?"finished \xB7 informational, no reply expected":M.lifecycleBasis==="retracted"?"finished \xB7 retracted, no reply expected":"finished \xB7 reply recorded";if(M.lifecycle==="processing")return M.lifecycleBasis==="confirmed"?"processing \xB7 picked up":"processing \xB7 attempted"}if(M.lifecycle==="finished")return M.lifecycleBasis==="merged"?"finished \u2014 merged into an earlier message, no separate response":M.lifecycleBasis==="informational"?"finished \u2014 informational, no response expected":M.lifecycleBasis==="retracted"?"finished \u2014 retracted, no response expected":"finished \u2014 response recorded";if(M.lifecycle==="queued")return"queued \u2014 waiting for handling";if(M.lifecycle==="processing")return M.lifecycleBasis==="confirmed"?"processing \u2014 picked up by inbox":"processing \u2014 delivery attempted; read not confirmed";throw new Error("Unknown lifecycle in owner response")}let D=null,W=M=>M!==null&&typeof M=="object"&&!Array.isArray(M),ee=(M,j)=>typeof M=="string"&&M.trim()?M:j,ne=!1;async function J(){if(!ne||D===f||m||document.hidden)return;let M=f;D=M,c("session-refresh").disabled=!0;try{let j=await w(o);if(!S(M))return;if(!W(j)||!Array.isArray(j.messages))throw new Error("Recent messages were not supplied by the history source");let Y=j.messages.slice(-20).map(z=>{let re=W(z)?z:{},te=re.content==null?"Message content not recorded.":typeof re.content=="string"?re.content:JSON.stringify(re.content),de=u("article","");return de.append(u("h3",ee(re.role,"Unknown role")),u("p",ee(re.timestamp,"Time not recorded.")),u("pre",te)),de});c("session-history").dataset.state="ready",c("session-history").replaceChildren(...Y.length?Y:[u("p","No recent messages returned.")]),l("session-history-status",`Latest ${Y.length} messages.${j.truncated===!0?" Older messages are not shown.":""}`),l("session-source",`Provider ${ee(j.provider,"not recorded")}; session ${ee(j.sessionId,"not recorded")}. Optional bounded provider tail. ${j.truncated===!0?"Older output truncated. ":""}Fetched ${new Date().toISOString()}.`)}catch(j){S(M)&&(c("session-history").dataset.state="error",c("session-history").children.length===0&&c("session-history").replaceChildren(u("p","Recent messages unavailable.")),l("session-history-status","Recent messages unavailable. Try Refresh transcript."),l("session-source",`History unavailable; previous content may be stale. ${L(j)}`))}finally{D===M&&(D=null),S(M)&&(c("session-refresh").disabled=!1)}}async function oe(){if(!s||m||document.hidden)return;let M=f;try{let j=new URLSearchParams({ownerTeam:s,ownerAlias:r,limit:"20"}),Y=await w(`${n}/api/tasks?${j}`);if(!S(M))return;if(!Array.isArray(Y.rows))throw new Error("Invalid task response");c("session-tasks").replaceChildren(u("p","Up to 20 assigned work items."),...Y.rows.slice(0,20).map(z=>{let re=u("a",`#${z.id} ${z.title} \u2014 ${z.kind}, ${z.status}`);re.href=`${n}/tasks/${Number(z.id)}`;let te=u("p","");if(te.append(re),Number.isSafeInteger(z.parent_id)&&z.parent_id>0){let de=u("a",` Parent work item #${z.parent_id}`);de.href=`${n}/tasks/${z.parent_id}`,te.append(de)}return te}),...Y.rows.length?[]:[u("p","No recorded assignment for this session.")])}catch(j){S(M)&&l("session-tasks",`Assigned work unavailable: ${L(j)}`)}}async function k(){if(E===g||h===null||m||document.hidden)return;E=g;let M=h,j=g,Y=f;try{let z=await w(`${n}/api/queue/${M}/state`);if(j!==g||!S(Y))return;if(z.id!==M)throw new Error("Queue identity mismatch");if(z.lifecycle==="finished"&&!b(z.lifecycleBasis)&&!z.answer)throw new Error("Finished state has no correlated response");if(z.answer&&z.answer.prompt_queue_id!==M)throw new Error("Answer correlation mismatch");c("comm-state").dataset.queueId=String(M),c("comm-state").dataset.lifecycle=z.lifecycle,c("comm-state").dataset.lifecycleBasis=z.lifecycleBasis,l("comm-state",`Queue #${M}: ${N(z)}. Created ${z.createdAt}. Last checked ${new Date().toISOString()}.`),z.answer?l("comm-response",`${z.answer.answer_text}
|
|
593
|
+
${z.answer.truncated?`Truncated response; ${z.answer.totalBytes} total bytes. No continuation endpoint available.`:""}`):l("comm-response",z.lifecycleBasis==="merged"?"No separate answer: prompt merged into another prompt.":z.lifecycleBasis==="informational"?"No answer expected: this was an informational prompt.":z.lifecycleBasis==="retracted"?"No answer expected: this prompt was retracted.":"Outcome unknown: no reply recorded. This does not establish failure or unread work."),z.lifecycle!=="finished"&&++_<60?p=setTimeout(()=>void k(),5e3):z.lifecycle!=="finished"&&l("comm-state",`Queue #${M}: observation stalled \u2014 automatic checks paused after 60 reads; last state ${N(z)}. Check again manually. This does not establish execution failure.`)}catch(z){j===g&&S(Y)&&l("comm-state",`State check failed; last content may be stale. ${L(z)}. Check again manually.`)}finally{E===j&&(E=null)}}async function O(M,j=!1){if(!Number.isSafeInteger(M)||M<1||m||document.hidden)return;c("comm-reading-panel").hidden=!1,y={id:M,admitted:j},clearTimeout(p),h=null,g++,_=0;let Y=g,z=f;delete c("comm-state").dataset.queueId,delete c("comm-state").dataset.lifecycle,delete c("comm-state").dataset.lifecycleBasis,l("comm-context","Loading recorded endpoints. Related task: not recorded; assigned work shown separately."),l("comm-state",`Loading queue #${M}\u2026`),l("comm-response",""),l("comm-preview","Loading request preview\u2026"),c("comm-check").hidden=!1;let re=new URL(location.href);re.searchParams.set("queue",String(M)),window.history.replaceState(null,"",re);try{let te=await w(`${n}/api/queue/${M}`);if(Y!==g||!S(z))return;if(te.queue.id!==M)throw new Error("Queue envelope identity mismatch");if(j&&te.queue.to_id!=="math")throw new Error("Admitted receipt is not addressed to math");if(te.queue.to_id!==t&&te.queue.from_id!==t)throw new Error("Queue message does not belong to this team");h=M;let de=c("comm-context");if(de.replaceChildren(u("span",`Request #${M}: `),A(te.queue.from_id,te.queue.to_id),u("span",". Expected reply context: "),I(te.queue.to_id),u("span",` inbox for prompt #${M} from `),I(te.queue.from_id),u("span",". Check the response status below; a reply may not be recorded. Related task: not recorded; assigned work shown separately.")),typeof te.queue.retracted_reason=="string"&&te.queue.retracted_reason&&de.append(u("span",` Retraction reason: ${te.queue.retracted_reason}.`)),a==="true"&&te.queue.to_id==="math"){let Se=u("a","Open full prompt and answer");Se.href=`${n}/comm/math/prompts/${M}`,de.append(Se)}let xe=await w(`${n}/api/queue/${M}/preview`);if(Y!==g||!S(z))return;if(xe.id!==M)throw new Error("Preview identity mismatch");l("comm-preview",xe.status==="available"?`${xe.text??""}${xe.truncated?`
|
|
594
|
+
[Prompt preview truncated]`:""}`:`Prompt preview ${xe.status}; content unavailable.`)}catch(te){Y===g&&S(z)&&(l("comm-preview",`Prompt preview unavailable: ${L(te)}`),h===null&&l("comm-state","Queue selection unavailable; select a message from this team."))}await k()}let $=null;async function q(){if($===f||m||document.hidden)return;let M=f;$=M,c("comm-refresh").disabled=!0;try{let j=await w(`${n}/api/teams`).catch(()=>null);if(!S(M))return;R=j?.teams??[],x=j!==null;let Y=R.find(K=>K.name===t),z=Y?.channel==="local"&&typeof Y.description=="string"?Y.description.trim():"";l("session-purpose",j===null?"Team purpose unavailable.":z?`Recorded team description: \u201C${z}\u201D`:"No team purpose recorded.");let re=await Promise.all(["to","from"].map(async K=>{let Te=await w(`${n}/api/queue/prompts?${K}=${encodeURIComponent(t)}&limit=20`);if(!Array.isArray(Te.rows))throw new Error("Invalid message list");return Te}));if(!S(M))return;let te=new Map;for(let K of re)for(let Te of K.rows.slice(0,20)){if(!Number.isSafeInteger(Te.id)||Te.id<1)throw new Error("Invalid queue identity");if(Te.to_id!==t&&Te.from_id!==t)throw new Error("Message outside current team");let ze=te.get(Te.id);(!ze||Te.lifecycle==="finished"&&ze.lifecycle!=="finished")&&te.set(Te.id,Te)}let de=K=>Number.isFinite(Date.parse(K))?Date.parse(K):Number.MAX_VALUE,Se=[...te.values()].sort((K,Te)=>de(K.created_ts)-de(Te.created_ts)||K.id-Te.id).map(K=>{let Te=u("li","");Te.dataset.queueId=String(K.id);let ze=u("a",`Read exchange #${K.id}`);ze.href=H(K.id),ze.addEventListener("click",ye=>{ye.defaultPrevented||ye.button!==0||ye.metaKey||ye.ctrlKey||ye.shiftKey||ye.altKey||(ye.preventDefault(),O(K.id))}),Te.append(ze);let We=u("div","");We.dataset.queueId=String(K.id),We.dataset.event="request";let Ut=Number.isFinite(Date.parse(K.created_ts))?K.created_ts:"Time not recorded; placed last by request ID",V=u("span",K.lifecycle==="queued"?"Queued":K.lifecycle==="processing"?"Processing":K.lifecycleBasis==="merged"?"Combined":K.lifecycleBasis==="informational"?"Informational":K.lifecycleBasis==="retracted"?"Retracted":"Replied");if(V.className=`status-chip status-${K.lifecycle==="queued"?"queued":K.lifecycle==="processing"?"processing":b(K.lifecycleBasis)?"muted":"replied"}`,V.title=N(K),We.append(u("p",`Request recorded: ${Ut}`),A(K.from_id,K.to_id),V),K.from_id===K.to_id&&We.append(u("p","Self-addressed request.")),K.subject_id!=null&&We.append(u("p",`Recorded subject label: ${K.subject_id}`)),Te.append(We),K.lifecycle==="finished"&&!b(K.lifecycleBasis)){let ye=u("div","");ye.dataset.queueId=String(K.id),ye.dataset.event="response",ye.append(u("span","Answer recorded in "),I(K.to_id),u("span",` inbox for prompt #${K.id} from `),I(K.from_id),u("p",`Recorded reply time: ${K.answeredAt??"Time not recorded"}`));let lt=u("details",""),rt=u("pre","Open to load the recorded reply.");lt.append(u("summary","Show reply"),rt);let _t=!1,Ke=!1;lt.addEventListener("toggle",async()=>{if(!lt.open||_t||Ke||m||document.hidden)return;let Tn=f;Ke=!0,rt.textContent="Loading reply\u2026";try{let Sr=await w(`${n}/api/queue/${K.id}/state`);if(!S(Tn))return;let ur=Sr.answer;if(Sr.id!==K.id||ur===null||ur.prompt_queue_id!==K.id)throw new Error("Answer identity mismatch");if(typeof ur.answer_text!="string")throw new Error("Reply text unavailable");let nt=Array.from(ur.answer_text);rt.textContent=nt.slice(0,1200).join("")+(nt.length>1200||ur.truncated?`
|
|
595
|
+
[Reply excerpt; open the full exchange for available text.]`:""),_t=!0}catch(Sr){S(Tn)&&(rt.textContent=`Reply unavailable: ${L(Sr)}. Close and reopen to retry.`)}finally{Ke=!1}}),ye.append(lt),Te.append(ye)}else Te.append(u("p",K.lifecycleBasis==="merged"?"No separate answer: prompt merged into another prompt.":K.lifecycleBasis==="informational"?"No answer expected: this was an informational prompt.":K.lifecycleBasis==="retracted"?`No answer expected: this prompt was retracted. Reason: ${K.retracted_reason??"no reason recorded"}.`:"Reply: not recorded"));return Te});c("comm-sequence").replaceChildren(...Se.slice(-5)),c("comm-older-sequence").replaceChildren(...Se.slice(0,-5)),c("comm-older").hidden=Se.length<=5,l("comm-older-label",`Show ${Math.max(0,Se.length-5)} older loaded prompts`),l("comm-coverage",`Showing newest ${Math.min(5,Se.length)} of ${te.size} loaded prompts, ordered by arrival, oldest first; answers are grouped with their prompts. ${re.some(K=>K.meta.next_cursor!==null)?"This is a limited sample; additional records have not been loaded.":"All prompts from the returned pages are available here."}`)}catch(j){S(M)&&l("comm-coverage",`Message context unavailable; previous events may be stale. ${L(j)}`)}finally{$===M&&($=null),S(M)&&(c("comm-refresh").disabled=!1)}}let U=c("comm-form");if(U&&i==="true"&&t==="math"&&r==="Lead"){let M=c("comm-draft"),j=c("comm-submit"),Y=c("comm-confirm"),z=c("comm-edit"),re=null,te=!1,de=!1,xe="Page paused during admission";T=()=>{m||document.hidden||!re||!de||(Y.disabled=te,te||(l("comm-send-status",`Admission uncertain or failed: ${xe}. Retry preserves the exact prompt and dedupe key. Keep this page open until resolved.`),Y.textContent="Retry same prompt safely"))},U.addEventListener("submit",Se=>{if(Se.preventDefault(),!(m||document.hidden||te||re)){if(!M.value.trim()||new TextEncoder().encode(M.value).length>65536){l("comm-send-status","Enter a nonblank prompt of at most 64 KiB UTF-8.");return}re={to:"math",prompt:M.value,dedupeKey:`localweb:${crypto.randomUUID()}`},M.disabled=!0,j.disabled=!0,l("comm-review",`To math, from operator:
|
|
596
|
+
${re.prompt}`),c("comm-review").hidden=!1,Y.hidden=!1,z.hidden=!1,l("comm-send-status","Review the exact prompt before confirming.")}}),z.addEventListener("click",()=>{te||de||(re=null,M.disabled=!1,j.disabled=!1,Y.hidden=!0,z.hidden=!0,c("comm-review").hidden=!0)}),Y.addEventListener("click",async()=>{if(!re||te||m||document.hidden)return;let Se=f;te=!0,de=!0,Y.disabled=!0,z.hidden=!0,l("comm-send-status","Submitting; waiting for confirmation that the prompt was queued\u2026");try{let K=await w(`${n}/api/comm/send`,re);if(!S(Se))throw new Error("Page paused before receipt could be shown");if(!Number.isSafeInteger(K.queueId)||K.queueId<1)throw new Error("Missing queue receipt");l("comm-send-status",`Accepted as queue #${K.queueId}${K.replayed?" (existing prompt recovered)":""}.`),re=null,de=!1,M.value="",M.disabled=!1,j.disabled=!1,Y.hidden=!0,Y.textContent="Confirm send to math",c("comm-review").hidden=!0,O(K.queueId,!0),q()}catch(K){xe=L(K)}finally{te=!1,!m&&!document.hidden&&(Y.disabled=!1),T()}})}c("session-refresh").addEventListener("click",()=>{ne=!0,l("session-refresh","Refresh transcript"),J()}),c("comm-refresh").addEventListener("click",()=>void q()),c("comm-check").addEventListener("click",()=>{clearTimeout(p),_=0,k()});let Z=M=>{f++,g++,clearTimeout(p),D=null,$=null;for(let[j,Y]of d)(M||Y)&&j.abort()},G=()=>{m||document.hidden||(ne&&J(),oe(),q(),y&&O(y.id,y.admitted),T())},ie=()=>{document.hidden?Z(!1):G()};document.addEventListener("visibilitychange",ie);let be=()=>{m=!0,Z(!0),document.removeEventListener("visibilitychange",ie)};window.addEventListener("pagehide",be),window.addEventListener("pageshow",M=>{M.persisted&&(m=!1,document.addEventListener("visibilitychange",ie),G())}),oe(),q();let ae=Number(new URL(location.href).searchParams.get("queue"));return Number.isSafeInteger(ae)&&ae>0&&O(ae),be}function cb(e){let{context:t}=e,r=e.config??he,n=e.remoteStalledConfig??{},o=e.fetchReport??ke,s=e.send??Jt,i=e.whoami??Zu,a=e.fetchHealth??uE,c=e.heavyLockStatusPath??Kn(),l=e.heavyLockPath??Yn(),u=e.tail??Fi,d=e.tailJson??qi,m=new dn;if(e.publish===!0){let w=e.passcodeFilePath!==void 0?e.passcodeFilePath:Zn(t.db.path),b=e.readPasscodeAuthority??(()=>w===null?null:ew(w));SE(m,{allowedOrigins:e.allowedOrigins,mountPath:e.mountPath,readAuthority:b,...e.remoteKey!==void 0?{remoteKey:e.remoteKey}:{}})}else m.use("*",async(w,b)=>{w.header("Cache-Control","no-store");let N=w.req.header("origin");if(N!==void 0&&!e.allowedOrigins.includes(N))return w.json({error:"origin not allowed"},403);await b()});m.route("/",PE({context:t,allowedOrigins:e.allowedOrigins,mountPath:e.mountPath,enabled:!0})),ib(m,t,e.mountPath),IE(m,{webDistDir:e.webDistDir,mountPath:e.mountPath}),GE(m,t,e.mountPath),XE(m,t,e.mountPath),sb(m,t,e.mountPath),m.post("/api/jobs/on-demand",async w=>{let b;try{b=await w.req.json()}catch{return w.json({error:"invalid JSON"},400)}if(b===null||typeof b!="object"||Array.isArray(b))return w.json({error:"expected object"},400);let N=b;if(typeof N.db!="string"||typeof N.local_scope!="string"||typeof N.script!="string"||!Array.isArray(N.args)||!N.args.every(D=>typeof D=="string")||N.conversationid!==void 0&&typeof N.conversationid!="string")return w.json({error:"invalid on-demand request"},400);try{let D=await Gw(t.db.db,t.db.path,t.teams,{db:N.db,localScope:N.local_scope,script:N.script,args:N.args,...typeof N.conversationid=="string"?{conversationId:N.conversationid}:{}});return"status"in D&&D.status==="busy"?w.json(D,503):w.json(D,202)}catch(D){if(D instanceof P||D instanceof C){let W=D.code==="INVALID_ARGUMENT"||D.code==="INVALID_SCHEDULE"?400:D.code==="NOT_FOUND"?404:D.code==="CONFLICT"?409:D.code==="DB_BUSY"?503:500;return W===503&&w.header("Retry-After","1"),w.json({error:D.message},W)}return w.json({error:D instanceof Error?D.message:String(D)},500)}}),m.get("/api/teams",w=>w.json(Xu(t))),m.get("/api/identities/:key",w=>w.json(zs(t.teams,w.req.param("key")))),m.get("/api/state",w=>{let b=w.req.query("team");return b!==void 0?w.json(Ku(t,b)):w.req.query("active")!==void 0?w.json(Yu(t)):w.json(zu(t))}),m.get("/api/status",async w=>{let b=w.req.query("live")==="1"||w.req.query("live")==="true",N=await Qu(t,{live:b,fetchReport:o});return w.json(N)}),m.get("/api/liveness",async w=>{let b=await o(),N=t.teams.map(D=>{let W=B(D)?null:si(t.db.db,{site:D.peerSite,team:D.name,alias:D.alias});return{team:D.name,running:B(D)?je(D,b):!1,deadReclaimable:B(D)?cn(D,b):!1,remoteOutbound:W?{state:W.state,sentTs:W.sent_ts,ackedTs:W.acked_ts,repliedTs:W.replied_ts}:null}});return w.json({report:b,teams:N})}),m.get("/api/stalled",async w=>{let b=await o(),N=ft(c,l,void 0,ee=>{process.stderr.write(`[api/stalled] heavy-lock probe failed, treating conservatively as held: ${ee.message}
|
|
597
|
+
`)}),D=await Pn(t.db.db,t.teams.filter(B),b,N,r,void 0,{readOnly:!0}),W=Vw(t.db.db,t.teams.filter(ee=>!B(ee)),n);return w.json({stalled:D,remoteStalled:W})});function f(w){let b=t.teams.find(D=>D.name===w);if(!b)return{error:`unknown team "${w}"`,status:404};if(!B(b))return{error:`team "${w}" is a remote team (channel=lmmail) -- not reachable via lctl`,status:400};let N;try{N=Q(b)}catch(D){return{error:D instanceof Error?D.message:String(D),status:500}}return{teamfilePath:N}}function p(w,b,N,D){return d(w,b,{lines:N?Number(N):20,...D?{since:D}:{}})}let h=(e.mountPath??"").replace(/\/$/,"");m.get("/running",w=>{try{let b=is(),N=b.report===null?"<p>Activity has not yet been observed; running, dead, and idle counts are unknown.</p>":`<p>Cached observation taken ${b.observedAt?pe(b.observedAt):"at an unknown time"}. Refreshing this page does not run a new activity scan.</p>`,D=b.lastError?`<p class="warning">Observer failed${b.lastErrorAt?` ${pe(b.lastErrorAt)}`:""}: ${v(b.lastError)}. ${b.report?"Showing the last successful observation.":"No successful observation is available."}</p>`:"",W=b.report===null?"":hE(Ql(b.report),Br(t.teams),h);return Me(w,$e("Running","<p>This page loaded just now; activity data comes from a separate scheduled observation and may be older.</p>"+N+D+W,h))}catch(b){return Me(w,$e("Running unavailable",`<p>${v(b instanceof Error?b.message:String(b))}</p>`,h),502)}}),m.get("/sessions/:team/:alias",w=>{let b=w.req.param("team"),N=w.req.param("alias"),D=`Session: ${b} / ${N}`,W={"data-page":"session","data-team":b,"data-alias":N},ee=f(b);if("error"in ee)return Me(w,$e(D,`<p role="alert">${v(ee.error)}</p>`,h,W),ee.status);let ne=ab(b,N,h,{canonicalTeamfile:ee.teamfilePath,commPageEnabled:!0}),J=Array.from(ne.matchAll(/<script>([\s\S]*?)<\/script>/g),oe=>oe[1]);return Me(w,$e(D,ne,h,W,J))}),m.get("/api/session/:team/:alias",async w=>{let b=w.req.param("team"),N=w.req.param("alias"),D=f(b);if("error"in D)return w.json({error:D.error},D.status);let{teamfilePath:W}=D,ee=w.req.query("since"),ne=w.req.query("limit");try{let J=await p(W,N,ne,ee);return w.json(J)}catch(J){return w.json({error:J instanceof Error?J.message:String(J)},404)}}),m.get("/api/transcript",async w=>{let b=w.req.query("team");if(!b)return w.json({error:"team is required"},400);let N=t.teams.find(J=>J.name===b);if(!N)return w.json({error:`unknown team "${b}"`},404);if(!B(N))return w.json({error:`team "${b}" is a remote team (channel=lmmail) -- not reachable via lctl`},400);let D=w.req.query("alias")??N.leadAlias,W;try{W=Q(N)}catch(J){return w.json({error:J instanceof Error?J.message:String(J)},500)}let ee=w.req.query("lines"),ne=w.req.query("since");try{let J=await u(W,D,{...ee?{lines:Number(ee)}:{},...ne?{since:ne}:{}});return w.json({team:b,alias:D,...J})}catch(J){return w.json({error:J instanceof Error?J.message:String(J)},502)}}),m.get("/api/queue",w=>{let b=w.req.query("to");return w.json(Bu(t,b))}),m.get("/api/queue/stats",w=>{try{let b=x(w.req.query("to"),"to");return w.json(Vu(t,b))}catch(b){return _(w,b)}});let g=w=>{try{let b=w.req.query(),N={fromId:x(b.from,"from"),toId:x(b.to,"to"),status:A(b.status),since:H(b.since,"since"),until:H(b.until,"until"),after:y(b.after,"after"),limit:y(b.limit,"limit",200)};return w.json(Aa(t,N))}catch(b){return _(w,b)}};m.get("/api/queue/prompts",g),m.get("/api/queue/:id",w=>{let b=Number(w.req.param("id")),N=ro(t,b);return N?w.json({queue:N}):w.json(Ae("queue_not_found",`no queue entry ${b}`),404)}),m.get("/api/queue/:id/state",w=>{let b=Number(w.req.param("id")),N=ws(t,b);return N?w.json(N):w.json(Ae("queue_not_found",`no queue entry ${b}`),404)}),m.post("/api/queue/:id/answer",async w=>{try{let b=T(w.req.param("id"),"id"),N=await w.req.json().catch(()=>({})),D=x(N.from,"from"),W=x(N.text,"text");if(D===void 0||W===void 0)return w.json(Ae("invalid_argument","from and text are required"),400);let ee=gn(t.db.db,b,D,W);return w.json({answer:ee},202)}catch(b){return _(w,b)}}),m.get("/api/queue/:id/preview",w=>{try{let b=T(w.req.param("id"),"id"),N=jr(t,b);return N?w.json(N):w.json(Ae("queue_not_found",`no queue entry ${b}`),404)}catch(b){return _(w,b)}}),m.post("/api/enqueue",async w=>{let b=await w.req.json().catch(()=>({})),N=b.prompt;if(!b.to||!N||!b.from)return w.json({error:"to, prompt, and from are required"},400);if(b.from==="autopilot")return w.json({error:"from: 'autopilot' is reserved for the tool's own automated enqueues"},400);try{let D=e.publish===!0&&b.from==="operator",W=we(t.db.db,t.teams,b.to,N,{from:b.from,...D?{operatorPriority:!0}:{}});return w.json({id:W})}catch(D){return w.json({error:D instanceof Error?D.message:String(D)},400)}}),m.post("/api/comm/send",async w=>{try{let b=await w.req.json().catch(()=>({})),N=x(b.to,"to"),D=x(b.prompt,"prompt"),W=x(b.dedupeKey,"dedupeKey");if(N===void 0||D===void 0||W===void 0)return w.json(Ae("invalid_argument","to, prompt, and dedupeKey are required"),400);let ee=Ra(t.db.db,t.teams,{to:N,prompt:D,dedupeKey:W});return w.json(ee,ee.replayed?200:202)}catch(b){return _(w,b)}}),m.post("/api/queue/deliver",async w=>{let b=await o(),N=xr(t.db.db,{teams:t.teams,report:b,...e.remoteMail?{remoteMail:e.remoteMail}:{}});return w.json({delivered:N})}),m.post("/api/queue/retrieve",async w=>{let b=await w.req.json().catch(()=>({}));if(!b.to)return w.json({error:"to is required"},400);if(b.id!==void 0&&(!Number.isInteger(b.id)||b.id<=0))return w.json({error:"id must be a positive integer"},400);try{let D=ui(t.db.db,b.to,b.id).map(W=>{let ee;try{ee=kM(W.prompt_file,"utf8")}catch{ee="(could not read prompt file)"}return{...W,content:ee}});return w.json({retrieved:D})}catch(N){return _(w,N)}}),m.get("/api/inbox",w=>{let b=w.req.query("to");return b?w.json(Gu(t,b)):w.json(Ae("to_required","to is required"),400)});function _(w,b){if(b instanceof C){let N=b.code==="NOT_FOUND"?404:b.code==="CONFLICT"?409:b.code==="DB_BUSY"?503:b.code==="STORAGE_ERROR"?500:400;return w.json(Ae(b.code,b.message),N)}return w.json(Ae("internal_error",b instanceof Error?b.message:String(b)),500)}let E=new Set(["epic","task","subtask"]);function y(w,b,N){if(w===void 0)return;let D=Number(w);if(!/^[1-9]\d*$/.test(w)||!Number.isSafeInteger(D)||N!==void 0&&D>N)throw new C("INVALID_ARGUMENT",N!==void 0?`${b} must be a positive integer <= ${N}`:`${b} must be a positive integer`);return D}function S(w,b){if(w===void 0)return;let N=Number(w);if(!/^\d+$/.test(w)||!Number.isSafeInteger(N))throw new C("INVALID_ARGUMENT",`${b} must be a nonnegative integer`);return N}function T(w,b){let N=Number(w);if(!/^[1-9]\d*$/.test(w)||!Number.isSafeInteger(N))throw new C("INVALID_ARGUMENT",`${b} must be a positive integer`);return N}function R(w){if(w!==void 0){if(!E.has(w))throw new C("INVALID_ARGUMENT","kind must be 'epic', 'task', or 'subtask'");return w}}function x(w,b){if(w!==void 0){if(w.trim()==="")throw new C("INVALID_ARGUMENT",`${b} must not be blank`);return w}}function I(w,b){if(w!==void 0){if(w==="1"||w==="true")return!0;if(w==="0"||w==="false")return!1;throw new C("INVALID_ARGUMENT",`${b} must be '1'/'true' or '0'/'false'`)}}function A(w){if(w!==void 0){if(!qc.includes(w))throw new C("INVALID_ARGUMENT",`status must be one of: ${qc.join(", ")}`);return w}}function H(w,b){if(w===void 0)return;let N=w.trim()===""?NaN:Date.parse(w);if(Number.isNaN(N))throw new C("INVALID_ARGUMENT",`${b} must be a valid ISO8601 date-time string`);return new Date(N).toISOString()}function L(w,b){let N=x(w,"ownerTeam"),D=x(b,"ownerAlias");if(!(N===void 0&&D===void 0)){if(N===void 0||D===void 0)throw new C("INVALID_ARGUMENT","ownerTeam and ownerAlias must both be given");return{team:N,alias:D}}}return m.get("/api/tasks",w=>{let b=w.req.query();try{let N={project:x(b.project,"project"),kind:R(b.kind),status:x(b.status,"status"),parentId:y(b.parentId,"parentId"),owner:L(b.ownerTeam,b.ownerAlias),unassigned:I(b.unassigned,"unassigned"),limit:y(b.limit,"limit",Le),after:S(b.after,"after")};return w.json(Nr(t.db.db,N))}catch(N){return _(w,N)}}),m.get("/api/tasks/summary",w=>{try{let b=y(w.req.query("id"),"id"),N=x(w.req.query("project"),"project");return w.json(Cr(t.db.db,{id:b,project:N}))}catch(b){return _(w,b)}}),m.get("/api/tasks/:id",w=>{try{let b=T(w.req.param("id"),"id");return w.json(Ir(t.db.db,b))}catch(b){return _(w,b)}}),m.get("/api/tasks/:id/tree",w=>{try{let b=T(w.req.param("id"),"id");return w.json(Lr(t.db.db,b))}catch(b){return _(w,b)}}),m.get("/api/tasks/:id/notes",w=>{try{let b=T(w.req.param("id"),"id"),N=S(w.req.query("after"),"after"),D=y(w.req.query("limit"),"limit",Le);return w.json(sp(t.db.db,b,{limit:D,after:N}))}catch(b){return _(w,b)}}),m.post("/api/send",async w=>{let b=await w.req.json().catch(()=>({})),N=b.prompt;if(!b.team||!N)return w.json({error:"team and prompt are required"},400);let D=t.teams.find(J=>J.name===b.team);if(!D)return w.json({error:`unknown team "${b.team}"`},404);if(!B(D))return w.json({error:`team "${b.team}" is a remote team (channel=lmmail) -- not reachable via lctl`},400);let W=await s({teamfilePath:Q(D),alias:D.leadAlias},N),ee=eo(W),ne=Date.now();return mr(t.db.db,D.name,ee.status,ne),ot(t.db.db,D.name,ee.status,ne,{note:"web send"}),w.json({status:ee.status,outcome:W})}),m.get("/api/history",w=>{let b=w.req.query("team"),N=w.req.query("limit"),D=Iu(t,b,N);return"error"in D?w.json(D,400):w.json(D)}),m.get("/api/sources",w=>w.json(Ju(t))),m.get("/api/mail/status",w=>w.json(Lu(t))),m.get("/api/subscriptions",async w=>{let{status:b,body:N}=await dE();return w.json(N,b)}),m.get("/api/whoami",async w=>{let{data:b,exitCode:N}=await i();return"error"in b?w.json(b,N===4?502:400):w.json(b)}),m.get("/api/running",async w=>w.json(await o())),m.get("/api/running/humanized",async w=>w.json(Ql(await o()))),m.get("/api/running/observed",w=>w.json(is())),m.get("/api/heavy-lock",w=>{try{return w.json(Yl(c,l))}catch(b){if(b instanceof zn)return w.json(Ae("heavy_lock_probe_failed",b.message),502);throw b}}),m.get("/api/health",async w=>{let b=w.req.query("target");if(!b)return w.json(Ae("target_required","target is required"),400);try{let N=await a(b);return w.json(N)}catch(N){return w.json(Ae("health_fetch_failed",N instanceof Error?N.message:String(N)),502)}}),m.post("/api/sources",async w=>{let b=await w.req.json().catch(()=>({}));if(!b.path)return w.json({error:"path is required"},400);let N=$a(t,b.path,b.label??void 0);return N.ok?(t.teams=rn(t.db.db,t.teamsConfPath),w.json({ok:!0})):w.json({error:N.output},400)}),m.delete("/api/sources",w=>{let b=w.req.query("path");return b?(Ys(t.db.db,b),t.teams=rn(t.db.db,t.teamsConfPath),w.json({ok:!0})):w.json({error:"path is required"},400)}),m}function dd(e){return e.teams=rn(e.db.db,e.teamsConfPath),e.teams}var xM=4173,RM="127.0.0.1";function lb(e){if(process.env.LMBEE_SITE_UUID!==void 0)try{let h=Nn(e.context.db.db,void 0,process.env.LMBEE_SITE_UUID);if(e.remoteMail&&e.remoteMail.localSiteId!==h)throw new Error("Remote mail site identity conflicts with the database binding")}catch(h){return Promise.reject(h)}let t=e.port??xM,r=e.hostname??RM,n=e.publish??!1;if(!["127.0.0.1","::1","localhost"].includes(r)&&!n)return Promise.reject(new Error("LocalWeb refuses a non-loopback bind without --publish (which also requires passcode auth)"));let o=r==="::1"?"[::1]":r,s=fs(e.context.db.path),i=null;if(s!==null)try{i=wa(s,e.lockOwnerLabel??"lmbee-serve")}catch(h){return Promise.reject(h)}let a=t===0?[]:[`http://${o}:${t}`,`http://localhost:${t}`,`http://[::1]:${t}`],c=e.remoteMail?{client:e.remoteMail.client,localSiteId:e.remoteMail.localSiteId}:void 0,l,u,d,m,f=null,p=null;try{let h=e.passcodeFilePath??Zn(e.context.db.path);n&&h!==null&&ya(h),l=cb({context:e.context,allowedOrigins:a,publish:n,passcodeFilePath:h,...e.config!==void 0?{config:e.config}:{},...e.fetchReport!==void 0?{fetchReport:e.fetchReport}:{},...e.mountPath!==void 0?{mountPath:e.mountPath}:{},...e.webDistDir!==void 0?{webDistDir:e.webDistDir}:{},...c?{remoteMail:c}:{},...e.remoteStalledConfig!==void 0?{remoteStalledConfig:e.remoteStalledConfig}:{}});let g=e.mountPath?.endsWith("/")?e.mountPath.slice(0,-1):e.mountPath;if(g?u=new dn().route(g,l).get(`${g}/`,async _=>{let E=new URL(_.req.url);E.pathname="/",E.search="";let y=await l.fetch(new Request(E,{method:"GET",headers:_.req.raw.headers}));return y.ok?_.redirect(g,302):y}):u=l,d=B_({db:e.context.db.db,getTeams:()=>dd(e.context),...e.intervalMs!==void 0?{intervalMs:e.intervalMs}:{},...e.config!==void 0?{config:e.config}:{},...e.fetchReport!==void 0?{fetchReport:e.fetchReport}:{},...e.maintainerWake!==void 0?{maintainerWake:e.maintainerWake}:{},...e.autoContinue!==void 0?{autoContinue:e.autoContinue}:{},...e.miniplayerVerify!==void 0?{miniplayerVerify:e.miniplayerVerify}:{},...e.hungHolderCheck!==void 0?{hungHolderCheck:e.hungHolderCheck}:{},...e.epicReview!==void 0?{epicReview:e.epicReview}:{},...e.orphanReconciler!==void 0?{orphanReconciler:e.orphanReconciler}:{},...e.hangProbeCollect!==void 0?{hangProbeCollect:e.hangProbeCollect}:{},...e.autoNudgeRedirectReview!==void 0?{autoNudgeRedirectReview:e.autoNudgeRedirectReview}:{},...e.rateLimitCollect!==void 0?{rateLimitCollect:e.rateLimitCollect}:{},...e.rateLimitPolicy!==void 0?{rateLimitPolicy:e.rateLimitPolicy}:{},...e.rateLimitAutomation!==void 0?{rateLimitAutomation:e.rateLimitAutomation}:{},onTick:_=>{process.stderr.write(`[cron] tick: watch=${_.watch.why}, ${_.stalled.length} stalled (${_.stalled.join(", ")||"none"})${_.maintainerWoken?", maintainer woken":""}${_.autoContinued.length?`, auto-continued (${_.autoContinued.join(", ")})`:""}
|
|
598
598
|
`)},onError:_=>{process.stderr.write(`[cron] tick failed: ${_ instanceof Error?_.stack??_.message:String(_)}
|
|
599
|
-
`)}}),m=
|
|
599
|
+
`)}}),m=Dw({db:e.context.db.db,getTeams:()=>dd(e.context),...e.queueIntervalMs!==void 0?{intervalMs:e.queueIntervalMs}:{},...e.fetchReport!==void 0?{fetchReport:e.fetchReport}:{},...c?{remoteMail:c}:{},...e.deliverImpl!==void 0?{deliverImpl:e.deliverImpl}:{},...e.minMemoryPercent!==void 0?{minMemoryPercent:e.minMemoryPercent}:{},onDeliver:_=>{_>0&&process.stderr.write(`[queue] delivered ${_}
|
|
600
600
|
`)},onError:_=>{process.stderr.write(`[queue] delivery pass failed: ${_ instanceof Error?_.stack??_.message:String(_)}
|
|
601
|
-
`)}}),e.remoteMail){let _=e.remoteMail;f=
|
|
601
|
+
`)}}),e.remoteMail){let _=e.remoteMail;f=Ow({db:e.context.db.db,client:_.client,mailbox:_.mailbox,worker:{localSiteId:_.localSiteId,allowlist:_.allowlist,dispatch:E=>nw(e.context.db.db,dd(e.context),E,{client:_.client,localSiteId:_.localSiteId})},..._.intervalMs!==void 0?{intervalMs:_.intervalMs}:{},onPoll:E=>{if(_.onPoll?.(E),E.recorded>0||E.retriedFailed>0){let y=e.fetchReport??ke,S=e.deliverImpl??xr;y().then(T=>S(e.context.db.db,{teams:e.context.teams,report:T,...c?{remoteMail:c}:{}})).catch(T=>{process.stderr.write(`[mail] prompt-delivery trigger failed: ${T instanceof Error?T.stack??T.message:String(T)}
|
|
602
602
|
`)})}},onError:_.onMailError??(E=>{process.stderr.write(`[mail] poll failed: ${E instanceof Error?E.stack??E.message:String(E)}
|
|
603
|
-
`)})})}if(e.execWorker){let _=e.execWorker;p=(_.createExecWorkerImpl??
|
|
604
|
-
`),S.onMailError?.(R)})}if(p&&e.execWorker){let S=e.execWorker;(S.ensureExecMailboxImpl??
|
|
603
|
+
`)})})}if(e.execWorker){let _=e.execWorker;p=(_.createExecWorkerImpl??Nw)({client:_.client,mailbox:_.mailbox,adminUsers:_.adminUsers,allowUsers:_.allowUsers,allowAnonymous:_.allowAnonymous,..._.pollIntervalMs!==void 0?{pollIntervalMs:_.pollIntervalMs}:{},..._.timeoutCapSeconds!==void 0?{timeoutCapSeconds:_.timeoutCapSeconds}:{}})}}catch(h){throw i?.release(),h}return new Promise((h,g)=>{let _=!1,E;try{E=Lp({fetch:u.fetch,port:t,hostname:r},y=>{if(t===0&&a.push(`http://${o}:${y.port}`,`http://localhost:${y.port}`,`http://[::1]:${y.port}`),_=!0,d.start(),m.start(),f&&e.remoteMail){let S=e.remoteMail;(S.ensureMailboxImpl??Cw)(S.client,S.mailbox).then(()=>f?.start()).catch(R=>{process.stderr.write(`[mail] mailbox provisioning failed, mail lane stays dormant this run: ${R instanceof Error?R.stack??R.message:String(R)}
|
|
604
|
+
`),S.onMailError?.(R)})}if(p&&e.execWorker){let S=e.execWorker;(S.ensureExecMailboxImpl??Rw)(S.client,S.mailbox).then(()=>p?.start()).catch(R=>{process.stderr.write(`[exec-worker] mailbox provisioning failed, exec stays dormant this run: ${R instanceof Error?R.stack??R.message:String(R)}
|
|
605
605
|
`)})}h({app:l,scheduler:d,queueScheduler:m,mailScheduler:f,execWorker:p,server:E,port:y.port,hostname:r,close(){d.stop(),m.stop(),f?.stop(),p?.stop(),E.close(),i?.release()},async shutdown(){d.stop(),m.stop(),f?.stop(),p?.stop();let S=new Promise((R,x)=>{E.close(I=>I?x(I):R())}),T=(async()=>{for(;d.isTicking()||m.isDelivering()||(f?.isPolling()??!1);)await new Promise(R=>setTimeout(R,50))})();await Promise.all([S,T,p?.whenIdle()??Promise.resolve()]),i?.release()}})})}catch(y){i?.release(),g(y instanceof Error?y:new Error(String(y)));return}E.on("error",y=>{if(_){process.stderr.write(`[serve] post-bind server error (ignored -- lock/scheduler untouched): ${y instanceof Error?y.stack??y.message:String(y)}
|
|
606
|
-
`);return}_=!0,i?.release(),g(y instanceof Error?y:new Error(String(y)))})})}function St(e,t=[]){let r=new Set(t),n=[],o={};for(let s=0;s<e.length;s++){let i=e[s];if(i==="-h")o.help=!0;else if(i.startsWith("--")){let a=i.slice(2),c=e[s+1];!r.has(a)&&c!==void 0&&!c.startsWith("--")?(o[a]=c,s++):o[a]=!0}else n.push(i)}return{positionals:n,flags:o}}function _n(e,t){if(e===void 0)return;if(typeof e!="string")return new Error(`${t} requires a numeric value (milliseconds)`);let r=Number(e);return!Number.isFinite(r)||r<0?new Error(`${t} must be a finite, non-negative number of milliseconds, got "${e}"`):r}function lo(e,t){if(e===void 0)return;if(typeof e!="string")return new Error(`${t} requires a numeric value`);let r=Number(e);return!Number.isFinite(r)||r<0?new Error(`${t} must be a finite, non-negative number, got "${e}"`):r}import{existsSync as
|
|
607
|
-
`,{flag:"wx"})}catch(o){throw o&&typeof o=="object"&&"code"in o&&o.code==="EEXIST"?new P("INVALID_ARGUMENT",`export path already exists: ${t} (rm it first; there is no --force)`):new P("INVALID_ARGUMENT",`cannot write export to ${t}: ${o instanceof Error?o.message:String(o)}`)}return n}function
|
|
608
|
-
refuses if PATH already exists (rm it first; there is no --force). Definitions only, never execution state.`;function Es(e,t,r){if(t.length>1)throw new P("INVALID_ARGUMENT",`cron ${e} takes exactly one PATH argument -- refusing unexpected extra argument ${JSON.stringify(t[1])}`);for(let n of Object.keys(r))if(n!=="json"&&n!=="help")throw new P("INVALID_ARGUMENT",`cron ${e} does not know flag "--${n}" (only --json and --help)`)}function
|
|
609
|
-
${
|
|
610
|
-
`)}async function
|
|
611
|
-
`)}),i=t.nowMs??Date.now(),a=t.config??he;return{teams:n.map(c=>({team:c.name,stalled:rl(e.db.db,c,o,s,a,i)}))}}var La=Bt(Ct(),1);import{readFileSync as
|
|
606
|
+
`);return}_=!0,i?.release(),g(y instanceof Error?y:new Error(String(y)))})})}function St(e,t=[]){let r=new Set(t),n=[],o={};for(let s=0;s<e.length;s++){let i=e[s];if(i==="-h")o.help=!0;else if(i.startsWith("--")){let a=i.slice(2),c=e[s+1];!r.has(a)&&c!==void 0&&!c.startsWith("--")?(o[a]=c,s++):o[a]=!0}else n.push(i)}return{positionals:n,flags:o}}function _n(e,t){if(e===void 0)return;if(typeof e!="string")return new Error(`${t} requires a numeric value (milliseconds)`);let r=Number(e);return!Number.isFinite(r)||r<0?new Error(`${t} must be a finite, non-negative number of milliseconds, got "${e}"`):r}function lo(e,t){if(e===void 0)return;if(typeof e!="string")return new Error(`${t} requires a numeric value`);let r=Number(e);return!Number.isFinite(r)||r<0?new Error(`${t} must be a finite, non-negative number, got "${e}"`):r}import{existsSync as NM,readFileSync as IM,writeFileSync as LM}from"node:fs";var md="lmbee-cron-export",ub=["schema_version","kind","exported_at","exported_from","jobs"],db=["id","title","schedule_expr","action_kind","action_payload","provider","model","working_directory","escalation_owner","timezone","enabled"],CM=["provider","model","working_directory","escalation_owner","timezone"];function OM(e){return{id:e.id,title:e.title,schedule_expr:e.schedule_expr,action_kind:e.action_kind,action_payload:e.action_payload,provider:e.provider,model:e.model,working_directory:e.working_directory,escalation_owner:e.escalation_owner,timezone:e.timezone,enabled:!!e.enabled}}function DM(e){return e instanceof Error&&"code"in e&&typeof e.code=="string"&&e.code.startsWith("SQLITE_BUSY")}function MM(e,t){let r;try{r=e.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'cron_jobs'").get()!==void 0?e.prepare("SELECT * FROM cron_jobs ORDER BY id").all():[]}catch(n){throw DM(n)?new P("SOURCE_BUSY","source database is locked by another process -- export never waits on locks (busy_timeout = 0); retry shortly",3):n}for(let n of r)if(n.action_kind!=="command"&&n.action_kind!=="script")throw new P("INVALID_ARGUMENT",`cron job ${n.id} "${n.title}" has action_kind "${n.action_kind}" -- export does not carry ${n.action_kind}-kind jobs, so no file was written (import would refuse it; never produce a transferable payload containing one -- re-create the job manually on the target)`);return{schema_version:1,kind:md,exported_at:new Date().toISOString(),exported_from:t,jobs:r.map(OM)}}function PM(e,t,r){let n=MM(e,r);try{LM(t,`${JSON.stringify(n,null,2)}
|
|
607
|
+
`,{flag:"wx"})}catch(o){throw o&&typeof o=="object"&&"code"in o&&o.code==="EEXIST"?new P("INVALID_ARGUMENT",`export path already exists: ${t} (rm it first; there is no --force)`):new P("INVALID_ARGUMENT",`cannot write export to ${t}: ${o instanceof Error?o.message:String(o)}`)}return n}function UM(e){let t=Lo(e);dc(t);let r=new yt(t,{readonly:!0,fileMustExist:!0});return r.pragma("busy_timeout = 0"),{db:r,path:t,close:()=>r.close()}}var mb=`usage: lmbee cron export PATH [--json] -- write all cron job DEFINITIONS (ids preserved) as one JSON document;
|
|
608
|
+
refuses if PATH already exists (rm it first; there is no --force). Definitions only, never execution state.`;function Es(e,t,r){if(t.length>1)throw new P("INVALID_ARGUMENT",`cron ${e} takes exactly one PATH argument -- refusing unexpected extra argument ${JSON.stringify(t[1])}`);for(let n of Object.keys(r))if(n!=="json"&&n!=="help")throw new P("INVALID_ARGUMENT",`cron ${e} does not know flag "--${n}" (only --json and --help)`)}function fb(e){let{positionals:t,flags:r}=St(e,["json","help"]),n=r.json===!0;try{if(r.help===!0)return{output:mb,exitCode:0};Es("export",t,r);let o=t[0];if(o===void 0)throw new P("INVALID_ARGUMENT",`an export PATH is required
|
|
609
|
+
${mb}`);let s=UM();try{let i=PM(s.db,o,s.path);return n?{output:JSON.stringify({schema_version:1,ok:!0,data:{path:o,exported_from:s.path,jobs:i.jobs.length}}),exitCode:0}:{output:`exported ${i.jobs.length} jobs to ${o}`,exitCode:0}}finally{s.close()}}catch(o){if(o instanceof P)return n?{output:JSON.stringify({schema_version:1,ok:!1,error:{code:o.code,message:o.message}}),exitCode:o.exitCode}:{output:`${o.code}: ${o.message}`,exitCode:o.exitCode};throw o}}function vt(e,t){throw new P("INVALID_ARGUMENT",`jobs[${e}]: ${t}`)}function FM(e,t){(typeof e!="object"||e===null||Array.isArray(e))&&vt(t,"must be a JSON object");let r=e;for(let l of Object.keys(r))db.includes(l)||vt(t,`unknown key "${l}"`);for(let l of db)l in r||vt(t,`missing key "${l}"`);let{id:n,title:o,schedule_expr:s,action_kind:i,action_payload:a,enabled:c}=r;(typeof n!="number"||!Number.isSafeInteger(n)||n<1)&&vt(t,"id must be a positive safe integer"),(typeof o!="string"||o.trim().length===0)&&vt(t,"title must be a nonblank string"),typeof s!="string"&&vt(t,"schedule_expr must be a string"),typeof i!="string"&&vt(t,"action_kind must be a string"),i==="enqueue"&&vt(t,"import does not carry enqueue-kind jobs (zero existed when this was designed; refusing rather than risking a payload current validation rejects -- create it manually)"),(i==="session"||i==="miniplayer")&&vt(t,`import does not carry ${i}-kind jobs (out of scope -- untested expansion; create it manually)`),i!=="command"&&i!=="script"&&vt(t,`action_kind "${i}" is not a known kind; only "command" and "script" are accepted`),typeof a!="string"&&vt(t,"action_payload must be a string"),typeof c!="boolean"&&vt(t,`enabled must be a JSON boolean (true/false), not ${JSON.stringify(c)}`);for(let l of CM){let u=r[l];u!==null&&typeof u!="string"&&vt(t,`${l} must be a string or null`)}return r}function pb(e){let t;try{t=IM(e,"utf8")}catch(i){throw new P("INVALID_ARGUMENT",`cannot read import file ${e}: ${i instanceof Error?i.message:String(i)}`)}let r;try{r=JSON.parse(t)}catch(i){throw new P("INVALID_ARGUMENT",`import file ${e} is not valid JSON: ${i instanceof Error?i.message:String(i)}`)}if(typeof r!="object"||r===null||Array.isArray(r))throw new P("INVALID_ARGUMENT","import document must be a JSON object");let n=r;for(let i of Object.keys(n))if(!ub.includes(i))throw new P("INVALID_ARGUMENT",`unknown top-level key "${i}"`);for(let i of ub)if(!(i in n))throw new P("INVALID_ARGUMENT",`missing top-level key "${i}"`);if(n.schema_version!==1)throw new P("INVALID_ARGUMENT",`schema_version must be 1, got ${JSON.stringify(n.schema_version)}`);if(n.kind!==md)throw new P("INVALID_ARGUMENT",`kind must be "${md}", got ${JSON.stringify(n.kind)}`);for(let i of["exported_at","exported_from"])if(typeof n[i]!="string")throw new P("INVALID_ARGUMENT",`${i} must be a string, got ${JSON.stringify(n[i])}`);if(!Array.isArray(n.jobs))throw new P("INVALID_ARGUMENT","jobs must be an array");let o=n.jobs.map((i,a)=>FM(i,a)),s=new Set;for(let i of o){if(s.has(i.id))throw new P("INVALID_ARGUMENT",`duplicate id ${i.id} within the document`);s.add(i.id)}return o}function hb(e){return{...e,title:e.title.trim(),timezone:e.timezone===null?null:e.timezone.trim()}}function qM(e,t){let r=hb(t);return e.title===r.title&&e.schedule_expr===r.schedule_expr&&e.action_kind===r.action_kind&&e.action_payload===r.action_payload&&e.provider===r.provider&&e.model===r.model&&e.working_directory===r.working_directory&&e.escalation_owner===r.escalation_owner&&e.timezone===r.timezone&&!!e.enabled===r.enabled}function jM(e){let t=hb(e);return{id:t.id,title:t.title,scheduleExpr:t.schedule_expr,actionKind:t.action_kind,actionPayload:t.action_payload,enabled:t.enabled,...t.provider!==null?{provider:t.provider}:{},...t.model!==null?{model:t.model}:{},...t.working_directory!==null?{workingDirectory:t.working_directory}:{},...t.escalation_owner!==null?{escalationOwner:t.escalation_owner}:{},...t.timezone!==null?{timezone:t.timezone}:{}}}function gb(e){pb(e)}function _b(e,t){let r=pb(t),n=[],o=[];e.transaction(()=>{for(let a of r){let c=zi(e,a.id);if(c!==null){if(qM(c,a)){n.push({id:a.id,title:a.title});continue}throw new P("CONFLICT",`cron job ${a.id} already exists with a different definition: existing "${c.title}" vs import "${a.title}" -- refusing the whole file, nothing written`,4)}Jn(e,jM(a)),o.push(a)}}).immediate();let i=[];for(let a of o)a.working_directory!==null&&!NM(a.working_directory)&&i.push(`job ${a.id} "${a.title}": working_directory ${a.working_directory} does not exist on this host`);return{imported:o.length,skipped:n,warnings:i}}function wb(e){let t=[`imported ${e.imported}, skipped ${e.skipped.length} already-present`];for(let r of e.skipped)t.push(`skipped: ${r.id} "${r.title}"`);for(let r of e.warnings)t.push(`warning: ${r}`);return t.join(`
|
|
610
|
+
`)}async function yb(e,t={}){let r=t.team===void 0?e.teams:e.teams.filter(c=>c.name===t.team);if(t.team!==void 0){if(r.length===0)throw new Error(`unknown team: ${t.team}`);if(!r.every(B))throw new Error(`stalled verdict requires a local team: ${t.team}`)}let n=r.filter(B),o=await(t.fetchReportImpl??ke)(),s=t.heavyLockImpl?.()??ft(void 0,void 0,void 0,c=>{process.stderr.write(`[stalled] heavy-lock probe failed, treating conservatively as held: ${c.message}
|
|
611
|
+
`)}),i=t.nowMs??Date.now(),a=t.config??he;return{teams:n.map(c=>({team:c.name,stalled:rl(e.db.db,c,o,s,a,i)}))}}var La=Bt(Ct(),1);import{readFileSync as HM}from"node:fs";function wn(e,t,r={}){if(e===void 0)return;if(typeof e!="string"||!/^\d+$/.test(e))throw new P("INVALID_ARGUMENT",`${t} must be a nonnegative integer`);let n=Number(e),o=r.minimum??1;if(!Number.isSafeInteger(n)||n<o||r.maximum!==void 0&&n>r.maximum){let s=r.maximum!==void 0?`between ${o} and ${r.maximum}`:`>= ${o}`;throw new P("INVALID_ARGUMENT",`${t} must be an integer ${s}`)}return n}function gr(e,t){let r=wn(e,t,{minimum:1});if(r===void 0)throw new P("INVALID_ARGUMENT",`${t} is required`);return r}function BM(e){return e==="enqueue"||e==="command"||e==="script"||e==="session"||e==="miniplayer"}var WM=["pending","running","succeeded","failed","escalated"];function GM(e){return WM.includes(e)}function Eb(e){let t=e.payload,r=e.prompt,n=e["prompt-file"];if([t,r,n].filter(s=>s!==void 0).length>1)throw new P("INVALID_ARGUMENT","provide only one of --payload, --prompt, or --prompt-file");if(n!==void 0){if(typeof n!="string")throw new P("INVALID_ARGUMENT","--prompt-file requires a path");try{return HM(n,"utf8")}catch(s){throw new P("INVALID_ARGUMENT",`cannot read --prompt-file ${n}: ${s instanceof Error?s.message:String(s)}`)}}if(typeof t=="string")return t;if(typeof r=="string")return r}function Je(e){return typeof e=="string"?e:void 0}function ht(e,t,r={}){return e?JSON.stringify({schema_version:1,ok:!0,data:t,meta:r}):VM(t,r)}function bb(e,t){return e?{output:JSON.stringify({schema_version:1,ok:!1,error:{code:t.code,message:t.message}}),exitCode:t.exitCode}:{output:`${t.code}: ${t.message}`,exitCode:t.exitCode}}function VM(e,t){let r;if(Array.isArray(e)){let o=s=>s!==null&&typeof s=="object"&&"title"in s;r=e.length===0?"(empty)":e.every(o)?(0,La.formatTable)([["ID","ENABLED","KIND","SCHEDULE","TITLE"],...e.map(s=>["id","enabled","action_kind","schedule_expr","title"].map(i=>(0,La.escapeCell)(String(s[i]??""))))]):e.map(s=>JSON.stringify(s)).join(`
|
|
612
612
|
`)}else typeof e=="string"?r=e:r=JSON.stringify(e,null,2);let n=t.next_cursor;return n!=null?`${r}
|
|
613
|
-
More records: --after ${String(n)}`:r}var
|
|
613
|
+
More records: --after ${String(n)}`:r}var Tb=`usage: lmbee cron create --title TEXT --schedule "m h dom mon dow" --kind enqueue|command|script|session|miniplayer [--payload TEXT | --prompt TEXT | --prompt-file PATH] [--provider P] [--model M] [--cwd DIR] [--owner NAME] [--disabled] [--timezone IANA-name] | show ID | list [--enabled true|false] [--limit N] [--after ID] | update ID [--title T] [--schedule EXPR] [--payload TEXT|--prompt TEXT|--prompt-file PATH] [--provider P] [--model M] [--cwd DIR] [--owner NAME] [--timezone IANA-name|""] [--if-revision N] | enable ID | disable ID | remove ID | reset ID | reset-session ID | export PATH | import PATH | runs [--job ID] [--status pending|running|succeeded|failed|escalated] [--limit N] [--after ID] | run RUN-ID | trigger ID | report RUN-TOKEN --status succeeded|failed|escalated --summary TEXT [--artifact A[,B]] [--requested-action TEXT] [--owner NAME] | resolve RUN-ID [--resolution TEXT] [--actor NAME] [--note TEXT] [--confirm-stopped]
|
|
614
614
|
NOTE: a job fires at most once per daemon tick interval (default 30 minutes), regardless of how frequent its own schedule expression is -- lmcron catches up a missed window, coalesced to one fire, never one fire per missed minute.
|
|
615
|
-
NOTE: export/import carry job DEFINITIONS only (ids preserved), NEVER execution state -- runtime/session columns reset on import, historical timestamps are deliberately omitted, and the overlap fences live in cron_runs, which is not migrated. At scheduler cutover, stop the old daemon BEFORE the new one ticks; never run both schedules concurrently.`;async function
|
|
616
|
-
`)});if(m.held&&(m.holder===null||m.holder.holder===l.name))return{team:l.name,dispatched:!1,status:null,wake:null};if(ti(e.db,l.name,l.leadAlias,n))return{team:l.name,dispatched:!1,status:null,wake:null};let f=await t({teamfilePath:d,alias:l.leadAlias},e.resolveNudgeMessage(l)),p=eo(f);return mr(e.db,l.name,p.status,n),Uo(e.db,l.name,new Date(n).toISOString()),ot(e.db,l.name,p.status,n),{team:l.name,dispatched:!0,status:p.status,wake:p.wake}}),c=a.find(l=>l.wake!==null)?.wake??null;return{results:a,wake:c}}async function
|
|
617
|
-
`)}),a=oa(r.promptsDir);return(r.scanOnceImpl??
|
|
618
|
-
`):"(no eligible teams)"}async function
|
|
619
|
-
Manual nudge/enqueue/lctl chat and queue delivery to ${t} are unaffected.`}function
|
|
620
|
-
`)}var
|
|
615
|
+
NOTE: export/import carry job DEFINITIONS only (ids preserved), NEVER execution state -- runtime/session columns reset on import, historical timestamps are deliberately omitted, and the overlap fences live in cron_runs, which is not migrated. At scheduler cutover, stop the old daemon BEFORE the new one ticks; never run both schedules concurrently.`;async function Sb(e,t,r,n,o=[]){try{let[s,...i]=t;switch(s){case"create":{let a=r.title;if(typeof a!="string")throw new P("INVALID_ARGUMENT","--title is required");let c=r.schedule;if(typeof c!="string")throw new P("INVALID_ARGUMENT","--schedule is required");let l=r.kind;if(typeof l!="string"||!BM(l))throw new P("INVALID_ARGUMENT",'--kind must be "enqueue", "command", "script", "session", or "miniplayer"');let u=Eb(r);if(u===void 0)throw new P("INVALID_ARGUMENT",l==="session"||l==="miniplayer"?"--prompt or --prompt-file is required":"--payload is required");let d=Jn(e,{title:a,scheduleExpr:c,actionKind:l,actionPayload:u,enabled:r.disabled!==!0,timezone:typeof r.timezone=="string"?r.timezone:void 0,...Je(r.provider)!==void 0?{provider:Je(r.provider)}:{},...Je(r.model)!==void 0?{model:Je(r.model)}:{},...Je(r.cwd)!==void 0?{workingDirectory:Je(r.cwd)}:{},...Je(r.owner)!==void 0?{escalationOwner:Je(r.owner)}:{}});return{output:ht(n,d),exitCode:0}}case"show":{let a=gr(i[0],"id");return{output:ht(n,Ce(e,a)),exitCode:0}}case"list":{let a=r.enabled,c;if(a!==void 0){if(a!=="true"&&a!=="false")throw new P("INVALID_ARGUMENT",'--enabled must be "true" or "false"');c=a==="true"}let{rows:l,meta:u}=Ki(e,{enabled:c,limit:wn(r.limit,"--limit",{maximum:Le})??100,after:wn(r.after,"--after",{minimum:0})??0});return{output:ht(n,l,u),exitCode:0}}case"update":{let a=gr(i[0],"id"),c=Eb(r),l=ig(e,a,{title:typeof r.title=="string"?r.title:void 0,scheduleExpr:typeof r.schedule=="string"?r.schedule:void 0,actionPayload:c,timezone:typeof r.timezone=="string"?r.timezone===""?null:r.timezone:void 0,provider:Je(r.provider),model:Je(r.model),workingDirectory:typeof r.cwd=="string"?r.cwd===""?null:r.cwd:void 0,escalationOwner:typeof r.owner=="string"?r.owner===""?null:r.owner:void 0,ifRevision:wn(r["if-revision"],"--if-revision")});return{output:ht(n,l),exitCode:0}}case"enable":case"disable":{let a=gr(i[0],"id"),c=ag(e,a,s==="enable");return{output:ht(n,c),exitCode:0}}case"remove":{let a=gr(i[0],"id"),c=cg(e,a);return{output:ht(n,c),exitCode:0}}case"reset":{let a=gr(i[0],"id"),c=hg(e,a);return{output:ht(n,c),exitCode:0}}case"reset-session":{let a=gr(i[0],"id"),c=lg(e,a);return{output:ht(n,c),exitCode:0}}case"runs":{let a=r.status;if(a!==void 0&&(typeof a!="string"||!GM(a)))throw new P("INVALID_ARGUMENT","--status must be one of pending|running|succeeded|failed|escalated");let c=r.job!==void 0?wn(r.job,"--job"):void 0,{rows:l,next_cursor:u}=Wi(e,{...c!==void 0?{jobId:c}:{},...a!==void 0?{status:a}:{},limit:wn(r.limit,"--limit",{maximum:Le})??100,after:wn(r.after,"--after",{minimum:0})??0});return{output:ht(n,l.map(Xo),{next_cursor:u}),exitCode:0}}case"run":{let a=gr(i[0],"id");return{output:ht(n,Xo(Be(e,a))),exitCode:0}}case"trigger":{let a=gr(i[0],"id"),c=await ss(e,a,o);return{output:ht(n,{trigger:c.kind,job:c.job}),exitCode:0}}case"report":{let a=i[0];if(a===void 0)throw new P("INVALID_ARGUMENT","a run token is required");let c=r.status;if(typeof c!="string"||c!=="succeeded"&&c!=="failed"&&c!=="escalated")throw new P("INVALID_ARGUMENT",'--status must be "succeeded", "failed", or "escalated"');let l=r.summary;if(typeof l!="string")throw new P("INVALID_ARGUMENT","--summary is required");let u=typeof r.artifact=="string"?r.artifact:void 0,d=u!==void 0?u.split(",").map(p=>p.trim()).filter(p=>p.length>0):void 0,m=typeof r["requested-action"]=="string"?r["requested-action"]:Je(r.action),f=Bh(e,a,{status:c,summary:l,...d!==void 0?{artifacts:d}:{},...m!==void 0?{action:m}:{},...Je(r.owner)!==void 0?{owner:Je(r.owner)}:{},...Je(r.reason)!==void 0?{reason:Je(r.reason)}:{}});return{output:ht(n,Xo(f)),exitCode:0}}case"import":{Es("import",i,r);let a=i[0];if(a===void 0)throw new P("INVALID_ARGUMENT","an import PATH is required");let c=_b(e,a);return{output:n?ht(!0,c):wb(c),exitCode:0}}case"resolve":{let a=gr(i[0],"id"),c=Gh(e,a,{resolution:Je(r.resolution),actor:Je(r.actor),note:Je(r.note),confirmStopped:r["confirm-stopped"]===!0});return{output:ht(n,Xo(c)),exitCode:0}}default:return n?bb(n,new P("INVALID_ARGUMENT",Tb)):{output:Tb,exitCode:1}}}catch(s){if(s instanceof P)return bb(n,s);throw s}}var vb=["disabled","confirm-stopped"];async function Ab(e){let t=e.send??Jt,r=e.config??he,n=e.nowMs??Date.now(),o=e.maxParallel??4,s=e.readHeavyLockStatusImpl??ft,i=e.teams.filter(l=>!se(e.db,l.name)?.confirmed_done_ts),a=await JM(i,o,async l=>{if(!await tl(e.db,l,e.report,e.heavyLock,r,n))return{team:l.name,dispatched:!1,status:null,wake:null};let d;try{d=Q(l)}catch(h){let g=h instanceof Error?h.message:String(h);return mr(e.db,l.name,"ENV-ERROR",n),Uo(e.db,l.name,new Date(n).toISOString()),ot(e.db,l.name,"ENV-ERROR",n,{note:g}),{team:l.name,dispatched:!0,status:"ENV-ERROR",wake:"env"}}let m=s(e.heavyLockStatusPath,e.heavyLockPath,void 0,h=>{process.stderr.write(`[scan] heavy-lock probe failed for ${l.name}, treating conservatively as held: ${h.message}
|
|
616
|
+
`)});if(m.held&&(m.holder===null||m.holder.holder===l.name))return{team:l.name,dispatched:!1,status:null,wake:null};if(ti(e.db,l.name,l.leadAlias,n))return{team:l.name,dispatched:!1,status:null,wake:null};let f=await t({teamfilePath:d,alias:l.leadAlias},e.resolveNudgeMessage(l)),p=eo(f);return mr(e.db,l.name,p.status,n),Uo(e.db,l.name,new Date(n).toISOString()),ot(e.db,l.name,p.status,n),{team:l.name,dispatched:!0,status:p.status,wake:p.wake}}),c=a.find(l=>l.wake!==null)?.wake??null;return{results:a,wake:c}}async function JM(e,t,r){let n=new Array(e.length),o=0;async function s(){for(;;){let a=o++;if(a>=e.length)return;n[a]=await r(e[a])}}let i=Math.max(1,Math.min(t,e.length));return await Promise.all(Array.from({length:i},()=>s())),n}async function bs(e,t,r={}){let o=await(r.fetchReport??ke)(),s=r.readHeavyLockStatusImpl??ft,i=s(void 0,void 0,void 0,l=>{process.stderr.write(`[scan] heavy-lock probe failed, treating conservatively as held: ${l.message}
|
|
617
|
+
`)}),a=oa(r.promptsDir);return(r.scanOnceImpl??Ab)({db:e,teams:t.filter(B),report:o,heavyLock:i,readHeavyLockStatusImpl:s,resolveNudgeMessage:l=>sa(a,l)})}function Ts(e){let t=e.results.map(r=>`${r.team}: ${r.dispatched?r.status:"skipped (not stalled)"}`);return t.length?t.join(`
|
|
618
|
+
`):"(no eligible teams)"}async function $b(e,t,r={}){if(t.length===0)throw new Error("usage: lmbee nudge <team> [team2 ...]");let n=e.teams.filter(s=>t.includes(s.name));if(n.length===0)throw new Error(`nudge: no matching teams for: ${t.join(", ")}`);let o=await bs(e.db.db,n,r);return Ts(o)}function kb(e,t,r){let n=$t(e.db.db,t),o={companionTeam:r.companionTeam,workerAlias:r.workerAlias??"Worker",commitThreshold:r.commitThreshold??$l,hoursThresholdMs:r.hoursThresholdMs??kl,shiftStartedTs:n?.companionTeam===r.companionTeam?n?.shiftStartedTs??null:null,shiftStartedSha:n?.companionTeam===r.companionTeam?n?.shiftStartedSha??null:null,turnsDispatched:n?.companionTeam===r.companionTeam?n?.turnsDispatched??0:0,lastReviewedTurn:n?.companionTeam===r.companionTeam?n?.lastReviewedTurn??0:0};return Oi(e.db.db,t,o),r.json?JSON.stringify({team:t,...o}):`auto-nudge for ${t} now redirects to ${o.companionTeam}:${o.workerAlias} (review due after ${o.commitThreshold} commits or ${(o.hoursThresholdMs/36e5).toFixed(1)}h, whichever first).
|
|
619
|
+
Manual nudge/enqueue/lctl chat and queue delivery to ${t} are unaffected.`}function xb(e,t,r={}){let n=$t(e.db.db,t)!==null;return ih(e.db.db,t),r.json?JSON.stringify({team:t,redirected:!1}):n?`auto-nudge for ${t} no longer redirects -- back to nudging ${t} directly.`:`auto-nudge for ${t} was not redirected (no-op).`}function zM(e,t){let r=t!==void 0?[t]:xl(e.db.db),n=[];for(let o of r){let s=$t(e.db.db,o);s!==null&&n.push({team:o,config:s})}return n}function Rb(e,t,r={}){let n=zM(e,t);return r.json?JSON.stringify(n):n.length===0?t!==void 0?`${t}: not redirected.`:"no teams are currently redirected.":n.map(o=>{let s=o.config.shiftStartedTs!==null?`shift started ${o.config.shiftStartedTs}`:"no shift started yet (redirect configured, auto-continue has not fired for this team since)",i=o.config.turnsDispatched<Bo?`, ramp-up turn ${o.config.turnsDispatched}/${Bo} (every turn always reviewed)`:"";return`${o.team} -> ${o.config.companionTeam}:${o.config.workerAlias} (${o.config.commitThreshold} commits or ${(o.config.hoursThresholdMs/36e5).toFixed(1)}h) -- ${s}${i}`}).join(`
|
|
620
|
+
`)}var KM=new Set(["operator","lmauto"]),YM=new Set(["autopilot"]);function QM(e,t){return YM.has(e)?t:e}function Nb(e,t,r,n){if(n.newTaskTitle!==void 0&&n.taskId!==void 0)throw new Error("prompt: --new-task and --task are exclusive -- start a new task OR continue an existing one, not both");if(n.newTaskTitle===void 0&&n.taskId===void 0&&KM.has(n.from))throw new Error(`prompt: --from ${n.from} requires either --new-task <title> or --task <id> -- an operator/proxy-initiated prompt always names the task it belongs to (this is the exact class of prompt #16024 measured going missing)`);let o,s;if(n.newTaskTitle!==void 0){let c=ay(e.db.db,{title:n.newTaskTitle,description:n.newTaskDescription});o=c.id,s=`new task #${c.id}: "${c.title}"`}else if(n.taskId!==void 0){let c=gs(e.db.db,n.taskId);if(c===null)throw new Error(`prompt: --task ${n.taskId} does not refer to an existing prompt task`);o=c.id,s=`task #${c.id}: "${c.title}"`}else{let c=QM(n.from,t);o=my(e.db.db,c),s=o!==null?`inherited task #${o} from ${c}'s own most recent message`:`no task (${c} has no prior chat history to inherit from)`}let i=qr("prompt",r,n.literal);return`prompt#${cy(e.db.db,{taskId:o,fromId:n.from,toId:t,prompt:i}).id} -> ${t} (${s}) -- lives in the prompt_tasks/task_prompts ledger, not queue; enqueue/queue answer are unaffected, and nothing is mirrored between them.`}function Ib(e,t,r={}){let n=hy(e.db.db,t);if(r.json)return JSON.stringify({tasks:n});if(n.length===0)return`prompt tasks ${t}: no threads yet`;let o=n.map(s=>`#${s.task.id} "${s.task.title}" -- ${s.promptCount} prompt${s.promptCount===1?"":"s"}, last ${s.lastPromptAt}`);return`prompt tasks ${t}:
|
|
621
621
|
${o.join(`
|
|
622
|
-
`)}`}function
|
|
622
|
+
`)}`}function Lb(e,t,r={}){let n=gs(e.db.db,t);if(n===null)return`prompt log: task #${t} does not exist`;let o=ly(e.db.db,t);if(r.json)return JSON.stringify({task:n,messages:o});if(o.length===0)return`prompt log #${t} ("${n.title}"): no prompts yet`;let s=o.map(i=>`#${i.id} ${i.from_id} -> ${i.to_id} (${i.created_at}):
|
|
623
623
|
${i.prompt}`);return`prompt log #${t} ("${n.title}"):
|
|
624
624
|
|
|
625
625
|
${s.join(`
|
|
626
626
|
|
|
627
|
-
`)}`}function
|
|
627
|
+
`)}`}function Cb(e,t,r,n){let o=e.db.db.prepare("SELECT task_id FROM task_prompts WHERE id = ?").get(t);if(o===void 0)throw new Error(`prompt reassign: prompt #${t} does not exist`);let s=fy(e.db.db,{promptId:t,toTaskId:r,reassignedBy:n.by}),i=o.task_id!==null?`task #${o.task_id}`:"no task";return`prompt reassign: prompt #${t} moved from ${i} to task #${s.task_id} by ${n.by}`}function Ob(e,t,r={}){let n=py(e.db.db,t);if(r.json)return JSON.stringify({reassignments:n});if(n.length===0)return`prompt reassignments #${t}: none`;let o=n.map(s=>`#${s.id} ${s.reassigned_at} by ${s.reassigned_by}: ${s.from_task_id!==null?`task #${s.from_task_id}`:"no task"} -> task #${s.to_task_id}`);return`prompt reassignments #${t}:
|
|
628
628
|
${o.join(`
|
|
629
|
-
`)}`}function
|
|
630
|
-
Every team whose resolved auto-nudge target uses "${t}" goes quiet; manual nudge/enqueue/lctl chat is unaffected.`}function
|
|
631
|
-
`)}function
|
|
632
|
-
FROM rate_limit_bucket_samples WHERE provider = ? AND bucket_id = ? AND resets_at = ? AND read_at >= ? ORDER BY read_at ASC`).all(t,r,n,s).map(m=>({readAt:m.readAt,usedFraction:m.usedFraction})),c=a.length>0?(a[a.length-1].readAt-a[0].readAt)*1e3:0,l=`samples=${a.length} span=${Math.round(c/1e3)}s (lookback ${Math.round(18e5/6e4)}m)`,u=Zi(a,o),d=u.kind==="insufficient_data"?`no-forecast: ${u.reason}`:u.kind==="no_forecast"?"no-forecast: flat or non-increasing usage":`forecastable: reaches 100% at ${new Date(u.forecastAtMs).toISOString()}`;return`${l} -- ${d}`}function
|
|
629
|
+
`)}`}function Db(e,t,r={}){if(Pi(e.db.db,t,{reason:r.reason??null,expiresAt:r.expiresAt??null}),r.json)return JSON.stringify(Mi(e.db.db,t));let n=r.reason?` (${r.reason})`:"",o=r.expiresAt?`, auto-re-enables at ${r.expiresAt}`:", indefinite (explicit re-enable required)";return`provider "${t}" disabled for auto-nudge${n}${o}.
|
|
630
|
+
Every team whose resolved auto-nudge target uses "${t}" goes quiet; manual nudge/enqueue/lctl chat is unaffected.`}function Mb(e,t,r={}){let n=Mi(e.db.db,t)!==null;return Th(e.db.db,t),r.json?JSON.stringify({provider:t,disabled:!1}):n?`provider "${t}" re-enabled. Any team quiesced by it resumes on its own next-due check -- suppressed #195 reviews coalesce into one, covering everything since the shift began.`:`provider "${t}" was not disabled (no-op).`}function XM(e,t,r=Date.now()){return(t!==void 0?Go(e.db.db).filter(o=>o.provider===t):Go(e.db.db)).map(o=>({provider:o.provider,config:o,expired:!it(e.db.db,o.provider,r).disabled}))}function Pb(e,t,r={}){let n=XM(e,t);return r.json?JSON.stringify(n):n.length===0?t!==void 0?`${t}: not disabled.`:"no providers are currently disabled.":n.map(o=>{let s=o.config.reason?` (${o.config.reason})`:"",i=o.expired?", EXPIRED -- effectively re-enabled, run `provider enable` to clear the stale record":o.config.expiresAt!==null?`, auto-re-enables at ${o.config.expiresAt}`:", indefinite";return`${o.provider}: disabled since ${o.config.disabledAt}${s}${i}`}).join(`
|
|
631
|
+
`)}function eP(e,t){let r=e-t.readAt*1e3,n=t.resetsAtIso?Date.parse(t.resetsAtIso):NaN,o=Number.isFinite(n)&&n<e?e-n:null;return{ageMs:r,stale:r>9e5,expiredMs:o}}function tP(e,t,r,n){let o=Date.now(),s=Math.floor((o-18e5)/1e3),a=e.prepare(`SELECT used_fraction AS usedFraction, read_at AS readAt
|
|
632
|
+
FROM rate_limit_bucket_samples WHERE provider = ? AND bucket_id = ? AND resets_at = ? AND read_at >= ? ORDER BY read_at ASC`).all(t,r,n,s).map(m=>({readAt:m.readAt,usedFraction:m.usedFraction})),c=a.length>0?(a[a.length-1].readAt-a[0].readAt)*1e3:0,l=`samples=${a.length} span=${Math.round(c/1e3)}s (lookback ${Math.round(18e5/6e4)}m)`,u=Zi(a,o),d=u.kind==="insufficient_data"?`no-forecast: ${u.reason}`:u.kind==="no_forecast"?"no-forecast: flat or non-increasing usage":`forecastable: reaches 100% at ${new Date(u.forecastAtMs).toISOString()}`;return`${l} -- ${d}`}function Ub(e,t={}){let r=e.db.db,n=r.prepare(`SELECT r1.provider, r1.status, r1.source, r1.read_at, r1.reason, r1.detail
|
|
633
633
|
FROM rate_limit_readings r1
|
|
634
634
|
WHERE r1.id = (SELECT id FROM rate_limit_readings r2 WHERE r2.provider = r1.provider ORDER BY read_at DESC, id DESC LIMIT 1)
|
|
635
635
|
ORDER BY r1.provider`).all(),o=r.prepare(`SELECT s.provider, s.bucket_id AS bucketId, s.window_type AS windowType, s.used_fraction AS usedFraction,
|
|
@@ -641,37 +641,37 @@ Every team whose resolved auto-nudge target uses "${t}" goes quiet; manual nudge
|
|
|
641
641
|
ORDER BY read_at DESC, id DESC LIMIT 1
|
|
642
642
|
)
|
|
643
643
|
AND s.resets_at = (SELECT MAX(resets_at) FROM rate_limit_bucket_samples s3 WHERE s3.provider = s.provider AND s3.bucket_id = s.bucket_id)
|
|
644
|
-
ORDER BY s.provider, s.bucket_id`).all(),s=r.prepare("SELECT provider, bucket_id AS bucketId, resets_at AS resetsAt, rule, armed_at AS armedAt, forecast_at AS forecastAt FROM rate_limit_policy_arm ORDER BY provider, bucket_id").all(),i=ra(r),a=(()=>{if(i===null)return"policy: never run.";let d=Math.round((Date.now()-i.lastRunAtMs)/1e3),m=Object.entries(i.outcomeCounts).map(([f,p])=>`${p} ${f}`).join(", ")||"nothing to evaluate";return`policy: last ran ${new Date(i.lastRunAtMs).toISOString()} (${d}s ago), evaluated ${i.seriesEvaluated} series (${m}).`})(),c=Date.now(),l=o.map(d=>({...d,...
|
|
645
|
-
${a}`;let u=[a];for(let d of n){let m=new Date(d.read_at*1e3).toISOString();d.status==="ok"?u.push(`${d.provider}: ok (${d.source??"unknown source"}), last read ${m}`):u.push(`${d.provider}: ${d.status} (${d.reason??"no reason given"}), last read ${m}${d.detail?` -- ${d.detail}`:""}`);for(let f of l.filter(p=>p.provider===d.provider)){let p=s.find(E=>E.provider===f.provider&&E.bucketId===f.bucketId&&E.resetsAt===f.resetsAt),h=p?` [ARMED rule=${p.rule}, forecast ${new Date(p.forecastAt).toISOString()}]`:"",g=f.stale?` [STALE, read ${fe(f.ageMs)} ago]`:"",_=f.expiredMs!==null?` [WINDOW EXPIRED ${fe(f.expiredMs)} ago -- not a current reading]`:"";u.push(` ${f.bucketId} (${f.windowType}): used_fraction=${f.usedFraction} resets_at=${f.resetsAtIso??"unknown"}${g}${_}${h}`),u.push(` ${
|
|
646
|
-
`)}function
|
|
644
|
+
ORDER BY s.provider, s.bucket_id`).all(),s=r.prepare("SELECT provider, bucket_id AS bucketId, resets_at AS resetsAt, rule, armed_at AS armedAt, forecast_at AS forecastAt FROM rate_limit_policy_arm ORDER BY provider, bucket_id").all(),i=ra(r),a=(()=>{if(i===null)return"policy: never run.";let d=Math.round((Date.now()-i.lastRunAtMs)/1e3),m=Object.entries(i.outcomeCounts).map(([f,p])=>`${p} ${f}`).join(", ")||"nothing to evaluate";return`policy: last ran ${new Date(i.lastRunAtMs).toISOString()} (${d}s ago), evaluated ${i.seriesEvaluated} series (${m}).`})(),c=Date.now(),l=o.map(d=>({...d,...eP(c,d)}));if(t.json)return JSON.stringify({latestByProvider:n,series:l,armed:s,policyHeartbeat:i});if(n.length===0)return`rate-limit: no readings collected yet.
|
|
645
|
+
${a}`;let u=[a];for(let d of n){let m=new Date(d.read_at*1e3).toISOString();d.status==="ok"?u.push(`${d.provider}: ok (${d.source??"unknown source"}), last read ${m}`):u.push(`${d.provider}: ${d.status} (${d.reason??"no reason given"}), last read ${m}${d.detail?` -- ${d.detail}`:""}`);for(let f of l.filter(p=>p.provider===d.provider)){let p=s.find(E=>E.provider===f.provider&&E.bucketId===f.bucketId&&E.resetsAt===f.resetsAt),h=p?` [ARMED rule=${p.rule}, forecast ${new Date(p.forecastAt).toISOString()}]`:"",g=f.stale?` [STALE, read ${fe(f.ageMs)} ago]`:"",_=f.expiredMs!==null?` [WINDOW EXPIRED ${fe(f.expiredMs)} ago -- not a current reading]`:"";u.push(` ${f.bucketId} (${f.windowType}): used_fraction=${f.usedFraction} resets_at=${f.resetsAtIso??"unknown"}${g}${_}${h}`),u.push(` ${tP(r,f.provider,f.bucketId,f.resetsAt)}`)}}return u.join(`
|
|
646
|
+
`)}function Fb(e,t={}){let r=e.db.db,n=t.limit??20,o=t.provider?r.prepare(`SELECT ts, provider, bucket_id AS bucketId, window_type AS windowType, outcome, detail
|
|
647
647
|
FROM rate_limit_policy_log WHERE provider = ? ORDER BY ts DESC, id DESC LIMIT ?`).all(t.provider,n):r.prepare("SELECT ts, provider, bucket_id AS bucketId, window_type AS windowType, outcome, detail FROM rate_limit_policy_log ORDER BY ts DESC, id DESC LIMIT ?").all(n),s=ra(r);if(t.json)return JSON.stringify({rows:o,policyHeartbeat:s});if(o.length===0){let i=t.provider?` for ${t.provider}`:"";if(s===null)return`rate-limit log: empty${i} (policy has never run -- collection may be off, or --rate-limit-policy/--rate-limit-automation is not enabled).`;let a=Math.round((Date.now()-s.lastRunAtMs)/1e3);return`rate-limit log: empty${i} (policy last evaluated ${a}s ago, ${s.seriesEvaluated} series fleet-wide, nothing crossed a threshold).`}return o.map(i=>`${new Date(i.ts).toISOString()} ${i.provider}/${i.bucketId} (${i.windowType}) ${i.outcome}: ${i.detail}`).join(`
|
|
648
|
-
`)}var
|
|
648
|
+
`)}var rP=[7,30],fd=3,nP=20,oP="USD cost not computed -- lmbi's pricing engine is a governed per-snapshot process, not yet exposed as a reusable query surface; token totals shown instead";function sP(e){if(e.length===0)return null;let t=Math.floor(e.length/2);return e.length%2===0?(e[t-1]+e[t])/2:e[t]}function iP(e){if(e.length===0)return null;let t=Math.min(e.length-1,Math.ceil(e.length*.9)-1);return e[Math.max(0,t)]}function aP(e){return(e.tokens_in_cached??0)+(e.tokens_in_uncached??0)+(e.tokens_cache_write??0)+(e.tokens_out??0)}function cP(e,t,r){if(!r||t.sessionid===null||t.endedAtIso===null)return null;let n=e.prepare(`SELECT provider, sessionid, timestamp, tokens_in_cached, tokens_in_uncached, tokens_cache_write, tokens_out
|
|
649
649
|
FROM lmbi_session_responses
|
|
650
|
-
WHERE provider = ? AND sessionid = ? AND timestamp IS NOT NULL AND timestamp >= ? AND timestamp <= ?`).all(t.provider,t.sessionid,t.startedAtIso,t.endedAtIso);return n.length===0?null:n.reduce((o,s)=>o+
|
|
650
|
+
WHERE provider = ? AND sessionid = ? AND timestamp IS NOT NULL AND timestamp >= ? AND timestamp <= ?`).all(t.provider,t.sessionid,t.startedAtIso,t.endedAtIso);return n.length===0?null:n.reduce((o,s)=>o+aP(s),0)}function lP(e,t){return e.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(t)!==void 0}function qb(e){let t=e.filter(s=>s.outcome==="done").length,r=e.filter(s=>s.outcome==="failed").length,n=e.filter(s=>s.outcome==="contention").length,o=t+r;return{doneCount:t,failedCount:r,contentionCount:n,completionRate:o>0?t/o:null,sampleSize:e.length,lowConfidence:e.length<nP}}function jb(e){let t=e.nowMs??Date.now(),r=[],n={},o=lP(e.lmautoDb,"lmbi_session_responses");for(let s of rP){let i=new Date(t-s*24*60*60*1e3).toISOString(),{rows:a,skippedUnattributable:c}=kh(e.lctlDb,i);n[s]=c;let l=new Map;for(let d of a){let m=`${d.provider}\0${d.model??""}`,f=l.get(m)??{provider:d.provider,model:d.model,invocations:[]};f.invocations.push(d),l.set(m,f)}let u=t-fd*24*60*60*1e3;for(let d of l.values()){let m=d.invocations.filter(T=>T.outcome==="done"&&T.durationMs!==null).map(T=>T.durationMs).sort((T,R)=>T-R),f=qb(d.invocations),{doneCount:p,failedCount:h,contentionCount:g}=f,_=d.invocations.filter(T=>Date.parse(T.startedAtIso)>=u),E=qb(_),y=0,S=0;for(let T of d.invocations){if(T.outcome!=="done")continue;let R=cP(e.lmautoDb,T,o);R===null?S++:y+=R}r.push({provider:d.provider,model:d.model,windowDays:s,sampleSize:f.sampleSize,lowConfidence:f.lowConfidence,recentCompletionRate:E.completionRate,recentSampleSize:E.sampleSize,recentLowConfidence:E.lowConfidence,medianDurationMs:sP(m),p90DurationMs:iP(m),completionRate:f.completionRate,doneCount:p,failedCount:h,contentionCount:g,totalTokens:y,tokenJoinMisses:S,costUnavailableReason:oP})}}return{rows:r.sort((s,i)=>s.windowDays-i.windowDays||s.provider.localeCompare(i.provider)||(s.model??"").localeCompare(i.model??"")),skippedUnattributableByWindow:n}}function Hb(e,t={}){let r=Object.values(t).reduce((i,a)=>i+a,0);if(e.length===0)return r>0?`reliability report: no attributable chat dispatches found (${r} skipped as unattributable -- see tracked_invocation's own meta shape).`:"reliability report: no chat dispatches found in either window.";let n=[],o=null;for(let i of e){i.windowDays!==o&&(o=i.windowDays,n.push(`
|
|
651
651
|
-- ${i.windowDays}d reliability window --`));let a=i.model??"(default)",c=i.lowConfidence?`n=${i.sampleSize}, LOW CONFIDENCE`:`n=${i.sampleSize}`,l=i.completionRate===null?"completion rate unknown (no done/failed evidence)":`completion rate ${(i.completionRate*100).toFixed(1)}%`,u=i.recentCompletionRate===null?`last ${fd}d unknown (n=${i.recentSampleSize})`:`last ${fd}d ${(i.recentCompletionRate*100).toFixed(1)}%${i.recentLowConfidence?" LOW CONFIDENCE":""} (n=${i.recentSampleSize})`,d=i.medianDurationMs!==null?`median ${Math.round(i.medianDurationMs/1e3)}s / p90 ${Math.round(i.p90DurationMs/1e3)}s`:i.doneCount>0?"duration unknown (completed dispatch(es) recorded no end time)":"duration unknown (no completed dispatch)",m=i.tokenJoinMisses>0?` (${i.tokenJoinMisses} join miss(es), tokens undercounted)`:"";n.push(` ${i.provider}/${a} (${c}): ${l} [${u}], ${d}, ${i.totalTokens} tokens across ${i.doneCount} completed dispatch(es)${m} -- ${i.costUnavailableReason}`)}let s=Object.entries(t).filter(([,i])=>i>0).map(([i,a])=>`${a} unattributable dispatch(es) skipped in the ${i}d window`);return s.length>0&&n.push(`
|
|
652
652
|
(${s.join("; ")} -- see tracked_invocation's own meta shape)`),n.join(`
|
|
653
|
-
`).trimStart()}function
|
|
654
|
-
`).filter(d=>c.some(m=>d.includes(m))).filter(d=>!l.some(m=>d.includes(m)));return{lctlRunning:o,otherTeamsRunning:s,externalWrapperProcessLines:u}}function
|
|
653
|
+
`).trimStart()}function Bb(e,t={}){let r=Wn(t.lctlDbPath);try{let{rows:n,skippedUnattributableByWindow:o}=jb({lctlDb:r,lmautoDb:e.db.db});return t.json?JSON.stringify({rows:n,skippedUnattributableByWindow:o}):Hb(n,o)}finally{r.close()}}async function Wb(e,t={}){let r=await ed({configPath:e});return t.json?JSON.stringify(r):JSON.stringify(r,null,2)}import{execFile as uP}from"node:child_process";import{basename as dP}from"node:path";import{promisify as mP}from"node:util";var fP=mP(uP),pP=["lmplayer run","opencode run"];function hP(){return nn[nn.length-1]??"lmctl"}function gP(e){let t=e.lastIndexOf(":");if(t===-1)return[e];let r=e.slice(0,t),n=e.slice(t+1);return[e,`${dP(r)} ${n}`]}async function Gb(e,t=ke,r=fP){let n=(typeof e=="string"?[e]:e).filter(d=>d!==""),o;try{o=await t()}catch{o=null}let s=o===null?null:o.running.filter(d=>!n.includes(d.target??"")),i;try{i=(await r("ps",["aux"])).stdout}catch{i=""}let a=hP(),c=[`${a} chat`,`${a} terminal`,...pP],l=n.flatMap(gP),u=i.split(`
|
|
654
|
+
`).filter(d=>c.some(m=>d.includes(m))).filter(d=>!l.some(m=>d.includes(m)));return{lctlRunning:o,otherTeamsRunning:s,externalWrapperProcessLines:u}}function Vb(e){return(e.otherTeamsRunning?.length??0)>0||e.externalWrapperProcessLines.length>0}function _P(e){let t=process.env.LMBEE_TEAM_NAME;if(!t)return null;let r=e.teams.find(n=>n.name===t);if(r===void 0||!B(r))return null;try{return`${Q(r)}:${r.leadAlias}`}catch{return null}}async function Jb(e,t={}){let r=t.exclude===void 0?[]:typeof t.exclude=="string"?t.exclude.split(","):t.exclude,n=_P(e),o=n===null?r:[n,...r],i=await(t.checkInFlightDispatchImpl??Gb)(o),a=Vb(i);if(t.json)return JSON.stringify({inFlight:a,...i});if(!a)return"clear -- no other team's session or external wrapper process currently running.";let c=[];for(let u of i.otherTeamsRunning??[])c.push(` lmctl running: ${u.target??"(unknown target)"}`);for(let u of i.externalWrapperProcessLines)c.push(` process: ${u.trim()}`);let l=i.lctlRunning===null?"\n(note: `lmctl running --json` itself failed -- this reading is from the process scan alone)":"";return`IN FLIGHT -- hold the restart:
|
|
655
655
|
${c.join(`
|
|
656
|
-
`)}${l}`}import{readFileSync as
|
|
657
|
-
`)}function
|
|
658
|
-
`)}function
|
|
659
|
-
`).filter(o=>o.trim().length>0).length;return{head:t.trim().slice(0,48)||"(empty)",dirty:String(n)}}catch{return{head:"(no git)",dirty:"-"}}}function
|
|
660
|
-
${s}`;if(
|
|
656
|
+
`)}${l}`}import{readFileSync as wP,statSync as zb}from"node:fs";function Ca(e,t=wP){try{let r=t(`/proc/${e}/stat`,"utf8");return r.slice(r.lastIndexOf(")")+2).trim().split(/\s+/)[19]??null}catch{return null}}function yP(e,t=process.kill,r=Ca){let n;try{t(e.pid,0),n=!0}catch(s){n=s.code==="EPERM"}return n?e.startTicks===null?{alive:!0,identityVerified:!1}:r(e.pid)===e.startTicks?{alive:!0,identityVerified:!0}:{alive:!1,identityVerified:!0}:{alive:!1,identityVerified:e.startTicks!==null}}function EP(e,t=zb){let r=[],n=[],o=[];for(let s of e){let i;try{i=t(s).size}catch{o.push(s);continue}i>0?r.push(s):n.push(s)}return{complete:r,empty:n,missing:o}}function Kb(e,t,r=process.kill,n=Ca,o=zb){let s=yP(e,r,n),i=EP(t,o),a;return s.alive?a="running":t.length===0?a="unknown":i.missing.length===0&&i.empty.length===0?a="finished":i.complete.length>0||i.empty.length>0?a="finished-partial":a="unknown",{status:a,process:s,artifacts:i}}function Yb(e,t={}){let r=Ca(e);return t.json?JSON.stringify({pid:e,startTicks:r}):r===null?`could not capture an identity for pid ${e} -- process may not exist, or /proc is unavailable (non-Linux)`:`pid ${e} startTicks=${r} -- save this and pass it back as --start-ticks to \`dispatch-status check\` later`}function bP(e,t){let r=[`status: ${t.status}`];return r.push(`process: pid ${e}, alive=${t.process.alive}, identityVerified=${t.process.identityVerified}`),!t.process.identityVerified&&t.process.alive&&r.push(' (no start-ticks identity was given -- "alive" reflects raw pid existence only, PID reuse cannot be ruled out)'),t.artifacts.complete.length>0&&r.push(` complete: ${t.artifacts.complete.join(", ")}`),t.artifacts.empty.length>0&&r.push(` empty (exists, zero bytes): ${t.artifacts.empty.join(", ")}`),t.artifacts.missing.length>0&&r.push(` missing: ${t.artifacts.missing.join(", ")}`),r.join(`
|
|
657
|
+
`)}function Qb(e,t,r={}){let n=Kb({pid:e,startTicks:r.startTicks??null},t);return r.json?JSON.stringify({pid:e,...n}):bP(e,n)}function Xb(e,t,r,n,o={}){return wy(e.db.db,t,r,n),o.json?JSON.stringify({name:t,teamfilePath:r,alias:n}):`logical name "${t}" -> ${r}:${n}`}function Zb(e,t,r={}){let n=va(e.db.db,t);return r.json?JSON.stringify(n):n===null?`"${t}" is not registered`:`"${t}" -> ${n.teamfilePath}:${n.alias}`}function eT(e,t={}){let r=yy(e.db.db);return t.json?JSON.stringify(r):r.length===0?"no logical names registered":r.map(n=>`${n.name} -> ${n.teamfilePath}:${n.alias} (updated ${n.updatedAt})`).join(`
|
|
658
|
+
`)}function tT(e,t,r={}){let n=va(e.db.db,t)!==null;return Ey(e.db.db,t),r.json?JSON.stringify({name:t,cleared:n}):n?`logical name "${t}" cleared`:`"${t}" was not registered (no-op)`}import{execFile as TP}from"node:child_process";import{promisify as SP}from"node:util";var _r=Bt(Ct(),1),rT=SP(TP);async function vP(e){try{let[{stdout:t},{stdout:r}]=await Promise.all([rT("git",["-C",e,"log","--oneline","-1"],{timeout:1e4}),rT("git",["-C",e,"status","--porcelain"],{timeout:1e4})]),n=r.split(`
|
|
659
|
+
`).filter(o=>o.trim().length>0).length;return{head:t.trim().slice(0,48)||"(empty)",dirty:String(n)}}catch{return{head:"(no git)",dirty:"-"}}}function AP(e,t){return B(e)?je(e,t)?"Running":cn(e,t)?"Dead":"Idle":"remote -- delivery only"}async function nT(e,t={}){let n=await(t.fetchReport??ke)(),o=t.only&&t.only.length>0?new Set(t.only):null,s=o?e.teams.filter(c=>o.has(c.name)):e.teams,i=["TEAM","LIVE","STATUS(self-report)","PROGRESS","GIT-HEAD","UNCOMMITTED"],a=await Promise.all(s.map(async c=>{let l=qe(e.db.db,c.name),u=se(e.db.db,c.name),d=B(c)?await vP(c.repoPath):{head:"(remote)",dirty:"-"},m=u?.confirmed_done_ts?"DONE(confirmed)":u?.progress_status??"?";return[(0,_r.escapeCell)(c.name),(0,_r.escapeCell)(AP(c,n)),(0,_r.escapeCell)(l?.status??"?"),(0,_r.escapeCell)(m),(0,_r.escapeCell)(d.head),(0,_r.escapeCell)(d.dirty)]}));return(0,_r.formatTable)([i,...a])}var $P=8,kP=18e5;function pd(e){return e.teams.filter(B).filter(t=>t.autoNudge)}function xP(e){let t=pd(e);return t.length>0&&t.every(r=>se(e.db.db,r.name)?.confirmed_done_ts)}async function oT(e,t={}){let r=await bs(e.db.db,pd(e),t);return Ts(r)}async function sT(e,t={}){let r=t.maxScans??$P,n=t.scanIntervalMs??kP,o=t.sleep??(i=>new Promise(a=>setTimeout(a,i))),s="(no scans ran)";for(let i=1;i<=r;i++){let a=await bs(e.db.db,pd(e),t);if(s=Ts(a),a.wake)return`AUTOPILOT WAKE [${a.wake}]:
|
|
660
|
+
${s}`;if(xP(e))return`AUTOPILOT WAKE [all-done]:
|
|
661
661
|
${s}`;i<r&&await o(n)}return`AUTOPILOT WAKE [heartbeat]: exhausted ${r} scans with no wake condition
|
|
662
|
-
${s}`}function
|
|
663
|
-
(manual nudge and queue delivery are unaffected)`}function
|
|
664
|
-
(manual nudge and queue delivery are unaffected; \`lmbee scan start\` resumes)`}function
|
|
662
|
+
${s}`}function RP(e){let t=Ur(e.db.db);return{paused:t!==null,state:t}}function iT(e,t={}){let r=RP(e);if(t.json)return JSON.stringify(r);if(!r.paused)return"auto-scan: running (auto-continue nudges active)";let n=r.state;return`auto-scan: paused${` since ${n.paused_at}`+(n.actor!==null?`, by ${n.actor}`:"")+(n.note!==null?` -- ${n.note}`:"")+(n.resume_after!==null?` (resume_after: ${n.resume_after})`:"")}
|
|
663
|
+
(manual nudge and queue delivery are unaffected)`}function aT(e,t={}){let r={paused_at:new Date().toISOString(),actor:t.actor??null,note:t.note??null,resume_after:t.resumeAfter??null};if(r.resume_after!==null&&Number.isNaN(Date.parse(r.resume_after)))throw new Error(`--resume-after "${r.resume_after}" is not a parseable timestamp`);if(Dg(e.db.db,r),t.json)return JSON.stringify({paused:!0,state:r});let n=r.resume_after!==null?` (flagged stale if still paused past ${r.resume_after})`:"";return`auto-scan paused at ${r.paused_at}${n} -- the daemon stops auto-continue nudging within one tick.
|
|
664
|
+
(manual nudge and queue delivery are unaffected; \`lmbee scan start\` resumes)`}function cT(e,t={}){let r=Ur(e.db.db)!==null;return Mg(e.db.db),t.json?JSON.stringify({paused:!1,state:null}):r?"auto-scan resumed -- the daemon picks it up within one tick.":"auto-scan is already running (no pause was in effect)."}async function lT(e,t,r,n={}){let{baseId:o,alias:s}=an(t),i=e.teams.find(E=>E.name===o);if(!i)throw new Error(`send: unknown team "${o}"`);if(!B(i))throw new Error(`send: team "${o}" is a remote team (channel=lmmail) -- not reachable via lctl`);let a=s??i.leadAlias,c=Q(i),l=tn(i);if(l.length>0&&!l.some(E=>E.alias===a))throw new Error(`send: "${a}" is not a configured member of team "${o}" -- actual members: ${l.map(E=>E.alias).join(", ")}`);let u=qr("send",r,n.literal),d=n.send??Jt,m=n.probe??us,f=n.nowMs??Date.now(),p=await d({teamfilePath:c,alias:a},u),h=eo(p);if(mr(e.db.db,i.name,h.status,f),ot(e.db.db,i.name,h.status,f,{note:"send"}),h.status==="ENV-ERROR"||h.status==="NO-OUTPUT")try{(await m(c,a)).sessionResolves||sy(e.db.db,c,a,{kind:"evicted",remedy:`lctl refresh ${c} ${a}`})}catch{}else hs(e.db.db,c,a)!==null&&iy(e.db.db,c,a);let g=p.kind==="ok"?p.replyText.split(`
|
|
665
665
|
`).slice(-6).join(`
|
|
666
666
|
`):"";return`${a===i.leadAlias?i.name:`${i.name}:${a}`}: ${h.status}${g?`
|
|
667
|
-
${g}`:""}`}import{spawnSync as
|
|
668
|
-
(lctl takes a teamfile path; lmbee takes a team name)`,exitCode:1};let L=e.teams.filter(B).map(w=>w.name).sort();return{output:`terminal: "${o}" is not a known local team -- known local teams: ${L.length>0?L.join(", "):"(none configured)"}`,exitCode:1}}let u=c??l.leadAlias,d;try{d=Q(l)}catch(L){return{output:`terminal: could not resolve ${a}'s teamfile: ${L instanceof Error?L.message:String(L)}`,exitCode:1}}let m=n.pollIntervalMs??
|
|
667
|
+
${g}`:""}`}import{spawnSync as IP}from"node:child_process";var LP=2e3,CP=3e4;async function uT(e,t,r,n={}){let{baseId:o,alias:s}=an(t),i=o.endsWith(".lmctl")?o.slice(0,-6):null,a=i??o,c=r??s,l=e.teams.find(L=>L.name===a);if(l===void 0||!B(l)){if(i!==null)return{output:`terminal: "${o}" is not a known local team -- did you mean "${i}"?
|
|
668
|
+
(lctl takes a teamfile path; lmbee takes a team name)`,exitCode:1};let L=e.teams.filter(B).map(w=>w.name).sort();return{output:`terminal: "${o}" is not a known local team -- known local teams: ${L.length>0?L.join(", "):"(none configured)"}`,exitCode:1}}let u=c??l.leadAlias,d;try{d=Q(l)}catch(L){return{output:`terminal: could not resolve ${a}'s teamfile: ${L instanceof Error?L.message:String(L)}`,exitCode:1}}let m=n.pollIntervalMs??LP,f=n.leaseMs??6e4,p=n.maxWaitMs??CP,h=n.fetchReport??ke,g=n.spawnSyncImpl??IP,_=n.sleep??(L=>new Promise(w=>setTimeout(w,L))),E=n.now??Date.now,y=n.reason??null,S=n.pid??process.pid,T=E();if(Ef(e.db.db,a,u,S,new Date(T).toISOString(),y,f)===null){let L=Lc(e.db.db,a,u,T),w=L?`held by pid ${L.holderPid} since ${L.reservedAt}${L.reason?` (${L.reason})`:""}`:"held by another acquirer";return{output:`terminal: ${a}:${u} is already reserved -- ${w}`,exitCode:1}}let x=[`reserved ${a}:${u} -- no other automated dispatch (queue delivery, auto-scan, escalation) will claim it while this runs`],I=!1;try{for(;;){let L=await h();if(!tf(d,u,L))break;if(E()-T>=p){I=!0;break}await _(m)}}finally{Tf(e.db.db,a,u,S)}if(I)return x.push(`${a}:${u} is still busy after ${fe(p)} -- reservation released, try again`),{output:x.join(`
|
|
669
669
|
`),exitCode:1};x.push(`${a}:${u} is available -- launching terminal now (reservation released)`);let A=g("lmctl",["terminal",d,u],{stdio:"inherit"}),H=A.status??(A.error?1:0);return{output:x.join(`
|
|
670
|
-
`),exitCode:H}}import{readFileSync as
|
|
671
|
-
`).filter(a=>a.trim().length>0).map(a=>{let[c,l,...u]=a.split(" ");return{hash:c??"",date:l??"",subject:u.join(" ")}});return{...r,repoRoot:n,commits:i,checkError:null}}catch(s){let i=s instanceof Error?s.message:String(s);return{...r,repoRoot:n,commits:[],checkError:`could not check ${n}: ${i}`}}}function
|
|
670
|
+
`),exitCode:H}}import{readFileSync as hT}from"node:fs";import{basename as UP}from"node:path";import{execFileSync as dT}from"node:child_process";import{dirname as OP}from"node:path";var DP=new Set(["done","closed","cancelled"]);function MP(e){return e.trim().toLowerCase().replace(/[\s_]+/g,"-")}function PP(e){return OP(e)}function mT(e,t,r=dT){let n=Oe(e,t);return fT(n,r)}function fT(e,t){let r={id:e.id,title:e.title,status:e.status};if(DP.has(MP(e.status)))return{...r,repoRoot:null,commits:[],checkError:"already terminal -- nothing to audit"};if(e.owner_team_path===null)return{...r,repoRoot:null,commits:[],checkError:"unowned -- no repo to check"};let n=PP(e.owner_team_path),o=`#${e.id}([^0-9]|$)`;try{let i=t("git",["-C",n,"log","--oneline","--date=short","--pretty=format:%h %ad %s","-i","-E",`--grep=${o}`,`--since=${e.created_at}`],{encoding:"utf8"}).split(`
|
|
671
|
+
`).filter(a=>a.trim().length>0).map(a=>{let[c,l,...u]=a.split(" ");return{hash:c??"",date:l??"",subject:u.join(" ")}});return{...r,repoRoot:n,commits:i,checkError:null}}catch(s){let i=s instanceof Error?s.message:String(s);return{...r,repoRoot:n,commits:[],checkError:`could not check ${n}: ${i}`}}}function pT(e,t,r=dT){let n=Lr(e,t),o=[],s=i=>{o.push(i);for(let a of i.children)s(a)};return s(n),o.map(i=>fT(i,r))}var wT=["unassigned","clear-parent","clear-owner","attention","clear-blocked-on"];function Wr(e,t,r,n){let o=e[t],s=e[r];if(o!==void 0&&s!==void 0)throw new C("INVALID_ARGUMENT",`--${t} and --${r} are mutually exclusive`);if(typeof o=="string")return o;if(typeof s=="string"){if(s==="-"){if(n.used)throw new C("INVALID_ARGUMENT","At most one input may read stdin");n.used=!0;try{return hT(0,"utf8")}catch(i){throw new C("INPUT_ERROR",`Cannot read UTF-8 input from stdin: ${i instanceof Error?i.message:String(i)}`)}}try{return hT(s,"utf8")}catch(i){throw new C("INPUT_ERROR",`Cannot read UTF-8 input from ${s}: ${i instanceof Error?i.message:String(i)}`)}}}function rr(e,t,r={}){if(e===void 0)return;if(typeof e!="string"||!/^\d+$/.test(e))throw new C("INVALID_ARGUMENT",`${t} must be a nonnegative integer`);let n=Number(e),o=r.minimum??1;if(!Number.isSafeInteger(n)||n<o||r.maximum!==void 0&&n>r.maximum){let s=r.maximum!==void 0?`between ${o} and ${r.maximum}`:`>= ${o}`;throw new C("INVALID_ARGUMENT",`${t} must be an integer ${s}`)}return n}function tr(e,t){let r=rr(e,t,{minimum:1});if(r===void 0)throw new C("INVALID_ARGUMENT",`${t} is required`);return r}function Oa(e,t){let r=e[`${t}-team`],n=e[`${t}-alias`];if(!(r===void 0&&n===void 0)){if(r===void 0||n===void 0)throw new C("INVALID_ARGUMENT",`--${t}-team and --${t}-alias must both be given`);if(typeof r!="string"||typeof n!="string")throw new C("INVALID_ARGUMENT",`--${t}-team and --${t}-alias require values`);return{team:r,alias:n}}}function gT(e,t,r){let n=typeof e["blocked-on"]=="string"?e["blocked-on"]:void 0;if(n!==void 0&&n!=="operator"&&!t.some(o=>o.name===n))throw new C("INVALID_ARGUMENT",`--blocked-on "${n}" is not "operator" or a registered team name`);if(n!==void 0&&n!=="operator"&&r&&UP(r)===`${n}.lmctl`)throw new C("INVALID_ARGUMENT",`--blocked-on "${n}" is this task's own owner team -- a team cannot be blocked on itself`);return n}function _T(e){return e==="epic"||e==="task"||e==="subtask"}function Ot(e,t,r={}){return e?JSON.stringify({schema_version:1,ok:!0,data:t,meta:r}):qP(t,r)}function FP(e,t){return e?{output:JSON.stringify({schema_version:1,ok:!1,error:{code:t.code,message:t.message}}),exitCode:t.exitCode}:{output:`${t.code}: ${t.message}`,exitCode:t.exitCode}}function qP(e,t){let r;Array.isArray(e)?r=e.length===0?"(empty)":e.map(o=>o&&typeof o=="object"&&"title"in o?[..."attentionReason"in o?["attentionReason"]:[],"id","kind","status","project","title"].map(s=>String(o[s]??"")).join(" "):JSON.stringify(o)).join(`
|
|
672
672
|
`):typeof e=="string"?r=e:r=JSON.stringify(e,null,2);let n=t.next_cursor;return n!=null?`${r}
|
|
673
|
-
More records: --after ${String(n)}`:r}function
|
|
674
|
-
`)}var
|
|
673
|
+
More records: --after ${String(n)}`:r}function jP(e){return e.length===0?"(no non-terminal tasks in scope)":e.map(r=>{if(r.checkError!==null)return`#${r.id} [${r.status}] ${r.title} -- ${r.checkError}`;if(r.commits.length===0)return`#${r.id} [${r.status}] ${r.title} -- no commits mention #${r.id} in ${r.repoRoot} since it was created`;let n=r.commits[0];return`#${r.id} [${r.status}] ${r.title} -- POSSIBLY DONE: ${r.commits.length} commit(s) mention #${r.id} in ${r.repoRoot} since creation, most recent ${n.hash} (${n.date}) ${n.subject}`}).join(`
|
|
674
|
+
`)}var HP="usage: lmbee tasks create <epic|task|subtask> --title TEXT [--parent ID] [--project LABEL] [--status TEXT] [--blocked-on operator|TEAM] [--owner-team PATH --owner-alias ALIAS | --unassigned] (--blocked-on without --status implies --status blocked) | show ID | list [--project L] [--kind K] [--status S] [--parent ID] [--owner-team P --owner-alias A | --unassigned] [--limit N] [--after ID] | list --attention [--project L] | update ID [--title T] [--status S] [--parent ID | --clear-parent] [--owner-team P --owner-alias A | --clear-owner] [--if-revision N] [--blocked-on operator|TEAM | --clear-blocked-on] (--blocked-on without --status implies --status blocked) | tree ID | summary [ID] [--project L] | audit ID | audit --epic ID | note add ID --body T|--body-file P | note list ID | dep add|remove ID REQUIRED_ID | dep list ID [--direction D]";function yT(e,t,r,n,o=[]){try{let[s,...i]=t,a={used:!1};switch(s){case"create":{let c=i[0];if(c===void 0||!_T(c))throw new C("INVALID_ARGUMENT","create requires a kind: epic, task, or subtask");let l=r.title;if(typeof l!="string")throw new C("INVALID_ARGUMENT","--title is required");let u=Oa(r,"owner"),d=gT(r,o,u?.team),m=typeof r.status=="string"?r.status:void 0,f=tp(e,{kind:c,title:l,parentId:rr(r.parent,"--parent"),project:typeof r.project=="string"?r.project:void 0,status:m??(d!==void 0?"blocked":void 0),blockedOn:d,owner:u,unassigned:r.unassigned===!0,description:Wr(r,"description","description-file",a),requirements:Wr(r,"requirements","requirements-file",a),acceptanceCriteria:Wr(r,"acceptance-criteria","acceptance-criteria-file",a)});return{output:Ot(n,f),exitCode:0}}case"show":{let c=tr(i[0],"id");return{output:Ot(n,Ir(e,c)),exitCode:0}}case"tree":{let c=tr(i[0],"id");return{output:Ot(n,Lr(e,c)),exitCode:0}}case"list":{if(r.attention===!0){let m=typeof r.project=="string"?r.project:void 0,f=lp(e,{project:m});return{output:Ot(n,f),exitCode:0}}let c=Oa(r,"owner"),l=r.kind;if(l!==void 0&&(typeof l!="string"||!_T(l)))throw new C("INVALID_ARGUMENT","--kind must be epic, task, or subtask");let{rows:u,meta:d}=Nr(e,{project:typeof r.project=="string"?r.project:void 0,kind:typeof l=="string"?l:void 0,status:typeof r.status=="string"?r.status:void 0,parentId:rr(r.parent,"--parent"),owner:c,unassigned:r.unassigned===!0,limit:rr(r.limit,"--limit",{maximum:Le})??100,after:rr(r.after,"--after",{minimum:0})??0});return{output:Ot(n,u,d),exitCode:0}}case"audit":{let c=rr(r.epic,"--epic"),l=i[0];if(c===void 0==(l===void 0))throw new C("INVALID_ARGUMENT","audit requires exactly one of: an id, or --epic ID");let u=c!==void 0?pT(e,c):[mT(e,tr(l,"id"))];return n?{output:JSON.stringify({schema_version:1,ok:!0,data:u}),exitCode:0}:{output:jP(u),exitCode:0}}case"summary":{let c=i[0]!==void 0?tr(i[0],"id"):void 0,l=typeof r.project=="string"?r.project:void 0;return{output:Ot(n,Cr(e,{id:c,project:l})),exitCode:0}}case"update":{let c=tr(i[0],"id"),l=Oa(r,"owner"),u=rr(r.parent,"--parent");if(u!==void 0&&r["clear-parent"]===!0)throw new C("INVALID_ARGUMENT","--parent and --clear-parent are exclusive");let d=l?.team??(r["clear-owner"]===!0?null:Oe(e,c).owner_team_path),m=gT(r,o,d),f=typeof r.status=="string"?r.status:void 0,p=mi(e,c,{title:typeof r.title=="string"?r.title:void 0,status:f??(m!==void 0?"blocked":void 0),parentId:u,clearParent:r["clear-parent"]===!0,owner:l,clearOwner:r["clear-owner"]===!0,ifRevision:rr(r["if-revision"],"--if-revision"),description:Wr(r,"description","description-file",a),requirements:Wr(r,"requirements","requirements-file",a),acceptanceCriteria:Wr(r,"acceptance-criteria","acceptance-criteria-file",a),holdUntil:typeof r["hold-until"]=="string"?r["hold-until"]:void 0,holdReason:Wr(r,"hold-reason","hold-reason-file",a),clearHold:r["clear-hold"]===!0,blockedOn:m,clearBlockedOn:r["clear-blocked-on"]===!0});return{output:Ot(n,p),exitCode:0}}case"note":{let[c,...l]=i;if(c==="add"){let u=tr(l[0],"id"),d=Wr(r,"body","body-file",a);if(d===void 0)throw new C("INVALID_ARGUMENT","--body or --body-file is required");let m=Oa(r,"author");return{output:Ot(n,zt(e,u,{body:d,author:m})),exitCode:0}}if(c==="list"){let u=tr(l[0],"id"),{rows:d,meta:m}=Gc(e,u,{limit:rr(r.limit,"--limit",{maximum:Le})??100,after:rr(r.after,"--after",{minimum:0})??0});return{output:Ot(n,d,m),exitCode:0}}throw new C("INVALID_ARGUMENT","note requires add or list")}case"dep":{let[c,...l]=i;if(c==="add"||c==="remove"){let u=tr(l[0],"id"),d=tr(l[1],"required_id"),m=c==="add"?ap(e,u,d):cp(e,u,d);return{output:Ot(n,m),exitCode:0}}if(c==="list"){let u=tr(l[0],"id"),d=r.direction;if(d!==void 0&&d!=="outgoing"&&d!=="incoming"&&d!=="both")throw new C("INVALID_ARGUMENT","--direction must be outgoing, incoming, or both");return Oe(e,u),{output:Ot(n,mt(e,u,d??"outgoing")),exitCode:0}}throw new C("INVALID_ARGUMENT","dep requires add, remove, or list")}default:return{output:HP,exitCode:n?2:1}}}catch(s){if(s instanceof C)return FP(n,s);throw s}}var gt=Bt(Ct(),1);var BP=20;function WP(e,t,r={}){let n=zs(e.teams,t),o=r.limit??BP,s=Wu(e,{toId:t,limit:o}).rows,i=Wu(e,{fromId:t,limit:o}).rows,a=null;if(n.kind==="local"&&n.repoPath!==void 0&&n.leadAlias!==void 0)try{let c=Q({name:n.key,repoPath:n.repoPath});a=Re(e.db.db,c,n.leadAlias)?.entities??[]}catch{a=null}return{team:{key:n.key,kind:n.kind},messagesTo:s,messagesFrom:i,ownedTasks:a,invocationHistoryCoverage:"unavailable"}}function ET(e,t,r={}){let n=WP(e,t,r);if(r.json)return JSON.stringify(n);let o=[];o.push(`Team: ${n.team.key} (${n.team.kind})`);let s=[],i=n.messagesTo.map(u=>[String(u.id),(0,gt.escapeCell)(u.from_id),(0,gt.escapeCell)(u.status),ge(u.created_ts)]),a=n.messagesFrom.map(u=>[String(u.id),(0,gt.escapeCell)(u.to_id),(0,gt.escapeCell)(u.status),ge(u.created_ts)]),c=(n.ownedTasks??[]).map(u=>[String(u.id),(0,gt.escapeCell)(u.kind),(0,gt.escapeCell)(u.status),(0,gt.escapeCell)(u.title)]);i.length>0&&s.push({rows:i,headers:["ID","FROM","STATUS","CREATED"]}),a.length>0&&s.push({rows:a,headers:["ID","TO","STATUS","CREATED"]}),c.length>0&&s.push({rows:c,headers:["ID","KIND","STATUS","TITLE"]});let l=(0,gt.measureColumns)(s);return o.push(`
|
|
675
675
|
Messages to this team (queue, newest first):
|
|
676
676
|
${i.length===0?"(none)":(0,gt.renderGrid)(i,{widths:l,headers:["ID","FROM","STATUS","CREATED"]})}`),o.push(`
|
|
677
677
|
Messages from this team (queue, newest first):
|
|
@@ -679,9 +679,9 @@ ${a.length===0?"(none)":(0,gt.renderGrid)(a,{widths:l,headers:["ID","TO","STATUS
|
|
|
679
679
|
Owned tasks (lmtasks):
|
|
680
680
|
${n.ownedTasks===null?"(unavailable -- not a local team with a resolvable teamfile)":c.length===0?"(none)":(0,gt.renderGrid)(c,{widths:l,headers:["ID","KIND","STATUS","TITLE"]})}`),o.push(`
|
|
681
681
|
Provider/invocation/mail history: unavailable -- pending lctl-src's own increment-2 delivery (not silently omitted; this coverage state is explicit).`),o.join(`
|
|
682
|
-
`)}import{mkdirSync as
|
|
682
|
+
`)}import{mkdirSync as GP,readFileSync as VP,statSync as JP,writeFileSync as zP}from"node:fs";import{homedir as KP}from"node:os";import{basename as bT,dirname as TT,join as YP}from"node:path";function QP(){return YP(KP(),".lmbee","on-demand-teams.conf")}function ST(e,t,r,n={}){let o;try{o=JP(r)}catch{return{output:`error: teamfile not found: ${r}`,ok:!1}}if(!o.isFile())return{output:`error: teamfile must be a regular file, not a directory: ${r}`,ok:!1};if(bT(r)!==`${t}.lmctl`)return{output:`error: teamfile must be named "${t}.lmctl" to match team name "${t}" (got "${bT(r)}") -- resolveTeamfilePath's own convention, not a new rule`,ok:!1};let s=n.alias??"Lead",i=TT(r),a=n.confPath??QP(),c="";try{c=VP(a,"utf8")}catch{}let l=c.split(/\r?\n/).filter(g=>g.trim().length>0&&!g.trim().startsWith("#")),u=g=>g.split(/\t+/)[0]?.trim()===t,d=l.some(u),m=l.filter(g=>!u(g)),f=`${t} ${i} ${s} on-demand registered via "lmbee team register", ${new Date().toISOString().slice(0,10)}`,p=[...m,f].join(`
|
|
683
683
|
`)+`
|
|
684
|
-
`;return
|
|
684
|
+
`;return GP(TT(a),{recursive:!0}),zP(a,p),Ks(e.db.db,a,"on-demand teams (lmbee team register)"),Co(p).some(g=>g.name===t)?{output:`team ${d?"re-registered":"registered"}: ${t} (teamfile ${r}, alias ${s}) -- addressable via enqueue/chat now, on-demand (no standing auto-nudge)`,ok:!0}:{output:`error: wrote ${a} but the team did not parse back out -- not registered`,ok:!1}}async function vT(e,t={}){let n=await(t.fetchReport??ke)(),o=Xs(e.db.db,e.teams.filter(B),n),s=o.active.length?o.active.join(","):"(none)";if(o.wake)return{text:`WATCH CHANGE [${o.why}] | now-active: ${s}`,changed:!0};let i=o.newlyActive.length?` (newly-active: ${o.newlyActive.join(",")})`:"";return{text:`WATCH nochange | active: ${s}${i}`,changed:!1}}var Gr=`usage: lmbee <command> [args]
|
|
685
685
|
|
|
686
686
|
Core loop:
|
|
687
687
|
lmbee run | once | watch
|
|
@@ -837,7 +837,7 @@ Daemon:
|
|
|
837
837
|
[--remote-mail --remote-allow user_id1,user_id2,...]
|
|
838
838
|
[--exec-worker [--exec-mailbox name] [--exec-admin id1,id2,...] [--exec-allow id1,id2,...] [--exec-allow-anonymous]]
|
|
839
839
|
lmbee shutdown --force (graceful stop of the systemd-managed daemon: systemctl --user stop lmbee.service --
|
|
840
|
-
--force is required; the unconfirmed default refuses rather than acting)`;function
|
|
840
|
+
--force is required; the unconfirmed default refuses rather than acting)`;function kT(e){if(e.length===0)return!0;let[t,r]=e;return t==="-h"||t==="--help"||t==="help"?!0:r==="-h"||r==="--help"}var XP=new Set(["status","oversee","history","teams","attention","stalled","in-flight"]);function xT(e){let[t,r]=e;return XP.has(t)?!0:t==="team"?r!=="register"&&e.includes("--timeline"):t==="state"?r==="list"||r==="get"||r==="active":t==="queue"?r==="list"||r==="get"||r==="inbox"||r==="stats"||r==="redeliver-check"||r==="pause-status"||r==="owed"||r==="close-answered"||r==="pull":t==="source"?r==="list":t==="mail"||t==="scan"||t==="auto-nudge-redirect"||t==="provider"?r==="status":t==="dispatch-status"?!0:t==="logical-name"?r==="get"||r==="list":t==="tasks"?r==="show"||r==="list"||r==="tree"||r==="summary"?!0:r==="note"||r==="dep"?e[2]==="list":!1:t==="cron"?r==="show"||r==="list"||r==="runs"||r==="run"||r==="export":t==="prompt"?r==="log"||r==="tasks"||r==="reassignments":!1}var AT=`usage: lmbee queue <command> [args]
|
|
841
841
|
|
|
842
842
|
Read: inbox <to> [--prompts] prompts waiting for a team (authoritative)
|
|
843
843
|
list [team] all rows, optionally filtered
|
|
@@ -863,62 +863,62 @@ Close: answer <id[,id,...]> <text|@file> --from <team>
|
|
|
863
863
|
Control: pause <team> [--reason <text>] | resume <team> | pause-status [<team>]
|
|
864
864
|
gc [days]
|
|
865
865
|
|
|
866
|
-
Pass --help after any subcommand for its own usage line, e.g. "lmbee queue list --help"
|
|
866
|
+
Pass --help after any subcommand for its own usage line, e.g. "lmbee queue list --help".`,$T={list:{usage:"usage: lmbee queue list [team] [--json]",allowedFlags:["json"]},get:{usage:"usage: lmbee queue get <id> [--json]",allowedFlags:["json"]},deliver:{usage:"usage: lmbee queue deliver [team]",allowedFlags:[]},retrieve:{usage:"usage: lmbee queue retrieve <to> [--id <queueId>]",allowedFlags:["id"]},inbox:{usage:"usage: lmbee queue inbox <to> [--prompts] [--json]",allowedFlags:["prompts","json"]},gc:{usage:"usage: lmbee queue gc [days]",allowedFlags:[]},stats:{usage:"usage: lmbee queue stats [to] [--json]",allowedFlags:["json"]},state:{usage:"usage: lmbee queue state <id> [--json]",allowedFlags:["json"]},answer:{usage:"usage: lmbee queue answer <id[,id,...]> <text|@file> --from <team> [--amend] [--literal] [--json]",allowedFlags:["from","literal","amend","json"]},retract:{usage:"usage: lmbee queue retract <id> --from <team> --reason <text> [--no-notice] [--json]",allowedFlags:["from","reason","no-notice","json"]},resolve:{usage:"usage: lmbee queue resolve <id> --from <proxyTeam> --reason <text> [--amend] [--literal] [--json]",allowedFlags:["from","reason","literal","amend","json"]},pause:{usage:"usage: lmbee queue pause <team> [--reason <text>] [--json]",allowedFlags:["reason","json"]},resume:{usage:"usage: lmbee queue resume <team> [--json]",allowedFlags:["json"]},"pause-status":{usage:"usage: lmbee queue pause-status [team] [--json]",allowedFlags:["json"]},owed:{usage:"usage: lmbee queue owed <team> [--ids] [--json]",allowedFlags:["ids","json"]},pull:{usage:"usage: lmbee queue pull [id id ...] [--from <team>] [--all] [--open] [--mark [id,id,...]] [--json] [--full]",allowedFlags:["from","all","open","mark","json","full"]},"close-answered":{usage:"usage: lmbee queue close-answered <team> [--ids] [--json]",allowedFlags:["ids","json"]},"redeliver-check":{usage:"usage: lmbee queue redeliver-check <team> [--json]",allowedFlags:["json"]},redeliver:{usage:"usage: lmbee queue redeliver <id> --reason <text> [--json]",allowedFlags:["reason","json"]},doctor:{usage:"usage: lmbee queue doctor [toId] [--repair] [--swallowed] [--json]",allowedFlags:["repair","swallowed","json"]}};async function RT(e,t){if(t.length===0)return{output:`${Gr}
|
|
867
867
|
`,exitCode:0};let[r,...n]=t,{positionals:o,flags:s}=St(n,["live","json","timeline","stuck-processing-all","ids","prompts","literal","amend","help","no-notice"]),i=s.json===!0;if(s.help===!0&&r!=="queue")return{output:`${Gr}
|
|
868
|
-
`,exitCode:0};switch(r){case"run":return{output:await
|
|
868
|
+
`,exitCode:0};switch(r){case"run":return{output:await sT(e),exitCode:0};case"once":return{output:await oT(e),exitCode:0};case"watch":{let a=await vT(e);return{output:a.text,exitCode:a.changed?10:0}}case"status":return{output:await aE(e,{live:s.live===!0,json:i}),exitCode:0};case"oversee":return{output:await nT(e,{only:o}),exitCode:0};case"state":{let[a,...c]=o;return a==="list"?{output:tE(e,{json:i,nonDone:s["non-done"]===!0}),exitCode:0}:a==="get"?c[0]===void 0?X("usage: lmbee state get <team>"):{output:rE(e,c[0],{json:i}),exitCode:0}:a==="set"?c[0]===void 0||c[1]===void 0?X("usage: lmbee state set <team> <status> [note]"):{output:nE(e,c[0],c[1],c.slice(2).join(" ")),exitCode:0}:a==="active"?{output:iE(e,{json:i}),exitCode:0}:a==="confirm-done"?c[0]===void 0?X("usage: lmbee state confirm-done <team> [note]"):{output:oE(e,c[0],c.slice(1).join(" ")||void 0),exitCode:0}:a==="reopen"?c[0]===void 0?X("usage: lmbee state reopen <team> [note]"):{output:await sE(e,c[0],c.slice(1).join(" ")||void 0),exitCode:0}:X("usage: lmbee state list | get <team> | set <team> <status> [note] | confirm-done <team> [note] | reopen <team> [note] | active")}case"enqueue":{let[a,...c]=o,l="usage: lmbee enqueue <team>[:<alias>] <prompt|@file> --from <operator|team-name> [--expects-response true|false] [--in-reply-to <id>] [--literal]";if(a===void 0||c.length===0)return X(l);let u=typeof s.from=="string"?s.from:void 0;if(u===void 0)return X(l);if(u==="autopilot")return X("enqueue: --from 'autopilot' is reserved for the tool's own automated enqueues");let d;if(s["expects-response"]!==void 0)if(s["expects-response"]==="true")d=!0;else if(s["expects-response"]==="false")d=!1;else return X(`enqueue: --expects-response must be "true" or "false"; ${l}`);let m;if(s["in-reply-to"]!==void 0){let f=Number(s["in-reply-to"]);if(typeof s["in-reply-to"]!="string"||!Number.isInteger(f)||f<=0)return X(`enqueue: --in-reply-to must be a positive integer queue id; ${l}`);m=f}return{output:await Ny(e,a,c.join(" "),{from:u,...d!==void 0?{expectsResponse:d}:{},...m!==void 0?{inReplyTo:m}:{},...s.literal===!0?{literal:!0}:{}}),exitCode:0}}case"prompt":{let a='usage: lmbee prompt <to> <prompt|@file> --from <id> [--new-task "title" [--task-description TEXT] | --task <id>] [--literal] | lmbee prompt log <task-id> [--json] | lmbee prompt tasks <team> [--json] | lmbee prompt reassign <prompt-id> --task <task-id> --by <id> | lmbee prompt reassignments <prompt-id> [--json]';if(o[0]==="tasks"){let p=o[1];return p===void 0?X(`prompt tasks: requires a team id; ${a}`):{output:Ib(e,p,{json:s.json===!0}),exitCode:0}}if(o[0]==="log"){let p=o[1],h=p!==void 0?Number(p):NaN;return p===void 0||!Number.isInteger(h)||h<=0?X(`prompt log: requires a positive integer task id; ${a}`):{output:Lb(e,h,{json:s.json===!0}),exitCode:0}}if(o[0]==="reassign"){let p=o[1],h=p!==void 0?Number(p):NaN;if(p===void 0||!Number.isInteger(h)||h<=0)return X(`prompt reassign: requires a positive integer prompt id; ${a}`);let g=typeof s.task=="string"?Number(s.task):NaN;if(typeof s.task!="string"||!Number.isInteger(g)||g<=0)return X(`prompt reassign: --task must be a positive integer task id; ${a}`);let _=typeof s.by=="string"?s.by:void 0;return _===void 0?X(`prompt reassign: --by is required; ${a}`):{output:Cb(e,h,g,{by:_}),exitCode:0}}if(o[0]==="reassignments"){let p=o[1],h=p!==void 0?Number(p):NaN;return p===void 0||!Number.isInteger(h)||h<=0?X(`prompt reassignments: requires a positive integer prompt id; ${a}`):{output:Ob(e,h,{json:s.json===!0}),exitCode:0}}let[c,...l]=o;if(c===void 0||l.length===0)return X(a);let u=typeof s.from=="string"?s.from:void 0;if(u===void 0)return X(a);let d=typeof s["new-task"]=="string"?s["new-task"]:void 0,m=typeof s["task-description"]=="string"?s["task-description"]:void 0,f;if(s.task!==void 0){let p=Number(s.task);if(typeof s.task!="string"||!Number.isInteger(p)||p<=0)return X(`prompt: --task must be a positive integer task id; ${a}`);f=p}return{output:Nb(e,c,l.join(" "),{from:u,...d!==void 0?{newTaskTitle:d}:{},...m!==void 0?{newTaskDescription:m}:{},...f!==void 0?{taskId:f}:{},...s.literal===!0?{literal:!0}:{}}),exitCode:0}}case"queue":{let[a,...c]=o,l=a!==void 0?$T[a]:void 0;if(l!==void 0){if(s.help===!0)return{output:`${l.usage}
|
|
869
869
|
`,exitCode:0};let u=new Set(["help",...l.allowedFlags]),d=Object.keys(s).find(m=>!u.has(m));if(d!==void 0)return X(`queue ${a}: unknown flag --${d}
|
|
870
|
-
${l.usage}`)}if(a==="list")return{output:
|
|
871
|
-
usage: lmbee queue retrieve <to> [--id <queueId>]`):{output:
|
|
872
|
-
${m}`);let g=u.split(",").map(Number);return
|
|
870
|
+
${l.usage}`)}if(a==="list")return{output:Iy(e,c[0],{json:i}),exitCode:0};if(a==="get")return c[0]===void 0?X("usage: lmbee queue get <id>"):{output:Ly(e,Number(c[0]),{json:i}),exitCode:0};if(a==="deliver")return{output:await By(e,c[0]),exitCode:0};if(a==="retrieve"){if(c[0]===void 0)return X("usage: lmbee queue retrieve <to> [--id <queueId>]");let u=s.id;return u!==void 0&&(typeof u!="string"||!/^\d+$/.test(u)||!Number.isSafeInteger(Number(u))||Number(u)<=0)?X(`queue retrieve: --id must be a positive integer
|
|
871
|
+
usage: lmbee queue retrieve <to> [--id <queueId>]`):{output:Wy(e,c[0],u===void 0?{}:{id:Number(u)}),exitCode:0}}if(a==="inbox")return c[0]===void 0?X("usage: lmbee queue inbox <to> [--prompts]"):{output:Gy(e,c[0],{json:i,promptsOnly:s.prompts===!0}),exitCode:0};if(a==="gc")return{output:Yy(e,c[0]!==void 0?Number(c[0]):void 0),exitCode:0};if(a==="stats")return{output:Ky(e,c[0],{json:i}),exitCode:0};if(a==="doctor")return{output:Qy(e,c[0],{repair:s.repair===!0,swallowed:s.swallowed===!0,json:i}),exitCode:0};if(a==="state")return c[0]===void 0?X("usage: lmbee queue state <id>"):{output:Cy(e,Number(c[0]),{json:i}),exitCode:0};if(a==="answer"){let[u,...d]=c,m="usage: lmbee queue answer <id[,id,...]> <text|@file> --from <team> [--amend] [--literal]";if(u===void 0||d.length===0)return X(m);let f=typeof s.from=="string"?s.from:void 0;if(f===void 0)return X(m);let p=s.literal===!0,h=s.amend===!0;if(u.includes(",")){if(h)return X(`queue answer: --amend does not support a comma-separated id list
|
|
872
|
+
${m}`);let g=u.split(",").map(Number);return Dy(e,g,f,d.join(" "),{json:i,literal:p})}return Oy(e,Number(u),f,d.join(" "),{json:i,literal:p,amend:h})}if(a==="retract"){let[u,...d]=c,m="usage: lmbee queue retract <id> --from <team> --reason <text> [--no-notice]";if(u===void 0)return X(m);let f=typeof s.from=="string"?s.from:void 0,h=(typeof s.reason=="string"?s.reason:void 0)??(d.length>0?d.join(" "):void 0);return f===void 0||h===void 0?X(m):Py(e,Number(u),f,h,{json:i,noNotice:s["no-notice"]===!0})}if(a==="resolve"){let[u,...d]=c,m="usage: lmbee queue resolve <id> --from <proxyTeam> --reason <text> [--amend] [--literal]";if(u===void 0)return X(m);let f=typeof s.from=="string"?s.from:void 0,h=(typeof s.reason=="string"?s.reason:void 0)??(d.length>0?d.join(" "):void 0);return f===void 0||h===void 0?X(m):My(e,Number(u),f,h,{json:i,literal:s.literal===!0,amend:s.amend===!0})}if(a==="pause"){if(c[0]===void 0)return X("usage: lmbee queue pause <team> [--reason <text>]");let u=typeof s.reason=="string"?s.reason:void 0;return qy(e,c[0],u,{json:i})}if(a==="resume")return c[0]===void 0?X("usage: lmbee queue resume <team>"):jy(e,c[0],{json:i});if(a==="pause-status")return Hy(e,c[0],{json:i});if(a==="owed")return c[0]===void 0?X("usage: lmbee queue owed <team> [--ids]"):{output:Vy(e,c[0],{json:i,idsOnly:s.ids===!0}),exitCode:0};if(a==="pull"){let u=$T.pull.usage,d=typeof s.from=="string"?s.from:process.env.LMBEE_TEAM_NAME;if(d===void 0)return X(`queue pull: cannot infer the calling team -- pass --from <team> or set LMBEE_TEAM_NAME
|
|
873
873
|
${u}`);let m;if(c.length>0&&(m=c.map(Number),m.some(p=>!Number.isInteger(p)||p<=0)))return X(`queue pull: prompt ids must be positive integers
|
|
874
874
|
${u}`);let f;if(s.mark!==void 0)if(typeof s.mark!="string")f=!0;else{let p=s.mark.split(",").map(Number);if(p.some(h=>!Number.isInteger(h)||h<=0))return X(`queue pull: --mark ids must be a comma-separated list of positive integers
|
|
875
|
-
${u}`);f=p}return{output:
|
|
876
|
-
`,exitCode:0}:X(
|
|
877
|
-
`),exitCode:0}}case"team":{if(o[0]==="register"){let l=o[1],u=typeof s.teamfile=="string"?s.teamfile:void 0;if(l===void 0||u===void 0)return X("usage: lmbee team register <name> --teamfile <path> [--alias <alias>]");let d=typeof s.alias=="string"?s.alias:void 0,m=
|
|
878
|
-
${Gr}`,exitCode:1}}}function X(e){return{output:e,exitCode:1}}import{mkdir as
|
|
875
|
+
${u}`);f=p}return{output:zy(e,d,{...m!==void 0?{ids:m}:{},all:s.all===!0,open:s.open===!0,...f!==void 0?{mark:f}:{},json:i,full:s.full===!0}),exitCode:0}}if(a==="close-answered")return c[0]===void 0?X("usage: lmbee queue close-answered <team> [--ids]"):{output:Jy(e,c[0],{json:i,idsOnly:s.ids===!0}),exitCode:0};if(a==="redeliver-check")return c[0]===void 0?X("usage: lmbee queue redeliver-check <team>"):Uy(e,c[0],{json:i});if(a==="redeliver"){let[u,...d]=c,m="usage: lmbee queue redeliver <id> --reason <text>";if(u===void 0)return X(m);let p=(typeof s.reason=="string"?s.reason:void 0)??(d.length>0?d.join(" "):void 0);return p===void 0?X(m):Fy(e,Number(u),p,{json:i})}return s.help===!0?{output:`${AT}
|
|
876
|
+
`,exitCode:0}:X(AT)}case"nudge":return o.length===0?X("usage: lmbee nudge <team> [team2 ...]"):{output:await $b(e,o),exitCode:0};case"send":{let[a,...c]=o;return a===void 0||c.length===0?X("usage: lmbee send <team> <prompt|@file> [--literal]"):{output:await lT(e,a,c.join(" "),{literal:s.literal===!0}),exitCode:0}}case"terminal":{let[a,c]=o;if(a===void 0)return X("usage: lmbee terminal <team>[:<alias>] [<alias>] [--reason <text>]");let l=typeof s.reason=="string"?s.reason:void 0;return uT(e,a,c,{reason:l})}case"history":{let a=o[0]!==void 0&&/^\d+$/.test(o[0]),c=a?void 0:o[0],l=a?o[0]:o[1];return{output:ry(e,c,l,{json:i}),exitCode:0}}case"teams":return{output:cE(e,{json:i}),exitCode:0};case"in-flight":{let a=typeof s.exclude=="string"?s.exclude:void 0;return{output:await Jb(e,{...a!==void 0?{exclude:a}:{},json:i}),exitCode:0}}case"dispatch-status":{let[a]=o,c=typeof s.pid=="string"?Number.parseInt(s.pid,10):NaN;if(Number.isNaN(c))return X("usage: lmbee dispatch-status capture --pid N | check --pid N [--start-ticks T] --artifacts P1,P2,...");if(a==="capture")return{output:Yb(c,{json:i}),exitCode:0};if(a==="check"){let l=typeof s.artifacts=="string"?s.artifacts.split(",").map(d=>d.trim()).filter(d=>d.length>0):[],u=typeof s["start-ticks"]=="string"?s["start-ticks"]:void 0;return{output:Qb(c,l,{...u!==void 0?{startTicks:u}:{},json:i}),exitCode:0}}return X("usage: lmbee dispatch-status capture --pid N | check --pid N [--start-ticks T] --artifacts P1,P2,...")}case"logical-name":{let[a,c]=o;if(a==="set"){let l=typeof s.teamfile=="string"?s.teamfile:void 0,u=typeof s.alias=="string"?s.alias:void 0;if(c===void 0||l===void 0||u===void 0)return X("usage: lmbee logical-name set <name> --teamfile PATH --alias ALIAS");try{return{output:Xb(e,c,l,u,{json:i}),exitCode:0}}catch(d){return{output:d instanceof Error?d.message:String(d),exitCode:1}}}return a==="get"?c===void 0?X("usage: lmbee logical-name get <name>"):{output:Zb(e,c,{json:i}),exitCode:0}:a==="list"?{output:eT(e,{json:i}),exitCode:0}:a==="clear"?c===void 0?X("usage: lmbee logical-name clear <name>"):{output:tT(e,c,{json:i}),exitCode:0}:X("usage: lmbee logical-name set <name> --teamfile PATH --alias ALIAS | get <name> | list | clear <name>")}case"attention":{let a=typeof s.team=="string"?s.team:void 0,c=typeof s.maintainer=="string"?s.maintainer:void 0,l=s["stuck-processing-all"]===!0,u=await ha(e,{team:a,maintainer:c,stuckProcessingFleetWide:l});return{output:ms(u,{json:i}),exitCode:0}}case"stalled":{if(o.length>1)return X("usage: lmbee stalled [team] [--json]");let a=lo(s["idle-threshold-ms"],"--idle-threshold-ms"),c=lo(s["cooldown-ms"],"--cooldown-ms");if(a instanceof Error)return X(a.message);if(c instanceof Error)return X(c.message);let l=await yb(e,{team:o[0],config:{idleThresholdMs:a??he.idleThresholdMs,cooldownMs:c??he.cooldownMs}});return{output:i?JSON.stringify(l):l.teams.map(({team:u,stalled:d})=>`${u} ${d}`).join(`
|
|
877
|
+
`),exitCode:0}}case"team":{if(o[0]==="register"){let l=o[1],u=typeof s.teamfile=="string"?s.teamfile:void 0;if(l===void 0||u===void 0)return X("usage: lmbee team register <name> --teamfile <path> [--alias <alias>]");let d=typeof s.alias=="string"?s.alias:void 0,m=ST(e,l,u,{alias:d});return{output:m.output,exitCode:m.ok?0:1}}let[a]=o;if(a===void 0||s.timeline!==!0)return X("usage: lmbee team <name> --timeline [--limit N] | lmbee team register <name> --teamfile <path> [--alias <alias>]");let c=lo(s.limit,"--limit");return c instanceof Error?{output:`error: ${c.message}`,exitCode:1}:c!==void 0&&(c<1||c>Mo)?{output:`error: --limit must be a positive integer <= ${Mo}`,exitCode:1}:{output:ET(e,a,{limit:c,json:i}),exitCode:0}}case"source":{let[a,...c]=o;if(a==="add"){if(c[0]===void 0)return X("usage: lmbee source add <path> [label...]");let l=$a(e,c[0],c.slice(1).join(" ")||void 0);return{output:l.output,exitCode:l.ok?0:1}}return a==="list"?{output:Xy(e,{json:i}),exitCode:0}:a==="remove"?c[0]===void 0?X("usage: lmbee source remove <path>"):{output:Zy(e,c[0]),exitCode:0}:X("usage: lmbee source add <path> [label...] | list | remove <path>")}case"mail":{let[a]=o;return a==="status"?{output:oy(e,{json:i}),exitCode:0}:X("usage: lmbee mail status")}case"scan":{let[a]=o;if(a==="status")return{output:iT(e,{json:i}),exitCode:0};if(a==="pause"){let c=typeof s.actor=="string"?s.actor:void 0,l=typeof s.note=="string"?s.note:void 0,u=typeof s["resume-after"]=="string"?s["resume-after"]:void 0;return{output:aT(e,{...c!==void 0?{actor:c}:{},...l!==void 0?{note:l}:{},...u!==void 0?{resumeAfter:u}:{},json:i}),exitCode:0}}return a==="start"?{output:cT(e,{json:i}),exitCode:0}:X("usage: lmbee scan pause [--actor NAME] [--note TEXT] [--resume-after ISO] | start | status")}case"auto-nudge-redirect":{let[a,c]=o;if(a==="status")return{output:Rb(e,c,{json:i}),exitCode:0};if(a==="clear")return c===void 0?X("usage: lmbee auto-nudge-redirect clear <team>"):{output:xb(e,c,{json:i}),exitCode:0};if(a==="set"){if(c===void 0||typeof s.companion!="string")return X("usage: lmbee auto-nudge-redirect set <team> --companion <team> [--worker-alias A] [--commit-threshold N] [--hours-threshold-ms N]");let l=typeof s["worker-alias"]=="string"?s["worker-alias"]:void 0,u=typeof s["commit-threshold"]=="string"?Number.parseInt(s["commit-threshold"],10):void 0,d=typeof s["hours-threshold-ms"]=="string"?Number.parseInt(s["hours-threshold-ms"],10):void 0;return{output:kb(e,c,{companionTeam:s.companion,...l!==void 0?{workerAlias:l}:{},...u!==void 0&&!Number.isNaN(u)?{commitThreshold:u}:{},...d!==void 0&&!Number.isNaN(d)?{hoursThresholdMs:d}:{},json:i}),exitCode:0}}return X("usage: lmbee auto-nudge-redirect set <team> --companion <team> [...] | clear <team> | status [<team>]")}case"provider":{let[a,c]=o;if(a==="status")return{output:Pb(e,c,{json:i}),exitCode:0};if(a==="enable")return c===void 0?X("usage: lmbee provider enable <name>"):{output:Mb(e,c,{json:i}),exitCode:0};if(a==="disable"){if(c===void 0)return X("usage: lmbee provider disable <name> [--reason TEXT] [--expires-at ISO]");let l=typeof s.reason=="string"?s.reason:void 0,u=typeof s["expires-at"]=="string"?s["expires-at"]:void 0;return{output:Db(e,c,{...l!==void 0?{reason:l}:{},...u!==void 0?{expiresAt:u}:{},json:i}),exitCode:0}}return X("usage: lmbee provider disable <name> [--reason TEXT] [--expires-at ISO] | enable <name> | status [<name>]")}case"rate-limit":{let[a]=o;if(a==="status")return{output:Ub(e,{json:i}),exitCode:0};if(a==="log"){let c=typeof s.provider=="string"?s.provider:void 0,l=typeof s.limit=="string"?Number.parseInt(s.limit,10):void 0,u=l!==void 0&&!Number.isNaN(l)?l:void 0;return{output:Fb(e,{...c!==void 0?{provider:c}:{},...u!==void 0?{limit:u}:{},json:i}),exitCode:0}}return X("usage: lmbee rate-limit status | log [--provider NAME] [--limit N]")}case"reliability-report":try{return{output:Bb(e,{json:i}),exitCode:0}}catch(a){return{output:`reliability-report: ${a instanceof Error?a.message:String(a)}`,exitCode:1}}case"subscriptions":{let a=typeof s.config=="string"?s.config:void 0;if(a===void 0)return X("usage: lmbee subscriptions --config <path> [--json]");try{return{output:await Wb(a,{json:i}),exitCode:0}}catch(c){return{output:`subscriptions: ${c instanceof Error?c.message:String(c)}`,exitCode:1}}}case"tasks":{let a=St(n,["json",...wT]),c=yT(e.db.db,a.positionals,a.flags,a.flags.json===!0||i,e.teams);return{output:c.output,exitCode:c.exitCode}}case"cron":{let a=St(n,["json",...vb]),c=await Sb(e.db.db,a.positionals,a.flags,a.flags.json===!0||i,e.teams);return{output:c.output,exitCode:c.exitCode}}default:return{output:`unknown command: ${r}
|
|
878
|
+
${Gr}`,exitCode:1}}}function X(e){return{output:e,exitCode:1}}import{mkdir as yq,readFile as Eq,stat as bq,writeFile as Tq}from"node:fs/promises";import{mkdir as dU,readFile as VT,stat as mU,writeFile as fU}from"node:fs/promises";import{readFileSync as pU}from"node:fs";import{homedir as hU}from"node:os";import{dirname as gU,extname as _U}from"node:path";var KT="https://lmctl.ai/tools/lmchat";async function YT(e,t={}){let r=NU(t),n=wd(e);if(n.kind==="whoami"){r.stdout(RU(r.env,n.api));return}if(n.kind==="login"){let{runLogin:s}=await Promise.resolve().then(()=>(GT(),WT));if(await s({io:{stdout:{write:a=>r.stdout(a.replace(/\n$/,""))},stderr:{write:a=>r.stderr(a.replace(/\n$/,""))}},env:r.env})!==0)throw new nr("login failed");return}let o=$U(n.api,r.env);if(n.kind==="register-room"){await Vr(r.fetch,`${o}/rooms`,{method:"POST",headers:{...wr(r.env),"content-type":"application/json"},body:JSON.stringify({room_name:n.roomName})}),r.stdout(`created ${n.roomName}`);return}if(n.kind==="rooms"){let s=await Vr(r.fetch,`${o}/rooms`,{method:"GET",headers:wr(r.env)});if(n.json)r.stdout(JSON.stringify(s.rooms));else{r.stdout("room next_seq created_at");for(let i of s.rooms)r.stdout(`${i.room_name} ${i.next_seq} ${i.created_at}`)}return}if(n.kind==="read"&&await JT(r,o,n),n.kind==="post"){let s=await wU(r,o,n);r.stdout(String(s));return}if(n.kind==="say"){let s=await yU(r,o,n);r.stdout(String(s));return}if(n.kind==="list"){await JT(r,o,{...n,kind:"read"});return}if(n.kind==="get"){await bU(r,o,n),r.stdout(`saved ${n.out}`);return}if(n.kind==="delete"){let s=await TU(r,o,n);r.stdout(`deleted ${s}`);return}if(n.kind==="delete-room"){let s=await SU(r,o,n);r.stdout(`deleted room ${s}`);return}}function wd(e){let t=[...e],r=Pe(t,"--api"),n=t.shift();if(!n||n==="help"||n==="--help"||n==="-h")throw new nr(zT());if(n==="whoami"){let o=Pe(t,"--api")??r;return Mt(t),{kind:"whoami",...o?{api:o}:{}}}if(n==="login"){let o=Pe(t,"--api")??r;return Mt(t),{kind:"login",...o?{api:o}:{}}}if(n==="rooms"){let o=Pe(t,"--api")??r,s=Ma(t,"--json");return Mt(t),{kind:"rooms",...s?{json:!0}:{},...o?{api:o}:{}}}if(n==="read"){let o=Pe(t,"--api")??r,s=Dt(t,"room_name"),i=Pe(t,"--after"),a=Pe(t,"--limit"),c=Pe(t,"--interval"),l=Ma(t,"--follow"),u=Ma(t,"--json");return Mt(t),{kind:"read",roomName:s,...i!==void 0?{after:i}:{},...a!==void 0?{limit:a}:{},...c!==void 0?{interval:c}:{},...l?{follow:!0}:{},...u?{json:!0}:{},...o?{api:o}:{}}}if(n==="register-room"||n==="create"){let o=Pe(t,"--api")??r,s=Dt(t,"room_name");return Mt(t),{kind:"register-room",roomName:s,...o?{api:o}:{}}}if(n==="post"){let o=Pe(t,"--api")??r,s=Dt(t,"room_name"),i=gd(t,"--name"),a=gd(t,"--file"),c=Pe(t,"--content-type");return Mt(t),{kind:"post",roomName:s,name:i,file:a,...c?{contentType:c}:{},...o?{api:o}:{}}}if(n==="say"){let o=Pe(t,"--api")??r,s=Dt(t,"room_name"),i=Pe(t,"--title"),a=Dt(t,"text");return Mt(t),{kind:"say",roomName:s,text:a,...i?{title:i}:{},...o?{api:o}:{}}}if(n==="list"){let o=Pe(t,"--api")??r,s=Dt(t,"room_name"),i=Pe(t,"--after"),a=Pe(t,"--limit"),c=Ma(t,"--json");return Mt(t),{kind:"list",roomName:s,...i!==void 0?{after:i}:{},...a!==void 0?{limit:a}:{},...c?{json:!0}:{},...o?{api:o}:{}}}if(n==="get"){let o=Pe(t,"--api")??r,s=Dt(t,"room_name"),i=Dt(t,"seq"),a=gd(t,"--out");return Mt(t),{kind:"get",roomName:s,seq:i,out:a,...o?{api:o}:{}}}if(n==="delete"){let o=Pe(t,"--api")??r,s=Dt(t,"room_name"),i=Dt(t,"seq");return Mt(t),{kind:"delete",roomName:s,seq:i,...o?{api:o}:{}}}if(n==="delete-room"){let o=Pe(t,"--api")??r,s=Dt(t,"room_name");return Mt(t),{kind:"delete-room",roomName:s,...o?{api:o}:{}}}throw new nr(`unknown command: ${n}
|
|
879
879
|
|
|
880
|
-
${
|
|
881
|
-
`)}function Ma(e,t){let r=e.indexOf(t);return r===-1?!1:(e.splice(r,1),!0)}function Pe(e,t){let r=e.indexOf(t);if(r===-1)return;let n=e[r+1];if(!n||n.startsWith("--"))throw new nr(`missing value for ${t}`);return e.splice(r,2),n}function gd(e,t){let r=Pe(e,t);if(!r)throw new nr(`missing required ${t}`);return r}function Dt(e,t){let r=e.shift();if(!r||r.startsWith("--"))throw new nr(`missing ${t}`);return r}function Mt(e){if(e.length>0)throw new nr(`unexpected argument: ${e[0]}`)}function
|
|
882
|
-
`)}var nr=class extends Error{};import{mkdir as
|
|
880
|
+
${zT()}`)}async function wU(e,t,r){let n=await e.stat(r.file);if(!n.isFile())throw new Error(`not a file: ${r.file}`);let o=r.contentType??xU(r.name),s=await Vr(e.fetch,`${t}/rooms/${encodeURIComponent(r.roomName)}/files`,{method:"POST",headers:{...wr(e.env),"content-type":"application/json"},body:JSON.stringify({name:r.name,content_type:o,size:n.size})}),i=await e.readFile(r.file),a=typeof i=="string"?Buffer.from(i):i,c=new FormData;for(let[d,m]of Object.entries(s.fields))c.append(d,m);c.append("file",new Blob([a],{type:s.content_type}),s.name);let l=await e.fetch(s.upload_url,{method:"POST",body:c});if(!l.ok)throw new Error(`S3 upload failed: ${l.status} ${await l.text().catch(()=>"")}`.trim());return(await Vr(e.fetch,`${t}/rooms/${encodeURIComponent(r.roomName)}/files/${encodeURIComponent(String(s.seq))}/commit`,{method:"POST",headers:{...wr(e.env),"content-type":"application/json"},body:JSON.stringify({name:s.name})})).seq}async function yU(e,t,r){return(await Vr(e.fetch,`${t}/rooms/${encodeURIComponent(r.roomName)}/messages`,{method:"POST",headers:{...wr(e.env),"content-type":"application/json"},body:JSON.stringify({text:r.text,...r.title?{title:r.title}:{}})})).seq}async function JT(e,t,r){let n=r.after,o=Number(r.interval??"5");if(!Number.isFinite(o)||o<1)throw new nr(`--interval must be a finite number >= 1 seconds (got "${r.interval}")`);let s=o*1e3,i=!1,a=[];for(;;){let c=await EU(e,t,r.roomName,n,r.limit);r.follow?r.json?c.files.length>0&&e.stdout(JSON.stringify(c.files)):(i||(XT(e.stdout),i=!0),ZT(e.stdout,c.files)):a.push(...c.files);let l=typeof c.next_after=="number"?String(c.next_after):n,u=l!==void 0&&l!==n;if(u&&(n=l),!c.has_more||!u){if(!r.follow){r.json?e.stdout(JSON.stringify(a)):kU(e.stdout,a);return}await vU(s)}}}async function EU(e,t,r,n,o){let s=new URLSearchParams;n!==void 0&&s.set("after",n),o!==void 0&&s.set("limit",o);let i=s.toString();return Vr(e.fetch,`${t}/rooms/${encodeURIComponent(r)}/files${i?`?${i}`:""}`,{method:"GET",headers:wr(e.env)})}async function bU(e,t,r){let n=await e.fetch(`${t}/rooms/${encodeURIComponent(r.roomName)}/files/${encodeURIComponent(r.seq)}`,{method:"GET",headers:wr(e.env),redirect:"manual"});if(n.status!==302)throw await _d(n,"download request failed"),new Error(`download request did not return a redirect: ${n.status}`);let o=n.headers.get("location");if(!o)throw new Error("download redirect missing Location header");let s=await e.fetch(o,{method:"GET"});await _d(s,"presigned download failed");let i=new Uint8Array(await s.arrayBuffer());await e.mkdir(gU(r.out),{recursive:!0}),await e.writeFile(r.out,i)}async function TU(e,t,r){return(await Vr(e.fetch,`${t}/rooms/${encodeURIComponent(r.roomName)}/files/${encodeURIComponent(r.seq)}`,{method:"DELETE",headers:wr(e.env)})).seq}async function SU(e,t,r){return(await Vr(e.fetch,`${t}/rooms/${encodeURIComponent(r.roomName)}`,{method:"DELETE",headers:wr(e.env)})).room_name}function vU(e){return new Promise(t=>setTimeout(t,e))}async function Vr(e,t,r){let n=await e(t,r);return await _d(n,"API request failed"),await n.json()}async function _d(e,t){if(e.ok)return;let r=await e.text().catch(()=>"");throw new Error(`${t}: ${e.status}${r?` ${r}`:""}`)}function AU(e){return QT(e).appkey}function QT(e){if(Pa(e.LMCTL_APPKEY))return{appkey:e.LMCTL_APPKEY,source:"LMCTL_APPKEY"};let t=e.LMCTL_APPKEY_FILE?.trim();if(t){let s=hd(t);if(s)return{appkey:s,source:"LMCTL_APPKEY_FILE"}}let r=e.XDG_CONFIG_HOME?.trim()||`${hU()}/.config`,n=hd(`${r}/lmctl/appkey.json`);if(n)return{appkey:n,source:"~/.config/lmctl/appkey.json"};let o=hd(`${r}/lmctl/lmchat-apikey`);if(o)return{appkey:o,source:"~/.config/lmctl/lmchat-apikey (legacy)"};if(Pa(e.LMCHAT_APP_KEY))return{appkey:e.LMCHAT_APP_KEY,source:"LMCHAT_APP_KEY (legacy)"};throw new Error("no appkey found; run `lmchat login` (or put a key in ~/.config/lmctl/appkey.json or ~/.config/lmctl/lmchat-apikey)")}function Pa(e){return!!(e&&e===e.trim()&&!/[\u0000-\u001f\u007f]/.test(e))}function hd(e){let t;try{t=pU(e,"utf8")}catch{return}let r=t.trim();if(r){if(r.startsWith("{"))try{let n=JSON.parse(r),o=typeof n.appkey=="string"?n.appkey.trim():void 0;return Pa(o)?o:void 0}catch{return}return Pa(r)?r:void 0}}function wr(e){return{authorization:`Bearer ${AU(e)}`}}function $U(e,t){return(e??t.LMCHAT_API_URL??KT).replace(/\/+$/,"")}function kU(e,t){XT(e),ZT(e,t)}function XT(e){e("seq name size content_type created_at")}function ZT(e,t){for(let r of t)e(`${r.seq} ${r.name} ${r.size} ${r.content_type} ${r.created_at}`)}function xU(e){let t=_U(e).toLowerCase();return{".gif":"image/gif",".jpeg":"image/jpeg",".jpg":"image/jpeg",".json":"application/json",".md":"text/markdown",".pdf":"application/pdf",".png":"image/png",".txt":"text/plain",".webp":"image/webp",".zip":"application/zip"}[t]??"application/octet-stream"}function RU(e,t){let r="unset";try{r=QT(e).source}catch{r="unset"}return[`API: ${t??e.LMCHAT_API_URL??KT}`,`appkey source: ${r}`,"","All commands authenticate with the ONE shared appkey (Authorization: Bearer <appkey>).","Get a key with `lmchat login`; it is resolved from LMCTL_APPKEY, LMCTL_APPKEY_FILE,","~/.config/lmctl/appkey.json, or ~/.config/lmctl/lmchat-apikey.","LMCHAT_APP_KEY is still accepted for compatibility.","The server derives your user from the appkey \u2014 the client never sends a user id."].join(`
|
|
881
|
+
`)}function Ma(e,t){let r=e.indexOf(t);return r===-1?!1:(e.splice(r,1),!0)}function Pe(e,t){let r=e.indexOf(t);if(r===-1)return;let n=e[r+1];if(!n||n.startsWith("--"))throw new nr(`missing value for ${t}`);return e.splice(r,2),n}function gd(e,t){let r=Pe(e,t);if(!r)throw new nr(`missing required ${t}`);return r}function Dt(e,t){let r=e.shift();if(!r||r.startsWith("--"))throw new nr(`missing ${t}`);return r}function Mt(e){if(e.length>0)throw new nr(`unexpected argument: ${e[0]}`)}function NU(e){return{fetch:e.fetch??fetch,env:e.env??process.env,stdout:e.stdout??(t=>console.log(t)),stderr:e.stderr??(t=>console.error(t)),readFile:e.readFile??((t,r)=>r?VT(t,{encoding:r}):VT(t)),writeFile:e.writeFile??((t,r)=>fU(t,r)),mkdir:e.mkdir??((t,r)=>dU(t,r)),stat:e.stat??(t=>mU(t))}}function zT(){return["usage: (all commands use the shared appkey \u2014 run `lmchat login` first)"," lmchat login # browser sign-in -> saves ~/.config/lmctl/appkey.json"," lmchat whoami [--api URL]"," lmchat rooms [--json] [--api URL] # list your rooms"," lmchat create <room_name> [--api URL] # create a room"," lmchat say <room_name> <text> [--title title] # post a text message"," lmchat read <room_name> [--after N] [--limit N] [--follow] [--interval S] [--json] # read/poll new messages"," lmchat list <room_name> [--after N] [--limit N] [--json] # alias for read"," lmchat post <room_name> --name <filename> --file <path> [--content-type type] # upload a file"," lmchat get <room_name> <seq> --out <path> # download"," lmchat delete <room_name> <seq> # remove a handled message"," lmchat delete-room <room_name> # remove a room and its files"," (register-room is an alias for create; list is an alias for read)"].join(`
|
|
882
|
+
`)}var nr=class extends Error{};import{mkdir as BU,readFile as WU,stat as GU,writeFile as VU}from"node:fs/promises";import{basename as JU,extname as zU,join as KU}from"node:path";async function wS(e,t={}){let r=oF(t),n=yd(e);if(n.kind==="whoami"){r.stdout(eF(r.env,n.api));return}if(n.kind==="login"){let{runLogin:a}=await Promise.resolve().then(()=>(hS(),pS));if(await a({env:r.env})!==0)throw new Error("login failed");return}let o=ZU(n.api,r.env),s=ve({env:r.env}).appkey,i=wt({apiUrl:o,appkey:s,fetch:r.fetch});if(n.kind==="mailboxes"){let a=await yn(()=>i.listMailboxes());r.stdout("mailbox created_at");for(let c of a)r.stdout(`${c.mailbox_name} ${c.created_at}`);return}if(n.kind==="create"){await yn(()=>i.createMailbox(n.mailbox,{tolerate409:!1})),r.stdout(`created ${n.mailbox}`);return}if(n.kind==="send"){let a=await yn(()=>YU(r,i,n));r.stdout(String(a));return}if(n.kind==="list"){let a=await yn(()=>i.listMessages(n.mailbox,{...n.status?{status:n.status}:{},...n.after?{after:QU(n.after)}:{}}));r.stdout("seq status sender subject attachments created_at");for(let c of a.messages)r.stdout(`${c.seq} ${c.read?"read":"unread"} ${c.sender} ${c.subject} ${c.attachments.length} ${c.created_at}`);return}if(n.kind==="read"){let a=gS(n.seq),c=await yn(()=>i.getMessage(n.mailbox,a));await r.mkdir(n.out,{recursive:!0});let l=new Set;for(let[u,d]of[c.body,...c.attachments].entries()){let m=d.name;l.has(m)&&(m=`${String(u).padStart(3,"0")}_${m}`),l.add(m);let f=KU(n.out,m);await r.writeFile(f,await yn(()=>i.download(d.download_url),"presigned download failed")),r.stdout(`saved ${f}`)}return}n.kind==="delete"&&(await yn(()=>i.deleteMessage(n.mailbox,gS(n.seq))),r.stdout(`deleted ${n.seq}`))}function yd(e){let t=[...e],r=mo(t,"--api"),n=t.shift();if(!n||["help","--help","-h"].includes(n))throw new yr(_S());if(n==="login"||n==="whoami"||n==="mailboxes")return uo(t),{kind:n,...r?{api:r}:{}};if(n==="create"){let o=En(t,"mailbox");return uo(t),{kind:"create",mailbox:o,...r?{api:r}:{}}}if(n==="send"){let o=En(t,"mailbox"),s=nF(t,"--file"),i=mo(t,"--subject"),a=rF(t,"--attach");return uo(t),{kind:"send",mailbox:o,file:s,attachments:a,...i?{subject:i}:{},...r?{api:r}:{}}}if(n==="list"){let o=En(t,"mailbox"),s=mo(t,"--status"),i=mo(t,"--after");return uo(t),{kind:"list",mailbox:o,...s?{status:s}:{},...i?{after:i}:{},...r?{api:r}:{}}}if(n==="read"){let o=En(t,"mailbox"),s=En(t,"seq"),i=mo(t,"--out")??".";return uo(t),{kind:"read",mailbox:o,seq:s,out:i,...r?{api:r}:{}}}if(n==="delete"){let o=En(t,"mailbox"),s=En(t,"seq");return uo(t),{kind:"delete",mailbox:o,seq:s,...r?{api:r}:{}}}throw new yr(`unknown command: ${n}
|
|
883
883
|
|
|
884
|
-
${
|
|
885
|
-
`)}function
|
|
886
|
-
`)}var
|
|
884
|
+
${_S()}`)}async function YU(e,t,r){let n=[r.file,...r.attachments],o=await Promise.all(n.map(async s=>{if(!(await e.stat(s)).isFile())throw new Error(`not a file: ${s}`);return{name:JU(s),contentType:tF(s),bytes:await e.readFile(s)}}));return t.sendMessage({mailbox:r.mailbox,...r.subject?{subject:r.subject}:{},body:o[0],attachments:o.slice(1)})}async function yn(e,t){try{return await e()}catch(r){if(!(r instanceof Wt))throw r;let n=/^upload failed for (.+?): HTTP/.exec(r.message),o=t??(n?`S3 upload failed for ${n[1]}`:"API request failed");throw yS(o,r.status,r.responseBody)}}function gS(e){if(!/^[1-9]\d*$/.test(e))throw Fa("seq_invalid");let t=Number(e);if(!Number.isSafeInteger(t))throw Fa("seq_invalid");return t}function QU(e){if(!/^(0|[1-9]\d*)$/.test(e))throw Fa("after_invalid");let t=Number(e);if(!Number.isSafeInteger(t))throw Fa("after_invalid");return t}function Fa(e){return yS("API request failed",400,JSON.stringify({error:e}))}function yS(e,t,r){return new Error(`${e}: ${t}${r?` ${r}`:""}`)}function XU(e){try{let{source:t}=ve({env:e});return t==="env:LMCTL_APPKEY"?"LMCTL_APPKEY":t==="env:LMCTL_APPKEY_FILE"?"LMCTL_APPKEY_FILE":t==="file:default"?"~/.config/lmctl/appkey.json":t}catch{return"unset"}}function ZU(e,t){let r=e??t.LMMAIL_API_URL;if(!r)throw new Error("missing LMMAIL_API_URL or --api");return r.replace(/\/+$/,"")}function eF(e,t){return[`API: ${t??e.LMMAIL_API_URL??"unset (set --api or LMMAIL_API_URL)"}`,`appkey source: ${XU(e)}`,"identity: derived server-side from the shared appkey"].join(`
|
|
885
|
+
`)}function tF(e){return{".txt":"text/plain",".md":"text/markdown",".html":"text/html",".json":"application/json",".pdf":"application/pdf",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".zip":"application/zip"}[zU(e).toLowerCase()]??"application/octet-stream"}function mo(e,t){let r=e.indexOf(t);if(r<0)return;let n=e[r+1];if(!n||n.startsWith("--"))throw new yr(`missing value for ${t}`);return e.splice(r,2),n}function rF(e,t){let r=e.indexOf(t);if(r<0)return[];let n=[],o=r+1;for(;o<e.length&&!e[o].startsWith("--");)n.push(e[o]),o+=1;if(!n.length)throw new yr(`missing value for ${t}`);return e.splice(r,n.length+1),n}function nF(e,t){let r=mo(e,t);if(!r)throw new yr(`missing required ${t}`);return r}function En(e,t){let r=e.shift();if(!r||r.startsWith("--"))throw new yr(`missing ${t}`);return r}function uo(e){if(e.length)throw new yr(`unexpected argument: ${e[0]}`)}function oF(e){return{fetch:e.fetch??fetch,env:e.env??process.env,stdout:e.stdout??(t=>console.log(t)),readFile:e.readFile??(t=>WU(t)),writeFile:e.writeFile??((t,r)=>VU(t,r)),mkdir:e.mkdir??((t,r)=>BU(t,r)),stat:e.stat??(t=>GU(t))}}function _S(){return["usage:"," lmmail login"," lmmail whoami [--api URL]"," lmmail mailboxes [--api URL]"," lmmail create <name> [--api URL]"," lmmail send <mailbox> --file <body.txt|md|html> [--attach <file...>] [--subject text]"," lmmail list <mailbox> [--status all|unread|read] [--after N]"," lmmail read <mailbox> <seq> [--out dir]"," lmmail delete <mailbox> <seq>"].join(`
|
|
886
|
+
`)}var yr=class extends Error{};import{mkdir as _F,readFile as wF,stat as yF,writeFile as EF}from"node:fs/promises";import{dirname as bF,extname as TF}from"node:path";async function PS(e,t={}){let r=IF(t),n=bd(e);if(n.kind==="whoami"){r.stdout(xF(r.env,n.api));return}if(n.kind==="login"){let{runLogin:i}=await Promise.resolve().then(()=>(DS(),OS));if(await i({env:r.env})!==0)throw new Error("login failed");return}let o=$F(n.api,r.env),s=kF(r.env);if(n.kind==="push"||n.kind==="update"){await SF(r,o,s,n),r.stdout(`${n.kind==="push"?"created":"updated"} ${n.name}`);return}if(n.kind==="list"){let i=new URLSearchParams;n.after&&i.set("after",n.after),n.limit&&i.set("limit",n.limit);let a=await xs(r.fetch,`${o}/notes${i.size?`?${i}`:""}`,{method:"GET",headers:s});r.stdout("name size content_type created_at updated_at");for(let c of a.notes)r.stdout(`${c.name} ${c.size} ${c.content_type} ${c.created_at} ${c.updated_at}`);r.stdout(`next_after=${a.next_after} has_more=${a.has_more}`);return}if(n.kind==="read"){let i=await xs(r.fetch,`${o}/notes/${encodeURIComponent(n.name)}`,{method:"GET",headers:s}),a=await r.fetch(i.download_url);await Td(a,"presigned download failed");let c=new Uint8Array(await a.arrayBuffer());n.out?(await r.mkdir(bF(n.out),{recursive:!0}),await r.writeFile(n.out,c),r.stdout(`saved ${n.out}`)):r.stdout(Buffer.from(c).toString("utf8"));return}n.kind==="delete"&&(await xs(r.fetch,`${o}/notes/${encodeURIComponent(n.name)}`,{method:"DELETE",headers:s}),r.stdout(`deleted ${n.name}`))}function bd(e){let t=[...e],r=ks(t,"--api"),n=t.shift();if(!n||["help","--help","-h"].includes(n))throw new Jr(MS());if(n==="login"||n==="whoami")return $s(t),{kind:n,...r?{api:r}:{}};if(n==="push"||n==="update"){let o=Ed(t,"name"),s=NF(t,"--file");return $s(t),{kind:n,name:o,file:s,...r?{api:r}:{}}}if(n==="list"){let o=ks(t,"--after"),s=ks(t,"--limit");return $s(t),{kind:"list",...o?{after:o}:{},...s?{limit:s}:{},...r?{api:r}:{}}}if(n==="read"){let o=Ed(t,"name"),s=ks(t,"--out");return $s(t),{kind:"read",name:o,...s?{out:s}:{},...r?{api:r}:{}}}if(n==="delete"){let o=Ed(t,"name");return $s(t),{kind:"delete",name:o,...r?{api:r}:{}}}throw new Jr(`unknown command: ${n}
|
|
887
887
|
|
|
888
|
-
${
|
|
889
|
-
`)}function
|
|
890
|
-
`)}var Jr=class extends Error{};async function
|
|
888
|
+
${MS()}`)}async function SF(e,t,r,n){let o=await e.stat(n.file);if(!o.isFile())throw new Error(`not a file: ${n.file}`);let s=RF(n.file),i=n.kind==="push"?`${t}/notes`:`${t}/notes/${encodeURIComponent(n.name)}`,a=await xs(e.fetch,i,{method:n.kind==="push"?"POST":"PUT",headers:{...r,"content-type":"application/json"},body:JSON.stringify({...n.kind==="push"?{name:n.name}:{},content_type:s,size:o.size})}),c=await e.readFile(n.file),l=new FormData;for(let[m,f]of Object.entries(a.fields))l.append(m,f);l.append("file",new Blob([c],{type:a.content_type}),a.name);let u=await e.fetch(a.upload_url,{method:"POST",body:l});await Td(u,"S3 upload failed");let d=a.finalize_url.startsWith("http")?a.finalize_url:`${t}${a.finalize_url.startsWith("/")?"":"/"}${a.finalize_url}`;await xs(e.fetch,d,{method:"POST",headers:{...r,"content-type":"application/json"},body:JSON.stringify({operation_token:a.operation_token})})}function vF(e){try{return ve({env:e}).appkey}catch{throw new Error("no appkey found; run `lmnote login` (or set LMCTL_APPKEY / copy ~/.config/lmctl/appkey.json here)")}}function AF(e){try{let t=ve({env:e}).source;return t==="env:LMCTL_APPKEY"?"LMCTL_APPKEY":t==="env:LMCTL_APPKEY_FILE"?"LMCTL_APPKEY_FILE":t==="file:default"?"~/.config/lmctl/appkey.json":t}catch{return"unset"}}function $F(e,t){let r=e??t.LMNOTE_API_URL;if(!r)throw new Error("missing LMNOTE_API_URL or --api");return r.replace(/\/+$/,"")}function kF(e){return{authorization:`Bearer ${vF(e)}`}}function xF(e,t){return[`API: ${t??e.LMNOTE_API_URL??"unset (set --api or LMNOTE_API_URL)"}`,`appkey source: ${AF(e)}`,"notebook identity: derived server-side from the shared appkey"].join(`
|
|
889
|
+
`)}function RF(e){return{".txt":"text/plain",".md":"text/markdown",".html":"text/html",".json":"application/json",".pdf":"application/pdf",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".zip":"application/zip"}[TF(e).toLowerCase()]??"application/octet-stream"}async function xs(e,t,r){let n=await e(t,r);return await Td(n,"API request failed"),n.json()}async function Td(e,t){if(e.ok)return;let r=await e.text().catch(()=>"");throw new Error(`${t}: ${e.status}${r?` ${r}`:""}`)}function ks(e,t){let r=e.indexOf(t);if(r<0)return;let n=e[r+1];if(!n||n.startsWith("--"))throw new Jr(`missing value for ${t}`);return e.splice(r,2),n}function NF(e,t){let r=ks(e,t);if(!r)throw new Jr(`missing required ${t}`);return r}function Ed(e,t){let r=e.shift();if(!r||r.startsWith("--"))throw new Jr(`missing ${t}`);return r}function $s(e){if(e.length)throw new Jr(`unexpected argument: ${e[0]}`)}function IF(e){return{fetch:e.fetch??fetch,env:e.env??process.env,stdout:e.stdout??(t=>console.log(t)),readFile:e.readFile??(t=>wF(t)),writeFile:e.writeFile??((t,r)=>EF(t,r)),mkdir:e.mkdir??((t,r)=>_F(t,r)),stat:e.stat??(t=>yF(t))}}function MS(){return["usage:"," lmnote login"," lmnote whoami [--api URL]"," lmnote push <name> --file <path>"," lmnote list [--after name] [--limit N]"," lmnote read <name> [--out path]"," lmnote update <name> --file <path>"," lmnote delete <name>"].join(`
|
|
890
|
+
`)}var Jr=class extends Error{};async function ov(e,t={}){let r=t.fetch??fetch,n=t.env??process.env,o=t.stdout??(l=>console.log(l)),s=Sd(e);if(s.kind==="whoami"){o(zF(n,s.api));return}if(s.kind==="login"){let{runLogin:l}=await Promise.resolve().then(()=>(ZS(),XS));if(await l({env:n})!==0)throw new Error("login failed");return}let i=VF(s.api,n),a=JF(n),c={...a,"content-type":"application/json"};if(s.kind==="create"){await or(r,`${i}/sheets`,{method:"POST",headers:c,body:JSON.stringify({name:s.name,columns:s.columns})}),o(`created ${s.name}`);return}if(s.kind==="sheets"){o("name columns next_row created_at updated_at");let l="";for(let u=0;u<100;u+=1){let d=await or(r,`${i}/sheets${l?`?after=${encodeURIComponent(l)}`:""}`,{method:"GET",headers:a});for(let m of d.sheets)o(`${m.name} ${ev(m.columns)} ${m.next_row} ${m.created_at} ${m.updated_at}`);if(!d.has_more){o(`next_after=${d.next_after} has_more=false`);return}if(!d.next_after||d.next_after===l)throw new Error("sheet list cursor did not advance");l=d.next_after}throw new Error("sheet listing did not finish")}if(s.kind==="add-column"){let l=await or(r,`${i}/sheets/${encodeURIComponent(s.sheet)}/columns`,{method:"POST",headers:c,body:JSON.stringify({label:s.label})});o(`added ${l.column.letter} ${l.column.label}`);return}if(s.kind==="read"){let l=new URLSearchParams;s.after&&l.set("after",s.after),s.limit&&l.set("limit",s.limit);let u=await or(r,`${i}/sheets/${encodeURIComponent(s.sheet)}/rows${l.size?`?${l}`:""}`,{method:"GET",headers:a});o(`columns ${ev(u.sheet.columns)}`),o("row_num created_at updated_at cells");for(let d of u.rows)o(`${d.row_num} ${d.created_at} ${d.updated_at} ${JSON.stringify(d.cells)}`);o(`next_after=${u.next_after} has_more=${u.has_more}`);return}if(s.kind==="add-row"){let l=await or(r,`${i}/sheets/${encodeURIComponent(s.sheet)}/rows`,{method:"POST",headers:c,body:JSON.stringify({cells:s.cells,...s.row?{row_num:Number(s.row)}:{}})});o(`added row ${l.row_num}`);return}if(s.kind==="update-row"){await or(r,`${i}/sheets/${encodeURIComponent(s.sheet)}/rows/${s.row}`,{method:"PUT",headers:c,body:JSON.stringify({cells:s.cells})}),o(`updated ${s.sheet} row ${s.row}`);return}if(s.kind==="set-cell"){await or(r,`${i}/sheets/${encodeURIComponent(s.sheet)}/cells/${encodeURIComponent(s.address)}`,{method:"PUT",headers:c,body:JSON.stringify({value:s.value})}),o(`set ${s.sheet} ${s.address}`);return}if(s.kind==="clear-cell"){await or(r,`${i}/sheets/${encodeURIComponent(s.sheet)}/cells/${encodeURIComponent(s.address)}`,{method:"DELETE",headers:a}),o(`cleared ${s.sheet} ${s.address}`);return}if(s.kind==="delete-row"){await or(r,`${i}/sheets/${encodeURIComponent(s.sheet)}/rows/${s.row}`,{method:"DELETE",headers:a}),o(`deleted ${s.sheet} row ${s.row}`);return}if(s.kind==="delete-sheet"){for(let l=0;l<100;l+=1)if((await or(r,`${i}/sheets/${encodeURIComponent(s.name)}`,{method:"DELETE",headers:a})).deleted){o(`deleted ${s.name}`);return}throw new Error("sheet deletion did not finish")}}function Sd(e){let t=[...e],r=fo(t,"--api"),n=t.shift();if(!n||["help","--help","-h"].includes(n))throw new ir(nv());if(n==="login"||n==="whoami"||n==="sheets")return sr(t),{kind:n,...r?{api:r}:{}};if(n==="create"){let o=ct(t,"name"),s=KF(t,"--cols").split(",").map(i=>i.trim());return sr(t),{kind:"create",name:o,columns:s,...r?{api:r}:{}}}if(n==="add-column"){let o=ct(t,"sheet"),s=ct(t,"label");return sr(t),{kind:"add-column",sheet:o,label:s,...r?{api:r}:{}}}if(n==="read"){let o=ct(t,"sheet"),s=fo(t,"--after"),i=fo(t,"--limit");return sr(t),{kind:"read",sheet:o,...s?{after:s}:{},...i?{limit:i}:{},...r?{api:r}:{}}}if(n==="add-row"){let o=ct(t,"sheet"),s=fo(t,"--row"),i=tv(rv(t,"--set"));return sr(t),{kind:"add-row",sheet:o,cells:i,...s?{row:s}:{},...r?{api:r}:{}}}if(n==="update-row"){let o=ct(t,"sheet"),s=ct(t,"row"),i=tv(rv(t,"--set"),!0);return sr(t),{kind:"update-row",sheet:o,row:s,cells:i,...r?{api:r}:{}}}if(n==="set-cell"){let o=ct(t,"sheet"),s=ct(t,"cell"),i=ct(t,"value");return sr(t),{kind:"set-cell",sheet:o,address:s,value:i,...r?{api:r}:{}}}if(n==="clear-cell"){let o=ct(t,"sheet"),s=ct(t,"cell");return sr(t),{kind:"clear-cell",sheet:o,address:s,...r?{api:r}:{}}}if(n==="delete-row"){let o=ct(t,"sheet"),s=ct(t,"row");return sr(t),{kind:"delete-row",sheet:o,row:s,...r?{api:r}:{}}}if(n==="delete-sheet"){let o=ct(t,"name");return sr(t),{kind:"delete-sheet",name:o,...r?{api:r}:{}}}throw new ir(`unknown command: ${n}
|
|
891
891
|
|
|
892
|
-
${
|
|
893
|
-
`)}function
|
|
894
|
-
`)}var ir=class extends Error{};import{readFile as
|
|
892
|
+
${nv()}`)}function WF(e){try{return ve({env:e}).appkey}catch{throw new Error("no appkey found; run `lmsheet login` (or set LMCTL_APPKEY / copy ~/.config/lmctl/appkey.json here)")}}function GF(e){try{let t=ve({env:e}).source;return t==="env:LMCTL_APPKEY"?"LMCTL_APPKEY":t==="env:LMCTL_APPKEY_FILE"?"LMCTL_APPKEY_FILE":t==="file:default"?"~/.config/lmctl/appkey.json":t}catch{return"unset"}}function VF(e,t){let r=e??t.LMSHEET_API_URL;if(!r)throw new Error("missing LMSHEET_API_URL or --api");return r.replace(/\/+$/,"")}function JF(e){return{authorization:`Bearer ${WF(e)}`}}function zF(e,t){return[`API: ${t??e.LMSHEET_API_URL??"unset (set --api or LMSHEET_API_URL)"}`,`appkey source: ${GF(e)}`,"sheet identity: derived server-side from the shared appkey"].join(`
|
|
893
|
+
`)}function ev(e){return e.map(t=>`${t.letter}:${t.label}`).join(",")}function tv(e,t=!1){if(t&&e.length===0)throw new ir("at least one --set is required");let r={};for(let n of e){let o=n.indexOf("="),s=o>0?n.slice(0,o):"";if(!/^[A-Z]+$/.test(s))throw new ir(`invalid --set: ${n}`);r[s]=n.slice(o+1)}return r}async function or(e,t,r){let n=await e(t,r);if(!n.ok){let o=await n.text().catch(()=>"");throw new Error(`API request failed: ${n.status}${o?` ${o}`:""}`)}return n.json()}function fo(e,t){let r=e.indexOf(t);if(r<0)return;let n=e[r+1];if(!n||n.startsWith("--"))throw new ir(`missing value for ${t}`);return e.splice(r,2),n}function rv(e,t){let r=[];for(;e.includes(t);){let n=fo(e,t);n!==void 0&&r.push(n)}return r}function KF(e,t){let r=fo(e,t);if(!r)throw new ir(`missing required ${t}`);return r}function ct(e,t){let r=e.shift();if(!r||r.startsWith("--"))throw new ir(`missing ${t}`);return r}function sr(e){if(e.length)throw new ir(`unexpected argument: ${e[0]}`)}function nv(){return["usage:"," lmsheet login"," lmsheet whoami [--api URL]",' lmsheet create <name> --cols "Name,Email,Age"'," lmsheet sheets"," lmsheet add-column <sheet> <label>"," lmsheet read <sheet> [--after N] [--limit N]"," lmsheet add-row <sheet> [--set A=value ...] [--row N]"," lmsheet update-row <sheet> <row> --set A=value [--set B=value ...]"," lmsheet set-cell <sheet> <A1> <value>"," lmsheet clear-cell <sheet> <A1>"," lmsheet delete-row <sheet> <row>"," lmsheet delete-sheet <name>"].join(`
|
|
894
|
+
`)}var ir=class extends Error{};import{readFile as cq,stat as lq}from"node:fs/promises";import{basename as bv,extname as uq}from"node:path";async function Tv(e,t={}){let r=wq(t);if(!e.length||["help","-h","--help"].includes(e[0]??"")){r.stdout(Ad());return}let n=$d(e);if(n.kind==="login"){let{runLogin:i}=await Promise.resolve().then(()=>(Ev(),yv));if(await i({env:r.env})!==0)throw new Error("login failed");return}if(n.kind==="whoami"){let i=dq(r.env);r.stdout(`API: ${n.api??r.env.LMTEXT_API_URL??"unset (set --api or LMTEXT_API_URL)"}`),r.stdout(`appkey source: ${i.source}`),r.stdout("identity: derived server-side from the shared appkey");return}let o=mq(n.api,r.env),s=fq(r.env);if(n.kind==="transcribe"){let i=await r.stat(n.file);if(!i.isFile())throw new Error(`not a file: ${n.file}`);if(i.size<1||i.size>25*1024*1024)throw new Error("audio file must be between 1 byte and 25 MB");let a=gq(n.file),c=await po(r.fetch,`${o}/transcriptions`,{method:"POST",headers:{...s,"content-type":"application/json"},body:JSON.stringify({file_name:bv(n.file),content_type:a,...n.language?{language_code:n.language}:{}})}),l=await r.readFile(n.file),u=new FormData;for(let[m,f]of Object.entries(c.upload_fields))u.append(m,f);u.append("file",new Blob([new Uint8Array(l)],{type:a}),bv(n.file));let d=await r.fetch(c.upload_url,{method:"POST",body:u});if(await hq(d,"S3 upload failed"),await po(r.fetch,`${o}/transcriptions/${encodeURIComponent(c.transcription_id)}/finalize`,{method:"POST",headers:s}),!n.wait){r.stdout(c.transcription_id);return}for(;;){let m=await po(r.fetch,`${o}/transcriptions/${encodeURIComponent(c.transcription_id)}`,{method:"GET",headers:s});if(m.status==="completed"){r.stdout(m.transcript??"");return}if(m.status==="failed")throw new Error(m.failure_reason??"transcription_failed");await r.sleep(3e3)}}if(n.kind==="list"){let i=new URLSearchParams;n.status&&i.set("status",n.status),n.after&&i.set("after",n.after),n.limit&&i.set("limit",n.limit);let a=await po(r.fetch,`${o}/transcriptions${i.size?`?${i}`:""}`,{method:"GET",headers:s});r.stdout("transcription_id status created_at duration_ms");for(let c of a.transcriptions)r.stdout(`${c.transcription_id} ${c.status} ${c.created_at} ${c.duration_ms??""}`);a.has_more&&a.next_after&&r.stdout(`next_after=${a.next_after} has_more=true`),a.truncated&&r.stderr("warning: list results are truncated at the 1,000-object scan ceiling; older matching transcriptions may be omitted");return}if(n.kind==="get"){let i=await po(r.fetch,`${o}/transcriptions/${encodeURIComponent(n.id)}`,{method:"GET",headers:s});r.stdout(JSON.stringify(i,null,2));return}if(n.kind==="delete"){let i=await po(r.fetch,`${o}/transcriptions/${encodeURIComponent(n.id)}`,{method:"DELETE",headers:s});r.stdout(JSON.stringify(i,null,2));return}}function $d(e){let t=[...e],r=Is(t,"--api"),n=t.shift();if(!n||["help","-h","--help"].includes(n))throw new bn(Ad());if(n==="login"||n==="whoami")return Ls(t),{kind:n,...r?{api:r}:{}};if(n==="transcribe"){let o=vd(t,"file"),s=Is(t,"--language"),i=_q(t,"--wait");return Ls(t),{kind:"transcribe",file:o,...s?{language:s}:{},wait:i,...r?{api:r}:{}}}if(n==="list"){let o=Is(t,"--status"),s=Is(t,"--after"),i=Is(t,"--limit");return Ls(t),{kind:"list",...o?{status:o}:{},...s?{after:s}:{},...i?{limit:i}:{},...r?{api:r}:{}}}if(n==="get"){let o=vd(t,"id");return Ls(t),{kind:"get",id:o,...r?{api:r}:{}}}if(n==="delete"){let o=vd(t,"id");return Ls(t),{kind:"delete",id:o,...r?{api:r}:{}}}throw new bn(`unknown command: ${n}
|
|
895
895
|
|
|
896
|
-
${Ad()}`)}function
|
|
897
|
-
`)}function
|
|
896
|
+
${Ad()}`)}function dq(e){try{return{source:ve({env:e}).source}}catch(t){return t instanceof en?{source:"unset"}:{source:"unset"}}}function mq(e,t){let r=e??t.LMTEXT_API_URL;if(!r)throw new Error("missing LMTEXT_API_URL or --api");return r.replace(/\/+$/,"")}function fq(e){return{authorization:`Bearer ${pq(e)}`}}function pq(e){return ve({env:e}).appkey}async function po(e,t,r){let n=await e(t,r);if(!n.ok){let o=await n.text().catch(()=>"");throw new Error(`API request failed: ${n.status} ${o}`)}return await n.json()}async function hq(e,t){if(!e.ok){let r=await e.text().catch(()=>"");throw new Error(`${t}: ${e.status} ${r}`)}}function gq(e){return{".mp3":"audio/mpeg",".mp4":"audio/mp4",".m4a":"audio/mp4",".wav":"audio/wav",".flac":"audio/flac",".ogg":"audio/ogg",".webm":"audio/webm",".amr":"audio/amr"}[uq(e).toLowerCase()]??"application/octet-stream"}function Is(e,t){let r=e.indexOf(t);if(r<0)return;let n=e[r+1];if(!n||n.startsWith("--"))throw new bn(`missing value for ${t}`);return e.splice(r,2),n}function _q(e,t){let r=e.indexOf(t);return r<0?!1:(e.splice(r,1),!0)}function vd(e,t){let r=e.shift();if(!r||r.startsWith("--"))throw new bn(`missing ${t}`);return r}function Ls(e){if(e.length)throw new bn(`unexpected argument: ${e[0]}`)}function Ad(){return["usage:"," lmtext login"," lmtext whoami [--api URL]"," lmtext transcribe <file> [--language LANG] [--wait] [--api URL]"," lmtext list [--status all|uploading|in_progress|completed|failed] [--after CURSOR] [--limit N] [--api URL]"," lmtext get <id> [--api URL]"," lmtext delete <id> [--api URL]"].join(`
|
|
897
|
+
`)}function wq(e){return{fetch:e.fetch??fetch,env:e.env??process.env,stdout:e.stdout??(t=>process.stdout.write(`${t}
|
|
898
898
|
`)),stderr:e.stderr??(t=>process.stderr.write(`${t}
|
|
899
|
-
`)),sleep:e.sleep??(t=>new Promise(r=>setTimeout(r,t))),readFile:e.readFile??(t=>
|
|
900
|
-
`),1}let p=m.length===0?["--help"]:m,h=process.exitCode,g;try{let _=
|
|
901
|
-
`),0;throw g!==void 0
|
|
899
|
+
`)),sleep:e.sleep??(t=>new Promise(r=>setTimeout(r,t))),readFile:e.readFile??(t=>cq(t)),stat:e.stat??(t=>lq(t))}}var bn=class extends Error{};var Cs=class extends Error{status;responseBody;constructor(t,r){super(`HTTP ${t}${r?` ${r}`:""}`),this.status=t,this.responseBody=r,this.name="HttpResponseError"}},ho=class extends Error{service;status;cause;constructor(t,r,n){super(`${t} request failed: HTTP ${r}`),this.service=t,this.status=r,this.cause=n,this.name="AdapterHttpError"}},go=class extends Error{service;cause;constructor(t,r){super(r instanceof Error?r.message:String(r)),this.service=t,this.cause=r,this.name="ServiceCliUsageError"}},_o=class extends Error{service;exitCode;constructor(t,r){super(`${t} CLI reported exit code ${r}`),this.service=t,this.exitCode=r,this.name="ServiceCliExitError"}};async function Ba(e){if(!e.ok)throw new Cs(e.status,await e.text().catch(()=>""))}var Sv=Object.freeze({lmchat:wo("https://lmctl.ai/tools/lmchat","LMCTL_LMCHAT_API_URL","LMCHAT_API_URL"),lmmail:wo("https://ecezfoozb3.execute-api.us-east-1.amazonaws.com/prod","LMCTL_LMMAIL_API_URL","LMMAIL_API_URL"),lmnote:wo("https://vijni9tfxh.execute-api.us-east-1.amazonaws.com/prod","LMCTL_LMNOTE_API_URL","LMNOTE_API_URL"),lmsheet:wo("https://9zdvg8wfjh.execute-api.us-east-1.amazonaws.com/prod","LMCTL_LMSHEET_API_URL","LMSHEET_API_URL"),lmtext:wo("https://bxdbjn5k90.execute-api.us-east-1.amazonaws.com/prod","LMCTL_LMTEXT_API_URL","LMTEXT_API_URL"),lmsound:wo("https://lmctl.ai/tools/lmsound","LMCTL_LMSOUND_API_URL")});function kd(e,t){let r=Sv[e];return(t[r.overrideEnv]?.trim()||r.defaultUrl).replace(/\/+$/,"")}function vv(e,t){let r=Sv[e];return{...t,[r.serviceEnv]:kd(e,t)}}function wo(e,t,r){return{defaultUrl:e,overrideEnv:t,...r?{serviceEnv:r}:{}}}var Sq={lmchat:(e,t)=>YT(e,t),lmmail:(e,t)=>wS(e,t),lmnote:(e,t)=>PS(e,t),lmsheet:(e,t)=>ov(e,t),lmtext:(e,t)=>Tv(e,t)},vq={lmchat:wd,lmmail:yd,lmnote:bd,lmsheet:Sd,lmtext:$d},Aq=Object.freeze({lmchat:new Set(["delete","delete-room"]),lmmail:new Set(["delete"]),lmnote:new Set(["delete"]),lmsheet:new Set(["delete-row","delete-sheet"]),lmtext:new Set(["delete"])});async function Av(e,t,r={}){let n=r.env??process.env,o=r.stdout??(_=>process.stdout.write(_)),s=r.stderr??(_=>process.stderr.write(_)),i=r.resolveAppkeyImpl??ve,a=r.serviceRunners??Sq,c=r.serviceParsers??vq,l=r.fetchImpl??fetch,u=t.indexOf("--force"),d=u!==-1,m=d?[...t.slice(0,u),...t.slice(u+1)]:t,f=m.length===0||m.length===1&&(m[0]==="--help"||m[0]==="-h");if(!f){let _=m[0];if(_!==void 0&&Aq[e].has(_)&&!d)return o(`lmbee ${e}: refusing to run "${_}" without --force -- this permanently deletes data. Re-run with --force to proceed.
|
|
900
|
+
`),1}let p=m.length===0?["--help"]:m,h=process.exitCode,g;try{let _=vv(e,n);if(!f){try{c[e](p)}catch(T){throw T instanceof Error&&T.constructor.name==="UsageError"?new go(e,T):T}_.LMCTL_APPKEY=i({env:n}).appkey}let y=$q(_,o,s,async(T,R)=>{let x=await l(T,R);return x.ok||(g=x.status),x});await a[e](p,y);let S=process.exitCode;if(S!=null&&S!==0&&S!==h){let T=typeof S=="number"?S:Number(S);throw new _o(e,T)}return 0}catch(_){if(f)return o(`${xq(_)}
|
|
901
|
+
`),0;throw g!==void 0&&!kq(_)?new ho(e,g,_):_}finally{process.exitCode=h}}function $q(e,t,r,n){return{env:e,fetch:n,stdout:o=>t(`${o}
|
|
902
902
|
`),stderr:o=>r(`${o}
|
|
903
|
-
`),sleep:o=>new Promise(s=>setTimeout(s,o)),readFile:(o,s)=>
|
|
904
|
-
`)}function Wa(e,t){return yo(e,t,r=>new
|
|
905
|
-
`)}let u=await o(`${c}/speak`,{method:"POST",headers:{...l,"content-type":"application/json"},body:JSON.stringify({text:i.text,...i.voice?{voice_id:i.voice}:{},...i.engine?{engine:i.engine}:{},...i.format?{format:i.format}:{}})});await Ba(u);let d=await u.json();if(typeof d.download_url!="string")throw new Error("lmsound response missing download_url");if(!i.out)return d.download_url;let m=await o(d.download_url);return await Ba(m),await s(i.out,new Uint8Array(await m.arrayBuffer())),`saved ${i.out}`}var
|
|
906
|
-
`),
|
|
903
|
+
`),sleep:o=>new Promise(s=>setTimeout(s,o)),readFile:(o,s)=>Eq(o,s),writeFile:(o,s)=>Tq(o,s),mkdir:(o,s)=>yq(o,s),stat:o=>bq(o)}}function kq(e){return!!(e&&typeof e=="object"&&"status"in e&&typeof e.status=="number")}function xq(e){return e instanceof Error?e.message:String(e)}import{writeFile as Rq}from"node:fs/promises";function yo(e,t,r){let n=e.indexOf(t);if(n<0)return;let o=e[n+1];if(!o||o.startsWith("--"))throw r(`${t} requires a value`);return e.splice(n,2),o}var Er=class extends Error{};function Nq(){return["usage:",' lmbee lmsound speak "text" [--voice ID] [--engine ENGINE] [--format FORMAT] [--out FILE]'," lmbee lmsound voices"].join(`
|
|
904
|
+
`)}function Wa(e,t){return yo(e,t,r=>new Er(r))}function Iq(e){let t=[...e],r=t.shift();if(r==="voices"){if(t.length)throw new Er(`unexpected argument: ${t[0]}`);return{kind:"voices"}}if(r==="speak"){let n=t.shift();if(!n)throw new Er("lmsound speak requires text");let o=Wa(t,"--voice"),s=Wa(t,"--engine"),i=Wa(t,"--format"),a=Wa(t,"--out");if(t.length)throw new Er(`unexpected argument: ${t[0]}`);return{kind:"speak",text:n,...o?{voice:o}:{},...s?{engine:s}:{},...i?{format:i}:{},...a?{out:a}:{}}}throw new Er(`unknown lmsound command: ${r??""}`)}async function $v(e,t={}){if(e.length===0||e.length===1&&(e[0]==="--help"||e[0]==="-h"))return Nq();let r=t.env??process.env,n=t.resolveAppkeyImpl??ve,o=t.fetchImpl??fetch,s=t.writeFileImpl??Rq,i=Iq(e),a=n({env:r}).appkey,c=kd("lmsound",r),l={authorization:`Bearer ${a}`};if(i.kind==="voices"){let f=await o(`${c}/voices`,{headers:l});await Ba(f);let p=await f.json(),h=["id name language gender engines"];for(let g of p.voices??[])h.push(`${g.id} ${g.name} ${g.language_code} ${g.gender} ${g.supported_engines.join(",")}`);return h.join(`
|
|
905
|
+
`)}let u=await o(`${c}/speak`,{method:"POST",headers:{...l,"content-type":"application/json"},body:JSON.stringify({text:i.text,...i.voice?{voice_id:i.voice}:{},...i.engine?{engine:i.engine}:{},...i.format?{format:i.format}:{}})});await Ba(u);let d=await u.json();if(typeof d.download_url!="string")throw new Error("lmsound response missing download_url");if(!i.out)return d.download_url;let m=await o(d.download_url);return await Ba(m),await s(i.out,new Uint8Array(await m.arrayBuffer())),`saved ${i.out}`}var Lq=new Set(["lmchat","lmmail","lmnote","lmsheet","lmtext"]);function kv(e){return Lq.has(e)}async function xv(e,t){try{return await Av(e,[...t])}catch(r){return process.stderr.write(`${r instanceof Error?r.message:String(r)}
|
|
906
|
+
`),Nv(r)}}async function Rv(e){try{return{output:await $v(e),exitCode:0}}catch(t){return{output:t instanceof Error?t.message:String(t),exitCode:Nv(t)}}}function Nv(e){if(e instanceof go||e instanceof Er)return 2;if(e instanceof _o)return Cq(e.exitCode);if(e instanceof en||e instanceof Us)return 3;if(e instanceof dr||e instanceof Fs)return 4;let t=e instanceof Cs||e instanceof ho?e.status:void 0;return t===401||t===403?3:Oq(e)?4:1}function Cq(e){return Number.isInteger(e)&&e>0&&e<=255?e:1}function Oq(e){if(!(e instanceof Error))return!1;let t=e.code,r=e.cause,n=typeof t=="string"?t:typeof r?.code=="string"?r.code:"";return/^(ECONNREFUSED|ECONNRESET|ENOTFOUND|EAI_AGAIN|ETIMEDOUT|UND_ERR_)/.test(n)}import{randomUUID as lj}from"node:crypto";import{randomUUID as Mq}from"node:crypto";import{hostname as Pq,userInfo as Uq}from"node:os";var Fq=120,Iv=60,qq=20,jq=1e3,Hq=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;async function xd(e,t,r){try{await e.createMailbox(t,{tolerate409:!1});return}catch(o){if(!Bq(o))throw o}let n=5;for(let o=1;o<=n;o+=1){if((await e.listMailboxes()).some(i=>i.mailbox_name===t))return;o<n&&await r(100*2**(o-1))}throw new Error(`refusing exec: reply mailbox ${t} is not owned by the current user`)}function Bq(e){if(!e||typeof e!="object")return!1;let t=e;return t.status===409&&t.code==="mailbox_exists"}async function Rd(e,t){let r=Tu({v:1,type:bu,id:t.id,command:t.command,timeout_s:t.timeoutSeconds??Iv,reply_to:t.replyMailbox});await e.sendMessage({mailbox:t.daemonMailbox,subject:`exec ${t.id}`,body:{name:"body.txt",contentType:"text/plain; charset=utf-8",bytes:Buffer.from(JSON.stringify(r),"utf8")}})}async function Nd(e,t,r,n,o,s={}){let i=new Set(r),a=new Map,c=s.longPoll??{supported:!0};for(;i.size>0&&o.now()<n;){let l=0;for(;i.size>0;){let d=n-o.now();if(d<=0)return a;let m=await Wq(e,t,l,d,c);for(let f of m.messages){let p=zq(f.subject,i);if(p)try{let h=await Jq(e,t,f.seq,p,o.now);a.set(p,h),i.delete(p)}catch(h){s.onMalformed?.(h)}}if(i.size===0)return a;if(m.messages.length===0||m.next_after<=l)break;l=m.next_after}let u=n-o.now();if(u<=0)break;await o.sleep(Math.min(jq,u))}return a}async function Wq(e,t,r,n,o){let s=o.supported?Math.min(qq,Math.floor(n/1e3)):0,i={status:"unread",after:r,...s>0?{wait_s:s}:{}};try{return await e.listMessages(t,i)}catch(a){if(!o.supported||s===0||!Gq(a))throw a;return o.supported=!1,await e.listMessages(t,{status:"unread",after:r})}}function Gq(e){let t=e;return t?.status===400&&t.code==="wait_s_invalid"}function Lv(e,t){return`lmexec-replies-${`${e}-${t}`.replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^[^A-Za-z0-9]+/,"").replace(/[.-]+$/,"")||"user-host"}`.slice(0,128).replace(/[.-]+$/,"")}function Cv(e){return Lv(e,"fleet")}function Vq(e){return Hq.test(e)?Rn(e.toLowerCase()):e}async function Jq(e,t,r,n,o){let s=await e.getMessage(t,r),i=Buffer.from(await e.download(s.body.download_url)).toString("utf8"),a=uw(i);if(a.id!==n)throw new Error("reply body id does not match subject id");let c=new Map(await Promise.all(s.attachments.map(async d=>[d.name,Buffer.from(await e.download(d.download_url)).toString("utf8")]))),l=c.get("stdout.txt")??a.stdout,u=c.get("stderr.txt")??a.stderr;return{result:a,stdout:l,stderr:u,receivedAt:o()}}function zq(e,t){for(let r of t)if(e===Su(r))return r}var Pt=class extends Error{};async function Ov(e,t,r={}){let n=r.env??process.env,o=r.resolveAppkeyImpl??ve,s=r.createMailClientImpl??wt,i=r.now??Date.now,a=r.sleep??(T=>new Promise(R=>setTimeout(R,T))),c=r.username??(()=>Uq().username),l=r.hostname??Pq,u=r.waitSeconds??Fq;if(!Number.isFinite(u)||u<=0)throw new Pt("--wait-s must be positive");let d=r.replyMailbox??(n.LMEXEC_REPLY_MAILBOX?.trim()||Lv(c(),l())),{appkey:m}=o({env:n}),f=s({apiUrl:Nt(n),appkey:m}),p=Mq();await xd(f,d,a),await Rd(f,{id:p,daemonMailbox:Vq(e),command:t,replyMailbox:d,timeoutSeconds:Iv});let h=[],g=i()+Math.round(u*1e3),E=(await Nd(f,d,new Set([p]),g,{now:i,sleep:a},{onMalformed:T=>h.push(`[lmbee exec] ignored malformed matching reply: ${T instanceof Error?T.message:String(T)}
|
|
907
907
|
`)})).get(p);if(!E)return{stdout:"",stderr:`${h.join("")}[lmbee exec] timed out waiting for a reply
|
|
908
908
|
`,exitCode:124};let y=E.result.v===2?` trust=${E.result.sender_trust} sender=${E.result.sender}`:"",S=`[lmbee exec] exit=${E.result.exit_code===null?"timeout":E.result.exit_code} duration_ms=${E.result.duration_ms} truncated=${E.result.truncated}${y}
|
|
909
|
-
`;return{stdout:E.stdout,stderr:`${E.stderr}${S}`,exitCode:E.result.exit_code??124}}import{randomUUID as
|
|
910
|
-
`),await
|
|
911
|
-
`)}async function
|
|
912
|
-
`)}async function
|
|
913
|
-
`)}function
|
|
914
|
-
`);for(let
|
|
909
|
+
`;return{stdout:E.stdout,stderr:`${E.stderr}${S}`,exitCode:E.result.exit_code??124}}import{randomUUID as Kq}from"node:crypto";import{mkdir as Yq,readFile as Qq,rename as Xq,rm as Zq,writeFile as ej}from"node:fs/promises";import{dirname as Pv,join as tj}from"node:path";var Uv=2,rj=/^[A-Za-z0-9_-]+$/,Id=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,Ue=class extends Error{};function Fv(){return tj(Pv($r()),"lmt-peers.json")}function ar(e,t){if(!Id.test(e))throw new Ue(`${t} must be a UUID`);return e.toLowerCase()}function Ld(e){return Id.test(e)}function qv(e){return Ga(e,"peer alias")}function Ga(e,t){if(e.length>128||!rj.test(e))throw new Ue(`${t} must match [A-Za-z0-9_-]+`);if(Id.test(e))throw new Ue(`${t} must not be a UUID`);return e}function Os(e,t){try{return Ym(e,t)}catch(r){throw new Ue(r instanceof Error?r.message:String(r))}}function Dv(){return Object.create(null)}async function Ds(){let e=Fv(),t;try{t=await Qq(e,"utf8")}catch(i){if(i.code==="ENOENT")return Dv();throw i}let r;try{r=JSON.parse(t)}catch{throw new Error(`peer registry is invalid JSON: ${e}`)}if(!r||typeof r!="object"||Array.isArray(r))throw new Error(`peer registry is invalid: ${e}`);let n=r;if(n.v!==Uv||!n.peers||typeof n.peers!="object"||Array.isArray(n.peers))throw new Error(`peer registry is invalid: ${e}`);let o=Dv(),s=new Set;for(let[i,a]of Object.entries(n.peers)){if(!a||typeof a!="object"||Array.isArray(a))throw new Error(`peer registry has invalid entry for ${i}`);let c=a;try{let l=ar(i,"peer registry site-uuid"),u=Os(l,Mv(c.mailbox,`peer registry has invalid mailbox for ${i}`)),d=c.alias===void 0?void 0:qv(Mv(c.alias,`peer registry has invalid alias for ${i}`));if(d){if(s.has(d))throw new Error(`peer registry has duplicate alias: ${d}`);s.add(d)}o[l]=d===void 0?{mailbox:u}:{mailbox:u,alias:d}}catch{throw new Error(`peer registry has invalid entry for ${i}`)}}return o}async function jv(e){let t=Fv(),r={v:Uv,peers:e},n=`${t}.${process.pid}.${Kq()}.tmp`;await Yq(Pv(t),{recursive:!0});let o=!1;try{await ej(n,`${JSON.stringify(r,null,2)}
|
|
910
|
+
`),await Xq(n,t),o=!0}finally{if(!o)try{await Zq(n)}catch(s){if(s.code!=="ENOENT")throw s}}}function nj(e,t,r){if(r!==void 0){for(let[n,o]of Object.entries(e))if(n!==t&&o.alias===r)throw new Error(`peer alias already registered: ${r}`)}}function Hv(e,t){for(let[r,n]of Object.entries(t))if(n.alias===e)return{siteUuid:ar(r,"wire site-uuid"),mailbox:Os(r,n.mailbox)}}function Mv(e,t){if(typeof e!="string")throw new Error(t);return e}async function Bv(){let e=await Ds(),t=["site-uuid alias mailbox"];for(let r of Object.keys(e).sort()){let n=e[r];t.push(`${r} ${n.alias??""} ${n.mailbox}`)}return t.join(`
|
|
911
|
+
`)}async function Wv(e,t,r){let n=ar(e,"site-uuid"),o=Os(n,t),s=await Ds(),i=s[n],a=r===void 0?i?.alias:qv(r);return nj(s,n,a),s[n]=a===void 0?{mailbox:o}:{mailbox:o,alias:a},await jv(s),`peer ${n}${a?` (${a})`:""} -> ${o}`}async function Gv(e){let t=ar(e,"site-uuid"),r=await Ds();if(!Object.hasOwn(r,t))throw new Error(`unknown peer site-uuid: ${t}`);return delete r[t],await jv(r),`removed peer ${t}`}function Eo(e){let t=e.env??process.env,r=e.resolveAppkeyImpl??ve,n=e.createMailClientImpl??wt,{appkey:o}=r({env:t});return n({apiUrl:Nt(t),appkey:o})}function Od(e){try{return Ec(e)}catch(t){throw new Ue(t instanceof Error?t.message:String(t))}}function oj(e){if(e.includes("..")||e.endsWith(".")||!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(e))throw new Ue("--mailbox must be a valid mailbox name");return e}async function Vv(e,t={}){let r=Od(e),n=t.siteUuid===void 0?await ri($r()):ar(t.siteUuid,"--site-uuid"),o=t.mailbox??An(n),s=Eo(t),i;try{i=await s.registerSite(r,n,o)}catch(a){throw a instanceof Wt&&a.code==="site_name_taken"?new Error(`site name already registered to a different site in this account: ${r}`):a}return`registered ${i.site_name} -> ${i.site_uuid} (${i.mailbox})`}async function Jv(e,t={}){let r=Od(e),n=Eo(t),o;try{o=await n.resolveSite(r)}catch(s){if(!(s instanceof Wt&&s.status===404))throw s}return o?{output:`${o.site_name} ${o.site_uuid} ${o.mailbox}`,exitCode:0}:{output:`unknown site name in this account: ${r}`,exitCode:1}}async function Va(e){let t=new Map,r=new Map,n=new Set,o;do{let s=await e.listSites({limit:50,...o?{cursor:o}:{}});for(let i of s.sites)t.set(i.site_uuid.toLowerCase(),i);for(let i of s.discovered){let a=zv(i),c=r.get(a);(!c||i.last_seen_at>c.last_seen_at)&&r.set(a,i)}if(o=s.next_cursor,o){if(n.has(o))throw new Error("site listing returned a repeated cursor");n.add(o)}}while(o);return{sites:[...t.values()],discovered:[...r.values()]}}function zv(e){return e.site_uuid?`uuid#${e.site_uuid.toLowerCase()}`:`mailbox#${e.mailbox}#${e.owner_user_id}`}function sj(e){let t=[`uuid#${e.site_uuid.toLowerCase()}`],r=e.content_mailbox??e.mailbox,n=e.content_mailbox_owner_user_id??e.mailbox_owner_user_id;return n&&t.push(`mailbox#${r}#${n}`),e.exec_mailbox&&e.exec_mailbox_owner_user_id&&t.push(`mailbox#${e.exec_mailbox}#${e.exec_mailbox_owner_user_id}`),t}function ij(e,t){let r=new Set(e.flatMap(sj));return t.filter(n=>!r.has(zv(n))&&!r.has(`mailbox#${n.mailbox}#${n.owner_user_id}`))}function Cd(e){return e.display_name??e.registered_name??e.site_name}function aj(e,t){let r=["REGISTERED","display-name registered-name site-uuid content-mailbox exec-mailbox"];for(let n of e.sort((o,s)=>Cd(o).localeCompare(Cd(s))))r.push([Cd(n),n.registered_name??n.site_name,n.site_uuid,n.content_mailbox??n.mailbox,n.exec_mailbox??"-"].join(" "));r.push("","DISCOVERED","display-name site-uuid mailbox owner-user-id last-seen-at");for(let n of t.sort((o,s)=>s.last_seen_at-o.last_seen_at))r.push([n.name??"-",n.site_uuid??"-",n.mailbox,n.owner_user_id,n.last_seen_at].join(" "));return r.join(`
|
|
912
|
+
`)}async function Kv(e={}){let t=Eo(e),r=await Va(t);return aj(r.sites,ij(r.sites,r.discovered))}async function cj(e,t){let r=await Va(e),n=[...new Set(r.discovered.filter(o=>o.mailbox===t).map(o=>o.owner_user_id))];if(n.length===0)throw new Error(`mailbox is not present in site discovery: ${t}`);if(n.length>1)throw new Error(`mailbox ownership changed during site discovery; retry: ${t}`);return{kind:"mailbox",value:t,owner_user_id:n[0]}}async function Yv(e,t,r){return t!==void 0?{kind:"uuid",value:ar(t,"--uuid")}:await cj(e,oj(r))}async function Qv(e,t){let r=e.trim();if(!r)throw new Ue("site display name must be non-empty");let n=Eo(t),o=await Yv(n,t.uuid,t.mailbox),s=await n.setSiteName(o,r);return`named ${s.site_key} -> ${s.name}`}async function Xv(e){let t=Eo(e),r=await Yv(t,e.uuid,e.mailbox);return`cleared ${(await t.deleteSiteName(r)).site_key}`}async function Zv(e,t={}){let r=Od(e);return await Eo(t).deleteSite(r),`removed ${r}`}function zr(){return"usage: lmbee sites register <name> [--site-uuid <uuid>] [--mailbox <name>] | resolve <name> | list | set-name (--uuid <uuid> | --mailbox <name>) <name> | clear-name (--uuid <uuid> | --mailbox <name>) | remove <name>"}var uj=15,dj=60,mj="lmbee status --live --json";async function eA(e={}){let t=e.env??process.env,r=e.resolveAppkeyImpl??ve,n=e.createMailClientImpl??wt,o=e.now??Date.now,s=e.sleep??(m=>new Promise(f=>setTimeout(f,m))),i=e.username??(()=>process.env.USER??process.env.USERNAME??"user"),a=e.waitSeconds??uj;if(!Number.isFinite(a)||a<=0)throw new Error("--wait-s must be positive");let{appkey:c}=r({env:t}),l=n({apiUrl:Nt(t),appkey:c}),u=(await Va(l)).sites.sort((m,f)=>m.site_name.localeCompare(f.site_name)),d=Cv(i());await xd(l,d,s);try{let m=u.map(S=>({site:S,execMailbox:Rn(S.site_uuid),id:lj(),sentAt:o()}));await Promise.all(m.map(async S=>{try{await Rd(l,{id:S.id,daemonMailbox:S.execMailbox,command:mj,replyMailbox:d,timeoutSeconds:dj})}catch(T){S.sendError=T instanceof Error?T.message:String(T)}}));let f=o()+Math.round(a*1e3),p=new Set(m.filter(S=>S.sendError===void 0).map(S=>S.id)),h=await Nd(l,d,p,f,{now:o,sleep:s}),g=m.filter(S=>S.sendError===void 0).length,_=h.size,E=u.length===0?"empty":_===u.length?"all":_===0?"none":"partial";return{verdict:E,exit_code:E==="none"?2:E==="partial"?3:0,sent:g,answered:_,sites:m.map(S=>fj(S,h.get(S.id))),generated_at:new Date(o()).toISOString()}}finally{await l.deleteMailbox(d)}}function fj(e,t){let r={site_name:e.site.site_name,site_uuid:e.site.site_uuid,mailbox:e.execMailbox};if(!t)return{...r,liveness:"stale",error:e.sendError??"no_reply"};let n={...r,liveness:"live",latency_ms:Math.max(0,t.receivedAt-e.sentAt)},o=pj(t);if(o)return{...n,error:o};if(t.result.exit_code!==0)return{...n,error:t.result.timed_out?"remote_timeout":`remote_exit_${t.result.exit_code}`};try{let s=JSON.parse(t.stdout);if(!s||typeof s!="object"||Array.isArray(s))throw new Error("expected JSON object");return{...n,status:s}}catch{return{...n,error:"invalid_status_json"}}}function pj(e){if(e.result.exit_code===126)try{let t=JSON.parse(e.stderr);return typeof t.error?.code=="string"?t.error.code:"remote_rejected"}catch{return"remote_rejected"}}function tA(e){let t=["SITE LIVENESS LATENCY_MS TEAMS DAEMON ERROR"];for(let r of e.sites)t.push([r.site_name||r.site_uuid,r.liveness,r.latency_ms??"-",hj(r.status)??"-",gj(r.status)??"-",r.error??"-"].join(" "));return t.push(`Fleet: ${e.verdict} (sent ${e.sent}/${e.sites.length}, answered ${e.answered}/${e.sites.length}; exit ${e.exit_code})`),t.join(`
|
|
913
|
+
`)}function hj(e){return Array.isArray(e?.teams)?e.teams.length:void 0}function gj(e){return typeof e?.live=="boolean"?`live:${e.live}`:void 0}function rA(){return"usage: lmbee exec <site-uuid-or-mailbox> [--wait-s N] <command...> | lmbee exec <site-uuid-or-mailbox> [--wait-s N] -- <literal command...>"}function Dd(){return"usage: lmbee fleet status [--json] [--wait-s N]"}function nA(e,t){return yo(e,t,r=>new Pt(r))}function _j(e){let t=e.indexOf("--"),r=t<0?[...e]:[...e.slice(0,t)],n=t<0?void 0:e.slice(t+1),o=nA(r,"--wait-s"),s=o===void 0?void 0:Number(o);if(s!==void 0&&(!Number.isFinite(s)||s<=0))throw new Pt("--wait-s must be positive");let i=r.shift();if(!i)throw new Pt(rA());let a=n??r;if(n&&r.length>0)throw new Pt(`unexpected argument before --: ${r[0]}`);if(a.length===0)throw new Pt(rA());return{target:i,command:a.join(" "),...s===void 0?{}:{waitSeconds:s}}}async function oA(e){try{let{target:t,command:r,waitSeconds:n}=_j(e),o=await Ov(t,r,{waitSeconds:n});return{output:`${o.stdout}${o.stderr}`.replace(/\n$/,""),exitCode:o.exitCode}}catch(t){return{output:t instanceof Error?t.message:String(t),exitCode:t instanceof Pt?1:2}}}async function sA(e){let[t,...r]=e;if(t!=="status")return{output:Dd(),exitCode:1};let n=r.includes("--json");try{let o=[...r],s=o.indexOf("--json");n&&o.splice(s,1);let i=nA(o,"--wait-s"),a=i===void 0?void 0:Number(i);if(a!==void 0&&(!Number.isFinite(a)||a<=0))return{output:Dd(),exitCode:1};if(o.length>0)return{output:Dd(),exitCode:1};let c=await eA({waitSeconds:a});return{output:n?JSON.stringify(c,null,2):tA(c),exitCode:c.exit_code}}catch(o){let s=o instanceof Error?o.message:String(o),i=o instanceof Pt?1:2;return{output:n?JSON.stringify({verdict:"error",exit_code:i,error:s},null,2):s,exitCode:i}}}import{cpSync as Ja,existsSync as Kr,mkdirSync as wj,readFileSync as Md,readdirSync as yj,rmSync as iA,statSync as aA}from"node:fs";import{homedir as uA}from"node:os";import{join as et,sep as Pd}from"node:path";var bo=class extends Error{constructor(t){super(`migrate-home: refusing to run -- an lmauto daemon appears to be live (${t}). Stop it first (systemctl --user stop lmauto.service if it runs as a service, or kill the pid) before re-running.`),this.name="DaemonLiveError"}},Ud=class extends Error{targetDbPath;sizeBytes;constructor(t,r){super(`migrate-home: refusing to replace an existing target database: ${t} already exists (${r} bytes). migrate-home never deletes a database it did not create this run. If this file is debris from an interrupted migrate-home run, or you are certain it is disposable, re-run with --replace-existing-target-db; otherwise move it aside yourself (e.g. \`mv ${t} ${t}.bak\`) and re-run.`),this.targetDbPath=t,this.sizeBytes=r,this.name="TargetDbExistsError"}};function dA(){return et(uA(),".lmauto")}function mA(){return et(process.env.LMCTL_HOME??et(uA(),".lmctl"),"lmauto")}function Ej(e){try{return process.kill(e,0),!0}catch(t){return t.code==="EPERM"}}async function bj(e){try{return(await fetch(`http://127.0.0.1:${e}/api/teams`,{signal:AbortSignal.timeout(1e3)})).body?.cancel(),!0}catch{return!1}}function Tj(e,t){let r=et(e,"serve.pid");if(!Kr(r))return null;let n=Md(r,"utf8").trim(),o=Number(n);return!Number.isInteger(o)||o<=0?null:t(o)?o:null}var cA=["team_state","kv","events","queue","sources","team_progress","mail_ledger","mail_outbound_ledger"];function lA(e,t){return e.prepare(`SELECT COUNT(*) as n FROM ${t}`).get().n}function Fd(e){if(!Kr(e))return 0;let t=0;for(let r of yj(e,{withFileTypes:!0}))r.isDirectory()?t+=Fd(et(e,r.name)):t+=1;return t}function Sj(e,t,r){let n=t.endsWith(Pd)?t:t+Pd,o=e.prepare("SELECT id, prompt_file FROM queue").all(),s=new Map(o.map(l=>[l.id,l.prompt_file])),i=o.filter(l=>l.prompt_file.startsWith(n)),a=e.prepare("UPDATE queue SET prompt_file = ? WHERE id = ?");return e.transaction(l=>{for(let u of l){let d=r+u.prompt_file.slice(t.length);a.run(d,u.id)}})(i),{rewrittenCount:i.length,originalPathById:s}}async function fA(e){let{sourceDir:t,targetDir:r,port:n=4173}=e,o=e.isDaemonAlive??Ej,s=e.probeHttpAlive??bj,i=e.checkSiteLock??z_,a=et(t,"state.db"),c=et(r,"state.db"),l=i(a);if(l!==null)throw new bo(`${l.ownerLabel} pid ${l.pid} (site lock for ${a})`);let u=Tj(t,o);if(u!==null)throw new bo(`pid ${u}, ${et(t,"serve.pid")}`);if(await s(n))throw new bo(`something is listening on port ${n}`);if(t===r||r.startsWith(t+Pd))throw new Error(`migrate-home: target (${r}) must not be, or be nested inside, source (${t})`);let d=e.acquireSiteLock??wa,m=fs(a),f=[];try{f.push(d(m,"migrate-home")),f.push(d(et(t,"site.lock"),"migrate-home"))}catch(p){for(let h of f.splice(0))h.release();throw p instanceof Xn?new bo(`${p.holder.ownerLabel} pid ${p.holder.pid}, ${p.lockPath}`):p}try{wj(r,{recursive:!0});let p=!1,h=!1;if(Kr(a)){let ne=Kr(c);if(ne&&e.replaceExistingTargetDb!==!0)throw new Ud(c,aA(c).size);let J=new yt(a);try{if(J.prepare("SELECT COUNT(*) AS n FROM sqlite_master").get(),ne){process.stderr.write(`migrate-home: replacing existing target database ${c} (${aA(c).size} bytes) with a snapshot of ${a} (explicit replaceExistingTargetDb consent)
|
|
914
|
+
`);for(let oe of["","-wal","-shm"])iA(c+oe,{force:!0});h=!0}else for(let oe of["-wal","-shm"])iA(c+oe,{force:!0});J.prepare("VACUUM INTO ?").run(c)}finally{J.close()}p=!0}let g=et(t,"queue"),_=et(r,"queue"),E=Fd(g);E>0&&Ja(g,_,{recursive:!0});let y=et(t,"prompts"),S=et(r,"prompts"),T=Fd(y);T>0&&Ja(y,S,{recursive:!0});let R=et(t,"site-uuid"),x=et(r,"site-uuid"),I=!1,A=!1;Kr(R)&&(Ja(R,x),I=!0,A=Md(R,"utf8")!==Md(x,"utf8"));let H=et(t,"lmt-peers.json"),L=et(r,"lmt-peers.json"),w=!1;Kr(H)&&(Ja(H,L),w=!0);let b=0,N=0,D=[],W=[],ee={};if(p){let ne=new yt(a,{readonly:!0});try{for(let oe of cA)ee[oe]={source:lA(ne,oe),target:0}}finally{ne.close()}let J=new yt(c);try{for(let $ of cA)ee[$].target=lA(J,$);let{rewrittenCount:oe,originalPathById:k}=Sj(J,g,_);b=oe;let O=J.prepare("SELECT id, prompt_file FROM queue").all();N=O.length;for(let $ of O){if(Kr($.prompt_file))continue;let q=k.get($.id);Kr(q)?D.push(`#${$.id} -> ${$.prompt_file}`):W.push(`#${$.id} -> ${$.prompt_file}`)}}finally{J.close()}}return{sourceDir:t,targetDir:r,stateDbCopied:p,replacedExistingTargetDb:h,queueFilesCopied:E,promptFilesCopied:T,rewrittenPromptPaths:b,queueRowCount:N,missingPromptFiles:D,preExistingMissingPromptFiles:W,siteIdentityCopied:I,siteIdentityMismatch:A,lmtPeersCopied:w,rowCountParity:ee}}finally{for(let p of f.splice(0))p.release()}}async function pA(e={}){let t=e.source??dA(),r=e.target??mA(),n=await fA({sourceDir:t,targetDir:r,replaceExistingTargetDb:e.replaceExistingTargetDb});return{output:kj(n),exitCode:vj(n)}}function vj(e){return e.missingPromptFiles.length>0||e.siteIdentityMismatch||Aj(e)?1:0}function Aj(e){return Object.values(e.rowCountParity).some(t=>t.source!==t.target)}function $j(e){let t=Object.entries(e).filter(([,r])=>r.source!==r.target);return t.length===0?` table row-count parity: OK (${Object.keys(e).length} table(s) checked, all match)`:` PARITY CHECK FAILED -- ${t.length} table(s) with a source/target row-count mismatch:
|
|
915
915
|
`+t.map(([r,n])=>` ${r}: source=${n.source}, target=${n.target}`).join(`
|
|
916
|
-
`)}function
|
|
916
|
+
`)}function kj(e){return[`migrate-home: ${e.sourceDir} -> ${e.targetDir}`,e.replacedExistingTargetDb?" REPLACED an existing target database: the previous state.db in the target dir was DELETED (explicit --replace-existing-target-db consent) and replaced by the source snapshot":null,` state.db copied: ${e.stateDbCopied?"yes":"no (no source state.db found)"}`,` queue files copied: ${e.queueFilesCopied}`,` prompt files copied: ${e.promptFilesCopied}`,` prompt_file paths rewritten (new DB only): ${e.rewrittenPromptPaths}`,` queue rows in new DB: ${e.queueRowCount}`,e.missingPromptFiles.length>0?` PARITY CHECK FAILED -- ${e.missingPromptFiles.length} missing prompt file(s) that existed in source but not in the new copy:
|
|
917
917
|
`+e.missingPromptFiles.map(r=>` ${r}`).join(`
|
|
918
|
-
`):" parity check: OK (every queue row's prompt_file that existed in source also exists in the new location)",e.preExistingMissingPromptFiles.length>0?` (${e.preExistingMissingPromptFiles.length} queue row(s) reference a file already missing in source too -- pre-existing, e.g. garbage-collected -- not a migration defect, not blocking)`:null,` site identity (site-uuid): ${e.siteIdentityCopied?e.siteIdentityMismatch?"PARITY CHECK FAILED -- copied bytes differ from source":"copied, verified byte-identical":"not present in source (remote mail was never enabled) -- nothing to copy"}`,` lmt peer registry (lmt-peers.json): ${e.lmtPeersCopied?"copied":"not present in source -- nothing to copy"}
|
|
919
|
-
`)}import{existsSync as Kd,readdirSync as Hj,statSync as Bj}from"node:fs";import{join as Wj}from"node:path";function st(e){return{ok:!0,value:e}}function le(e,t,r={}){return{ok:!1,error:{code:e,message:t,...r},code:e,message:t,...r.file?{file:r.file}:{},...r.issues?{issues:r.issues}:{},...r.details?{details:r.details}:{}}}var pA=/^@([A-Za-z0-9][A-Za-z0-9._-]*)\/([A-Za-z0-9][A-Za-z0-9._-]*)$/;function Kr(e){if(typeof e!="string"||e.trim()==="")return le("SPEC_SYNTAX","Module spec must be a non-empty string");let t=e.indexOf("#");if(t!==-1){let a=e.slice(0,t),c=e.slice(t+1),l=pA.exec(a);if(!l)return le("SPEC_SYNTAX",`Invalid module spec syntax: "${e}" (expected @owner/repo[#(latest|dev)])`);let u=l[1],d=l[2];if(u==="."||u===".."||d==="."||d==="..")return le("SPEC_SYNTAX",`Invalid owner or repo name: "${e}"`);if(c!=="latest"&&c!=="dev")return le("SPEC_CHANNEL","only the latest and dev channels are supported");let m=c,f=`@${u}/${d}#${m}`;return st({owner:u,repo:d,channel:m,key:f,requested:e})}let r=pA.exec(e);if(!r)return le("SPEC_SYNTAX",`Invalid module spec syntax: "${e}" (expected @owner/repo[#(latest|dev)])`);let n=r[1],o=r[2];if(n==="."||n===".."||o==="."||o==="..")return le("SPEC_SYNTAX",`Invalid owner or repo name: "${e}"`);let s="latest",i=`@${n}/${o}#${s}`;return st({owner:n,repo:o,channel:s,key:i,requested:e})}import{accessSync as kj,constants as xj,statSync as Rj}from"node:fs";import{homedir as Nj}from"node:os";import{isAbsolute as jd,join as Hd,relative as hA,resolve as qd}from"node:path";var Ij=/^[a-z][a-z0-9_]*$/;function Qr(e=process.env){let t=e.LMCTL_HOME&&e.LMCTL_HOME.trim()!==""?e.LMCTL_HOME:Hd(e.HOME??Nj(),".lmctl");return Hd(t,"modules")}function To(e,t){let r=qd(e),n=qd(r,"github.com"),o=qd(n,t.owner,t.repo,t.channel),s=hA(r,o),i=hA(n,o);if(s.startsWith("..")||jd(s)||i.startsWith("..")||jd(i))throw new Error(`Path traversal detected: entry directory "${o}" escapes cache root "${r}"`);return o}function za(e){return`cli.schema.${e}.json`}function Ya(e,t){if(typeof e!="string"||!Ij.test(e))return;let r=t??process.env.PATH??"",n=process.platform==="win32"?";":":",o=r.split(n);for(let s of o){let i=s.trim();if(!i||!jd(i))continue;let a=Hd(i,e);try{if(!Rj(a).isFile())continue;return process.platform==="win32"||kj(a,xj.X_OK),a}catch{}}}import{createHash as zd,randomUUID as Ka}from"node:crypto";import{existsSync as Tr,promises as Ie}from"node:fs";import{dirname as Gd,isAbsolute as kA,join as tt,relative as xA,resolve as Vd}from"node:path";var Lj=new Set(["__proto__","constructor","prototype"]);function So(e){return Lj.has(e)}var Cj=/^(>=|>|<=|<|=)(\d+\.\d+\.\d+)$/;function gA(e){if(typeof e!="string")return!1;let t=e.trim().split(/\s+/).filter(Boolean);if(t.length===0||t.length>4)return!1;for(let r of t)if(!Cj.test(r))return!1;return!0}var _A=/^[a-z][a-z0-9_.-]{0,63}$/,wA=/^[a-z][a-z0-9_.-]*$/;function yA(e){if(typeof e!="string"||e.length>200)return-1;try{let r=new RegExp(e+"|()").exec("");return r?r.length-2:-1}catch{return-1}}var Bd=new Set(["string","number","boolean","object","array","json"]),EA=new Set(["1","?","+","*"]),bA=new Set(["string","number","boolean","object"]),TA=new Set(["read","write","dynamic"]),SA=new Set(["object","array","string","number","boolean","null"]),vA=/^[a-z][a-z0-9_]*$/,Oj=/^[A-Za-z_]\w*$/,Dj=/^[A-Za-z_][A-Za-z0-9_-]*$/,AA=new Set(["name","type","occurs","default","enum","positional","items","description","aliases","cliOnly","docOnly","derived"]);function Mj(e,t,r,n,o){if(e===void 0)return!0;let s=i=>!o||o.length===0||o.includes(i);if(n==="+"||n==="*"||t==="array"){if(!Array.isArray(e))return!1;let i=r??(t==="array"?"string":t);return e.every(a=>s(a)&&$A(a,i))}return s(e)&&$A(e,t)}function $A(e,t){switch(t){case"string":return typeof e=="string";case"number":return typeof e=="number"&&!Number.isNaN(e);case"boolean":return typeof e=="boolean";case"object":return typeof e=="object"&&e!==null&&!Array.isArray(e);case"array":return Array.isArray(e);case"json":return e!==void 0;default:return!1}}function Wd(e){let t=[],r=(i,a,c={})=>{let l=c.usage??(c.op?`${c.op} [flags]`:"<unknown> [flags]"),u=c.synopsis??l;t.push({code:i,message:`${a}. Expected: ${u}`,...c.op?{op:c.op}:{},...c.param?{param:c.param}:{},synopsis:u,usage:l,...c.received!==void 0?{received:c.received}:{},...c.allowed!==void 0?{allowed:c.allowed}:{}})};if(e===null||typeof e!="object"||Array.isArray(e))return r("DOCUMENT_PARSE","cli.schema.v1: document must be an object",{received:e}),{ok:!1,issues:t};let n=e;n.schema!=="cli.schema.v1"&&r("DOCUMENT_PARSE",`cli.schema.v1: unsupported schema tag: ${JSON.stringify(n.schema)}`,{received:n.schema,allowed:["cli.schema.v1"]});let o=n.tool;if(typeof o!="string"||!vA.test(o)?r("DOCUMENT_PARSE",`cli.schema.v1: tool must be a string matching ^[a-z][a-z0-9_]*$, received ${JSON.stringify(o)}`,{received:o}):So(o)&&r("RESERVED_NAME",`cli.schema.v1: tool cannot be named "${o}" (reserved name)`,{received:o}),n.version!==void 0&&typeof n.version!="string"&&r("TYPE_MISMATCH",`cli.schema.v1: version must be a string, received ${typeof n.version}`,{received:n.version}),n.policy!==void 0)if(n.policy===null||typeof n.policy!="object"||Array.isArray(n.policy))r("TYPE_MISMATCH","cli.schema.v1: policy must be an object",{received:n.policy});else{let i=n.policy;(typeof i.dryrun!="boolean"||typeof i.readonly!="boolean")&&r("TYPE_MISMATCH","cli.schema.v1: policy must contain boolean dryrun and readonly properties",{received:n.policy})}if(n.inputs!==void 0)if(!Array.isArray(n.inputs))r("TYPE_MISMATCH","cli.schema.v1: inputs must be an array",{received:n.inputs});else for(let i of n.inputs)["flags","json","graphql"].includes(i)||r("ENUM_VIOLATION",`cli.schema.v1: inputs contains unsupported form "${String(i)}"`,{received:i,allowed:["flags","json","graphql"]});let s=(i,a,c=!1)=>{if(i===null||typeof i!="object"||Array.isArray(i)){r("TYPE_MISMATCH",`cli.schema.v1: param${a?` in "${a}"`:""} must be an object`,{op:a,received:i});return}let l=i,u=l.name;if(typeof u!="string"){r("TYPE_MISMATCH",`cli.schema.v1: param${a?` in "${a}"`:""} needs a string name`,{op:a,received:u});return}for(let _ of Object.keys(l))AA.has(_)||r("UNKNOWN_PARAM",`cli.schema.v1: param "${u}"${a?` in "${a}"`:""} has unknown property "${_}"`,{op:a,param:u,received:_,allowed:Array.from(AA)});(c?Dj:Oj).test(u)?So(u)&&r("RESERVED_NAME",`cli.schema.v1: ${c?"global ":""}param "${u}"${a?` in "${a}"`:""} is a reserved name`,{op:a,param:u,received:u}):r("DOCUMENT_PARSE",`cli.schema.v1: param "${u}"${a?` in "${a}"`:""} name must match ${c?"^[A-Za-z_][A-Za-z0-9_-]*$":"^[A-Za-z_]\\w*$"}`,{op:a,param:u,received:u}),!c&&u==="dryrun"&&r("DOCUMENT_PARSE",'cli.schema.v1: param cannot be named "dryrun" (reserved global policy flag)',{op:a,param:u,received:u});let m=l.aliases;if(m!==void 0&&Array.isArray(m))for(let _ of m)typeof _=="string"&&So(_)&&r("RESERVED_NAME",`cli.schema.v1: param "${u}"${a?` in "${a}"`:""} alias "${_}" is a reserved name`,{op:a,param:u,received:_});let f=l.type;(typeof f!="string"||!Bd.has(f))&&r("ENUM_VIOLATION",`cli.schema.v1: param "${u}"${a?` in "${a}"`:""} has invalid type: ${JSON.stringify(f)}`,{op:a,param:u,received:f,allowed:Array.from(Bd)});let p=l.occurs;p!==void 0&&!EA.has(p)&&r("ENUM_VIOLATION",`cli.schema.v1: param "${u}"${a?` in "${a}"`:""} has invalid occurs: ${JSON.stringify(p)}`,{op:a,param:u,received:p,allowed:Array.from(EA)});let h=l.enum;h!==void 0&&(!Array.isArray(h)||!h.every(_=>typeof _=="string"||typeof _=="number"))&&r("TYPE_MISMATCH",`cli.schema.v1: param "${u}"${a?` in "${a}"`:""} enum must be an array of strings or numbers`,{op:a,param:u,received:h});let g=l.items;if(g!==void 0&&!bA.has(g)&&r("ENUM_VIOLATION",`cli.schema.v1: param "${u}"${a?` in "${a}"`:""} has invalid items type: ${JSON.stringify(g)}`,{op:a,param:u,received:g,allowed:Array.from(bA)}),l.default!==void 0&&Bd.has(f)){let _=Array.isArray(h)?h:void 0;Mj(l.default,f,g,p,_)||r("TYPE_MISMATCH",`cli.schema.v1: param "${u}"${a?` in "${a}"`:""} default value does not match declared type "${f}"`,{op:a,param:u,received:l.default})}};if(n.globals!==void 0)if(!Array.isArray(n.globals))r("TYPE_MISMATCH","cli.schema.v1: globals must be an array",{received:n.globals});else for(let i of n.globals)s(i,void 0,!0);if(!Array.isArray(n.operations))r("DOCUMENT_PARSE","cli.schema.v1: operations must be an array",{received:n.operations});else{let i=new Set;for(let a of n.operations){if(a===null||typeof a!="object"||Array.isArray(a)){r("DOCUMENT_PARSE","cli.schema.v1: every operation must be an object",{received:a});continue}let c=a,l=c.name;if(typeof l!="string"){r("DOCUMENT_PARSE","cli.schema.v1: every operation needs a string name",{received:l});continue}if(vA.test(l)?So(l)&&r("RESERVED_NAME",`cli.schema.v1: operation cannot be named "${l}" (reserved name)`,{op:l,received:l}):r("DOCUMENT_PARSE",`cli.schema.v1: operation name "${l}" must match ^[a-z][a-z0-9_]*$`,{op:l,received:l}),i.has(l)&&r("DOCUMENT_PARSE",`cli.schema.v1: duplicate operation name "${l}"`,{op:l}),i.add(l),c.access!==void 0&&(TA.has(c.access)||r("ENUM_VIOLATION",`cli.schema.v1: operation "${l}" has invalid access: ${JSON.stringify(c.access)}`,{op:l,received:c.access,allowed:Array.from(TA)})),c.returns!==void 0&&(SA.has(c.returns)||r("ENUM_VIOLATION",`cli.schema.v1: operation "${l}" has invalid returns: ${JSON.stringify(c.returns)}`,{op:l,received:c.returns,allowed:Array.from(SA)})),!Array.isArray(c.params))r("DOCUMENT_PARSE",`cli.schema.v1: operation "${l}" needs a params array`,{op:l,received:c.params});else for(let u of c.params)s(u,l,!1)}}if(n.product!==void 0){let i=n.product;if(i===null||typeof i!="object"||Array.isArray(i))r("TYPE_MISMATCH","cli.schema.v1: product must be an object",{received:i});else{let a=i,c=new Set(["name","supported","detect"]);for(let d of Object.keys(a))c.has(d)||r("UNKNOWN_PARAM",`cli.schema.v1: unknown product property "${d}"`,{received:d,allowed:Array.from(c)});let l=a.name;typeof l!="string"?r("TYPE_MISMATCH","cli.schema.v1: product.name must be a string",{received:l}):_A.test(l)||r("DOCUMENT_PARSE",`cli.schema.v1: product.name must match ^[a-z][a-z0-9_.-]{0,63}$, received ${JSON.stringify(l)}`,{received:l});let u=a.supported;if(typeof u!="string"?r("TYPE_MISMATCH","cli.schema.v1: product.supported must be a string",{received:u}):gA(u)||r("DOCUMENT_PARSE",`cli.schema.v1: product.supported must be a conjunction of 1 to 4 comparators (>=, >, <=, <, = followed by numeric x.y.z), received ${JSON.stringify(u)}`,{received:u}),a.detect!==void 0){let d=a.detect;if(d===null||typeof d!="object"||Array.isArray(d))r("TYPE_MISMATCH","cli.schema.v1: product.detect must be an object",{received:d});else{let m=d,f=new Set(["argv","pattern"]);for(let g of Object.keys(m))f.has(g)||r("UNKNOWN_PARAM",`cli.schema.v1: unknown product.detect property "${g}"`,{received:g,allowed:Array.from(f)});let p=m.argv;if(!Array.isArray(p)||p.length<1||p.length>8||!p.every(g=>typeof g=="string"&&g.length>0))r("DOCUMENT_PARSE","cli.schema.v1: product.detect.argv must be an array of 1 to 8 non-empty strings",{received:p});else{let g=p[0];wA.test(g)||r("DOCUMENT_PARSE",`cli.schema.v1: product.detect.argv[0] must match ^[a-z][a-z0-9_.-]*$ (no slashes), received ${JSON.stringify(g)}`,{received:g})}let h=m.pattern;if(typeof h!="string")r("TYPE_MISMATCH","cli.schema.v1: product.detect.pattern must be a string",{received:h});else if(h.length>200)r("DOCUMENT_PARSE",`cli.schema.v1: product.detect.pattern exceeds maximum length of 200 characters (${h.length})`,{received:h});else{let g=yA(h);g!==1&&r("DOCUMENT_PARSE",`cli.schema.v1: product.detect.pattern must be a valid RegExp with exactly one capture group, found ${g}`,{received:h})}}}}}return t.length>0?{ok:!1,issues:t}:{ok:!0,value:e}}var Pj="https://raw.githubusercontent.com",IA=/^[A-Za-z0-9][A-Za-z0-9._-]*$/,Uj=2*1024*1024,LA="CURRENT";async function CA(e){let t=tt(e,LA);if(!Tr(t))return st(e);try{let r=(await Ie.readFile(t,"utf8")).trim();if(!IA.test(r)||r==="."||r==="..")return le("CACHE_CORRUPT",`Invalid ${t}`);let n=tt(e,"generations",r);return Tr(n)?st(n):le("CACHE_CORRUPT",`Missing cache generation ${r}`)}catch(r){return le("CACHE_CORRUPT",`Failed to read ${t}: ${r?.message??String(r)}`)}}function Qa(e){return typeof e=="string"?Kr(e):st(e)}async function vo(e,t){let r=Qa(e);if(!r.ok)return le(r.code,r.message);let n=r.value,o=t?.root??Qr(),s;try{s=To(o,n)}catch(g){return le("PATH_TRAVERSAL",g?.message??String(g))}let i=za(n.channel),a=await CA(s);if(!a.ok)return a;let c=a.value,l=tt(c,i),u=tt(c,"meta.json");if(!Tr(l)||!Tr(u))return le(c===s?"NOT_INSTALLED":"CACHE_CORRUPT",`Module ${n.key} is missing cache files`);let d,m;try{d=await Ie.readFile(l)}catch(g){return le("CACHE_CORRUPT",`Failed to read ${l}: ${g?.message??String(g)}; run: lmbee module install ${n.key} --force`,{file:l})}try{let g=await Ie.readFile(u,"utf-8");m=JSON.parse(g)}catch(g){return le("CACHE_CORRUPT",`Failed to read or parse ${u}: ${g?.message??String(g)}; run: lmbee module install ${n.key} --force`,{file:u})}let f=zd("sha256").update(d).digest("hex");if(f!==m.sha256)return le("CACHE_CORRUPT",`Cached schema hash mismatch in ${l}: expected ${m.sha256}, got ${f}; run: lmbee module install ${n.key} --force`,{file:l});let p;try{p=JSON.parse(d.toString("utf-8"))}catch(g){return le("BAD_JSON",`Failed to parse ${l} as JSON: ${g?.message??String(g)}`,{file:l})}let h=Wd(p);return h.ok?st({spec:n,dir:s,path:l,sha256:f,fetchedAt:m.fetched_at,lastChecked:m.last_checked??m.fetched_at,etag:m.etag,channel:n.channel,tool:h.value.tool,version:h.value.version,document:h.value}):le("INVALID_SCHEMA",`Cached schema in ${l} is invalid: ${h.issues[0]?.message}`,{file:l,issues:h.issues})}async function Fj(e,t){let{timeoutMs:r,fetchImpl:n,etag:o}=t,s;try{let i=AbortSignal.timeout(r),a={};if(o&&(a["If-None-Match"]=o),s=await n(e,{signal:i,headers:a,redirect:"manual"}),s.status>=300&&s.status<400&&s.status!==304){let c=s.headers.get("location");if(!c)return le("FETCH_FAILED",`Redirect response from ${e} missing Location header`);let l=new URL(c,e);if(l.protocol!=="https:"||l.hostname!=="raw.githubusercontent.com")return le("FETCH_FAILED",`Cross-host or non-HTTPS redirect to "${c}" refused (must stay on raw.githubusercontent.com)`);s=await n(l.href,{signal:i,headers:a,redirect:"manual"})}}catch(i){return i?.name==="TimeoutError"||i?.name==="AbortError"?le("FETCH_FAILED",`Fetch timed out after ${r}ms for ${e}`):le("FETCH_FAILED",`Network error fetching ${e}: ${i?.message??String(i)}`)}return st(s)}async function qj(e,t,r,n,o,s){let i;try{if(e.body&&typeof e.body.getReader=="function"){let u=e.body.getReader(),d=[],m=0;for(;;){let{done:f,value:p}=await u.read();if(f)break;if(m+=p.length,m>t)return await u.cancel(),le("OUTPUT_LIMIT",`Schema exceeds maximum size limit of ${t} bytes`);d.push(p)}i=Buffer.concat(d)}else{let u=await e.arrayBuffer();if(u.byteLength>t)return le("OUTPUT_LIMIT",`Schema exceeds maximum size limit of ${t} bytes`);i=Buffer.from(u)}}catch(u){return u?.name==="TimeoutError"||u?.name==="AbortError"?le("FETCH_FAILED",`Fetch stream timed out after ${r}ms`):le("FETCH_FAILED",`Error reading response stream: ${u?.message??String(u)}`)}let a;try{a=JSON.parse(i.toString("utf-8"))}catch(u){return le("BAD_JSON",`Failed to parse ${o} from ${s} as JSON: ${u?.message??String(u)}`)}let c=Wd(a);if(!c.ok){let u=c.issues[0]?.message??"Schema validation failed";return le("INVALID_SCHEMA",`Invalid schema for ${n}: ${u}`,{issues:c.issues})}let l=zd("sha256").update(i).digest("hex");return st({buffer:i,sha256:l,schema:c.value})}async function jj(e,t,r,n){let o=`gen-${Date.now()}-${Ka()}`,s=tt(e,"generations",o),i=tt(s,`.tmp.schema.${Ka()}`),a=tt(s,`.tmp.meta.${Ka()}`),c=tt(s,t),l=tt(s,"meta.json"),u=tt(e,`.tmp.current.${Ka()}`);try{await Ie.mkdir(s,{recursive:!0,mode:448}),await Ie.writeFile(i,r,{mode:384}),await Ie.rename(i,c),await NA(c,384),await Ie.writeFile(a,JSON.stringify(n,null,2)+`
|
|
920
|
-
`,{mode:384}),await Ie.rename(a,l),await
|
|
921
|
-
`,{mode:384}),await Ie.rename(u,tt(e,
|
|
918
|
+
`):" parity check: OK (every queue row's prompt_file that existed in source also exists in the new location)",e.preExistingMissingPromptFiles.length>0?` (${e.preExistingMissingPromptFiles.length} queue row(s) reference a file already missing in source too -- pre-existing, e.g. garbage-collected -- not a migration defect, not blocking)`:null,` site identity (site-uuid): ${e.siteIdentityCopied?e.siteIdentityMismatch?"PARITY CHECK FAILED -- copied bytes differ from source":"copied, verified byte-identical":"not present in source (remote mail was never enabled) -- nothing to copy"}`,` lmt peer registry (lmt-peers.json): ${e.lmtPeersCopied?"copied":"not present in source -- nothing to copy"}`,$j(e.rowCountParity),"",`Source (${e.sourceDir}) left fully intact -- this is your rollback path. Nothing has been`,"switched over yet: the running daemon and CLI defaults still point at the old location until a","separate, deliberate cutover step (stop the old daemon, flip defaults, start the new owner)."].filter(r=>r!==null).join(`
|
|
919
|
+
`)}import{existsSync as Yd,readdirSync as Bj,statSync as Wj}from"node:fs";import{join as Gj}from"node:path";function st(e){return{ok:!0,value:e}}function le(e,t,r={}){return{ok:!1,error:{code:e,message:t,...r},code:e,message:t,...r.file?{file:r.file}:{},...r.issues?{issues:r.issues}:{},...r.details?{details:r.details}:{}}}var hA=/^@([A-Za-z0-9][A-Za-z0-9._-]*)\/([A-Za-z0-9][A-Za-z0-9._-]*)$/;function Yr(e){if(typeof e!="string"||e.trim()==="")return le("SPEC_SYNTAX","Module spec must be a non-empty string");let t=e.indexOf("#");if(t!==-1){let a=e.slice(0,t),c=e.slice(t+1),l=hA.exec(a);if(!l)return le("SPEC_SYNTAX",`Invalid module spec syntax: "${e}" (expected @owner/repo[#(latest|dev)])`);let u=l[1],d=l[2];if(u==="."||u===".."||d==="."||d==="..")return le("SPEC_SYNTAX",`Invalid owner or repo name: "${e}"`);if(c!=="latest"&&c!=="dev")return le("SPEC_CHANNEL","only the latest and dev channels are supported");let m=c,f=`@${u}/${d}#${m}`;return st({owner:u,repo:d,channel:m,key:f,requested:e})}let r=hA.exec(e);if(!r)return le("SPEC_SYNTAX",`Invalid module spec syntax: "${e}" (expected @owner/repo[#(latest|dev)])`);let n=r[1],o=r[2];if(n==="."||n===".."||o==="."||o==="..")return le("SPEC_SYNTAX",`Invalid owner or repo name: "${e}"`);let s="latest",i=`@${n}/${o}#${s}`;return st({owner:n,repo:o,channel:s,key:i,requested:e})}import{accessSync as xj,constants as Rj,statSync as Nj}from"node:fs";import{homedir as Ij}from"node:os";import{isAbsolute as jd,join as Hd,relative as gA,resolve as qd}from"node:path";var Lj=/^[a-z][a-z0-9_]*$/;function Qr(e=process.env){let t=e.LMCTL_HOME&&e.LMCTL_HOME.trim()!==""?e.LMCTL_HOME:Hd(e.HOME??Ij(),".lmctl");return Hd(t,"modules")}function To(e,t){let r=qd(e),n=qd(r,"github.com"),o=qd(n,t.owner,t.repo,t.channel),s=gA(r,o),i=gA(n,o);if(s.startsWith("..")||jd(s)||i.startsWith("..")||jd(i))throw new Error(`Path traversal detected: entry directory "${o}" escapes cache root "${r}"`);return o}function za(e){return`cli.schema.${e}.json`}function Ka(e,t){if(typeof e!="string"||!Lj.test(e))return;let r=t??process.env.PATH??"",n=process.platform==="win32"?";":":",o=r.split(n);for(let s of o){let i=s.trim();if(!i||!jd(i))continue;let a=Hd(i,e);try{if(!Nj(a).isFile())continue;return process.platform==="win32"||xj(a,Rj.X_OK),a}catch{}}}import{createHash as zd,randomUUID as Ya}from"node:crypto";import{existsSync as br,promises as Ie}from"node:fs";import{dirname as Gd,isAbsolute as xA,join as tt,relative as RA,resolve as Vd}from"node:path";var Cj=new Set(["__proto__","constructor","prototype"]);function So(e){return Cj.has(e)}var Oj=/^(>=|>|<=|<|=)(\d+\.\d+\.\d+)$/;function _A(e){if(typeof e!="string")return!1;let t=e.trim().split(/\s+/).filter(Boolean);if(t.length===0||t.length>4)return!1;for(let r of t)if(!Oj.test(r))return!1;return!0}var wA=/^[a-z][a-z0-9_.-]{0,63}$/,yA=/^[a-z][a-z0-9_.-]*$/;function EA(e){if(typeof e!="string"||e.length>200)return-1;try{let r=new RegExp(e+"|()").exec("");return r?r.length-2:-1}catch{return-1}}var Bd=new Set(["string","number","boolean","object","array","json"]),bA=new Set(["1","?","+","*"]),TA=new Set(["string","number","boolean","object"]),SA=new Set(["read","write","dynamic"]),vA=new Set(["object","array","string","number","boolean","null"]),AA=/^[a-z][a-z0-9_]*$/,Dj=/^[A-Za-z_]\w*$/,Mj=/^[A-Za-z_][A-Za-z0-9_-]*$/,$A=new Set(["name","type","occurs","default","enum","positional","items","description","aliases","cliOnly","docOnly","derived"]);function Pj(e,t,r,n,o){if(e===void 0)return!0;let s=i=>!o||o.length===0||o.includes(i);if(n==="+"||n==="*"||t==="array"){if(!Array.isArray(e))return!1;let i=r??(t==="array"?"string":t);return e.every(a=>s(a)&&kA(a,i))}return s(e)&&kA(e,t)}function kA(e,t){switch(t){case"string":return typeof e=="string";case"number":return typeof e=="number"&&!Number.isNaN(e);case"boolean":return typeof e=="boolean";case"object":return typeof e=="object"&&e!==null&&!Array.isArray(e);case"array":return Array.isArray(e);case"json":return e!==void 0;default:return!1}}function Wd(e){let t=[],r=(i,a,c={})=>{let l=c.usage??(c.op?`${c.op} [flags]`:"<unknown> [flags]"),u=c.synopsis??l;t.push({code:i,message:`${a}. Expected: ${u}`,...c.op?{op:c.op}:{},...c.param?{param:c.param}:{},synopsis:u,usage:l,...c.received!==void 0?{received:c.received}:{},...c.allowed!==void 0?{allowed:c.allowed}:{}})};if(e===null||typeof e!="object"||Array.isArray(e))return r("DOCUMENT_PARSE","cli.schema.v1: document must be an object",{received:e}),{ok:!1,issues:t};let n=e;n.schema!=="cli.schema.v1"&&r("DOCUMENT_PARSE",`cli.schema.v1: unsupported schema tag: ${JSON.stringify(n.schema)}`,{received:n.schema,allowed:["cli.schema.v1"]});let o=n.tool;if(typeof o!="string"||!AA.test(o)?r("DOCUMENT_PARSE",`cli.schema.v1: tool must be a string matching ^[a-z][a-z0-9_]*$, received ${JSON.stringify(o)}`,{received:o}):So(o)&&r("RESERVED_NAME",`cli.schema.v1: tool cannot be named "${o}" (reserved name)`,{received:o}),n.version!==void 0&&typeof n.version!="string"&&r("TYPE_MISMATCH",`cli.schema.v1: version must be a string, received ${typeof n.version}`,{received:n.version}),n.policy!==void 0)if(n.policy===null||typeof n.policy!="object"||Array.isArray(n.policy))r("TYPE_MISMATCH","cli.schema.v1: policy must be an object",{received:n.policy});else{let i=n.policy;(typeof i.dryrun!="boolean"||typeof i.readonly!="boolean")&&r("TYPE_MISMATCH","cli.schema.v1: policy must contain boolean dryrun and readonly properties",{received:n.policy})}if(n.inputs!==void 0)if(!Array.isArray(n.inputs))r("TYPE_MISMATCH","cli.schema.v1: inputs must be an array",{received:n.inputs});else for(let i of n.inputs)["flags","json","graphql"].includes(i)||r("ENUM_VIOLATION",`cli.schema.v1: inputs contains unsupported form "${String(i)}"`,{received:i,allowed:["flags","json","graphql"]});let s=(i,a,c=!1)=>{if(i===null||typeof i!="object"||Array.isArray(i)){r("TYPE_MISMATCH",`cli.schema.v1: param${a?` in "${a}"`:""} must be an object`,{op:a,received:i});return}let l=i,u=l.name;if(typeof u!="string"){r("TYPE_MISMATCH",`cli.schema.v1: param${a?` in "${a}"`:""} needs a string name`,{op:a,received:u});return}for(let _ of Object.keys(l))$A.has(_)||r("UNKNOWN_PARAM",`cli.schema.v1: param "${u}"${a?` in "${a}"`:""} has unknown property "${_}"`,{op:a,param:u,received:_,allowed:Array.from($A)});(c?Mj:Dj).test(u)?So(u)&&r("RESERVED_NAME",`cli.schema.v1: ${c?"global ":""}param "${u}"${a?` in "${a}"`:""} is a reserved name`,{op:a,param:u,received:u}):r("DOCUMENT_PARSE",`cli.schema.v1: param "${u}"${a?` in "${a}"`:""} name must match ${c?"^[A-Za-z_][A-Za-z0-9_-]*$":"^[A-Za-z_]\\w*$"}`,{op:a,param:u,received:u}),!c&&u==="dryrun"&&r("DOCUMENT_PARSE",'cli.schema.v1: param cannot be named "dryrun" (reserved global policy flag)',{op:a,param:u,received:u});let m=l.aliases;if(m!==void 0&&Array.isArray(m))for(let _ of m)typeof _=="string"&&So(_)&&r("RESERVED_NAME",`cli.schema.v1: param "${u}"${a?` in "${a}"`:""} alias "${_}" is a reserved name`,{op:a,param:u,received:_});let f=l.type;(typeof f!="string"||!Bd.has(f))&&r("ENUM_VIOLATION",`cli.schema.v1: param "${u}"${a?` in "${a}"`:""} has invalid type: ${JSON.stringify(f)}`,{op:a,param:u,received:f,allowed:Array.from(Bd)});let p=l.occurs;p!==void 0&&!bA.has(p)&&r("ENUM_VIOLATION",`cli.schema.v1: param "${u}"${a?` in "${a}"`:""} has invalid occurs: ${JSON.stringify(p)}`,{op:a,param:u,received:p,allowed:Array.from(bA)});let h=l.enum;h!==void 0&&(!Array.isArray(h)||!h.every(_=>typeof _=="string"||typeof _=="number"))&&r("TYPE_MISMATCH",`cli.schema.v1: param "${u}"${a?` in "${a}"`:""} enum must be an array of strings or numbers`,{op:a,param:u,received:h});let g=l.items;if(g!==void 0&&!TA.has(g)&&r("ENUM_VIOLATION",`cli.schema.v1: param "${u}"${a?` in "${a}"`:""} has invalid items type: ${JSON.stringify(g)}`,{op:a,param:u,received:g,allowed:Array.from(TA)}),l.default!==void 0&&Bd.has(f)){let _=Array.isArray(h)?h:void 0;Pj(l.default,f,g,p,_)||r("TYPE_MISMATCH",`cli.schema.v1: param "${u}"${a?` in "${a}"`:""} default value does not match declared type "${f}"`,{op:a,param:u,received:l.default})}};if(n.globals!==void 0)if(!Array.isArray(n.globals))r("TYPE_MISMATCH","cli.schema.v1: globals must be an array",{received:n.globals});else for(let i of n.globals)s(i,void 0,!0);if(!Array.isArray(n.operations))r("DOCUMENT_PARSE","cli.schema.v1: operations must be an array",{received:n.operations});else{let i=new Set;for(let a of n.operations){if(a===null||typeof a!="object"||Array.isArray(a)){r("DOCUMENT_PARSE","cli.schema.v1: every operation must be an object",{received:a});continue}let c=a,l=c.name;if(typeof l!="string"){r("DOCUMENT_PARSE","cli.schema.v1: every operation needs a string name",{received:l});continue}if(AA.test(l)?So(l)&&r("RESERVED_NAME",`cli.schema.v1: operation cannot be named "${l}" (reserved name)`,{op:l,received:l}):r("DOCUMENT_PARSE",`cli.schema.v1: operation name "${l}" must match ^[a-z][a-z0-9_]*$`,{op:l,received:l}),i.has(l)&&r("DOCUMENT_PARSE",`cli.schema.v1: duplicate operation name "${l}"`,{op:l}),i.add(l),c.access!==void 0&&(SA.has(c.access)||r("ENUM_VIOLATION",`cli.schema.v1: operation "${l}" has invalid access: ${JSON.stringify(c.access)}`,{op:l,received:c.access,allowed:Array.from(SA)})),c.returns!==void 0&&(vA.has(c.returns)||r("ENUM_VIOLATION",`cli.schema.v1: operation "${l}" has invalid returns: ${JSON.stringify(c.returns)}`,{op:l,received:c.returns,allowed:Array.from(vA)})),!Array.isArray(c.params))r("DOCUMENT_PARSE",`cli.schema.v1: operation "${l}" needs a params array`,{op:l,received:c.params});else for(let u of c.params)s(u,l,!1)}}if(n.product!==void 0){let i=n.product;if(i===null||typeof i!="object"||Array.isArray(i))r("TYPE_MISMATCH","cli.schema.v1: product must be an object",{received:i});else{let a=i,c=new Set(["name","supported","detect"]);for(let d of Object.keys(a))c.has(d)||r("UNKNOWN_PARAM",`cli.schema.v1: unknown product property "${d}"`,{received:d,allowed:Array.from(c)});let l=a.name;typeof l!="string"?r("TYPE_MISMATCH","cli.schema.v1: product.name must be a string",{received:l}):wA.test(l)||r("DOCUMENT_PARSE",`cli.schema.v1: product.name must match ^[a-z][a-z0-9_.-]{0,63}$, received ${JSON.stringify(l)}`,{received:l});let u=a.supported;if(typeof u!="string"?r("TYPE_MISMATCH","cli.schema.v1: product.supported must be a string",{received:u}):_A(u)||r("DOCUMENT_PARSE",`cli.schema.v1: product.supported must be a conjunction of 1 to 4 comparators (>=, >, <=, <, = followed by numeric x.y.z), received ${JSON.stringify(u)}`,{received:u}),a.detect!==void 0){let d=a.detect;if(d===null||typeof d!="object"||Array.isArray(d))r("TYPE_MISMATCH","cli.schema.v1: product.detect must be an object",{received:d});else{let m=d,f=new Set(["argv","pattern"]);for(let g of Object.keys(m))f.has(g)||r("UNKNOWN_PARAM",`cli.schema.v1: unknown product.detect property "${g}"`,{received:g,allowed:Array.from(f)});let p=m.argv;if(!Array.isArray(p)||p.length<1||p.length>8||!p.every(g=>typeof g=="string"&&g.length>0))r("DOCUMENT_PARSE","cli.schema.v1: product.detect.argv must be an array of 1 to 8 non-empty strings",{received:p});else{let g=p[0];yA.test(g)||r("DOCUMENT_PARSE",`cli.schema.v1: product.detect.argv[0] must match ^[a-z][a-z0-9_.-]*$ (no slashes), received ${JSON.stringify(g)}`,{received:g})}let h=m.pattern;if(typeof h!="string")r("TYPE_MISMATCH","cli.schema.v1: product.detect.pattern must be a string",{received:h});else if(h.length>200)r("DOCUMENT_PARSE",`cli.schema.v1: product.detect.pattern exceeds maximum length of 200 characters (${h.length})`,{received:h});else{let g=EA(h);g!==1&&r("DOCUMENT_PARSE",`cli.schema.v1: product.detect.pattern must be a valid RegExp with exactly one capture group, found ${g}`,{received:h})}}}}}return t.length>0?{ok:!1,issues:t}:{ok:!0,value:e}}var Uj="https://raw.githubusercontent.com",LA=/^[A-Za-z0-9][A-Za-z0-9._-]*$/,Fj=2*1024*1024,CA="CURRENT";async function OA(e){let t=tt(e,CA);if(!br(t))return st(e);try{let r=(await Ie.readFile(t,"utf8")).trim();if(!LA.test(r)||r==="."||r==="..")return le("CACHE_CORRUPT",`Invalid ${t}`);let n=tt(e,"generations",r);return br(n)?st(n):le("CACHE_CORRUPT",`Missing cache generation ${r}`)}catch(r){return le("CACHE_CORRUPT",`Failed to read ${t}: ${r?.message??String(r)}`)}}function Qa(e){return typeof e=="string"?Yr(e):st(e)}async function vo(e,t){let r=Qa(e);if(!r.ok)return le(r.code,r.message);let n=r.value,o=t?.root??Qr(),s;try{s=To(o,n)}catch(g){return le("PATH_TRAVERSAL",g?.message??String(g))}let i=za(n.channel),a=await OA(s);if(!a.ok)return a;let c=a.value,l=tt(c,i),u=tt(c,"meta.json");if(!br(l)||!br(u))return le(c===s?"NOT_INSTALLED":"CACHE_CORRUPT",`Module ${n.key} is missing cache files`);let d,m;try{d=await Ie.readFile(l)}catch(g){return le("CACHE_CORRUPT",`Failed to read ${l}: ${g?.message??String(g)}; run: lmbee module install ${n.key} --force`,{file:l})}try{let g=await Ie.readFile(u,"utf-8");m=JSON.parse(g)}catch(g){return le("CACHE_CORRUPT",`Failed to read or parse ${u}: ${g?.message??String(g)}; run: lmbee module install ${n.key} --force`,{file:u})}let f=zd("sha256").update(d).digest("hex");if(f!==m.sha256)return le("CACHE_CORRUPT",`Cached schema hash mismatch in ${l}: expected ${m.sha256}, got ${f}; run: lmbee module install ${n.key} --force`,{file:l});let p;try{p=JSON.parse(d.toString("utf-8"))}catch(g){return le("BAD_JSON",`Failed to parse ${l} as JSON: ${g?.message??String(g)}`,{file:l})}let h=Wd(p);return h.ok?st({spec:n,dir:s,path:l,sha256:f,fetchedAt:m.fetched_at,lastChecked:m.last_checked??m.fetched_at,etag:m.etag,channel:n.channel,tool:h.value.tool,version:h.value.version,document:h.value}):le("INVALID_SCHEMA",`Cached schema in ${l} is invalid: ${h.issues[0]?.message}`,{file:l,issues:h.issues})}async function qj(e,t){let{timeoutMs:r,fetchImpl:n,etag:o}=t,s;try{let i=AbortSignal.timeout(r),a={};if(o&&(a["If-None-Match"]=o),s=await n(e,{signal:i,headers:a,redirect:"manual"}),s.status>=300&&s.status<400&&s.status!==304){let c=s.headers.get("location");if(!c)return le("FETCH_FAILED",`Redirect response from ${e} missing Location header`);let l=new URL(c,e);if(l.protocol!=="https:"||l.hostname!=="raw.githubusercontent.com")return le("FETCH_FAILED",`Cross-host or non-HTTPS redirect to "${c}" refused (must stay on raw.githubusercontent.com)`);s=await n(l.href,{signal:i,headers:a,redirect:"manual"})}}catch(i){return i?.name==="TimeoutError"||i?.name==="AbortError"?le("FETCH_FAILED",`Fetch timed out after ${r}ms for ${e}`):le("FETCH_FAILED",`Network error fetching ${e}: ${i?.message??String(i)}`)}return st(s)}async function jj(e,t,r,n,o,s){let i;try{if(e.body&&typeof e.body.getReader=="function"){let u=e.body.getReader(),d=[],m=0;for(;;){let{done:f,value:p}=await u.read();if(f)break;if(m+=p.length,m>t)return await u.cancel(),le("OUTPUT_LIMIT",`Schema exceeds maximum size limit of ${t} bytes`);d.push(p)}i=Buffer.concat(d)}else{let u=await e.arrayBuffer();if(u.byteLength>t)return le("OUTPUT_LIMIT",`Schema exceeds maximum size limit of ${t} bytes`);i=Buffer.from(u)}}catch(u){return u?.name==="TimeoutError"||u?.name==="AbortError"?le("FETCH_FAILED",`Fetch stream timed out after ${r}ms`):le("FETCH_FAILED",`Error reading response stream: ${u?.message??String(u)}`)}let a;try{a=JSON.parse(i.toString("utf-8"))}catch(u){return le("BAD_JSON",`Failed to parse ${o} from ${s} as JSON: ${u?.message??String(u)}`)}let c=Wd(a);if(!c.ok){let u=c.issues[0]?.message??"Schema validation failed";return le("INVALID_SCHEMA",`Invalid schema for ${n}: ${u}`,{issues:c.issues})}let l=zd("sha256").update(i).digest("hex");return st({buffer:i,sha256:l,schema:c.value})}async function Hj(e,t,r,n){let o=`gen-${Date.now()}-${Ya()}`,s=tt(e,"generations",o),i=tt(s,`.tmp.schema.${Ya()}`),a=tt(s,`.tmp.meta.${Ya()}`),c=tt(s,t),l=tt(s,"meta.json"),u=tt(e,`.tmp.current.${Ya()}`);try{await Ie.mkdir(s,{recursive:!0,mode:448}),await Ie.writeFile(i,r,{mode:384}),await Ie.rename(i,c),await IA(c,384),await Ie.writeFile(a,JSON.stringify(n,null,2)+`
|
|
920
|
+
`,{mode:384}),await Ie.rename(a,l),await IA(l,384),await Ie.writeFile(u,o+`
|
|
921
|
+
`,{mode:384}),await Ie.rename(u,tt(e,CA))}catch(d){return await Jd(i),await Jd(a),await Jd(u),le("ATOMIC_WRITE_FAILED",`Failed to write cached module files: ${d?.message??String(d)}`)}return st(void 0)}async function Kd(e,t){let r=Qa(e);if(!r.ok)return le(r.code,r.message);let n=r.value,o=t?.root??Qr(),s=t?.fetchImpl??globalThis.fetch,i=t?.now??(()=>new Date),a=t?.timeoutMs??1e4,c=t?.maxBytes??Fj,l=t?.force??!1,u;try{u=To(o,n)}catch(H){return le("PATH_TRAVERSAL",H?.message??String(H))}let d=za(n.channel),m=`${Uj}/${n.owner}/${n.repo}/HEAD/${d}`,f=await vo(n,{root:o});if(!l&&f.ok)return st({action:"unchanged",entry:f.value});let p=await qj(m,{timeoutMs:a,fetchImpl:s});if(!p.ok)return p;let h=p.value;if(h.status===404)return le("FETCH_FAILED",`Module ${n.key} not found: expected ${d} at the root of the default branch for ${n.owner}/${n.repo}`,{details:{status:404,url:m,file:d}});if(!h.ok)return le("FETCH_FAILED",`Failed to fetch ${m}: HTTP ${h.status} ${h.statusText}`,{details:{status:h.status,url:m}});let g=await jj(h,c,a,n.key,d,m);if(!g.ok)return g;let{buffer:_,sha256:E,schema:y}=g.value;if(!l&&f.ok&&f.value.sha256===E)return st({action:"unchanged",entry:f.value});let S=h.headers.get("etag")??h.headers.get("ETag")??void 0,T=i().toISOString(),R=T,x={spec:n.key,url:m,sha256:E,fetched_at:T,last_checked:R,etag:S,channel:n.channel,tool:y.tool,version:y.version??"unknown",bytes:_.length},I=await Hj(u,d,_,x);if(!I.ok)return I;let A=await vo(n,{root:o});return A.ok?st({action:f.ok?"replaced":"installed",entry:A.value}):A}async function Xa(e){let t=e?.root??Qr(),r=tt(t,"github.com");if(!br(r))return[];let n;try{n=await Ie.readdir(r)}catch{return[]}let o=[];for(let s of n){let i=tt(r,s),a;try{a=await Ie.stat(i)}catch{continue}if(!a.isDirectory())continue;let c;try{c=await Ie.readdir(i)}catch{continue}for(let l of c){let u=tt(i,l),d;try{d=await Ie.stat(u)}catch{continue}if(!d.isDirectory())continue;let m;try{m=await Ie.readdir(u)}catch{continue}for(let f of m){let p=tt(u,f),h;try{h=await Ie.stat(p)}catch{continue}if(!h.isDirectory())continue;let g=`@${s}/${l}#${f}`,E=f==="latest"||f==="dev"?f:void 0,y=E?za(E):`cli.schema.${f}.json`,S=await OA(p);if(!S.ok){o.push({spec:g,channel:E,dir:p,problem:S.message});continue}let T=S.value,R=tt(T,y),x=tt(T,"meta.json");if(!br(R)||!br(x)){o.push({spec:g,channel:E,dir:p,problem:`Missing ${y} or meta.json`});continue}let I,A;try{let L=await Ie.readFile(R);I=zd("sha256").update(L).digest("hex"),A=JSON.parse(await Ie.readFile(x,"utf-8"))}catch(L){o.push({spec:g,channel:E,dir:p,problem:`Unreadable or corrupt files: ${L?.message??String(L)}`});continue}if(I!==A.sha256){o.push({spec:g,channel:E,dir:p,problem:`Checksum mismatch: expected ${A.sha256}, got ${I}`});continue}let H=A.tool?Ka(A.tool)??null:null;o.push({spec:A.spec??g,channel:A.channel??E,tool:A.tool,version:A.version,sha256:A.sha256,fetchedAt:A.fetched_at,dir:p,binaryOnPath:H})}}}return o}async function DA(e,t){let r=t?.root??Qr(),n=t?.fetchImpl,o=t?.now,s=[];if(e!==void 0){let a=Array.isArray(e)?e:[e];for(let c of a){let l=Qa(c);if(l.ok)s.push(l.value);else return[{action:"failed",spec:typeof c=="string"?c:c.key,error:l.message}]}}else{let a=await Xa({root:r});for(let c of a)if(c.channel){let l=Yr(c.spec);l.ok&&s.push(l.value)}}let i=[];for(let a of s){let c=await vo(a,{root:r});if(!c.ok){i.push({action:"failed",spec:a.key,channel:a.channel,error:c.message});continue}let l=await Kd(a,{root:r,fetchImpl:n,now:o,force:!0});if(!l.ok){i.push({action:"failed",spec:a.key,channel:a.channel,error:l.message});continue}if(l.value.entry.sha256===c.value.sha256)i.push({action:"unchanged",spec:a.key,channel:a.channel,sha256:c.value.sha256,version:c.value.version});else{let u=new Set(c.value.document.operations.map(p=>p.name)),d=new Set(l.value.entry.document.operations.map(p=>p.name)),m=[...d].filter(p=>!u.has(p)).sort(),f=[...u].filter(p=>!d.has(p)).sort();i.push({action:"updated",spec:a.key,channel:a.channel,fromSha:c.value.sha256,toSha:l.value.entry.sha256,fromVersion:c.value.version,toVersion:l.value.entry.version,operationsAdded:m,operationsRemoved:f})}}return i}async function MA(e,t){let r=Qa(e);if(!r.ok)return le(r.code,r.message);let n=r.value,o=t?.root??Qr(),s=t?.allChannels??!1,i=Vd(o);if(s){for(let m of[n.owner,n.repo])if(!LA.test(m)||m==="."||m==="..")return le("PATH_TRAVERSAL",`Invalid owner or repo name "${m}" in ${n.key}`);let c=Vd(i,"github.com"),l=Vd(c,n.owner,n.repo),u=RA(i,l),d=RA(c,l);return u.startsWith("..")||xA(u)||d.startsWith("..")||xA(d)?le("PATH_TRAVERSAL","Target path escapes cache root"):br(l)?(await Ie.rm(l,{recursive:!0,force:!0}),await NA(l,i),st({removed:[l]})):le("NOT_INSTALLED",`Module ${n.owner}/${n.repo} not found in cache`)}let a;try{a=To(o,n)}catch(c){return le("PATH_TRAVERSAL",c?.message??String(c))}return br(a)?(await Ie.rm(a,{recursive:!0,force:!0}),await NA(a,i),st({removed:[a]})):le("NOT_INSTALLED",`Module ${n.key} is not installed`)}async function NA(e,t){let r=Gd(e);for(;r!==t&&r.startsWith(t)&&r!==Gd(r);)try{if((await Ie.readdir(r)).length===0)await Ie.rmdir(r),r=Gd(r);else break}catch{break}}async function IA(e,t){try{await Ie.chmod(e,t)}catch{}}async function Jd(e){try{await Ie.unlink(e)}catch{}}var Qd=`usage: lmbee module <command> [args] [--json]
|
|
922
922
|
|
|
923
923
|
Admin commands for schema modules (lmscript: import "@owner/repo[#latest|#dev]"):
|
|
924
924
|
lmbee module install <spec...> [--force] fetch, validate and cache; an identical entry is unchanged
|
|
@@ -943,55 +943,55 @@ Examples:
|
|
|
943
943
|
|
|
944
944
|
Cache: \${LMCTL_HOME:-~/.lmctl}/modules (shared with lmscript).
|
|
945
945
|
lmscript installs and refreshes modules on real runs; check, lint, dry-run and help use the cache only.
|
|
946
|
-
Installing the tool binary itself (npm, brew, ...) is separate; install and list show whether it is on PATH.`,
|
|
946
|
+
Installing the tool binary itself (npm, brew, ...) is separate; install and list show whether it is on PATH.`,Vj=new Set(["install","list","upgrade","delete","remove"]),Jj={install:["json","force","help"],list:["json","help"],upgrade:["json","help"],delete:["json","all-channels","help"]},Ms=e=>e?e.slice(0,12):null;function PA(e,t){if(!e)return null;try{return Ka(e,t??"")??null}catch{return null}}function Ao(e,t){return t?{stdout:`${JSON.stringify(Ae("usage",e))}
|
|
947
947
|
`,stderr:"",exitCode:2}:{stdout:"",stderr:`error: ${e}
|
|
948
948
|
run: lmbee module --help
|
|
949
|
-
`,exitCode:2}}async function
|
|
950
|
-
`,stderr:"",exitCode:0};if(o==="--json")return Ao("missing command: install, list, upgrade or delete",n);if(!
|
|
949
|
+
`,exitCode:2}}async function UA(e,t={}){let r=t.env??process.env,n=e.includes("--json"),[o,...s]=e;if(o===void 0||o==="help"||o==="--help"||o==="-h"||e.includes("--help")||e.includes("-h"))return{stdout:`${Qd}
|
|
950
|
+
`,stderr:"",exitCode:0};if(o==="--json")return Ao("missing command: install, list, upgrade or delete",n);if(!Vj.has(o))return Ao(`unknown module command '${o}' (expected install, list, upgrade or delete)`,n);let i=o==="remove"?"delete":o,a=Jj[i],c=new Set,l=[];for(let m of s)if(m.startsWith("-")){let f=m.replace(/^--?/,"");if(!m.startsWith("--")||!a.includes(f))return Ao(`unknown option '${m}' for module ${i}`,n);c.add(f)}else l.push(m);let u=t.root??Qr(r),d=t.pathVar??r.PATH;switch(i){case"install":return l.length===0?Ao("module install needs at least one spec (@owner/repo[#latest|#dev])",n):zj(l,c.has("force"),n,u,d,t);case"list":return l.length>0?Ao("module list takes no arguments",n):Kj(n,u,d);case"upgrade":return Qj(l,n,u,t);default:return l.length===0?Ao("module delete needs at least one spec (@owner/repo[#latest|#dev])",n):Xj(l,c.has("all-channels"),n,u)}}async function zj(e,t,r,n,o,s){let i=[];for(let u of e){let d=(h,g)=>({spec:u,status:"failed",channel:h,tool:null,namespace:null,version:null,operations:null,sha256:null,binary_on_path:null,error:g}),m=Yr(u);if(!m.ok){i.push(d(null,{code:m.code,message:m.message}));continue}let f=await Kd(m.value,{root:n,force:t,fetchImpl:s.fetchImpl,now:s.now});if(!f.ok){i.push({...d(m.value.channel,{code:f.code,message:f.message}),spec:m.value.key});continue}let p=f.value.entry;i.push({spec:m.value.key,status:f.value.action,channel:p.channel,tool:p.tool,namespace:p.tool,version:p.version??null,operations:p.document.operations.length,sha256:p.sha256,binary_on_path:PA(p.tool,o),error:null})}let a=i.some(u=>u.status==="failed")?1:0;if(r)return{stdout:`${JSON.stringify({root:n,results:i})}
|
|
951
951
|
`,stderr:"",exitCode:a};let c="",l="";for(let u of i){if(u.error){l+=`error: ${u.spec}: ${u.error.message}
|
|
952
952
|
`;continue}c+=`${u.status} ${u.spec}: tool ${u.tool}, namespace ${u.namespace}, version ${u.version??"unknown"}, ${u.operations} operation${u.operations===1?"":"s"}, channel ${u.channel}, sha256 ${Ms(u.sha256??void 0)}
|
|
953
953
|
`,c+=u.binary_on_path?` binary on PATH: ${u.binary_on_path}
|
|
954
954
|
`:` schema installed; install the tool itself (${u.tool}) and put it on PATH
|
|
955
|
-
`}return{stdout:c,stderr:l,exitCode:a}}function
|
|
955
|
+
`}return{stdout:c,stderr:l,exitCode:a}}function FA(e){try{if(!Yd(e))return;if(!Wj(e).isDirectory())return`module store ${e} is not a directory`;let t=Gj(e,"github.com");Yd(t)&&Bj(t);return}catch(t){return`module store ${e} is unreadable: ${t instanceof Error?t.message:String(t)}`}}async function Kj(e,t,r){let n=FA(t);if(n!==void 0)return e?{stdout:`${JSON.stringify(Ae("store_unreadable",n))}
|
|
956
956
|
`,stderr:"",exitCode:1}:{stdout:"",stderr:`error: ${n}
|
|
957
|
-
`,exitCode:1};let o=[];for(let a of await Xa({root:t})){let c={spec:a.spec,channel:a.channel??null,tool:a.tool??null,namespace:a.tool??null,version:a.version??null,sha256:a.sha256??null,fetched_at:a.fetchedAt??null,last_checked:null,binary_on_path:null,problem:a.problem??null};if(c.problem===null){let l=await vo(a.spec,{root:t});l.ok?(c.last_checked=l.value.lastChecked,c.binary_on_path=
|
|
957
|
+
`,exitCode:1};let o=[];for(let a of await Xa({root:t})){let c={spec:a.spec,channel:a.channel??null,tool:a.tool??null,namespace:a.tool??null,version:a.version??null,sha256:a.sha256??null,fetched_at:a.fetchedAt??null,last_checked:null,binary_on_path:null,problem:a.problem??null};if(c.problem===null){let l=await vo(a.spec,{root:t});l.ok?(c.last_checked=l.value.lastChecked,c.binary_on_path=PA(l.value.tool,r)):c.problem=l.message}o.push(c)}if(o.sort((a,c)=>a.spec<c.spec?-1:a.spec>c.spec?1:0),e)return{stdout:`${JSON.stringify({root:t,modules:o})}
|
|
958
958
|
`,stderr:"",exitCode:0};if(o.length===0)return{stdout:`no modules installed (cache: ${t})
|
|
959
959
|
`,stderr:"",exitCode:0};let s=["SPEC","CHANNEL","TOOL/NAMESPACE","VERSION","SHA256","FETCHED_AT","LAST_CHECKED","BINARY"],i=o.map(a=>a.problem!==null?[a.spec,a.channel??"-",`problem: ${a.problem}`]:[a.spec,a.channel??"-",a.tool===a.namespace?a.tool??"-":`${a.tool}/${a.namespace}`,a.version??"unknown",Ms(a.sha256??void 0)??"-",a.fetched_at??"-",a.last_checked??"-",a.binary_on_path??"missing"]);return{stdout:`${Yj(s,i)}cache: ${t}
|
|
960
960
|
`,stderr:"",exitCode:0}}function Yj(e,t){let r=e.map((n,o)=>Math.max(...[e,...t].filter(s=>o<s.length-1).map(s=>(s[o]??"").length),0));return[e,...t].map(n=>n.map((o,s)=>s<n.length-1?o.padEnd(r[s]??0):o).join(" ")).join(`
|
|
961
961
|
`)+`
|
|
962
|
-
`}async function
|
|
962
|
+
`}async function Qj(e,t,r,n){let o={version:null,from_version:null,to_version:null,sha256:null,from_sha256:null,operations_added:[],operations_removed:[],error:null},s=[],i=[];if(e.length===0){let u=FA(r);if(u!==void 0)return t?{stdout:`${JSON.stringify(Ae("store_unreadable",u))}
|
|
963
963
|
`,stderr:"",exitCode:1}:{stdout:"",stderr:`error: ${u}
|
|
964
|
-
`,exitCode:1};for(let d of await Xa({root:r})){let m=
|
|
964
|
+
`,exitCode:1};for(let d of await Xa({root:r})){let m=Yr(d.spec);m.ok?i.push(m.value):s.push({...o,spec:d.spec,status:"failed",channel:null,error:{code:"CACHE_CORRUPT",message:d.problem??m.message}})}}else for(let u of e){let d=Yr(u);d.ok?i.push(d.value):s.push({...o,spec:u,status:"failed",channel:null,error:{code:d.code,message:d.message}})}i=i.filter((u,d)=>i.findIndex(m=>m.key===u.key)===d);for(let u of i){let d=await vo(u,{root:r});if(!d.ok){s.push({...o,spec:u.key,status:"failed",channel:u.channel,error:{code:d.code,message:d.message}});continue}let[m]=await DA([u],{root:r,fetchImpl:n.fetchImpl,now:n.now});if(m===void 0||m.action==="failed"){let f=m?.error??"no outcome from the module store";s.push({...o,spec:u.key,status:"failed",channel:u.channel,error:{code:"REFRESH_FAILED",message:f}})}else m.action==="unchanged"?s.push({...o,spec:u.key,status:"unchanged",channel:u.channel,version:m.version??null,sha256:m.sha256}):s.push({...o,spec:u.key,status:"updated",channel:u.channel,version:m.toVersion??null,from_version:m.fromVersion??null,to_version:m.toVersion??null,sha256:m.toSha,from_sha256:m.fromSha,operations_added:m.operationsAdded,operations_removed:m.operationsRemoved})}let a=s.some(u=>u.status==="failed")?1:0;if(t)return{stdout:`${JSON.stringify({root:r,results:s})}
|
|
965
965
|
`,stderr:"",exitCode:a};if(s.length===0)return{stdout:`no modules installed (cache: ${r})
|
|
966
966
|
`,stderr:"",exitCode:0};let c="",l="";for(let u of s)if(u.status==="failed")l+=`error: ${u.spec}: ${u.error?.message}
|
|
967
967
|
`;else if(u.status==="unchanged")c+=`unchanged ${u.spec}: version ${u.version??"unknown"}, sha256 ${Ms(u.sha256??void 0)}
|
|
968
968
|
`;else{let d=[...u.operations_added.map(m=>`+${m}`),...u.operations_removed.map(m=>`-${m}`)];c+=`updated ${u.spec}: version ${u.from_version??"unknown"} -> ${u.to_version??"unknown"}, sha256 ${Ms(u.from_sha256??void 0)} -> ${Ms(u.sha256??void 0)}, operations ${d.length===0?"unchanged":d.join(" ")}
|
|
969
|
-
`}return{stdout:c,stderr:l,exitCode:a}}async function
|
|
969
|
+
`}return{stdout:c,stderr:l,exitCode:a}}async function Xj(e,t,r,n){let o=[];for(let c of e){let l=Yr(c);if(!l.ok){o.push({spec:c,status:"failed",channels:[],error:{code:l.code,message:l.message}});continue}let u=l.value,d=t?`@${u.owner}/${u.repo}`:u.key,m=["latest","dev"].filter(p=>{if(!t&&p!==u.channel)return!1;try{return Yd(To(n,{...u,channel:p}))}catch{return!1}}),f=await MA(u,{root:n,allChannels:t});if(!f.ok){let p=f.code==="NOT_INSTALLED"?`${d} is not installed`:f.message;o.push({spec:d,status:"failed",channels:[],error:{code:f.code,message:p}});continue}o.push({spec:d,status:"deleted",channels:m,error:null})}let s=o.some(c=>c.status==="failed")?1:0;if(r)return{stdout:`${JSON.stringify({root:n,results:o})}
|
|
970
970
|
`,stderr:"",exitCode:s};let i="",a="";for(let c of o)c.error?a+=`error: ${c.spec}: ${c.error.message}
|
|
971
971
|
`:i+=`deleted ${c.spec}${t?` (channels: ${c.channels.length>0?c.channels.join(", "):"none"})`:""}
|
|
972
|
-
`;return{stdout:i,stderr:a,exitCode:s}}function Xd(e){return{output:e,exitCode:0}}function $o(e){return{output:e,exitCode:1}}function Zd(){return"usage: lmbee localweb passcode get | set | rotate"}var
|
|
973
|
-
`,exitCode:1};let r=e.execFileImpl??
|
|
972
|
+
`;return{stdout:i,stderr:a,exitCode:s}}function Xd(e){return{output:e,exitCode:0}}function $o(e){return{output:e,exitCode:1}}function Zd(){return"usage: lmbee localweb passcode get | set | rotate"}var qA=32;async function Zj(){let e=[],t=0;for await(let r of process.stdin){let n=Buffer.from(r);if(t+=n.length,t>4096)throw new Error("passcode input exceeds 4096 bytes");e.push(n)}return Buffer.concat(e).toString("utf8")}async function jA(e,t={}){let[r,n,...o]=e;if(r!=="passcode")return $o(Zd());if(o.length)return $o(`unexpected argument; ${Zd()}`);let s=Lo(),i=Zn(s);if(i===null)return{output:`no passcode file for an in-memory DB (${s})`,exitCode:2};if(n==="get"){let a=tw(i);return a===null?{output:"no passcode set yet -- start the daemon or run `lmbee localweb passcode rotate`",exitCode:1}:Xd(a)}if(n==="set"){let a=t.readStdin??Zj,c;try{c=(await a()).trim()}catch{return $o("passcode input rejected")}let l=Buffer.byteLength(c,"utf8");return l===0||l>4096?$o("usage: lmbee localweb passcode set (reads a nonempty value of at most 4096 bytes from stdin)"):l<qA?$o(`passcode rejected: at least ${qA} bytes required (got ${l}) -- a short value meaningfully weakens the 256-bit guarantee rotate/startup generation otherwise provide; use \`lmbee localweb passcode rotate\` for a strong random value instead`):(yu(i,c),Xd("passcode updated"))}return n==="rotate"?Xd(ya(i)):$o(Zd())}import{randomUUID as e1}from"node:crypto";import{readFile as t1}from"node:fs/promises";function r1(e){try{let t=Wm(e);return n1(t.site),t}catch(t){throw new Ue(t instanceof Error?t.message:String(t))}}function n1(e){return Ld(e)?e.toLowerCase():Ga(e,"peer alias")}function HA(e,t,r,n,o=!1){let s=e??(t===void 0||t===""?r:t);return o&&s===""?s:Ga(s,n)}async function o1(e,t){return e==="-"?t():t1(e,"utf8")}async function s1(){let e=[];for await(let t of process.stdin)e.push(Buffer.from(t));return Buffer.concat(e).toString("utf8")}async function i1(e,t,r){if(Ld(e)){let s=ar(e,"site-uuid"),i=t[s];if(!i)throw new Error(`unknown peer site-uuid: ${s}; add it with lmbee peers add ${s} <mailbox>`);return{siteUuid:s,mailbox:Os(s,i.mailbox)}}let n=Hv(e,t);if(n)return n;try{let s=await r.resolveSite(e);return{siteUuid:ar(s.site_uuid,"resolved site-uuid"),mailbox:s.mailbox}}catch(s){if(!(s instanceof Wt&&s.status===404))throw s}let o=Object.values(t).map(s=>s.alias).filter(s=>s!==void 0).sort();throw new Error(`unknown peer alias or site name: ${e}; registered local aliases: ${o.length?o.join(", "):"(none)"}; not found in the account's site registry either`)}function BA(){return"usage: lmbee tell <site-uuid-or-alias:team-id:alias> (<prompt...> | --prompt-file <path|->) [--from-team <team>] [--from-alias <alias>]"}async function WA(e,t,r={}){let n=r.env??process.env,o=r.promptFile;if(!e||o===void 0&&t.length===0)throw new Ue(BA());if(o!==void 0&&t.length>0)throw new Ue("positional prompt and --prompt-file are mutually exclusive");let s=r1(e),i=o===void 0?t.join(" "):await o1(o,r.readStdin??s1);if(!i.trim())throw new Ue("tell prompt must be non-empty");let a=HA(r.fromTeam,n.LMT_FROM_TEAM,"","from-team",!0),c=HA(r.fromAlias,n.LMT_FROM_ALIAS,"operator","from-alias"),l=r.resolveAppkeyImpl??ve,u=r.createMailClientImpl??wt,{appkey:d}=l({env:n}),m=u({apiUrl:Nt(n),appkey:d}),f=await Ds(),{siteUuid:p,mailbox:h}=await i1(s.site,f,m),g={...s,site:p},_=await ri($r()),E=e1(),y={v:1,msg_id:E,to:g,from:{site:_,team:a,alias:c},sent_at:new Date().toISOString(),payload:i},S=await m.sendMessage({mailbox:h,subject:`delivery ${E}`,body:{name:"body.txt",contentType:"text/plain; charset=utf-8",bytes:Buffer.from(JSON.stringify(y),"utf8")}});return`sent ${E} from ${_}:${a}:${c} to ${e} via ${h} (seq ${S})`}function Tr(e){return{output:e,exitCode:0}}function cr(e){return{output:e,exitCode:1}}function em(e){return{output:e instanceof Error?e.message:String(e),exitCode:e instanceof Ue?1:2}}function a1(){return"usage: lmbee peers list | add <site-uuid> <mailbox> [--alias <name>] | remove <site-uuid>"}function lr(e,t){return yo(e,t,r=>new Ue(r))}async function GA(e){let[t,...r]=e;try{if(t==="list"){if(r.length)throw new Ue(`unexpected argument: ${r[0]}`);return Tr(await Bv())}if(t==="add"){let n=lr(r,"--alias");return r.length!==2?cr("usage: lmbee peers add <site-uuid> <mailbox> [--alias <name>]"):Tr(await Wv(r[0],r[1],n))}return t==="remove"?r.length!==1?cr("usage: lmbee peers remove <site-uuid>"):Tr(await Gv(r[0])):cr(a1())}catch(n){return em(n)}}function c1(e){let t=[...e];if(t.includes("--message-file"))throw new Ue("unknown option --message-file; use --prompt-file");let r=lr(t,"--prompt-file"),n=lr(t,"--from-team"),o=lr(t,"--from-alias"),[s,...i]=t;return{rawAddress:s,messageParts:i,promptFile:r,fromTeam:n,fromAlias:o}}async function VA(e){try{let{rawAddress:t,messageParts:r,promptFile:n,fromTeam:o,fromAlias:s}=c1(e);return Tr(await WA(t,r,{promptFile:n,fromTeam:o,fromAlias:s}))}catch(t){return em(t)}}async function JA(e){let[t,...r]=e;try{if(t==="register"){let n=lr(r,"--site-uuid"),o=lr(r,"--mailbox");return r.length!==1?cr(zr()):Tr(await Vv(r[0],{siteUuid:n,mailbox:o}))}if(t==="resolve")return r.length!==1?cr(zr()):await Jv(r[0]);if(t==="list")return r.length?cr(zr()):Tr(await Kv());if(t==="set-name"){let n=lr(r,"--uuid"),o=lr(r,"--mailbox");return n===void 0==(o===void 0)||r.length!==1?cr(zr()):Tr(await Qv(r[0],{uuid:n,mailbox:o}))}if(t==="clear-name"){let n=lr(r,"--uuid"),o=lr(r,"--mailbox");return n===void 0==(o===void 0)||r.length!==0?cr(zr()):Tr(await Xv({uuid:n,mailbox:o}))}return t==="remove"?r.length!==1?cr(zr()):Tr(await Zv(r[0])):cr(zr())}catch(n){return em(n)}}import{execFile as l1}from"node:child_process";import{promisify as u1}from"node:util";var d1=u1(l1),m1="lmbee.service";function f1(){return process.env.LMBEE_SYSTEMD_UNIT??m1}async function zA(e={}){let t=f1();if(!e.force)return{output:`lmbee shutdown: refusing to stop ${t} without --force -- this immediately stops queue delivery, mail polling, and anti-churn nudging. Re-run as \`lmbee shutdown --force\` to proceed.
|
|
973
|
+
`,exitCode:1};let r=e.execFileImpl??d1;try{await r("systemctl",["--user","stop",t])}catch(o){let s=o instanceof Error?o.message:String(o);return{output:`lmbee shutdown: systemctl --user stop ${t} failed: ${s}
|
|
974
974
|
`,exitCode:1}}let n;try{let{stdout:o}=await r("systemctl",["--user","is-active",t]);n=o.trim()}catch(o){let s=o&&typeof o=="object"&&"stdout"in o?String(o.stdout).trim():"";if(s.length===0){let i=o instanceof Error?o.message:String(o);return{output:`lmbee shutdown: ${t}: stop was issued, but its state could not be confirmed -- is-active check failed: ${i}
|
|
975
975
|
`,exitCode:1}}n=s}switch(n){case"inactive":return{output:`lmbee shutdown: ${t} stopped (state: ${n})
|
|
976
976
|
`,exitCode:0};case"active":return{output:`lmbee shutdown: stop reported success, but ${t} is active again (state: ${n})
|
|
977
977
|
`,exitCode:1};case"activating":case"deactivating":case"reloading":return{output:`lmbee shutdown: ${t} stop not yet confirmed -- unit is in a transitional state (state: ${n})
|
|
978
978
|
`,exitCode:1};default:return{output:`lmbee shutdown: ${t} stop not confirmed (state: ${n})
|
|
979
|
-
`,exitCode:1}}}function
|
|
979
|
+
`,exitCode:1}}}function p1(e,t,r){let n="";for(let o=0;o<e.length;o++){let s=e[o];t.atLineStart&&s!==`
|
|
980
980
|
`&&(n+=`${r()} `,t.atLineStart=!1),n+=s,s===`
|
|
981
|
-
`&&(t.atLineStart=!0)}return n}var
|
|
982
|
-
`}function
|
|
981
|
+
`&&(t.atLineStart=!0)}return n}var KA=!1;function YA(e=()=>new Date().toISOString()){if(!KA){KA=!0;for(let t of[process.stdout,process.stderr]){let r=t.write.bind(t),n={atLineStart:!0};t.write=(o,...s)=>r(typeof o=="string"?p1(o,n,e):o,...s)}}}function ko(e){return`${e instanceof Error?e.message:String(e)}
|
|
982
|
+
`}function E1(e){let t=tm(y1(),".lmbee");_1(t,{recursive:!0});let r=tm(t,"serve.log"),n=tm(t,"serve.pid"),o=g1(r,"a"),s=h1(process.execPath,[process.argv[1],...e],{detached:!0,stdio:["ignore",o,o]});s.unref(),s.pid!==void 0&&w1(n,`${s.pid}
|
|
983
983
|
`),process.stdout.write(`lmbee serve: started detached (pid ${s.pid??"?"}), log: ${r}, pidfile: ${n}
|
|
984
984
|
Stop it with: kill ${s.pid??"<pid>"}
|
|
985
|
-
`)}async function
|
|
986
|
-
`),0;if(e.length===1&&(e[0]==="--version"||e[0]==="-v"||e[0]==="-V")){let r=sl();return process.stdout.write(`lmbee ${
|
|
985
|
+
`)}async function b1(){let e=process.argv.slice(2);if(kT(e))return process.stdout.write(`${e[0]==="module"?Qd:Gr}
|
|
986
|
+
`),0;if(e.length===1&&(e[0]==="--version"||e[0]==="-v"||e[0]==="-V")){let r=sl();return process.stdout.write(`lmbee ${bp()} (${r.sha}${r.dirty?".dirty":""})
|
|
987
987
|
`),0}if(e[0]==="serve"){let{flags:r}=St(e.slice(1),["daemon","auto-continue","miniplayer-verify","hung-holder-check","epic-review","orphan-reconciler","orphan-reconciler-dry-run","hang-probe-collect","auto-nudge-redirect-review","rate-limit-collect","rate-limit-policy","rate-limit-automation","remote-mail","exec-worker","exec-allow-anonymous","publish","help"]);if(r.help===!0)return process.stdout.write(`${Gr}
|
|
988
|
-
`),0;if(r.daemon===!0)return
|
|
988
|
+
`),0;if(r.daemon===!0)return E1(e.filter(ae=>ae!=="--daemon")),0;YA();let n;try{process.env.LMBEE_SITE_UUID!==void 0&&vf(process.env.LMBEE_SITE_UUID),n=Li()}catch(ae){return process.stderr.write(ko(ae)),1}let o=r["remote-mail"]===!0,s=typeof r["remote-allow"]=="string"?r["remote-allow"]:void 0;if(o&&s===void 0)return process.stderr.write(`error: --remote-mail requires --remote-allow <user_id1,user_id2,...>
|
|
989
989
|
`),n.db.close(),1;if(!o&&s!==void 0)return process.stderr.write(`error: --remote-allow requires --remote-mail
|
|
990
|
-
`),n.db.close(),1;let i;if(o&&s!==void 0){let
|
|
991
|
-
`),n.db.close(),1;let M;try{M=Nn(n.db.db)}catch(j){return process.stderr.write(ko(j)),n.db.close(),1}try{let{appkey:j}=ve({env:process.env});i={client:wt({apiUrl:Nt(process.env),appkey:j}),localSiteId:M,mailbox:on(M),allowlist:
|
|
990
|
+
`),n.db.close(),1;let i;if(o&&s!==void 0){let ae=s.split(",").map(j=>j.trim()).filter(j=>j.length>0);if(ae.length===0)return process.stderr.write(`error: --remote-allow must name at least one sender user_id
|
|
991
|
+
`),n.db.close(),1;let M;try{M=Nn(n.db.db)}catch(j){return process.stderr.write(ko(j)),n.db.close(),1}try{let{appkey:j}=ve({env:process.env});i={client:wt({apiUrl:Nt(process.env),appkey:j}),localSiteId:M,mailbox:on(M),allowlist:ae}}catch(j){process.stderr.write(`[mail] --remote-mail setup failed, mail lane stays dormant this run: ${j instanceof Error?j.message:String(j)}
|
|
992
992
|
`)}}let a=r["exec-worker"]===!0,c=typeof r["exec-mailbox"]=="string"?r["exec-mailbox"]:void 0,l=typeof r["exec-admin"]=="string"?r["exec-admin"]:void 0,u=typeof r["exec-allow"]=="string"?r["exec-allow"]:void 0,d=r["exec-allow-anonymous"]===!0;if(!a&&c!==void 0)return process.stderr.write(`error: --exec-mailbox requires --exec-worker
|
|
993
|
-
`),n.db.close(),1;let m;if(a){let
|
|
994
|
-
`),n.db.close(),1;let
|
|
993
|
+
`),n.db.close(),1;let m;if(a){let ae=z=>(z??"").split(",").map(re=>re.trim()).filter(re=>re.length>0),M=new Set(ae(l)),j=new Set(ae(u));if(M.size===0&&j.size===0&&!d)return process.stderr.write(`error: --exec-worker requires at least one of --exec-admin, --exec-allow, or --exec-allow-anonymous
|
|
994
|
+
`),n.db.close(),1;let Y;try{Y=Nn(n.db.db)}catch(z){return process.stderr.write(ko(z)),n.db.close(),1}try{let{appkey:z}=ve({env:process.env}),re=c??Rn(Y);m={client:wt({apiUrl:Nt(process.env),appkey:z}),mailbox:re,adminUsers:M,allowUsers:j,allowAnonymous:d}}catch(z){process.stderr.write(`[exec-worker] --exec-worker setup failed, exec stays dormant this run: ${z instanceof Error?z.message:String(z)}
|
|
995
995
|
`)}}let f=typeof r.port=="string"?Number(r.port):void 0,p=r.publish===!0?!0:void 0,h=typeof r.hostname=="string"?r.hostname:void 0;if(h!==void 0&&!["127.0.0.1","::1","localhost"].includes(h)&&p===void 0)return process.stderr.write(`error: --hostname requires --publish for any non-loopback value
|
|
996
996
|
`),1;let g=typeof r["web-dist"]=="string"?r["web-dist"]:void 0,_=typeof r.interval=="string"?Number(r.interval):void 0,E=_n(r["queue-interval-ms"],"--queue-interval-ms");if(E instanceof Error)return process.stderr.write(`error: ${E.message}
|
|
997
997
|
`),1;let y=typeof r["maintainer-team"]=="string"?r["maintainer-team"]:void 0,S=typeof r["maintainer-prompt-file"]=="string"?r["maintainer-prompt-file"]:void 0;if(y===void 0!=(S===void 0))return process.stderr.write(`error: --maintainer-team and --maintainer-prompt-file must be given together
|
|
@@ -1001,24 +1001,24 @@ Stop it with: kill ${s.pid??"<pid>"}
|
|
|
1001
1001
|
`),1;let x=_n(r["maintainer-stale-threshold-ms"],"--maintainer-stale-threshold-ms");if(x instanceof Error)return process.stderr.write(`error: ${x.message}
|
|
1002
1002
|
`),1;let I=_n(r["maintainer-activity-freshness-ms"],"--maintainer-activity-freshness-ms");if(I instanceof Error)return process.stderr.write(`error: ${I.message}
|
|
1003
1003
|
`),1;if(I!==void 0&&y===void 0)return process.stderr.write(`error: --maintainer-activity-freshness-ms requires --maintainer-team and --maintainer-prompt-file
|
|
1004
|
-
`),1;let A=y!==void 0&&S!==void 0?{teamName:y,promptFile:S,...T!==void 0?{sessionAlivePath:T}:{},...R!==void 0?{sessionAliveFreshnessMs:R}:{},...I!==void 0?{activityFreshnessMs:I}:{},...x!==void 0?{maintainerStaleThresholdMs:x}:{}}:void 0,H=r["auto-continue"]===!0?{}:void 0,L=r["miniplayer-verify"]===!0?{}:void 0,w=r["hung-holder-check"]===!0?{}:void 0,b=r["epic-review"]===!0?{}:void 0,N=r["orphan-reconciler-dry-run"]===!0,D=r["orphan-reconciler"]===!0||N?{dryRun:N}:void 0,W=r["hang-probe-collect"]===!0?{}:void 0,ee=r["auto-nudge-redirect-review"]===!0?!0:void 0,
|
|
1004
|
+
`),1;let A=y!==void 0&&S!==void 0?{teamName:y,promptFile:S,...T!==void 0?{sessionAlivePath:T}:{},...R!==void 0?{sessionAliveFreshnessMs:R}:{},...I!==void 0?{activityFreshnessMs:I}:{},...x!==void 0?{maintainerStaleThresholdMs:x}:{}}:void 0,H=r["auto-continue"]===!0?{}:void 0,L=r["miniplayer-verify"]===!0?{}:void 0,w=r["hung-holder-check"]===!0?{}:void 0,b=r["epic-review"]===!0?{}:void 0,N=r["orphan-reconciler-dry-run"]===!0,D=r["orphan-reconciler"]===!0||N?{dryRun:N}:void 0,W=r["hang-probe-collect"]===!0?{}:void 0,ee=r["auto-nudge-redirect-review"]===!0?!0:void 0,ne=r["rate-limit-collect"]===!0?{}:void 0,J=r["rate-limit-policy"]===!0?{}:void 0,oe=r["rate-limit-automation"]===!0?{}:void 0,k=_n(r["idle-threshold-ms"],"--idle-threshold-ms"),O=_n(r["cooldown-ms"],"--cooldown-ms");if(k instanceof Error)return process.stderr.write(`error: ${k.message}
|
|
1005
1005
|
`),1;if(O instanceof Error)return process.stderr.write(`error: ${O.message}
|
|
1006
1006
|
`),1;let $=lo(r["min-memory-percent"],"--min-memory-percent");if($ instanceof Error)return process.stderr.write(`error: ${$.message}
|
|
1007
|
-
`),1;let q=$??Uc,U=k!==void 0||O!==void 0?{idleThresholdMs:k??he.idleThresholdMs,cooldownMs:O??he.cooldownMs}:void 0,Z;try{Z=await
|
|
1007
|
+
`),1;let q=$??Uc,U=k!==void 0||O!==void 0?{idleThresholdMs:k??he.idleThresholdMs,cooldownMs:O??he.cooldownMs}:void 0,Z;try{Z=await lb({context:n,...f!==void 0?{port:f}:{},...p!==void 0?{publish:p}:{},...h!==void 0?{hostname:h}:{},..._!==void 0?{intervalMs:_}:{},...E!==void 0?{queueIntervalMs:E}:{},...U!==void 0?{config:U}:{},...A!==void 0?{maintainerWake:A}:{},...b!==void 0?{epicReview:b}:{},...D!==void 0?{orphanReconciler:D}:{},...W!==void 0?{hangProbeCollect:W}:{},...ee!==void 0?{autoNudgeRedirectReview:ee}:{},...ne!==void 0?{rateLimitCollect:ne}:{},...J!==void 0?{rateLimitPolicy:J}:{},...oe!==void 0?{rateLimitAutomation:oe}:{},...H!==void 0?{autoContinue:H}:{},...L!==void 0?{miniplayerVerify:L}:{},...w!==void 0?{hungHolderCheck:w}:{},...i!==void 0?{remoteMail:i}:{},...m!==void 0?{execWorker:m}:{},...g!==void 0?{webDistDir:g}:{},minMemoryPercent:q})}catch(ae){return process.stderr.write(`${ae instanceof Error?ae.message:String(ae)}
|
|
1008
1008
|
`),n.db.close(),1}process.stdout.write(`lmbee serve: listening on http://${Z.hostname}:${Z.port}
|
|
1009
1009
|
`);let G=sl();process.stdout.write(`lmbee serve: build ${G.sha}${G.dirty?" (dirty)":""}, built ${G.builtAt}
|
|
1010
|
-
`);let
|
|
1011
|
-
`)}).finally(()=>{n.db.close(),process.exit(0)}))};return process.on("SIGINT",be),process.on("SIGTERM",be),new Promise(()=>{})}if(e[0]==="whoami"){let{flags:r}=St(e.slice(1),["json"]),{output:n,exitCode:o}=await
|
|
1012
|
-
`),o}if(e[0]==="peers"||e[0]==="tell"||e[0]==="sites"){let r=e.slice(1),{output:n,exitCode:o}=e[0]==="peers"?await
|
|
1013
|
-
`),o}if(e[0]==="localweb"){let{output:r,exitCode:n}=await
|
|
1014
|
-
`),n}if(
|
|
1015
|
-
`),n}if(e[0]==="exec"||e[0]==="fleet"){let r=e.slice(1),{output:n,exitCode:o}=e[0]==="exec"?await
|
|
1010
|
+
`);let ie=!1,be=()=>{ie||(ie=!0,Z.shutdown().catch(ae=>{process.stderr.write(`lmbee serve: error during graceful shutdown: ${ae instanceof Error?ae.message:String(ae)}
|
|
1011
|
+
`)}).finally(()=>{n.db.close(),process.exit(0)}))};return process.on("SIGINT",be),process.on("SIGTERM",be),new Promise(()=>{})}if(e[0]==="whoami"){let{flags:r}=St(e.slice(1),["json"]),{output:n,exitCode:o}=await lE({json:r.json===!0});return n&&process.stdout.write(`${n}
|
|
1012
|
+
`),o}if(e[0]==="peers"||e[0]==="tell"||e[0]==="sites"){let r=e.slice(1),{output:n,exitCode:o}=e[0]==="peers"?await GA(r):e[0]==="tell"?await VA(r):await JA(r);return n&&process.stdout.write(`${n}
|
|
1013
|
+
`),o}if(e[0]==="localweb"){let{output:r,exitCode:n}=await jA(e.slice(1));return r&&process.stdout.write(`${r}
|
|
1014
|
+
`),n}if(kv(e[0]??""))return await xv(e[0],e.slice(1));if(e[0]==="module"){let{stdout:r,stderr:n,exitCode:o}=await UA(e.slice(1));return r&&process.stdout.write(r),n&&process.stderr.write(n),o}if(e[0]==="lmsound"){let{output:r,exitCode:n}=await Rv(e.slice(1));return r&&process.stdout.write(`${r}
|
|
1015
|
+
`),n}if(e[0]==="exec"||e[0]==="fleet"){let r=e.slice(1),{output:n,exitCode:o}=e[0]==="exec"?await oA(r):await sA(r);return n&&process.stdout.write(`${n}
|
|
1016
1016
|
`),o}if(e[0]==="migrate-home"){let{flags:r,positionals:n}=St(e.slice(1),["help","replace-existing-target-db"]);if(r.help===!0)return process.stdout.write(`${Gr}
|
|
1017
1017
|
`),0;if(n.length>0)return process.stderr.write(`lmbee migrate-home: does not accept positional arguments (got: ${n.join(" ")}). --replace-existing-target-db is a bare boolean flag: its presence alone grants consent to DELETE and replace an existing target database -- omit it entirely to keep the refusal.
|
|
1018
|
-
`),1;let o=typeof r.source=="string"?r.source:void 0,s=typeof r.target=="string"?r.target:void 0;try{let{output:i,exitCode:a}=await
|
|
1018
|
+
`),1;let o=typeof r.source=="string"?r.source:void 0,s=typeof r.target=="string"?r.target:void 0;try{let{output:i,exitCode:a}=await pA({source:o,target:s,replaceExistingTargetDb:r["replace-existing-target-db"]===!0});return i&&process.stdout.write(`${i}
|
|
1019
1019
|
`),a}catch(i){return process.stderr.write(ko(i)),1}}if(e[0]==="shutdown"){let{flags:r}=St(e.slice(1),["help","force"]);if(r.help===!0)return process.stdout.write(`${Gr}
|
|
1020
|
-
`),0;let{output:n,exitCode:o}=await
|
|
1021
|
-
`),n}catch(r){return process.stderr.write(ko(r)),1}if(e[0]==="cron"&&e[1]==="import"){let{positionals:r,flags:n}=St(e.slice(2),["json","help"]);if(n.help!==!0){let o=n.json===!0;try{Es("import",r,n);let s=r[0];if(s===void 0)throw new P("INVALID_ARGUMENT","an import PATH is required");
|
|
1020
|
+
`),0;let{output:n,exitCode:o}=await zA({force:r.force===!0});return n&&process.stdout.write(n),o}if(e[0]==="cron"&&e[1]==="export")try{let{output:r,exitCode:n}=fb(e.slice(2));return r&&process.stdout.write(`${r}
|
|
1021
|
+
`),n}catch(r){return process.stderr.write(ko(r)),1}if(e[0]==="cron"&&e[1]==="import"){let{positionals:r,flags:n}=St(e.slice(2),["json","help"]);if(n.help!==!0){let o=n.json===!0;try{Es("import",r,n);let s=r[0];if(s===void 0)throw new P("INVALID_ARGUMENT","an import PATH is required");gb(s)}catch(s){if(s instanceof P)return process.stdout.write(o?`${JSON.stringify({schema_version:1,ok:!1,error:{code:s.code,message:s.message}})}
|
|
1022
1022
|
`:`${s.code}: ${s.message}
|
|
1023
|
-
`),s.exitCode;throw s}}}let t;try{t=Li({readOnly:
|
|
1024
|
-
`),n}catch(r){return process.stderr.write(ko(r)),1}finally{t?.db.close()}}
|
|
1023
|
+
`),s.exitCode;throw s}}}let t;try{t=Li({readOnly:xT(e)});let{output:r,exitCode:n}=await RT(t,e);return r&&process.stdout.write(`${r}
|
|
1024
|
+
`),n}catch(r){return process.stderr.write(ko(r)),1}finally{t?.db.close()}}b1().then(e=>{process.exitCode=e});
|