@lmctl-ai/lmctl 0.2.382 → 0.2.384

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/lmbee.js CHANGED
@@ -2163,7 +2163,7 @@ ${a}
2163
2163
  WHERE id = ? AND enabled = 1 AND revision = ? AND running_since_ts = ? AND running_systemd_unit = ?`).run("reconciled",s,t.id,t.revision,t.running_since_ts,t.running_systemd_unit),Dy(e,t.id,"reconciled: command execution confirmed gone by systemd probe; no exit callback survived the restart");return}e.prepare("UPDATE cron_jobs SET last_fire_status = ?, updated_at = ? WHERE id = ? AND enabled = 1 AND revision = ? AND running_since_ts = ?").run("skipped_overlap",s,t.id,t.revision,t.running_since_ts);return}let p=t.last_checked_ts!==null?Date.parse(t.last_checked_ts):Date.parse(t.created_at);if(p>r){eo(e,"UPDATE cron_jobs SET last_checked_ts = ?, last_fire_status = ?, last_fire_error = ?, updated_at = ?",[s,"error",`last_checked_ts (${t.last_checked_ts??t.created_at}) is after the current tick time -- checkpoint reset without firing`,s],t);return}let h=new Date(p),_=new Date(r);if(r-p>F9){eo(e,"UPDATE cron_jobs SET last_checked_ts = ?, last_fire_status = ?, updated_at = ?",[s,"skipped_stale",s],t);return}let g=t.timezone!==null?mC(h,t.timezone):h,w=t.timezone!==null?mC(_,t.timezone):_;if(!Y0(m,g,w)){eo(e,"UPDATE cron_jobs SET last_checked_ts = ?, updated_at = ?",[s,s],t);return}let E=bm(e,t.id);if(!(E===null||E.enabled===0||E.revision!==t.revision)){if(P9(t.action_kind)){B9(e,t,s,l,d,u);return}if(t.action_kind==="enqueue")try{let T=JSON.parse(t.action_payload),b={from:T.from??"autopilot",dedupeKey:`cron:${t.id}:${h.toISOString()}`};e.transaction(()=>{let I=e.prepare("SELECT enabled, revision, last_checked_ts FROM cron_jobs WHERE id = ?").get(t.id);return I===void 0||I.enabled===0||I.revision!==t.revision||I.last_checked_ts!==t.last_checked_ts?!1:(o(e,n,T.to,T.prompt,b),e.prepare("UPDATE cron_jobs SET last_checked_ts = ?, last_fired_ts = ?, last_fire_status = ?, last_fire_error = NULL, updated_at = ? WHERE id = ?").run(s,s,"ok",s,t.id),!0)}).immediate()&&l.push(t.title)}catch(T){try{d?.(t.id,T)}catch{}try{eo(e,"UPDATE cron_jobs SET last_fire_status = ?, last_fire_error = ?, updated_at = ?",["error",Nn(T),s],t)}catch{}}else{let T=s,b=`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 = ?
