@lmctl-ai/lmctl 0.2.5 → 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.
@@ -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: map, keys, values, entries, from_entries, has_key, get, set, delete_key, merge, clone, clear, size.
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lmctl-ai/lmctl",
3
- "version": "0.2.5",
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",