@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.
Files changed (182) hide show
  1. package/CHANGELOG.md +116 -0
  2. package/README.md +11 -51
  3. package/data/price-aliases.json +1 -0
  4. package/data/price-data.json +1 -1
  5. package/dist/cli/batch.d.ts +2 -0
  6. package/dist/cli/busy-evidence.d.ts +27 -0
  7. package/dist/cli/chat-cycle.d.ts +59 -0
  8. package/dist/cli/chat-exec.d.ts +83 -0
  9. package/dist/cli/chat-policy.d.ts +22 -0
  10. package/dist/cli/chat.d.ts +23 -0
  11. package/dist/cli/code-resolver.d.ts +8 -0
  12. package/dist/cli/common.d.ts +54 -0
  13. package/dist/cli/context.d.ts +12 -0
  14. package/dist/cli/cost.d.ts +2 -0
  15. package/dist/cli/export.d.ts +2 -0
  16. package/dist/cli/index.d.ts +3 -0
  17. package/dist/cli/index.js +1062 -1400
  18. package/dist/cli/infra.d.ts +78 -0
  19. package/dist/cli/ls.d.ts +2 -0
  20. package/dist/cli/mailbox-cli.d.ts +6 -0
  21. package/dist/cli/managed.d.ts +62 -0
  22. package/dist/cli/mcp-install.d.ts +23 -0
  23. package/dist/cli/mcp.d.ts +2 -0
  24. package/dist/cli/paths.d.ts +50 -0
  25. package/dist/cli/plan-wizard.d.ts +42 -0
  26. package/dist/cli/plan.d.ts +20 -0
  27. package/dist/cli/queue-delivery.d.ts +107 -0
  28. package/dist/cli/ratelimit.d.ts +3 -0
  29. package/dist/cli/remote-fetch.d.ts +7 -0
  30. package/dist/cli/run-queries.d.ts +82 -0
  31. package/dist/cli/running.d.ts +5 -0
  32. package/dist/cli/schema.sql +20 -1
  33. package/dist/cli/script.d.ts +6 -0
  34. package/dist/cli/script.js +2097 -0
  35. package/dist/cli/self-identity.d.ts +25 -0
  36. package/dist/cli/session-idle.d.ts +118 -0
  37. package/dist/cli/status.d.ts +22 -0
  38. package/dist/cli/tail.d.ts +18 -0
  39. package/dist/cli/target-resolver.d.ts +139 -0
  40. package/dist/cli/team-status.d.ts +91 -0
  41. package/dist/cli/teamfile-compat.d.ts +71 -0
  42. package/dist/cli/teamfile-store.d.ts +18 -0
  43. package/dist/cli/teamfile-template.d.ts +40 -0
  44. package/dist/cli/template-env.d.ts +25 -0
  45. package/dist/cli/terminal-lock.d.ts +25 -0
  46. package/dist/cli/terminal.d.ts +23 -0
  47. package/dist/cli/time-filter.d.ts +10 -0
  48. package/dist/cli/update-notifier.d.ts +11 -0
  49. package/dist/cli/version-util.d.ts +2 -0
  50. package/dist/config/seed_templates.d.ts +1 -0
  51. package/dist/db/backfill-event-log.d.ts +26 -0
  52. package/dist/db/delegation.d.ts +37 -0
  53. package/dist/db/escalation_vocab.d.ts +45 -0
  54. package/dist/db/event-log.d.ts +40 -0
  55. package/dist/db/index.d.ts +1213 -0
  56. package/dist/db/inflight-acquire.d.ts +70 -0
  57. package/dist/db/invocation-event-projections.d.ts +65 -0
  58. package/dist/db/ledger-identity.test.d.ts +1 -0
  59. package/dist/db/live-event-projections.d.ts +92 -0
  60. package/dist/db/migrate.d.ts +51 -0
  61. package/dist/db/open-readonly.d.ts +2 -0
  62. package/dist/db/process-liveness.d.ts +37 -0
  63. package/dist/db/sqlite.d.ts +47 -0
  64. package/dist/db/sqlite.test.d.ts +1 -0
  65. package/dist/db/terminal-lock.d.ts +14 -0
  66. package/dist/db/tracked-invocation-reconcile.d.ts +52 -0
  67. package/dist/db/tracked-invocation.d.ts +116 -0
  68. package/dist/mcp/dispatch.d.ts +45 -0
  69. package/dist/mcp/mediation.d.ts +128 -0
  70. package/dist/mcp/path-warning.d.ts +7 -0
  71. package/dist/mcp/server.d.ts +63 -0
  72. package/dist/mcp/tools.d.ts +24 -0
  73. package/dist/providers/adapter.d.ts +265 -0
  74. package/dist/providers/adapters/agy-adapter.d.ts +17 -0
  75. package/dist/providers/adapters/claude-adapter.d.ts +20 -0
  76. package/dist/providers/adapters/codex-adapter.d.ts +22 -0
  77. package/dist/providers/adapters/copilot-adapter.d.ts +16 -0
  78. package/dist/providers/adapters/dsh-adapter.d.ts +89 -0
  79. package/dist/providers/adapters/gemini-adapter.d.ts +44 -0
  80. package/dist/providers/adapters/hermes-adapter.d.ts +71 -0
  81. package/dist/providers/adapters/index.d.ts +35 -0
  82. package/dist/providers/adapters/kimi-adapter.d.ts +16 -0
  83. package/dist/providers/adapters/lmplayer-adapter.d.ts +14 -0
  84. package/dist/providers/adapters/opencode-adapter.d.ts +11 -0
  85. package/dist/providers/adapters/pi-adapter.d.ts +17 -0
  86. package/dist/providers/adapters/print-turn.d.ts +29 -0
  87. package/dist/providers/adapters/qwen-adapter.d.ts +11 -0
  88. package/dist/providers/agy.d.ts +32 -0
  89. package/dist/providers/base-adapter.d.ts +107 -0
  90. package/dist/providers/base.d.ts +12 -0
  91. package/dist/providers/binary-check.d.ts +102 -0
  92. package/dist/providers/bundle.d.ts +118 -0
  93. package/dist/providers/claude-mock.d.ts +90 -0
  94. package/dist/providers/claude.d.ts +21 -0
  95. package/dist/providers/codex-config.d.ts +15 -0
  96. package/dist/providers/codex.d.ts +25 -0
  97. package/dist/providers/config/model-selection-lint.d.ts +45 -0
  98. package/dist/providers/config/team-config.d.ts +183 -0
  99. package/dist/providers/config/types.d.ts +146 -0
  100. package/dist/providers/config/user-config.d.ts +88 -0
  101. package/dist/providers/copilot.d.ts +21 -0
  102. package/dist/providers/debug.d.ts +128 -0
  103. package/dist/providers/dsh-sidecar.d.ts +65 -0
  104. package/dist/providers/dsh-zstd.d.ts +27 -0
  105. package/dist/providers/dsh.d.ts +37 -0
  106. package/dist/providers/frontmatter.d.ts +46 -0
  107. package/dist/providers/gemini-session-reader.d.ts +151 -0
  108. package/dist/providers/gemini.d.ts +39 -0
  109. package/dist/providers/hermes.d.ts +90 -0
  110. package/dist/providers/index.d.ts +421 -0
  111. package/dist/providers/kimi.d.ts +37 -0
  112. package/dist/providers/model-catalog.d.ts +141 -0
  113. package/dist/providers/one-shot-timeout.d.ts +1 -0
  114. package/dist/providers/opencode-config.d.ts +62 -0
  115. package/dist/providers/opencode.d.ts +40 -0
  116. package/dist/providers/parsers/acp.d.ts +47 -0
  117. package/dist/providers/parsers/codex-app-server.d.ts +60 -0
  118. package/dist/providers/parsers/stream-json.d.ts +57 -0
  119. package/dist/providers/passive-readers/agy.d.ts +155 -0
  120. package/dist/providers/passive-readers/copilot.d.ts +173 -0
  121. package/dist/providers/passive-readers/dsh.d.ts +34 -0
  122. package/dist/providers/passive-readers/kimi.d.ts +44 -0
  123. package/dist/providers/passive-readers/opencode.d.ts +89 -0
  124. package/dist/providers/passive-readers/qwen.d.ts +151 -0
  125. package/dist/providers/passive-readers/shared.d.ts +138 -0
  126. package/dist/providers/passive-session-reader.d.ts +188 -0
  127. package/dist/providers/path-utils.d.ts +1 -0
  128. package/dist/providers/pi.d.ts +32 -0
  129. package/dist/providers/pricing.d.ts +107 -0
  130. package/dist/providers/qwen.d.ts +22 -0
  131. package/dist/providers/ratelimit-readings.d.ts +32 -0
  132. package/dist/providers/registry.d.ts +31 -0
  133. package/dist/providers/resume.d.ts +43 -0
  134. package/dist/providers/seed-instruction.d.ts +3 -0
  135. package/dist/providers/self-session-env.d.ts +21 -0
  136. package/dist/providers/session-limit.d.ts +9 -0
  137. package/dist/providers/strip-ansi.d.ts +5 -0
  138. package/dist/providers/transport-errors.d.ts +94 -0
  139. package/dist/providers/transport-lifecycle.d.ts +63 -0
  140. package/dist/providers/transport-wrappers.d.ts +110 -0
  141. package/dist/providers/transports/acp-profiles/config-option-step.d.ts +24 -0
  142. package/dist/providers/transports/acp-profiles/copilot.d.ts +12 -0
  143. package/dist/providers/transports/acp-profiles/gemini.d.ts +22 -0
  144. package/dist/providers/transports/acp-profiles/hermes.d.ts +27 -0
  145. package/dist/providers/transports/acp-profiles/index.d.ts +19 -0
  146. package/dist/providers/transports/acp-profiles/kimi.d.ts +24 -0
  147. package/dist/providers/transports/acp-profiles/opencode.d.ts +26 -0
  148. package/dist/providers/transports/acp-profiles/types.d.ts +258 -0
  149. package/dist/providers/transports/acp-rpc.d.ts +18 -0
  150. package/dist/providers/transports/acp.d.ts +215 -0
  151. package/dist/providers/transports/codex-app-server.d.ts +190 -0
  152. package/dist/providers/transports/hold-open.d.ts +120 -0
  153. package/dist/providers/transports/manager.d.ts +21 -0
  154. package/dist/providers/transports/stream-json.d.ts +162 -0
  155. package/dist/providers/transports/types.d.ts +56 -0
  156. package/dist/providers/types.d.ts +154 -0
  157. package/dist/providers/yolo-contract.d.ts +131 -0
  158. package/dist/script/adapter.d.ts +101 -0
  159. package/dist/script/batch-script.d.ts +7 -0
  160. package/dist/script/index.d.ts +3 -0
  161. package/dist/script/lmscript.d.ts +550 -0
  162. package/dist/shared/policy.d.ts +74 -0
  163. package/dist/shared-lib/db.d.ts +25 -0
  164. package/dist/shared-lib/passive-session-reader.d.ts +2 -0
  165. package/dist/shared-lib/provider-parse.d.ts +6 -0
  166. package/dist/templates/basedir.d.ts +52 -0
  167. package/dist/uri/lmctl_uri.d.ts +38 -0
  168. package/durable-memory/model_selection.md +122 -25
  169. package/examples/README.md +103 -0
  170. package/examples/anonymous-panel.lms +3 -0
  171. package/examples/batch-prompts.txt +9 -0
  172. package/examples/batchscript.lms +67 -0
  173. package/examples/n8n/agent-lib.lms +56 -0
  174. package/examples/n8n/git-lib.lms +93 -0
  175. package/examples/n8n/mock-support.db +0 -0
  176. package/examples/n8n/multi-agent-review.lms +107 -0
  177. package/examples/n8n/news-digest.lms +159 -0
  178. package/examples/n8n/rag-search.lms +163 -0
  179. package/examples/n8n/support-agent.lms +88 -0
  180. package/examples/n8n/ticket-triage.lms +156 -0
  181. package/package.json +13 -17
  182. package/dist/cli/side_effect_classifier.json +0 -19