2164
2164
  WHERE id = ? AND enabled = 1 AND revision = ? AND (last_checked_ts IS ?) AND (running_since_ts IS ?)`).run(s,s,"ok",s,b,s,t.id,t.revision,t.last_checked_ts,t.running_since_ts).changes===0)return;let I=AC(e,t,t.action_kind,b,a),R={logDir:c,systemdUnitName:b,onExit:(L,N,k,D)=>{let O=L===0?"ok":"error",v=O==="ok"?null:N?Nn(N):`Command exited with code ${L} -- see ${c??Em()}/${t.id}/ for output`;if(N)try{d?.(t.id,N)}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(O,v,new Date().toISOString(),t.id,T)}catch{}IC(e,I,L,N,k,D,b)}};try{i({id:t.id,action_payload:t.action_payload},R),l.push(t.title)}catch(L){try{d?.(t.id,L)}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",Nn(L),s,t.id,T)}catch{}kC(e,I,L)}}}}async function pC(e,t){for(;!e();)await new Promise(n=>setTimeout(n,t))}async function xl(e,t,n,r={}){let s=r.enqueueImpl??Ne,o=r.spawnCommandImpl??yl,i=r.isUnitStillRunningImpl??SC,a=r.executeRunImpl??Oy,c=r.logDir,l=r.pollMs??250,d=it(e,t);if(gl(e,t)&&r.onDemand===void 0)return{kind:"skipped_overlap",job:d};if(d.enabled===0)throw new G("DISABLED",`Cron job ${t} is disabled -- enable it first (\`cron enable ${t}\`), or a manual trigger would silently exercise a job the operator turned off on purpose`,4);let u=Te();if(d.action_kind==="command"){if(d.running_since_ts!==null)return d.running_systemd_unit!==null&&i(d.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 = ?
2165
2165
  WHERE id = ? AND revision = ? AND running_since_ts = ? AND running_systemd_unit = ?`).run("reconciled",u,d.id,d.revision,d.running_since_ts,d.running_systemd_unit),Dy(e,d.id,"reconciled: command execution confirmed gone by systemd probe; no exit callback survived the restart"),await xl(e,t,n,r)):{kind:"skipped_overlap",job:d};let p=u,h=`lmcron-job-${d.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 = ?
2166
- WHERE id = ? AND enabled = 1 AND revision = ? AND running_since_ts IS ?`).run(u,"ok",p,h,u,d.id,d.revision,d.running_since_ts).changes===0)return{kind:"skipped_overlap",job:it(e,t)};let g=AC(e,d,`${d.action_kind}:manual`,h,i),w={logDir:c,systemdUnitName:h,onExit:(y,E,T,b)=>{let A=y===0?"ok":"error",I=A==="ok"?null:E?Nn(E):`Command exited with code ${y} -- see ${c??Em()}/${d.id}/ for output`;try{e.prepare("UPDATE cron_jobs SET running_since_ts = NULL, running_systemd_unit = NULL, last_fire_status = ?, last_fire_error = ?, updated_at = ? WHERE id = ? AND running_since_ts = ?").run(A,I,new Date().toISOString(),d.id,p)}catch{}IC(e,g,y,E,T,b,h)}};try{o({id:d.id,action_payload:d.action_payload},w)}catch(y){kC(e,g,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",Nn(y),u,d.id,p)}catch{}throw new G("SPAWN_FAILED",`manual trigger of job ${t} failed to spawn: ${Nn(y)}`,1)}return await pC(()=>it(e,t).running_since_ts!==p,l),{kind:"fired",job:it(e,t)}}if(d.action_kind==="enqueue"){let p=JSON.parse(d.action_payload);return s(e,n,p.to,p.prompt,{from:p.from??"autopilot"}),e.prepare("UPDATE cron_jobs SET last_fired_ts = ?, last_fire_status = ?, last_fire_error = NULL, updated_at = ? WHERE id = ?").run(u,"ok",u,d.id),{kind:"fired",job:it(e,t)}}let f=JSON.stringify({kind:d.action_kind,payload:d.action_payload,provider:d.provider,model:d.model,workingDirectory:d.working_directory,escalationOwner:d.escalation_owner}),m=e.transaction(()=>{let p=e.prepare("SELECT enabled, revision FROM cron_jobs WHERE id = ?").get(d.id);if(p===void 0||p.enabled===0||p.revision!==d.revision)return null;let h=bl(e,d.id,`${d.action_kind}:manual`,f);if(h.kind==="claimed"){r.onDemand!==void 0&&V0(e,d.id,h.run.id,r.onDemand);let _=r.disableOnClaim?"enabled = 0, ":"";e.prepare(`UPDATE cron_jobs SET ${_}last_fired_ts = ?, last_fire_status = ?, last_fire_error = NULL, updated_at = ? WHERE id = ?`).run(u,"ok",u,d.id)}return h}).immediate();if(m===null)throw new G("CONFLICT",`Cron job ${t} was modified concurrently -- re-run \`cron trigger ${t}\``,5);if(m.kind==="escalation")return{kind:"blocked_escalation",job:it(e,t)};if(m.kind==="overlap")return{kind:"skipped_overlap",job:it(e,t)};try{a({db:e,job:d,run:m.run,runToken:m.token,...r.onDemand!==void 0?{onDemand:r.onDemand}:{},...r.runSpawnPrefixes!==void 0?{spawnPrefixes:r.runSpawnPrefixes}:{},...r.sessionDir!==void 0?{sessionDir:r.sessionDir}:{},...r.runTimeoutMs!==void 0?{timeoutMs:r.runTimeoutMs}:{},...r.runSeedTimeoutMs!==void 0?{seedTimeoutMs:r.runSeedTimeoutMs}:{}})}catch(p){try{Il(e,m.run.id,`worker dispatch threw: ${Nn(p)}`),Sy(e,m.run.id,{ok:!1,summary:`worker dispatch error: ${Nn(p)}`})}catch{}throw new G("SPAWN_FAILED",`manual trigger of job ${t} failed to dispatch: ${Nn(p)}`,1)}if(r.waitForCompletion===!1){let p=d;try{p=it(e,t)}catch(h){console.warn(`[triggerCronJobNow] post-dispatch getCronJob read failed for job ${t}:`,h)}return{kind:"fired",job:p,runId:m.run.id}}return await pC(()=>{let p=bt(e,m.run.id);return p.status!=="pending"&&p.status!=="running"},l),{kind:"fired",job:it(e,t),runId:m.run.id}}function B9(e,t,n,r,s,o){if(gl(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=bl(e,t.id,t.action_kind,i);return l.kind==="claimed"&&e.prepare("UPDATE cron_jobs SET last_checked_ts = ?, last_fired_ts = ?, last_fire_status = ?, last_fire_error = NULL, updated_at = ? WHERE id = ?").run(n,n,"ok",n,t.id),l}).immediate();if(a!==null){if(a.kind==="escalation"){eo(e,"UPDATE cron_jobs SET last_fire_status = ?, updated_at = ?",["blocked_escalation",n],t);return}if(a.kind==="overlap"){eo(e,"UPDATE cron_jobs SET last_fire_status = ?, updated_at = ?",["skipped_overlap",n],t);return}r.push(t.title);try{o.executeRunImpl({db:e,job:t,run:a.run,runToken:a.token,...o.runSpawnPrefixes!==void 0?{spawnPrefixes:o.runSpawnPrefixes}:{},...o.sessionDir!==void 0?{sessionDir:o.sessionDir}:{},...o.runTimeoutMs!==void 0?{timeoutMs:o.runTimeoutMs}:{},...o.runSeedTimeoutMs!==void 0?{seedTimeoutMs:o.runSeedTimeoutMs}:{}})}catch(c){try{Il(e,a.run.id,`worker dispatch threw: ${Nn(c)}`),Sy(e,a.run.id,{ok:!1,summary:`worker dispatch error: ${Nn(c)}`})}catch{}try{s?.(t.id,c)}catch{}}}}function eo(e,t,n,r){e.prepare(`${t} WHERE id = ? AND enabled = 1 AND revision = ? AND (last_checked_ts IS ?)`).run(...n,r.id,r.revision,r.last_checked_ts)}function RC(e,t){let n=e.transaction(()=>{it(e,t);try{e.prepare("UPDATE cron_jobs SET running_since_ts = NULL, running_systemd_unit = NULL WHERE id = ?").run(t)}catch(r){wa(r)}return Sm(e,t),it(e,t)});return rs(n)}import{execFileSync as G9}from"node:child_process";import{existsSync as X9,readFileSync as NC}from"node:fs";import{homedir as xC}from"node:os";import{join as LC}from"node:path";function Sa(){return process.env.LMBEE_HEAVY_STATUS??LC(xC(),".lmbee","heavy.status")}function ba(){return process.env.LMBEE_HEAVY_LOCK??LC(xC(),".lmbee","heavy.lock")}var va=class extends Error{};function V9(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 J9(e){let t;try{t=NC(e,"utf8")}catch{return null}try{let n=JSON.parse(t);return V9(n)?n:null}catch{return null}}function Y9(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 K9(e){try{let t=NC(`/proc/${e}/stat`,"utf8");return t.slice(t.lastIndexOf(")")+2).trim().split(/\s+/)[0]==="Z"}catch{return!1}}function z9(e){try{process.kill(e,0)}catch(t){return t.code==="EPERM"}return!K9(e)}function Q9(e,t=G9){if(!X9(e))return!1;try{return t("flock",["-n",e,"-c","true"],{stdio:"ignore"}),!1}catch(n){if((n&&typeof n=="object"?n.status:void 0)===1)return!0;let s=n instanceof Error?n.message:String(n);throw new va(`heavy-lock probe failed (flock did not run or exited abnormally): ${s}`)}}function $y(e=Sa(),t=ba(),n=J9,r=Q9,s=z9){for(let o=0;o<3;o++){let i=n(e),a=r(t),c=n(e);if(i!==null&&Y9(i,c)){if(!a)return{held:!1,holder:null};if(s(i.pid))return{held:!0,holder:i}}}return{held:r(t),holder:null}}function fn(e=Sa(),t=ba(),n=$y,r){try{return n(e,t)}catch(s){if(!(s instanceof va))throw s;return r?.(s),{held:!0,holder:null}}}var Im={observedAt:null,report:null,lastErrorAt:null,lastError:null};function CC(e,t){Im={observedAt:t,report:e,lastErrorAt:null,lastError:null}}function OC(e,t){Im={...Im,lastErrorAt:t,lastError:e}}function Ll(){return Im}import{execFile as Z9}from"node:child_process";import{promisify as e7}from"node:util";function ve(e){if(!Number.isFinite(e)||e<0)return"?";if(e<1e3)return"0s";if(e<6e4)return`${Math.floor(e/1e3)}s`;if(e<36e5)return`${Math.floor(e/6e4)}m`;if(e<864e5*2)return`${Math.floor(e/36e5)}h`;let t=Math.floor(e/864e5),n=Math.floor(e%864e5/36e5);return n===0?`${t}d`:`${t}d ${n}h`}function ke(e,t=Date.now()){let n=Date.parse(e);if(Number.isNaN(n))return"?";let r=t-n;return r<6e4?"just now":`${ve(r)} ago`}var t7=e7(Z9);function n7(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 r7(e){let t=JSON.parse(e);if(typeof t!="object"||t===null||!Array.isArray(t.running)||!Array.isArray(t.dead)||!Array.isArray(t.idle))throw new Error("unexpected `lmctl running --json` shape: missing running/dead/idle arrays");let n=t;for(let r of["running","dead","idle"])if(!n[r].every(n7))throw new Error(`unexpected \`lmctl running --json\` shape: a malformed element (bad/missing target or from_identity) in \`${r}\``);return n}async function Je(e=3e4,t={}){let n=t.reconcile===!0?["running","--json","--reconcile"]:["running","--json"],{stdout:r}=await t7("lmctl",n,{timeout:e});return r7(r)}function My(e,t=Date.now()){return{schema_version:e.schema_version,running:e.running.map(n=>({...n,running_for_human:ve(n.running_for_ms),started_human:ke(n.started_at,t)})),dead:e.dead.map(n=>({...n,stale_for_human:ve(n.stale_for_ms),started_human:ke(n.started_at,t)})),idle:e.idle.map(n=>({...n,ran_human:ve(n.ran_ms)}))}}import{readFileSync as s7}from"node:fs";import{randomUUID as o7}from"node:crypto";var Py={staleThresholdMs:2*60*6e4,escalationCooldownMs:60*6e4,digestTimeoutMs:9e4,leaseTimeoutMs:10*6e4,providerQuotaBackoffMs:24*60*6e4,operatorStaleThresholdMs:6e4,operatorEscalationCooldownMs:6e4};function i7(e){return/usage limit/i.test(e)&&/quota/i.test(e)}function a7(e){let t=[];for(let n of e)try{t.push({row:n,content:s7(n.prompt_file,"utf8")})}catch{continue}return t}function c7(e){let t=e.map(({row:n,content:r})=>`--- from "${n.from_id}", queued ${n.created_ts} ---
2166
+ WHERE id = ? AND enabled = 1 AND revision = ? AND running_since_ts IS ?`).run(u,"ok",p,h,u,d.id,d.revision,d.running_since_ts).changes===0)return{kind:"skipped_overlap",job:it(e,t)};let g=AC(e,d,`${d.action_kind}:manual`,h,i),w={logDir:c,systemdUnitName:h,onExit:(y,E,T,b)=>{let A=y===0?"ok":"error",I=A==="ok"?null:E?Nn(E):`Command exited with code ${y} -- see ${c??Em()}/${d.id}/ for output`;try{e.prepare("UPDATE cron_jobs SET running_since_ts = NULL, running_systemd_unit = NULL, last_fire_status = ?, last_fire_error = ?, updated_at = ? WHERE id = ? AND running_since_ts = ?").run(A,I,new Date().toISOString(),d.id,p)}catch{}IC(e,g,y,E,T,b,h)}};try{o({id:d.id,action_payload:d.action_payload},w)}catch(y){kC(e,g,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",Nn(y),u,d.id,p)}catch{}throw new G("SPAWN_FAILED",`manual trigger of job ${t} failed to spawn: ${Nn(y)}`,1)}return await pC(()=>it(e,t).running_since_ts!==p,l),{kind:"fired",job:it(e,t)}}if(d.action_kind==="enqueue"){let p=JSON.parse(d.action_payload);return s(e,n,p.to,p.prompt,{from:p.from??"autopilot"}),e.prepare("UPDATE cron_jobs SET last_fired_ts = ?, last_fire_status = ?, last_fire_error = NULL, updated_at = ? WHERE id = ?").run(u,"ok",u,d.id),{kind:"fired",job:it(e,t)}}let f=JSON.stringify({kind:d.action_kind,payload:d.action_payload,provider:d.provider,model:d.model,workingDirectory:d.working_directory,escalationOwner:d.escalation_owner}),m=e.transaction(()=>{let p=e.prepare("SELECT enabled, revision FROM cron_jobs WHERE id = ?").get(d.id);if(p===void 0||p.enabled===0||p.revision!==d.revision)return null;let h=bl(e,d.id,`${d.action_kind}:manual`,f);if(h.kind==="claimed"){r.onDemand!==void 0&&V0(e,d.id,h.run.id,r.onDemand);let _=r.disableOnClaim?"enabled = 0, ":"";e.prepare(`UPDATE cron_jobs SET ${_}last_fired_ts = ?, last_fire_status = ?, last_fire_error = NULL, updated_at = ? WHERE id = ?`).run(u,"ok",u,d.id)}return h}).immediate();if(m===null)throw new G("CONFLICT",`Cron job ${t} was modified concurrently -- re-run \`cron trigger ${t}\``,5);if(m.kind==="escalation")return{kind:"blocked_escalation",job:it(e,t)};if(m.kind==="overlap")return{kind:"skipped_overlap",job:it(e,t)};try{a({db:e,job:d,run:m.run,runToken:m.token,...r.onDemand!==void 0?{onDemand:r.onDemand}:{},...r.runSpawnPrefixes!==void 0?{spawnPrefixes:r.runSpawnPrefixes}:{},...r.sessionDir!==void 0?{sessionDir:r.sessionDir}:{},...r.runTimeoutMs!==void 0?{timeoutMs:r.runTimeoutMs}:{},...r.runSeedTimeoutMs!==void 0?{seedTimeoutMs:r.runSeedTimeoutMs}:{}})}catch(p){try{Il(e,m.run.id,`worker dispatch threw: ${Nn(p)}`),Sy(e,m.run.id,{ok:!1,summary:`worker dispatch error: ${Nn(p)}`})}catch{}throw new G("SPAWN_FAILED",`manual trigger of job ${t} failed to dispatch: ${Nn(p)}`,1)}if(r.waitForCompletion===!1){let p=d;try{p=it(e,t)}catch(h){console.warn(`[triggerCronJobNow] post-dispatch getCronJob read failed for job ${t}:`,h)}return{kind:"fired",job:p,runId:m.run.id}}return await pC(()=>{let p=bt(e,m.run.id);return p.status!=="pending"&&p.status!=="running"},l),{kind:"fired",job:it(e,t),runId:m.run.id}}function B9(e,t,n,r,s,o){if(gl(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=bl(e,t.id,t.action_kind,i);return l.kind==="claimed"&&e.prepare("UPDATE cron_jobs SET last_checked_ts = ?, last_fired_ts = ?, last_fire_status = ?, last_fire_error = NULL, updated_at = ? WHERE id = ?").run(n,n,"ok",n,t.id),l}).immediate();if(a!==null){if(a.kind==="escalation"){eo(e,"UPDATE cron_jobs SET last_fire_status = ?, updated_at = ?",["blocked_escalation",n],t);return}if(a.kind==="overlap"){eo(e,"UPDATE cron_jobs SET last_fire_status = ?, updated_at = ?",["skipped_overlap",n],t);return}r.push(t.title);try{o.executeRunImpl({db:e,job:t,run:a.run,runToken:a.token,...o.runSpawnPrefixes!==void 0?{spawnPrefixes:o.runSpawnPrefixes}:{},...o.sessionDir!==void 0?{sessionDir:o.sessionDir}:{},...o.runTimeoutMs!==void 0?{timeoutMs:o.runTimeoutMs}:{},...o.runSeedTimeoutMs!==void 0?{seedTimeoutMs:o.runSeedTimeoutMs}:{}})}catch(c){try{Il(e,a.run.id,`worker dispatch threw: ${Nn(c)}`),Sy(e,a.run.id,{ok:!1,summary:`worker dispatch error: ${Nn(c)}`})}catch{}try{s?.(t.id,c)}catch{}}}}function eo(e,t,n,r){e.prepare(`${t} WHERE id = ? AND enabled = 1 AND revision = ? AND (last_checked_ts IS ?)`).run(...n,r.id,r.revision,r.last_checked_ts)}function RC(e,t){let n=e.transaction(()=>{it(e,t);try{e.prepare("UPDATE cron_jobs SET running_since_ts = NULL, running_systemd_unit = NULL WHERE id = ?").run(t)}catch(r){wa(r)}return Sm(e,t),it(e,t)});return rs(n)}import{execFileSync as G9}from"node:child_process";import{existsSync as X9,readFileSync as NC}from"node:fs";import{homedir as xC}from"node:os";import{join as LC}from"node:path";function Sa(){return process.env.LMBEE_HEAVY_STATUS??LC(xC(),".lmbee","heavy.status")}function ba(){return process.env.LMBEE_HEAVY_LOCK??LC(xC(),".lmbee","heavy.lock")}var va=class extends Error{};function V9(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 J9(e){let t;try{t=NC(e,"utf8")}catch{return null}try{let n=JSON.parse(t);return V9(n)?n:null}catch{return null}}function Y9(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 K9(e){try{let t=NC(`/proc/${e}/stat`,"utf8");return t.slice(t.lastIndexOf(")")+2).trim().split(/\s+/)[0]==="Z"}catch{return!1}}function z9(e){try{process.kill(e,0)}catch(t){return t.code==="EPERM"}return!K9(e)}function Q9(e,t=G9){if(!X9(e))return!1;try{return t("flock",["-n",e,"-c","true"],{stdio:"ignore"}),!1}catch(n){if((n&&typeof n=="object"?n.status:void 0)===1)return!0;let s=n instanceof Error?n.message:String(n);throw new va(`heavy-lock probe failed (flock did not run or exited abnormally): ${s}`)}}function $y(e=Sa(),t=ba(),n=J9,r=Q9,s=z9){for(let o=0;o<3;o++){let i=n(e),a=r(t),c=n(e);if(i!==null&&Y9(i,c)){if(!a)return{held:!1,holder:null};if(s(i.pid))return{held:!0,holder:i}}}return{held:r(t),holder:null}}function fn(e=Sa(),t=ba(),n=$y,r){try{return n(e,t)}catch(s){if(!(s instanceof va))throw s;return r?.(s),{held:!0,holder:null}}}var Im={observedAt:null,report:null,lastErrorAt:null,lastError:null};function CC(e,t){Im={observedAt:t,report:e,lastErrorAt:null,lastError:null}}function OC(e,t){Im={...Im,lastErrorAt:t,lastError:e}}function Ll(){return Im}import{execFile as Z9}from"node:child_process";import{promisify as e7}from"node:util";function ve(e){if(!Number.isFinite(e)||e<0)return"?";if(e<1e3)return"0s";if(e<6e4)return`${Math.floor(e/1e3)}s`;if(e<36e5)return`${Math.floor(e/6e4)}m`;if(e<864e5*2)return`${Math.floor(e/36e5)}h`;let t=Math.floor(e/864e5),n=Math.floor(e%864e5/36e5);return n===0?`${t}d`:`${t}d ${n}h`}function ke(e,t=Date.now()){let n=Date.parse(e);if(Number.isNaN(n))return"?";let r=t-n;return r<6e4?"just now":`${ve(r)} ago`}var t7=e7(Z9);function n7(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 r7(e){let t=JSON.parse(e);if(typeof t!="object"||t===null||!Array.isArray(t.running)||!Array.isArray(t.dead)||!Array.isArray(t.idle))throw new Error("unexpected `lmctl running --json` shape: missing running/dead/idle arrays");let n=t;for(let r of["running","dead","idle"])if(!n[r].every(n7))throw new Error(`unexpected \`lmctl running --json\` shape: a malformed element (bad/missing target or from_identity) in \`${r}\``);return n}async function Je(e=3e4,t={}){let n=t.reconcile===!0?["running","--json","--reconcile"]:["running","--json"],{stdout:r}=await t7("lmctl",n,{timeout:e});return r7(r)}function My(e,t=Date.now()){return{schema_version:e.schema_version,running:e.running.map(n=>({...n,running_for_human:ve(n.running_for_ms),started_human:ke(n.started_at,t)})),dead:e.dead.map(n=>({...n,age_human:ve(n.age_ms),started_human:ke(n.started_at,t)})),idle:e.idle.map(n=>({...n,ran_human:ve(n.ran_ms)}))}}import{readFileSync as s7}from"node:fs";import{randomUUID as o7}from"node:crypto";var Py={staleThresholdMs:2*60*6e4,escalationCooldownMs:60*6e4,digestTimeoutMs:9e4,leaseTimeoutMs:10*6e4,providerQuotaBackoffMs:24*60*6e4,operatorStaleThresholdMs:6e4,operatorEscalationCooldownMs:6e4};function i7(e){return/usage limit/i.test(e)&&/quota/i.test(e)}function a7(e){let t=[];for(let n of e)try{t.push({row:n,content:s7(n.prompt_file,"utf8")})}catch{continue}return t}function c7(e){let t=e.map(({row:n,content:r})=>`--- from "${n.from_id}", queued ${n.created_ts} ---
2167
2167
  ${r}`);return`You have ${e.length} queued message(s) that couldn't be delivered automatically (presence-gated for a while) -- bundled here as a digest:
2168
2168
 
2169
2169
  ${t.join(`
@@ -2414,7 +2414,7 @@ label: ${t.label}
2414
2414
  appkey source: ${t.appkeySource}`,exitCode:n}}import{execFile as Kne}from"node:child_process";import{promisify as zne}from"node:util";var Qne=zne(Kne);async function OM(e,t=3e4){let n=e.trim().split(/\s+/).filter(Boolean),{stdout:r}=await Qne("lmctl",["status",...n,"--json"],{timeout:t}),s;try{s=JSON.parse(r)}catch(o){throw new Error(`unexpected \`lmctl status --json\` output (not valid JSON): ${o instanceof Error?o.message:String(o)}`)}if(typeof s!="object"||s===null||Array.isArray(s))throw new Error("unexpected `lmctl status --json` shape: expected a JSON object");return s}import{execFile as Zne}from"node:child_process";import{existsSync as ere}from"node:fs";import{promisify as tre}from"node:util";var nre=tre(Zne),op=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 Hw(e){let t=e.cliPath??process.env.LMBI_SUBSCRIPTION_CLI;if(t===void 0||t==="")throw new op;let n=e.execFileImpl??nre,{stdout:r}=await n("node",[t,e.configPath,"--json"],{timeout:e.timeoutMs??3e4});return JSON.parse(r)}async function DM(e={}){let t=e.configPath??process.env.LMBI_SUBSCRIPTION_CONFIG_PATH;if(t===void 0||t===""||!ere(t))return{status:200,body:{needs_configuration:!0}};try{return{status:200,body:await Hw({configPath:t,cliPath:e.cliPath,execFileImpl:e.execFileImpl})}}catch(n){return n instanceof op?{status:500,body:{error:n.message}}:{status:502,body:{error:n instanceof Error?n.message:String(n)}}}}import{createHash as FM,randomBytes as ore,timingSafeEqual as ire}from"node:crypto";var $M=e=>{let t=e.env.server?e.env.server:e.env,n=t.incoming.socket.remoteAddress,r=t.incoming.socket.remotePort,s=t.incoming.socket.remoteFamily;return{remote:{address:n,port:r,addressType:s==="IPv4"?"IPv4":s==="IPv6"?"IPv6":void 0}}};import{createHash as MM}from"node:crypto";import{basename as rre}from"node:path";function P(e){return String(e??"").replace(/[&<>"']/g,t=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[t])}var PM="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}}",sre=`default-src 'none'; style-src 'sha256-${MM("sha256").update(PM).digest("base64")}'; form-action 'self'`;function Ze(e,t){return`<a href="${P(e)}">${P(t)}</a>`}function Ma(e,t,n){return t.length?`<div class="table-scroll" role="region" aria-label="${P(n)}" tabindex="0"><table><caption>${P(n)}</caption><thead><tr>${e.map(r=>`<th scope="col">${P(r)}</th>`).join("")}</tr></thead><tbody>${t.map(r=>`<tr>${r.map(s=>`<td>${s}</td>`).join("")}</tr>`).join("")}</tbody></table></div>`:"<p>No matching records.</p>"}function Ae(e){return`<time datetime="${P(e)}" title="${P(e)}">${P(ke(e))}</time>`}function ft(e,t,n=200){return e.header("Cache-Control","no-store"),e.header("X-Content-Type-Options","nosniff"),e.html(t,n)}function qe(e,t,n,r={},s=[],o=!1){let i=n.replace(/\/$/,""),a=o&&i!=="",c=sre+`; base-uri '${a?"self":"none"}'`+(s.length?`; script-src ${s.map(u=>`'sha256-${MM("sha256").update(u).digest("base64")}'`).join(" ")}; connect-src 'self'`:""),l=Object.entries(r).map(([u,f])=>` ${u}="${P(f)}"`).join(""),d=[[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">
2415
2415
  <meta name="viewport" content="width=device-width, initial-scale=1"><meta http-equiv="Content-Security-Policy" content="${P(c)}"><title>${P(e)} \u2014 lmauto</title>
2416
2416
  ${a?`<base href="${P(i)}/" />`:""}
2417
- <style>${PM}</style></head><body><a href="#main">Skip to content</a><header><p>Local operations / lmauto</p><nav aria-label="Main">${d.map(([u,f])=>Ze(u,f)).join(" | ")}</nav></header><main${l} id="main"><h1>${P(e)}</h1>${t}</main><footer><p>Times are relative to this page load. Refresh for current data.</p></footer></body></html>`}function co(e){let t=new Map;for(let n of e)if(K(n))try{t.set(re(n),n.name)}catch{}return t}function UM(e,t,n){function r(o,i=!0){if(o===null)return"\u2014";let a=hi(o);if(!a)return P(o);let{teamfilePath:c,alias:l}=a,d=`${rre(c)}:${l}`,u=t.get(c);if(i&&u)return`<a href="${P(`${n}/sessions/${encodeURIComponent(u)}/${encodeURIComponent(l)}`)}" title="${P(o)}">${P(d)}</a>`;let f=i?`${o} \u2014 Not in the current local team registry -- no session page available`:o;return`<span title="${P(f)}">${P(d)}</span>`}function s(o,i,a){return`<section><h2>${o}</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 ${o.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 &lt;teamfile&gt;.lmctl:&lt;role&gt;: 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>"+s("Running",["Target","From","Started","Running for"],e.running.map(o=>[r(o.target),r(o.from_identity,!1),P(o.started_human),P(o.running_for_human)]))+s("Dead",["Target","From","Started","Stale for"],e.dead.map(o=>[r(o.target),r(o.from_identity,!1),P(o.started_human),P(o.stale_for_human)]))+s("Idle",["Target","From","Status","Ended","Idle for","Ran for"],e.idle.map(o=>[r(o.target),r(o.from_identity,!1),P(o.status),P(ke(o.ended_at)),P(ve(o.idle_ms)),P(o.ran_human)]))}var ip="localweb_session",are=8*1024,cre=1024,lre=30*24*60*60,dre=10,ure=6e4,fre=6e4,mre=1024;function XM(e,t){let n=pre(t.mountPath),r=`${n}/login`||"/login",s=`${n}/`||"/",o=n||"/",i=t.allowedOrigins,a=new Map,c=new Map,l=t.remoteKey??vre,d,u=()=>{let f;try{f=t.readAuthority()}catch{f=null}return!f||!f.passcode||!f.generation?(a.clear(),d=void 0,null):(d!==void 0&&f.generation!==d&&a.clear(),d=f.generation,f)};e.use("*",async(f,m)=>{f.header("Cache-Control","no-store");let p=hre(f.req.path,n);if(f.req.method==="GET"&&(p==="/healthz"||p==="/login")||f.req.method==="POST"&&p==="/login"){await m();return}let h=f.req.header("origin");if(h!==void 0&&!i.includes(h))return f.json({error:"origin not allowed"},403);let _=u();if(_===null)return Xl(f,p,r,n,"unavailable");let g=f.req.header("authorization");if(g!==void 0){let y=l(f),E=Date.now();if(WM(c,y,E))return Xl(f,p,r,n,"locked_out");let T=g.startsWith("Bearer ")?g.slice(7):"";if(!HM(T,_.passcode))return BM(c,y,E),Xl(f,p,r,n);GM(c,y),await m();return}let w=qM(f.req.header("cookie"));if(w===null||a.get(w)!==_.generation)return Xl(f,p,r,n,w===null?"missing":"expired");if(yre(f.req.method)&&!jM(f.req.url,f.req.header("host"),h,i))return Xl(f,p,r,n);await m()}),e.get("/healthz",f=>f.json({ok:!0})),e.get("/login",f=>f.html(_re(YM(f,r,n),n))),e.post("/login",async f=>{if(!jM(f.req.url,f.req.header("host"),f.req.header("origin"),i))return Ww(f,r,n);let m=l(f),p=Date.now();if(WM(c,m,p))return gre(f,n);let h=u();if(h===null)return Ww(f,r,n);let _=await Ere(f.req.raw).catch(()=>null);if(_===null||!HM(_,h.passcode))return BM(c,m,p),Ww(f,r,n);GM(c,m),a.size>=cre&&a.delete(a.keys().next().value);let g=ore(32).toString("base64url");return a.set(g,h.generation),f.header("Set-Cookie",wre(g,o,new URL(f.req.url).protocol==="https:")),f.redirect(JM(f,n)??s,303)}),e.post("/logout",f=>{let m=qM(f.req.header("cookie"));return m!==null&&a.delete(m),f.header("Set-Cookie",Tre(o,new URL(f.req.url).protocol==="https:")),f.redirect(r,303)})}function pre(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 hre(e,t){return t&&(e===t||e.startsWith(`${t}/`))?e.slice(t.length)||"/":e}function Xl(e,t,n,r,s="required"){let o=s==="locked_out"?429:401;if(t==="/api"||t.startsWith("/api/"))return e.json({error:s==="locked_out"?"too many failed attempts":"unauthorized"},o);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."}[s],a=e.req.method==="GET"?VM(`${r}${t}${new URL(e.req.url).search}`,r):null,c=a===null?n:`${n}?next=${encodeURIComponent(a)}`,l=s==="locked_out"?`<p>${i}</p>`:`<p>${i}</p><p><a href="${P(c)}">Log in</a></p>`;return e.html(qe("Authentication required",l,r),o)}function _re(e,t){return qe("LocalWeb login",`<form method="post" action="${P(e)}"><label>Passcode<input type="password" name="passcode" autocomplete="current-password" required></label><button type="submit">Log in</button></form>`,t)}function Ww(e,t,n){return e.html(qe("Login failed",`<p>Invalid credentials.</p><a href="${P(YM(e,t,n))}">Try again</a>`,n),401)}function gre(e,t){return e.html(qe("Login failed","<p>Too many failed attempts from this source. Try again shortly.</p>",t),429)}function VM(e,t){if(!e||e.length>4096||!e.startsWith("/")||e.startsWith("//")||/[\\\x00-\x20\x7f]/.test(e))return null;let n="http://localweb.invalid";try{let r=new URL(e,n),s=decodeURIComponent(r.pathname);if(r.origin!==n||s.includes("//")||/[\\\x00-\x1f\x7f]/.test(s))return null;let o=new URL(s,n),i=a=>!t||a===t||a.startsWith(`${t}/`);return o.origin!==n||o.pathname.includes("//")||!i(r.pathname)||!i(o.pathname)?null:`${r.pathname}${r.search}${r.hash}`}catch{return null}}function JM(e,t){let n=new URL(e.req.url).searchParams.getAll("next");return n.length===1?VM(n[0],t):null}function YM(e,t,n){let r=JM(e,n);return r===null?t:`${t}?next=${encodeURIComponent(r)}`}async function Ere(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 n=[],r=0;for(;;){let{done:o,value:i}=await t.read();if(o)break;if(r+=i.byteLength,r>are)throw await t.cancel(),new Error("form too large");n.push(i)}let s=new URLSearchParams(Buffer.concat(n).toString("utf8"));if(s.getAll("passcode").length!==1||[...s.keys()].some(o=>o!=="passcode"))throw new Error("invalid form");return s.get("passcode")??""}function jM(e,t,n,r){if(n===void 0||!r.includes(n))return!1;let s=new URL(e),o=t??s.host;return n===`${s.protocol}//${o}`&&r.includes(`${s.protocol}//${s.host}`)}function yre(e){return e!=="GET"&&e!=="HEAD"&&e!=="OPTIONS"}function qM(e){let t=(e??"").split(";").map(n=>n.trim()).filter(n=>n.startsWith(`${ip}=`)).map(n=>n.slice(ip.length+1));return t.length===1&&/^[A-Za-z0-9_-]{43}$/.test(t[0])?t[0]:null}function wre(e,t,n){return`${ip}=${e}; Path=${t}; HttpOnly; SameSite=Strict; Max-Age=${lre}${n?"; Secure":""}`}function Tre(e,t){return`${ip}=; Path=${e}; HttpOnly; SameSite=Strict; Max-Age=0${t?"; Secure":""}`}function HM(e,t){let n=FM("sha256").update(e,"utf8").digest(),r=FM("sha256").update(t,"utf8").digest();return ire(n,r)}function vre(e){try{return $M(e).remote.address??"unknown"}catch{return"unknown"}}function WM(e,t,n){let r=e.get(t);return r!==void 0&&n<r.lockedUntilMs}function BM(e,t,n){let r=e.get(t);if(r===void 0||n-r.windowStartMs>ure){e.size>=mre&&e.delete(e.keys().next().value),e.set(t,{count:1,windowStartMs:n,lockedUntilMs:0});return}r.count+=1,r.count>=dre&&(r.lockedUntilMs=n+fre)}function GM(e,t){e.delete(t)}import{createHash as Sre}from"node:crypto";var KM=64*1024,bre=new Set(["math"]);function Are(e,t){return Sre("sha256").update(e,"utf8").update("\0","utf8").update(t,"utf8").digest("hex")}function ap(e,t,n){let r=n.to?.trim(),s=n.prompt??"",o=n.dedupeKey?.trim();if(!r)throw new H("INVALID_ARGUMENT","to is required",2);if(!o)throw new H("INVALID_ARGUMENT","dedupeKey is required",2);if(s.trim().length===0)throw new H("INVALID_ARGUMENT","prompt is required",2);if(Buffer.byteLength(s,"utf8")>KM)throw new H("INVALID_ARGUMENT",`prompt exceeds the ${KM}-byte comm-flow cap`,2);if(!bre.has(r))throw new H("INVALID_ARGUMENT",`"${r}" is not a comm-flow-enabled target`,2);let i=t.find(l=>l.name===r);if(i===void 0||!K(i))throw new H("INVALID_ARGUMENT",`"${r}" is not a registered local team`,2);let a=Are(r,s);return e.transaction(()=>{let l=e.prepare("SELECT id, admission_fingerprint FROM queue WHERE dedupe_key = ?").get(o);if(l){if(l.admission_fingerprint===a)return{queueId:l.id,replayed:!0};throw new H("CONFLICT",`dedupeKey "${o}" was already used for a different prompt`,4)}let d=Ne(e,t,r,s,{from:"operator",dedupeKey:o});return e.prepare("UPDATE queue SET admission_fingerprint = ? WHERE id = ?").run(a,d),{queueId:d,replayed:!1}}).immediate()}import{existsSync as Ire,readFileSync as kre}from"node:fs";import{dirname as QM,join as Bw}from"node:path";import{fileURLToPath as ZM}from"node:url";var Rre=Bw(QM(ZM(import.meta.url)),"public"),Nre={"/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"}},xre=Bw(QM(ZM(import.meta.url)),"vendor-webui"),Lre={"/":{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 Cre(e){return e.endsWith("/")?e.slice(0,-1):e}function Ore(e,t){let n=e.replace(/<head[^>]*>/i,r=>`${r}
2417
+ <style>${PM}</style></head><body><a href="#main">Skip to content</a><header><p>Local operations / lmauto</p><nav aria-label="Main">${d.map(([u,f])=>Ze(u,f)).join(" | ")}</nav></header><main${l} id="main"><h1>${P(e)}</h1>${t}</main><footer><p>Times are relative to this page load. Refresh for current data.</p></footer></body></html>`}function co(e){let t=new Map;for(let n of e)if(K(n))try{t.set(re(n),n.name)}catch{}return t}function UM(e,t,n){function r(o,i=!0){if(o===null)return"\u2014";let a=hi(o);if(!a)return P(o);let{teamfilePath:c,alias:l}=a,d=`${rre(c)}:${l}`,u=t.get(c);if(i&&u)return`<a href="${P(`${n}/sessions/${encodeURIComponent(u)}/${encodeURIComponent(l)}`)}" title="${P(o)}">${P(d)}</a>`;let f=i?`${o} \u2014 Not in the current local team registry -- no session page available`:o;return`<span title="${P(f)}">${P(d)}</span>`}function s(o,i,a){return`<section><h2>${o}</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 ${o.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 &lt;teamfile&gt;.lmctl:&lt;role&gt;: 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>"+s("Running",["Target","From","Started","Running for"],e.running.map(o=>[r(o.target),r(o.from_identity,!1),P(o.started_human),P(o.running_for_human)]))+s("Dead",["Target","From","Started","Age"],e.dead.map(o=>[r(o.target),r(o.from_identity,!1),P(o.started_human),P(o.age_human)]))+s("Idle",["Target","From","Status","Ended","Idle for","Ran for"],e.idle.map(o=>[r(o.target),r(o.from_identity,!1),P(o.status),P(ke(o.ended_at)),P(ve(o.idle_ms)),P(o.ran_human)]))}var ip="localweb_session",are=8*1024,cre=1024,lre=30*24*60*60,dre=10,ure=6e4,fre=6e4,mre=1024;function XM(e,t){let n=pre(t.mountPath),r=`${n}/login`||"/login",s=`${n}/`||"/",o=n||"/",i=t.allowedOrigins,a=new Map,c=new Map,l=t.remoteKey??vre,d,u=()=>{let f;try{f=t.readAuthority()}catch{f=null}return!f||!f.passcode||!f.generation?(a.clear(),d=void 0,null):(d!==void 0&&f.generation!==d&&a.clear(),d=f.generation,f)};e.use("*",async(f,m)=>{f.header("Cache-Control","no-store");let p=hre(f.req.path,n);if(f.req.method==="GET"&&(p==="/healthz"||p==="/login")||f.req.method==="POST"&&p==="/login"){await m();return}let h=f.req.header("origin");if(h!==void 0&&!i.includes(h))return f.json({error:"origin not allowed"},403);let _=u();if(_===null)return Xl(f,p,r,n,"unavailable");let g=f.req.header("authorization");if(g!==void 0){let y=l(f),E=Date.now();if(WM(c,y,E))return Xl(f,p,r,n,"locked_out");let T=g.startsWith("Bearer ")?g.slice(7):"";if(!HM(T,_.passcode))return BM(c,y,E),Xl(f,p,r,n);GM(c,y),await m();return}let w=qM(f.req.header("cookie"));if(w===null||a.get(w)!==_.generation)return Xl(f,p,r,n,w===null?"missing":"expired");if(yre(f.req.method)&&!jM(f.req.url,f.req.header("host"),h,i))return Xl(f,p,r,n);await m()}),e.get("/healthz",f=>f.json({ok:!0})),e.get("/login",f=>f.html(_re(YM(f,r,n),n))),e.post("/login",async f=>{if(!jM(f.req.url,f.req.header("host"),f.req.header("origin"),i))return Ww(f,r,n);let m=l(f),p=Date.now();if(WM(c,m,p))return gre(f,n);let h=u();if(h===null)return Ww(f,r,n);let _=await Ere(f.req.raw).catch(()=>null);if(_===null||!HM(_,h.passcode))return BM(c,m,p),Ww(f,r,n);GM(c,m),a.size>=cre&&a.delete(a.keys().next().value);let g=ore(32).toString("base64url");return a.set(g,h.generation),f.header("Set-Cookie",wre(g,o,new URL(f.req.url).protocol==="https:")),f.redirect(JM(f,n)??s,303)}),e.post("/logout",f=>{let m=qM(f.req.header("cookie"));return m!==null&&a.delete(m),f.header("Set-Cookie",Tre(o,new URL(f.req.url).protocol==="https:")),f.redirect(r,303)})}function pre(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 hre(e,t){return t&&(e===t||e.startsWith(`${t}/`))?e.slice(t.length)||"/":e}function Xl(e,t,n,r,s="required"){let o=s==="locked_out"?429:401;if(t==="/api"||t.startsWith("/api/"))return e.json({error:s==="locked_out"?"too many failed attempts":"unauthorized"},o);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."}[s],a=e.req.method==="GET"?VM(`${r}${t}${new URL(e.req.url).search}`,r):null,c=a===null?n:`${n}?next=${encodeURIComponent(a)}`,l=s==="locked_out"?`<p>${i}</p>`:`<p>${i}</p><p><a href="${P(c)}">Log in</a></p>`;return e.html(qe("Authentication required",l,r),o)}function _re(e,t){return qe("LocalWeb login",`<form method="post" action="${P(e)}"><label>Passcode<input type="password" name="passcode" autocomplete="current-password" required></label><button type="submit">Log in</button></form>`,t)}function Ww(e,t,n){return e.html(qe("Login failed",`<p>Invalid credentials.</p><a href="${P(YM(e,t,n))}">Try again</a>`,n),401)}function gre(e,t){return e.html(qe("Login failed","<p>Too many failed attempts from this source. Try again shortly.</p>",t),429)}function VM(e,t){if(!e||e.length>4096||!e.startsWith("/")||e.startsWith("//")||/[\\\x00-\x20\x7f]/.test(e))return null;let n="http://localweb.invalid";try{let r=new URL(e,n),s=decodeURIComponent(r.pathname);if(r.origin!==n||s.includes("//")||/[\\\x00-\x1f\x7f]/.test(s))return null;let o=new URL(s,n),i=a=>!t||a===t||a.startsWith(`${t}/`);return o.origin!==n||o.pathname.includes("//")||!i(r.pathname)||!i(o.pathname)?null:`${r.pathname}${r.search}${r.hash}`}catch{return null}}function JM(e,t){let n=new URL(e.req.url).searchParams.getAll("next");return n.length===1?VM(n[0],t):null}function YM(e,t,n){let r=JM(e,n);return r===null?t:`${t}?next=${encodeURIComponent(r)}`}async function Ere(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 n=[],r=0;for(;;){let{done:o,value:i}=await t.read();if(o)break;if(r+=i.byteLength,r>are)throw await t.cancel(),new Error("form too large");n.push(i)}let s=new URLSearchParams(Buffer.concat(n).toString("utf8"));if(s.getAll("passcode").length!==1||[...s.keys()].some(o=>o!=="passcode"))throw new Error("invalid form");return s.get("passcode")??""}function jM(e,t,n,r){if(n===void 0||!r.includes(n))return!1;let s=new URL(e),o=t??s.host;return n===`${s.protocol}//${o}`&&r.includes(`${s.protocol}//${s.host}`)}function yre(e){return e!=="GET"&&e!=="HEAD"&&e!=="OPTIONS"}function qM(e){let t=(e??"").split(";").map(n=>n.trim()).filter(n=>n.startsWith(`${ip}=`)).map(n=>n.slice(ip.length+1));return t.length===1&&/^[A-Za-z0-9_-]{43}$/.test(t[0])?t[0]:null}function wre(e,t,n){return`${ip}=${e}; Path=${t}; HttpOnly; SameSite=Strict; Max-Age=${lre}${n?"; Secure":""}`}function Tre(e,t){return`${ip}=; Path=${e}; HttpOnly; SameSite=Strict; Max-Age=0${t?"; Secure":""}`}function HM(e,t){let n=FM("sha256").update(e,"utf8").digest(),r=FM("sha256").update(t,"utf8").digest();return ire(n,r)}function vre(e){try{return $M(e).remote.address??"unknown"}catch{return"unknown"}}function WM(e,t,n){let r=e.get(t);return r!==void 0&&n<r.lockedUntilMs}function BM(e,t,n){let r=e.get(t);if(r===void 0||n-r.windowStartMs>ure){e.size>=mre&&e.delete(e.keys().next().value),e.set(t,{count:1,windowStartMs:n,lockedUntilMs:0});return}r.count+=1,r.count>=dre&&(r.lockedUntilMs=n+fre)}function GM(e,t){e.delete(t)}import{createHash as Sre}from"node:crypto";var KM=64*1024,bre=new Set(["math"]);function Are(e,t){return Sre("sha256").update(e,"utf8").update("\0","utf8").update(t,"utf8").digest("hex")}function ap(e,t,n){let r=n.to?.trim(),s=n.prompt??"",o=n.dedupeKey?.trim();if(!r)throw new H("INVALID_ARGUMENT","to is required",2);if(!o)throw new H("INVALID_ARGUMENT","dedupeKey is required",2);if(s.trim().length===0)throw new H("INVALID_ARGUMENT","prompt is required",2);if(Buffer.byteLength(s,"utf8")>KM)throw new H("INVALID_ARGUMENT",`prompt exceeds the ${KM}-byte comm-flow cap`,2);if(!bre.has(r))throw new H("INVALID_ARGUMENT",`"${r}" is not a comm-flow-enabled target`,2);let i=t.find(l=>l.name===r);if(i===void 0||!K(i))throw new H("INVALID_ARGUMENT",`"${r}" is not a registered local team`,2);let a=Are(r,s);return e.transaction(()=>{let l=e.prepare("SELECT id, admission_fingerprint FROM queue WHERE dedupe_key = ?").get(o);if(l){if(l.admission_fingerprint===a)return{queueId:l.id,replayed:!0};throw new H("CONFLICT",`dedupeKey "${o}" was already used for a different prompt`,4)}let d=Ne(e,t,r,s,{from:"operator",dedupeKey:o});return e.prepare("UPDATE queue SET admission_fingerprint = ? WHERE id = ?").run(a,d),{queueId:d,replayed:!1}}).immediate()}import{existsSync as Ire,readFileSync as kre}from"node:fs";import{dirname as QM,join as Bw}from"node:path";import{fileURLToPath as ZM}from"node:url";var Rre=Bw(QM(ZM(import.meta.url)),"public"),Nre={"/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"}},xre=Bw(QM(ZM(import.meta.url)),"vendor-webui"),Lre={"/":{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 Cre(e){return e.endsWith("/")?e.slice(0,-1):e}function Ore(e,t){let n=e.replace(/<head[^>]*>/i,r=>`${r}
2418
2418
  <base href="${t}" />`);if(n===e)throw new Error("injectBaseHref: no <head> tag found in index.html -- cannot inject <base href>");return n}function zM(e,t,n,r){for(let s of Object.keys(n))e.get(s,o=>{let i=n[s];if(!i)return o.notFound();let a=Bw(t,i.file);if(!Ire(a))return o.notFound();let c=kre(a);return r!==void 0&&i.contentType.startsWith("text/html")&&(c=Ore(c.toString("utf8"),r)),o.body(c,200,{"content-type":i.contentType})})}function eP(e,t={}){let n=Cre(t.mountPath??""),r=t.webDistDir??xre;zM(e,r,Lre,n!==""?`${n}/`:void 0),zM(e,Rre,Nre,`${n}/legacy/`)}import{createHash as Vw,createHmac as Fre,randomBytes as Gw,timingSafeEqual as jre}from"node:crypto";import{basename as qre}from"node:path";import{existsSync as Dre}from"node:fs";import{homedir as $re}from"node:os";import{join as Mre}from"node:path";function Pre(e){return e||(process.env.LMTEAM_DB_PATH?process.env.LMTEAM_DB_PATH:Mre($re(),".lmteam","lmteam.db"))}function cp(e){let t=Pre(e);if(!Dre(t))throw new Error(`lmteam database not found at ${t} -- set LMTEAM_DB_PATH or check the path`);return new tn(t,{readonly:!0,fileMustExist:!0})}function tP(e,t={}){let n=t.status??"stands",r=t.affects?e.prepare(`SELECT d.* FROM decisions d JOIN decision_affects a ON a.decision_id = d.id
2419
2419
  WHERE a.target = ? AND d.status = ? ORDER BY d.decided_at DESC`).all(t.affects,n):e.prepare("SELECT * FROM decisions WHERE status = ? ORDER BY decided_at DESC").all(n),s=e.prepare("SELECT target FROM decision_affects WHERE decision_id = ? ORDER BY target");return r.map(o=>({...o,affects:s.all(o.id).map(i=>i.target)}))}function nP(e){return e.prepare("SELECT * FROM asks WHERE status = 'open' ORDER BY raised_at ASC").all()}function rP(e,t){return e.prepare("SELECT * FROM asks WHERE id = ?").get(t)??null}function sP(e){return e.prepare("SELECT * FROM blocked WHERE status = 'open' ORDER BY raised_at ASC").all()}function Ure(){let e=!1,t=0,n=new Set,r=U=>!e&&!document.hidden&&U===t,s=U=>document.getElementById(U),o=(U,B)=>{let W=s(U);W&&(W.textContent=B)},i=(U,B="")=>{let W=document.createElement(U);return W.textContent=B,W},a=U=>U!==null&&typeof U=="object"&&!Array.isArray(U),c=U=>Number.isSafeInteger(U)&&Number(U)>0,l=U=>typeof U=="string"&&Number.isFinite(Date.parse(U)),d=U=>U===null||l(U);async function u(U,B,W,se){n.add(W);let z,ue,J=new Promise((X,Q)=>{z=()=>{ue?.cancel().catch(()=>{}),Q(new Error("Request cancelled or timed out"))},W.signal.addEventListener("abort",z,{once:!0})}),V=setTimeout(()=>W.abort(),15e3),j=async()=>{W.signal.throwIfAborted();let X=await fetch(U,{method:se===void 0?"GET":"POST",signal:W.signal,credentials:"same-origin",cache:"no-store",redirect:"error",headers:{Accept:B==="json"?"application/json":"text/html",...se===void 0?{}:{"Content-Type":"application/x-www-form-urlencoded"}},...se===void 0?{}:{body:se}});if(W.signal.throwIfAborted(),X.status!==200||X.redirected||!X.headers.get("content-type")?.includes(B==="json"?"application/json":"text/html")){let Ee;if(B==="html"&&!X.redirected&&X.headers.get("content-type")?.includes("text/html")){let Ue=await X.text().catch(()=>""),te=/<h1>[^<]*<\/h1>\s*<p>([^<]*)<\/p>/.exec(Ue);te&&te[1]&&(Ee=te[1].replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#39;/g,"'"))}else X.body?.cancel().catch(()=>{});let He=new Error(Ee??"Unexpected server response");throw He.status=X.status,He}let Q=X.body?.getReader();if(ue=Q,!Q)throw new Error("Missing response body");let ee=new TextDecoder,ce=0,le="";try{for(;;){let Ee=await Q.read();if(W.signal.throwIfAborted(),Ee.done)break;if(ce+=Ee.value.byteLength,ce>(B==="json"?262144:2e6))throw new Error("Response exceeds safety limit");le+=ee.decode(Ee.value,{stream:!0})}return le+ee.decode()}catch(Ee){throw Q.cancel().catch(()=>{}),Ee}};try{return await Promise.race([j(),J])}finally{clearTimeout(V),W.signal.removeEventListener("abort",z),n.delete(W)}}function f(U,B){if(!a(U)||U.id!==B||!l(U.createdAt)||!d(U.pulledAt)||!d(U.answeredAt))throw new Error("Invalid queue state");let W=U.lifecycle,se=U.lifecycleBasis,z=U.answer;if(!(W==="queued"?se==="dispatched":W==="processing"?se==="confirmed"||se==="dispatched":W==="finished"&&["answer","merged","informational"].includes(String(se))))throw new Error("Invalid lifecycle evidence");if(se==="answer"){if(!a(z)||!c(z.id)||z.prompt_queue_id!==B||typeof z.answer_text!="string"||!l(z.answered_at)||z.answered_at!==U.answeredAt||!l(z.created_at)||typeof z.truncated!="boolean")throw new Error("Invalid correlated answer");let J=new TextEncoder().encode(z.answer_text).length;if(!Number.isSafeInteger(z.byteLength)||z.byteLength!==J||J>65536||!Number.isSafeInteger(z.totalBytes)||Number(z.totalBytes)<J||(z.truncated?Number(z.totalBytes)<=J:z.totalBytes!==J))throw new Error("Invalid response coverage")}else if(z!==null||U.answeredAt!==null)throw new Error("Unexpected answer");if(W==="queued"&&U.pulledAt!==null)throw new Error("Unexpected handling time");return U}let m=s("comm-state"),p=Number(m?.dataset.queueId),h=m?.dataset.mount??"",_,g=null,w=0,y=m?.dataset.lifecycle==="finished";function E(){if(clearTimeout(_),!(!m||!c(p)||e||document.hidden||y||g)){if(w>=60){o("comm-poll-notice","Automatic checks paused after 60 reads. Use Refresh state to check again.");return}_=setTimeout(()=>void T(),Math.min(1e3*1.5**w,1e4))}}async function T(){if(!m||g||e||document.hidden||y||w>=60)return;let U=new AbortController,B=t;g=U,w++;try{let W=await u(`${h}/api/queue/${p}/state`,"json",U);if(!r(B))return;let se=f(JSON.parse(W),p),z=se.lifecycleBasis,ue=se.answer,J=se.lifecycle==="queued"?"Queued":se.lifecycle==="processing"?"Processing":z==="merged"?"Combined":z==="informational"?"Informational":"Replied",V=se.lifecycle==="queued"?"Queued \u2014 waiting for handling":se.lifecycle==="processing"?z==="confirmed"?"Processing \u2014 picked up by inbox":"Processing \u2014 delivery attempted; read not confirmed":z==="merged"?"Finished \u2014 combined with another prompt":z==="informational"?"Finished \u2014 informational, no answer expected":"Finished \u2014 answer recorded",j=z==="merged"?"No separate answer: prompt combined into another prompt.":"No answer expected: this was an informational send.",X=m.dataset.sender??"sender not recorded",Q=m.dataset.recipient??"inbox not recorded",ee=ue?`Answer recorded in the ${Q} inbox for prompt #${p} from ${X}.`:se.lifecycle==="finished"?j:`No answer recorded for prompt #${p} from ${X} to ${Q}.`,ce=i("span",J);ce.className=`status-chip status-${se.lifecycle==="finished"?ue?"replied":"muted":se.lifecycle}`,ce.title=V,m.replaceChildren(ce,i("span",` \xB7 ${V}`)),m.dataset.lifecycle=se.lifecycle,m.dataset.lifecycleBasis=z,o("comm-receipt-summary",ue?"An answer is recorded below.":se.lifecycle==="finished"?j:"No answer recorded yet."),o("comm-response-status",ee),o("comm-response-none",!ue&&se.lifecycle!=="finished"?"No correlated answer recorded yet. Refresh to check again.":""),o("comm-response-meta",ue?`Recorded ${ue.answered_at} \xB7 answer #${ue.id} to prompt #${ue.prompt_queue_id}`:""),o("comm-response",ue?.answer_text??"");let le=s("comm-response");le&&(le.hidden=!ue),o("comm-response-truncation",ue?ue.truncated?`Truncated: ${ue.byteLength} of ${ue.totalBytes} bytes. No continuation endpoint is available.`:`${ue.byteLength} bytes returned.`:""),o("comm-reply-time",ue?.answered_at??"not recorded"),o("comm-handling-observation",`Latest handling evidence: ${se.pulledAt??"not recorded"}${se.pulledAt?z==="confirmed"?" (picked up)":z==="dispatched"?" (delivery attempted)":" (transport or pickup time)":""}`),o("comm-poll-notice",`State checked ${new Date().toISOString()}.`),y=se.lifecycle==="finished"}catch(W){r(B)&&o("comm-poll-notice",`State unavailable; displayed records may be stale. ${W instanceof Error?W.message:String(W)}. Use Refresh state.`)}finally{g===U&&(g=null),E()}}let b=s("comm-composer-container"),A=s("comm-draft-form"),I=null,R=!1,L=!1,N=!1,k=null,D=null,O=U=>Array.from(U.querySelectorAll("input, textarea")),v=(U,B)=>{let W=O(U).filter(se=>se.name===B);if(W.length!==1)throw new Error("Invalid review fields");return W[0]};function S(U,B){let W=O(U).map(se=>({input:se,value:se.value}));k=U,D=U.querySelector('button[type="submit"]'),U.addEventListener("submit",se=>{if(L||e||document.hidden){se.preventDefault();return}for(let z of W)z.input.value=z.value;L=!0,N=!0,B&&(B.disabled=!0),D&&(D.disabled=!0),o("comm-send-status","Submitting through the browser. If the outcome is uncertain, return here and retry this same confirmation.")})}let x=s("comm-confirm-form");if(x&&S(x,s("comm-edit-button")),A?.addEventListener("submit",U=>{N&&U.preventDefault()}),b&&A&&s("compose")){let U=Array.from(b.childNodes),B=A.querySelector('textarea[name="prompt"]'),W=A.querySelector('button[type="submit"]');A.addEventListener("submit",async se=>{if(!B||(se.preventDefault(),I||N||e||document.hidden))return;let z=B.value.replace(/\r\n?/g,`
2420
2420
  `);if(!z.trim()||new TextEncoder().encode(z.replace(/\n/g,`\r
@@ -21,14 +21,14 @@
21
21
  <div data-local-account-whoami-host><p class="muted" role="status">Loading identity\u2026</p></div>
22
22
  <div data-local-account-mail-host><p class="muted" role="status">Loading mail status\u2026</p></div>
23
23
  </section>
24
- `;let a=t.querySelector("[data-local-account-whoami-host]"),s=t.querySelector("[data-local-account-mail-host]");return(async()=>{let i=await e.transport.read({kind:"whoami"},r.signal);if(!(r.signal.aborted||!a)){if(i.status==="error"){a.innerHTML=N(i.error.message);return}i.status!=="pending"&&(a.innerHTML=F(i.data,i.ranCommand,i.ranAt))}})(),(async()=>{let i=await e.transport.read({kind:"mail-status"},r.signal);if(!(r.signal.aborted||!s)){if(i.status==="error"){s.innerHTML=W(i.error.message);return}i.status!=="pending"&&(s.innerHTML=O(i.data,i.ranCommand,i.ranAt))}})(),()=>{r.abort()}}},E=U;function x(t){return t.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function P(t,e){if(t&&typeof t=="object"&&"error"in t){let r=t.error;if(r&&typeof r=="object"){let a=r;if(typeof a.code=="string"&&typeof a.message=="string")return{code:a.code,message:a.message}}if(typeof r=="string")return{code:"http_error",message:r}}return{code:"http_error",message:`HTTP ${e}`}}function Q(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.name=="string"&&(e.channel==="local"||e.channel==="lmmail")}function B(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.id=="number"&&typeof e.from_id=="string"&&typeof e.to_id=="string"&&typeof e.status=="string"}function G(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.id=="number"&&typeof e.ts=="string"&&typeof e.team=="string"}function J(t){return!t||typeof t!="object"?!1:typeof t.team=="string"}function K(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.id=="number"&&typeof e.path=="string"}function V(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.provider=="string"&&typeof e.sessionId=="string"&&Array.isArray(e.messages)}function z(t){if(!t||typeof t!="object")return!1;let e=t;return Array.isArray(e.running)&&Array.isArray(e.dead)&&Array.isArray(e.idle)}function X(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.userId=="string"&&typeof e.label=="string"}function Y(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.counts=="object"&&e.counts!==null}function Z(t){return!t||typeof t!="object"?!1:typeof t.team=="string"}function tt(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.live=="boolean"&&Array.isArray(e.teams)&&e.teams.every(Z)}var L=class{apiBase;constructor(e=""){this.apiBase=e}url(e){return`${this.apiBase}${e}`}async read(e,r){let a=()=>new Date().toISOString();if(e.kind==="teams")return this.get(this.url("api/teams"),"lmauto teams --json",n=>{let o=n;return Array.isArray(o.teams)?{teams:o.teams.filter(Q)}:null},a,r);if(e.kind==="queue-list"){let l=e.team?`?to=${encodeURIComponent(e.team)}`:"",n=e.team?`lmauto queue list ${e.team} --json`:"lmauto queue list --json";return this.get(this.url(`api/queue${l}`),n,o=>{let d=o;return Array.isArray(d.queue)?{queue:d.queue.filter(B)}:null},a,r)}if(e.kind==="history"){let l=new URLSearchParams;e.team&&l.set("team",e.team),e.limit!==void 0&&l.set("limit",String(e.limit));let n=l.toString(),o=`lmauto history${e.team?` ${e.team}`:""}${e.limit!==void 0?` ${e.limit}`:""} --json`;return this.get(this.url(`api/history${n?`?${n}`:""}`),o,d=>{let u=d;return Array.isArray(u.events)?{events:u.events.filter(G)}:null},a,r)}if(e.kind==="state-list")return this.get(this.url("api/state"),"lmauto state list --json",n=>{let o=n;return!Array.isArray(o.teams)||!Array.isArray(o.active)?null:{teams:o.teams.filter(J),active:o.active.filter(d=>typeof d=="string")}},a,r);if(e.kind==="sources")return this.get(this.url("api/sources"),"lmauto source list --json",n=>{let o=n;return typeof o.defaultTeamsConfPath!="string"||!Array.isArray(o.sources)?null:{defaultTeamsConfPath:o.defaultTeamsConfPath,sources:o.sources.filter(K)}},a,r);if(e.kind==="session"){let l=`lmctl session ${e.team} ${e.alias}`;return this.get(this.url(`api/session/${encodeURIComponent(e.team)}/${encodeURIComponent(e.alias)}`),l,n=>V(n)?n:null,a,r)}if(e.kind==="running")return this.get(this.url("api/running"),"lmctl running --json",n=>z(n)?n:null,a,r);if(e.kind==="whoami")return this.get(this.url("api/whoami"),"lmauto whoami --json",n=>X(n)?n:null,a,r);if(e.kind==="mail-status")return this.get(this.url("api/mail/status"),"lmauto mail status --json",n=>Y(n)?n:null,a,r);let s=e.live?"?live=1":"",i=e.live?"lmauto status --live --json":"lmauto status --json";return this.get(this.url(`api/status${s}`),i,l=>tt(l)?l:null,a,r)}async get(e,r,a,s,i){try{let l=await fetch(e,{method:"GET",signal:i}),n=null;try{n=await l.json()}catch{n=null}if(!l.ok)return{status:"error",data:null,ranCommand:r,ranAt:null,error:P(n,l.status)};let o=a(n);return o===null?{status:"error",data:null,ranCommand:r,ranAt:null,error:{code:"invalid_response",message:"Unexpected response shape."}}:{status:"ready",data:o,ranCommand:r,ranAt:s()}}catch(l){if(i.aborted)throw l;return{status:"error",data:null,ranCommand:r,ranAt:null,error:{code:"network_error",message:l instanceof Error?l.message:"Network error."}}}}async write(e,r){if(e.kind==="enqueue"){let s=`lmauto enqueue ${e.team} "${x(e.message)}" --from ${e.from}`;return this.post(this.url("api/enqueue"),{to:e.team,from:e.from,prompt:e.message},s,i=>{let l=i;return typeof l.id!="number"?null:`queued #${l.id} -> ${e.team}`},r)}if(e.kind==="send"){let s=`lmauto send ${e.team} "${x(e.message)}"`;return this.post(this.url("api/send"),{team:e.team,prompt:e.message},s,i=>{let l=i;return typeof l.status!="string"?null:`${e.team}: ${l.status}`},r)}if(e.kind==="source-add"){let s=e.label?`lmauto source add ${e.path} "${x(e.label)}"`:`lmauto source add ${e.path}`,i=e.label?{path:e.path,label:e.label}:{path:e.path};return this.post(this.url("api/sources"),i,s,l=>l.ok!==!0?null:`added ${e.path}`,r)}let a=`lmauto source remove ${e.path}`;return this.del(this.url(`api/sources?path=${encodeURIComponent(e.path)}`),a,s=>s.ok!==!0?null:`removed ${e.path}`,r)}async del(e,r,a,s){let i=new Date().toISOString();try{let l=await fetch(e,{method:"DELETE",signal:s}),n=null;try{n=await l.json()}catch{n=null}if(!l.ok){let d=P(n,l.status);return{ok:!1,ranCommand:r,ranAt:i,summary:d.message,raw:n,error:d}}let o=a(n);if(o===null){let d={code:"invalid_response",message:"Unexpected response shape."};return{ok:!1,ranCommand:r,ranAt:i,summary:d.message,raw:n,error:d}}return{ok:!0,ranCommand:r,ranAt:i,summary:o,raw:n}}catch(l){if(s.aborted)throw l;let n={code:"network_error",message:l instanceof Error?l.message:"Network error."};return{ok:!1,ranCommand:r,ranAt:i,summary:n.message,raw:null,error:n}}}async post(e,r,a,s,i){let l=new Date().toISOString();try{let n=await fetch(e,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(r),signal:i}),o=null;try{o=await n.json()}catch{o=null}if(!n.ok){let u=P(o,n.status);return{ok:!1,ranCommand:a,ranAt:l,summary:u.message,raw:o,error:u}}let d=s(o);if(d===null){let u={code:"invalid_response",message:"Unexpected response shape."};return{ok:!1,ranCommand:a,ranAt:l,summary:u.message,raw:o,error:u}}return{ok:!0,ranCommand:a,ranAt:l,summary:d,raw:o}}catch(n){if(i.aborted)throw n;let o={code:"network_error",message:n instanceof Error?n.message:"Network error."};return{ok:!1,ranCommand:a,ranAt:l,summary:o.message,raw:null,error:o}}}};function p(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function et(t,e){if(!e)return`<p class="muted" data-local-ran>ran: <code>${p(t)}</code></p>`;let r=Math.max(0,Math.round((Date.now()-Date.parse(e))/1e3));return`<p class="muted" data-local-ran>ran: <code>${p(t)}</code>, ${r}s ago</p>`}function I(t){return t===null?"":p(t)}function rt(t){return`<tr data-local-running-row="${t.id}"><td>${p(t.kind)}</td><td>${I(t.target)}</td><td>${p(t.started_at)}</td><td>${t.running_for_ms}</td><td>${p(t.holder_liveness)}</td></tr>`}function nt(t){return`<tr data-local-dead-row="${t.id}"><td>${p(t.kind)}</td><td>${I(t.target)}</td><td>${p(t.started_at)}</td><td>${t.stale_for_ms}</td></tr>`}function at(t){return`<tr data-local-idle-row="${t.id}"><td>${p(t.kind)}</td><td>${I(t.target)}</td><td>${p(t.status)}</td><td>${t.idle_ms}</td><td>${t.error?p(t.error):""}</td></tr>`}function ot(t,e,r,a,s,i){t.innerHTML=`
24
+ `;let a=t.querySelector("[data-local-account-whoami-host]"),s=t.querySelector("[data-local-account-mail-host]");return(async()=>{let i=await e.transport.read({kind:"whoami"},r.signal);if(!(r.signal.aborted||!a)){if(i.status==="error"){a.innerHTML=N(i.error.message);return}i.status!=="pending"&&(a.innerHTML=F(i.data,i.ranCommand,i.ranAt))}})(),(async()=>{let i=await e.transport.read({kind:"mail-status"},r.signal);if(!(r.signal.aborted||!s)){if(i.status==="error"){s.innerHTML=W(i.error.message);return}i.status!=="pending"&&(s.innerHTML=O(i.data,i.ranCommand,i.ranAt))}})(),()=>{r.abort()}}},E=U;function x(t){return t.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function P(t,e){if(t&&typeof t=="object"&&"error"in t){let r=t.error;if(r&&typeof r=="object"){let a=r;if(typeof a.code=="string"&&typeof a.message=="string")return{code:a.code,message:a.message}}if(typeof r=="string")return{code:"http_error",message:r}}return{code:"http_error",message:`HTTP ${e}`}}function Q(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.name=="string"&&(e.channel==="local"||e.channel==="lmmail")}function B(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.id=="number"&&typeof e.from_id=="string"&&typeof e.to_id=="string"&&typeof e.status=="string"}function G(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.id=="number"&&typeof e.ts=="string"&&typeof e.team=="string"}function J(t){return!t||typeof t!="object"?!1:typeof t.team=="string"}function K(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.id=="number"&&typeof e.path=="string"}function V(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.provider=="string"&&typeof e.sessionId=="string"&&Array.isArray(e.messages)}function z(t){if(!t||typeof t!="object")return!1;let e=t;return Array.isArray(e.running)&&Array.isArray(e.dead)&&Array.isArray(e.idle)}function X(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.userId=="string"&&typeof e.label=="string"}function Y(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.counts=="object"&&e.counts!==null}function Z(t){return!t||typeof t!="object"?!1:typeof t.team=="string"}function tt(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.live=="boolean"&&Array.isArray(e.teams)&&e.teams.every(Z)}var L=class{apiBase;constructor(e=""){this.apiBase=e}url(e){return`${this.apiBase}${e}`}async read(e,r){let a=()=>new Date().toISOString();if(e.kind==="teams")return this.get(this.url("api/teams"),"lmauto teams --json",n=>{let o=n;return Array.isArray(o.teams)?{teams:o.teams.filter(Q)}:null},a,r);if(e.kind==="queue-list"){let l=e.team?`?to=${encodeURIComponent(e.team)}`:"",n=e.team?`lmauto queue list ${e.team} --json`:"lmauto queue list --json";return this.get(this.url(`api/queue${l}`),n,o=>{let d=o;return Array.isArray(d.queue)?{queue:d.queue.filter(B)}:null},a,r)}if(e.kind==="history"){let l=new URLSearchParams;e.team&&l.set("team",e.team),e.limit!==void 0&&l.set("limit",String(e.limit));let n=l.toString(),o=`lmauto history${e.team?` ${e.team}`:""}${e.limit!==void 0?` ${e.limit}`:""} --json`;return this.get(this.url(`api/history${n?`?${n}`:""}`),o,d=>{let u=d;return Array.isArray(u.events)?{events:u.events.filter(G)}:null},a,r)}if(e.kind==="state-list")return this.get(this.url("api/state"),"lmauto state list --json",n=>{let o=n;return!Array.isArray(o.teams)||!Array.isArray(o.active)?null:{teams:o.teams.filter(J),active:o.active.filter(d=>typeof d=="string")}},a,r);if(e.kind==="sources")return this.get(this.url("api/sources"),"lmauto source list --json",n=>{let o=n;return typeof o.defaultTeamsConfPath!="string"||!Array.isArray(o.sources)?null:{defaultTeamsConfPath:o.defaultTeamsConfPath,sources:o.sources.filter(K)}},a,r);if(e.kind==="session"){let l=`lmctl session ${e.team} ${e.alias}`;return this.get(this.url(`api/session/${encodeURIComponent(e.team)}/${encodeURIComponent(e.alias)}`),l,n=>V(n)?n:null,a,r)}if(e.kind==="running")return this.get(this.url("api/running"),"lmctl running --json",n=>z(n)?n:null,a,r);if(e.kind==="whoami")return this.get(this.url("api/whoami"),"lmauto whoami --json",n=>X(n)?n:null,a,r);if(e.kind==="mail-status")return this.get(this.url("api/mail/status"),"lmauto mail status --json",n=>Y(n)?n:null,a,r);let s=e.live?"?live=1":"",i=e.live?"lmauto status --live --json":"lmauto status --json";return this.get(this.url(`api/status${s}`),i,l=>tt(l)?l:null,a,r)}async get(e,r,a,s,i){try{let l=await fetch(e,{method:"GET",signal:i}),n=null;try{n=await l.json()}catch{n=null}if(!l.ok)return{status:"error",data:null,ranCommand:r,ranAt:null,error:P(n,l.status)};let o=a(n);return o===null?{status:"error",data:null,ranCommand:r,ranAt:null,error:{code:"invalid_response",message:"Unexpected response shape."}}:{status:"ready",data:o,ranCommand:r,ranAt:s()}}catch(l){if(i.aborted)throw l;return{status:"error",data:null,ranCommand:r,ranAt:null,error:{code:"network_error",message:l instanceof Error?l.message:"Network error."}}}}async write(e,r){if(e.kind==="enqueue"){let s=`lmauto enqueue ${e.team} "${x(e.message)}" --from ${e.from}`;return this.post(this.url("api/enqueue"),{to:e.team,from:e.from,prompt:e.message},s,i=>{let l=i;return typeof l.id!="number"?null:`queued #${l.id} -> ${e.team}`},r)}if(e.kind==="send"){let s=`lmauto send ${e.team} "${x(e.message)}"`;return this.post(this.url("api/send"),{team:e.team,prompt:e.message},s,i=>{let l=i;return typeof l.status!="string"?null:`${e.team}: ${l.status}`},r)}if(e.kind==="source-add"){let s=e.label?`lmauto source add ${e.path} "${x(e.label)}"`:`lmauto source add ${e.path}`,i=e.label?{path:e.path,label:e.label}:{path:e.path};return this.post(this.url("api/sources"),i,s,l=>l.ok!==!0?null:`added ${e.path}`,r)}let a=`lmauto source remove ${e.path}`;return this.del(this.url(`api/sources?path=${encodeURIComponent(e.path)}`),a,s=>s.ok!==!0?null:`removed ${e.path}`,r)}async del(e,r,a,s){let i=new Date().toISOString();try{let l=await fetch(e,{method:"DELETE",signal:s}),n=null;try{n=await l.json()}catch{n=null}if(!l.ok){let d=P(n,l.status);return{ok:!1,ranCommand:r,ranAt:i,summary:d.message,raw:n,error:d}}let o=a(n);if(o===null){let d={code:"invalid_response",message:"Unexpected response shape."};return{ok:!1,ranCommand:r,ranAt:i,summary:d.message,raw:n,error:d}}return{ok:!0,ranCommand:r,ranAt:i,summary:o,raw:n}}catch(l){if(s.aborted)throw l;let n={code:"network_error",message:l instanceof Error?l.message:"Network error."};return{ok:!1,ranCommand:r,ranAt:i,summary:n.message,raw:null,error:n}}}async post(e,r,a,s,i){let l=new Date().toISOString();try{let n=await fetch(e,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(r),signal:i}),o=null;try{o=await n.json()}catch{o=null}if(!n.ok){let u=P(o,n.status);return{ok:!1,ranCommand:a,ranAt:l,summary:u.message,raw:o,error:u}}let d=s(o);if(d===null){let u={code:"invalid_response",message:"Unexpected response shape."};return{ok:!1,ranCommand:a,ranAt:l,summary:u.message,raw:o,error:u}}return{ok:!0,ranCommand:a,ranAt:l,summary:d,raw:o}}catch(n){if(i.aborted)throw n;let o={code:"network_error",message:n instanceof Error?n.message:"Network error."};return{ok:!1,ranCommand:a,ranAt:l,summary:o.message,raw:null,error:o}}}};function p(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function et(t,e){if(!e)return`<p class="muted" data-local-ran>ran: <code>${p(t)}</code></p>`;let r=Math.max(0,Math.round((Date.now()-Date.parse(e))/1e3));return`<p class="muted" data-local-ran>ran: <code>${p(t)}</code>, ${r}s ago</p>`}function I(t){return t===null?"":p(t)}function rt(t){return`<tr data-local-running-row="${t.id}"><td>${p(t.kind)}</td><td>${I(t.target)}</td><td>${p(t.started_at)}</td><td>${t.running_for_ms}</td><td>${p(t.holder_liveness)}</td></tr>`}function nt(t){return`<tr data-local-dead-row="${t.id}"><td>${p(t.kind)}</td><td>${I(t.target)}</td><td>${p(t.started_at)}</td><td>${t.age_ms}</td></tr>`}function at(t){return`<tr data-local-idle-row="${t.id}"><td>${p(t.kind)}</td><td>${I(t.target)}</td><td>${p(t.status)}</td><td>${t.idle_ms}</td><td>${t.error?p(t.error):""}</td></tr>`}function ot(t,e,r,a,s,i){t.innerHTML=`
25
25
  <section class="local-pane" data-local-pane="running">
26
26
  <header><h2>Running</h2></header>
27
27
  ${et(s,i)}
28
28
  <h3>Running (${e.length})</h3>
29
29
  ${e.length===0?'<p class="muted">Nothing running.</p>':`<table class="local-table" data-local-running-table><thead><tr><th>KIND</th><th>TARGET</th><th>STARTED</th><th>RUNNING-FOR-MS</th><th>LIVENESS</th></tr></thead><tbody>${e.map(rt).join("")}</tbody></table>`}
30
30
  <h3>Dead (${r.length})</h3>
31
- ${r.length===0?'<p class="muted">None.</p>':`<table class="local-table" data-local-dead-table><thead><tr><th>KIND</th><th>TARGET</th><th>STARTED</th><th>STALE-FOR-MS</th></tr></thead><tbody>${r.map(nt).join("")}</tbody></table>`}
31
+ ${r.length===0?'<p class="muted">None.</p>':`<table class="local-table" data-local-dead-table><thead><tr><th>KIND</th><th>TARGET</th><th>STARTED</th><th>AGE-MS</th></tr></thead><tbody>${r.map(nt).join("")}</tbody></table>`}
32
32
  <h3>Idle (${a.length})</h3>
33
33
  ${a.length===0?'<p class="muted">None.</p>':`<table class="local-table" data-local-idle-table><thead><tr><th>KIND</th><th>TARGET</th><th>STATUS</th><th>IDLE-MS</th><th>ERROR</th></tr></thead><tbody>${a.map(at).join("")}</tbody></table>`}
34
34
  </section>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lmctl-ai/lmctl",
3
- "version": "0.2.382",
3
+ "version": "0.2.384",
4
4
  "description": "A provider-agnostic control plane for teams of AI coding agents — across providers, with independent review and durable memory.",
5
5
  "type": "module",
6
6
  "homepage": "https://lmctl.com",