@khorsheed/dsh-local-agent-claude-code 0.1.0-rc.6

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 (38) hide show
  1. package/README.en.md +120 -0
  2. package/README.i18n.yaml +6 -0
  3. package/README.md +120 -0
  4. package/cordis.patch.yml +42 -0
  5. package/lib/client.js +1065 -0
  6. package/lib/index.js +3771 -0
  7. package/lib/invariant.js +31 -0
  8. package/lib/types/claude-cli-provider.d.ts +389 -0
  9. package/lib/types/claude-cli-provider.js +1509 -0
  10. package/lib/types/client/SettingsCard.d.ts +78 -0
  11. package/lib/types/client/SettingsCard.js +198 -0
  12. package/lib/types/client/icons.d.ts +18 -0
  13. package/lib/types/client/icons.js +2 -0
  14. package/lib/types/client/index.d.ts +36 -0
  15. package/lib/types/client/index.js +87 -0
  16. package/lib/types/client/locales.d.ts +64 -0
  17. package/lib/types/client/locales.js +55 -0
  18. package/lib/types/control-requests.d.ts +15 -0
  19. package/lib/types/control-requests.js +62 -0
  20. package/lib/types/index.d.ts +81 -0
  21. package/lib/types/index.js +300 -0
  22. package/lib/types/invariant.d.ts +16 -0
  23. package/lib/types/invariant.js +33 -0
  24. package/lib/types/live-driver.d.ts +172 -0
  25. package/lib/types/live-driver.js +1057 -0
  26. package/lib/types/live-switch.d.ts +67 -0
  27. package/lib/types/live-switch.js +85 -0
  28. package/lib/types/model-broker.d.ts +131 -0
  29. package/lib/types/model-broker.js +248 -0
  30. package/lib/types/model-catalog.d.ts +27 -0
  31. package/lib/types/model-catalog.js +118 -0
  32. package/lib/types/provision.d.ts +63 -0
  33. package/lib/types/provision.js +132 -0
  34. package/lib/types/records.d.ts +120 -0
  35. package/lib/types/records.js +687 -0
  36. package/locale/en.json +6 -0
  37. package/locale/zh.json +6 -0
  38. package/package.json +106 -0
