@lmctl-ai/lmctl 0.1.259 → 0.1.260

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.
Files changed (2) hide show
  1. package/dist/cli/index.js +10 -9
  2. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -2574,7 +2574,7 @@ ${dk}
2574
2574
  `),1})}let s=Hn(gH,{target:r.target,alias:r.alias,flags:{session:r.sessionFlag,provider:r.providerFlag}});if(s.mode==="error")return t.stderr.write(`error: ${s.message}
2575
2575
  `),2;if(s.mode==="managed")return t.stderr.write(`error: chat managed mode requires --run <id>
2576
2576
  `),2;let i;if(s.mode==="ai-team"){if(s.alias===void 0)return t.stderr.write(`error: chat: alias required (internal)
2577
- `),2;let u=await Cl({teamfile:s.teamfile,alias:s.alias,prompt:r.prompt,permissionMode:r.permissionMode,...r.idleTimeoutMs!==void 0?{idleTimeoutMs:r.idleTimeoutMs}:{},...r.rootFlag!==void 0?{rootFlag:r.rootFlag}:{},env:n,io:t,onEvent:f=>{r.json===!0&&f.kind==="delta"||vH(t,f,r.quiet===!0)},...r.json===!0?{onAccepted:f=>{t.stdout.write(`${JSON.stringify({status:"accepted",message_id:f})}
2577
+ `),2;let u=await Cl({teamfile:s.teamfile,alias:s.alias,prompt:r.prompt,permissionMode:r.permissionMode,...r.idleTimeoutMs!==void 0?{idleTimeoutMs:r.idleTimeoutMs}:{},...r.rootFlag!==void 0?{rootFlag:r.rootFlag}:{},env:n,io:t,onEvent:f=>{r.json===!0&&f.kind==="delta"||vH(t,f,r.verbose===!0)},...r.json===!0?{onAccepted:f=>{t.stdout.write(`${JSON.stringify({status:"accepted",message_id:f})}
2578
2578
  `)}}:{}});return r.json===!0?u.status==="enqueued"?(t.stdout.write(`${JSON.stringify({status:"enqueued",path:"enqueued",id:u.id,message_id:u.messageId,sender:u.sender,receiver:u.receiver})}
2579
2579
  `),0):u.status==="busy"?(t.stdout.write(`${JSON.stringify({status:"busy",message:u.message,teamChatLogId:u.teamChatLogId})}
2580
2580
  `),1):u.status==="error"?(t.stdout.write(`${JSON.stringify({status:"error",errorKind:u.errorKind,message:u.message,teamChatLogId:u.teamChatLogId,...u.messageId===null?{}:{message_id:u.messageId}})}
@@ -2589,24 +2589,24 @@ ${dk}
2589
2589
  `)?"":`
