@khorsheed/dsh-local-agent 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 (99) hide show
  1. package/README.en.md +181 -0
  2. package/README.i18n.yaml +2 -0
  3. package/README.md +181 -0
  4. package/cordis.patch.yml +21 -0
  5. package/lib/client.js +8832 -0
  6. package/lib/index.js +5281 -0
  7. package/lib/invariant.js +85 -0
  8. package/lib/member-bridge.js +298 -0
  9. package/lib/typert.host.d.ts +3 -0
  10. package/lib/typert.host.js +3137 -0
  11. package/lib/typert.remote-client.d.ts +67 -0
  12. package/lib/typert.remote-client.js +1971 -0
  13. package/lib/types/cli-version.d.ts +82 -0
  14. package/lib/types/cli-version.js +165 -0
  15. package/lib/types/client/AuthStatusDot.d.ts +17 -0
  16. package/lib/types/client/AuthStatusDot.js +9 -0
  17. package/lib/types/client/HarnessModelPicker.d.ts +17 -0
  18. package/lib/types/client/HarnessModelPicker.js +48 -0
  19. package/lib/types/client/LocalAgentRecordsAction.d.ts +41 -0
  20. package/lib/types/client/LocalAgentRecordsAction.js +74 -0
  21. package/lib/types/client/MemberComposer.d.ts +79 -0
  22. package/lib/types/client/MemberComposer.js +308 -0
  23. package/lib/types/client/MemberConfiguration.d.ts +9 -0
  24. package/lib/types/client/MemberConfiguration.js +46 -0
  25. package/lib/types/client/MemberInboxView.d.ts +12 -0
  26. package/lib/types/client/MemberInboxView.js +38 -0
  27. package/lib/types/client/MemberLiveNode.d.ts +14 -0
  28. package/lib/types/client/MemberLiveNode.js +74 -0
  29. package/lib/types/client/MemberPaintDiagnostics.d.ts +7 -0
  30. package/lib/types/client/MemberPaintDiagnostics.js +20 -0
  31. package/lib/types/client/ModelConfigurationFields.d.ts +15 -0
  32. package/lib/types/client/ModelConfigurationFields.js +23 -0
  33. package/lib/types/client/ProviderAuthBlock.d.ts +59 -0
  34. package/lib/types/client/ProviderAuthBlock.js +164 -0
  35. package/lib/types/client/auth-status.d.ts +28 -0
  36. package/lib/types/client/auth-status.js +56 -0
  37. package/lib/types/client/icons.d.ts +22 -0
  38. package/lib/types/client/icons.js +6 -0
  39. package/lib/types/client/index.d.ts +62 -0
  40. package/lib/types/client/index.js +135 -0
  41. package/lib/types/client/live-node.d.ts +14 -0
  42. package/lib/types/client/live-node.js +34 -0
  43. package/lib/types/client/live-output.d.ts +34 -0
  44. package/lib/types/client/live-output.js +94 -0
  45. package/lib/types/client/live-paint.d.ts +40 -0
  46. package/lib/types/client/live-paint.js +74 -0
  47. package/lib/types/client/locales.d.ts +120 -0
  48. package/lib/types/client/locales.js +227 -0
  49. package/lib/types/client/member-configuration.d.ts +41 -0
  50. package/lib/types/client/member-configuration.js +114 -0
  51. package/lib/types/client/member-dock.d.ts +94 -0
  52. package/lib/types/client/member-dock.js +102 -0
  53. package/lib/types/client/member-feed.d.ts +24 -0
  54. package/lib/types/client/member-feed.js +134 -0
  55. package/lib/types/client/request-id.d.ts +3 -0
  56. package/lib/types/client/request-id.js +6 -0
  57. package/lib/types/client/settings-scope.d.ts +74 -0
  58. package/lib/types/client/settings-scope.js +98 -0
  59. package/lib/types/client/use-configuration-menu.d.ts +10 -0
  60. package/lib/types/client/use-configuration-menu.js +61 -0
  61. package/lib/types/container.d.ts +69 -0
  62. package/lib/types/container.js +129 -0
  63. package/lib/types/env.d.ts +17 -0
  64. package/lib/types/env.js +89 -0
  65. package/lib/types/gateway.d.ts +162 -0
  66. package/lib/types/gateway.js +470 -0
  67. package/lib/types/index.d.ts +1463 -0
  68. package/lib/types/index.js +2704 -0
  69. package/lib/types/invariant.d.ts +16 -0
  70. package/lib/types/invariant.js +105 -0
  71. package/lib/types/live-flush.d.ts +21 -0
  72. package/lib/types/live-flush.js +59 -0
  73. package/lib/types/live-stream.d.ts +41 -0
  74. package/lib/types/live-stream.js +178 -0
  75. package/lib/types/member-bridge.d.ts +50 -0
  76. package/lib/types/member-bridge.js +216 -0
  77. package/lib/types/member-channel.d.ts +86 -0
  78. package/lib/types/member-channel.js +232 -0
  79. package/lib/types/member-control-storage.d.ts +10 -0
  80. package/lib/types/member-control-storage.js +100 -0
  81. package/lib/types/member-control.d.ts +62 -0
  82. package/lib/types/member-control.js +359 -0
  83. package/lib/types/member-controls.d.ts +23 -0
  84. package/lib/types/member-controls.js +143 -0
  85. package/lib/types/member-feed.d.ts +4 -0
  86. package/lib/types/member-feed.js +45 -0
  87. package/lib/types/member-inbox.d.ts +30 -0
  88. package/lib/types/member-inbox.js +225 -0
  89. package/lib/types/model-directory.d.ts +43 -0
  90. package/lib/types/model-directory.js +192 -0
  91. package/lib/types/prepared-members.d.ts +15 -0
  92. package/lib/types/prepared-members.js +61 -0
  93. package/lib/types/settings-face.d.ts +61 -0
  94. package/lib/types/settings-face.js +61 -0
  95. package/lib/types/types.d.ts +959 -0
  96. package/lib/types/types.js +24 -0
  97. package/locale/en.json +6 -0
  98. package/locale/zh.json +6 -0
  99. package/package.json +112 -0
