@lmctl-ai/lmctl 0.1.280 → 0.1.281
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
|
@@ -3077,7 +3077,7 @@ Show provider session details, team rollups, or managed run state/token totals.`
|
|
|
3077
3077
|
[--recursive] [--all] [--format table|teamfile|json] [--json]
|
|
3078
3078
|
lmctl ls --runs [--limit N] [--format table|json] [--json]
|
|
3079
3079
|
|
|
3080
|
-
List native provider sessions in scope, or list recent managed runs with --runs.`,g4=50,AN=500});import{existsSync as ds,readFileSync as rp}from"node:fs";import{homedir as ON}from"node:os";import{dirname as CN,resolve as Hn}from"node:path";import{fileURLToPath as S4}from"node:url";function sp(t,e={}){let n=[],r=k4(e.modelSelectionDocPath);for(let s of t){let i=s.provider.trim().toLowerCase();if(s.effort&&i!=="opencode"&&i!=="lmplayer"&&i!=="qwen"&&n.push(`[${s.alias}] effort="${s.effort}" is ignored: effort selection is only supported for opencode and lmplayer.`),i==="qwen"&&s.effort&&n.push(`[${s.alias}] effort="${s.effort}" is not a qwen CLI flag: Qwen Code does not expose reasoning-effort selection. Use a thinking/effort model id in model= instead.`),i==="copilot"){if(!s.model)continue;n.push(`[${s.alias}] model="${s.model}" is ignored: copilot does not support lmctl model selection.`);continue}if(i==="lmplayer"&&!s.model){n.push(`[${s.alias}] provider=lmplayer has no model= \u2014 lmplayer will choose its own default model, which may not be visible in the teamfile. Set model= explicitly (e.g. github-copilot/gpt-5.4).`);continue}if(i==="lmplayer")continue;if(i==="opencode"){if(s.effort&&!s.model&&n.push(`[${s.alias}] effort="${s.effort}" has no effect without model= on an opencode member.`),!s.model){n.push(`[${s.alias}] provider=opencode has no model= \u2014 opencode will choose its own default model, which may not be servable and isn't visible in the teamfile. Set model= explicitly (e.g. github-copilot/gpt-5.4).`);continue}let a=C4(e.opencodeConfigPath);if(!a.available){n.push(`[${s.alias}] model="${s.model}" cannot be verified for opencode: ${a.reason}.`);continue}if(a.models.includes(s.model)||/^github-copilot\/(gpt|gemini|o[0-9])/.test(s.model))continue;if(!s.model.includes("/")){let l=a.models.filter(c=>c.endsWith(`/${s.model}`));n.push(l.length>0?`[${s.alias}] model="${s.model}" has no provider prefix \u2014 opencode model ids are <provider>/<model>. Your opencode.json declares it as ${l.join(" / ")}; set model=${l[0]}.`:`[${s.alias}] model="${s.model}" has no provider prefix \u2014 opencode model ids are <provider>/<model> (e.g. github-copilot/${s.model}). Declare it in ~/.config/opencode/opencode.json (see https://lmctl.com/examples/opencode.json).`);continue}n.push(`[${s.alias}] model="${s.model}" is not declared in your opencode.json. opencode resolves github-copilot GPT/Gemini config-free, but copilot Claude and custom providers must be declared \u2014 copy https://lmctl.com/examples/opencode.json to ~/.config/opencode/opencode.json and adjust for your account.`);continue}if(i==="kimi"){if(!s.model)continue;let a=L4(e.kimiConfigPath);a.available?a.models.includes(s.model)||n.push(`[${s.alias}] model="${s.model}" is not declared in Kimi's [models] config. Valid configured models: ${tp(a.models)}`):n.push(`[${s.alias}] model="${s.model}" cannot be verified for kimi: ${a.reason}.`);continue}if(i==="dsh"){if(!s.model)continue;LN.includes(s.model)||n.push(`[${s.alias}] model="${s.model}" is not in dsh's built-in catalog. Valid models: ${tp(LN)}. The catalog is patchable via dsh profile overlays \u2014 a model added that way warns here even though it may resolve.`);continue}if(!s.model)continue;let o=r.get(i);if(!o){n.push(`[${s.alias}] model="${s.model}" cannot be verified for provider "${i}": `+(Ml??"no tested models found in durable-memory/model_selection.md"));continue}o.includes(s.model)||n.push(`[${s.alias}] model="${s.model}" is not in the tested model list for provider "${i}". Valid tested models: ${tp(o)}`)}return n}function k4(t){if(!t&&bi)return bi;let e=new Map,n,r=t??I4();if(!ds(r))return n=`${r} not found`,t||ep(e),t||(bi=e),t||(Ml=n),e;let s;try{s=rp(r,"utf-8")}catch(i){return n=`${r} could not be read: ${i instanceof Error?i.message:String(i)}`,t||ep(e),t||(bi=e),t||(Ml=n),e}for(let[i,o]of Object.entries(v4)){let a=x4(s,o),l=R4(a);l.length>0&&e.set(i,l)}return e.size===0&&(n=`${r} has no tested model rows`),!t&&e.size===0&&ep(e),t||(bi=e),t||(Ml=n),e}function I4(){return N4(CN(S4(import.meta.url)))}function N4(t){let e=A4(t);if(e){let r=Hn(e,"durable-memory","model_selection.md");if(ds(r))return r}let n=[Hn(t,"..","..","durable-memory","model_selection.md"),Hn(t,"..","..","..","durable-memory","model_selection.md")];for(let r of n)if(ds(r))return r;return n[n.length-1]}function A4(t){let e=Hn(t);for(;;){if(ds(Hn(e,"package.json")))return e;let n=CN(e);if(n===e)return null;e=n}}function ep(t){for(let[e,n]of Object.entries(b4))t.set(e,n)}function x4(t,e){let r=new RegExp(`^## ${M4(e)}\\s*$`,"m").exec(t);if(!r)return"";let s=r.index+r[0].length,i=t.slice(s),o=/^##\s+/m.exec(i);return o?i.slice(0,o.index):i}function R4(t){let e=new Set;for(let n of t.split(/\r?\n/)){let r=n.trim();if(!r.startsWith("| `"))continue;let s=/^\|\s*`([^`]+)`\s*\|/.exec(r);if(!s)continue;let i=s[1].trim();i&&i!=="Configured `model="&&e.add(i)}return[...e]}function L4(t){let e=process.env.KIMI_CODE_HOME||Hn(ON(),".kimi-code"),n=t??Hn(e,"config.toml");if(!ds(n))return{available:!1,models:[],reason:`${n} not found`};let r;try{r=rp(n,"utf-8")}catch(i){return{available:!1,models:[],reason:`${n} could not be read: ${i instanceof Error?i.message:String(i)}`}}let s=new Set;for(let i of r.split(/\r?\n/)){if(/^\s*\[/.test(i)&&!/^\s*\[\s*(.+?)\s*\]\s*(?:#.*)?$/.test(i))return{available:!1,models:[],reason:`${n} has an invalid TOML table header`};let o=/^\s*\[\s*(.+?)\s*\]\s*(?:#.*)?$/.exec(i);if(!o)continue;let a=O4(o[1]);if(o[1].trim().startsWith("models")&&a===null)return{available:!1,models:[],reason:`${n} has an invalid [models] table header`};a?.[0]==="models"&&a.length>=2&&s.add(a[1])}return s.size===0?{available:!1,models:[],reason:`${n} has no [models] entries`}:{available:!0,models:[...s].sort()}}function O4(t){let e=[],n=0;for(;n<t.length;){for(;/\s/.test(t[n]??"");)n++;if(n>=t.length)break;let r="",s=t[n]==='"'||t[n]==="'"?t[n++]:void 0;if(s){for(;n<t.length&&t[n]!==s;)s==='"'&&t[n]==="\\"&&n+1<t.length&&n++,r+=t[n++];if(t[n]!==s)return null;n++}else{for(;n<t.length&&t[n]!==".";)r+=t[n++];r=r.trim()}if(!r)return null;for(e.push(r);/\s/.test(t[n]??"");)n++;if(n>=t.length)break;if(t[n]!==".")return null;n++}return e.length>0?e:null}function C4(t){let e=t??Hn(ON(),".config","opencode","opencode.json");if(!ds(e))return{available:!0,models:[]};let n;try{n=JSON.parse(rp(e,"utf-8"))}catch(r){return{available:!1,models:[],reason:`${e} could not be parsed: ${r instanceof Error?r.message:String(r)}`}}return{available:!0,models:$4(n)}}function $4(t){if(!np(t))return[];let e=$l(t.provider)??$l(t.providers);if(!e)return[];let n=new Set;for(let[r,s]of Object.entries(e)){if(!np(s))continue;let i=$l(s.models)??$l(s.model);if(i)for(let o of Object.keys(i))n.add(o.startsWith(`${r}/`)?o:`${r}/${o}`)}return[...n].sort()}function $l(t){return np(t)?t:null}function np(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function tp(t){return t.length>0?t.join(", "):"(none)"}function M4(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var v4,LN,b4,bi,Ml,$N=E(()=>{"use strict";v4={claude:"Claude",codex:"Codex",gemini:"Gemini",qwen:"Qwen",agy:"Antigravity"},LN=["deepseek-v4-flash","deepseek-v4-pro","deepseek-v4-flash-vision-exp"],b4={claude:["claude-opus-4-6","claude-opus-4-7","claude-opus-4-8","claude-opus-5","claude-sonnet-4-6","claude-sonnet-5","claude-haiku-4-5","claude-fable-5"],codex:["gpt-5.2","gpt-5.4","gpt-5.5","gpt-5.6-sol","gpt-5.4-mini","gpt-5.3-codex","gpt-5.3-codex-spark"],gemini:["gemini-3.1-pro-preview","gemini-3-flash-preview","gemini-3.1-flash-lite-preview","gemini-2.5-flash","gemini-2.5-flash-lite"],qwen:["qwen3.5-plus","qwen3.6-plus"],agy:["Gemini 3.5 Flash (Medium)","Gemini 3.5 Flash (High)","Gemini 3.5 Flash (Low)","Gemini 3.1 Pro (Low)","Gemini 3.1 Pro (High)","Claude Sonnet 4.6 (Thinking)","Claude Opus 4.6 (Thinking)","GPT-OSS 120B (Medium)"]},bi=null});import{homedir as D4}from"node:os";import{basename as j4}from"node:path";function Dl(t,e){let n=new Set;return{text:t.replace(F4,(s,i)=>{let o=i.trim(),a=P4[o];return a===void 0?(n.add(o),s):a(e)}),unknownNames:[...n].sort()}}function jl(t){return{workdir:t.workdir,teamfile:t.teamfile,date:U4(t.date)}}function U4(t){return t.toISOString().slice(0,10)}var P4,F4,ip=E(()=>{"use strict";P4={workdir:t=>t.workdir,teamfile:t=>t.teamfile,teamname:t=>{let e=j4(t.teamfile);return e.endsWith(".lmctl")?e.slice(0,-6):e},home:()=>D4(),date:t=>t.date},F4=/{{\s*([A-Za-z0-9_-]+)\s*}}/g});var Ni={};ae(Ni,{GEMINI_PROVIDER_NOTICE:()=>PN,_setLintOpenCodeConfigProbeForTests:()=>V4,_setLintSessiondirFsOpsForTests:()=>K4,_setTeamfileSeedForTests:()=>G4,buildRootTeamRegistrationRow:()=>HN,registerRootTeam:()=>XN,runHire:()=>sK,runLint:()=>rK,runRefresh:()=>iK,runSeed:()=>qN,sha256Text:()=>BN});import{createHash as W4}from"node:crypto";import{accessSync as q4,constants as MN,existsSync as B4,readFileSync as Ul,realpathSync as lp,statSync as H4,writeFileSync as Fl}from"node:fs";import{dirname as Xn,resolve as jN}from"node:path";function G4(t){FN=t??(async e=>{let{seed:n}=await Promise.resolve().then(()=>(mt(),Hd)),r=await n(e);return r.success?{sessionId:r.sessionId,warnings:r.warnings}:{error:r.error??"provider seed failed"}})}function K4(t){_r=t===null?cp:{...cp,...t}}function V4(t){UN=t??Wc}async function Y4(t,e,n){let r=t.filter(i=>i.teamfile===void 0&&i.provider.trim().toLowerCase()==="opencode"&&i.model!==void 0&&i.model.length>0);return(await Promise.all(r.map(async i=>({member:i,result:await UN({cwd:i.sessiondir??e,model:i.model,...i.effort!==void 0?{effort:i.effort}:{},...n!==void 0?{env:n}:{}})})))).flatMap(({member:i,result:o})=>o.status==="rejected"?[`[${i.alias}] ${o.option}="${o.value}" rejected by opencode: ${o.error}`]:[])}function z4(t,e){let n=Xn(e),r=new Set,s=[];for(let i of t){if(i.teamfile!==void 0)continue;let o=i.sessiondir??n,a=jN(o);if(r.has(a))continue;let l=Z4(a);l!==void 0&&(r.add(a),s.push(`${i.alias}: sessiondir ${a} is not writable (seed would fail: ${l}) \u2014 fix permissions or set a writable sessiondir`))}return s}function Z4(t){try{if(_r.existsSync(t)){if(!_r.statSync(t).isDirectory())return"ENOTDIR";_r.accessSync(t,MN.W_OK);return}let e=tK(t);if(e===void 0)return;if(!_r.statSync(e).isDirectory())return"ENOTDIR";_r.accessSync(e,MN.W_OK);return}catch(e){return nK(e)??"permission check failed"}}function Q4(t,e){let n=[];for(let r of t)r.teamfile!==void 0||r.sessiondir===void 0||WN(r.sessiondir,e)&&n.push(`${r.alias}: sessiondir equals the teamfile directory and is redundant; lmctl seed will remove it`);return n}function eK(t,e,n,r){let s=!1;for(let i of t){if(i.teamfile!==void 0||i.sessiondir===void 0||!WN(i.sessiondir,r))continue;let o=n.get(i.alias.toLowerCase());if(o===void 0)continue;let a=JN(e[o],"sessiondir");a!==e[o]&&(e[o]=a,s=!0),i.sessiondir=void 0}return s}function WN(t,e){return DN(t)===DN(e)}function DN(t){let e=jN(t);try{return lp(e)}catch{return e}}function tK(t){let e=t;for(;;){try{if(_r.existsSync(e))return e}catch{return}let n=Xn(e);if(n===e)return;e=n}}function nK(t){if(typeof t=="object"&&t!==null&&"code"in t){let e=t.code;if(typeof e=="string"&&e.length>0)return e}}async function rK(t,e={stdout:process.stdout,stderr:process.stderr}){if(t[0]==="--help"||t[0]==="-h"||t[0]==="help")return e.stdout.write(X4),0;if(t.length!==1)return e.stderr.write(`usage: lmctl lint <teamfile.lmctl>
|
|
3080
|
+
List native provider sessions in scope, or list recent managed runs with --runs.`,g4=50,AN=500});import{existsSync as ds,readFileSync as rp}from"node:fs";import{homedir as ON}from"node:os";import{dirname as CN,resolve as Hn}from"node:path";import{fileURLToPath as S4}from"node:url";function sp(t,e={}){let n=[],r=k4(e.modelSelectionDocPath);for(let s of t){let i=s.provider.trim().toLowerCase();if(s.effort&&i!=="opencode"&&i!=="lmplayer"&&i!=="qwen"&&n.push(`[${s.alias}] effort="${s.effort}" is ignored: effort selection is only supported for opencode and lmplayer.`),i==="qwen"&&s.effort&&n.push(`[${s.alias}] effort="${s.effort}" is not a qwen CLI flag: Qwen Code does not expose reasoning-effort selection. Use a thinking/effort model id in model= instead.`),i==="copilot"){if(!s.model)continue;n.push(`[${s.alias}] model="${s.model}" is ignored: copilot does not support lmctl model selection.`);continue}if(i==="lmplayer"&&!s.model){n.push(`[${s.alias}] provider=lmplayer has no model= \u2014 lmplayer will choose its own default model, which may not be visible in the teamfile. Set model= explicitly (e.g. github-copilot/gpt-5.4).`);continue}if(i==="lmplayer")continue;if(i==="opencode"){if(s.effort&&!s.model&&n.push(`[${s.alias}] effort="${s.effort}" has no effect without model= on an opencode member.`),!s.model){n.push(`[${s.alias}] provider=opencode has no model= \u2014 opencode will choose its own default model, which may not be servable and isn't visible in the teamfile. Set model= explicitly (e.g. github-copilot/gpt-5.4).`);continue}let a=C4(e.opencodeConfigPath);if(!a.available){n.push(`[${s.alias}] model="${s.model}" cannot be verified for opencode: ${a.reason}.`);continue}if(a.models.includes(s.model)||/^github-copilot\/(gpt|gemini|o[0-9])/.test(s.model))continue;if(!s.model.includes("/")){let l=a.models.filter(c=>c.endsWith(`/${s.model}`));n.push(l.length>0?`[${s.alias}] model="${s.model}" has no provider prefix \u2014 opencode model ids are <provider>/<model>. Your opencode.json declares it as ${l.join(" / ")}; set model=${l[0]}.`:`[${s.alias}] model="${s.model}" has no provider prefix \u2014 opencode model ids are <provider>/<model> (e.g. github-copilot/${s.model}). Declare it in ~/.config/opencode/opencode.json (see https://lmctl.com/examples/opencode.json).`);continue}n.push(`[${s.alias}] model="${s.model}" is not declared in your opencode.json. opencode resolves github-copilot GPT/Gemini config-free, but copilot Claude and custom providers must be declared \u2014 copy https://lmctl.com/examples/opencode.json to ~/.config/opencode/opencode.json and adjust for your account.`);continue}if(i==="kimi"){if(!s.model)continue;let a=L4(e.kimiConfigPath);a.available?a.models.includes(s.model)||n.push(`[${s.alias}] model="${s.model}" is not declared in Kimi's [models] config. Valid configured models: ${tp(a.models)}`):n.push(`[${s.alias}] model="${s.model}" cannot be verified for kimi: ${a.reason}.`);continue}if(i==="dsh"){if(!s.model)continue;LN.includes(s.model)||n.push(`[${s.alias}] model="${s.model}" is not in dsh's built-in catalog. Valid models: ${tp(LN)}. The catalog is patchable via dsh profile overlays \u2014 a model added that way warns here even though it may resolve.`);continue}if(!s.model)continue;let o=r.get(i);if(!o){n.push(`[${s.alias}] model="${s.model}" cannot be verified for provider "${i}": `+(Ml??"no tested models found in durable-memory/model_selection.md"));continue}o.includes(s.model)||n.push(`[${s.alias}] model="${s.model}" is not in the tested model list for provider "${i}". Valid tested models: ${tp(o)}`)}return n}function k4(t){if(!t&&bi)return bi;let e=new Map,n,r=t??I4();if(!ds(r))return n=`${r} not found`,t||ep(e),t||(bi=e),t||(Ml=n),e;let s;try{s=rp(r,"utf-8")}catch(i){return n=`${r} could not be read: ${i instanceof Error?i.message:String(i)}`,t||ep(e),t||(bi=e),t||(Ml=n),e}for(let[i,o]of Object.entries(v4)){let a=x4(s,o),l=R4(a);l.length>0&&e.set(i,l)}return e.size===0&&(n=`${r} has no tested model rows`),!t&&e.size===0&&ep(e),t||(bi=e),t||(Ml=n),e}function I4(){return N4(CN(S4(import.meta.url)))}function N4(t){let e=A4(t);if(e){let r=Hn(e,"durable-memory","model_selection.md");if(ds(r))return r}let n=[Hn(t,"..","..","durable-memory","model_selection.md"),Hn(t,"..","..","..","durable-memory","model_selection.md")];for(let r of n)if(ds(r))return r;return n[n.length-1]}function A4(t){let e=Hn(t);for(;;){if(ds(Hn(e,"package.json")))return e;let n=CN(e);if(n===e)return null;e=n}}function ep(t){for(let[e,n]of Object.entries(b4))t.set(e,n)}function x4(t,e){let r=new RegExp(`^## ${M4(e)}\\s*$`,"m").exec(t);if(!r)return"";let s=r.index+r[0].length,i=t.slice(s),o=/^##\s+/m.exec(i);return o?i.slice(0,o.index):i}function R4(t){let e=new Set;for(let n of t.split(/\r?\n/)){let r=n.trim();if(!r.startsWith("| `"))continue;let s=/^\|\s*`([^`]+)`\s*\|/.exec(r);if(!s)continue;let i=s[1].trim();i&&i!=="Configured `model="&&e.add(i)}return[...e]}function L4(t){let e=process.env.KIMI_CODE_HOME||Hn(ON(),".kimi-code"),n=t??Hn(e,"config.toml");if(!ds(n))return{available:!1,models:[],reason:`${n} not found`};let r;try{r=rp(n,"utf-8")}catch(i){return{available:!1,models:[],reason:`${n} could not be read: ${i instanceof Error?i.message:String(i)}`}}let s=new Set;for(let i of r.split(/\r?\n/)){if(/^\s*\[/.test(i)&&!/^\s*\[\s*(.+?)\s*\]\s*(?:#.*)?$/.test(i))return{available:!1,models:[],reason:`${n} has an invalid TOML table header`};let o=/^\s*\[\s*(.+?)\s*\]\s*(?:#.*)?$/.exec(i);if(!o)continue;let a=O4(o[1]);if(o[1].trim().startsWith("models")&&a===null)return{available:!1,models:[],reason:`${n} has an invalid [models] table header`};a?.[0]==="models"&&a.length>=2&&s.add(a[1])}return s.size===0?{available:!1,models:[],reason:`${n} has no [models] entries`}:{available:!0,models:[...s].sort()}}function O4(t){let e=[],n=0;for(;n<t.length;){for(;/\s/.test(t[n]??"");)n++;if(n>=t.length)break;let r="",s=t[n]==='"'||t[n]==="'"?t[n++]:void 0;if(s){for(;n<t.length&&t[n]!==s;)s==='"'&&t[n]==="\\"&&n+1<t.length&&n++,r+=t[n++];if(t[n]!==s)return null;n++}else{for(;n<t.length&&t[n]!==".";)r+=t[n++];r=r.trim()}if(!r)return null;for(e.push(r);/\s/.test(t[n]??"");)n++;if(n>=t.length)break;if(t[n]!==".")return null;n++}return e.length>0?e:null}function C4(t){let e=t??Hn(ON(),".config","opencode","opencode.json");if(!ds(e))return{available:!0,models:[]};let n;try{n=JSON.parse(rp(e,"utf-8"))}catch(r){return{available:!1,models:[],reason:`${e} could not be parsed: ${r instanceof Error?r.message:String(r)}`}}return{available:!0,models:$4(n)}}function $4(t){if(!np(t))return[];let e=$l(t.provider)??$l(t.providers);if(!e)return[];let n=new Set;for(let[r,s]of Object.entries(e)){if(!np(s))continue;let i=$l(s.models)??$l(s.model);if(i)for(let o of Object.keys(i))n.add(o.startsWith(`${r}/`)?o:`${r}/${o}`)}return[...n].sort()}function $l(t){return np(t)?t:null}function np(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function tp(t){return t.length>0?t.join(", "):"(none)"}function M4(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var v4,LN,b4,bi,Ml,$N=E(()=>{"use strict";v4={claude:"Claude",codex:"Codex",gemini:"Gemini",qwen:"Qwen",agy:"Antigravity"},LN=["deepseek-v4-flash","deepseek-v4-pro","deepseek-v4-flash-vision-exp"],b4={claude:["claude-opus-4-6","claude-opus-4-7","claude-opus-4-8","claude-opus-5","claude-sonnet-4-6","claude-sonnet-5","claude-haiku-4-5","claude-fable-5","claude-fable-5-1"],codex:["gpt-5.2","gpt-5.4","gpt-5.5","gpt-5.6-sol","gpt-5.4-mini","gpt-5.3-codex","gpt-5.3-codex-spark"],gemini:["gemini-3.1-pro-preview","gemini-3-flash-preview","gemini-3.1-flash-lite-preview","gemini-2.5-flash","gemini-2.5-flash-lite"],qwen:["qwen3.5-plus","qwen3.6-plus"],agy:["Gemini 3.5 Flash (Medium)","Gemini 3.5 Flash (High)","Gemini 3.5 Flash (Low)","Gemini 3.1 Pro (Low)","Gemini 3.1 Pro (High)","Claude Sonnet 4.6 (Thinking)","Claude Opus 4.6 (Thinking)","GPT-OSS 120B (Medium)"]},bi=null});import{homedir as D4}from"node:os";import{basename as j4}from"node:path";function Dl(t,e){let n=new Set;return{text:t.replace(F4,(s,i)=>{let o=i.trim(),a=P4[o];return a===void 0?(n.add(o),s):a(e)}),unknownNames:[...n].sort()}}function jl(t){return{workdir:t.workdir,teamfile:t.teamfile,date:U4(t.date)}}function U4(t){return t.toISOString().slice(0,10)}var P4,F4,ip=E(()=>{"use strict";P4={workdir:t=>t.workdir,teamfile:t=>t.teamfile,teamname:t=>{let e=j4(t.teamfile);return e.endsWith(".lmctl")?e.slice(0,-6):e},home:()=>D4(),date:t=>t.date},F4=/{{\s*([A-Za-z0-9_-]+)\s*}}/g});var Ni={};ae(Ni,{GEMINI_PROVIDER_NOTICE:()=>PN,_setLintOpenCodeConfigProbeForTests:()=>V4,_setLintSessiondirFsOpsForTests:()=>K4,_setTeamfileSeedForTests:()=>G4,buildRootTeamRegistrationRow:()=>HN,registerRootTeam:()=>XN,runHire:()=>sK,runLint:()=>rK,runRefresh:()=>iK,runSeed:()=>qN,sha256Text:()=>BN});import{createHash as W4}from"node:crypto";import{accessSync as q4,constants as MN,existsSync as B4,readFileSync as Ul,realpathSync as lp,statSync as H4,writeFileSync as Fl}from"node:fs";import{dirname as Xn,resolve as jN}from"node:path";function G4(t){FN=t??(async e=>{let{seed:n}=await Promise.resolve().then(()=>(mt(),Hd)),r=await n(e);return r.success?{sessionId:r.sessionId,warnings:r.warnings}:{error:r.error??"provider seed failed"}})}function K4(t){_r=t===null?cp:{...cp,...t}}function V4(t){UN=t??Wc}async function Y4(t,e,n){let r=t.filter(i=>i.teamfile===void 0&&i.provider.trim().toLowerCase()==="opencode"&&i.model!==void 0&&i.model.length>0);return(await Promise.all(r.map(async i=>({member:i,result:await UN({cwd:i.sessiondir??e,model:i.model,...i.effort!==void 0?{effort:i.effort}:{},...n!==void 0?{env:n}:{}})})))).flatMap(({member:i,result:o})=>o.status==="rejected"?[`[${i.alias}] ${o.option}="${o.value}" rejected by opencode: ${o.error}`]:[])}function z4(t,e){let n=Xn(e),r=new Set,s=[];for(let i of t){if(i.teamfile!==void 0)continue;let o=i.sessiondir??n,a=jN(o);if(r.has(a))continue;let l=Z4(a);l!==void 0&&(r.add(a),s.push(`${i.alias}: sessiondir ${a} is not writable (seed would fail: ${l}) \u2014 fix permissions or set a writable sessiondir`))}return s}function Z4(t){try{if(_r.existsSync(t)){if(!_r.statSync(t).isDirectory())return"ENOTDIR";_r.accessSync(t,MN.W_OK);return}let e=tK(t);if(e===void 0)return;if(!_r.statSync(e).isDirectory())return"ENOTDIR";_r.accessSync(e,MN.W_OK);return}catch(e){return nK(e)??"permission check failed"}}function Q4(t,e){let n=[];for(let r of t)r.teamfile!==void 0||r.sessiondir===void 0||WN(r.sessiondir,e)&&n.push(`${r.alias}: sessiondir equals the teamfile directory and is redundant; lmctl seed will remove it`);return n}function eK(t,e,n,r){let s=!1;for(let i of t){if(i.teamfile!==void 0||i.sessiondir===void 0||!WN(i.sessiondir,r))continue;let o=n.get(i.alias.toLowerCase());if(o===void 0)continue;let a=JN(e[o],"sessiondir");a!==e[o]&&(e[o]=a,s=!0),i.sessiondir=void 0}return s}function WN(t,e){return DN(t)===DN(e)}function DN(t){let e=jN(t);try{return lp(e)}catch{return e}}function tK(t){let e=t;for(;;){try{if(_r.existsSync(e))return e}catch{return}let n=Xn(e);if(n===e)return;e=n}}function nK(t){if(typeof t=="object"&&t!==null&&"code"in t){let e=t.code;if(typeof e=="string"&&e.length>0)return e}}async function rK(t,e={stdout:process.stdout,stderr:process.stderr}){if(t[0]==="--help"||t[0]==="-h"||t[0]==="help")return e.stdout.write(X4),0;if(t.length!==1)return e.stderr.write(`usage: lmctl lint <teamfile.lmctl>
|
|
3081
3081
|
`),2;let n=t[0],r;try{r=await O(e,c=>Te(n,c))}catch(c){return Fe(e,`${n}: ${c instanceof Error?c.message:String(c)}`)}let s;try{s=je(r)}catch(c){return Fe(e,`${n}: ${c instanceof Error?c.message:String(c)}`)}let i=Vf(s,Xn(r)),o=sp(s.members),a=Ul(r,"utf8"),l=Dl(a,jl({workdir:Xn(r),teamfile:r,date:new Date})).unknownNames;l.length>0&&o.push(`unknown template placeholder${l.length===1?"":"s"}: ${l.map(c=>`{{${c}}}`).join(", ")}`),o.push(...jc(s.members,Xn(r))),o.push(...z4(s.members,r)),o.push(...Q4(s.members,Xn(r))),o.push(...await Y4(s.members,Xn(r),e.env));for(let c of i)e.stderr.write(`error: ${c.field}: ${c.message}
|
|
3082
3082
|
`);for(let c of s.members)up([c],e),c.session!==void 0&&c.session.length<ki&&o.push(`${c.alias}: sessionid is shorter than ${ki} chars; run lmctl seed to refresh it`);for(let c of o)e.stderr.write(`warning: ${c}
|
|
3083
3083
|
`);return i.length>0?1:(e.stdout.write(`ok
|
|
@@ -44,6 +44,7 @@ or retiring tested model ids.
|
|
|
44
44
|
| `claude-sonnet-5` | Operator-confirmed 2026-07-05 (via GitHub Copilot: `opencode --model github-copilot/claude-sonnet-5 run …` → "build · claude-sonnet-5"). Also a valid native Claude Code model id (`claude --model claude-sonnet-5`). |
|
|
45
45
|
| `claude-haiku-4-5` | Ported from lmctl0 tested-model catalog. |
|
|
46
46
|
| `claude-fable-5` | Session observed locally via `lmctl0 ls` on 2026-06-11; `lmctl lint` compatibility smoke accepts it. Anthropic announced on 2026-06-12 that access to Fable 5 was suspended for customers; keep the id valid for existing teamfiles, but do not use it for new work while unavailable. |
|
|
47
|
+
| `claude-fable-5-1` | Fable 5.1, math.lmctl's designated review model as of 2026-09-02; requested addition to the lint tested-model catalog to silence the "not in the tested model list" warning on seed. |
|
|
47
48
|
|
|
48
49
|
## Codex
|
|
49
50
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmctl-ai/lmctl",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.281",
|
|
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",
|