@lmctl-ai/lmctl 0.1.157 → 0.1.158

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/cli/index.js CHANGED
@@ -2359,7 +2359,7 @@ List native provider sessions in scope, or list recent managed runs with --runs.
2359
2359
  `),0}async function lB(e,t={stdout:process.stdout,stderr:process.stderr}){if(e[0]==="--help"||e[0]==="-h"||e[0]==="help")return t.stdout.write(mf),0;let r,n;if(e.length===1){let u=Fr(e[0]);if(u===null)return t.stderr.write(mf),2;r=u.teamfile,n=u.alias}else if(e.length===2)[r,n]=e;else return t.stderr.write(mf),2;let s;try{s=await $(t,u=>Ee(r,u))}catch(u){return $e(t,`${r}: ${u instanceof Error?u.message:String(u)}`)}let i;try{i=ja(s,"utf8")}catch(u){return $e(t,`${r}: ${u instanceof Error?u.message:String(u)}`)}let o=i.split(`
2360
2360
  `),a=fB(o,n);if(a===void 0)return $e(t,`${n}: no active _MEMBER_ entry found`);let l=o[a];if(Fs(l,"teamfile")!==void 0)return $e(t,`${n}: refresh only applies to provider-backed members, not teamfile= members`);let c=(t.env??process.env)[Vn],d=Fs(l,"sessionid");return c!==void 0&&c.length>0&&d===c?$e(t,`${n}: cannot refresh its own running session \u2014 a meta-Lead or the operator must run this refresh.`):(o[a]=HS(l,"sessionid"),a>0&&/^\s*#CreationTime:/u.test(o[a-1])&&o.splice(a-1,1),Ma(s,o.join(`
2361
2361
  `),"utf8"),US([s],t))}function WS(e){return XW("sha256").update(e).digest("hex")}function BS(e,t){return{teamfile_path:t.teamfilePath,name:t.name,raw_text:t.rawText,raw_sha256:WS(t.rawText),registered_at:e?.registered_at??t.now,last_seeded_at:t.now}}function qS(e,t){let r=BS(e.getRootTeam(t.teamfilePath),t);return e.upsertRootTeam(r),r}function cB(e,t,r){let n=r.filter(a=>a.alias.toLowerCase()!=="lead").map(a=>{let l=a.teamfile!==void 0?`teamfile=${a.teamfile}`:`provider=${a.provider}`;return`- ${a.alias}: ${l}`}),s=n.length>0?n.join(`
