@lmctl-ai/lmctl 0.2.410 → 0.2.411

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 CHANGED
@@ -1 +1 @@
1
- {"sha": "25cc8fa881d7d8f8aef6645dce47cd6a77ac22a9", "dirty": false, "builtAt": "2026-10-23T23:09:34.000Z"}
1
+ {"sha": "288ca2b07c7139a4f3c0a1437bd7cc5208c3c62d", "dirty": false, "builtAt": "2026-10-23T23:48:00.000Z"}
package/dist/lmbee.js CHANGED
@@ -2786,7 +2786,7 @@ ${u}`);m=p}return{output:pU(e,d,{...f!==void 0?{ids:f}:{},all:o.all===!0,open:o.
2786
2786
  `),exitCode:0}}case"team":{if(s[0]==="register"){let l=s[1],u=typeof o.teamfile=="string"?o.teamfile:void 0;if(l===void 0||u===void 0)return oe("usage: lmbee team register <name> --teamfile <path> [--alias <alias>]");let d=typeof o.alias=="string"?o.alias:void 0,f=Wj(e,l,u,{alias:d});return{output:f.output,exitCode:f.ok?0:1}}let[a]=s;if(a===void 0||o.timeline!==!0)return oe("usage: lmbee team <name> --timeline [--limit N] | lmbee team register <name> --teamfile <path> [--alias <alias>]");let c=ac(o.limit,"--limit");return c instanceof Error?{output:`error: ${c.message}`,exitCode:1}:c!==void 0&&(c<1||c>Pc)?{output:`error: --limit must be a positive integer <= ${Pc}`,exitCode:1}:{output:qj(e,a,{limit:c,json:i}),exitCode:0}}case"source":{let[a,...c]=s;if(a==="add"){if(c[0]===void 0)return oe("usage: lmbee source add <path> [label...]");let l=Bp(e,c[0],c.slice(1).join(" ")||void 0);return{output:l.output,exitCode:l.ok?0:1}}return a==="list"?{output:EU(e,{json:i}),exitCode:0}:a==="remove"?c[0]===void 0?oe("usage: lmbee source remove <path>"):{output:yU(e,c[0]),exitCode:0}:oe("usage: lmbee source add <path> [label...] | list | remove <path>")}case"mail":{let[a]=s;return a==="status"?{output:bP(e,{json:i}),exitCode:0}:oe("usage: lmbee mail status")}case"scan":{let[a]=s;if(a==="status")return{output:kj(e,{json:i}),exitCode:0};if(a==="pause"){let c=typeof o.actor=="string"?o.actor:void 0,l=typeof o.note=="string"?o.note:void 0,u=typeof o["resume-after"]=="string"?o["resume-after"]:void 0;return{output:Rj(e,{...c!==void 0?{actor:c}:{},...l!==void 0?{note:l}:{},...u!==void 0?{resumeAfter:u}:{},json:i}),exitCode:0}}return a==="start"?{output:Nj(e,{json:i}),exitCode:0}:oe("usage: lmbee scan pause [--actor NAME] [--note TEXT] [--resume-after ISO] | start | status")}case"auto-nudge-redirect":{let[a,c]=s;if(a==="status")return{output:KF(e,c,{json:i}),exitCode:0};if(a==="clear")return c===void 0?oe("usage: lmbee auto-nudge-redirect clear <team>"):{output:YF(e,c,{json:i}),exitCode:0};if(a==="set"){if(c===void 0||typeof o.companion!="string")return oe("usage: lmbee auto-nudge-redirect set <team> --companion <team> [--worker-alias A] [--commit-threshold N] [--hours-threshold-ms N]");let l=typeof o["worker-alias"]=="string"?o["worker-alias"]:void 0,u=typeof o["commit-threshold"]=="string"?Number.parseInt(o["commit-threshold"],10):void 0,d=typeof o["hours-threshold-ms"]=="string"?Number.parseInt(o["hours-threshold-ms"],10):void 0;return{output:JF(e,c,{companionTeam:o.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 oe("usage: lmbee auto-nudge-redirect set <team> --companion <team> [...] | clear <team> | status [<team>]")}case"provider":{let[a,c]=s;if(a==="status")return{output:sj(e,c,{json:i}),exitCode:0};if(a==="enable")return c===void 0?oe("usage: lmbee provider enable <name>"):{output:rj(e,c,{json:i}),exitCode:0};if(a==="disable"){if(c===void 0)return oe("usage: lmbee provider disable <name> [--reason TEXT] [--expires-at ISO]");let l=typeof o.reason=="string"?o.reason:void 0,u=typeof o["expires-at"]=="string"?o["expires-at"]:void 0;return{output:nj(e,c,{...l!==void 0?{reason:l}:{},...u!==void 0?{expiresAt:u}:{},json:i}),exitCode:0}}return oe("usage: lmbee provider disable <name> [--reason TEXT] [--expires-at ISO] | enable <name> | status [<name>]")}case"rate-limit":{let[a]=s;if(a==="status")return{output:oj(e,{json:i}),exitCode:0};if(a==="log"){let c=typeof o.provider=="string"?o.provider:void 0,l=typeof o.limit=="string"?Number.parseInt(o.limit,10):void 0,u=l!==void 0&&!Number.isNaN(l)?l:void 0;return{output:ij(e,{...c!==void 0?{provider:c}:{},...u!==void 0?{limit:u}:{},json:i}),exitCode:0}}return oe("usage: lmbee rate-limit status | log [--provider NAME] [--limit N]")}case"reliability-report":try{return{output:uj(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 o.config=="string"?o.config:void 0;if(a===void 0)return oe("usage: lmbee subscriptions --config <path> [--json]");try{return{output:await dj(a,{json:i}),exitCode:0}}catch(c){return{output:`subscriptions: ${c instanceof Error?c.message:String(c)}`,exitCode:1}}}case"tasks":{let a=rn(r,["json",...Fj]),c=jj(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=rn(r,["json",...GF]),c=await WF(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: ${n}
2787
2787
  ${ko}`,exitCode:1}}}function oe(e){return{output:e,exitCode:1}}import{mkdir as jue,readFile as que,stat as Hue,writeFile as Bue}from"node:fs/promises";import{mkdir as Cce,readFile as m1,stat as Oce,writeFile as $ce}from"node:fs/promises";import{readFileSync as Dce}from"node:fs";import{homedir as Mce}from"node:os";import{dirname as Pce,extname as Uce}from"node:path";var _1="https://lmctl.ai/tools/lmchat";async function g1(e,t={}){let n=zce(t),r=hv(e);if(r.kind==="whoami"){n.stdout(Kce(n.env,r.api));return}if(r.kind==="login"){let{runLogin:o}=await Promise.resolve().then(()=>(f1(),d1));if(await o({io:{stdout:{write:a=>n.stdout(a.replace(/\n$/,""))},stderr:{write:a=>n.stderr(a.replace(/\n$/,""))}},env:n.env})!==0)throw new Vr("login failed");return}let s=Vce(r.api,n.env);if(r.kind==="register-room"){await Ro(n.fetch,`${s}/rooms`,{method:"POST",headers:{...vs(n.env),"content-type":"application/json"},body:JSON.stringify({room_name:r.roomName})}),n.stdout(`created ${r.roomName}`);return}if(r.kind==="rooms"){let o=await Ro(n.fetch,`${s}/rooms`,{method:"GET",headers:vs(n.env)});if(r.json)n.stdout(JSON.stringify(o.rooms));else{n.stdout("room next_seq created_at");for(let i of o.rooms)n.stdout(`${i.room_name} ${i.next_seq} ${i.created_at}`)}return}if(r.kind==="read"&&await p1(n,s,r),r.kind==="post"){let o=await Fce(n,s,r);n.stdout(String(o));return}if(r.kind==="say"){let o=await jce(n,s,r);n.stdout(String(o));return}if(r.kind==="list"){await p1(n,s,{...r,kind:"read"});return}if(r.kind==="get"){await Hce(n,s,r),n.stdout(`saved ${r.out}`);return}if(r.kind==="delete"){let o=await Bce(n,s,r);n.stdout(`deleted ${o}`);return}if(r.kind==="delete-room"){let o=await Wce(n,s,r);n.stdout(`deleted room ${o}`);return}}function hv(e){let t=[...e],n=Et(t,"--api"),r=t.shift();if(!r||r==="help"||r==="--help"||r==="-h")throw new Vr(h1());if(r==="whoami"){let s=Et(t,"--api")??n;return mr(t),{kind:"whoami",...s?{api:s}:{}}}if(r==="login"){let s=Et(t,"--api")??n;return mr(t),{kind:"login",...s?{api:s}:{}}}if(r==="rooms"){let s=Et(t,"--api")??n,o=Zp(t,"--json");return mr(t),{kind:"rooms",...o?{json:!0}:{},...s?{api:s}:{}}}if(r==="read"){let s=Et(t,"--api")??n,o=fr(t,"room_name"),i=Et(t,"--after"),a=Et(t,"--limit"),c=Et(t,"--interval"),l=Zp(t,"--follow"),u=Zp(t,"--json");return mr(t),{kind:"read",roomName:o,...i!==void 0?{after:i}:{},...a!==void 0?{limit:a}:{},...c!==void 0?{interval:c}:{},...l?{follow:!0}:{},...u?{json:!0}:{},...s?{api:s}:{}}}if(r==="register-room"||r==="create"){let s=Et(t,"--api")??n,o=fr(t,"room_name");return mr(t),{kind:"register-room",roomName:o,...s?{api:s}:{}}}if(r==="post"){let s=Et(t,"--api")??n,o=fr(t,"room_name"),i=mv(t,"--name"),a=mv(t,"--file"),c=Et(t,"--content-type");return mr(t),{kind:"post",roomName:o,name:i,file:a,...c?{contentType:c}:{},...s?{api:s}:{}}}if(r==="say"){let s=Et(t,"--api")??n,o=fr(t,"room_name"),i=Et(t,"--title"),a=fr(t,"text");return mr(t),{kind:"say",roomName:o,text:a,...i?{title:i}:{},...s?{api:s}:{}}}if(r==="list"){let s=Et(t,"--api")??n,o=fr(t,"room_name"),i=Et(t,"--after"),a=Et(t,"--limit"),c=Zp(t,"--json");return mr(t),{kind:"list",roomName:o,...i!==void 0?{after:i}:{},...a!==void 0?{limit:a}:{},...c?{json:!0}:{},...s?{api:s}:{}}}if(r==="get"){let s=Et(t,"--api")??n,o=fr(t,"room_name"),i=fr(t,"seq"),a=mv(t,"--out");return mr(t),{kind:"get",roomName:o,seq:i,out:a,...s?{api:s}:{}}}if(r==="delete"){let s=Et(t,"--api")??n,o=fr(t,"room_name"),i=fr(t,"seq");return mr(t),{kind:"delete",roomName:o,seq:i,...s?{api:s}:{}}}if(r==="delete-room"){let s=Et(t,"--api")??n,o=fr(t,"room_name");return mr(t),{kind:"delete-room",roomName:o,...s?{api:s}:{}}}throw new Vr(`unknown command: ${r}
2788
2788
 
2789
- ${h1()}`)}async function Fce(e,t,n){let r=await e.stat(n.file);if(!r.isFile())throw new Error(`not a file: ${n.file}`);let s=n.contentType??Yce(n.name),o=await Ro(e.fetch,`${t}/rooms/${encodeURIComponent(n.roomName)}/files`,{method:"POST",headers:{...vs(e.env),"content-type":"application/json"},body:JSON.stringify({name:n.name,content_type:s,size:r.size})}),i=await e.readFile(n.file),a=typeof i=="string"?Buffer.from(i):i,c=new FormData;for(let[d,f]of Object.entries(o.fields))c.append(d,f);c.append("file",new Blob([a],{type:o.content_type}),o.name);let l=await e.fetch(o.upload_url,{method:"POST",body:c});if(!l.ok)throw new Error(`S3 upload failed: ${l.status} ${await l.text().catch(()=>"")}`.trim());return(await Ro(e.fetch,`${t}/rooms/${encodeURIComponent(n.roomName)}/files/${encodeURIComponent(String(o.seq))}/commit`,{method:"POST",headers:{...vs(e.env),"content-type":"application/json"},body:JSON.stringify({name:o.name})})).seq}async function jce(e,t,n){return(await Ro(e.fetch,`${t}/rooms/${encodeURIComponent(n.roomName)}/messages`,{method:"POST",headers:{...vs(e.env),"content-type":"application/json"},body:JSON.stringify({text:n.text,...n.title?{title:n.title}:{}})})).seq}async function p1(e,t,n){let r=n.after,s=Number(n.interval??"5");if(!Number.isFinite(s)||s<1)throw new Vr(`--interval must be a finite number >= 1 seconds (got "${n.interval}")`);let o=s*1e3,i=!1,a=[];for(;;){let c=await qce(e,t,n.roomName,r,n.limit);n.follow?n.json?c.files.length>0&&e.stdout(JSON.stringify(c.files)):(i||(y1(e.stdout),i=!0),w1(e.stdout,c.files)):a.push(...c.files);let l=typeof c.next_after=="number"?String(c.next_after):r,u=l!==void 0&&l!==r;if(u&&(r=l),!c.has_more||!u){if(!n.follow){n.json?e.stdout(JSON.stringify(a)):Jce(e.stdout,a);return}await Gce(o)}}}async function qce(e,t,n,r,s){let o=new URLSearchParams;r!==void 0&&o.set("after",r),s!==void 0&&o.set("limit",s);let i=o.toString();return Ro(e.fetch,`${t}/rooms/${encodeURIComponent(n)}/files${i?`?${i}`:""}`,{method:"GET",headers:vs(e.env)})}async function Hce(e,t,n){let r=await e.fetch(`${t}/rooms/${encodeURIComponent(n.roomName)}/files/${encodeURIComponent(n.seq)}`,{method:"GET",headers:vs(e.env),redirect:"manual"});if(r.status!==302)throw await pv(r,"download request failed"),new Error(`download request did not return a redirect: ${r.status}`);let s=r.headers.get("location");if(!s)throw new Error("download redirect missing Location header");let o=await e.fetch(s,{method:"GET"});await pv(o,"presigned download failed");let i=new Uint8Array(await o.arrayBuffer());await e.mkdir(Pce(n.out),{recursive:!0}),await e.writeFile(n.out,i)}async function Bce(e,t,n){return(await Ro(e.fetch,`${t}/rooms/${encodeURIComponent(n.roomName)}/files/${encodeURIComponent(n.seq)}`,{method:"DELETE",headers:vs(e.env)})).seq}async function Wce(e,t,n){return(await Ro(e.fetch,`${t}/rooms/${encodeURIComponent(n.roomName)}`,{method:"DELETE",headers:vs(e.env)})).room_name}function Gce(e){return new Promise(t=>setTimeout(t,e))}async function Ro(e,t,n){let r=await e(t,n);return await pv(r,"API request failed"),await r.json()}async function pv(e,t){if(e.ok)return;let n=await e.text().catch(()=>"");throw new Error(`${t}: ${e.status}${n?` ${n}`:""}`)}function Xce(e){return E1(e).appkey}function E1(e){if(eh(e.LMCTL_APPKEY))return{appkey:e.LMCTL_APPKEY,source:"LMCTL_APPKEY"};let t=e.LMCTL_APPKEY_FILE?.trim();if(t){let o=fv(t);if(o)return{appkey:o,source:"LMCTL_APPKEY_FILE"}}let n=e.XDG_CONFIG_HOME?.trim()||`${Mce()}/.config`,r=fv(`${n}/lmctl/appkey.json`);if(r)return{appkey:r,source:"~/.config/lmctl/appkey.json"};let s=fv(`${n}/lmctl/lmchat-apikey`);if(s)return{appkey:s,source:"~/.config/lmctl/lmchat-apikey (legacy)"};if(eh(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 eh(e){return!!(e&&e===e.trim()&&!/[\u0000-\u001f\u007f]/.test(e))}function fv(e){let t;try{t=Dce(e,"utf8")}catch{return}let n=t.trim();if(n){if(n.startsWith("{"))try{let r=JSON.parse(n),s=typeof r.appkey=="string"?r.appkey.trim():void 0;return eh(s)?s:void 0}catch{return}return eh(n)?n:void 0}}function vs(e){return{authorization:`Bearer ${Xce(e)}`}}function Vce(e,t){return(e??t.LMCHAT_API_URL??_1).replace(/\/+$/,"")}function Jce(e,t){y1(e),w1(e,t)}function y1(e){e("seq name size content_type created_at")}function w1(e,t){for(let n of t)e(`${n.seq} ${n.name} ${n.size} ${n.content_type} ${n.created_at}`)}function Yce(e){let t=Uce(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 Kce(e,t){let n="unset";try{n=E1(e).source}catch{n="unset"}return[`API: ${t??e.LMCHAT_API_URL??_1}`,`appkey source: ${n}`,"","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(`
2789
+ ${h1()}`)}async function Fce(e,t,n){let r=await e.stat(n.file);if(!r.isFile())throw new Error(`not a file: ${n.file}`);let s=n.contentType??Yce(n.name),o=await Ro(e.fetch,`${t}/rooms/${encodeURIComponent(n.roomName)}/files`,{method:"POST",headers:{...vs(e.env),"content-type":"application/json"},body:JSON.stringify({name:n.name,content_type:s,size:r.size})}),i=await e.readFile(n.file),a=typeof i=="string"?Buffer.from(i):i,c=new FormData;for(let[d,f]of Object.entries(o.fields))c.append(d,f);c.append("file",new Blob([a],{type:o.content_type}),o.name);let l=await e.fetch(o.upload_url,{method:"POST",body:c});if(!l.ok)throw new Error(`S3 upload failed: ${l.status} ${await l.text().catch(()=>"")}`.trim());return(await Ro(e.fetch,`${t}/rooms/${encodeURIComponent(n.roomName)}/files/${encodeURIComponent(String(o.seq))}/commit`,{method:"POST",headers:{...vs(e.env),"content-type":"application/json"},body:JSON.stringify({name:o.name})})).seq}async function jce(e,t,n){return(await Ro(e.fetch,`${t}/rooms/${encodeURIComponent(n.roomName)}/messages`,{method:"POST",headers:{...vs(e.env),"content-type":"application/json"},body:JSON.stringify({text:n.text,...n.title?{title:n.title}:{}})})).seq}async function p1(e,t,n){let r=n.after,s=Number(n.interval??"5");if(!Number.isFinite(s)||s<1)throw new Vr(`--interval must be a finite number >= 1 seconds (got "${n.interval}")`);let o=s*1e3,i=!1,a=[],c=new Set;for(;;){let l=await qce(e,t,n.roomName,r,n.limit),u={...l,files:l.files.filter(m=>!c.has(m.seq))};for(let m of u.files)c.add(m.seq);n.follow?n.json?u.files.length>0&&e.stdout(JSON.stringify(u.files)):(i||(y1(e.stdout),i=!0),w1(e.stdout,u.files)):a.push(...u.files);let d=typeof u.next_after=="number"?String(u.next_after):r,f=d!==void 0&&d!==r;if(f&&(r=d),r!==void 0)for(let m of c)m<=Number(r)&&c.delete(m);if(!u.has_more||!f){if(!n.follow){n.json?e.stdout(JSON.stringify(a)):Jce(e.stdout,a);return}await Gce(o)}}}async function qce(e,t,n,r,s){let o=new URLSearchParams;r!==void 0&&o.set("after",r),s!==void 0&&o.set("limit",s);let i=o.toString();return Ro(e.fetch,`${t}/rooms/${encodeURIComponent(n)}/files${i?`?${i}`:""}`,{method:"GET",headers:vs(e.env)})}async function Hce(e,t,n){let r=await e.fetch(`${t}/rooms/${encodeURIComponent(n.roomName)}/files/${encodeURIComponent(n.seq)}`,{method:"GET",headers:vs(e.env),redirect:"manual"});if(r.status!==302)throw await pv(r,"download request failed"),new Error(`download request did not return a redirect: ${r.status}`);let s=r.headers.get("location");if(!s)throw new Error("download redirect missing Location header");let o=await e.fetch(s,{method:"GET"});await pv(o,"presigned download failed");let i=new Uint8Array(await o.arrayBuffer());await e.mkdir(Pce(n.out),{recursive:!0}),await e.writeFile(n.out,i)}async function Bce(e,t,n){return(await Ro(e.fetch,`${t}/rooms/${encodeURIComponent(n.roomName)}/files/${encodeURIComponent(n.seq)}`,{method:"DELETE",headers:vs(e.env)})).seq}async function Wce(e,t,n){return(await Ro(e.fetch,`${t}/rooms/${encodeURIComponent(n.roomName)}`,{method:"DELETE",headers:vs(e.env)})).room_name}function Gce(e){return new Promise(t=>setTimeout(t,e))}async function Ro(e,t,n){let r=await e(t,n);return await pv(r,"API request failed"),await r.json()}async function pv(e,t){if(e.ok)return;let n=await e.text().catch(()=>"");throw new Error(`${t}: ${e.status}${n?` ${n}`:""}`)}function Xce(e){return E1(e).appkey}function E1(e){if(eh(e.LMCTL_APPKEY))return{appkey:e.LMCTL_APPKEY,source:"LMCTL_APPKEY"};let t=e.LMCTL_APPKEY_FILE?.trim();if(t){let o=fv(t);if(o)return{appkey:o,source:"LMCTL_APPKEY_FILE"}}let n=e.XDG_CONFIG_HOME?.trim()||`${Mce()}/.config`,r=fv(`${n}/lmctl/appkey.json`);if(r)return{appkey:r,source:"~/.config/lmctl/appkey.json"};let s=fv(`${n}/lmctl/lmchat-apikey`);if(s)return{appkey:s,source:"~/.config/lmctl/lmchat-apikey (legacy)"};if(eh(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 eh(e){return!!(e&&e===e.trim()&&!/[\u0000-\u001f\u007f]/.test(e))}function fv(e){let t;try{t=Dce(e,"utf8")}catch{return}let n=t.trim();if(n){if(n.startsWith("{"))try{let r=JSON.parse(n),s=typeof r.appkey=="string"?r.appkey.trim():void 0;return eh(s)?s:void 0}catch{return}return eh(n)?n:void 0}}function vs(e){return{authorization:`Bearer ${Xce(e)}`}}function Vce(e,t){return(e??t.LMCHAT_API_URL??_1).replace(/\/+$/,"")}function Jce(e,t){y1(e),w1(e,t)}function y1(e){e("seq name size content_type created_at")}function w1(e,t){for(let n of t)e(`${n.seq} ${n.name} ${n.size} ${n.content_type} ${n.created_at}`)}function Yce(e){let t=Uce(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 Kce(e,t){let n="unset";try{n=E1(e).source}catch{n="unset"}return[`API: ${t??e.LMCHAT_API_URL??_1}`,`appkey source: ${n}`,"","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(`
2790
2790
  `)}function Zp(e,t){let n=e.indexOf(t);return n===-1?!1:(e.splice(n,1),!0)}function Et(e,t){let n=e.indexOf(t);if(n===-1)return;let r=e[n+1];if(!r||r.startsWith("--"))throw new Vr(`missing value for ${t}`);return e.splice(n,2),r}function mv(e,t){let n=Et(e,t);if(!n)throw new Vr(`missing required ${t}`);return n}function fr(e,t){let n=e.shift();if(!n||n.startsWith("--"))throw new Vr(`missing ${t}`);return n}function mr(e){if(e.length>0)throw new Vr(`unexpected argument: ${e[0]}`)}function zce(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,n)=>n?m1(t,{encoding:n}):m1(t)),writeFile:e.writeFile??((t,n)=>$ce(t,n)),mkdir:e.mkdir??((t,n)=>Cce(t,n)),stat:e.stat??(t=>Oce(t))}}function h1(){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(`
2791
2791
  `)}var Vr=class extends Error{};import{mkdir as ule,readFile as dle,stat as fle,writeFile as mle}from"node:fs/promises";import{basename as ple,extname as hle,join as _le}from"node:path";async function F1(e,t={}){let n=Ale(t),r=_v(e);if(r.kind==="whoami"){n.stdout(Tle(n.env,r.api));return}if(r.kind==="login"){let{runLogin:a}=await Promise.resolve().then(()=>(M1(),D1));if(await a({env:n.env})!==0)throw new Error("login failed");return}let s=wle(r.api,n.env),o=xe({env:n.env}).appkey,i=Pt({apiUrl:s,appkey:o,fetch:n.fetch});if(r.kind==="mailboxes"){let a=await bi(()=>i.listMailboxes());n.stdout("mailbox created_at");for(let c of a)n.stdout(`${c.mailbox_name} ${c.created_at}`);return}if(r.kind==="create"){await bi(()=>i.createMailbox(r.mailbox,{tolerate409:!1})),n.stdout(`created ${r.mailbox}`);return}if(r.kind==="send"){let a=await bi(()=>gle(n,i,r));n.stdout(String(a));return}if(r.kind==="list"){let a=await bi(()=>i.listMessages(r.mailbox,{...r.status?{status:r.status}:{},...r.after?{after:Ele(r.after)}:{}}));n.stdout("seq status sender subject attachments created_at");for(let c of a.messages)n.stdout(`${c.seq} ${c.read?"read":"unread"} ${c.sender} ${c.subject} ${c.attachments.length} ${c.created_at}`);return}if(r.kind==="read"){let a=P1(r.seq),c=await bi(()=>i.getMessage(r.mailbox,a));await n.mkdir(r.out,{recursive:!0});let l=new Set;for(let[u,d]of[c.body,...c.attachments].entries()){let f=d.name;l.has(f)&&(f=`${String(u).padStart(3,"0")}_${f}`),l.add(f);let m=_le(r.out,f);await n.writeFile(m,await bi(()=>i.download(d.download_url),"presigned download failed")),n.stdout(`saved ${m}`)}return}r.kind==="delete"&&(await bi(()=>i.deleteMessage(r.mailbox,P1(r.seq))),n.stdout(`deleted ${r.seq}`))}function _v(e){let t=[...e],n=uc(t,"--api"),r=t.shift();if(!r||["help","--help","-h"].includes(r))throw new Ss(U1());if(r==="login"||r==="whoami"||r==="mailboxes")return lc(t),{kind:r,...n?{api:n}:{}};if(r==="create"){let s=Ai(t,"mailbox");return lc(t),{kind:"create",mailbox:s,...n?{api:n}:{}}}if(r==="send"){let s=Ai(t,"mailbox"),o=ble(t,"--file"),i=uc(t,"--subject"),a=Sle(t,"--attach");return lc(t),{kind:"send",mailbox:s,file:o,attachments:a,...i?{subject:i}:{},...n?{api:n}:{}}}if(r==="list"){let s=Ai(t,"mailbox"),o=uc(t,"--status"),i=uc(t,"--after");return lc(t),{kind:"list",mailbox:s,...o?{status:o}:{},...i?{after:i}:{},...n?{api:n}:{}}}if(r==="read"){let s=Ai(t,"mailbox"),o=Ai(t,"seq"),i=uc(t,"--out")??".";return lc(t),{kind:"read",mailbox:s,seq:o,out:i,...n?{api:n}:{}}}if(r==="delete"){let s=Ai(t,"mailbox"),o=Ai(t,"seq");return lc(t),{kind:"delete",mailbox:s,seq:o,...n?{api:n}:{}}}throw new Ss(`unknown command: ${r}
2792
2792
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lmctl-ai/lmctl",
3
- "version": "0.2.410",
3
+ "version": "0.2.411",
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",