@@ -0,0 +1,959 @@
1
+ /**
2
+ * Local-agent family type vocabulary, exported through the `./types` subpath
3
+ * so Typert Remote boundary types resolve from a public non-root subpath
4
+ * (the wire-schema generator's requirement for {@link LocalAgentGateway}
5
+ * method signatures).
6
+ * @module @khorsheed/dsh-local-agent/types
7
+ */
8
+ import type { TokenUsage } from '@deepseek-ai/dsh-llm';
9
+ /** In-flight text item, identified by the durable turn/step coordinate. */
10
+ export interface LocalAgentStreamItem {
11
+ id: string;
12
+ turn: number;
13
+ step: number;
14
+ kind: 'think' | 'text';
15
+ text: string;
16
+ revision: number;
17
+ receivedAt: number;
18
+ }
19
+ /** Reconnection starts with a baseline; subsequent updates carry suffixes or explicit replacements. */
20
+ export interface LocalAgentStreamFrame {
21
+ baseline: boolean;
22
+ updates: readonly (LocalAgentStreamItem & {
23
+ append: boolean;
24
+ })[];
25
+ removed: readonly string[];
26
+ }
27
+ /** One browser connection multiplexes every currently rendered member surface. */
28
+ export interface LocalAgentMemberFeedRequest {
29
+ memberId: string;
30
+ channel: 'configuration' | 'directory' | 'output';
31
+ }
32
+ export type LocalAgentMemberFeedEvent = {
33
+ memberId: string;
34
+ channel: 'configuration';
35
+ value: LocalAgentMemberControlState;
36
+ } | {
37
+ memberId: string;
38
+ channel: 'directory';
39
+ value: LocalAgentModelDirectory;
40
+ } | {
41
+ memberId: string;
42
+ channel: 'output';
43
+ value: LocalAgentStreamFrame;
44
+ } | {
45
+ memberId: string;
46
+ channel: 'error';
47
+ source: 'configuration' | 'directory' | 'output';
48
+ message: string;
49
+ };
50
+ /** Log-only recovery checkpoint; never injected into a model's conversation. */
51
+ export interface LocalAgentStreamCheckpoint extends Omit<LocalAgentStreamItem, 'revision'> {
52
+ sessionId: string;
53
+ opening?: boolean;
54
+ /** Final native message has replaced this subitem presentation. */
55
+ closed?: boolean;
56
+ append: boolean;
57
+ }
58
+ declare module '@deepseek-ai/dsh-session/types' {
59
+ interface SessionEventMap {
60
+ /** Plugin-owned live presentation anchor and incremental recovery checkpoints. */
61
+ 'local-agent/stream': LocalAgentStreamCheckpoint;
62
+ }
63
+ }
64
+ /** One session record a harness's records adapter lists. */
65
+ export interface LocalAgentSessionRecord {
66
+ /** Harness session id. */
67
+ id: string;
68
+ /** The workspace directory the session ran in. */
69
+ workDir: string;
70
+ /** Optional session title when the harness records one. */
71
+ title?: string;
72
+ /** Optional epoch-millis start time when the harness records one. */
73
+ startedAt?: number;
74
+ }
75
+ /**
76
+ * How much is known about a harness's credential, from the two channels a
77
+ * status read has: the scoped home's own shape, and what delegation rounds
78
+ * observed.
79
+ *
80
+ * - `absent` — no credential in the scoped home (or the harness declares no
81
+ * probe at all). Nothing to try.
82
+ * - `present-unverified` — a credential record exists and nothing has
83
+ * exercised it in this host process. The record could be expired and
84
+ * unrefreshable and still look exactly like this; saying so is the point.
85
+ * - `verified` — a delegation round reached the CLI's endpoint and completed
86
+ * since the last login/logout, so the credential is known live.
87
+ * - `rejected` — a round's endpoint rejected the credential (a 401/403 a
88
+ * presence probe cannot see) and no fresh login has rewritten the
89
+ * credential marker since.
90
+ *
91
+ * The grade is per host process: after a restart a present credential reports
92
+ * `present-unverified` until a round exercises it, because that is what is
93
+ * actually known. An eager liveness probe at status time is deliberately NOT
94
+ * this field's job.
95
+ */
96
+ export type LocalAgentCredentialState = 'absent' | 'present-unverified' | 'verified' | 'rejected';
97
+ /** One harness's auth-status snapshot, shared by the command and Remote channels. */
98
+ export interface LocalAgentStatus {
99
+ /** Harness command prefix. */
100
+ name: string;
101
+ /** Human display name. */
102
+ displayName: string;
103
+ /**
104
+ * Whether the scoped home holds usable credentials — the SHAPE answer,
105
+ * kept for every surface written before {@link LocalAgentCredentialState}
106
+ * existed. Exactly `credentialState === 'verified' || 'present-unverified'`:
107
+ * a record that is present but never exercised still reads true, which is
108
+ * why the finer field exists.
109
+ */
110
+ authenticated: boolean;
111
+ /**
112
+ * How much is actually known about the credential — the liveness grade
113
+ * behind {@link LocalAgentStatus.authenticated}. Always present.
114
+ */
115
+ credentialState: LocalAgentCredentialState;
116
+ /**
117
+ * Absolute scoped home — of the SCOPE this status was asked about (see
118
+ * {@link LocalAgentStatus.scope}), which for the default scope is the
119
+ * directory it always was.
120
+ */
121
+ homeDir: string;
122
+ /**
123
+ * The named scope this status describes, when it describes one. Absent
124
+ * means the default scope — the only one that existed before named scopes,
125
+ * so every surface written before the field keeps reading exactly what it
126
+ * read. A named scope holds its own account: its credential grade, its
127
+ * session records and its delegation mappings are its own.
128
+ */
129
+ scope?: string;
130
+ /** Subagent provider name, when the harness delegates. */
131
+ delegationProvider?: string;
132
+ /**
133
+ * Whether the harness declares a device-code login flow (`/<name> login`).
134
+ * A harness without one authenticates through the host instance (e.g. by
135
+ * resolving a credential), so surfaces must not offer a login action.
136
+ */
137
+ loginable?: boolean;
138
+ /**
139
+ * A pty login is waiting for the user to paste the OAuth code
140
+ * (`/<name> code <value>`). Surfaces render the paste box while set.
141
+ */
142
+ loginAwaitingCode?: boolean;
143
+ /**
144
+ * Whether the harness declares a sign-out path (`/<name> logout`). A
145
+ * harness without one has no account to switch, so surfaces must not offer
146
+ * a logout action.
147
+ */
148
+ logoutable?: boolean;
149
+ /**
150
+ * The harness's fairness-relevant effective settings, when the harness
151
+ * declares a snapshot ({@link LocalAgentHarness.effectiveSettings}).
152
+ * Additive: surfaces and clients written before the field simply ignore it.
153
+ */
154
+ effectiveSettings?: LocalAgentEffectiveSettings;
155
+ }
156
+ /**
157
+ * One harness's fairness-relevant effective settings — the read side of the
158
+ * web-eval condition hash. Everything here is a knob the evaluation must hold
159
+ * equal across harnesses (drive, approval boundary, reasoning effort,
160
+ * endpoint route, CLI version) expressed as PURE JSON. Credentials never
161
+ * enter: no keys, no tokens, no full URLs (an endpoint reports its hostname
162
+ * only — a URL's path could carry tenant or project ids).
163
+ *
164
+ * A field the harness has no knob for — or one whose knob this deployment
165
+ * leaves unset — stays ABSENT (`sandbox`, `permissionMode`, `autoApprove`,
166
+ * `reasoningEffort`, `model`, `cliVersion`): absence is itself the honest
167
+ * condition-hash input, never a substituted default. `drive` and
168
+ * `baseUrlSet` are always present.
169
+ */
170
+ export interface LocalAgentEffectiveSettings {
171
+ /**
172
+ * How delegation rounds run: a one-shot CLI process per round (`exec`) or a
173
+ * resident runtime driven over its wire (`live`). The reported value is the
174
+ * configured driver preference in force; a live round may still fall back
175
+ * to exec when its channel cannot come up.
176
+ */
177
+ drive: 'exec' | 'live';
178
+ /**
179
+ * The file-effect boundary in force, in the harness's own vocabulary.
180
+ * Codex: the sandbox policy every round passes to `codex exec --sandbox`.
181
+ * dsh: the permission preset provisioning pins into the sub-profile
182
+ * (`read-only` / `workspace-write` / `danger-full-access`), which also
183
+ * decides the sub-dsh's approval policy through dsh-base's own preset
184
+ * table. Absent when the deployment pins none.
185
+ */
186
+ sandbox?: string;
187
+ /** Claude Code: the `claude -p` permission handling (`skip` or `normal`). */
188
+ permissionMode?: string;
189
+ /**
190
+ * Kimi: whether the scoped config's permission rules auto-approve tool use
191
+ * (the `Bash(*)` allow rule the provisioning gate keys on).
192
+ */
193
+ autoApprove?: boolean;
194
+ /**
195
+ * The reasoning effort in force, when the harness has one. Kimi reads its
196
+ * scoped config (`[thinking] effort`, falling back to the model's
197
+ * `default_effort`); codex reads its scoped config's
198
+ * `model_reasoning_effort`. Absent when the harness exposes no effort knob.
199
+ */
200
+ reasoningEffort?: string;
201
+ /** Whether a non-default endpoint is in force (a provider-pinned or env-provided base URL). */
202
+ baseUrlSet: boolean;
203
+ /**
204
+ * The endpoint's HOSTNAME only, present exactly when `baseUrlSet`. Never
205
+ * the full URL — its path can carry credential-adjacent segments.
206
+ */
207
+ baseUrlHost?: string;
208
+ /**
209
+ * The CLI's own version, as the CLI itself reports it — the version a
210
+ * delegation round would run with right now. Resolved by the family's
211
+ * `<cli> --version` probe, which spawns at most once per executable
212
+ * identity (resolved path + mtime + size) and is therefore cheap enough for
213
+ * a status read while still re-probing across an upgrade. Absent when the
214
+ * CLI cannot be asked (not installed, non-zero exit, timeout, no
215
+ * version-shaped token in its banner) — absence is the honest condition
216
+ * input, never a substituted guess.
217
+ */
218
+ cliVersion?: string;
219
+ /**
220
+ * The configured model identifier a delegation round would run with — read
221
+ * in one fixed order, never guessed: the harness's OWN `model` plugin-config
222
+ * key first (codex, claude-code, and kimi each accept one, and a set key
223
+ * rides every round's CLI launch), then the harness's scoped configuration
224
+ * surface (kimi's `default_model`, codex's `model`, claude-code's
225
+ * `settings.json` `model`, dsh's host `agentDefaultModel` selection
226
+ * formatted `provider/model` — the CLI's own default stays unnamed), then
227
+ * absent. Absence is the honest answer, never a substituted default.
228
+ *
229
+ * This deliberately does NOT report a delegation-level model
230
+ * ({@link DelegationCallOptions.model}): that one belongs to one
231
+ * delegation, while this field answers "what would a round with no model of
232
+ * its own run" — the harness-wide setting, which is what the evaluation's
233
+ * condition snapshot is asking about.
234
+ *
235
+ * This is a LIVE read of what the NEXT such round would run with. A run's
236
+ * condition hash freezes it at run setup, so changing the key mid-run does
237
+ * not rewrite the recorded condition — the next round's model read-back
238
+ * fails the run as misattributed instead (web-eval frozen decision 5).
239
+ */
240
+ model?: string;
241
+ /**
242
+ * Extra `NODE_OPTIONS` the harness injects when a round runs against a
243
+ * container exec target ({@link DelegationExecTarget}). Only the dsh
244
+ * harness declares one: its HTTP client is node's `fetch` (undici), which
245
+ * does not read `HTTP(S)_PROXY` by default, so a round inside a unit whose
246
+ * only egress is a whitelist proxy needs `--use-env-proxy` to open
247
+ * undici's `EnvHttpProxyAgent` — without it the CLI dials the API directly
248
+ * and the proxy never even sees a `CONNECT`. Reported unconditionally
249
+ * because the injection is unconditional in code; absent means the harness
250
+ * injects none. Never a credential — a node flag.
251
+ */
252
+ containerNodeOptions?: string;
253
+ }
254
+ /**
255
+ * The hostname of an endpoint URL, or undefined when the value does not parse
256
+ * as a URL (scheme-less `host:port` forms included — still reported via
257
+ * `baseUrlSet`, just without a hostname).
258
+ */
259
+ export declare function endpointHost(url: string): string | undefined;
260
+ /** Roster row: enough of a harness for a client list. */
261
+ export interface LocalAgentRosterRow {
262
+ /** Harness command prefix. */
263
+ name: string;
264
+ /** Human display name. */
265
+ displayName: string;
266
+ }
267
+ /**
268
+ * One family delegation's CLI-session mapping, recorded by the harness
269
+ * provider after its first round settles (the CLI session id is only known
270
+ * from the round's output). The resume tool resolves a caller-supplied dsh
271
+ * child session id against this registry, and ownership is proven by the
272
+ * recorded parent session id: a forged handle naming another session is
273
+ * rejected instead of resuming someone else's conversation context.
274
+ */
275
+ export interface LocalAgentDelegationRecord {
276
+ /** Creation-time reasoning request and optional frozen evaluation lock. */
277
+ effort?: string;
278
+ configurationLock?: string;
279
+ /** The dsh subagent child session id (the run id of the first round). */
280
+ childSessionId: string;
281
+ /** The `ctx.subagents` provider name that owns the CLI session. */
282
+ provider: string;
283
+ /** The delegating parent session id that created the child. */
284
+ parentSessionId: string;
285
+ /**
286
+ * The CLI's own session/thread id, used to build the resume command.
287
+ */
288
+ cliSessionId: string;
289
+ /**
290
+ * The resolved working directory the FIRST round ran in — the anchor the
291
+ * resume-consistency check compares a later round's effective cwd against.
292
+ * Recorded by the provider at the delegation's first-round record point;
293
+ * absent on records written before the field existed (they opt out of the
294
+ * check rather than guess).
295
+ */
296
+ cwd?: string;
297
+ /**
298
+ * The named scope whose scoped home this delegation ran against — the
299
+ * anchor a resume round must repeat. Absent means the DEFAULT scope, which
300
+ * is what every record written before the field existed is; a resume that
301
+ * names a scope against such a record (or names none against a scoped one)
302
+ * is refused rather than continuing the CLI session under another account's
303
+ * credentials.
304
+ */
305
+ scope?: string;
306
+ /**
307
+ * The model identifier the provider observed in its own output stream for
308
+ * the latest settled round (claude's stream-json init, codex's rollout
309
+ * turn_context, kimi's wire usage/request records, the sub-dsh session's
310
+ * assistant source). Read back verbatim, never guessed: absent when the
311
+ * stream yielded none. This is the observed half of the evaluation's
312
+ * "declared model == actually-run model" check (web-eval frozen decision
313
+ * 5); it never enters any prompt or model-visible face.
314
+ */
315
+ observedModel?: string;
316
+ /**
317
+ * The model this delegation REQUESTED — the `model` call option its first
318
+ * round carried, recorded so every resume round re-requests the same value.
319
+ * The requested half of the pair whose observed half is
320
+ * {@link LocalAgentDelegationRecord.observedModel}: a delegation that asked
321
+ * for one model and read back another is exactly what the evaluation's
322
+ * declared-vs-run check exists to catch.
323
+ *
324
+ * Absent means the delegation named none — its rounds fall back to the
325
+ * plugin config, the scoped file, then the CLI's default, and a resume of
326
+ * it does the same. Records written before this field existed are that
327
+ * case, unchanged.
328
+ */
329
+ model?: string;
330
+ /**
331
+ * The CLI version the latest settled round actually ran, read back the same
332
+ * way {@link LocalAgentDelegationRecord.observedModel} is: from the CLI's
333
+ * own stream or records when it names one (codex's rollout `session_meta`
334
+ * carries `cli_version`, claude's stream-json init carries
335
+ * `claude_code_version`), otherwise from the family's `--version` probe of
336
+ * the executable the round spawned. Absent when neither channel answered.
337
+ */
338
+ cliVersion?: string;
339
+ /**
340
+ * Kimi transcript lines already mirrored into the child session. The kimi
341
+ * provider advances this after every round so a resumed round mirrors only
342
+ * its delta instead of duplicating earlier messages.
343
+ */
344
+ kimiMirroredLines?: number;
345
+ }
346
+ /**
347
+ * One delegation's record WITHOUT the CLI-session resume handle — the
348
+ * read-only projection {@link LocalAgentRegistry.delegationOf} returns for
349
+ * surfaces that need a delegation's facts (provider, parent, observed model,
350
+ * first-round cwd) but must never see the resume handle, which stays a
351
+ * first-class parameter plus the intent channel.
352
+ */
353
+ export type LocalAgentDelegationInfo = Omit<LocalAgentDelegationRecord, 'cliSessionId'>;
354
+ /**
355
+ * The member-channel view of one delegation, projected by the gateway's
356
+ * `memberOf` Remote for the composer: everything the browser needs to decide
357
+ * "this child session is a family member" and to label it, without the
358
+ * CLI-session resume handle (which never leaves the host).
359
+ */
360
+ export interface LocalAgentDelegationView {
361
+ /** The dsh subagent child session id. */
362
+ childSessionId: string;
363
+ /** The `ctx.subagents` provider name that owns the CLI session. */
364
+ provider: string;
365
+ /** The delegating parent session id that created the child. */
366
+ parentSessionId: string;
367
+ /** The owning harness's human display name, when a harness claims the provider. */
368
+ harnessDisplayName?: string;
369
+ }
370
+ /**
371
+ * Result of one user-initiated member prompt (`promptMember` Remote). Facade
372
+ * failures (unknown delegation, parent not live, resume locked, …) arrive as
373
+ * structured errors for the composer to render inline, never as raw exceptions
374
+ * over the wire.
375
+ */
376
+ export interface LocalAgentMemberInput {
377
+ id: string;
378
+ text: string;
379
+ status: 'queued' | 'running' | 'done' | 'failed' | 'cancelled' | 'uncertain';
380
+ createdAt: number;
381
+ updatedAt: number;
382
+ error?: string;
383
+ }
384
+ export interface LocalAgentMemberInbox {
385
+ memberId: string;
386
+ paused: boolean;
387
+ error?: string;
388
+ messages: LocalAgentMemberInput[];
389
+ }
390
+ export type LocalAgentPromptResult = {
391
+ ok: true;
392
+ requestId?: string;
393
+ } | {
394
+ ok: false;
395
+ error: string;
396
+ };
397
+ /**
398
+ * Where a member's effective model comes from, in the family's fixed
399
+ * resolution order (first match wins): the session-level override set through
400
+ * the composer's model picker, then the delegation's own recorded model, then
401
+ * the harness's plugin-config `model` (settings card / YAML), then the scoped
402
+ * config file's own default, and last the CLI's built-in default — which by
403
+ * itself names nothing, exactly as it did before any of these layers existed.
404
+ * A harness MAY still name that compiled default through a side channel:
405
+ * codex's app-server `model/list` marks the account's built-in default with
406
+ * `isDefault`, so a broker that probed the catalog reports `cli-builtin` WITH
407
+ * `effective` set (the one case this source names a model). And even when
408
+ * nothing names it, the delegation records show what last actually ran —
409
+ * {@link LocalAgentModelInfo.lastObserved}.
410
+ */
411
+ export type LocalAgentModelSource = 'override' | 'delegation' | 'settings' | 'cli-config' | 'cli-builtin';
412
+ /** Provider-native values, never normalized into a supposedly equivalent budget. */
413
+ export interface LocalAgentReasoningOption {
414
+ value: string;
415
+ label: string;
416
+ description?: string;
417
+ }
418
+ /** A catalog candidate is not proof that an account can successfully run it. */
419
+ export interface LocalAgentModelEntry {
420
+ value: string;
421
+ label: string;
422
+ resolvedModel?: string;
423
+ description?: string;
424
+ source: 'native' | 'configuration' | 'history';
425
+ hidden?: boolean;
426
+ reasoning?: {
427
+ options: readonly LocalAgentReasoningOption[];
428
+ default?: string;
429
+ };
430
+ }
431
+ export interface LocalAgentModelDirectoryData {
432
+ entries: readonly LocalAgentModelEntry[];
433
+ defaultModel?: string;
434
+ /** Complete enumeration of this source, not a guarantee of account access. */
435
+ complete: boolean;
436
+ customInput: boolean;
437
+ unsupported?: boolean;
438
+ reason?: string;
439
+ }
440
+ export interface LocalAgentModelDirectory extends LocalAgentModelDirectoryData {
441
+ status: 'loading' | 'ready' | 'stale' | 'error' | 'unsupported';
442
+ refreshing: boolean;
443
+ revision: number;
444
+ refreshedAt?: number;
445
+ }
446
+ /** Inherit the member's creation settings, ask for the harness default, or pin a native value. */
447
+ export type LocalAgentConfigurationChoice = {
448
+ mode: 'inherit' | 'default';
449
+ } | {
450
+ mode: 'value';
451
+ value: string;
452
+ };
453
+ export interface LocalAgentMemberConfiguration {
454
+ model: LocalAgentConfigurationChoice;
455
+ effort: LocalAgentConfigurationChoice;
456
+ }
457
+ /** Resolved control facts; actual generation observations are recorded separately. */
458
+ export interface LocalAgentResolvedConfiguration {
459
+ model?: string;
460
+ effort?: string;
461
+ }
462
+ export interface LocalAgentAppliedConfiguration {
463
+ revision: number;
464
+ selection: LocalAgentMemberConfiguration;
465
+ resolved: LocalAgentResolvedConfiguration;
466
+ }
467
+ export interface LocalAgentPendingConfiguration {
468
+ revision: number;
469
+ requestId: string;
470
+ kind: 'selection' | 'cancel';
471
+ selection: LocalAgentMemberConfiguration;
472
+ }
473
+ export interface LocalAgentMemberControlState {
474
+ memberId: string;
475
+ /** Monotonic intent revision, including cancellation. */
476
+ revision: number;
477
+ current: LocalAgentAppliedConfiguration;
478
+ pending?: LocalAgentPendingConfiguration;
479
+ operation?: LocalAgentPendingConfiguration & {
480
+ previous: LocalAgentAppliedConfiguration;
481
+ };
482
+ status: 'idle' | 'pending' | 'applying' | 'reconciling' | 'failed';
483
+ /** Immutable configuration captured at admission, including tool continuation. */
484
+ round?: {
485
+ id: string;
486
+ configuration: LocalAgentAppliedConfiguration;
487
+ };
488
+ lockedReason?: string;
489
+ /** First admitted configuration of a frozen evaluation; defaults cannot drift on resume. */
490
+ frozen?: LocalAgentAppliedConfiguration;
491
+ error?: string;
492
+ }
493
+ export interface LocalAgentControlReceipt {
494
+ requestId: string;
495
+ revision: number;
496
+ status: 'pending' | 'applying' | 'applied' | 'cancelled' | 'failed' | 'conflict' | 'locked' | 'unsupported';
497
+ error?: string;
498
+ }
499
+ /**
500
+ * The model surface for one member — or, without a member, for a harness's
501
+ * next round (the settings card's "what would run" line). Every layer reports
502
+ * its own value so a UI can explain WHY the effective model is what it is;
503
+ * `choices` is the pickable vocabulary (settings + scoped-config default +
504
+ * config-discovered + recently used, deduped), never a hardcoded catalog.
505
+ */
506
+ export interface LocalAgentModelInfo {
507
+ /** Durable current/pending selection, shared by every member entry point. */
508
+ configuration?: LocalAgentMemberControlState;
509
+ /** The model the next round would actually run with, when any layer names one. */
510
+ effective?: string;
511
+ /** Which layer {@link LocalAgentModelInfo.effective} came from. */
512
+ source: LocalAgentModelSource;
513
+ /** The session-level override, when one is active for the member. */
514
+ override?: string;
515
+ /** The delegation's recorded model, when the delegation named one. */
516
+ delegation?: string;
517
+ /** The harness's plugin-config `model`, when the settings layer sets one. */
518
+ settings?: string;
519
+ /** The scoped config file's own default model, when the file names one. */
520
+ cliDefault?: string;
521
+ /**
522
+ * The most recent model the provider was OBSERVED running (the delegation
523
+ * records' {@link LocalAgentDelegationRecord.observedModel}), filled by the
524
+ * core gateway when the broker itself names none. Display context for the
525
+ * cli-builtin layer: the CLI's compiled default names nothing, but "what
526
+ * ran last time" is exactly what a member still on that default would run
527
+ * again — so surfaces show it as the last-observed hint, never as
528
+ * {@link LocalAgentModelInfo.effective} (an observation is not a layer).
529
+ */
530
+ lastObserved?: string;
531
+ /**
532
+ * The pickable model identifiers (deduped; empty when nothing names a
533
+ * model). The core gateway appends {@link LocalAgentModelInfo.lastObserved}
534
+ * as the final entry when no broker choice already lists it, so a member
535
+ * that only ever ran its CLI default still has a one-item menu.
536
+ */
537
+ choices: readonly string[];
538
+ /** Rich, source-labelled directory; choices remains the legacy read face. */
539
+ directory?: LocalAgentModelDirectory;
540
+ /** Whether the harness's live driver is on for the member's rounds. */
541
+ live: boolean;
542
+ /**
543
+ * False while a round is in flight for the member: a model switch retires
544
+ * the member's resident runtime so the NEXT round respawns with the new
545
+ * model, and retiring a runtime mid-round would kill the run.
546
+ */
547
+ switchable: boolean;
548
+ /** Why a switch is currently refused, when {@link LocalAgentModelInfo.switchable} is false. */
549
+ reason?: string;
550
+ }
551
+ /**
552
+ * A harness's model knob, registered with the harness and routed by the
553
+ * gateway: the settings card reads the memberless info, the member composer
554
+ * reads and switches per member. A harness without a broker keeps its old
555
+ * faces exactly (the card's free-text model input still writes plugin config).
556
+ */
557
+ /** Stable execution identity, available before the first native session ID arrives. */
558
+ export interface MemberConfigurationAdapter {
559
+ /** Re-resolve defaults and validate before every whole-turn admission. */
560
+ prepare?(selection: LocalAgentMemberConfiguration): Promise<LocalAgentResolvedConfiguration>;
561
+ /** Read-only validation. Unknown native values can fail later at the control boundary. */
562
+ validate(selection: LocalAgentMemberConfiguration): Promise<void>;
563
+ /** No generation. Implementations must bound native controls and preserve session history. */
564
+ apply(selection: LocalAgentMemberConfiguration, previous: LocalAgentAppliedConfiguration, operationId: string): Promise<LocalAgentResolvedConfiguration>;
565
+ /** Reconcile before retry/recovery; unknown never authorizes another round. */
566
+ reconcile(state: LocalAgentMemberControlState): Promise<{
567
+ active: boolean;
568
+ matches: 'current' | 'operation' | 'unknown';
569
+ resolved: LocalAgentResolvedConfiguration;
570
+ }>;
571
+ }
572
+ export interface LocalAgentMemberBinding {
573
+ childSessionId: string;
574
+ provider: string;
575
+ parentSessionId: string;
576
+ cwd: string;
577
+ scope?: string;
578
+ model?: string;
579
+ effort?: string;
580
+ configurationLock?: string;
581
+ }
582
+ export interface LocalAgentModelBroker {
583
+ /** Native preparation for the core-owned configuration admission barrier. */
584
+ configurationAdapter?(binding: LocalAgentMemberBinding): MemberConfigurationAdapter;
585
+ /** Refresh only discovery; never starts a model turn or changes selection. */
586
+ modelDirectory?(childSessionId?: string, refresh?: boolean): LocalAgentModelDirectory | Promise<LocalAgentModelDirectory>;
587
+ /** Keeps an open picker current after a background probe. */
588
+ followModelDirectory?(childSessionId: string | undefined, signal: AbortSignal): AsyncIterable<LocalAgentModelDirectory>;
589
+ /**
590
+ * Read the model surface. With a member, `delegationModel` carries the
591
+ * delegation record's requested model (the record lives in the core; the
592
+ * broker ranks it between override and settings).
593
+ * @param childSessionId - the member to read, absent for the harness default.
594
+ * @param delegationModel - the delegation's recorded model, when it named one.
595
+ * @returns the layer-by-layer surface.
596
+ */
597
+ modelInfo(childSessionId?: string, delegationModel?: string): LocalAgentModelInfo | Promise<LocalAgentModelInfo>;
598
+ /**
599
+ * Set (or clear, with undefined) a member's session-level model override.
600
+ * The override outranks the delegation's recorded model and the settings
601
+ * layer; it is in-memory and deliberately does not survive a host restart.
602
+ * When the member has a live runtime, setting a DIFFERENT model retires the
603
+ * runtime so the next round respawns with the new model; the same model is
604
+ * a no-op. Throws when a round is in flight for the member.
605
+ * @param childSessionId - the member to switch.
606
+ * @param model - the model identifier, or undefined to clear the override.
607
+ */
608
+ setMemberModel(childSessionId: string, model: string | undefined): Promise<void>;
609
+ }
610
+ /**
611
+ * One member-to-member notification handed to the room gate — the frozen
612
+ * contract (`proposals/closed/2026-08-19-local-agent-member-channel.md` §3):
613
+ * `{ from, to, content, parentSessionId, provenance }`. The bridge cannot
614
+ * speak roster names for the SENDER (only room owns the roster), so `from`
615
+ * is the sender's dsh child session id and the full delegation view rides
616
+ * as `provenance`; room resolves both endpoints to roster names. The
617
+ * CLI-session resume handle never crosses.
618
+ */
619
+ export interface LocalAgentMemberMessage {
620
+ /** The sending member's dsh child session id (resolved from its run token). */
621
+ from: string;
622
+ /**
623
+ * The raw `to` argument: a member's dsh child session id, or — only
624
+ * meaningful to a claiming room — a member name from the room roster.
625
+ */
626
+ to: string;
627
+ /** The notification text. */
628
+ content: string;
629
+ /** The parent session both members belong to. */
630
+ parentSessionId: string;
631
+ /** The sender's delegation view, recorded as the delivery's provenance. */
632
+ provenance: Record<string, string>;
633
+ }
634
+ /**
635
+ * The room gate's answer to a member notification, passed back to the sender
636
+ * verbatim. Phase 1's gate is always human confirmation
637
+ * ('pending-confirm'); 'sent'/'busy' belong to the phase-2 auto gate. A
638
+ * DECLINE is not a value: the gate throws (the parent session is not a room
639
+ * this instance manages) and the family direct-sends.
640
+ */
641
+ export type RoomMemberMessageReceipt = 'sent' | 'pending-confirm' | 'busy';
642
+ /**
643
+ * Duck-typed shape of the room service's member-message gate, probed via
644
+ * `ctx.get('room')` — deliberately NO import of any room package, so the
645
+ * optional local-agent → room edge needs no inter-plugin dependency and no
646
+ * independence-checker sanction: room absent or declining is invisible to the
647
+ * family path. Room implements this shape to own the dispatch gate.
648
+ */
649
+ export type MemberRoomCommandName = 'room_plan' | 'room_read' | 'room_invite' | 'room_message';
650
+ export interface MemberRoomCommand {
651
+ name: MemberRoomCommandName;
652
+ arguments: Record<string, unknown>;
653
+ }
654
+ export interface RoomMemberMessageGate {
655
+ /** Explicit ownership prevents a rejected room operation falling through to direct execution. */
656
+ isRoom?(request: {
657
+ sessionId: string;
658
+ }): Promise<boolean>;
659
+ receiveMemberCommand?(actor: LocalAgentMemberRun, command: MemberRoomCommand): Promise<MemberMessageOutcome>;
660
+ receiveMemberMessage(message: LocalAgentMemberMessage): Promise<RoomMemberMessageReceipt>;
661
+ }
662
+ /**
663
+ * Outcome of one `member_message` delivery. Channel-level failures (unknown or
664
+ * expired token, unknown member) are `ok: false` tool errors;
665
+ * delivery verdicts — including a failed direct send — are receipts the sender
666
+ * can quote in its conclusion: `sent` / `pending-confirm` / `busy` /
667
+ * `error: <reason>` (or whatever a claiming room returns, passed verbatim).
668
+ */
669
+ export type MemberMessageOutcome = {
670
+ readonly ok: true;
671
+ readonly receipt: string;
672
+ } | {
673
+ readonly ok: false;
674
+ readonly error: string;
675
+ };
676
+ /** Environment variable carrying the member-bridge socket path (spawn env → bridge). */
677
+ export declare const MEMBER_BRIDGE_SOCKET_ENV = "DSH_MEMBER_SOCKET";
678
+ /** Environment variable carrying the per-run member-bridge token. */
679
+ export declare const MEMBER_BRIDGE_TOKEN_ENV = "DSH_MEMBER_TOKEN";
680
+ /**
681
+ * One in-flight CLI run registered for the member channel: the per-run token's
682
+ * resolution target. The token is minted at run start (fresh or resume) and
683
+ * invalidated when the run settles — a member's identity is never
684
+ * self-reported. The token is the sole credential (host 0.1.5 removed the
685
+ * child pid the parentage cross-check used; the auth-hardening proposal
686
+ * tracks a stronger second factor).
687
+ */
688
+ export interface LocalAgentMemberRun {
689
+ /** The dsh child session id of the run (its member identity). */
690
+ childSessionId: string;
691
+ /** The delegating parent session id. */
692
+ parentSessionId: string;
693
+ /** The `ctx.subagents` provider name running the CLI. */
694
+ provider: string;
695
+ }
696
+ /**
697
+ * What one delegation tool call intends for the provider's next `start()`.
698
+ * The tool stages exactly one intent per call before awaiting
699
+ * `ctx.subagents.start()`, and the provider consumes exactly one per start,
700
+ * so a per-(parent, provider) FIFO keeps fresh and resume rounds paired even
701
+ * under parallel delegation.
702
+ */
703
+ export type LocalAgentDelegationIntent = {
704
+ readonly kind: 'fresh';
705
+ readonly onAdmitted?: () => void | Promise<void>;
706
+ readonly preparedMemberId?: string;
707
+ readonly effort?: string;
708
+ readonly configurationLock?: string;
709
+ /**
710
+ * The working directory the round's CLI process runs in, when the caller
711
+ * supplied one (the `cwd` call option riding the staged intent). Absent
712
+ * means the provider's default — the parent session's cwd.
713
+ */
714
+ readonly cwd?: string;
715
+ /**
716
+ * Run the CLI inside this container instead of on the host (the `exec`
717
+ * call option riding the same staged intent). Absent means the host.
718
+ */
719
+ readonly exec?: DelegationExecTarget;
720
+ /**
721
+ * The named scope whose scoped home the round runs against (the `scope`
722
+ * call option riding the same staged intent). Absent means the default
723
+ * scope — the provider then resolves the same directory it always did.
724
+ */
725
+ readonly scope?: string;
726
+ /**
727
+ * The model this delegation requested (the `model` call option riding the
728
+ * same staged intent). The provider passes it to the CLI and RECORDS it,
729
+ * so every resume round of this delegation re-requests the same value.
730
+ * Absent means the provider falls back to its plugin config, then the
731
+ * scoped file, then the CLI default.
732
+ */
733
+ readonly model?: string;
734
+ } | {
735
+ readonly kind: 'resume';
736
+ readonly onAdmitted?: () => void | Promise<void>;
737
+ /** The dsh child session id to continue (the resume handle). */
738
+ readonly childSessionId: string;
739
+ /** The CLI session id the resume command continues. */
740
+ readonly cliSessionId: string;
741
+ /**
742
+ * The working directory the caller asks the resume round to run in, when
743
+ * supplied. The provider compares it (or the parent-session default)
744
+ * against the recorded first-round cwd and fails loud on a mismatch.
745
+ */
746
+ readonly cwd?: string;
747
+ /**
748
+ * Run the resume round's CLI inside this container. The caller repeats
749
+ * the first round's target; nothing recorded can verify that for it.
750
+ */
751
+ readonly exec?: DelegationExecTarget;
752
+ /**
753
+ * The named scope the resume round runs against. Unlike the container
754
+ * target this one IS anchored: the record carries the first round's
755
+ * scope, and a round naming another (or none) is refused.
756
+ */
757
+ readonly scope?: string;
758
+ };
759
+ /**
760
+ * One settled round's tool-call accounting, counted from the events the
761
+ * provider ALREADY parses for its transcript mirror — no second parse, no new
762
+ * readback channel. Per round, never cumulative.
763
+ *
764
+ * `byName` keys are whatever the harness's own CLI calls the tool, verbatim
765
+ * and un-normalized: codex reports its stream item types (`command_execution`,
766
+ * `web_search_call`), claude the `tool_use` name (`Bash`, `Read`, `TodoWrite`,
767
+ * an MCP tool's full name), kimi and dsh the tool name their own events carry.
768
+ * Cross-harness comparison is therefore `count` ONLY — the names are for a
769
+ * reader, and normalizing them would invent an equivalence the CLIs never
770
+ * agreed to. `byName` is absent when the events carried no usable name, and
771
+ * its values always sum to `count`.
772
+ */
773
+ export interface LocalAgentToolCalls {
774
+ /** Tool calls the round made. Zero is a real observation — the round used none. */
775
+ readonly count: number;
776
+ /** Per-tool counts under the CLI's own names; absent when no name was available. */
777
+ readonly byName?: Readonly<Record<string, number>>;
778
+ }
779
+ /**
780
+ * One progress update for a delegation run. Providers report the data-bearing
781
+ * kinds ({@link reportRunProgress} on the registry — the facade only forwards);
782
+ * the facade itself emits the `heartbeat` kind while a facade-tracked run is
783
+ * in flight, so a caller can render "in progress" without any provider
784
+ * support.
785
+ */
786
+ export type LocalAgentRunProgress = {
787
+ readonly kind: 'heartbeat';
788
+ /** Milliseconds since the facade started tracking the run. */
789
+ readonly elapsedMs: number;
790
+ } | {
791
+ readonly kind: 'mirror';
792
+ /** Total CLI transcript lines mirrored into the child session so far. */
793
+ readonly mirroredLines: number;
794
+ } | {
795
+ readonly kind: 'delta';
796
+ /** A live transcript increment (M3; not yet emitted by any provider). */
797
+ readonly text: string;
798
+ } | {
799
+ readonly kind: 'settled';
800
+ /** Native generation observation only, never copied from the requested effort. */
801
+ readonly observedEffort?: string;
802
+ /**
803
+ * The model identifier the provider observed in its own output stream for
804
+ * this round, when the stream carried one — absent otherwise, never
805
+ * guessed. The observed half of the evaluation's declared-vs-run model
806
+ * check; never enters any prompt or model-visible face.
807
+ */
808
+ readonly observedModel?: string;
809
+ /**
810
+ * The CLI version the round ran, when the provider could read one back
811
+ * (its own stream or records first, the `--version` probe second).
812
+ */
813
+ readonly cliVersion?: string;
814
+ /** The settled round's token usage, when the harness reported one. */
815
+ readonly usage?: TokenUsage;
816
+ /**
817
+ * The round's tool-call accounting, counted from the transcript events the
818
+ * provider already parsed. Absent when the harness reported none for this
819
+ * round — absence is "not observed", which is not the same fact as a
820
+ * `count: 0` round that ran no tools, so it is never filled in with zero.
821
+ */
822
+ readonly toolCalls?: LocalAgentToolCalls;
823
+ };
824
+ /**
825
+ * Where one delegation round's CLI process runs when the caller has already
826
+ * acquired a container for it (a lab unit). Given a target, the provider
827
+ * spawns `docker exec -w <workdir> [-e NAME…] <container> <the same argv>`
828
+ * instead of the CLI directly; stdio stays piped and every downstream
829
+ * layer — stream parse, settle, readback, delegation record — is the host
830
+ * path's, unchanged.
831
+ *
832
+ * The scoped home stays a HOST directory, bind-mounted read-write into the
833
+ * unit: readback (codex's rollout, kimi's wire log, the sub-dsh session log)
834
+ * reads it straight off the host filesystem, and credential refreshes the CLI
835
+ * writes land back on the host. `env` is where the caller names those
836
+ * in-container paths (`CODEX_HOME`, `CLAUDE_CONFIG_DIR`, `KIMI_CODE_HOME`,
837
+ * `DSH_HOME`), which is why every provider REQUIRES its own scoped-home
838
+ * variable here: the host path it would otherwise forward means nothing
839
+ * inside the unit.
840
+ *
841
+ * Absent everywhere means the host path, byte-for-byte the behavior before
842
+ * this option existed.
843
+ */
844
+ export interface DelegationExecTarget {
845
+ /**
846
+ * The container the round runs in — a name or id the caller acquired (lab's
847
+ * `UnitInfo.resource`). The family only ever runs `docker exec` against it:
848
+ * creating, inspecting, mounting and destroying it belong to the caller.
849
+ */
850
+ readonly container: string;
851
+ /** Absolute in-container working directory (`docker exec -w`). */
852
+ readonly workdir: string;
853
+ /**
854
+ * Environment entries for the in-container process, overriding the
855
+ * provider's own per key. Values travel in the docker CLIENT's environment
856
+ * and reach the container through NAME-only `-e` flags, so nothing here
857
+ * lands in the host process table.
858
+ */
859
+ readonly env?: Readonly<Record<string, string>>;
860
+ }
861
+ /**
862
+ * Call options for the public delegation facade (`LocalAgentRegistry.start` /
863
+ * `resume`). The interface is deliberately additive: later milestones extend
864
+ * it without changing the existing fields.
865
+ */
866
+ export interface DelegationCallOptions {
867
+ /** Host-only durable input edge, executed at the provider admission boundary. */
868
+ readonly onAdmitted?: () => void | Promise<void>;
869
+ /** Reserved identity returned by prepareMember; never a caller-selected resume override. */
870
+ readonly preparedMemberId?: string;
871
+ /** Native reasoning value, fixed at creation unless changed through member controls. */
872
+ readonly effort?: string;
873
+ /** Frozen evaluation condition: rejects interactive configuration changes. */
874
+ readonly configurationLock?: string;
875
+ /**
876
+ * Child display label persisted with a session-backed child; omitted, the
877
+ * harness's own display name labels the delegation.
878
+ */
879
+ readonly label?: string;
880
+ /**
881
+ * Caller-owned extra cancellation channel. It is fused with the facade's
882
+ * internal `cancel()` controller: aborting either cancels the run.
883
+ */
884
+ readonly signal?: AbortSignal;
885
+ /**
886
+ * Per-call progress callback: receives the same {@link LocalAgentRunProgress}
887
+ * payloads the `localAgent/run-progress` cordis event carries, routed to the
888
+ * tracked run this call started. For callers that cannot conveniently
889
+ * subscribe to cordis events.
890
+ */
891
+ readonly onProgress?: (event: LocalAgentRunProgress) => void;
892
+ /**
893
+ * `resume` only: when the child session is not live, reattach it from
894
+ * persistence (the default, true). Pass `false` to fail loud instead — the
895
+ * pre-facade behavior — leaving the absent session untouched.
896
+ */
897
+ readonly reattach?: boolean;
898
+ /**
899
+ * The working directory the CLI round runs in. On a fresh delegation it
900
+ * replaces the parent session's cwd (the `resolveChildCwd` override — an
901
+ * orchestrator giving each cell its own directory); on a resume it must
902
+ * match the first round's recorded cwd or the call fails loud, since the
903
+ * CLI conversation continues in the directory its earlier rounds ran in.
904
+ * Absent everywhere means the parent session's cwd — the behavior before
905
+ * this option existed, unchanged.
906
+ */
907
+ readonly cwd?: string;
908
+ /**
909
+ * Run the round's CLI inside an already-acquired container instead of on
910
+ * the host ({@link DelegationExecTarget}). The transport is the only thing
911
+ * it changes; a round with a target still parses, settles, reads back and
912
+ * records exactly as a host round does. On a resume, repeat the SAME target
913
+ * the first round used — the recorded first-round anchor is the host `cwd`,
914
+ * so a swapped container is a caller error the record cannot catch.
915
+ */
916
+ readonly exec?: DelegationExecTarget;
917
+ /**
918
+ * Run the round against a NAMED scoped home of the harness
919
+ * (`<homesRoot>/<harness>@<scope>`) instead of the default one. A scope is
920
+ * a name matching `[a-z0-9-]`, never a path; the directory is materialized
921
+ * (0700, then the harness's own provisioning) the first time anything names
922
+ * it, and it holds its own credentials — nothing is copied from the default
923
+ * scope, so a fresh scope needs its own `/<harness> login --scope <name>`.
924
+ *
925
+ * On a resume the scope must be the one the first round recorded, absence
926
+ * included: continuing a CLI session against another account's credentials
927
+ * is refused rather than attempted.
928
+ *
929
+ * Absent everywhere means the default scope — byte for byte the behavior
930
+ * before scopes existed. A scoped round is exec-only (the live drivers bind
931
+ * the default scoped home) and, on kimi, carries no member channel (the
932
+ * bridge declaration is written into the default scope's `mcp.json`).
933
+ */
934
+ readonly scope?: string;
935
+ /**
936
+ * The model this DELEGATION runs — `start` only. It outranks the harness's
937
+ * `model` plugin-config key, which in turn outranks the scoped
938
+ * configuration file and, last, the CLI's own default. Absent leaves that
939
+ * pre-existing order exactly as it was, so a caller that names no model
940
+ * gets byte-identical behavior.
941
+ *
942
+ * **Not accepted on `resume`.** A model belongs to the delegation, not to
943
+ * one of its rounds: the first round records what it requested and every
944
+ * later round of the same CLI session re-requests that same value (none,
945
+ * when the first round named none). Passing it to `resume` is a caller
946
+ * error and fails loud rather than switching a conversation's model
947
+ * mid-way — which the CLI would honour and the transcript would not show.
948
+ *
949
+ * A round with a model is exec-only, for the reason a scoped round is: the
950
+ * live drivers bind their model when the resident runtime spawns, and one
951
+ * runtime serves many rounds.
952
+ *
953
+ * dsh spells it `provider/model` (the shape `effectiveSettings.model`
954
+ * reports); the three CLI harnesses take whatever identifier their own CLI
955
+ * takes.
956
+ */
957
+ readonly model?: string;
958
+ }
959
+ //# sourceMappingURL=types.d.ts.map