@lmctl-ai/lmctl 0.2.62 → 0.2.63
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/CHANGELOG.md +3 -0
- package/README.md +4 -0
- package/build-info.json +1 -1
- package/dist/cli/index.js +12 -9
- package/dist/cli/lmscript.js +228 -228
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,9 @@ All notable public-preview changes for `@lmctl-ai/lmctl` are recorded here.
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
- **Breaking: explicit properties replace implicit profile globals.** init.toml keeps its name and stores lmctl properties. Provider1..3 become PROPS.Provider1..3.Provider; Model1/2/3 become PROPS.Provider1/2/3.Model1. Directory/NonInteractive remain invocation facts. PROPS is a strict read-only hierarchical map, with dotted-key indexing; get_property/has_property/get_properties/set_property use plain values and run-local copies/overlays. Checks are profile-free with known-key suggestions; reads load the profile lazily. Nested ARGV now contains only the child arguments, matching top-level ARGV (no filename). Bare variables, ARGV, PROPS and env() are separate access forms; f-string expressions stay general.
|
|
8
|
+
|
|
9
|
+
|
|
7
10
|
- **Workspace interpreter containment.** Script routes use only the declared monorepo sibling and report a missing build instead of silently running a retired checkout. Fresh clones bootstrap with `npm ci --ignore-scripts && npm run build` at the root; the ordered build now smoke-tests the script route.
|
|
8
11
|
|
|
9
12
|
- **Gate fixes: script ABI restored.** lm_members and lm_session_list return plain arrays; lm_member returns a map-or-null; prompt reads return arrays; batch open/close use managed handles/booleans. Seed/lint/turn results retain legacy projections and snake-case prompt IDs. Neutral API envelopes remain internal, and operational failures name the script call.
|
package/README.md
CHANGED
|
@@ -131,3 +131,7 @@ LMCTL_DB="$test_root/state.db" MINIPLAYER_HOME="$test_root/miniplayer" \
|
|
|
131
131
|
`LMCTL_DB` overrides lmctl's default SQLite database; an explicit `--db PATH`
|
|
132
132
|
takes precedence. The integration tests also isolate `LMCTL_HOME` and native
|
|
133
133
|
provider storage. Mock responses need no keys or network access.
|
|
134
|
+
|
|
135
|
+
### lmctl properties (init.toml)
|
|
136
|
+
|
|
137
|
+
`~/.lmctl/init.toml` (or `$LMCTL_HOME/init.toml`) is lmctl's properties file, not the process environment. Managed TOML keys include `Provider1.provider` and `Provider1.model1`; top-level user keys such as `Env1` are supported. Scripts use `PROPS.Provider1.Provider`, `PROPS.Provider1.Model1` or `PROPS["Provider1.Model1"]`. The source repository documents the complete property contract. The six old bare provider/model globals are removed. `--check` uses declared keys without a profile or DB; a file-backed runtime read needs a valid profile and reports its path plus `lmctl init` guidance. `Directory` and `NonInteractive` remain core invocation facts.
|
package/build-info.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"sha": "
|
|
1
|
+
{"sha": "73bf5b850295a40b8dd26f20f3488cc3e637c7a5", "dirty": true, "builtAt": "2026-10-05T06:39:45.000Z"}
|
package/dist/cli/index.js
CHANGED
|
@@ -1755,13 +1755,14 @@ ${o}`,r),this.line=n,this.column=s,this.codeblock=o}static x(e,r,n){throw new t(
|
|
|
1755
1755
|
`;)r++;continue}let s=r;if(n==='"'||n==="'"){let o=t.startsWith(n.repeat(3),r);r+=o?3:1;let i=!1;for(;r<t.length;){if(n==='"'&&t[r]==="\\"){r+=2;continue}if(t[r]===n){if(!o){r++,i=!0;break}if(t.startsWith(n.repeat(3),r)){for(;t[r]===n;)r++;i=!0;break}}r++}if(!i)throw new Error("cannot locate string boundary");e.push({start:s,end:r,text:t.slice(s,r),kind:"string",multiline:o});continue}if("[]=.{},".includes(n)){r++,e.push({start:s,end:r,text:n,kind:"symbol"});continue}for(;r<t.length&&!/\s/.test(t[r])&&!`"'#[]=.{},`.includes(t[r]);)r++;if(r===s)throw new Error("cannot locate token");e.push({start:s,end:r,text:t.slice(s,r),kind:"word"})}return e}function lC(t){let e=xn(t+" = 0"),r=[];for(;e&&typeof e=="object"&&!Array.isArray(e);){let n=Object.entries(e);if(n.length!==1)throw new Error("ambiguous key");r.push(n[0][0]),e=n[0][1]}return r}function cC(t){let e=xn(t+`
|
|
1756
1756
|
__init_edit_marker__ = 0`),r=[];for(;e&&typeof e=="object"&&!Array.isArray(e);){let n=Object.entries(e);if(n.length!==1)return[];if(n[0][0]==="__init_edit_marker__")return r;r.push(n[0][0]),e=n[0][1]}return[]}function Nu(t){return'"'+Array.from(t).map(e=>{let r=e.codePointAt(0);if(r>=55296&&r<=57343)throw new Error("managed string contains an invalid Unicode scalar");return e==='"'?'\\"':e==="\\"?"\\\\":r<32||r===127?"\\u"+r.toString(16).padStart(4,"0"):e}).join("")+'"'}function $T(t,e,r=[]){if(r.length===2&&zs.includes(r[0])&&Qs.includes(r[1])||Object.is(t,e))return!0;if(t instanceof Date||e instanceof Date)return t instanceof Date&&e instanceof Date&&t.toISOString()===e.toISOString();if(!t||!e||typeof t!="object"||typeof e!="object"||Array.isArray(t)!==Array.isArray(e))return!1;let n=Object.keys(t),s=Object.keys(e);return n.length!==s.length||n.some(o=>!Object.hasOwn(e,o))?!1:n.every(o=>$T(t[o],e[o],[...r,o]))}function PT(t,e){try{let r=Xt(t),n=[];for(let u of zs)for(let m of Qs){let f=r.config[u.toLowerCase()][m],_=e[u.toLowerCase()][m];f!==_&&n.push({section:u,key:m,oldValue:f,newValue:_,line:1})}if(!n.length)return{ok:!0,text:t,changes:n};let s=new Map,o=aC(t),i=0,a=[];for(;i<o.length;){if(o[i].kind==="newline"){i++;continue}let u=i;if(o[i].text==="["){for(;i<o.length&&o[i].kind!=="newline";)i++;a=cC(t.slice(o[u].start,o[i-1].end));continue}for(;i<o.length&&o[i].text!=="=";)i++;if(i===o.length)throw new Error("cannot locate assignment");let m=lC(t.slice(o[u].start,o[i-1].end));i++;let f=i,_=0;for(;i<o.length;){let g=o[i];if(g.kind==="newline"&&_===0)break;g.kind==="symbol"&&((g.text==="["||g.text==="{")&&_++,(g.text==="]"||g.text==="}")&&_--),i++}if(a.length===1&&m.length===1&&i-f===1){let g=o[f];g.kind==="string"&&!g.multiline&&s.set(a[0]+"."+m[0],g)}}let l=n.map(u=>{let m=s.get(u.section+"."+u.key);if(!m)throw new Error("cannot edit "+u.section+"."+u.key+" in place (multiline, dotted or inline managed layout); edit by hand");return u.line=t.slice(0,m.start).split(/\r\n|\r|\n/).length,{start:m.start,end:m.end,text:Nu(u.newValue)}}).sort((u,m)=>m.start-u.start),c=t;for(let u of l)c=c.slice(0,u.start)+u.text+c.slice(u.end);let d=Xt(c);for(let u of zs)for(let m of Qs)if(d.config[u.toLowerCase()][m]!==e[u.toLowerCase()][m])throw new Error("managed-value verification failed");if(!$T(r.document,d.document))throw new Error("unmanaged semantic verification failed");return{ok:!0,text:c,changes:n}}catch(r){return{ok:!1,error:r.message,line:r.line}}}var FT=k(()=>{"use strict";Au();ya()});import{existsSync as dC,mkdirSync as IJ,readdirSync as uC,writeFileSync as bJ}from"node:fs";import{homedir as fC}from"node:os";import{dirname as NJ,join as Cn}from"node:path";function Ru(t){let e=UT[t]??UT.claude;return{provider:t,model1:e[0],model2:e[1],model3:e[2]}}function jT(t){let e=t.filter((i,a)=>t.indexOf(i)===a),r=e.length>0?e:["claude"],[n,s=n,o=n]=r;return{provider1:Ru(n),provider2:Ru(s),provider3:Ru(o)}}function eo(t){try{return dC(t)&&uC(t).length>0}catch{return!1}}function WT(){let t=fC(),e=process.env.KIMI_CODE_HOME??Cn(t,".kimi-code"),r=[];return eo(Cn(t,".claude","projects"))&&r.push("claude"),(eo(Cn(t,".codex","sessions"))||eo(Cn(t,".code","sessions")))&&r.push("codex"),eo(Cn(t,".gemini","antigravity-cli","conversations"))&&r.push("agy"),eo(Cn(e,"sessions"))&&r.push("kimi"),r}function wa(t){return Nu(t)}function to(t){let e=(r,n)=>[`[${r}]`,`provider = ${wa(n.provider)}`,`model1 = ${wa(n.model1)}`,`model2 = ${wa(n.model2)}`,`model3 = ${wa(n.model3)}`].join(`
|
|
1757
1757
|
`);return`# Generated by \`lmctl init\`. This is a STARTING POINT, not a fixed answer --
|
|
1758
|
-
#
|
|
1758
|
+
# lmctl properties: hierarchical keys such as Provider1.provider, Provider1.model1,
|
|
1759
|
+
# and user-defined top-level Env1. edit any value below to change what \`lmctl plan\`/\`lmctl quickrun\` resolve to.
|
|
1759
1760
|
#
|
|
1760
1761
|
# Provider1/Provider2/Provider3 are SLOTS, not a ranking: a .lmctl template
|
|
1761
1762
|
# published on lmctl.com writes \${Provider1}/\${Model1}, so the same template
|
|
1762
1763
|
# works whether you have one provider or three -- with only one, all three
|
|
1763
|
-
# slots just point at it. lmscript
|
|
1764
|
-
# Provider1
|
|
1764
|
+
# slots just point at it. lmscript reads PROPS.Provider1.Provider and
|
|
1765
|
+
# PROPS.Provider1.Model1 (managed lowercase TOML fields projected as property paths).
|
|
1765
1766
|
#
|
|
1766
1767
|
# model1 is the slot's active/top-tier model; model2 and model3 are lighter
|
|
1767
1768
|
# alternatives for the SAME provider. Promote one to model1 to make it the
|
|
@@ -2218,7 +2219,7 @@ ${Af}
|
|
|
2218
2219
|
This is a starting point, not a fixed answer -- edit provider/model1/model2/model3 above before running lmctl plan or lmctl quickrun if it is not right.
|
|
2219
2220
|
`),e.stdout.write(`${Af}
|
|
2220
2221
|
`),l(),0}catch(i){return e.stderr.write("error: cannot update "+o+": "+(i instanceof Error?i.message:String(i))+`
|
|
2221
|
-
`),1}}var Af,oM,Cw=k(()=>{"use strict";Lw();qr();Af="These are
|
|
2222
|
+
`),1}}var Af,oM,Cw=k(()=>{"use strict";Lw();qr();Af="These are lmctl properties: lmscript reads PROPS.Provider1.Provider and PROPS.Provider1.Model1; legacy plan/quickrun templates use them as ${Provider1}/${Model1}.",oM=`usage: lmctl init [--force]
|
|
2222
2223
|
|
|
2223
2224
|
Writes ~/.lmctl/init.toml if it does not exist: three provider slots
|
|
2224
2225
|
(Provider1/2/3), each resolved to a provider and a starting model,
|
|
@@ -2235,8 +2236,9 @@ old -> new. If nothing would change, the file is not rewritten. A file
|
|
|
2235
2236
|
whose whole document is invalid TOML or whose managed slot schema is invalid is reported with its line number and left
|
|
2236
2237
|
byte-identical.
|
|
2237
2238
|
|
|
2238
|
-
The
|
|
2239
|
-
Provider1
|
|
2239
|
+
The file contains lmctl properties: hierarchical keys Provider1.provider,
|
|
2240
|
+
Provider1.model1, and user-defined top-level keys such as Env1. Scripts read
|
|
2241
|
+
PROPS.Provider1.Provider and PROPS.Provider1.Model1. Plan and quickrun read this
|
|
2240
2242
|
file so a published .lmctl template's \${Provider1}/\${Model1}-style
|
|
2241
2243
|
placeholders resolve without asking you provider/model questions
|
|
2242
2244
|
directly.
|
|
@@ -2306,9 +2308,10 @@ it is expected.
|
|
|
2306
2308
|
List current samples from lmctl.com/quickrun/index.txt, or fetch and execute
|
|
2307
2309
|
one. Example: lmctl quickrun solo
|
|
2308
2310
|
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2311
|
+
init.toml contains lmctl properties. Scripts lazily read PROPS.Provider1.Provider
|
|
2312
|
+
and PROPS.Provider1.Model1; checks use passive keys without opening the profile.
|
|
2313
|
+
Directory and NonInteractive are invocation facts, and ARGV holds script arguments.
|
|
2314
|
+
Samples can be added
|
|
2312
2315
|
to the website without a CLI release.
|
|
2313
2316
|
Bare names always select hosted samples; use ./paths for local scripts or directories.
|
|
2314
2317
|
Explicit URLs are also accepted. Only run scripts you trust.
|