@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,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;
|