@lmctl-ai/lmctl 0.2.10 → 0.2.12
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/chat-exec.d.ts +8 -0
- package/dist/cli/index.js +407 -405
- package/dist/cli/queue-delivery.d.ts +15 -0
- package/dist/cli/script.js +190 -190
- package/dist/providers/adapter.d.ts +8 -2
- package/dist/providers/bundle.d.ts +6 -0
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/parsers/acp.d.ts +24 -0
- package/dist/providers/transports/acp.d.ts +2 -0
- package/dist/script/lmscript.d.ts +23 -1
- package/package.json +1 -1
|
@@ -162,8 +162,14 @@ export interface TurnResult {
|
|
|
162
162
|
/** "ok" (default/omitted) = normal completion.
|
|
163
163
|
* "stalled" = idle timeout fired — provider went silent for the
|
|
164
164
|
* configured duration. The child process is still alive. The text
|
|
165
|
-
* field contains whatever was produced before the stall.
|
|
166
|
-
|
|
165
|
+
* field contains whatever was produced before the stall.
|
|
166
|
+
* "empty" = ACP transports only (see transport-wrappers.ts's
|
|
167
|
+
* emptyTurnStatus): the provider's own protocol reported a normal
|
|
168
|
+
* completion, but produced no text and no observed activity -- almost
|
|
169
|
+
* always an upstream failure (rate limit, quota, auth) that the
|
|
170
|
+
* provider's ACP layer swallowed instead of surfacing as an error.
|
|
171
|
+
* Never set for non-ACP transports (stream-json, codex-app-server). */
|
|
172
|
+
status?: "ok" | "stalled" | "empty";
|
|
167
173
|
/** When status === "stalled": how long the provider was idle (ms). */
|
|
168
174
|
stalledAfterMs?: number;
|
|
169
175
|
/** Human-readable strings when this turn's provider silently dropped a
|
|
@@ -70,6 +70,12 @@ export interface BundleTurnResult {
|
|
|
70
70
|
* provider configuration is applied once at open, not per spawn.
|
|
71
71
|
*/
|
|
72
72
|
warnings?: string[];
|
|
73
|
+
/**
|
|
74
|
+
* ACP bundle sessions only (see AcpOutputProcessorResult.sawActivity) --
|
|
75
|
+
* whether this turn saw any real agent activity, as opposed to a clean
|
|
76
|
+
* but empty completion. Omitted for non-ACP bundle implementations.
|
|
77
|
+
*/
|
|
78
|
+
sawActivity?: boolean;
|
|
73
79
|
}
|
|
74
80
|
export interface BundleSession {
|
|
75
81
|
/** Provider key this session serves (e.g. "opencode"). */
|
|
@@ -124,7 +124,7 @@ export interface ChatResult {
|
|
|
124
124
|
durationMs: number;
|
|
125
125
|
stopReason?: string;
|
|
126
126
|
numTurns?: number;
|
|
127
|
-
status?: "ok" | "stalled";
|
|
127
|
+
status?: "ok" | "stalled" | "empty";
|
|
128
128
|
stalledAfterMs?: number;
|
|
129
129
|
/** Human-readable strings when this turn's provider silently dropped a
|
|
130
130
|
* declared model=/effort= (task #232). Omitted when nothing was dropped. */
|
|
@@ -9,11 +9,19 @@ export interface AcpResult {
|
|
|
9
9
|
* rejection the turn proceeded past anyway. Omitted when nothing was
|
|
10
10
|
* dropped. */
|
|
11
11
|
warnings?: string[];
|
|
12
|
+
/** See AcpOutputProcessorResult.sawActivity. */
|
|
13
|
+
sawActivity: boolean;
|
|
12
14
|
}
|
|
13
15
|
export interface AcpOutputProcessorResult {
|
|
14
16
|
result: string;
|
|
15
17
|
sessionId: string;
|
|
16
18
|
stopReason: string;
|
|
19
|
+
/** Whether THIS turn saw any real agent activity (message/thought text,
|
|
20
|
+
* a tool call or its result, a plan) -- as opposed to pure session
|
|
21
|
+
* bookkeeping (session_info_update, current_mode_update,
|
|
22
|
+
* config_option_update, available_commands_update, usage_update,
|
|
23
|
+
* user_message_chunk) or nothing at all. See ACP_MEANINGFUL_UPDATE_KINDS. */
|
|
24
|
+
sawActivity: boolean;
|
|
17
25
|
}
|
|
18
26
|
export interface AcpOutputProcessor {
|
|
19
27
|
setSessionId(sessionId: string): void;
|
|
@@ -32,6 +40,22 @@ export interface AcpOutputProcessor {
|
|
|
32
40
|
export declare function isolateGeminiLatestAgentMessage(text: string): string;
|
|
33
41
|
export declare function acpSessionIdFromResponse(response: Record<string, unknown>, fallback?: string): string;
|
|
34
42
|
export declare function acpStopReasonFromResponse(response: Record<string, unknown>): string;
|
|
43
|
+
/**
|
|
44
|
+
* `sessionUpdate` kinds that represent real agent work, grounded in actual
|
|
45
|
+
* production ACP traffic (checked against a full day's ~/.lmctl/debug-*.log,
|
|
46
|
+
* 2026-09-29) plus the ACP spec's own "plan" kind (Zed and friends). Every
|
|
47
|
+
* OTHER kind seen in that traffic -- session_info_update, current_mode_
|
|
48
|
+
* update, config_option_update, available_commands_update, usage_update,
|
|
49
|
+
* user_message_chunk (an echo of the user's OWN input, not agent work) -- is
|
|
50
|
+
* pure session bookkeeping, and any future/unrecognized kind is treated the
|
|
51
|
+
* same conservative way: NOT activity. This is a whitelist, not a blacklist,
|
|
52
|
+
* on purpose -- the failure mode of missing a real silent-failure turn is
|
|
53
|
+
* bad, but the failure mode of flagging a legitimate turn as broken is
|
|
54
|
+
* worse (it would fire fleet-wide, for every provider, on every genuinely
|
|
55
|
+
* empty-but-fine turn), so activity only counts when there is positive
|
|
56
|
+
* evidence of it.
|
|
57
|
+
*/
|
|
58
|
+
export declare const ACP_MEANINGFUL_UPDATE_KINDS: Set<string>;
|
|
35
59
|
export declare function createAcpOutputProcessor(opts?: {
|
|
36
60
|
tool?: string;
|
|
37
61
|
onDelta?: (text: string) => void;
|
|
@@ -155,6 +155,8 @@ export interface AcpSessionTurnResult {
|
|
|
155
155
|
* profile's sessionSetup runs once at open, not per spawn.
|
|
156
156
|
*/
|
|
157
157
|
warnings?: string[];
|
|
158
|
+
/** See AcpOutputProcessorResult.sawActivity. */
|
|
159
|
+
sawActivity: boolean;
|
|
158
160
|
}
|
|
159
161
|
/**
|
|
160
162
|
* An open ACP bundle session: one provider process serving many prompts.
|
|
@@ -413,7 +413,29 @@ export declare class Environment {
|
|
|
413
413
|
readonly id: number;
|
|
414
414
|
private readonly values;
|
|
415
415
|
readonly parent?: Environment;
|
|
416
|
-
|
|
416
|
+
/**
|
|
417
|
+
* True only for the environment a function CALL creates (invokeNamed's
|
|
418
|
+
* fnEnv) -- never for a plain nested block (if/while/for body). Marks
|
|
419
|
+
* where `set()`'s upward search for an EXISTING binding must stop.
|
|
420
|
+
*
|
|
421
|
+
* Real incident, 2026-09-29 (operator finding): `fn f(x) { outer = 1; }`
|
|
422
|
+
* silently mutated an outer/global `outer` whenever one already existed,
|
|
423
|
+
* purely because the name collided -- "dynamic scoping with implicit
|
|
424
|
+
* global mutation," math's words, and no `local`/`my`/`let` to defend
|
|
425
|
+
* against it (a *working* `let` already existed in the grammar, but was
|
|
426
|
+
* entirely undocumented, which is why it went unnoticed). A name that
|
|
427
|
+
* happens to already exist as a global is not evidence the function
|
|
428
|
+
* meant to reference it. `set()` now treats a name not yet bound WITHIN
|
|
429
|
+
* the current function's own scope chain as a fresh function-local,
|
|
430
|
+
* matching every language cited for comparison (Perl's `my`, JS's
|
|
431
|
+
* function/`let` scoping, Python's function-scope-by-default) --
|
|
432
|
+
* without this flag, an if/while/for block's `set()` calls would ALSO
|
|
433
|
+
* stop at their own Environment, breaking ordinary control flow (e.g.
|
|
434
|
+
* `if (true) { x = 2; }` updating a `x` declared earlier in the SAME
|
|
435
|
+
* function must keep working).
|
|
436
|
+
*/
|
|
437
|
+
readonly isFunctionBoundary: boolean;
|
|
438
|
+
constructor(parent?: Environment, isFunctionBoundary?: boolean);
|
|
417
439
|
resolveBinding(name: string): {
|
|
418
440
|
env: Environment;
|
|
419
441
|
name: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmctl-ai/lmctl",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.12",
|
|
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",
|