@lmctl-ai/lmctl 0.1.341 → 0.2.2
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 +131 -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 +1081 -1891
- 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 +108 -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,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared "who holds this, and are they alive / how long" evidence for busy/held
|
|
3
|
+
* errors — the same instinct as the #80 terminal busy/held-evidence, factored
|
|
4
|
+
* out so the chat busy-now path and terminal.ts do not each re-derive the
|
|
5
|
+
* live/dead verdict.
|
|
6
|
+
*/
|
|
7
|
+
export type HolderLiveness = 'live' | 'dead' | null;
|
|
8
|
+
export interface BusyHolderEvidence {
|
|
9
|
+
holder_pid: number | null;
|
|
10
|
+
holder_liveness: HolderLiveness;
|
|
11
|
+
/** ISO timestamp the current turn/hold started. */
|
|
12
|
+
since: string;
|
|
13
|
+
/** Wall-clock ms since `since` (time the target has been active) — the
|
|
14
|
+
* "time-since-last-activity" evidence; null when `since` is unparseable. */
|
|
15
|
+
idle_ms: number | null;
|
|
16
|
+
}
|
|
17
|
+
/** live/dead/null verdict for a holder pid — null means "no pid recorded". */
|
|
18
|
+
export declare function holderLiveness(holderPid: number | null): HolderLiveness;
|
|
19
|
+
export declare function busyHolderEvidence(input: {
|
|
20
|
+
holderPid: number | null;
|
|
21
|
+
since: string;
|
|
22
|
+
nowMs?: number;
|
|
23
|
+
}): BusyHolderEvidence;
|
|
24
|
+
/** Human duration via lmformat, e.g. "0s", "45s", "3m 12s", "2h 5m". */
|
|
25
|
+
export declare function formatElapsed(ms: number): string;
|
|
26
|
+
/** Parenthesised evidence suffix: `(active 3m 12s; holder_pid=123, live)`. */
|
|
27
|
+
export declare function formatBusyEvidence(ev: BusyHolderEvidence): string;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Dal } from '../db/index.js';
|
|
2
|
+
export declare const CYCLE_FRESH_WINDOW_MS = 60000;
|
|
3
|
+
/**
|
|
4
|
+
* How many cross-team hops must be SIMULTANEOUSLY IN FLIGHT before a revisit is
|
|
5
|
+
* treated as a runaway loop rather than a normal exchange.
|
|
6
|
+
*
|
|
7
|
+
* WHY THIS IS A HOP COUNT AND NOT A COUNT OF REVISITS. The obvious reading of
|
|
8
|
+
* the name is "how many times has this target already appeared in the chain",
|
|
9
|
+
* but that number can never exceed 1: `ancestorChain` walks parent pointers and
|
|
10
|
+
* breaks on the first node it has already seen, so the chain it returns is
|
|
11
|
+
* DEDUPLICATED. Gating on `priorTargetEntries.length >= 2` would therefore be
|
|
12
|
+
* dead code that disables cycle detection entirely.
|
|
13
|
+
*
|
|
14
|
+
* Counting repeats over time does not work either: `releaseAgentInflight`
|
|
15
|
+
* deletes the row when an exchange completes, so a finished hop leaves no trace
|
|
16
|
+
* here, and the lease forbids two concurrent holds of the same lane. The live
|
|
17
|
+
* table only ever shows what is in flight RIGHT NOW.
|
|
18
|
+
*
|
|
19
|
+
* What that table can tell us is how deep the live cross-team call stack is,
|
|
20
|
+
* and that is the signal that actually separates the two cases:
|
|
21
|
+
*
|
|
22
|
+
* 1 hop — A is holding B, and B messages A back. One outstanding call: a
|
|
23
|
+
* reply, an acknowledgement, a bounded handshake. NOT a loop. This
|
|
24
|
+
* is the case that was being blocked (`lmmol → diagramkit → lmmol`,
|
|
25
|
+
* a 3-node chain), stalling a real cross-team review.
|
|
26
|
+
* 2 hops — A is holding B AND B is holding A, and another cross-team call is
|
|
27
|
+
* being opened on top. Both parties are now blocked inside each
|
|
28
|
+
* other; nothing can unwind. That is a live deadlock, and it is what
|
|
29
|
+
* this mechanism exists to stop.
|
|
30
|
+
*
|
|
31
|
+
* So: one outstanding hop is allowed, two or more is refused. Raising this
|
|
32
|
+
* further would let genuinely stuck stacks keep growing, which is the failure
|
|
33
|
+
* mode the whole check is here to prevent.
|
|
34
|
+
*/
|
|
35
|
+
export declare const CYCLE_MAX_REVISITS = 2;
|
|
36
|
+
export interface ChatCycleNode {
|
|
37
|
+
teamfile: string;
|
|
38
|
+
alias: string;
|
|
39
|
+
}
|
|
40
|
+
export interface DetectCrossTeamCycleInput {
|
|
41
|
+
root: string;
|
|
42
|
+
sender: ChatCycleNode;
|
|
43
|
+
receiverTeamfile: string;
|
|
44
|
+
receiverAlias: string;
|
|
45
|
+
now: Date;
|
|
46
|
+
}
|
|
47
|
+
export interface DetectCrossTeamCycleResult {
|
|
48
|
+
stop: boolean;
|
|
49
|
+
chain: string;
|
|
50
|
+
}
|
|
51
|
+
type ChatCycleDal = Pick<Dal, 'listAgentInflight' | 'clearAgentInflightOlderThan'>;
|
|
52
|
+
export declare function detectCrossTeamCycle(dal: ChatCycleDal, input: DetectCrossTeamCycleInput): DetectCrossTeamCycleResult;
|
|
53
|
+
export declare function deriveRootFromLiveInflight(dal: ChatCycleDal, input: {
|
|
54
|
+
sender: ChatCycleNode;
|
|
55
|
+
now: Date;
|
|
56
|
+
}): string | null;
|
|
57
|
+
export declare function agentInflightTtlMsFromEnv(env?: NodeJS.ProcessEnv): number;
|
|
58
|
+
export declare function crossTeamCycleMessage(chain: string): string;
|
|
59
|
+
export {};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { ProgressEvent } from '../providers/index.js';
|
|
2
|
+
import type { BundleSession } from '../providers/bundle.js';
|
|
3
|
+
import type { PermissionMode } from '../providers/yolo-contract.js';
|
|
4
|
+
import type { AgentInflightInput } from '../db/index.js';
|
|
5
|
+
import { type CliIo } from './common.js';
|
|
6
|
+
export type AiTeamChatEvent = {
|
|
7
|
+
kind: 'delta';
|
|
8
|
+
chunk: string;
|
|
9
|
+
} | {
|
|
10
|
+
kind: 'progress';
|
|
11
|
+
alias: string;
|
|
12
|
+
event: ProgressEvent;
|
|
13
|
+
} | {
|
|
14
|
+
kind: 'warning';
|
|
15
|
+
message: string;
|
|
16
|
+
};
|
|
17
|
+
export type AiTeamChatResult = {
|
|
18
|
+
status: 'ok';
|
|
19
|
+
replyText: string;
|
|
20
|
+
wroteDelta: boolean;
|
|
21
|
+
teamChatLogId: number | null;
|
|
22
|
+
messageId: string | null;
|
|
23
|
+
durationMs?: number;
|
|
24
|
+
} | {
|
|
25
|
+
status: 'stalled';
|
|
26
|
+
replyText: string;
|
|
27
|
+
wroteDelta: boolean;
|
|
28
|
+
teamChatLogId: number | null;
|
|
29
|
+
messageId: string | null;
|
|
30
|
+
durationMs?: number;
|
|
31
|
+
} | {
|
|
32
|
+
status: 'busy';
|
|
33
|
+
message: string;
|
|
34
|
+
teamChatLogId: number | null;
|
|
35
|
+
} | {
|
|
36
|
+
status: 'error';
|
|
37
|
+
errorKind: 'cycle' | 'provider' | 'target';
|
|
38
|
+
message: string;
|
|
39
|
+
teamChatLogId: number | null;
|
|
40
|
+
messageId: string | null;
|
|
41
|
+
};
|
|
42
|
+
export interface ExecuteAiTeamChatTurnInput {
|
|
43
|
+
teamfile: string;
|
|
44
|
+
alias: string;
|
|
45
|
+
prompt: string;
|
|
46
|
+
/** Refuse to dispatch if a multi-turn caller's target session changed. */
|
|
47
|
+
expectedSession?: {
|
|
48
|
+
provider: string;
|
|
49
|
+
sessionid: string;
|
|
50
|
+
};
|
|
51
|
+
permissionMode: PermissionMode;
|
|
52
|
+
idleTimeoutMs?: number;
|
|
53
|
+
rootFlag?: string;
|
|
54
|
+
env?: NodeJS.ProcessEnv;
|
|
55
|
+
/** v61: per-message framing for the team_chat_log row — 'batch' when this
|
|
56
|
+
* turn is one prompt of a `lmctl batch` run; omitted (NULL) otherwise. */
|
|
57
|
+
messageType?: 'batch';
|
|
58
|
+
/**
|
|
59
|
+
* Caller-held in-flight lease (batch bundle mode): the caller
|
|
60
|
+
* acquired the `agent_inflight` lease once for the whole bundle, so this
|
|
61
|
+
* turn skips the receiver busy check AND the acquire/release/heartbeat —
|
|
62
|
+
* they all moved to bundle scope. Instead the turn VERIFIES per prompt
|
|
63
|
+
* that the caller still holds the lease, matched by lease identity AND
|
|
64
|
+
* holder pid (the heartbeat call doubles as a lease-CAS touch); a lost
|
|
65
|
+
* lease fails the turn, aborting the bundle instead of dispatching
|
|
66
|
+
* unsynchronized. The per-turn chat pointer, tracked_invocation, and
|
|
67
|
+
* team_chat_log row are unaffected.
|
|
68
|
+
*/
|
|
69
|
+
heldLease?: {
|
|
70
|
+
row: AgentInflightInput;
|
|
71
|
+
leaseId: string;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Caller-held bundle provider session (batch bundle mode): the turn
|
|
75
|
+
* goes through the already-open provider process. See
|
|
76
|
+
* src/providers/bundle.ts for the lifecycle contract.
|
|
77
|
+
*/
|
|
78
|
+
bundleSession?: BundleSession;
|
|
79
|
+
io: CliIo;
|
|
80
|
+
onEvent?: (event: AiTeamChatEvent) => void;
|
|
81
|
+
onAccepted?: (messageId: string) => void;
|
|
82
|
+
}
|
|
83
|
+
export declare function executeAiTeamChatTurn(input: ExecuteAiTeamChatTurnInput): Promise<AiTeamChatResult>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface ChatPolicyTeam {
|
|
2
|
+
teamfile: string;
|
|
3
|
+
aliases: readonly string[];
|
|
4
|
+
leadAlias: string | null;
|
|
5
|
+
}
|
|
6
|
+
export interface ChatPolicyRegistry {
|
|
7
|
+
teams: readonly ChatPolicyTeam[];
|
|
8
|
+
}
|
|
9
|
+
export interface CanSendInput {
|
|
10
|
+
rootTeamfile: string;
|
|
11
|
+
fromTeamfile: string;
|
|
12
|
+
fromAlias: string;
|
|
13
|
+
toTeamfile: string;
|
|
14
|
+
toAlias: string;
|
|
15
|
+
registry: ChatPolicyRegistry;
|
|
16
|
+
}
|
|
17
|
+
export interface CanSendResult {
|
|
18
|
+
allowed: boolean;
|
|
19
|
+
reason: string;
|
|
20
|
+
outOfPolicy: boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare function canSend(input: CanSendInput): CanSendResult;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type CliIo } from './common.js';
|
|
2
|
+
export declare function runChat(args: string[], io?: CliIo): Promise<number>;
|
|
3
|
+
/**
|
|
4
|
+
* Resolve `--prompt-file` to the prompt text. Reads the file (or stdin for
|
|
5
|
+
* `-`) as UTF-8 and returns it byte-for-byte EXCEPT for exactly one trailing
|
|
6
|
+
* newline, which is stripped so `--prompt-file f` matches what the author sees
|
|
7
|
+
* in the editor (files conventionally end with a newline). A CRLF terminator
|
|
8
|
+
* counts as that one newline.
|
|
9
|
+
*
|
|
10
|
+
* No shell is involved at any point, which is the entire purpose.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolvePromptInput(promptFile: string, io: CliIo, stdin?: NodeJS.ReadableStream): Promise<string | {
|
|
13
|
+
error: string;
|
|
14
|
+
}>;
|
|
15
|
+
/**
|
|
16
|
+
* Parse `--idle-timeout <duration>` per lmctl0 grammar: `<n>(s|m|h|d)`,
|
|
17
|
+
* a bare integer >= 1000 (raw milliseconds), or `0` (disables the timer —
|
|
18
|
+
* libraryChat semantics). A bare integer under 1000 is refused (see inline
|
|
19
|
+
* comment) rather than silently treated as milliseconds — always give an
|
|
20
|
+
* explicit unit for anything meant as seconds. Returns ms (number), or an
|
|
21
|
+
* error string the caller surfaces verbatim. Pure.
|
|
22
|
+
*/
|
|
23
|
+
export declare function parseIdleTimeoutMs(value: string): number | string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Dal, ProjectRow, TeamMemberRow, TeamRow } from '../db/index.js';
|
|
2
|
+
import { type CliIo } from './common.js';
|
|
3
|
+
export interface ProjectResolvingIo extends CliIo {
|
|
4
|
+
cwd?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function resolveProject(io: ProjectResolvingIo, dal: Dal, override?: string): ProjectRow | number;
|
|
7
|
+
export declare function resolveTeam(io: ProjectResolvingIo, dal: Dal, project: ProjectRow, override?: string): TeamRow | number;
|
|
8
|
+
export declare function resolveAlias(io: ProjectResolvingIo, dal: Dal, team: TeamRow, override?: string): TeamMemberRow | number;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type Dal } from '../db/index.js';
|
|
2
|
+
export interface CliWriter {
|
|
3
|
+
write(chunk: string): unknown;
|
|
4
|
+
}
|
|
5
|
+
export interface CliReader {
|
|
6
|
+
isTTY?: boolean;
|
|
7
|
+
setEncoding?(encoding: BufferEncoding): unknown;
|
|
8
|
+
resume?(): unknown;
|
|
9
|
+
pause?(): unknown;
|
|
10
|
+
once(event: 'data', listener: (chunk: string | Buffer) => void): unknown;
|
|
11
|
+
}
|
|
12
|
+
export interface CliIo {
|
|
13
|
+
stdout: CliWriter;
|
|
14
|
+
stderr: CliWriter;
|
|
15
|
+
stdin?: CliReader;
|
|
16
|
+
dal?: Dal;
|
|
17
|
+
cwd?: string;
|
|
18
|
+
env?: NodeJS.ProcessEnv;
|
|
19
|
+
}
|
|
20
|
+
export interface ParsedFlags {
|
|
21
|
+
positionals: string[];
|
|
22
|
+
flags: Record<string, string | boolean>;
|
|
23
|
+
error?: string;
|
|
24
|
+
}
|
|
25
|
+
export declare function withDal<T>(io: CliIo, fn: (dal: Dal) => Promise<T> | T): Promise<T>;
|
|
26
|
+
export declare function parseFlags(args: string[], valueFlags: string[], boolFlags?: string[]): ParsedFlags;
|
|
27
|
+
export declare function flagString(parsed: ParsedFlags, name: string): string | undefined;
|
|
28
|
+
export declare function flagBool(parsed: ParsedFlags, name: string): boolean;
|
|
29
|
+
export declare function writeJson(io: CliIo, value: unknown): void;
|
|
30
|
+
export declare function userError(io: CliIo, message: string): number;
|
|
31
|
+
/** Local wall-clock `HH:MM:SS` for progress-narration lines (batch, and any
|
|
32
|
+
* command whose stderr narration benefits from a when-did-this-happen marker
|
|
33
|
+
* without a full date). */
|
|
34
|
+
export declare function hhmmss(): string;
|
|
35
|
+
/** Silence-aware heartbeat for waits that can run long (provider seed spawn,
|
|
36
|
+
* a multi-minute chat turn, a batch prompt). Writes `renderLine(elapsedSeconds)`
|
|
37
|
+
* to stderr every `intervalMs`, but SKIPS the tick when `poke()` was called
|
|
38
|
+
* within the last interval -- streaming events already tell the user work is
|
|
39
|
+
* happening, so only true silence earns a "still running" line. The timer is
|
|
40
|
+
* unref'd; callers must `stop()` in a finally. */
|
|
41
|
+
export declare function startSilenceHeartbeat(io: CliIo, renderLine: (elapsedSeconds: number) => string, intervalMs?: number): {
|
|
42
|
+
poke: () => void;
|
|
43
|
+
stop: () => void;
|
|
44
|
+
};
|
|
45
|
+
export declare function internalError(io: CliIo, error: unknown): number;
|
|
46
|
+
/** Reads the LMCTL_INVOCATION_ID env var a parent turn's own dispatch set on
|
|
47
|
+
* this process -- the dispatch-lineage edge `lmctl running --tree` walks.
|
|
48
|
+
* Malformed/absent -> null (this dispatch is a root, e.g. a human's direct
|
|
49
|
+
* `lmctl prompt`/`lmctl terminal`). Shared by chat-exec.ts and terminal.ts,
|
|
50
|
+
* the two places a tracked_invocation row gets created. */
|
|
51
|
+
export declare function parseInvocationIdEnv(value: string | undefined): number | null;
|
|
52
|
+
export declare function installStdoutEpipeGuard(io: CliIo): void;
|
|
53
|
+
/** Test-only: reset the once-flag so install behaviour can be asserted. */
|
|
54
|
+
export declare function _resetStdoutEpipeGuardForTests(): void;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Dal, ProjectRow } from '../db/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Walk from `cwd` (and each ancestor up to the filesystem root) looking
|
|
4
|
+
* for a project whose `local_path` is that exact path. Returns the first
|
|
5
|
+
* hit, or `null` when none match.
|
|
6
|
+
*
|
|
7
|
+
* Path comparison is exact-string after `resolve()` normalization on
|
|
8
|
+
* both the query path and the DB value. On Linux + WSL2 (per § 12 of the
|
|
9
|
+
* design decisions) we don't normalize case or separators beyond what
|
|
10
|
+
* `node:path` provides.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveActiveProject(cwd: string, dal: Dal): ProjectRow | null;
|