@lmctl-ai/lmctl 0.2.20 → 0.2.21

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.
@@ -0,0 +1,2 @@
1
+ export declare function seedInProgress(teamfile: string, alias: string): boolean;
2
+ export declare function beginSeedFlight(teamfile: string, alias: string): () => void;
@@ -1,5 +1,5 @@
1
1
  import { BaseProviderAdapter } from "../base-adapter.js";
2
- import type { SeedOptions } from "../adapter.js";
2
+ import type { SeedOptions, SeedResult } from "../adapter.js";
3
3
  export declare function createAgyAdapter(opts?: {
4
4
  agyDir?: string;
5
5
  }): AgyAdapter;
@@ -8,6 +8,7 @@ declare class AgyAdapter extends BaseProviderAdapter {
8
8
  agyDir?: string;
9
9
  });
10
10
  protected seedArgsFor(opts?: SeedOptions): string[];
11
+ seed(cwd: string, opts?: SeedOptions): Promise<SeedResult>;
11
12
  manualSeedHint(sessiondir: string): {
12
13
  launchCommand: string;
13
14
  postLaunchNote: string;
@@ -36,6 +36,8 @@ export interface BaseAdapterConfig {
36
36
  binary: string;
37
37
  /** Args for seeding a new session with the explicit seed instruction. */
38
38
  seedArgs: string[];
39
+ /** Process timeout for the one-shot seed command. */
40
+ seedTimeoutMs?: number;
39
41
  /** If seed input should be sent via stdin instead of args. */
40
42
  seedStdin?: string;
41
43
  /** Default resume command template. {{session_id}} is replaced. */
@@ -54,6 +56,7 @@ export declare class BaseProviderAdapter implements ProviderAdapter {
54
56
  protected provider: SessionProvider;
55
57
  protected binary: string;
56
58
  protected seedArgs: string[];
59
+ protected seedTimeoutMs: number;
57
60
  protected seedStdin?: string;
58
61
  protected resumeTemplate: string;
59
62
  protected startTemplate: string;
@@ -32,4 +32,3 @@ export declare function catalogModelWarnings(members: MemberConfig[], opts?: {
32
32
  export declare function catalogModelErrors(members: MemberConfig[], opts?: {
33
33
  snapshot?: CatalogSnapshot;
34
34
  }): Promise<TeamValidationError[]>;
35
- export declare function resolveModelSelectionDocPathFromHere(here: string): string;
@@ -335,6 +335,8 @@ export interface ListSessionsOptions {
335
335
  * ```
336
336
  */
337
337
  export declare function listSessions(opts?: ListSessionsOptions): Promise<SessionSummary[]>;
338
+ /** Delete one native session from a known provider. */
339
+ export declare function deleteSession(provider: ProviderName, sessionId: string, registry?: ProviderRegistry): Promise<boolean>;
338
340
  /**
339
341
  * Options for `countTokens()`.
340
342
  */
@@ -0,0 +1,21 @@
1
+ type CommandResult = {
2
+ status: number | null;
3
+ stdout?: string;
4
+ error?: NodeJS.ErrnoException;
5
+ };
6
+ type CommandRunner = (timeoutMs: number, env: NodeJS.ProcessEnv) => CommandResult;
7
+ type HttpResult = {
8
+ status: number;
9
+ body: string;
10
+ };
11
+ type HttpRunner = (url: string, headers: Record<string, string>, timeoutMs: number) => Promise<HttpResult>;
12
+ /** Test seam; production callers should use readAgy. */
13
+ export declare function _setAgyDepsForTests(deps: {
14
+ command?: CommandRunner;
15
+ http?: HttpRunner;
16
+ } | null): void;
17
+ export declare function readAgy(options: {
18
+ timeoutSeconds: number;
19
+ env: NodeJS.ProcessEnv;
20
+ }): Promise<Record<string, unknown>>;
21
+ export {};
@@ -0,0 +1,5 @@
1
+ export interface ClaudeReadOptions {
2
+ timeoutSeconds: number;
3
+ env: NodeJS.ProcessEnv;
4
+ }
5
+ export declare function readClaude({ timeoutSeconds, env }: ClaudeReadOptions): Promise<Record<string, unknown>>;
@@ -0,0 +1,6 @@
1
+ type JsonObject = Record<string, unknown>;
2
+ export declare function readCodex(options: {
3
+ timeoutSeconds: number;
4
+ env: NodeJS.ProcessEnv;
5
+ }): Promise<JsonObject>;
6
+ export {};
@@ -0,0 +1,5 @@
1
+ export interface KimiReadOptions {
2
+ timeoutSeconds: number;
3
+ env: NodeJS.ProcessEnv;
4
+ }
5
+ export declare function readKimi({ timeoutSeconds, env }: KimiReadOptions): Promise<Record<string, unknown>>;
@@ -0,0 +1,14 @@
1
+ /** Wire format shared by the in-process subscription quota readers. */
2
+ export declare const SCHEMA_URL = "https://lmctl.com/schemas/lmratelimit-v1.json";
3
+ export declare function clampFraction(value: unknown): number | null;
4
+ export declare function toFraction(value: unknown, scale: 'fraction' | 'percent'): number | null;
5
+ export declare function isoFromEpoch(value: unknown): string | null;
6
+ export declare function epochFromIso(value: unknown): number | null;
7
+ export declare function windowTypeFromMinutes(value: unknown): string;
8
+ export declare function windowTypeFromLabel(value: unknown): string;
9
+ export declare function windowSuffix(type: string): string;
10
+ export declare function redact(value: unknown, secrets?: Iterable<string | null | undefined>): string;
11
+ export declare function makeBucket(fields: Record<string, unknown>): Record<string, unknown>;
12
+ export declare function makeReading(provider: string, status: string, fields?: Record<string, unknown>): Record<string, unknown>;
13
+ export declare function errorReading(provider: string, status: string, reason: string, detail?: unknown, source?: string, secrets?: Iterable<string | null | undefined>, retryAfterSeconds?: number | null): Record<string, unknown>;
14
+ export declare function parseRetryAfter(headers: Headers): number | null;
@@ -1,19 +1,4 @@
1
1
  export declare const VALID_RATELIMIT_TARGETS: readonly ["all", "codex", "agy", "claude", "kimi"];
2
- export interface RatelimitRunResult {
3
- status: number | null;
4
- stdout: string;
5
- stderr: string;
6
- signal?: string | null;
7
- error?: (Error & {
8
- code?: string;
9
- }) | undefined;
10
- }
11
- export type RatelimitRunner = (bin: string, args: string[], timeoutMs: number) => RatelimitRunResult;
12
- export interface RatelimitFsDeps {
13
- exists(path: string): boolean;
14
- }
15
- export declare function _setRatelimitRunnerForTests(fn: RatelimitRunner | null): void;
16
- export declare function _setRatelimitFsDepsForTests(deps: Partial<RatelimitFsDeps> | null): void;
17
2
  export interface RatelimitReadingsOptions {
18
3
  providers?: string[];
19
4
  targets?: string[];
@@ -29,4 +14,4 @@ export type RatelimitReadingsResult = {
29
14
  error: string;
30
15
  readings: [];
31
16
  };
32
- export declare function queryRatelimitReadings(options?: RatelimitReadingsOptions): RatelimitReadingsResult;
17
+ export declare function queryRatelimitReadings(options?: RatelimitReadingsOptions): Promise<RatelimitReadingsResult>;
@@ -1,18 +1,22 @@
1
1
  # Book Team
2
2
 
3
- # Use this team for long-form writing projects. Lead keeps the outline and
4
- # acceptance criteria current, then coordinates drafting, editing, and factual
5
- # checks. Keep chapter plans and decisions in durable-memory/ so refreshed
6
- # sessions can recover the book state.
7
- # Suggested flow:
8
- # lmctl chat book-team.lmctl Lead "Draft chapter 1 from durable-memory/outline.md"
3
+ # Use this team for long-form writing projects. A suggested way to USE it: keep
4
+ # the outline and acceptance criteria in durable-memory/, then prompt members in
5
+ # turn for drafting, editing and factual checks. Keep chapter plans and
6
+ # decisions in durable-memory/ so refreshed sessions can recover the book state.
7
+ # You drive that sequence -- prompt each member:
8
+ # lmctl prompt book-team.lmctl Drafter "Draft chapter 1 from durable-memory/outline.md"
9
9
  #
10
- # lmctl chat is synchronous but does not always wait for a reply: when the
11
- # receiver is free the message is delivered and chat blocks for the reply; when
12
- # the receiver is BUSY the message is enqueued and chat returns immediately.
13
- # Both cases exit 0, so exit code alone cannot tell you a reply arrived.
14
- # Check with --json: status="ok" is a delivered reply (with replyText),
15
- # status="enqueued" means it was queued. lmctl status shows pending lanes.
10
+ # ALIASES ARE NAMES, NOT CAPABILITIES. Every alias below is a label you chose.
11
+ # lmctl gives none of them any power the others lack, and a seeded member is
12
+ # told only to establish its session -- it does not know lmctl exists or that
13
+ # the other members are there. The difference between them is how YOU use them.
14
+ # To let one send prompts to others, paste that guidance into its session
15
+ # yourself; give the same text to any other member and it can do it too.
16
+ #
17
+ # lmctl prompt blocks until the member replies. If the member is already running
18
+ # a turn you get "<alias> is busy; wait and retry" -- nothing is held for you,
19
+ # so retrying is the caller's job.
16
20
  #
17
21
  # For async, lmctl is foreground/background agnostic: wrap the same command in
18
22
  # your provider or host runtime's native background facility (e.g. Claude
@@ -1,18 +1,22 @@
1
1
  # Research Team
2
2
 
3
- # Use this team when the operator needs a researched answer with clear caveats.
4
- # Lead owns the final answer. Delegate independent passes to the researchers,
5
- # ask Critic to identify weak evidence or contradictions, then have Synthesizer
6
- # merge the strongest findings into a concise response.
7
- # Suggested flow:
8
- # lmctl chat research-team.lmctl Lead "Research <question>"
3
+ # Use this team when you need a researched answer with clear caveats. A
4
+ # suggested way to USE it: ask each researcher for an independent pass, ask
5
+ # Critic to find weak evidence or contradictions, then ask Synthesizer to merge
6
+ # the strongest findings. You drive that sequence -- prompt each member:
7
+ # lmctl prompt research-team.lmctl Researcher1 "Research <question>"
8
+ # lmctl prompt research-team.lmctl Critic "Find weak evidence in <path>"
9
9
  #
10
- # lmctl chat is synchronous but does not always wait for a reply: when the
11
- # receiver is free the message is delivered and chat blocks for the reply; when
12
- # the receiver is BUSY the message is enqueued and chat returns immediately.
13
- # Both cases exit 0, so exit code alone cannot tell you a reply arrived.
14
- # Check with --json: status="ok" is a delivered reply (with replyText),
15
- # status="enqueued" means it was queued. lmctl status shows pending lanes.
10
+ # ALIASES ARE NAMES, NOT CAPABILITIES. Every alias below is a label you chose.
11
+ # lmctl gives none of them any power the others lack, and a seeded member is
12
+ # told only to establish its session -- it does not know lmctl exists or that
13
+ # the other members are there. The difference between them is how YOU use them.
14
+ # To let one send prompts to others, paste that guidance into its session
15
+ # yourself; give the same text to any other member and it can do it too.
16
+ #
17
+ # lmctl prompt blocks until the member replies. If the member is already running
18
+ # a turn you get "<alias> is busy; wait and retry" -- nothing is held for you,
19
+ # so retrying is the caller's job.
16
20
  #
17
21
  # For async, lmctl is foreground/background agnostic: wrap the same command in
18
22
  # your provider or host runtime's native background facility (e.g. Claude
@@ -1,18 +1,23 @@
1
1
  # Review Team
2
2
 
3
- # Use this team for implementation tasks that need independent review. Lead
4
- # sends implementation work to Author, asks Reviewer1 and Reviewer2 for separate
5
- # reviews, asks SecurityReviewer for trust-boundary concerns when relevant, and
6
- # routes findings back to Author before final signoff.
7
- # Suggested flow:
8
- # lmctl chat review-team.lmctl Lead "Implement <task> and get review signoff"
3
+ # Use this team for implementation tasks that need independent review. A
4
+ # suggested way to USE it: send implementation work to Author, ask Reviewer1 and
5
+ # Reviewer2 for separate reviews, ask SecurityReviewer about trust boundaries
6
+ # when relevant, then send the findings back to Author before signoff.
7
+ # You drive that sequence -- prompt each member yourself:
8
+ # lmctl prompt review-team.lmctl Author "Implement <task>"
9
+ # lmctl prompt review-team.lmctl Reviewer1 "Review the change in <path>"
9
10
  #
10
- # lmctl chat is synchronous but does not always wait for a reply: when the
11
- # receiver is free the message is delivered and chat blocks for the reply; when
12
- # the receiver is BUSY the message is enqueued and chat returns immediately.
13
- # Both cases exit 0, so exit code alone cannot tell you a reply arrived.
14
- # Check with --json: status="ok" is a delivered reply (with replyText),
15
- # status="enqueued" means it was queued. lmctl status shows pending lanes.
11
+ # ALIASES ARE NAMES, NOT CAPABILITIES. Every alias below is a label you chose.
12
+ # lmctl gives none of them any power the others lack, and a seeded member is
13
+ # told only to establish its session -- it does not know lmctl exists or that
14
+ # the other members are there. The difference between them is how YOU use them.
15
+ # To let one send prompts to others, paste that guidance into its session
16
+ # yourself; give the same text to any other member and it can do it too.
17
+ #
18
+ # lmctl prompt blocks until the member replies. If the member is already running
19
+ # a turn you get "<alias> is busy; wait and retry" -- nothing is held for you,
20
+ # so retrying is the caller's job.
16
21
  #
17
22
  # For async, lmctl is foreground/background agnostic: wrap the same command in
18
23
  # your provider or host runtime's native background facility (e.g. Claude
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lmctl-ai/lmctl",
3
- "version": "0.2.20",
3
+ "version": "0.2.21",
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",
@@ -21,7 +21,6 @@
21
21
  "dist/**/*.d.ts",
22
22
  "dist/cli/schema.sql",
23
23
  "dist/config/",
24
- "durable-memory/model_selection.md",
25
24
  "data/price-data.json",
26
25
  "data/price-aliases.json",
27
26
  "workflows/",
@@ -38,7 +37,7 @@
38
37
  "license": "SEE LICENSE IN LICENSE",
39
38
  "publishConfig": {
40
39
  "access": "public",
41
- "tag": "latest"
40
+ "tag": "staging"
42
41
  },
43
42
  "dependencies": {},
44
43
  "optionalDependencies": {}