@lmctl-ai/lmctl 0.1.342 → 0.2.3
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 +116 -0
- package/README.md +11 -51
- package/data/price-aliases.json +1 -0
- package/data/price-data.json +1 -1
- package/dist/cli/batch.d.ts +2 -0
- package/dist/cli/busy-evidence.d.ts +27 -0
- package/dist/cli/chat-cycle.d.ts +59 -0
- package/dist/cli/chat-exec.d.ts +83 -0
- package/dist/cli/chat-policy.d.ts +22 -0
- package/dist/cli/chat.d.ts +23 -0
- package/dist/cli/code-resolver.d.ts +8 -0
- package/dist/cli/common.d.ts +54 -0
- package/dist/cli/context.d.ts +12 -0
- package/dist/cli/cost.d.ts +2 -0
- package/dist/cli/export.d.ts +2 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +1062 -1400
- package/dist/cli/infra.d.ts +78 -0
- package/dist/cli/ls.d.ts +2 -0
- package/dist/cli/mailbox-cli.d.ts +6 -0
- package/dist/cli/managed.d.ts +62 -0
- package/dist/cli/mcp-install.d.ts +23 -0
- package/dist/cli/mcp.d.ts +2 -0
- package/dist/cli/paths.d.ts +50 -0
- package/dist/cli/plan-wizard.d.ts +42 -0
- package/dist/cli/plan.d.ts +20 -0
- package/dist/cli/queue-delivery.d.ts +107 -0
- package/dist/cli/ratelimit.d.ts +3 -0
- package/dist/cli/remote-fetch.d.ts +7 -0
- package/dist/cli/run-queries.d.ts +82 -0
- package/dist/cli/running.d.ts +5 -0
- package/dist/cli/schema.sql +20 -1
- package/dist/cli/script.d.ts +6 -0
- package/dist/cli/script.js +2097 -0
- package/dist/cli/self-identity.d.ts +25 -0
- package/dist/cli/session-idle.d.ts +118 -0
- package/dist/cli/status.d.ts +22 -0
- package/dist/cli/tail.d.ts +18 -0
- package/dist/cli/target-resolver.d.ts +139 -0
- package/dist/cli/team-status.d.ts +91 -0
- package/dist/cli/teamfile-compat.d.ts +71 -0
- package/dist/cli/teamfile-store.d.ts +18 -0
- package/dist/cli/teamfile-template.d.ts +40 -0
- package/dist/cli/template-env.d.ts +25 -0
- package/dist/cli/terminal-lock.d.ts +25 -0
- package/dist/cli/terminal.d.ts +23 -0
- package/dist/cli/time-filter.d.ts +10 -0
- package/dist/cli/update-notifier.d.ts +11 -0
- package/dist/cli/version-util.d.ts +2 -0
- package/dist/config/seed_templates.d.ts +1 -0
- package/dist/db/backfill-event-log.d.ts +26 -0
- package/dist/db/delegation.d.ts +37 -0
- package/dist/db/escalation_vocab.d.ts +45 -0
- package/dist/db/event-log.d.ts +40 -0
- package/dist/db/index.d.ts +1213 -0
- package/dist/db/inflight-acquire.d.ts +70 -0
- package/dist/db/invocation-event-projections.d.ts +65 -0
- package/dist/db/ledger-identity.test.d.ts +1 -0
- package/dist/db/live-event-projections.d.ts +92 -0
- package/dist/db/migrate.d.ts +51 -0
- package/dist/db/open-readonly.d.ts +2 -0
- package/dist/db/process-liveness.d.ts +37 -0
- package/dist/db/sqlite.d.ts +47 -0
- package/dist/db/sqlite.test.d.ts +1 -0
- package/dist/db/terminal-lock.d.ts +14 -0
- package/dist/db/tracked-invocation-reconcile.d.ts +52 -0
- package/dist/db/tracked-invocation.d.ts +116 -0
- package/dist/mcp/dispatch.d.ts +45 -0
- package/dist/mcp/mediation.d.ts +128 -0
- package/dist/mcp/path-warning.d.ts +7 -0
- package/dist/mcp/server.d.ts +63 -0
- package/dist/mcp/tools.d.ts +24 -0
- package/dist/providers/adapter.d.ts +265 -0
- package/dist/providers/adapters/agy-adapter.d.ts +17 -0
- package/dist/providers/adapters/claude-adapter.d.ts +20 -0
- package/dist/providers/adapters/codex-adapter.d.ts +22 -0
- package/dist/providers/adapters/copilot-adapter.d.ts +16 -0
- package/dist/providers/adapters/dsh-adapter.d.ts +89 -0
- package/dist/providers/adapters/gemini-adapter.d.ts +44 -0
- package/dist/providers/adapters/hermes-adapter.d.ts +71 -0
- package/dist/providers/adapters/index.d.ts +35 -0
- package/dist/providers/adapters/kimi-adapter.d.ts +16 -0
- package/dist/providers/adapters/lmplayer-adapter.d.ts +14 -0
- package/dist/providers/adapters/opencode-adapter.d.ts +11 -0
- package/dist/providers/adapters/pi-adapter.d.ts +17 -0
- package/dist/providers/adapters/print-turn.d.ts +29 -0
- package/dist/providers/adapters/qwen-adapter.d.ts +11 -0
- package/dist/providers/agy.d.ts +32 -0
- package/dist/providers/base-adapter.d.ts +107 -0
- package/dist/providers/base.d.ts +12 -0
- package/dist/providers/binary-check.d.ts +102 -0
- package/dist/providers/bundle.d.ts +118 -0
- package/dist/providers/claude-mock.d.ts +90 -0
- package/dist/providers/claude.d.ts +21 -0
- package/dist/providers/codex-config.d.ts +15 -0
- package/dist/providers/codex.d.ts +25 -0
- package/dist/providers/config/model-selection-lint.d.ts +45 -0
- package/dist/providers/config/team-config.d.ts +183 -0
- package/dist/providers/config/types.d.ts +146 -0
- package/dist/providers/config/user-config.d.ts +88 -0
- package/dist/providers/copilot.d.ts +21 -0
- package/dist/providers/debug.d.ts +128 -0
- package/dist/providers/dsh-sidecar.d.ts +65 -0
- package/dist/providers/dsh-zstd.d.ts +27 -0
- package/dist/providers/dsh.d.ts +37 -0
- package/dist/providers/frontmatter.d.ts +46 -0
- package/dist/providers/gemini-session-reader.d.ts +151 -0
- package/dist/providers/gemini.d.ts +39 -0
- package/dist/providers/hermes.d.ts +90 -0
- package/dist/providers/index.d.ts +421 -0
- package/dist/providers/kimi.d.ts +37 -0
- package/dist/providers/model-catalog.d.ts +141 -0
- package/dist/providers/one-shot-timeout.d.ts +1 -0
- package/dist/providers/opencode-config.d.ts +62 -0
- package/dist/providers/opencode.d.ts +40 -0
- package/dist/providers/parsers/acp.d.ts +47 -0
- package/dist/providers/parsers/codex-app-server.d.ts +60 -0
- package/dist/providers/parsers/stream-json.d.ts +57 -0
- package/dist/providers/passive-readers/agy.d.ts +155 -0
- package/dist/providers/passive-readers/copilot.d.ts +173 -0
- package/dist/providers/passive-readers/dsh.d.ts +34 -0
- package/dist/providers/passive-readers/kimi.d.ts +44 -0
- package/dist/providers/passive-readers/opencode.d.ts +89 -0
- package/dist/providers/passive-readers/qwen.d.ts +151 -0
- package/dist/providers/passive-readers/shared.d.ts +138 -0
- package/dist/providers/passive-session-reader.d.ts +188 -0
- package/dist/providers/path-utils.d.ts +1 -0
- package/dist/providers/pi.d.ts +32 -0
- package/dist/providers/pricing.d.ts +107 -0
- package/dist/providers/qwen.d.ts +22 -0
- package/dist/providers/ratelimit-readings.d.ts +32 -0
- package/dist/providers/registry.d.ts +31 -0
- package/dist/providers/resume.d.ts +43 -0
- package/dist/providers/seed-instruction.d.ts +3 -0
- package/dist/providers/self-session-env.d.ts +21 -0
- package/dist/providers/session-limit.d.ts +9 -0
- package/dist/providers/strip-ansi.d.ts +5 -0
- package/dist/providers/transport-errors.d.ts +94 -0
- package/dist/providers/transport-lifecycle.d.ts +63 -0
- package/dist/providers/transport-wrappers.d.ts +110 -0
- package/dist/providers/transports/acp-profiles/config-option-step.d.ts +24 -0
- package/dist/providers/transports/acp-profiles/copilot.d.ts +12 -0
- package/dist/providers/transports/acp-profiles/gemini.d.ts +22 -0
- package/dist/providers/transports/acp-profiles/hermes.d.ts +27 -0
- package/dist/providers/transports/acp-profiles/index.d.ts +19 -0
- package/dist/providers/transports/acp-profiles/kimi.d.ts +24 -0
- package/dist/providers/transports/acp-profiles/opencode.d.ts +26 -0
- package/dist/providers/transports/acp-profiles/types.d.ts +258 -0
- package/dist/providers/transports/acp-rpc.d.ts +18 -0
- package/dist/providers/transports/acp.d.ts +215 -0
- package/dist/providers/transports/codex-app-server.d.ts +190 -0
- package/dist/providers/transports/hold-open.d.ts +120 -0
- package/dist/providers/transports/manager.d.ts +21 -0
- package/dist/providers/transports/stream-json.d.ts +162 -0
- package/dist/providers/transports/types.d.ts +56 -0
- package/dist/providers/types.d.ts +154 -0
- package/dist/providers/yolo-contract.d.ts +131 -0
- package/dist/script/adapter.d.ts +101 -0
- package/dist/script/batch-script.d.ts +7 -0
- package/dist/script/index.d.ts +3 -0
- package/dist/script/lmscript.d.ts +550 -0
- package/dist/shared/policy.d.ts +74 -0
- package/dist/shared-lib/db.d.ts +25 -0
- package/dist/shared-lib/passive-session-reader.d.ts +2 -0
- package/dist/shared-lib/provider-parse.d.ts +6 -0
- package/dist/templates/basedir.d.ts +52 -0
- package/dist/uri/lmctl_uri.d.ts +38 -0
- package/durable-memory/model_selection.md +122 -25
- package/examples/README.md +103 -0
- package/examples/anonymous-panel.lms +3 -0
- package/examples/batch-prompts.txt +9 -0
- package/examples/batchscript.lms +67 -0
- package/examples/n8n/agent-lib.lms +56 -0
- package/examples/n8n/git-lib.lms +93 -0
- package/examples/n8n/mock-support.db +0 -0
- package/examples/n8n/multi-agent-review.lms +107 -0
- package/examples/n8n/news-digest.lms +159 -0
- package/examples/n8n/rag-search.lms +163 -0
- package/examples/n8n/support-agent.lms +88 -0
- package/examples/n8n/ticket-triage.lms +156 -0
- package/package.json +13 -17
- package/dist/cli/side_effect_classifier.json +0 -19
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thin adapter mounting lmt + lmauto as `lmctl` subcommands, gated behind
|
|
3
|
+
* `LMCTL_INFRA_CLI`. Off by default — see
|
|
4
|
+
* ~/repos/infraqa/lmctl-thin-merge-design.md (§2.2 "the seam") for the
|
|
5
|
+
* original design; this was P2 of that design's phasing.
|
|
6
|
+
*
|
|
7
|
+
* STATUS (2026-09-10, lmauto.lmctl): `lmt` (the target this adapter was built
|
|
8
|
+
* against) is now RETIRED — see ~/repos/tools/lmt/RETIRED.md. Its command
|
|
9
|
+
* surface was absorbed natively into `@lmctl-ai/lmbee` (the renamed
|
|
10
|
+
* `lmauto`), but lmbee does NOT export the `InfraLmtModule` contract this
|
|
11
|
+
* file expects (`INFRA_CLI_CONTRACT`/`createRuntime`/a raw-exit-code
|
|
12
|
+
* `dispatch(argv, runtime)`) — lmbee's own `dispatch(context, argv)` has a
|
|
13
|
+
* different signature and return shape (`Promise<{output, exitCode}>`,
|
|
14
|
+
* requires a `CliContext` built via `buildContext()`, not a bare
|
|
15
|
+
* `runtime`), and it has no concept of a frozen `INFRA_CLI_CONTRACT` version
|
|
16
|
+
* number at all (that was an lmt-specific, this-adapter-specific concept).
|
|
17
|
+
* Blindly swapping the import target from `@lmctl-ai/lmt` to
|
|
18
|
+
* `@lmctl-ai/lmbee` would NOT make this adapter work — it would still throw,
|
|
19
|
+
* just for a different reason (shape mismatch, not MODULE_NOT_FOUND), while
|
|
20
|
+
* looking superficially "fixed." `defaultLoadInfraModule` below has been
|
|
21
|
+
* changed to throw directly instead of importing a package that no longer
|
|
22
|
+
* has any plausible target, so the previously-accurate-but-now-stale
|
|
23
|
+
* "private repo, no CI credential" reasoning doesn't linger as a misleading
|
|
24
|
+
* TODO. Reviving `LMCTL_INFRA_CLI` needs a real design pass against lmbee's
|
|
25
|
+
* actual `dispatch()`/`buildContext()` shape (coordinate with lmauto.lmctl,
|
|
26
|
+
* lmbee's owner) — not a mechanical rename, and out of scope for this
|
|
27
|
+
* cleanup. Still safely inert either way: `runInfraCommand`'s catch below
|
|
28
|
+
* already handles the throw as the correct "not available" remediation
|
|
29
|
+
* case, and the feature stays off by default.
|
|
30
|
+
*
|
|
31
|
+
* lmauto's own P1 landed first (lmauto-cli-v0.2.21, verified against
|
|
32
|
+
* ~/repos/lmauto/src/cli/dispatch.ts): its `dispatch()` never throws for
|
|
33
|
+
* ordinary usage/validation misuse (every malformed argv returns
|
|
34
|
+
* `{output, exitCode: 1}`; only a genuine internal failure — DB/fs error —
|
|
35
|
+
* still propagates), and it now exports `COMMANDS` (its 16 routable verbs,
|
|
36
|
+
* as of the lmbee migration's Stage 2) + `PROCESS_ONLY_COMMANDS`
|
|
37
|
+
* (`whoami`/`migrate-home`/`serve`/`peers`/`tell`/`sites`/`exec`/`fleet`/the
|
|
38
|
+
* 6 cloud-service adapters, reachable only through lmbee's own bin, never
|
|
39
|
+
* through `dispatch()`). Neither changes anything HERE: `InfraLmtModule.
|
|
40
|
+
* dispatch`'s return shape below was lmt's own contract, one layer above
|
|
41
|
+
* lmauto's/lmbee's own — with lmt retired, that specific contract has no
|
|
42
|
+
* living implementation to target at all anymore, lmbee's own `dispatch()`
|
|
43
|
+
* shape included. Also confirmed with lmauto/lmbee directly: its DB
|
|
44
|
+
* resolution (`buildContext()`/`resolveLmautoDbPath()`) has no concept of
|
|
45
|
+
* lmctl's `--db` anywhere in the chain, so the `--db` firewall correctly
|
|
46
|
+
* lives only in `src/cli/index.ts` (already shipped), not here.
|
|
47
|
+
*/
|
|
48
|
+
import type { CliIo } from './common.js';
|
|
49
|
+
/** Design §2.2: lmt's embedding contract version this lmctl build expects. */
|
|
50
|
+
export declare const INFRA_CLI_CONTRACT_EXPECTED = 1;
|
|
51
|
+
/**
|
|
52
|
+
* Flat command names + the `auto` namespace, per the design's §2.1
|
|
53
|
+
* command-surface mapping. This list is pinned by the design doc itself,
|
|
54
|
+
* not derived from lmt's export — so it can be wired into `COMMANDS` and
|
|
55
|
+
* collision-checked before lmt exports anything.
|
|
56
|
+
*/
|
|
57
|
+
export declare const INFRA_FLAT_COMMANDS: readonly ["lmchat", "lmmail", "lmnote", "lmsheet", "lmtext", "lmsound", "login", "whoami", "exec", "tell", "peers", "site"];
|
|
58
|
+
export declare const INFRA_NAMESPACE_COMMAND = "auto";
|
|
59
|
+
export declare function infraCliEnabled(env?: NodeJS.ProcessEnv): boolean;
|
|
60
|
+
export declare function isInfraCommand(command: string): boolean;
|
|
61
|
+
interface InfraLmtModule {
|
|
62
|
+
INFRA_CLI_CONTRACT: number;
|
|
63
|
+
createRuntime: (...args: unknown[]) => unknown;
|
|
64
|
+
dispatch: (argv: string[], runtime: unknown) => Promise<number> | number;
|
|
65
|
+
}
|
|
66
|
+
/** Test seam — production always uses {@link defaultLoadInfraModule}. */
|
|
67
|
+
export type InfraModuleLoader = () => Promise<InfraLmtModule>;
|
|
68
|
+
/**
|
|
69
|
+
* Design §2.6 acceptance criteria, implemented ahead of the real module:
|
|
70
|
+
* - optional-absent → exit 1 + the exact remediation string (never throws
|
|
71
|
+
* up through the CLI dispatcher).
|
|
72
|
+
* - contract-version skew → refuse rather than dispatch into a mismatched
|
|
73
|
+
* manifest.
|
|
74
|
+
* - pass-through parity → argv forwarded verbatim (minus the `auto`
|
|
75
|
+
* prefix), no re-parsing here.
|
|
76
|
+
*/
|
|
77
|
+
export declare function runInfraCommand(command: string, args: string[], io: CliIo, loadModule?: InfraModuleLoader): Promise<number>;
|
|
78
|
+
export {};
|
package/dist/cli/ls.d.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* P3 (briefs/lmctl0-verbs-native-port-design.md §2.4 / §2.5) — managed
|
|
3
|
+
* mode shared helpers. Consumed by terminal/chat/tail/info/ls when the
|
|
4
|
+
* P0 classifier returns `{mode:'managed'}`. The §2.4 precedence is
|
|
5
|
+
* kind-keyed (verbatim from the design):
|
|
6
|
+
*
|
|
7
|
+
* • workflow_escalation → attention payload is context-only; resolve
|
|
8
|
+
* the agent via the latest `agent_call`
|
|
9
|
+
* session_event for the RUN (never via
|
|
10
|
+
* interactive_session; never via a
|
|
11
|
+
* payload.step_id == session_event.step_id
|
|
12
|
+
* join — see Dal.latestAgentCall doc-comment).
|
|
13
|
+
* • interactive_waiting_op → interactive_session is authoritative for
|
|
14
|
+
* the paused step + resumeInteractive.
|
|
15
|
+
* Agent identity still via latestAgentCall.
|
|
16
|
+
* • running (no attention) → latestAgentCall only.
|
|
17
|
+
* • none resolves → clear error (no DAL write).
|
|
18
|
+
*
|
|
19
|
+
* All helpers are read-only; spawn nothing. They take `Dal` so callers
|
|
20
|
+
* can inject a memory DAL in tests.
|
|
21
|
+
*/
|
|
22
|
+
import type { Dal } from '../db/index.js';
|
|
23
|
+
export interface ManagedAgent {
|
|
24
|
+
/** Resolved provider for the agent session. */
|
|
25
|
+
provider: string;
|
|
26
|
+
/** Native session id (the provider's id). */
|
|
27
|
+
sessionid: string;
|
|
28
|
+
/** Working directory for the provider TUI. */
|
|
29
|
+
sessiondir: string;
|
|
30
|
+
/** Team-member alias the run's latest agent_call drove. */
|
|
31
|
+
alias: string;
|
|
32
|
+
/** Optional model override. */
|
|
33
|
+
model?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Resolve a run-id to its agent provider session (§2.4 precedence). Uses
|
|
37
|
+
* `Dal.latestAgentCall` — RUN-keyed, ORDER BY id DESC — and falls back to
|
|
38
|
+
* the single-member team rule (§2.5) when no agent_call has been written
|
|
39
|
+
* yet. NEVER joins `session_event` by `payload.step_id`, NEVER consults
|
|
40
|
+
* `interactive_session`.
|
|
41
|
+
*
|
|
42
|
+
* `aliasOverride` (optional) — if provided, looks up that specific member
|
|
43
|
+
* (skipping latestAgentCall). Used by callers that surface `--alias A`
|
|
44
|
+
* alongside `--run <id>` per the §3 grammar / §2.5 disambiguation.
|
|
45
|
+
*
|
|
46
|
+
* Returns `{ok:<ManagedAgent>}` on success or `{err:<message>}` on any
|
|
47
|
+
* resolution failure (caller surfaces as a clear user-error).
|
|
48
|
+
*/
|
|
49
|
+
export declare function resolveManagedAgent(dal: Dal, run_id: number, aliasOverride?: string): {
|
|
50
|
+
ok: ManagedAgent;
|
|
51
|
+
} | {
|
|
52
|
+
err: string;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Find the run's pending operator-answerable attention (if any).
|
|
56
|
+
* Returns the unacked `requires_user=1` attention row's `{kind, attention_id}`
|
|
57
|
+
* or null. Read-only.
|
|
58
|
+
*/
|
|
59
|
+
export declare function pendingOperatorAttention(dal: Dal, run_id: number): {
|
|
60
|
+
kind: string;
|
|
61
|
+
attention_id: number;
|
|
62
|
+
} | null;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { CliIo } from './common.js';
|
|
2
|
+
import type { TeamConfig } from '../providers/config/team-config.js';
|
|
3
|
+
interface McpInstallFileOps {
|
|
4
|
+
existsSync(path: string): boolean;
|
|
5
|
+
mkdirSync(path: string, opts: {
|
|
6
|
+
recursive: true;
|
|
7
|
+
}): unknown;
|
|
8
|
+
readFileSync(path: string, encoding: 'utf8'): string;
|
|
9
|
+
writeFileSync(path: string, data: string, encoding: 'utf8'): unknown;
|
|
10
|
+
renameSync(oldPath: string, newPath: string): unknown;
|
|
11
|
+
unlinkSync(path: string): unknown;
|
|
12
|
+
}
|
|
13
|
+
export type CopilotMcpServerConfig = Record<string, unknown>;
|
|
14
|
+
export declare function _setMcpInstallTestHooksForTests(input: {
|
|
15
|
+
homeDir?: string;
|
|
16
|
+
fileOps?: Partial<McpInstallFileOps>;
|
|
17
|
+
} | null): void;
|
|
18
|
+
export declare function cleanupStaleMcpForTeam(io: CliIo, config: TeamConfig, teamfilePath: string): void;
|
|
19
|
+
export declare function copilotMcpConfigPath(homeDir?: string): string;
|
|
20
|
+
export declare function mergeCopilotMcpServers(path: string, desiredServers: Record<string, CopilotMcpServerConfig>): {
|
|
21
|
+
changed: boolean;
|
|
22
|
+
};
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ~/.lmctl root directory (or override via `LMCTL_HOME`).
|
|
3
|
+
*
|
|
4
|
+
* `LMCTL_HOME` is the absolute path TO `.lmctl` (i.e. the directory that
|
|
5
|
+
* contains `state.db`) — not the parent. Used by tests to redirect the entire
|
|
6
|
+
* state tree.
|
|
7
|
+
*
|
|
8
|
+
* Without an override we use `os.homedir()` + `.lmctl`. Note: on POSIX, libuv
|
|
9
|
+
* resolves `homedir` from /etc/passwd rather than `$HOME`, which is why we
|
|
10
|
+
* expose a dedicated env override instead of relying on `$HOME` for test
|
|
11
|
+
* isolation.
|
|
12
|
+
*/
|
|
13
|
+
export declare function lmctlNextHome(): string;
|
|
14
|
+
/** The default DB path: ~/.lmctl/state.db (under `LMCTL_HOME`). */
|
|
15
|
+
export declare function defaultDbPath(): string;
|
|
16
|
+
/**
|
|
17
|
+
* Single source of truth for the state.db path.
|
|
18
|
+
*
|
|
19
|
+
* Priority order (highest first):
|
|
20
|
+
* 1. dbFlag arg (passed via top-level `--db PATH` flag)
|
|
21
|
+
* 2. process.env.LMCTL_DB
|
|
22
|
+
* 3. ~/.lmctl/state.db (under `LMCTL_HOME`)
|
|
23
|
+
*
|
|
24
|
+
* Parent directories are created on first DB open by migrate().
|
|
25
|
+
*/
|
|
26
|
+
export declare function resolveDbPath(dbFlag?: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* One-line human rendering of the resolved state location, shared by
|
|
29
|
+
* `lmctl status`'s footer and the stale-SELF-marker error so both name the DB
|
|
30
|
+
* the same way. When the path came from an explicit `--db`/`LMCTL_DB` override,
|
|
31
|
+
* the label says so.
|
|
32
|
+
*/
|
|
33
|
+
export declare function describeStateLocation(dbPath: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Detect whether `dbPath` lives on a WSL `/mnt/c` Windows-mounted volume.
|
|
36
|
+
* WSL Windows-mount IO is ~5-10x slower than the native ext4 home volume,
|
|
37
|
+
* which surfaces as flaky locks + slow migrations. We emit a one-line
|
|
38
|
+
* stderr hint at startup so operators can move the DB if they hit it.
|
|
39
|
+
*
|
|
40
|
+
* Exposed for tests; production callers should use `warnIfSlowDbPath`.
|
|
41
|
+
*/
|
|
42
|
+
export declare function isSlowWslMount(dbPath: string, plat?: NodeJS.Platform): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Print a one-line stderr warning if `dbPath` is on `/mnt/c`. No-op on
|
|
45
|
+
* non-Linux platforms and on non-`/mnt/c` paths. Idempotent — safe to call
|
|
46
|
+
* once at startup.
|
|
47
|
+
*/
|
|
48
|
+
export declare function warnIfSlowDbPath(dbPath: string, stderr?: {
|
|
49
|
+
write: (chunk: string) => unknown;
|
|
50
|
+
}, plat?: NodeJS.Platform): void;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive fallback for `lmctl plan`: a plain node:readline wizard (no new
|
|
3
|
+
* dependencies). Every question here has a flag equivalent on `runPlan`; this
|
|
4
|
+
* module only runs when config flags are absent and stdin is a TTY (or
|
|
5
|
+
* `--wizard` forced it). It returns the final teamfile text plus where to
|
|
6
|
+
* write it — plan.ts owns the actual write/lint/seed pipeline so the flags
|
|
7
|
+
* path and the wizard path behave identically after this point.
|
|
8
|
+
*/
|
|
9
|
+
import { type ProviderBinaryCheck } from '../providers/binary-check.js';
|
|
10
|
+
import type { CliIo } from './common.js';
|
|
11
|
+
import { type MemberSpec } from './teamfile-template.js';
|
|
12
|
+
export interface PlanWizardInitial {
|
|
13
|
+
provider?: string;
|
|
14
|
+
model?: string;
|
|
15
|
+
pattern?: string;
|
|
16
|
+
members?: MemberSpec[];
|
|
17
|
+
seed?: boolean;
|
|
18
|
+
/** Explicit --output destination; skips the directory/name questions. */
|
|
19
|
+
output?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface PlanWizardResult {
|
|
22
|
+
destPath: string;
|
|
23
|
+
text: string;
|
|
24
|
+
seed: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface PlanWizardOptions {
|
|
27
|
+
io: CliIo;
|
|
28
|
+
/** Line source for readline — real stdin in the CLI, a scripted stream in tests. */
|
|
29
|
+
input: NodeJS.ReadableStream;
|
|
30
|
+
cwd: string;
|
|
31
|
+
/** Preselected directory (positional arg); defaults to cwd. */
|
|
32
|
+
directory?: string;
|
|
33
|
+
initial?: PlanWizardInitial;
|
|
34
|
+
/** Test seam — defaults to probing PATH via checkProviderBinaries. */
|
|
35
|
+
checkProviders?: () => ProviderBinaryCheck[];
|
|
36
|
+
/** Test seam — defaults to spawning $EDITOR synchronously on the temp file. */
|
|
37
|
+
editFile?: (path: string) => void;
|
|
38
|
+
env?: NodeJS.ProcessEnv;
|
|
39
|
+
}
|
|
40
|
+
export declare function runPlanWizard(opts: PlanWizardOptions): Promise<PlanWizardResult | null>;
|
|
41
|
+
/** Members for reporting after a wizard run — re-parse so `$EDITOR` changes are reflected. */
|
|
42
|
+
export declare function wizardMembers(text: string): MemberSpec[];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `lmctl plan` — flags-first, wizard-fallback teamfile generator.
|
|
3
|
+
*
|
|
4
|
+
* Every wizard question has a flag; the wizard fires only when no config
|
|
5
|
+
* flags are present AND stdin is a TTY (`--wizard` forces it,
|
|
6
|
+
* `--non-interactive` suppresses it with a missing-params error). Session
|
|
7
|
+
* ids are never generated here — seeding is `lmctl seed`'s job, chained via
|
|
8
|
+
* `--seed` (lint first, refuse to seed when lint fails).
|
|
9
|
+
*/
|
|
10
|
+
import type { ProviderBinaryCheck } from '../providers/binary-check.js';
|
|
11
|
+
import type { CliIo } from './common.js';
|
|
12
|
+
/** Test seams — fetch for --from URLs, provider probe + editor for the wizard. */
|
|
13
|
+
export interface PlanDeps {
|
|
14
|
+
fetchFn?: typeof fetch;
|
|
15
|
+
checkProviders?: () => ProviderBinaryCheck[];
|
|
16
|
+
editFile?: (path: string) => void;
|
|
17
|
+
/** Overrides stdin TTY detection (wizard auto-trigger). */
|
|
18
|
+
stdinIsTTY?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare function runPlan(args: string[], io?: CliIo, deps?: PlanDeps): Promise<number>;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { chat as libraryChat, type ProgressEvent } from '../providers/index.js';
|
|
2
|
+
import type { BundleSession } from '../providers/bundle.js';
|
|
3
|
+
import type { CliIo } from './common.js';
|
|
4
|
+
import type { PermissionMode } from '../providers/yolo-contract.js';
|
|
5
|
+
/**
|
|
6
|
+
* Hold-open predicate for the receiver's provider turn
|
|
7
|
+
* (BUG-chat-client-death-interrupts-receiver-live-session).
|
|
8
|
+
*
|
|
9
|
+
* The stream-json transport closes the provider child's stdin on the first
|
|
10
|
+
* result event, which makes headless claude exit immediately — orphaning any
|
|
11
|
+
* `run_in_background` dispatches the receiver fired during its turn. The
|
|
12
|
+
* durable "this session still has outstanding dispatched work" signal is an
|
|
13
|
+
* `agent_inflight` row whose SENDER is the receiver's own identity, held by
|
|
14
|
+
* a live pid: every `lmctl prompt` the receiver dispatched acquires exactly
|
|
15
|
+
* such a lease (its sender attribution comes from LMCTL_SELF_SESSIONID in
|
|
16
|
+
* the provider spawn env) and releases it when the dispatched turn
|
|
17
|
+
* finalizes.
|
|
18
|
+
*
|
|
19
|
+
* Predicate scope, deliberately narrow:
|
|
20
|
+
* - DIRECT children only (rows where sender = the session being run),
|
|
21
|
+
* never the transitive subtree. This is sufficient by recursion, not an
|
|
22
|
+
* approximation (operator-confirmed 2026-07-26): a direct child that
|
|
23
|
+
* dispatched further work applies this same holdOpen check before ITS
|
|
24
|
+
* stdin closes, so it holds its own lease — the one we watch — until
|
|
25
|
+
* its children are done. The same fix at every level yields full
|
|
26
|
+
* subtree coverage through one-hop checks; walking deeper would be
|
|
27
|
+
* redundant, not more correct.
|
|
28
|
+
* - live local pid required (`isProcessAlive`): dead-pid and null-pid rows
|
|
29
|
+
* are orphans for the reclaim machinery, not outstanding work — waiting
|
|
30
|
+
* on a corpse would hold the turn open for nothing. agent_inflight has
|
|
31
|
+
* no host column; like the busy check, liveness is judged against the
|
|
32
|
+
* local host (pre-existing remote-holder ambiguity, unchanged here).
|
|
33
|
+
* - the lease for THIS delivery (receiver == the session being run) is
|
|
34
|
+
* excluded — without that guard a self-addressed chat would wait on its
|
|
35
|
+
* own lease until max-hold.
|
|
36
|
+
*
|
|
37
|
+
* Bounding (the "stuck row" question): the real bound is per-poll liveness —
|
|
38
|
+
* a holder that dies or gets reclaimed drops out on the next poll. maxHoldMs
|
|
39
|
+
* (= the agent_inflight TTL, 8h default) is last-resort insurance against a
|
|
40
|
+
* live-but-wedged holder; anything SHORTER would re-introduce the original
|
|
41
|
+
* bug by killing legitimately long dispatched work, and the adapter's idle
|
|
42
|
+
* timer (same 8h default, resolves 'stalled') backstops independently.
|
|
43
|
+
*/
|
|
44
|
+
export declare function buildDispatchHoldOpen(io: CliIo, receiver: LaneIdentity, env: NodeJS.ProcessEnv): NonNullable<Parameters<typeof libraryChat>[0]['holdOpen']>;
|
|
45
|
+
export interface LaneIdentity {
|
|
46
|
+
teamfile: string;
|
|
47
|
+
alias: string;
|
|
48
|
+
}
|
|
49
|
+
export interface LaneDeliveryTarget extends LaneIdentity {
|
|
50
|
+
provider: string;
|
|
51
|
+
sessionId: string;
|
|
52
|
+
cwd: string;
|
|
53
|
+
model?: string;
|
|
54
|
+
effort?: string;
|
|
55
|
+
isLead?: boolean;
|
|
56
|
+
}
|
|
57
|
+
export interface DeliverLaneInput {
|
|
58
|
+
sender: LaneIdentity;
|
|
59
|
+
receiver: LaneDeliveryTarget;
|
|
60
|
+
newMessage: string;
|
|
61
|
+
newMessageFrom?: string;
|
|
62
|
+
io: CliIo;
|
|
63
|
+
permissionMode: PermissionMode;
|
|
64
|
+
env: NodeJS.ProcessEnv;
|
|
65
|
+
idleTimeoutMs?: number;
|
|
66
|
+
/** Multi-turn callers must never fall back to a fresh provider session. */
|
|
67
|
+
requireResume?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Caller-held bundle provider session (batch bundle mode): the turn
|
|
70
|
+
* goes through the already-open provider process. When set, the
|
|
71
|
+
* `holdOpen` below is still built but ignored by the transport — the
|
|
72
|
+
* bundle's persistence IS the hold, and its close() runs the check once.
|
|
73
|
+
*/
|
|
74
|
+
bundleSession?: BundleSession;
|
|
75
|
+
onDelta?: (chunk: string) => void;
|
|
76
|
+
onProgress?: (event: ProgressEvent) => void;
|
|
77
|
+
onPromptBuilt?: (prompt: string) => void | Promise<void>;
|
|
78
|
+
}
|
|
79
|
+
export type DeliverLaneResult = {
|
|
80
|
+
status: 'ok';
|
|
81
|
+
receipt: string;
|
|
82
|
+
prompt: string;
|
|
83
|
+
wroteDelta: boolean;
|
|
84
|
+
durationMs?: number;
|
|
85
|
+
/** Task #232: human-readable strings when the provider silently
|
|
86
|
+
* dropped a declared model=/effort=. Omitted when nothing was dropped. */
|
|
87
|
+
warnings?: string[];
|
|
88
|
+
} | {
|
|
89
|
+
status: 'stalled';
|
|
90
|
+
receipt: string;
|
|
91
|
+
prompt: string;
|
|
92
|
+
wroteDelta: boolean;
|
|
93
|
+
durationMs?: number;
|
|
94
|
+
stalledAfterMs?: number;
|
|
95
|
+
warnings?: string[];
|
|
96
|
+
} | {
|
|
97
|
+
status: 'error';
|
|
98
|
+
receipt: string;
|
|
99
|
+
prompt: string;
|
|
100
|
+
wroteDelta: boolean;
|
|
101
|
+
durationMs?: number;
|
|
102
|
+
error: string;
|
|
103
|
+
};
|
|
104
|
+
export declare function deliverLane(input: DeliverLaneInput): Promise<DeliverLaneResult>;
|
|
105
|
+
export declare function renderQueuedChatPrompt(newPrompt: string, options?: {
|
|
106
|
+
newMessageFrom?: string;
|
|
107
|
+
}): string;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function isHttpsUrl(value: string): boolean;
|
|
2
|
+
export declare function isUrlLike(value: string): boolean;
|
|
3
|
+
export declare function httpsOnlyError(value: string, noun: string): string | null;
|
|
4
|
+
export declare function fetchHttpsBytes(url: string, options: {
|
|
5
|
+
description: string;
|
|
6
|
+
timeoutMs?: number;
|
|
7
|
+
}): Promise<Buffer>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DAL-pure run/attention/escalation read queries shared by the surviving
|
|
3
|
+
* stateless commands (`prompt --run`, `ls --runs`, the MCP mediation core).
|
|
4
|
+
*
|
|
5
|
+
* Relocated verbatim from src/serve/data.ts when the daemon/HTTP surface
|
|
6
|
+
* (`serve`/`api`) moved to lmbee — these helpers import only db types and
|
|
7
|
+
* perform no I/O beyond `dal.query`.
|
|
8
|
+
*/
|
|
9
|
+
import type { AttentionRow, Dal, RunRow } from '../db/index.js';
|
|
10
|
+
export declare function listRuns(dal: Dal, opts?: {
|
|
11
|
+
limit?: number;
|
|
12
|
+
}): RunRow[];
|
|
13
|
+
export declare function listAttentions(dal: Dal, opts?: {
|
|
14
|
+
unacked?: boolean;
|
|
15
|
+
}): AttentionRow[];
|
|
16
|
+
export interface EscalationRow {
|
|
17
|
+
attention_id: number;
|
|
18
|
+
/**
|
|
19
|
+
* Discriminator for the operator response contract. Interactive rows resume
|
|
20
|
+
* an `interactive_session`; workflow escalations are session-free DEF-1
|
|
21
|
+
* decisions and accept only a declared outcome token or `@abort`.
|
|
22
|
+
*/
|
|
23
|
+
kind: string;
|
|
24
|
+
/**
|
|
25
|
+
* Attention severity tier. Historical attention values were error/warn/info-ish.
|
|
26
|
+
*
|
|
27
|
+
* project_issue #37 item 5: `"attn"` is the value used for the new
|
|
28
|
+
* `interactive_waiting_operator` (operator-pause) escalations. It is an
|
|
29
|
+
* intentional new tier — these are NOT errors and NOT warnings; they are
|
|
30
|
+
* operator-attention requests with no provenance baggage. UI/tooling that
|
|
31
|
+
* filters or color-codes by severity should branch on "attn" alongside the
|
|
32
|
+
* pre-existing error/warn/info-ish values.
|
|
33
|
+
*/
|
|
34
|
+
severity: string | null;
|
|
35
|
+
created_at: string;
|
|
36
|
+
project_id: number | null;
|
|
37
|
+
project: string | null;
|
|
38
|
+
run_id: number | null;
|
|
39
|
+
workflow_name: string | null;
|
|
40
|
+
step_id: number | null;
|
|
41
|
+
state_name: string | null;
|
|
42
|
+
prompt: string | null;
|
|
43
|
+
/** Most recent interactive_session row status; null when no session linked. */
|
|
44
|
+
session_status: string | null;
|
|
45
|
+
/**
|
|
46
|
+
* ISO timestamp when the attention was acknowledged; null when still pending.
|
|
47
|
+
* Surfaced so operators using `escalations list --all` can distinguish acked
|
|
48
|
+
* from unacked history. project_issue #45.
|
|
49
|
+
*/
|
|
50
|
+
acknowledged_at: string | null;
|
|
51
|
+
node_path: string[] | null;
|
|
52
|
+
expected_response: {
|
|
53
|
+
kind: string;
|
|
54
|
+
choices: string[] | null;
|
|
55
|
+
} | null;
|
|
56
|
+
transcript_tail: string[] | null;
|
|
57
|
+
paused_at: string | null;
|
|
58
|
+
created_run_inputs: Record<string, unknown> | null;
|
|
59
|
+
workflow_version_id: number | null;
|
|
60
|
+
/**
|
|
61
|
+
* Session-free workflow-escalation context copied from attention.payload.
|
|
62
|
+
* `workflow_escalation` has no interactive_session row, so the JOIN columns
|
|
63
|
+
* above are intentionally null for prompt/step details; SDKs and CLI clients
|
|
64
|
+
* must use these nullable fields to render the human prompt.
|
|
65
|
+
*/
|
|
66
|
+
workflow_step: {
|
|
67
|
+
id: string;
|
|
68
|
+
name: string | null;
|
|
69
|
+
type: string | null;
|
|
70
|
+
} | null;
|
|
71
|
+
escalation_tier: string | null;
|
|
72
|
+
escalation_token: string | null;
|
|
73
|
+
escalation_reason: string | null;
|
|
74
|
+
declared_outcomes: string[] | null;
|
|
75
|
+
agent_output: string | null;
|
|
76
|
+
}
|
|
77
|
+
export declare function listEscalations(dal: Dal, opts?: {
|
|
78
|
+
project?: string;
|
|
79
|
+
all?: boolean;
|
|
80
|
+
since?: string;
|
|
81
|
+
}): EscalationRow[];
|
|
82
|
+
export declare function getEscalation(dal: Dal, attention_id: number): EscalationRow | null;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type CliIo } from './common.js';
|
|
2
|
+
/** Test-only seam: cap the number of `--watch` ticks so tests can exercise
|
|
3
|
+
* the loop without hanging on the SIGINT/SIGTERM shutdown. */
|
|
4
|
+
export declare function _setRunningWatchMaxTicksForTests(maxTicks: number | null): void;
|
|
5
|
+
export declare function runRunning(args: string[], io: CliIo): Promise<number>;
|
package/dist/cli/schema.sql
CHANGED
|
@@ -613,7 +613,13 @@ CREATE TABLE IF NOT EXISTS team_chat_log (
|
|
|
613
613
|
status TEXT NOT NULL,
|
|
614
614
|
error_detail TEXT,
|
|
615
615
|
truncated INTEGER NOT NULL DEFAULT 0,
|
|
616
|
-
created_at TEXT NOT NULL
|
|
616
|
+
created_at TEXT NOT NULL,
|
|
617
|
+
-- v61: batch-vs-individual framing ('batch' for rows belonging to a batch
|
|
618
|
+
-- run, NULL for individual chats). Distinct from
|
|
619
|
+
-- message_pending.message_type (request/response lane semantics).
|
|
620
|
+
-- Appended LAST so a fresh create and a v60->v61 ALTER-upgrade converge on
|
|
621
|
+
-- the same column order (migrate-v32's table_info parity check).
|
|
622
|
+
message_type TEXT CHECK(message_type IN ('batch'))
|
|
617
623
|
);
|
|
618
624
|
CREATE INDEX IF NOT EXISTS idx_team_chat_log_root_time
|
|
619
625
|
ON team_chat_log(root_teamfile, created_at);
|
|
@@ -878,3 +884,16 @@ CREATE TABLE IF NOT EXISTS state_ledger_identity (
|
|
|
878
884
|
instance_id TEXT NOT NULL,
|
|
879
885
|
created_at TEXT NOT NULL
|
|
880
886
|
);
|
|
887
|
+
|
|
888
|
+
-- v61: schema metadata kv. Holds min_reader_version -- the oldest build
|
|
889
|
+
-- schema version that may safely open this db (batch redesign Landing A,
|
|
890
|
+
-- item 0). migrate()'s skew check refuses a newer db only when
|
|
891
|
+
-- min_reader_version exceeds the binary's CURRENT_USER_VERSION; a db without
|
|
892
|
+
-- the marker defaults to its raw user_version (strict, pre-v61 behavior).
|
|
893
|
+
-- v61 is purely additive, so its floor is 60. Additive migrations keep/lower
|
|
894
|
+
-- the floor (INSERT OR IGNORE); breaking ones raise it to their own version.
|
|
895
|
+
CREATE TABLE IF NOT EXISTS schema_meta (
|
|
896
|
+
key TEXT PRIMARY KEY,
|
|
897
|
+
value TEXT NOT NULL
|
|
898
|
+
);
|
|
899
|
+
INSERT OR IGNORE INTO schema_meta (key, value) VALUES ('min_reader_version', '60');
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type CliIo } from './common.js';
|
|
2
|
+
import { type FunctionDoc, type LMScript, type ScriptModule } from '../script/adapter.js';
|
|
3
|
+
export declare function formatFunctionDoc(doc: FunctionDoc): string;
|
|
4
|
+
export declare function formatModuleOverview(engine: LMScript, module: ScriptModule): string;
|
|
5
|
+
export declare function formatCategoryOverview(engine: LMScript): string;
|
|
6
|
+
export declare function runScript(args: string[], io?: CliIo): Promise<number>;
|