@@ -0,0 +1,421 @@
1
+ /**
2
+ * Public API surface for the lmctl provider library.
3
+ *
4
+ * Phase A0.4 introduces this facade so A1's engine switch (gated by
5
+ * `LMCTL_USE_LIBRARY_PROVIDER=1`) can `import { chat, seed,
6
+ * listSessions, countTokens } from "../providers/index.js"` and rely on
7
+ * a stable surface even as the internal file layout under
8
+ * `src/providers/` evolves.
9
+ *
10
+ * The four exported functions are thin wrappers around the existing
11
+ * adapter / registry plumbing copied in by A0.1. They do not introduce
12
+ * new behavior; if `chat()` rejects, the rejection comes from the
13
+ * underlying transport (claude / codex / gemini), not from this layer.
14
+ *
15
+ * @module providers
16
+ */
17
+ import type { ProgressEvent, TurnOptions } from "./adapter.js";
18
+ import type { ProviderName, SessionSummary, SessionTokenUsage } from "./types.js";
19
+ import { ProviderRegistry } from "./registry.js";
20
+ import type { BundleSession, BundleSessionOpenOptions } from "./bundle.js";
21
+ /**
22
+ * Test-only escape hatch: drop the cached default registry. Calls to
23
+ * `chat()` / `seed()` / `listSessions()` / `countTokens()` made without
24
+ * an explicit `registry:` field will rebuild on next use.
25
+ */
26
+ export declare function _resetDefaultRegistryForTests(): void;
27
+ /**
28
+ * Options for a single chat turn against an existing native provider session.
29
+ */
30
+ export interface ChatOptions {
31
+ /** Which provider drives the turn. */
32
+ provider: ProviderName;
33
+ /** Native session id to resume. */
34
+ sessionId: string;
35
+ /** Working directory the provider CLI runs in for this turn. */
36
+ cwd: string;
37
+ /** The user prompt sent on this turn. */
38
+ prompt: string;
39
+ /** Optional model override; format is provider-specific (e.g. `claude-sonnet-4-6`). */
40
+ model?: string;
41
+ /** Optional effort / variant override; used by OpenCode ACP. Kimi has no genuine per-turn effort override, so this is unsupported (and warned on) for kimi members. */
42
+ effort?: string;
43
+ /**
44
+ * Idle timeout in ms. Default: 8 hours. `0` disables the timer; when
45
+ * the timer fires the turn resolves with `status: "stalled"` rather
46
+ * than killing the child — see the underlying `TurnResult` doc.
47
+ */
48
+ timeoutMs?: number;
49
+ /** Abort signal for cancellation (caller rejects immediately on abort). */
50
+ signal?: AbortSignal;
51
+ /** Streaming delta callback — every text chunk the provider emits. */
52
+ onDelta?: (text: string) => void;
53
+ /** Classified progress events (tool_use / tool_result / thinking / …). */
54
+ onProgress?: (event: ProgressEvent) => void;
55
+ /** Environment overrides for the spawned provider process. */
56
+ env?: NodeJS.ProcessEnv;
57
+ /** Override the spawned provider binary path (troubleshooting dev builds). */
58
+ progPath?: string;
59
+ /**
60
+ * Teamfile alias of the member being spawned.
61
+ */
62
+ alias?: string;
63
+ /** Role-based Lead signal from teamfile resolution. */
64
+ isLead?: boolean;
65
+ /**
66
+ * Defer end-of-turn shutdown while the session still has outstanding
67
+ * dispatched work of its own. See `TurnOptions.holdOpen`.
68
+ */
69
+ holdOpen?: TurnOptions["holdOpen"];
70
+ /**
71
+ * Permission mode for the turn — `"yolo"` (default) or `"plan"`.
72
+ * Plumbed straight through to the adapter's TurnOptions so the
73
+ * transport rewrites argv / JSON-RPC params per the table in
74
+ * `src/providers/yolo-contract.ts`. Default `"yolo"` preserves
75
+ * the historical contract.
76
+ */
77
+ permissionMode?: import("./yolo-contract.js").PermissionMode;
78
+ /**
79
+ * Fail closed on resume: when `true`, a provider that cannot load the
80
+ * requested `sessionId` MUST error instead of silently creating a NEW
81
+ * session. Currently only meaningful for ACP-transport providers
82
+ * (opencode/kimi/gemini/copilot) — that's the only transport that reads it
83
+ * (see `acp.ts` `session/load` handling); every other provider silently
84
+ * IGNORES it (it is a request for stricter behavior a provider MAY not
85
+ * support, never an error). Omitted/`false` preserves the historical
86
+ * fallback-with-warning behavior. Batch opts in so successive prompts keep
87
+ * their conversation; ordinary chat preserves its existing behavior.
88
+ * Other callers (e.g. a Hermes ACP adapter) may also opt in explicitly.
89
+ *
90
+ * Caveat: a member configured with a custom one-shot `agent=` command routes
91
+ * through `runOneShotAgent`, which bypasses the ACP transport entirely — the
92
+ * flag has no effect there (consistent with "a provider MAY not support it").
93
+ */
94
+ requireResume?: boolean;
95
+ /**
96
+ * Caller-held bundle session (batch bundle mode): when set, this
97
+ * turn goes through the already-open provider process instead of
98
+ * spawning a new one. Spawn-time options (model, effort, env, holdOpen)
99
+ * were fixed at open. See src/providers/bundle.ts for the contract.
100
+ */
101
+ bundleSession?: import("./bundle.js").BundleSession;
102
+ /**
103
+ * Provider-adapter registry. If omitted, a default built from
104
+ * `createAllAdapters()` is reused across calls. Pass an explicit
105
+ * registry when you need custom provider home directories
106
+ * (testing) or a non-default adapter set.
107
+ */
108
+ registry?: ProviderRegistry;
109
+ }
110
+ /**
111
+ * Result of a single chat turn.
112
+ *
113
+ * `text` is the final assistant response (with multi-turn aggregation
114
+ * applied for stream-json — see `joinResultTurns`). `status` is `"ok"`
115
+ * on normal completion, or `"stalled"` when the idle timer fired (the
116
+ * child remains alive; caller decides what to do).
117
+ *
118
+ * Per-turn token usage is NOT returned here — providers persist it to
119
+ * their on-disk session files. Read it with `countTokens()` after.
120
+ */
121
+ export interface ChatResult {
122
+ text: string;
123
+ sessionId: string;
124
+ durationMs: number;
125
+ stopReason?: string;
126
+ numTurns?: number;
127
+ status?: "ok" | "stalled";
128
+ stalledAfterMs?: number;
129
+ /** Human-readable strings when this turn's provider silently dropped a
130
+ * declared model=/effort= (task #232). Omitted when nothing was dropped. */
131
+ warnings?: string[];
132
+ }
133
+ /**
134
+ * Run one chat turn against an existing native session.
135
+ *
136
+ * Delegates to `ProviderAdapter.sendTurn` for the named provider.
137
+ *
138
+ * @param opts - chat call options; see {@link ChatOptions}
139
+ * @param opts.provider - which provider adapter drives the turn
140
+ * (for example `"claude"`, `"codex"`, `"gemini"`, or `"agy"`)
141
+ * @param opts.sessionId - native session id to resume
142
+ * @param opts.cwd - working directory the provider CLI runs in
143
+ * @param opts.prompt - user message sent on this turn
144
+ * @param opts.model - optional provider-specific model override
145
+ * @param opts.timeoutMs - idle timeout in ms (default 8h; 0 disables)
146
+ * @param opts.signal - abort signal; on abort the caller rejects with
147
+ * `Error("Aborted")` while the child gets a graceful-shutdown ladder
148
+ * @param opts.onDelta - streaming text-chunk callback
149
+ * @param opts.onProgress - classified ProgressEvent callback
150
+ * @param opts.env - environment overrides for the spawned child
151
+ * @param opts.progPath - override the spawned binary path (dev builds)
152
+ * @param opts.alias - teamfile alias of the spawning member
153
+ * (Lead-only flows gate on case-insensitive `"lead"`)
154
+ * @param opts.registry - DI for the ProviderRegistry; omit to use the
155
+ * lazily-built default
156
+ * @returns A {@link ChatResult} with the assembled assistant text plus
157
+ * session bookkeeping (durationMs, stopReason, numTurns, status).
158
+ * @throws `Error` (plain) when `opts.provider` is not registered in
159
+ * the supplied (or default) registry — message matches
160
+ * `/not registered/`. {@link TransportConnectionError} if the
161
+ * provider binary cannot be spawned (ENOENT).
162
+ * {@link TransportProcessError} if it exits non-zero before a final
163
+ * result event. {@link TransportJsonError} on malformed wire frames.
164
+ * {@link TransportRpcError} on JSON-RPC errors from codex / gemini
165
+ * app-server. `Error("Aborted")` (plain) on `opts.signal` abort.
166
+ * @example
167
+ * ```ts
168
+ * import { chat } from "../providers/index.js";
169
+ *
170
+ * const result = await chat({
171
+ * provider: "claude",
172
+ * sessionId: "ses-abc",
173
+ * cwd: "/repo",
174
+ * prompt: "summarize the diff",
175
+ * model: "claude-sonnet-4-6",
176
+ * onDelta: (chunk) => process.stdout.write(chunk),
177
+ * });
178
+ * console.log(result.text);
179
+ * ```
180
+ */
181
+ export declare function chat(opts: ChatOptions): Promise<ChatResult>;
182
+ /**
183
+ * Options for opening a bundle session — one provider process serving many
184
+ * prompts (batch bundle mode). The lifecycle contract is in
185
+ * `src/providers/bundle.ts`.
186
+ */
187
+ export interface OpenBundleSessionOptions extends BundleSessionOpenOptions {
188
+ /** Which provider drives the bundle. */
189
+ provider: ProviderName;
190
+ /** Adapter registry override. See {@link ChatOptions.registry}. */
191
+ registry?: ProviderRegistry;
192
+ }
193
+ /**
194
+ * Providers whose adapter implements `openSession` — the bundle-SUPPORTED
195
+ * set for this version (Landing C1: the ACP providers). Distinct from
196
+ * `BUNDLE_CAPABLE_PROVIDERS` in bundle.ts, which is the by-design matrix
197
+ * including the transports a follow-up landing will implement.
198
+ */
199
+ export declare function bundleSupportedProviders(registry?: ProviderRegistry): string[];
200
+ /**
201
+ * Open a bundle session for `opts.provider`. Throws when the provider's
202
+ * adapter has no `openSession` (not bundle-supported in this version).
203
+ */
204
+ export declare function openBundleSession(opts: OpenBundleSessionOptions): Promise<BundleSession>;
205
+ /**
206
+ * Options for bootstrapping a new provider session.
207
+ */
208
+ export interface SeedOptions {
209
+ /** Provider whose CLI will be spawned to create the session. */
210
+ provider: ProviderName;
211
+ /** Working directory where the session-bound subprocess will run. */
212
+ cwd: string;
213
+ /** Optional initial-turn model override. */
214
+ model?: string;
215
+ /** Optional initial-turn effort / variant override. */
216
+ effort?: string;
217
+ /** Optional initial seed prompt; defaults to the standard seed ACK prompt. */
218
+ prompt?: string;
219
+ /** Adapter registry override. See {@link ChatOptions.registry}. */
220
+ registry?: ProviderRegistry;
221
+ }
222
+ /**
223
+ * Result of `seed()`. On success, the on-disk session has been written
224
+ * and is discoverable via `listSessions()`. On failure, `error` carries
225
+ * the human-readable cause; the caller typically falls back to the
226
+ * adapter's `manualSeedHint()`.
227
+ *
228
+ * A0.5 extension (added during A2.1): `sessionId` carries the native
229
+ * session id of the freshly-created session when discovery can match
230
+ * a single new entry against the pre-seed snapshot. Callers that need
231
+ * the id (the engine's `seedMember` does) read it directly; older
232
+ * callers that only checked `success` keep working unchanged.
233
+ *
234
+ * `sessionId` may be omitted (undefined) when:
235
+ * - `success: false`
236
+ * - discovery couldn't isolate a single new session (parallel seed
237
+ * races; corrupt session file; provider that doesn't persist
238
+ * immediately). Callers must defensively fall back to
239
+ * `listSessions()` + their own diff logic in that case.
240
+ */
241
+ export interface SeedResult {
242
+ success: boolean;
243
+ error?: string;
244
+ /** Non-fatal provider diagnostics that callers should surface to the operator. */
245
+ warnings?: string[];
246
+ /** Native session id of the freshly-created session. See doc above. */
247
+ sessionId?: string;
248
+ }
249
+ /**
250
+ * Bootstrap a new native session for the given provider in `cwd`.
251
+ *
252
+ * Delegates to `ProviderAdapter.seed`. The provider spawns its own
253
+ * one-shot seed turn (via the SEED_INITIAL_PROMPT shared across
254
+ * adapters) and the session file lands in the provider's home
255
+ * directory. `listSessions()` will then find it.
256
+ *
257
+ * @param opts - seed call options; see {@link SeedOptions}
258
+ * @param opts.provider - provider whose CLI is spawned
259
+ * (for example `"claude"`, `"codex"`, `"gemini"`, or `"agy"`)
260
+ * @param opts.cwd - working directory the session is bound to
261
+ * @param opts.model - optional initial-turn model override
262
+ * @param opts.registry - DI for the ProviderRegistry; omit to use the
263
+ * lazily-built default
264
+ * @returns {@link SeedResult} — `{success: true, sessionId?}` on
265
+ * success (with the new session id when discovery can isolate one),
266
+ * `{success: false, error}` on failure (error is human-readable
267
+ * and surfaces the adapter / transport reason).
268
+ * @throws `Error` (plain) when `opts.provider` is not registered in
269
+ * the supplied (or default) registry — message matches
270
+ * `/not registered/`. Otherwise the adapter swallows underlying
271
+ * transport / spawn errors into `SeedResult.error` rather than
272
+ * rejecting; an unexpected throw indicates a bug at this layer.
273
+ * @example
274
+ * ```ts
275
+ * import { seed } from "../providers/index.js";
276
+ *
277
+ * const { success, error, sessionId } = await seed({
278
+ * provider: "claude",
279
+ * cwd: "/repo/teams/backend",
280
+ * });
281
+ * if (!success) throw new Error(`seed failed: ${error}`);
282
+ * await persist(sessionId); // engine writes the new id to teamfile
283
+ * ```
284
+ */
285
+ export declare function seed(opts: SeedOptions): Promise<SeedResult>;
286
+ /**
287
+ * Options for enumerating on-disk provider sessions.
288
+ */
289
+ export interface ListSessionsOptions {
290
+ /** Restrict to one provider. Omit to list across all registered providers. */
291
+ provider?: ProviderName;
292
+ /** Filter by canonical workspace path (matches `SessionSummary.cwd`). */
293
+ workspace?: string;
294
+ /** Cap the result count after sorting by `modifiedAt` descending. */
295
+ limit?: number;
296
+ /** Only sessions modified at-or-after this date. */
297
+ from?: Date;
298
+ /** Only sessions modified at-or-before this date. */
299
+ to?: Date;
300
+ /** Adapter registry override. See {@link ChatOptions.registry}. */
301
+ registry?: ProviderRegistry;
302
+ }
303
+ /**
304
+ * Enumerate native provider sessions on disk.
305
+ *
306
+ * Walks the registered providers' session directories
307
+ * (`~/.claude/projects/`, `~/.codex/sessions/`, `~/.gemini/tmp/.../chats/`, ...)
308
+ * via the existing `ProviderRegistry.listAll` plumbing.
309
+ *
310
+ * @param opts - listing options; see {@link ListSessionsOptions}.
311
+ * All fields are optional; omit `opts` entirely to list across every
312
+ * registered provider with no filtering.
313
+ * @param opts.provider - restrict to one provider; omit for all
314
+ * @param opts.workspace - filter by canonical workspace path (matched
315
+ * against `SessionSummary.cwd` via `canonicalPath`)
316
+ * @param opts.limit - cap the result count after newest-first sort
317
+ * @param opts.from - lower bound on `modifiedAt` (inclusive)
318
+ * @param opts.to - upper bound on `modifiedAt` (inclusive)
319
+ * @param opts.registry - DI for the ProviderRegistry; omit to use the
320
+ * lazily-built default
321
+ * @returns Array of {@link SessionSummary} entries, sorted newest-first.
322
+ * @throws Adapter `discover()` calls catch and log most filesystem
323
+ * errors internally (a corrupt session JSONL doesn't fail the whole
324
+ * listing). Unexpected throws bubble up.
325
+ * @example
326
+ * ```ts
327
+ * import { listSessions } from "../providers/index.js";
328
+ *
329
+ * const recent = await listSessions({
330
+ * provider: "claude",
331
+ * workspace: "/repo",
332
+ * limit: 5,
333
+ * });
334
+ * for (const s of recent) console.log(s.sessionId, s.modifiedAt);
335
+ * ```
336
+ */
337
+ export declare function listSessions(opts?: ListSessionsOptions): Promise<SessionSummary[]>;
338
+ /**
339
+ * Options for `countTokens()`.
340
+ */
341
+ export interface CountTokensOptions {
342
+ /** Session id to look up. */
343
+ sessionId: string;
344
+ /**
345
+ * Restrict the lookup to one provider. If omitted, the registry
346
+ * probes every provider in registration order and returns the first
347
+ * match (same semantics as `lmctl info <sessionid>`).
348
+ */
349
+ provider?: ProviderName;
350
+ /** Adapter registry override. See {@link ChatOptions.registry}. */
351
+ registry?: ProviderRegistry;
352
+ }
353
+ /**
354
+ * Aggregate token usage for a single session.
355
+ *
356
+ * `input`, `output`, etc. mirror `SessionSummary.total*Tokens` —
357
+ * cumulative counts across every turn the session has produced. `total`
358
+ * is the sum the provider reports (when available); when only the
359
+ * per-bucket fields are populated, callers can compute `input +
360
+ * cachedInput + cacheWriteInput + output + reasoningOutput`.
361
+ */
362
+ export interface TokenCount {
363
+ /** Provider that owns the session. */
364
+ provider: ProviderName;
365
+ /** Echoed sessionId for round-trip identification. */
366
+ sessionId: string;
367
+ /** Cumulative uncached input tokens. */
368
+ input: number;
369
+ /** Cumulative cache-hit input tokens. */
370
+ cachedInput: number;
371
+ /** Cumulative cache-write input tokens (claude only today). */
372
+ cacheWriteInput: number;
373
+ /** Cumulative output tokens. */
374
+ output: number;
375
+ /** Cumulative reasoning (a.k.a. "thoughts") output tokens. */
376
+ reasoningOutput: number;
377
+ /**
378
+ * Cumulative grand total = sum of the five per-bucket fields above.
379
+ * This is NOT the last-turn total — see `lastTurn.totalTokens`.
380
+ */
381
+ total: number;
382
+ /** Raw last-turn usage snapshot when the session file recorded it. */
383
+ lastTurn?: SessionTokenUsage;
384
+ }
385
+ /**
386
+ * Aggregate token usage for a single session.
387
+ *
388
+ * Loads the session via the registered adapter, then extracts the
389
+ * `total*Tokens` fields the discovery / load pass already computed.
390
+ * Returns zeros for any field the provider did not report — callers
391
+ * MUST treat 0 as "not measured" rather than "free." `total` is the
392
+ * SUM of the five per-bucket fields; for a last-turn snapshot read
393
+ * `lastTurn.totalTokens` instead.
394
+ *
395
+ * @param opts - lookup options; see {@link CountTokensOptions}
396
+ * @param opts.sessionId - native session id (UUID-like)
397
+ * @param opts.provider - restrict to one provider; omit to probe every
398
+ * registered provider in registration order
399
+ * @param opts.registry - DI for the ProviderRegistry; omit to use the
400
+ * lazily-built default
401
+ * @returns {@link TokenCount} populated from the session's persisted
402
+ * token buckets.
403
+ * @throws `Error("session <sessionId> not found")` when no registered
404
+ * provider can resolve the id (message matches `/not found/`).
405
+ * @example
406
+ * ```ts
407
+ * import { countTokens } from "../providers/index.js";
408
+ *
409
+ * const usage = await countTokens({ sessionId: "ses-abc" });
410
+ * console.log(`${usage.input} in / ${usage.output} out`);
411
+ * ```
412
+ */
413
+ export declare function countTokens(opts: CountTokensOptions): Promise<TokenCount>;
414
+ export type { ProviderAdapter } from "./adapter.js";
415
+ export type { ProgressEvent, TurnOptions, TurnResult, } from "./adapter.js";
416
+ export type { ProviderName, SessionSummary, SessionDetail, SessionTokenUsage, ConversationMessage, MessageRole, } from "./types.js";
417
+ export { ProviderRegistry, createAdapterRegistry } from "./registry.js";
418
+ export { createAllAdapters } from "./adapters/index.js";
419
+ export type { BundleSession, BundleSessionOpenOptions, BundleTurnOptions, BundleTurnResult, } from "./bundle.js";
420
+ export { BUNDLE_CAPABLE_PROVIDERS, BUNDLE_NEVER_CAPABLE_PROVIDERS, } from "./bundle.js";
421
+ export { TransportError, TransportConnectionError, TransportProcessError, TransportJsonError, TransportRpcError, } from "./transport-errors.js";
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Kimi Code session provider.
3
+ *
4
+ * Kimi persists an append-only session index plus one self-contained directory
5
+ * per session:
6
+ * $KIMI_CODE_HOME/session_index.jsonl
7
+ * $KIMI_CODE_HOME/sessions/<workspace>/<session>/state.json
8
+ * $KIMI_CODE_HOME/sessions/<workspace>/<session>/agents/main/wire.jsonl
9
+ */
10
+ import type { SessionDetail, SessionProvider, SessionSummary } from "./types.js";
11
+ interface KimiProviderOptions {
12
+ kimiHome?: string;
13
+ }
14
+ export declare class KimiProvider implements SessionProvider {
15
+ name: "kimi";
16
+ private readonly homeDir;
17
+ private readonly sessionsDir;
18
+ constructor(opts?: KimiProviderOptions);
19
+ discoverSessions(): Promise<SessionSummary[]>;
20
+ loadSession(sessionId: string): Promise<SessionDetail | null>;
21
+ resolveSessionPath(sessionId: string): Promise<string | null>;
22
+ deleteSession(sessionId: string): Promise<boolean>;
23
+ getWatchPaths(): {
24
+ directory: string;
25
+ filePattern: RegExp;
26
+ }[];
27
+ private indexPath;
28
+ private sessionFiles;
29
+ private readIndex;
30
+ private filesFor;
31
+ private validSessionDir;
32
+ private findSession;
33
+ private readState;
34
+ private summary;
35
+ private parseWire;
36
+ }
37
+ export {};
@@ -0,0 +1,141 @@
1
+ /**
2
+ * lmprice <-> lmctl integration (approved design v2, section 1) -- the pure
3
+ * model-catalog layer: provider adapters + catalog resolution over an
4
+ * ALREADY-LOADED dataset snapshot (loading/refresh stays in pricing.ts).
5
+ *
6
+ * Identity vs billing route (design review correction #2): the same
7
+ * normalized model id can have divergent priced offers across sources
8
+ * (DeepSeek direct vs gateway rows differ ~2x; `:batch` variants share slugs
9
+ * but price differently). Rows are therefore grouped by adapter-normalized
10
+ * identity into ONE CatalogModel whose `offers` keep every source-qualified
11
+ * row; route preference (first-party > litellm > openrouter > manual) picks
12
+ * the winning row, never a reconciled average.
13
+ *
14
+ * Resolution order in resolveModel() (design section 1, exact):
15
+ * 1. aliases.json exact hit (also probing `<provider>/<declared>`, since
16
+ * the table keys are harness-qualified) -- evidence states honored:
17
+ * established/asserted follow standard_slug -> standards[] ->
18
+ * catalog_record_id pin; `unresolved` or a null standard_slug is
19
+ * TERMINAL (`kimi-code/k3` must never fall through to guessing).
20
+ * 2. Adapter path: normalize(declared) -> candidate ids -> match rows via
21
+ * candidate fields (source_model_id, every path suffix of it -- which
22
+ * covers LiteLLM route prefixes and the last `/`-segment -- and
23
+ * gateway_id where present; lowercased).
24
+ * 3. Miss -> `unknown`.
25
+ */
26
+ import type { PriceRecord } from "./pricing.js";
27
+ export type ResolutionState = {
28
+ kind: "priced";
29
+ model: CatalogModel;
30
+ } | {
31
+ kind: "known-unpriced";
32
+ id: string;
33
+ } | {
34
+ kind: "estimated";
35
+ model: CatalogModel;
36
+ } | {
37
+ kind: "unresolved";
38
+ alias: string;
39
+ } | {
40
+ kind: "unknown";
41
+ declared: string;
42
+ } | {
43
+ kind: "no-catalog";
44
+ };
45
+ export interface CatalogModel {
46
+ id: string;
47
+ normalizedId: string;
48
+ offers: PriceOffer[];
49
+ contextWindow?: number;
50
+ }
51
+ export interface PriceOffer {
52
+ route: string;
53
+ source: string;
54
+ sourceModelId: string;
55
+ provider: string | null;
56
+ pricing: PriceRecord["pricing"];
57
+ estimated: boolean;
58
+ }
59
+ /**
60
+ * The dataset record shape the catalog layer reads. Structurally compatible
61
+ * with pricing.ts's PriceRecord (the extra fields are optional so a slimmed
62
+ * record still satisfies this), but grounded in lmprice's real published
63
+ * schema (record_id / provider / mode / gateway_id / context_window).
64
+ */
65
+ export interface CatalogRecord {
66
+ record_id?: string | null;
67
+ source: string;
68
+ source_model_id: string;
69
+ provider?: string | null;
70
+ mode?: string | null;
71
+ gateway_id?: string | null;
72
+ pricing: PriceRecord["pricing"];
73
+ context_window?: {
74
+ input_tokens?: number | null;
75
+ } | null;
76
+ }
77
+ export interface CatalogDataLike {
78
+ records: CatalogRecord[];
79
+ }
80
+ export type AliasEvidence = "established" | "asserted" | "unresolved";
81
+ export interface AliasStandard {
82
+ standard_slug: string;
83
+ display_name?: string | null;
84
+ vendor?: string | null;
85
+ catalog_record_id: string | null;
86
+ note?: string | null;
87
+ }
88
+ export interface AliasEntry {
89
+ alias: string;
90
+ standard_slug: string | null;
91
+ evidence: AliasEvidence;
92
+ source_url?: string | null;
93
+ note?: string | null;
94
+ }
95
+ export interface AliasTable {
96
+ schema_version: number;
97
+ standards: AliasStandard[];
98
+ aliases: AliasEntry[];
99
+ }
100
+ /**
101
+ * Design section 1 sketches `matchRow(record)`; the implemented signature
102
+ * takes the normalized candidate ids as a second argument because matching
103
+ * is candidates-vs-row-candidate-fields, not a bare regex on the raw id
104
+ * (review correction #3).
105
+ */
106
+ export interface ProviderAdapter {
107
+ matchRow(record: CatalogRecord, candidates: readonly string[]): boolean;
108
+ normalize(declared: string): string[];
109
+ isChatModel(record: CatalogRecord): boolean;
110
+ /** Family + capability membership WITHOUT a candidate check (catalog stats). */
111
+ coversRecord(record: CatalogRecord): boolean;
112
+ }
113
+ /**
114
+ * Providers WITHOUT adapters are skipped (`no-catalog`): copilot, opencode,
115
+ * pi, dsh, lmplayer. dsh/opencode models can still resolve via the aliases
116
+ * table, which is consulted BEFORE the adapter check.
117
+ */
118
+ export declare const PROVIDER_ADAPTERS: Record<string, ProviderAdapter>;
119
+ /**
120
+ * Resolve one declared model string for one provider against a loaded
121
+ * catalog snapshot + alias table. Pure; never throws; no I/O.
122
+ */
123
+ export declare function resolveModel(provider: string, declared: string, data: CatalogDataLike | null, aliases: AliasTable | null): ResolutionState;
124
+ export interface OfferResolution {
125
+ state: ResolutionState;
126
+ /** The offer to price at when the state is priced/estimated, else null. */
127
+ offer: PriceOffer | null;
128
+ /**
129
+ * How the offer was selected: the alias table's catalog_record_id pin
130
+ * when resolution came through aliases, route preference
131
+ * (first-party > litellm > openrouter > manual, first with rates) otherwise.
132
+ */
133
+ provenance: "alias-pin" | "route-preference" | null;
134
+ }
135
+ export declare function resolveOfferForCost(provider: string, declared: string, data: CatalogDataLike | null, aliases: AliasTable | null): OfferResolution;
136
+ /**
137
+ * Count of distinct model identities a provider's adapter covers in this
138
+ * catalog -- the "(N known)" in lint/seed's unknown-model warning. `null`
139
+ * when the provider has no adapter.
140
+ */
141
+ export declare function catalogKnownModelCount(data: CatalogDataLike, provider: string): number | null;
@@ -0,0 +1 @@
1
+ export declare function getOneShotTimeoutMs(env?: NodeJS.ProcessEnv): number;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Opencode `.opencode/opencode.json` permission writer.
3
+ *
4
+ * **YOLO contract via config** (`permission: "allow"`).
5
+ *
6
+ * Opencode's ACP mode does NOT accept the `--dangerously-skip-permissions`
7
+ * argv flag (it's `run`-subcommand-only — empirically verified, see commit
8
+ * log around the opencode06 incident). The only way to satisfy lmctl's
9
+ * YOLO contract for opencode is via the `permission` key in
10
+ * opencode.json. Per the opencode schema:
11
+ * - shorthand `"allow"` → `{ "*": "allow" }` (all tools)
12
+ * - object form → per-tool decisions
13
+ * We use the shorthand.
14
+ *
15
+ * lmctl does NOT inject a provider/model catalog here — models resolve
16
+ * from opencode's own default catalog (models.dev + provider auth) and
17
+ * the user's `~/.config/opencode/opencode.json`. We write only
18
+ * `permission: "allow"`.
19
+ */
20
+ import type { MemberConfig } from "./config/team-config.js";
21
+ import type { McpExecutableWarningOptions } from "../mcp/path-warning.js";
22
+ export declare const OPENCODE_LMCTL_MCP_TIMEOUT_MS = 86400000;
23
+ export declare function buildOpencodeMcpEntry(): Record<string, unknown>;
24
+ /**
25
+ * Predicate: is this `permission` value "effectively allow everything"?
26
+ *
27
+ * Two equivalent shapes per opencode's schema satisfy lmctl's YOLO
28
+ * contract:
29
+ * - the shorthand string `"allow"`
30
+ * - the object form `{ "*": "allow" }` (single wildcard-allow entry)
31
+ *
32
+ * Anything else (`"ask"`, `"deny"`, multi-entry objects with mixed
33
+ * rules, etc.) is a USER OVERRIDE we respect but warn about — turns
34
+ * may hang waiting on permission prompts opencode would otherwise
35
+ * auto-approve.
36
+ */
37
+ export declare function isEffectivelyAllowAll(permission: unknown): boolean;
38
+ export interface OpencodeYoloOverrideFsOps {
39
+ existsSync(path: string): boolean;
40
+ readFileSync(path: string, encoding: BufferEncoding): string;
41
+ }
42
+ export declare function opencodeYoloOverrideWarnings(members: MemberConfig[], baseDir: string, fsOps?: OpencodeYoloOverrideFsOps): string[];
43
+ /**
44
+ * Install or upgrade `<targetDir>/.opencode/opencode.json`.
45
+ *
46
+ * What we write:
47
+ * - `permission: "allow"` — the YOLO contract for opencode.
48
+ *
49
+ * Merge semantics:
50
+ * - If the file is missing, write a fresh one with
51
+ * `{ permission: "allow" }`.
52
+ * - If the file exists, only fill in `permission` when absent;
53
+ * a user-supplied permission value is PRESERVED (user override
54
+ * wins). Existing user MCP entries are preserved untouched. When
55
+ * the user-set value is not effectively allow-all, emit a structured
56
+ * `opencode_yolo_override` warning via errorLog so the operator
57
+ * knows YOLO isn't in effect.
58
+ *
59
+ * Returns true iff the file was written, false if already up-to-date
60
+ * or skipped due to malformed JSON.
61
+ */
62
+ export declare function installOpencodeConfig(targetDir: string, _options?: McpExecutableWarningOptions): boolean;