2362
- `):"- (no non-Lead members)",i=r.find(a=>a.alias.toLowerCase()==="lead")?.provider??"",o=dB(i,e);return["lmctl seed initial connection only. Create or pin this provider session, then stop.","Do not inspect files, run commands, infer a task, delegate, edit, or begin work.","",`Teamfile path: ${e}`,"You are alias Lead for this AI-managed .lmctl team.","","Delegating work:",`- Blocking command shape: lmctl chat "${e}" <alias> "your task here"`,"- SAFE INPUT \u2014 use for ANYTHING non-trivial. A prompt typed into the command line is expanded by YOUR shell first,"," so backticks, $(...), $VAR and quotes are executed or stripped out of the message before lmctl sees it."," If the text contains backticks, quotes, $, newlines, or ANY relayed/pasted/quoted content, do NOT put it in the command.",` Write it to a file with your file-writing tool (NOT echo/heredoc \u2014 those are shell too), then: lmctl chat "${e}" <alias> --prompt-file <path>`,"- MCP lmctl_chat is synchronous/blocking; use it only as a quick-ping or backup path.","- lmctl is foreground/background agnostic. Use your provider or host runtime for async command handling when it supports that.","- For delegation, run the lmctl chat command above. If your runtime has a tracked background mode, it may wrap that same blocking command and notify you when it completes.","- For arbitrary shell work, use your provider/runtime shell tools directly; lmctl does not execute shell commands.",o,"","Delegation is an ACTION, not a plan: to hand a member a task, run the command or call the tool.","If you use lmctl_chat and it appears only after tool search, call it in the SAME turn and do not stop after discovering it or say you're about to call it.","","Team members:",s,"","Example MCP calls:",...r.filter(a=>a.alias.toLowerCase()!=="lead").map(a=>`lmctl_chat(team="${e}", alias="${a.alias}", prompt="your task here")`),"","If a member feels sluggish or starts drifting (degraded or off-track output):",` 1. Check ONE member's session health: lmctl health "${e}" <alias> (size/state \u2014 informational).`," 2. Make sure important state is captured in durable-memory/ \u2014 update it if not.",` 3. Replace its session: lmctl refresh "${e}" <alias> (re-seeds the member: drops chat history, re-reads durable-memory/). You cannot refresh your own Lead session \u2014 a meta-Lead or the operator does that.`,` Optional: lmctl tail "${e}" <alias> to inspect its recent messages while troubleshooting.`,"(These health/recovery commands are shell commands. For delegation, prefer lmctl chat; lmctl_chat is the synchronous backup.)","","Full teamfile document at seed time:","```lmctl",t.trimEnd(),"```","","Remember this teamfile path. Do not ask the operator for it when asked to ping or delegate to members.","Reply exactly: ACK: teamfile context recorded."].join(`
2362
+ `):"- (no non-Lead members)",i=r.find(a=>a.alias.toLowerCase()==="lead")?.provider??"",o=dB(i,e);return["lmctl seed initial connection only. Create or pin this provider session, then stop.","Do not inspect files, run commands, infer a task, delegate, edit, or begin work.","",`Teamfile path: ${e}`,"You are alias Lead for this AI-managed .lmctl team.","","Delegating work:",`- Blocking command shape: lmctl chat "${e}" <alias> "your task here"`,"- SAFE INPUT \u2014 use for ANYTHING non-trivial. A prompt typed into the command line is expanded by YOUR shell first,"," so backticks, $(...), $VAR and quotes are executed or stripped out of the message before lmctl sees it."," If the text contains backticks, quotes, $, newlines, or ANY relayed/pasted/quoted content, do NOT put it in the command.",` Write it to a file with your file-writing tool (NOT echo/heredoc \u2014 those are shell too), then: lmctl chat "${e}" <alias> --prompt-file <path>`,"- lmctl is foreground/background agnostic. Use your provider or host runtime for async command handling when it supports that.","- For delegation, run the lmctl chat command above. If your runtime has a tracked background mode, it may wrap that same blocking command, but check the result with --json or lmctl status.","- Busy receiver ENQUEUES. lmctl chat exits 0 for BOTH delivered and enqueued, so exit code alone CANNOT tell you a reply arrived.","- lmctl chat ... --json is machine-readable: status/path distinguishes a DELIVERED reply from an ENQUEUED message, with id/sender/receiver fields.","- lmctl status shows your identity, members with busy/idle, mail queued TO and FROM you, and why a receiver is busy. Run it when you are unsure whether a delegation landed.","- For arbitrary shell work, use your provider/runtime shell tools directly; lmctl does not execute shell commands.",o,"","Delegation is an ACTION, not a plan: to hand a member a task, run the command or call the tool.","","Team members:",s,"","If a member feels sluggish or starts drifting (degraded or off-track output):",` 1. Check ONE member's session health: lmctl health "${e}" <alias> (size/state \u2014 informational).`," 2. Make sure important state is captured in durable-memory/ \u2014 update it if not.",` 3. Replace its session: lmctl refresh "${e}" <alias> (re-seeds the member: drops chat history, re-reads durable-memory/). You cannot refresh your own Lead session \u2014 a meta-Lead or the operator does that.`,` Optional: lmctl tail "${e}" <alias> to inspect its recent messages while troubleshooting.`,"(These health/recovery commands are shell commands. For delegation, use lmctl chat.)","","Full teamfile document at seed time:","```lmctl",t.trimEnd(),"```","","Remember this teamfile path. Do not ask the operator for it when asked to ping or delegate to members.","Reply exactly: ACK: teamfile context recorded."].join(`
2363
2363
  `)}function dB(e,t){let r=`lmctl chat "${t}" <alias> "your task here"`;switch(e.toLowerCase()){case"claude":return`- Claude tip: run the blocking command (${r}) as background Bash (run_in_background: true); the runtime re-invokes you with the reply when it completes.`;case"copilot":return`- Copilot tip: run the blocking command (${r}) via bash async mode (mode:"async"); the runtime notifies you with output when it completes.`;case"agy":return`- Antigravity tip: run the blocking command (${r}) via run_command with WaitMsBeforeAsync: 0 (Background Tasks); agy wakes you with the output when it completes.`;case"qwen":return`- Qwen tip: run the blocking command (${r}) via the monitor tool; it notifies you on completion.`;case"codex":return"- Codex note: run lmctl chat as the blocking delegation primitive; use Codex-native tool/background behavior when available.";case"gemini":return"- Gemini note: run lmctl chat as the blocking delegation primitive; use Gemini-native tool/background behavior when available.";case"opencode":return"- OpenCode note: use the provider-native background/task surface when available; otherwise run one blocking lmctl chat turn and wait.";default:return"- If your provider has native background completion, use it around the blocking command; otherwise run one blocking lmctl chat turn at a time."}}function uB(e){let t=new Map;for(let r=0;r<e.length;r+=1){let n=e[r];if(!/^\s*_MEMBER_\s+\S/.test(n))continue;let s=Fs(n,"alias");s!==void 0&&t.set(s.toLowerCase(),r)}return t}function fB(e,t){let r=t.toLowerCase();for(let n=0;n<e.length;n+=1){let s=e[n];if(/^\s*_MEMBER_\s+\S/u.test(s)&&Fs(s,"alias")?.toLowerCase()===r)return n}}function mB(e,t){for(let r of e.split(`
2364
2364
  `))if(/^\s*#?\s*_MEMBER_\s+\S/u.test(r)&&Fs(r,"alias")===t)return!0;return!1}function pB(e){return/^[A-Za-z][A-Za-z0-9_-]*$/u.test(e)}function Fs(e,t){let n=new RegExp(`(?:^|\\s)${t}=(?:"([^"]*)"|(\\S*))`).exec(e);return n===null?void 0:n[1]??n[2]??""}function _B(e,t,r){let n=`${t}=${gf(r)}`,s=new RegExp(`(^|\\s)${t}=(?:"[^"]*"|\\S*)`);return s.test(e)?e.replace(s,(i,o)=>`${o}${n}`):`${e.trimEnd()} ${n}`}function HS(e,t){let r=new RegExp(`(^|\\s)${t}=(?:"[^"]*"|\\S*)`);return e.replace(r,"").replace(/\s+/gu," ").trimEnd()}function gf(e){return/[\s"]/u.test(e)?`"${e.replace(/"/g,'\\"')}"`:e}function hB(e,t){let r=e.split(`
2365
2365
  `),n=-1;for(let a=r.length-1;a>=0;a-=1)if(/^\s*_MEMBER_(?:\s|$)/u.test(r[a])){n=a;break}if(n>=0)return r.splice(n+1,0,t),r.join(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lmctl-ai/lmctl",
3
- "version": "0.1.157",
3
+ "version": "0.1.158",
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",