@@ -0,0 +1,31 @@
1
+ //#region lib/types/invariant.js
2
+ /**
3
+ * Package-owned invariant companion for `@khorsheed/dsh-local-agent-claude-code`.
4
+ * @module @khorsheed/dsh-local-agent-claude-code/invariant
5
+ */
6
+ const PACKAGE_NAME = "@khorsheed/dsh-local-agent-claude-code";
7
+ /** Cordis companion plugin name. */
8
+ const name = "local-agent-claude-code-invariant";
9
+ /** Service required before the companion can reserve package ownership. */
10
+ const inject = ["invariants"];
11
+ /**
12
+ * The claude-code harness definition is this bundle's contract with the core
13
+ * registry: whenever a `claude-code` harness registers, its scoped-home
14
+ * variable must be the one this bundle pins.
15
+ */
16
+ const install = (ctx, fail) => {
17
+ ctx.on("internal/dispatch", (_mode, eventName, args) => {
18
+ if (eventName !== "localAgent/harness-added") return;
19
+ const harness = args[0];
20
+ if (harness.name !== "claude-code") return;
21
+ if (harness.homeEnvVar !== "CLAUDE_CONFIG_DIR") fail("claude-code harness registered with a home env other than the local-agent-claude-code contract");
22
+ }, { global: true });
23
+ };
24
+ /**
25
+ * Register this package's invariant companion.
26
+ * @param ctx - plugin context carrying the invariant registry.
27
+ * @returns the installed registration's disposer.
28
+ */
29
+ const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
30
+ //#endregion
31
+ export { apply, inject, name };
@@ -0,0 +1,389 @@
1
+ /**
2
+ * One-shot Claude Code CLI subagent lifecycle: spawn `claude -p "<task>"`
3
+ * through the subprocess seam under the harness's scoped home, capture its
4
+ * JSON result as the run output, and dispose to whole-tree quiescence.
5
+ * Mirrors the kimi/codex providers: every accepted run is a fresh process
6
+ * and a fresh claude session; there is no continuation across runs.
7
+ *
8
+ * The provider name `claude-local` avoids colliding with the official
9
+ * `subagent-claude-code` package's provider name `claude-code` — a
10
+ * composition that mounts both would fail loud with DUPLICATE_PROVIDER. The
11
+ * tool row in this bundle's patch takes the official model-facing name
12
+ * `subagent_claude_code` instead: the official preset row ships disabled,
13
+ * and the patch disables it too (a deliberate user re-enable conflicts
14
+ * loud, by design).
15
+ * @module @khorsheed/dsh-local-agent-claude-code/claude-cli-provider
16
+ */
17
+ import type { ContentBlock, TokenUsage } from '@deepseek-ai/dsh-llm';
18
+ import type { TodoItem } from '@deepseek-ai/dsh-tool-todo';
19
+ import { type ResolvedSubagentStartRequest, type SubagentCapabilities, type SubagentProvider, type SubagentRun, type SubagentStartRequest, type SubagentStopReason } from '@deepseek-ai/dsh-subagent';
20
+ import type { Context } from '@deepseek-ai/cordis';
21
+ import type { Session } from '@deepseek-ai/dsh-session';
22
+ import type { SubprocessHandle, SubprocessSpawnSpec } from '@deepseek-ai/dsh-subprocess';
23
+ import type { DelegationExecTarget, LocalAgentToolCalls } from '@khorsheed/dsh-local-agent/types';
24
+ import type { ClaudeLiveDriver } from './live-driver.ts';
25
+ /** Default POSIX grace between subprocess termination tiers. */
26
+ export declare const DEFAULT_DISPOSE_GRACE_MS = 3000;
27
+ /**
28
+ * Auth-shaped failure signatures in claude's result error or stderr: the
29
+ * endpoint rejected the credential (401/403, revoked token). Narrow on
30
+ * purpose — matched against provider-controlled error strings only.
31
+ */
32
+ export declare const CLAUDE_AUTH_FAILURE: RegExp;
33
+ /**
34
+ * Member channel registration for one claude process lifetime: mint the
35
+ * per-run token and build the bridge MCP declaration for the spawn argv
36
+ * (`--mcp-config <json>` — verified end-to-end against the real CLI).
37
+ * Nothing is written to the scoped home and there is nothing to prune at
38
+ * settle; `release` only invalidates the token. Returns undefined when the
39
+ * mounted core predates the member channel (declare-and-degrade). The exec
40
+ * driver registers per round; the live driver registers per resident
41
+ * process and releases on reclaim.
42
+ */
43
+ export interface ClaudeMemberRunHandle {
44
+ readonly token: string;
45
+ readonly mcpConfig: string;
46
+ readonly allowedTool: string;
47
+ release(): void;
48
+ }
49
+ /** Register one member run with the channel; see {@link ClaudeMemberRunHandle}. */
50
+ export declare function registerClaudeMemberRun(ctx: Context, childSessionId: string, parentSessionId: string): ClaudeMemberRunHandle | undefined;
51
+ /**
52
+ * The version `claude --version` reports, probed through the shared subprocess
53
+ * seam against the SCOPED config directory (never the user's own
54
+ * installation) and cached by the family probe against the executable's
55
+ * identity. The effective-settings snapshot uses it; a settled round prefers
56
+ * the version its own stream named.
57
+ * @param ctx - host context carrying the subprocess seam.
58
+ * @param homeDir - the harness's scoped home.
59
+ * @returns the version, or undefined when the CLI cannot be asked.
60
+ */
61
+ export declare function claudeCliVersion(ctx: Context, homeDir: string): Promise<string | undefined>;
62
+ export declare class ClaudeCliProvider implements SubagentProvider {
63
+ private readonly ctx;
64
+ private readonly permissionMode;
65
+ private readonly baseUrl?;
66
+ private readonly live?;
67
+ private readonly model?;
68
+ readonly name = "claude-local";
69
+ readonly capabilities: SubagentCapabilities;
70
+ readonly inheritsParentContext = false;
71
+ /**
72
+ * @param live - the live driver, or a resolver returning the current
73
+ * generation's driver per member (the settings toggle swaps generations;
74
+ * a resolver may return undefined to steer one member's round to exec
75
+ * while a retiring generation still hosts it).
76
+ * @param model - resolver for the member's effective model, read PER ROUND
77
+ * so a settings-card write or a composer switch takes effect on the next
78
+ * delegation without a reload. Receives the member (the child session id)
79
+ * and the round's delegation-layer model, and answers in the family's
80
+ * order — session-level override, delegation, settings. Absent (the
81
+ * resolver not passed), the delegation's own model still rides, exactly
82
+ * as before the key existed.
83
+ */
84
+ constructor(ctx: Context, permissionMode?: 'skip' | 'normal', baseUrl?: string | undefined, live?: ClaudeLiveDriver | ((childSessionId: string) => ClaudeLiveDriver | undefined) | undefined, model?: ((childSessionId: string, delegationModel?: string) => string | undefined) | undefined);
85
+ /** Resolve the live driver for one round's member, if live is on for it. */
86
+ private liveDriver;
87
+ /** The round's model fragment for the exec spawn spec (see {@link resolveRoundModel}). */
88
+ private roundModel;
89
+ /** Per-round member-channel registration for the exec path (see {@link registerClaudeMemberRun}). */
90
+ private memberRun;
91
+ start(request: ResolvedSubagentStartRequest): Promise<SubagentRun>;
92
+ /** Fresh round: record the child session, spawn `claude -p`, append after settle. */
93
+ private startClaudeFresh;
94
+ /** Resume round: continue the recorded claude session inside the existing child session. */
95
+ private startClaudeResume;
96
+ }
97
+ /** Fully resolved inputs for one Claude CLI run. */
98
+ export interface ClaudeCliRunSpec {
99
+ /** Parent Session workspace; also the claude process cwd. */
100
+ readonly cwd: string;
101
+ /**
102
+ * Explicit environment layered after the shared credential scrub; an
103
+ * `undefined` value tombstones an inherited ambient entry, a string
104
+ * restores or overrides it.
105
+ */
106
+ readonly env: Readonly<NodeJS.ProcessEnv>;
107
+ /**
108
+ * Run the CLI inside this container instead of on the host: the argv below
109
+ * is wrapped in `docker exec` and {@link env} is forwarded through NAME-only
110
+ * `-e` flags. Absent means the host spawn, unchanged.
111
+ */
112
+ readonly exec?: DelegationExecTarget | undefined;
113
+ /** Resolved endpoint label for diagnostics; absent means the CLI default. */
114
+ readonly endpointLabel?: string | undefined;
115
+ /** Permission mode passed to `claude -p`. */
116
+ readonly permissionMode: 'skip' | 'normal';
117
+ /**
118
+ * Model this round runs with, passed as `claude -p --model <model>`. Absent
119
+ * means no `--model` on the argv at all: the scoped `settings.json`'s own
120
+ * `model` (or, with none, the CLI's built-in default) decides, exactly as
121
+ * before the key existed.
122
+ */
123
+ readonly model?: string | undefined;
124
+ readonly effort?: string | undefined;
125
+ readonly controlled?: boolean;
126
+ /** Subprocess termination grace passed to the shared process-tree owner. */
127
+ readonly disposeGraceMs: number;
128
+ /** Shared subprocess service spawn operation. */
129
+ readonly spawn: (spec: SubprocessSpawnSpec) => SubprocessHandle;
130
+ /** Diagnostic sink for a post-publication error flattened into a result. */
131
+ readonly onError?: (error: Error, stopReason: SubagentStopReason) => void;
132
+ /**
133
+ * Called when the settled failure is auth-shaped (the endpoint rejected the
134
+ * credential — a 401/403 a presence probe cannot see). The provider wires
135
+ * this to the family registry's auth-failure mark.
136
+ */
137
+ readonly onAuthFailure?: ((detail: string) => void) | undefined;
138
+ /**
139
+ * Called when the round SETTLED COMPLETED — the CLI reached its endpoint and
140
+ * produced an answer, which is the only evidence a host has that the scoped
141
+ * credential is live. The provider wires this to the family registry's
142
+ * auth-success mark (the `verified` credential grade).
143
+ */
144
+ readonly onAuthSuccess?: (() => void) | undefined;
145
+ /**
146
+ * The version the executable reports, resolved lazily and cached by the
147
+ * family probe. Only consulted when the round's own stream named none.
148
+ */
149
+ readonly cliVersion?: (() => Promise<string | undefined>) | undefined;
150
+ /**
151
+ * Member channel: the bridge MCP declaration for this run, injected as
152
+ * `--mcp-config <json>` plus a `--allowedTools` entry for the bridge's one
153
+ * tool (claude `-p` auto-denies permission prompts). Absent on a core that
154
+ * predates the member channel — the argv is then exactly the pre-channel
155
+ * shape.
156
+ */
157
+ readonly member?: {
158
+ readonly mcpConfig: string;
159
+ readonly allowedTool: string;
160
+ } | undefined;
161
+ /** dsh subagent session recording this delegation; its response is appended after settle. */
162
+ readonly childSession?: Session | undefined;
163
+ /** Host context carrying session persistence. */
164
+ readonly ctx?: Context | undefined;
165
+ /**
166
+ * Resume round: continue the session named by `cliSessionId` with
167
+ * `claude -p --resume <session_id>` instead of a fresh `claude -p`,
168
+ * appending this round into the same child session under the given turn.
169
+ */
170
+ readonly resume?: {
171
+ readonly cliSessionId: string;
172
+ readonly turn: number;
173
+ } | undefined;
174
+ /**
175
+ * Called after the run settles with the claude session id parsed from the
176
+ * result JSON (absent when none was reported). The fresh path uses it to
177
+ * record the delegation so a later resume round can continue the session.
178
+ */
179
+ readonly onSessionId?: ((sessionId: string | undefined) => void) | undefined;
180
+ /**
181
+ * Called once per settled round, after the output stream has been fully
182
+ * parsed and mirrored: the round's observed model identifier and token
183
+ * usage, each absent when the stream yielded none. The provider wires this
184
+ * to the registry's observation channel (`recordRoundSettled` — the
185
+ * delegation record's `observedModel` merge and the `settled` run-progress
186
+ * event). Fires for fresh and resume rounds alike, on every terminal state.
187
+ */
188
+ readonly onRoundSettled?: ((round: {
189
+ readonly observedModel?: string;
190
+ readonly usage?: TokenUsage;
191
+ readonly toolCalls?: LocalAgentToolCalls;
192
+ }) => void) | undefined;
193
+ }
194
+ /**
195
+ * Validate and join the one-shot task before crossing the process boundary.
196
+ * @param prompt - task content accepted from the shared subagent service.
197
+ * @returns the joined non-empty text.
198
+ */
199
+ export declare function textTask(prompt: readonly ContentBlock[]): string;
200
+ /** One ordered transcript line from a `claude --output-format stream-json` stream. */
201
+ export type ClaudeTranscriptLine = {
202
+ kind: 'think';
203
+ text: string;
204
+ streamId?: string;
205
+ } | {
206
+ kind: 'text';
207
+ text: string;
208
+ streamId?: string;
209
+ }
210
+ /**
211
+ * Tool activity: one `tool_use` with its (possibly still pending)
212
+ * `tool_result`. `id` is the stream's tool_use id when present, else a
213
+ * synthesized position-based id — stable within a run either way, so the
214
+ * child session's `tool/call`/`tool/result` events pair by it.
215
+ */
216
+ | {
217
+ kind: 'tool';
218
+ id: string;
219
+ name: string;
220
+ args?: string;
221
+ result?: string;
222
+ };
223
+ /** Mutable fold state shared by the batch parse and the incremental parser. */
224
+ interface ClaudeStreamFoldState {
225
+ readonly lines: ClaudeTranscriptLine[];
226
+ /** tool_use id → transcript line index, so a result pairs with its own call. */
227
+ readonly callsById: Map<string, number>;
228
+ text: string | undefined;
229
+ usage: TokenUsage | undefined;
230
+ sessionId: string | undefined;
231
+ /**
232
+ * The model identifier the stream named: the `model` field on the
233
+ * `system` init event (verified against claude 2.x stream-json) or on the
234
+ * terminal `result` event. Absent when neither carries one.
235
+ */
236
+ model: string | undefined;
237
+ /**
238
+ * The CLI's own version, from the `system` init event's
239
+ * `claude_code_version` (claude 2.1.x puts its whole build-info object
240
+ * there, so the `VERSION` field is read out of it; a plain string is
241
+ * accepted too). Absent when the stream names none — the provider then
242
+ * falls back to the family's `--version` probe.
243
+ */
244
+ cliVersion: string | undefined;
245
+ error: string | undefined;
246
+ /** Whether the stream's terminal `result` event was folded. */
247
+ completed: boolean;
248
+ /**
249
+ * The last TodoWrite translation (last-wins within the stream). TodoWrite
250
+ * blocks are intercepted BEFORE the text fold — the member's task list
251
+ * crosses as a native `todo/write` snapshot, never a `[工具 TodoWrite]` line.
252
+ */
253
+ todos: TodoItem[] | undefined;
254
+ /** A TodoWrite whose input missed the documented shape (degraded to the text fold). */
255
+ todoSkew: boolean;
256
+ /**
257
+ * Tool calls this stream made, keyed by the `tool_use` block's own `name` —
258
+ * claude's vocabulary verbatim (`Bash`, `Read`, `TodoWrite`, an MCP tool's
259
+ * full `mcp__server__tool`), never normalized across harnesses. Counted in
260
+ * the branch that already folds the block, so no event is parsed twice.
261
+ */
262
+ readonly toolCalls: Map<string, number>;
263
+ }
264
+ /**
265
+ * Fold a tool-call counter into the settled shape: `{count, byName}` with the
266
+ * per-name values summing to `count`. An empty map yields undefined — a
267
+ * stream that named no tool call reports nothing rather than a zero it did
268
+ * not observe.
269
+ * @param counts - the fold's per-name tally.
270
+ * @returns the settled accounting, or undefined when nothing was counted.
271
+ */
272
+ export declare function toolCallsOf(counts: ReadonlyMap<string, number>): LocalAgentToolCalls | undefined;
273
+ /**
274
+ * Translate one TodoWrite tool input into the dsh whole-list snapshot.
275
+ * Claude's documented schema is `{todos: [{content, status, activeForm}]}`
276
+ * with status `pending | in_progress | completed` — dsh's TodoItem vocabulary
277
+ * minus `activeForm` (display-only). Unknown statuses map to `pending`; a
278
+ * shape-skewed input returns undefined and the caller degrades to the plain
279
+ * text fold — shape skew must never throw into the mirror.
280
+ * @param input - the tool_use block's `input` payload.
281
+ * @returns the dsh todo list, or undefined on shape skew.
282
+ */
283
+ export declare function todosFromTodoWrite(input: unknown): TodoItem[] | undefined;
284
+ /**
285
+ * The CLI version named by a `system` init event's `claude_code_version`.
286
+ * claude 2.1.x serializes its whole build-info module there
287
+ * (`{ VERSION, BUILD_TIME, GIT_SHA, … }`), so the version is a field of it; a
288
+ * future release that emits a bare string is accepted unchanged. Anything
289
+ * else yields undefined and the probe answers instead.
290
+ * @param value - the event's `claude_code_version` field.
291
+ * @returns the version string, or undefined.
292
+ */
293
+ export declare function claudeVersionFromInit(value: unknown): string | undefined;
294
+ /**
295
+ * Incremental `claude --output-format stream-json` parser: feed stdout chunks
296
+ * as they arrive and the folded transcript accumulates line by line. The last
297
+ * line is volatile until the terminal `result` event — a `tool_result` merges
298
+ * into a pending tool line — so live consumers hold it back (see the run's
299
+ * live mirror).
300
+ */
301
+ export declare class ClaudeStreamParser implements ClaudeStreamFoldState {
302
+ private buffer;
303
+ readonly lines: ClaudeTranscriptLine[];
304
+ readonly callsById: Map<string, number>;
305
+ text: string | undefined;
306
+ usage: TokenUsage | undefined;
307
+ sessionId: string | undefined;
308
+ model: string | undefined;
309
+ cliVersion: string | undefined;
310
+ error: string | undefined;
311
+ completed: boolean;
312
+ todos: TodoItem[] | undefined;
313
+ todoSkew: boolean;
314
+ readonly toolCalls: Map<string, number>;
315
+ /** Fold every complete NDJSON line in the chunk; the tail stays buffered. */
316
+ push(chunk: string): void;
317
+ }
318
+ /**
319
+ * Parse a `claude -p --verbose --output-format stream-json` NDJSON stream.
320
+ * Each line is one event: `system` init (carries the session id and the
321
+ * model), `assistant` (content blocks: `text`, `tool_use`, `thinking`), `user`
322
+ * (a `tool_result` block), and a terminal `result` (final usage, error flag,
323
+ * session id). Content blocks fold into an ordered transcript (thinking,
324
+ * reply text, tool calls with results), the last assistant `text` becomes the
325
+ * run output, and the `result` event's usage/session id ride the parse. The
326
+ * model identifier comes from the init (or result) event's `model` field. A
327
+ * malformed stream or an `is_error` result yields the error instead.
328
+ * @param output - the collected stdout NDJSON text.
329
+ * @returns the ordered transcript, final answer text, usage, session id, the
330
+ * observed model, and the error when the run reported one.
331
+ */
332
+ export declare function parseClaudeStreamJson(output: string): {
333
+ lines: readonly ClaudeTranscriptLine[];
334
+ text?: string;
335
+ usage?: TokenUsage;
336
+ error?: string;
337
+ sessionId?: string;
338
+ model?: string;
339
+ /** The CLI version the stream's init event named, when it carried one. */
340
+ cliVersion?: string;
341
+ /** The stream's last TodoWrite translation, when one was folded. */
342
+ todos?: TodoItem[];
343
+ /** Whether a shape-skewed TodoWrite degraded to the text fold. */
344
+ todoSkew?: boolean;
345
+ /** The round's tool-call accounting, absent when the stream made none. */
346
+ toolCalls?: LocalAgentToolCalls;
347
+ };
348
+ /** The placeholder think line for a `redacted_thinking` block (content is server-encrypted by design). */
349
+ export declare const REDACTED_THINKING_TEXT = "\uFF08\u601D\u8003\u5185\u5BB9\u5DF2\u7531\u670D\u52A1\u7AEF\u9690\u85CF\uFF1Aredacted_thinking\uFF0C\u5185\u5BB9\u6309\u8BBE\u8BA1\u4E0D\u53EF\u89C1\uFF0C\u6B64\u884C\u4EC5\u6807\u793A\u5B83\u5B58\u5728\uFF09";
350
+ /**
351
+ * Start the real `claude -p` child and publish its run. The claude
352
+ * result arrives as an NDJSON event stream on stdout (`--verbose
353
+ * --output-format stream-json`): assistant content blocks (text, tool_use,
354
+ * thinking), user tool_result blocks, and a terminal result event carrying
355
+ * usage and session id. stderr is piped for diagnostics and never folded
356
+ * into the run output. A resume round spawns `claude -p --resume
357
+ * <session_id>` instead, continuing the same session. The run id is the
358
+ * child session id for a session-backed run.
359
+ * @param request - resolved shared subagent request.
360
+ * @param spec - workspace, environment, process service, and diagnostic policy.
361
+ * @returns the published run after the child starts.
362
+ */
363
+ export declare function startClaudeCliRun(request: SubagentStartRequest, spec: ClaudeCliRunSpec): Promise<SubagentRun>;
364
+ /** One assistant-role message event, attributed to the claude route. */
365
+ export declare function assistantEvent(blocks: readonly ContentBlock[]): import("@deepseek-ai/dsh-llm").AssistantMessage;
366
+ /**
367
+ * Fold one transcript line into the child session as one assistant step,
368
+ * wrapped in the step/start–step/end boundary pair the live conversation
369
+ * assembler requires: without a boundary the step never enters the location
370
+ * index, the line's assistant message resolves to a turn-level location, and
371
+ * the real-time view renders nothing (only a full rebuild, which mints step
372
+ * drafts from the explicit coordinates, recovers it). Tool cards escape that
373
+ * fate only because their definition does not consult the step location.
374
+ */
375
+ export declare function appendClaudeTranscriptLine(childSession: Session, turn: number, step: number, line: ClaudeTranscriptLine, usage: TokenUsage | undefined): void;
376
+ /** The delta-progress text for one transcript line. */
377
+ export declare function claudeLineText(line: ClaudeTranscriptLine): string;
378
+ /**
379
+ * Persist the child session's mirrored events. Thin wrapper over the core's
380
+ * {@link persistChildSession}: a live session syncs through the core's cached
381
+ * per-child write handle (host 0.1.5's live write-behind never checkpoints a
382
+ * mirror session — it has no agent loop — so production child logs stayed
383
+ * header-only until the explicit sync), a standalone one through a one-shot
384
+ * handle flow. Kept under the historical name for the live driver. Root cause
385
+ * and fix identical to codex's codex-cli-provider.ts persistIfStandalone.
386
+ */
387
+ export declare function persistIfStandalone(ctx: Context, childSession: Session): Promise<void>;
388
+ export {};
389
+ //# sourceMappingURL=claude-cli-provider.d.ts.map