2590
2590
  `}`),t.stderr.write(`note: ${uk(s.alias)}
2591
2591
  `),u.status==="stalled"?1:0)}else{if(s.provider===void 0)return t.stderr.write(`error: chat raw mode (bare sessionid / --session) requires --provider <name>
2592
- `),2;i={provider:s.provider,sessionId:s.sessionid,cwd:process.cwd()}}let o=!1,a=le(),l=0,c=0,d=0;try{let u={provider:i.provider,sessionId:i.sessionId,cwd:i.cwd,prompt:r.prompt,permissionMode:r.permissionMode,env:n,onDelta:p=>{o=!0,a&&(l+=1,d=Buffer.byteLength(p,"utf8"),c+=d),t.stdout.write(p)},onProgress:p=>pk(t,i.alias??"(raw)",p,r.quiet===!0)};i.model!==void 0&&(u.model=i.model),i.effort!==void 0&&(u.effort=i.effort),i.alias!==void 0&&(u.alias=i.alias),i.isLead!==void 0&&(u.isLead=i.isLead),r.idleTimeoutMs!==void 0&&(u.timeoutMs=r.idleTimeoutMs);let f=await Wt(u);a&&je(JSON.stringify({event:"chat_return",alias:i.alias??"(raw)",provider:i.provider,streamed:o,blockCount:l,streamedBytes:c,resultTextBytes:Buffer.byteLength(f.text,"utf8"),lastChunkBytes:d,tailPreview:TH(f.text,200)}));let m=f.status==="stalled";return o?f.text.endsWith(`
2592
+ `),2;i={provider:s.provider,sessionId:s.sessionid,cwd:process.cwd()}}let o=!1,a=le(),l=0,c=0,d=0;try{let u={provider:i.provider,sessionId:i.sessionId,cwd:i.cwd,prompt:r.prompt,permissionMode:r.permissionMode,env:n,onDelta:p=>{o=!0,a&&(l+=1,d=Buffer.byteLength(p,"utf8"),c+=d),t.stdout.write(p)},onProgress:p=>pk(t,i.alias??"(raw)",p,r.verbose===!0)};i.model!==void 0&&(u.model=i.model),i.effort!==void 0&&(u.effort=i.effort),i.alias!==void 0&&(u.alias=i.alias),i.isLead!==void 0&&(u.isLead=i.isLead),r.idleTimeoutMs!==void 0&&(u.timeoutMs=r.idleTimeoutMs);let f=await Wt(u);a&&je(JSON.stringify({event:"chat_return",alias:i.alias??"(raw)",provider:i.provider,streamed:o,blockCount:l,streamedBytes:c,resultTextBytes:Buffer.byteLength(f.text,"utf8"),lastChunkBytes:d,tailPreview:TH(f.text,200)}));let m=f.status==="stalled";return o?f.text.endsWith(`
2593
2593
  `)||t.stdout.write(`
2594
2594
  `):t.stdout.write(`${f.text}${f.text.endsWith(`
2595
2595
  `)?"":`
2596
2596
  `}`),f.status==="stalled"?1:0}catch(u){let f=u instanceof Error?u.message:String(u);return t.stderr.write(`error: ${f}
2597
- `),1}}function uk(e){return`${e}'s turn has finished and exited; resubmit \`lmctl chat\` to continue (no persistent session is left running)`}function EH(e){let t=[],n="yolo",r,s,i,o,a,l,c=!1,d=!1,u=!1;for(let h=0;h<e.length;h+=1){let g=e[h];if(g==="--permission-mode"){let y=e[++h];if(y===void 0||y.startsWith("--"))return"missing value for --permission-mode";if(y!=="plan"&&y!=="yolo")return`--permission-mode must be one of plan|yolo (got "${y}")`;n=y;continue}if(g==="--idle-timeout"){let y=e[++h];if(y===void 0||y.startsWith("--"))return"missing value for --idle-timeout";let E=mk(y);if(typeof E=="string")return E;r=E;continue}if(g==="--session"){let y=e[++h];if(y===void 0||y.startsWith("--"))return"missing value for --session";s=y;continue}if(g==="--provider"){let y=e[++h];if(y===void 0||y.startsWith("--"))return"missing value for --provider";i=y;continue}if(g==="--from"||g.startsWith("--from="))return tk("chat");if(g.startsWith("I_am="))return`unknown argument: ${g}`;if(g==="--root"){let y=e[++h];if(y===void 0||y.startsWith("--"))return"missing value for --root";o=y;continue}if(g==="--prompt-file"){let y=e[++h];if(y===void 0||y!=="-"&&y.startsWith("--"))return"missing value for --prompt-file";a=y;continue}if(g==="--force"||g.startsWith("--force="))return"unknown option --force (a dead holder auto-reclaims; for a live holder use lmctl chat)";if(g==="--json"){d=!0;continue}if(g==="--quiet"){u=!0;continue}if(g==="--run"){let y=e[++h];if(y===void 0||y.startsWith("--"))return"missing value for --run";l=y;continue}if(g==="--done"){c=!0;continue}if(g.startsWith("--"))return`unknown flag: ${g}`;t.push(g)}if(l!==void 0){if(s!==void 0)return"--run is mutually exclusive with --session";if(i!==void 0)return"--run is mutually exclusive with --provider";if(o!==void 0)return"--run is mutually exclusive with --root";if(a!==void 0&&t.length>0)return"--prompt-file is mutually exclusive with a positional answer; pass one or the other";if(a===void 0&&t.length===0)return"a prompt (answer) is required with --run";if(t.length>1)return`--run takes exactly one positional (the answer); got ${t.length}`;let h={prompt:a!==void 0?"":t[0],permissionMode:n,runFlag:l,done:c,json:d,quiet:u};return a!==void 0&&(h.promptFile=a),h}let f,m,p;if(a!==void 0){if(t.length===0){if(s===void 0)return"expected <teamfile>:<alias> --prompt-file <path> | <teamfile> <alias> --prompt-file <path> | --session <id> --prompt-file <path>"}else if(t.length===1)f=t[0];else if(t.length===2)f=t[0],m=t[1];else return"--prompt-file is mutually exclusive with a positional prompt; pass one or the other";p=""}else{if(t.length===0)return"a prompt is required";if(t.length===1){if(s===void 0)return'expected <teamfile>:<alias> "<prompt>" | <teamfile> <alias> "<prompt>" | <sessionid> "<prompt>" | --session <id> "<prompt>"';p=t[0]}else if(t.length===2)f=t[0],p=t[1];else if(t.length===3)f=t[0],m=t[1],p=t[2];else return`too many positionals (${t.length}); expected at most <teamfile> <alias> <prompt>`}if(c)return"--done requires --run";let _={prompt:p,permissionMode:n};return f!==void 0&&(_.target=f),m!==void 0&&(_.alias=m),r!==void 0&&(_.idleTimeoutMs=r),s!==void 0&&(_.sessionFlag=s),i!==void 0&&(_.providerFlag=i),o!==void 0&&(_.rootFlag=o),a!==void 0&&(_.promptFile=a),d&&(_.json=d),u&&(_.quiet=u),_}async function fk(e,t,n=process.stdin){let r;try{r=e==="-"?await wH(n):hH(e,"utf8")}catch(o){let a=o instanceof Error?o.message:String(o);return{error:`--prompt-file ${e}: ${a}`}}let s=r.endsWith(`\r
2597
+ `),1}}function uk(e){return`${e}'s turn has finished and exited; resubmit \`lmctl chat\` to continue (no persistent session is left running)`}function EH(e){let t=[],n="yolo",r,s,i,o,a,l,c=!1,d=!1,u=!1;for(let h=0;h<e.length;h+=1){let g=e[h];if(g==="--permission-mode"){let y=e[++h];if(y===void 0||y.startsWith("--"))return"missing value for --permission-mode";if(y!=="plan"&&y!=="yolo")return`--permission-mode must be one of plan|yolo (got "${y}")`;n=y;continue}if(g==="--idle-timeout"){let y=e[++h];if(y===void 0||y.startsWith("--"))return"missing value for --idle-timeout";let E=mk(y);if(typeof E=="string")return E;r=E;continue}if(g==="--session"){let y=e[++h];if(y===void 0||y.startsWith("--"))return"missing value for --session";s=y;continue}if(g==="--provider"){let y=e[++h];if(y===void 0||y.startsWith("--"))return"missing value for --provider";i=y;continue}if(g==="--from"||g.startsWith("--from="))return tk("chat");if(g.startsWith("I_am="))return`unknown argument: ${g}`;if(g==="--root"){let y=e[++h];if(y===void 0||y.startsWith("--"))return"missing value for --root";o=y;continue}if(g==="--prompt-file"){let y=e[++h];if(y===void 0||y!=="-"&&y.startsWith("--"))return"missing value for --prompt-file";a=y;continue}if(g==="--force"||g.startsWith("--force="))return"unknown option --force (a dead holder auto-reclaims; for a live holder use lmctl chat)";if(g==="--json"){d=!0;continue}if(g==="--verbose"){u=!0;continue}if(g==="--run"){let y=e[++h];if(y===void 0||y.startsWith("--"))return"missing value for --run";l=y;continue}if(g==="--done"){c=!0;continue}if(g.startsWith("--"))return`unknown flag: ${g}`;t.push(g)}if(l!==void 0){if(s!==void 0)return"--run is mutually exclusive with --session";if(i!==void 0)return"--run is mutually exclusive with --provider";if(o!==void 0)return"--run is mutually exclusive with --root";if(a!==void 0&&t.length>0)return"--prompt-file is mutually exclusive with a positional answer; pass one or the other";if(a===void 0&&t.length===0)return"a prompt (answer) is required with --run";if(t.length>1)return`--run takes exactly one positional (the answer); got ${t.length}`;let h={prompt:a!==void 0?"":t[0],permissionMode:n,runFlag:l,done:c,json:d,verbose:u};return a!==void 0&&(h.promptFile=a),h}let f,m,p;if(a!==void 0){if(t.length===0){if(s===void 0)return"expected <teamfile>:<alias> --prompt-file <path> | <teamfile> <alias> --prompt-file <path> | --session <id> --prompt-file <path>"}else if(t.length===1)f=t[0];else if(t.length===2)f=t[0],m=t[1];else return"--prompt-file is mutually exclusive with a positional prompt; pass one or the other";p=""}else{if(t.length===0)return"a prompt is required";if(t.length===1){if(s===void 0)return'expected <teamfile>:<alias> "<prompt>" | <teamfile> <alias> "<prompt>" | <sessionid> "<prompt>" | --session <id> "<prompt>"';p=t[0]}else if(t.length===2)f=t[0],p=t[1];else if(t.length===3)f=t[0],m=t[1],p=t[2];else return`too many positionals (${t.length}); expected at most <teamfile> <alias> <prompt>`}if(c)return"--done requires --run";let _={prompt:p,permissionMode:n};return f!==void 0&&(_.target=f),m!==void 0&&(_.alias=m),r!==void 0&&(_.idleTimeoutMs=r),s!==void 0&&(_.sessionFlag=s),i!==void 0&&(_.providerFlag=i),o!==void 0&&(_.rootFlag=o),a!==void 0&&(_.promptFile=a),d&&(_.json=d),u&&(_.verbose=u),_}async function fk(e,t,n=process.stdin){let r;try{r=e==="-"?await wH(n):hH(e,"utf8")}catch(o){let a=o instanceof Error?o.message:String(o);return{error:`--prompt-file ${e}: ${a}`}}let s=r.endsWith(`\r
2598
2598
  `)?r.slice(0,-2):r.endsWith(`
2599
2599
  `)?r.slice(0,-1):r;if(s.length===0)return{error:`--prompt-file ${e}: file is empty; a prompt is required`};let i=Buffer.byteLength(s,"utf8");return i>65536&&t.stderr.write(`warning: prompt is ${i} bytes, over the ${65536}-byte mailbox payload cap.
2600
2600
  It sends intact to an idle receiver, but if the receiver is BUSY the message is queued and
2601
2601
  the stored copy is truncated to the cap. Split it or wait for the receiver to be idle.
2602
- `),s}async function wH(e){let t=[];for await(let n of e)t.push(typeof n=="string"?Buffer.from(n,"utf8"):n);return Buffer.concat(t).toString("utf8")}function mk(e){if(e==="0")return 0;if(/^\d+$/.test(e))return Number(e);let t=/^(\d+)([smhd])$/.exec(e);if(t===null)return`invalid --idle-timeout "${e}" (expected <n>(s|m|h|d), integer ms, or 0)`;let n=Number(t[1]),r=t[2];return n*(r==="s"?1e3:r==="m"?6e4:r==="h"?36e5:864e5)}function pk(e,t,n,r=!1){if(n.kind!=="tool_use"&&n.kind!=="tool_result"&&n.kind!=="api_retry")return;let s=n.kind==="tool_use"?`[${t}] tool_use ${n.tool??"tool"}${n.summary?`: ${n.summary}`:""}`:n.kind==="tool_result"?`[${t}] tool_result${n.status?` ${n.status}`:""}${n.summary?`: ${n.summary}`:""}`:`[${t}] api_retry${n.summary?`: ${n.summary}`:""}`;$({event:"chat_progress",alias:t,progress_kind:n.kind,line:s}),r||e.stderr.write(`${s}
2602
+ `),s}async function wH(e){let t=[];for await(let n of e)t.push(typeof n=="string"?Buffer.from(n,"utf8"):n);return Buffer.concat(t).toString("utf8")}function mk(e){if(e==="0")return 0;if(/^\d+$/.test(e))return Number(e);let t=/^(\d+)([smhd])$/.exec(e);if(t===null)return`invalid --idle-timeout "${e}" (expected <n>(s|m|h|d), integer ms, or 0)`;let n=Number(t[1]),r=t[2];return n*(r==="s"?1e3:r==="m"?6e4:r==="h"?36e5:864e5)}function pk(e,t,n,r=!1){if(n.kind!=="tool_use"&&n.kind!=="tool_result"&&n.kind!=="api_retry")return;let s=n.kind==="tool_use"?`[${t}] tool_use ${n.tool??"tool"}${n.summary?`: ${n.summary}`:""}`:n.kind==="tool_result"?`[${t}] tool_result${n.status?` ${n.status}`:""}${n.summary?`: ${n.summary}`:""}`:`[${t}] api_retry${n.summary?`: ${n.summary}`:""}`;$({event:"chat_progress",alias:t,progress_kind:n.kind,line:s}),r&&e.stderr.write(`${s}
2603
2603
  `)}function TH(e,t){return e.slice(-t)}function vH(e,t,n=!1){t.kind==="delta"?e.stdout.write(t.chunk):t.kind==="progress"?pk(e,t.alias,t.event,n):e.stderr.write(t.message)}var gH,dk,hk=w(()=>{"use strict";vt();Yi();Le();rt();Lm();ki();ce();za();cn();gH={name:"chat",allowsBareTeamfile:!1,supportsRaw:!0},dk=`usage: lmctl chat <teamfile>:<alias> "<prompt>"
2604
2604
  lmctl chat <teamfile> <alias> "<prompt>"
2605
2605
  lmctl chat <sessionid> "<prompt>" --provider <name>
2606
2606
  lmctl chat --provider <name> --session <id> "<prompt>"
2607
2607
  lmctl chat --run <id> "<answer>" [--done]
2608
2608
  [--permission-mode plan|yolo] [--idle-timeout <duration>]
2609
- [--root <teamfile>] [--json] [--quiet]
2609
+ [--root <teamfile>] [--json] [--verbose]
2610
2610
 
2611
2611
  Safe input (no shell involved) \u2014 use for anything non-trivial:
2612
2612
  lmctl chat <teamfile>:<alias> --prompt-file <path>
@@ -2620,10 +2620,11 @@ Safe input (no shell involved) \u2014 use for anything non-trivial:
2620
2620
  Managed-team --json synchronous sends emit an early {"status":"accepted",
2621
2621
  "message_id":"msg_..."} line after durable creation, then a final result line
2622
2622
  with the same message_id. Busy and enqueued outcomes emit one line.
2623
- --quiet suppresses the live "[alias] tool_use/tool_result/api_retry"
2624
- progress narration on stderr (still recorded to ~/.lmctl/debug-*.log either
2625
- way) \u2014 useful when this chat call itself runs nested inside an already-
2626
- interactive session, e.g. a tool call issued from within \`lmctl terminal\`.
2623
+ --verbose prints the live "[alias] tool_use/tool_result/api_retry"
2624
+ progress narration on stderr (always recorded to ~/.lmctl/debug-*.log either
2625
+ way; off by default, since this chat call may run nested inside an already-
2626
+ interactive session, e.g. a tool call issued from within \`lmctl terminal\`,
2627
+ where unconditional narration would bleed into unrelated output).
2627
2628
 
2628
2629
  Send a prompt to a team member or raw provider session, or answer a paused run.`});function xi(e){for(let t=e.length-1;t>=0;t-=1){let n=e[t],r=bH.exec(n.content);if(r===null){if(n.role==="assistant"&&n.content.trim().length>0)return null;continue}let s=Number.parseInt(r[1],10),i=r[2]===void 0?0:Number.parseInt(r[2],10),o=r[3].toLowerCase(),a=r[4]?.trim()??null,l=`${r[1]}${r[2]!==void 0?`:${r[2]}`:""}${o}`;return{state:"LIMITED",resets_at:a===null?null:SH(n.timestamp,s,i,o,a),reset_time:l,timezone:a,detected_at:n.timestamp.toISOString()}}return null}function SH(e,t,n,r,s){if(!Number.isFinite(e.getTime())||t<1||t>12||n<0||n>59)return null;let i=kH(t,r);try{let o=IH(e,s),a=gk(o.year,o.month,o.day,i,n,s);if(a.getTime()<=e.getTime()){let l=RH(o,1);a=gk(l.year,l.month,l.day,i,n,s)}return a.toISOString()}catch{return null}}function kH(e,t){return t==="am"?e===12?0:e:e===12?12:e+12}function IH(e,t){let n=yk(t,!1).formatToParts(e);return{year:En(n,"year"),month:En(n,"month"),day:En(n,"day")}}function gk(e,t,n,r,s,i){let o=Date.UTC(e,t-1,n,r,s,0,0);for(let a=0;a<3;a+=1){let l=NH(new Date(o),i);o=Date.UTC(e,t-1,n,r,s,0,0)-l}return new Date(o)}function NH(e,t){let n=yk(t,!0).formatToParts(e);return Date.UTC(En(n,"year"),En(n,"month")-1,En(n,"day"),En(n,"hour"),En(n,"minute"),En(n,"second"),0)-e.getTime()}function yk(e,t){let n=t?AH:xH,r=n.get(e);if(r!==void 0)return r;let s=new Intl.DateTimeFormat("en-US",{timeZone:e,hourCycle:"h23",year:"numeric",month:"2-digit",day:"2-digit",...t?{hour:"2-digit",minute:"2-digit",second:"2-digit"}:{}});return n.set(e,s),s}function En(e,t){let n=e.find(r=>r.type===t)?.value;if(n===void 0)throw new Error(`missing ${t}`);return Number.parseInt(n,10)}function RH(e,t){let n=new Date(Date.UTC(e.year,e.month-1,e.day+t));return{year:n.getUTCFullYear(),month:n.getUTCMonth()+1,day:n.getUTCDate()}}var bH,xH,AH,Om=w(()=>{"use strict";bH=/you['\u2019]ve hit your session limit\s*(?:\u00b7|-|:)?\s*resets\s+([0-9]{1,2})(?::([0-9]{2}))?\s*(am|pm)\s*(?:\(([^)]+)\))?/i;xH=new Map,AH=new Map});var Tk={};me(Tk,{runRecover:()=>OH});import{dirname as Ek,resolve as wk}from"node:path";async function OH(e,t,n={}){if(e.includes("--help")||e.includes("-h"))return t.stdout.write(`${$m}
2629
2630
  `),0;let r=Y(e.filter(p=>p!=="--"),[],["--all","--dry-run","--json"]);if(r.error!==void 0)return I(t,`${r.error}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lmctl-ai/lmctl",
3
- "version": "0.1.259",
3
+ "version": "0.1.260",
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",