@lmctl-ai/lmctl 0.2.4 → 0.2.6
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 +382 -380
- package/dist/cli/script.js +326 -318
- package/dist/providers/config/model-selection-lint.d.ts +4 -2
- package/dist/script/lmscript.d.ts +33 -3
- package/durable-memory/model_selection.md +14 -9
- package/package.json +1 -1
|
@@ -36,8 +36,10 @@ export declare function modelSelectionWarnings(members: MemberConfig[], opts?: {
|
|
|
36
36
|
* - unresolved -> silent (deliberate non-binding in lmprice's alias
|
|
37
37
|
* table, not lint's claim to second-guess)
|
|
38
38
|
* - no-catalog / catalog unavailable -> skip silently
|
|
39
|
-
* The returned warnings wire into lint/seed's standard warnings array
|
|
40
|
-
*
|
|
39
|
+
* The returned warnings wire into lint/seed's standard warnings array
|
|
40
|
+
* (operator ruling, 2026-09-29: lint has exactly two outcomes, ok/warning --
|
|
41
|
+
* never an error, and the `--strict` flag that used to promote warnings to
|
|
42
|
+
* a failing exit code has been removed entirely).
|
|
41
43
|
*/
|
|
42
44
|
export declare function catalogModelWarnings(members: MemberConfig[], opts?: {
|
|
43
45
|
snapshot?: CatalogSnapshot;
|
|
@@ -6,13 +6,19 @@
|
|
|
6
6
|
* 2. Scan all and check before execution: In-memory AST validation upfront. Zero intermediate files generated.
|
|
7
7
|
* 3. Language features: Top-level functions, flow control (if/else, while, for, break, continue, return), tuple & destructuring assignment: (a, b) = [1, 2], dot notation (data.key), object literals { key: val }, and negative indexing arr[-1].
|
|
8
8
|
* 4. Predefined functions implemented in TypeScript:
|
|
9
|
-
* - File I/O: read_file, write_file, append_file, read_lines, read_json, write_json, read_csv, write_csv, file_exists, delete_file.
|
|
9
|
+
* - File I/O: read_file, write_file, append_file, read_lines, read_json, write_json, read_csv, write_csv, file_exists, delete_file, mkdir, rmdir, copy_file, move_file, basename, dirname, path_join, abs_path.
|
|
10
10
|
* - Data structures:
|
|
11
11
|
* * List/Array: list, len, push, pop, shift, unshift, insert, remove_at, slice, concat, reverse, sort, contains, index_of, join, unique, flatten, first, last, is_empty, sum, avg.
|
|
12
|
-
* * Hash/Map:
|
|
12
|
+
* * Hash/Map: hash, keys, values, entries, from_entries, has_key, get, set, delete_key, merge, clone, clear, size. ("map" is deliberately unimplemented, not an empty-hash constructor -- reserved for a future higher-order array-transform function.)
|
|
13
13
|
* - JSON processing: data = json(out), json_parse, json_parse_safe, json_stringify, pluck, filter_by, find_by.
|
|
14
|
+
* - Regex: regex_test/test, regex_match/match/search, regex_find_all/findall, regex_replace, split_regex -- patterns are plain strings compiled via the host RegExp engine.
|
|
15
|
+
* - Environment & time: env, getenv, set_env, now, timestamp, date, strftime, date_format.
|
|
16
|
+
* - Null handling: coalesce, if_null, default_to, if_else (expression-level ternary).
|
|
14
17
|
* - System & Process: system() returning SystemResult, prompt_human() for attended terminal pause/handoff.
|
|
15
18
|
* - Comprehensive string operations (split, lines, words, join, trim, upper, lower, contains, replace, slice, etc.).
|
|
19
|
+
* - First-class function values: a bare reference to an already-declared function name (user or host) is a
|
|
20
|
+
* callable FunctionRef, assignable to a variable (`g = dbl; g(4);`) -- a NAMED reference, not a lexical
|
|
21
|
+
* closure; calling through a non-identifier expression (e.g. `arr[0](x)`) is not supported.
|
|
16
22
|
* 5. Register new functions: API allowing host TypeScript functions to be registered and checked statically.
|
|
17
23
|
*
|
|
18
24
|
* Security & Authority Model:
|
|
@@ -315,7 +321,7 @@ export declare class Parser {
|
|
|
315
321
|
private consume;
|
|
316
322
|
private consumeOptionalSemicolon;
|
|
317
323
|
}
|
|
318
|
-
export declare const STDLIB_SOURCE = "# LMScript Standard Library (std.lms)\n\n# String Utilities\nfn is_blank(s) {\n if (s == null) {\n return true;\n }\n return len(trim(s)) == 0;\n}\n\n# Array Utilities\nfn chunk(arr, size) {\n if (size <= 0) {\n return [];\n }\n res = [];\n current = [];\n for (i = 0; i < len(arr); i = i + 1) {\n push(current, arr[i]);\n if (len(current) == size) {\n push(res, current);\n current = [];\n }\n }\n if (len(current) > 0) {\n push(res, current);\n }\n return res;\n}\n\nfn compact(arr) {\n res = [];\n for (i = 0; i < len(arr); i = i + 1) {\n item = arr[i];\n if (item != null) {\n push(res, item);\n }\n }\n return res;\n}\n\nfn zip(arr1, arr2) {\n res = [];\n limit = len(arr1);\n if (len(arr2) < limit) {\n limit = len(arr2);\n }\n for (i = 0; i < limit; i = i + 1) {\n push(res, [arr1[i], arr2[i]]);\n }\n return res;\n}\n\nfn take(arr, n) {\n res = [];\n limit = n;\n if (limit > len(arr)) {\n limit = len(arr);\n }\n for (i = 0; i < limit; i = i + 1) {\n push(res, arr[i]);\n }\n return res;\n}\n\nfn drop(arr, n) {\n res = [];\n start = n;\n if (start < 0) {\n start = 0;\n }\n for (i = start; i < len(arr); i = i + 1) {\n push(res, arr[i]);\n }\n return res;\n}\n\n# Math Utilities\nfn clamp(val, low, high) {\n if (val < low) {\n return low;\n }\n if (val > high) {\n return high;\n }\n return val;\n}\n";
|
|
324
|
+
export declare const STDLIB_SOURCE = "# LMScript Standard Library (std.lms)\n\n# String Utilities\nfn is_blank(s) {\n if (s == null) {\n return true;\n }\n return len(trim(s)) == 0;\n}\n\n# Array Utilities\nfn chunk(arr, size) {\n if (size <= 0) {\n return [];\n }\n res = [];\n current = [];\n for (i = 0; i < len(arr); i = i + 1) {\n push(current, arr[i]);\n if (len(current) == size) {\n push(res, current);\n current = [];\n }\n }\n if (len(current) > 0) {\n push(res, current);\n }\n return res;\n}\n\nfn compact(arr) {\n res = [];\n for (i = 0; i < len(arr); i = i + 1) {\n item = arr[i];\n if (item != null) {\n push(res, item);\n }\n }\n return res;\n}\n\nfn zip(arr1, arr2) {\n res = [];\n limit = len(arr1);\n if (len(arr2) < limit) {\n limit = len(arr2);\n }\n for (i = 0; i < limit; i = i + 1) {\n push(res, [arr1[i], arr2[i]]);\n }\n return res;\n}\n\nfn enumerate(arr) {\n res = [];\n for (i = 0; i < len(arr); i = i + 1) {\n push(res, [i, arr[i]]);\n }\n return res;\n}\n\nfn take(arr, n) {\n res = [];\n limit = n;\n if (limit > len(arr)) {\n limit = len(arr);\n }\n for (i = 0; i < limit; i = i + 1) {\n push(res, arr[i]);\n }\n return res;\n}\n\nfn drop(arr, n) {\n res = [];\n start = n;\n if (start < 0) {\n start = 0;\n }\n for (i = start; i < len(arr); i = i + 1) {\n push(res, arr[i]);\n }\n return res;\n}\n\n# Math Utilities\nfn clamp(val, low, high) {\n if (val < low) {\n return low;\n }\n if (val > high) {\n return high;\n }\n return val;\n}\n";
|
|
319
325
|
export declare function getStdlibProgram(): Program;
|
|
320
326
|
export interface CheckOptions {
|
|
321
327
|
/** Inspect literal built-in read paths against the current filesystem. No script evaluation. */
|
|
@@ -385,6 +391,23 @@ export declare class BreakSignal {
|
|
|
385
391
|
}
|
|
386
392
|
export declare class ContinueSignal {
|
|
387
393
|
}
|
|
394
|
+
/**
|
|
395
|
+
* First-class function value (operator ruling, 2026-09-29, Rule 2 -- "if it
|
|
396
|
+
* is just how it came out, it is worth fixing": no stated design rationale
|
|
397
|
+
* anywhere separated function names from the variable namespace; it was an
|
|
398
|
+
* omission of scope, not a deliberate tradeoff). A bare reference to an
|
|
399
|
+
* already-declared function name (user `fn` or host) evaluates to one of
|
|
400
|
+
* these, which can be assigned, stored, and called through a variable --
|
|
401
|
+
* `g = dbl; g(4);` now works. Deliberately a NAMED reference, not a true
|
|
402
|
+
* lexical closure over an enclosing scope: nothing in the reported gaps
|
|
403
|
+
* (map/filter/reduce/etc. over top-level named functions) needs closures,
|
|
404
|
+
* and adding them is a materially bigger, separate change.
|
|
405
|
+
*/
|
|
406
|
+
export declare class FunctionRef {
|
|
407
|
+
readonly name: string;
|
|
408
|
+
constructor(name: string);
|
|
409
|
+
toString(): string;
|
|
410
|
+
}
|
|
388
411
|
export declare class Environment {
|
|
389
412
|
private static nextId;
|
|
390
413
|
readonly id: number;
|
|
@@ -464,6 +487,13 @@ export declare class Interpreter {
|
|
|
464
487
|
evaluateProgram(program: Program): any;
|
|
465
488
|
private execStmt;
|
|
466
489
|
private evalExpr;
|
|
490
|
+
/** A call's callee name is normally used directly -- but if it names
|
|
491
|
+
* neither a declared user function nor a host function, it may be a
|
|
492
|
+
* variable holding a first-class FunctionRef (`g = dbl; g(4);`), in which
|
|
493
|
+
* case the actual function to invoke is the ref's name instead. */
|
|
494
|
+
private resolveCallTarget;
|
|
495
|
+
private invokeNamed;
|
|
496
|
+
private resolveIdentifier;
|
|
467
497
|
private isTruthy;
|
|
468
498
|
evaluateProgramAsync(program: Program): Promise<any>;
|
|
469
499
|
private execStmtAsync;
|
|
@@ -10,15 +10,20 @@ For `.lmctl` teamfile compatibility mode:
|
|
|
10
10
|
This REPLACED the static tested-model lists that used to live in this
|
|
11
11
|
document (2026-09-24) — hand-copied lists contradicted the catalog.
|
|
12
12
|
|
|
13
|
-
**Best-effort contract (operator, 2026-09-25): lint is
|
|
14
|
-
claimed to be 100% up to date.** Checks can lag provider
|
|
15
|
-
directions — a model lint warns about may have just been
|
|
16
|
-
a model lint accepts may have just been retired. Every
|
|
17
|
-
warning, never an error
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
**Best-effort contract (operator, 2026-09-25, hardened 2026-09-29): lint is
|
|
14
|
+
advisory and is NOT claimed to be 100% up to date.** Checks can lag provider
|
|
15
|
+
reality in BOTH directions — a model lint warns about may have just been
|
|
16
|
+
added upstream, and a model lint accepts may have just been retired. Every
|
|
17
|
+
model check is a warning, never an error, full stop: lint has exactly two
|
|
18
|
+
outcomes (ok / warning) and always exits 0 on warnings-only. There used to be
|
|
19
|
+
a `--strict` flag that could promote warnings to a failing exit code; the
|
|
20
|
+
operator removed it entirely (2026-09-29: "no need to give users the choice
|
|
21
|
+
with no obvious value") — lmctl decides the scoping, not the caller. Exit 1
|
|
22
|
+
is reserved for genuine validation errors (a malformed teamfile, an
|
|
23
|
+
unparseable member line), never for a warning. The runtime stance for
|
|
24
|
+
anything unrecognized or out of date is always: "not recognized — could
|
|
25
|
+
still be valid; no cost information," never a failure. Cost is equally
|
|
26
|
+
best-effort (n/a with a reason, never a guessed price).
|
|
22
27
|
- `codex` and `agy` model validation queries each provider's own live
|
|
23
28
|
catalog command (`codex debug models`, `agy models`) instead of a
|
|
24
29
|
hand-copied list — see their `## Codex` / `## Antigravity` sections
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmctl-ai/lmctl",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
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",
|