@robota-sdk/agent-interface-session 3.0.0-beta.81

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,669 @@
1
+ import { IActionRequest, IContextWindowState, IHistoryEntry, IToolExecutionResult, IToolSchema, TActionResponse, TToolArgs, TToolParameters, TUniversalMessage, TUniversalValue } from "@robota-sdk/agent-core";
2
+ import { IUsageSnapshot, TUsageSurface } from "@robota-sdk/agent-interface-analytics";
3
+ import { ICommandListEntry, ICommandResult, TCommandInvocationSource, TCommandUiIntent } from "@robota-sdk/agent-interface-command";
4
+ import { IBackgroundJobGroupCreateRequest, IBackgroundJobGroupState, IBackgroundTaskInput, IBackgroundTaskListFilter, IBackgroundTaskLogCursor, IBackgroundTaskLogPage, IBackgroundTaskState, IExecutionWorkspaceEvent, IExecutionWorkspaceSnapshot, IExecutionWorkspaceSnapshotOptions, ISubagentJobState, TBackgroundJobGroupEvent, TBackgroundTaskEvent, TBackgroundTaskIsolation } from "@robota-sdk/agent-interface-execution";
5
+ //#region src/compact-contracts.d.ts
6
+ type TCompactTrigger = 'manual' | 'auto';
7
+ interface ICompactEvent {
8
+ trigger: TCompactTrigger;
9
+ before: IContextWindowState;
10
+ after: IContextWindowState;
11
+ }
12
+ //#endregion
13
+ //#region src/session-loop-contracts.d.ts
14
+ /** A self-paced loop's durable lifecycle, independent of its disposable wake timer. */
15
+ type TSessionLoopPhase = 'waiting' | 'pending' | 'running' | 'stopped' | 'expired';
16
+ /** Session-owned state needed to resume without replaying an uncertain iteration. */
17
+ interface ISessionLoopState {
18
+ loopId: string;
19
+ instruction: string;
20
+ /** Omitted prompts are re-resolved by the host before each iteration. */
21
+ useDefaultPrompt?: boolean;
22
+ createdAt: string;
23
+ expiresAt: string;
24
+ /** Monotonic change counter, used to reconcile an ambiguous store write. */
25
+ revision: number;
26
+ /** Incremented whenever a new opportunity to run is committed. */
27
+ generation: number;
28
+ phase: TSessionLoopPhase;
29
+ /** Required while waiting; absent once that opportunity has been consumed. */
30
+ nextAllowedAt?: string;
31
+ /** Last committed choice, in the 1 minute–1 hour self-paced range. */
32
+ delaySeconds?: number;
33
+ reason?: string;
34
+ /** Once consumed, an omitted decision cannot produce another fallback. */
35
+ fallbackUsed: boolean;
36
+ terminalReason?: string;
37
+ }
38
+ //#endregion
39
+ //#region src/prompt-file-reference-types.d.ts
40
+ /**
41
+ * Leaf type module for {@link IPromptFileReferenceRecord}.
42
+ *
43
+ * Split out of `event-contracts.ts` so `turn-contracts.ts` can depend on this type without
44
+ * importing the whole of `event-contracts.ts` (which imports from `session-contracts.ts`, which in
45
+ * turn imports from `turn-contracts.ts`) — that previously created an import cycle.
46
+ */
47
+ type TPromptFileReferenceReason = 'manual' | 'prompt-reference';
48
+ interface IPromptFileReferenceRecord {
49
+ originalReference: string;
50
+ sourcePath: string;
51
+ relativePath: string;
52
+ reason: TPromptFileReferenceReason;
53
+ depth: number;
54
+ byteLength: number;
55
+ }
56
+ //#endregion
57
+ //#region src/event-contracts.d.ts
58
+ type TSkillActivationSource = 'skill' | 'plugin';
59
+ type TSkillActivationInvocation = 'user-slash' | 'model-tool';
60
+ type TSkillActivationMode = 'inject' | 'fork';
61
+ type TSkillActivationStatus = 'started' | 'completed' | 'failed';
62
+ interface ISkillActivationEvent {
63
+ readonly type: 'skill-activation';
64
+ readonly skillName: string;
65
+ readonly source: TSkillActivationSource;
66
+ readonly invocation: TSkillActivationInvocation;
67
+ readonly mode: TSkillActivationMode;
68
+ readonly status: TSkillActivationStatus;
69
+ readonly timestamp: string;
70
+ readonly qualifiedName?: string;
71
+ readonly error?: string;
72
+ }
73
+ type TMemoryType = 'user' | 'feedback' | 'project' | 'reference';
74
+ interface IMemoryReference {
75
+ topic: string;
76
+ path: string;
77
+ score: number;
78
+ truncated: boolean;
79
+ }
80
+ interface IMemoryEvent {
81
+ type: 'memory_candidate_extracted' | 'memory_candidate_queued' | 'memory_candidate_saved' | 'memory_candidate_skipped' | 'memory_candidate_approved' | 'memory_candidate_rejected' | 'memory_retrieved';
82
+ at: string;
83
+ candidateId?: string;
84
+ topic?: string;
85
+ reason?: string;
86
+ data?: Record<string, TUniversalValue>;
87
+ }
88
+ type TContextReferenceLoadType = 'manual' | 'prompt-reference' | 'system';
89
+ type TContextReferenceStatus = 'active' | 'observed';
90
+ interface IContextReferenceItem {
91
+ id: string;
92
+ sourcePath: string;
93
+ relativePath: string;
94
+ originalReference: string;
95
+ loadType: TContextReferenceLoadType;
96
+ status: TContextReferenceStatus;
97
+ byteLength: number;
98
+ loadedAt: string;
99
+ lastUsedAt?: string;
100
+ }
101
+ //#endregion
102
+ //#region src/tool-summary-types.d.ts
103
+ /**
104
+ * Leaf type module for {@link IToolSummary}.
105
+ *
106
+ * Split out of `session-contracts.ts` so `turn-contracts.ts` can depend on this type without
107
+ * importing back from `session-contracts.ts` (which imports `IExecutionResult`/`TTurnSource` from
108
+ * `turn-contracts.ts`) — that previously created an import cycle between the two.
109
+ */
110
+ interface IToolSummary {
111
+ name: string;
112
+ args: string;
113
+ }
114
+ //#endregion
115
+ //#region src/turn-contracts.d.ts
116
+ /**
117
+ * RUNTIME-003: the identity of one submission, handed back to whoever made it.
118
+ *
119
+ * Without this a subscriber has only the session-global `complete` / `interrupted` / `error` events,
120
+ * which say that A turn ended and never which one. Two callers listening at once are answered by
121
+ * whichever fires first — measured in the MCP adapter, where the second `submit` was handed the
122
+ * running turn's response as its own.
123
+ *
124
+ * `completed` ALWAYS settles, and that is the part worth stating. A session runs one turn at a time
125
+ * and queues the rest, and a queued submission does not always get to run: the co-drive queue
126
+ * coalesces a same-driver entry into the one behind it and drops at capacity. A handle that only
127
+ * settled for submissions that ran would leave the others waiting forever, which is the hang this
128
+ * type exists to make impossible — so a submission that never runs REJECTS with `TurnNotRunError`
129
+ * and says which of those happened.
130
+ */
131
+ interface ITurnHandle {
132
+ /** Minted when the submission is accepted, and kept if it waits in the queue before running. */
133
+ readonly turnId: string;
134
+ /** Resolves with THIS submission's result; rejects with `TurnNotRunError` if it never ran. */
135
+ readonly completed: Promise<IExecutionResult>;
136
+ }
137
+ /** Why a submission never became a turn. */
138
+ type TTurnNotRunReason =
139
+ /** A later same-driver input replaced it in the queue (tail-coalesce). */
140
+ 'coalesced' |
141
+ /** The queue was at capacity when it arrived. */
142
+ 'dropped' |
143
+ /**
144
+ * The queue was cleared before it ran — abort, cancel, or session shutdown.
145
+ *
146
+ * A separate `'shutdown'` member was declared here and never produced: shutdown clears the queue
147
+ * through the same `clearPendingQueue`, so every entry it discards is already reported as
148
+ * cancelled. Review found it, and a vocabulary member no code path can emit is a promise to the
149
+ * consumer that nothing keeps — it would have them writing a branch that never runs.
150
+ */
151
+ 'cancelled';
152
+ /**
153
+ * The error a rejected `ITurnHandle.completed` carries.
154
+ *
155
+ * Declared as a SHAPE here and constructed in `@robota-sdk/agent-framework`, because an interface
156
+ * package is inert by rule — no classes, no runtime dependency edges. A consumer narrows on `name`
157
+ * and reads `reason`; it does not need the constructor to do that.
158
+ */
159
+ interface ITurnNotRunError extends Error {
160
+ readonly name: 'TurnNotRunError';
161
+ readonly turnId: string;
162
+ readonly reason: TTurnNotRunReason;
163
+ }
164
+ /**
165
+ * Is this rejection the declared "the turn never ran" outcome, or a real failure?
166
+ *
167
+ * The narrowing the comment above prescribes, written ONCE. A consumer that catches
168
+ * `completed`'s rejection has two different things in hand: an ordinary refusal, which it should
169
+ * report to its caller as an outcome, and an exception from inside a turn, which it should let
170
+ * surface. Review found the MCP adapter flattening both into a soft tool error and so hiding real
171
+ * bugs behind a message that reads like a queue decision.
172
+ *
173
+ * A pure predicate over a shape — no class, no runtime dependency edge, the same category as the
174
+ * event readers this package already exports. Each consumer spelling `error.name ===
175
+ * 'TurnNotRunError'` for itself is how a second spelling of the same question appears, and then
176
+ * disagrees.
177
+ */
178
+ declare function isTurnNotRunError(error: unknown): error is ITurnNotRunError;
179
+ /** Result of a completed prompt execution. */
180
+ interface IExecutionResult {
181
+ response: string;
182
+ /** Present only when an aborted turn resolved with a partial result; never a successful reply. */
183
+ interrupted?: true;
184
+ history: IHistoryEntry[];
185
+ toolSummaries: IToolSummary[];
186
+ contextState: IContextWindowState;
187
+ usage?: IUsageSnapshot;
188
+ promptFileReferences?: IPromptFileReferenceRecord[];
189
+ }
190
+ /**
191
+ * Origin of a turn — a human prompt, an agent-wakeup re-entry (FLOW-002), another session's
192
+ * message (PEER-002, #1809), or a host-admitted external event (#1997).
193
+ *
194
+ * `'peer'` is a MEMBER rather than something a caller encodes into the prompt text, because #1809
195
+ * requires a peer message to reach the runtime with EXPLICIT origin: an agent answering a peer must
196
+ * be able to tell that it is answering a peer rather than its own operator, and prose inside the
197
+ * input is not something code can branch on. WHICH peer it was travels in `driverId`, which stays
198
+ * display attribution and never becomes an authorization input.
199
+ *
200
+ * Declared here rather than in `session-contracts.ts`, where it used to live: that file is at its
201
+ * size ratchet and the rule is to split rather than extend, and turn origin belongs to turn identity
202
+ * — the same reasoning that created this file.
203
+ */
204
+ type TTurnSource = 'user' | 'agent-wakeup' | 'peer' | 'external';
205
+ //#endregion
206
+ //#region src/driver-contracts.d.ts
207
+ /**
208
+ * REMOTE-014 E5 co-drive attribution: a stable, SERVER-ASSIGNED id for the driver of an input/turn. It is
209
+ * DISPLAY/ATTRIBUTION ONLY — never an authorization input (the OWNER PRINCIPLE, REMOTE-006, governs
210
+ * authorization; remote == local). Remote = the E3 `deviceId`; local = {@link OWNER_DRIVER_ID}; an
211
+ * agent-wakeup/goal turn = {@link AGENT_DRIVER_ID}.
212
+ */
213
+ type TDriverId = string;
214
+ /** The local operator ("owner") driver id — the default for a human turn with no explicit driver. */
215
+ declare const OWNER_DRIVER_ID: TDriverId;
216
+ /** The reserved driver id for an autonomous (wakeup/goal/agent-initiated) turn — never the owner. */
217
+ declare const AGENT_DRIVER_ID: TDriverId;
218
+ /** REMOTE-014 E5: options for `submit` — carries the SERVER-ASSIGNED driver id for co-drive attribution. */
219
+ interface ISubmitOptions {
220
+ /** Cancels only this submission, including while queued or preparing its turn. */
221
+ readonly signal?: AbortSignal;
222
+ readonly driverId?: TDriverId;
223
+ /** Trusted product surface that accepted this turn; independent from the driver's identity. */
224
+ readonly surface?: TUsageSurface;
225
+ /**
226
+ * PEER-002 (#1809): where this turn came from, when it is not an ordinary user prompt.
227
+ *
228
+ * Carried here beside `driverId` because it is the same KIND of fact and travels with it: both
229
+ * describe the turn's origin, both are set by whoever accepted the submission, and neither is an
230
+ * authorization input. What stops a caller from simply declaring itself a peer is not this field
231
+ * — it is that a `'peer'` turn is REFUSED unless it also names the peer's driver id, so the
232
+ * origin cannot be claimed without also being attributed.
233
+ */
234
+ readonly turnSource?: TTurnSource;
235
+ /**
236
+ * Called once, synchronously, the moment the submission is accepted — queued behind a running
237
+ * turn or about to run — with the handle `submit` will later resolve to.
238
+ *
239
+ * `submit` on an idle session resolves only after the turn it started has finished, so a caller
240
+ * that must answer as soon as the input is taken (a peer's delivery ack) cannot learn acceptance
241
+ * from the returned promise. It must not throw: the turn is already accepted when it runs.
242
+ */
243
+ readonly onAccepted?: (handle: ITurnHandle) => void;
244
+ /** A `'peer'` turn only: which message it answers and where an answer to it goes. */
245
+ readonly peer?: IPeerTurnContext;
246
+ }
247
+ /**
248
+ * What a peer turn needs beyond who sent it: the route of the answer. Set by the host that admitted
249
+ * the message, never taken from it. A reply goes to `replyTo` and names `messageId`, so the model can
250
+ * answer only the session that asked, and the asker can thread the answer. It grants nothing: what
251
+ * the turn may do is the session's ordinary permissions' to decide.
252
+ */
253
+ interface IPeerTurnContext {
254
+ /** The id of the message this turn answers. */
255
+ readonly messageId: string;
256
+ /** The session id a reply goes to: the sender's. */
257
+ readonly replyTo: string;
258
+ }
259
+ /**
260
+ * CMD-004 Phase 2: a command-issued UI intent, emitted as a fire-and-forget `ui_intent` session
261
+ * event. Routed to the REQUESTING surface: `requesterDriverId` is stamped from the command-origin
262
+ * driver id passed into `executeCommand` (the REMOTE-014 E5 server-assigned id for remote surfaces;
263
+ * the active turn's driver only as a fallback for model-invoked commands). Other surfaces ignore it;
264
+ * an intent needs no answer (no parking, no response promise). Serializable.
265
+ */
266
+ interface IUiIntentEvent {
267
+ intent: TCommandUiIntent;
268
+ /** The server-assigned driver id of the surface that issued the command (routing/display-only). */
269
+ requesterDriverId?: TDriverId;
270
+ }
271
+ /**
272
+ * CMD-004 Phase 2: the session was renamed (host-executed `session-rename` action). Broadcast so
273
+ * every attached surface — including co-driving ones — updates its title. Serializable.
274
+ */
275
+ interface ISessionRenamedEvent {
276
+ name: string;
277
+ }
278
+ //#endregion
279
+ //#region src/session-event-map.d.ts
280
+ /** Permission handler result — SDK-owned type (mirrors agent-sessions TPermissionResult).
281
+ * true = allow, false = deny, 'allow-session' = allow and remember for this session,
282
+ * 'allow-project' = allow and persist to the project's local settings (location owned by the consuming layer). */
283
+ type TPermissionResultValue = boolean | 'allow-session' | 'allow-project';
284
+ /** A single diff line for Edit tool display. */
285
+ interface IDiffLine {
286
+ type: 'add' | 'remove' | 'context' | 'hunk';
287
+ text: string;
288
+ lineNumber: number;
289
+ }
290
+ /** Tool execution state visible to clients. */
291
+ interface IToolState {
292
+ toolName: string;
293
+ firstArg: string;
294
+ isRunning: boolean;
295
+ result?: 'success' | 'error' | 'denied';
296
+ diffLines?: IDiffLine[];
297
+ diffFile?: string;
298
+ toolResultData?: string;
299
+ executionId?: string;
300
+ }
301
+ /** Permission handler delegate — clients provide their own UI. */
302
+ type TInteractivePermissionHandler = (toolName: string, toolArgs: TToolArgs) => Promise<TPermissionResultValue>;
303
+ /**
304
+ * REMOTE-007 (B4-2a) — transport-neutral permission/ask.
305
+ *
306
+ * The session emits a pending-prompt event and awaits a `resolve*(id)` reply instead of invoking a
307
+ * single injected callback, so ANY attached surface (local TUI, a WS/WebRTC driver, a web UI) can
308
+ * render + answer the SAME prompt. `id` correlates the emit with its resolve; the session parks the
309
+ * awaiting promise and the first `resolvePermission`/`resolveAsk(id, …)` settles it (later resolves for
310
+ * a settled id are no-ops). `prompt_resolved` lets a co-driving second surface dismiss a prompt the
311
+ * first already answered.
312
+ */
313
+ /** A tool call awaiting a permission decision. Serializable — crosses the transport boundary unchanged. */
314
+ interface IPermissionRequestEvent {
315
+ id: string;
316
+ toolName: string;
317
+ toolArgs: TToolArgs;
318
+ /** Whether this session can durably persist a project-scoped approval. */
319
+ canPersistProjectPermission?: boolean;
320
+ /** REMOTE-014 E5: the driver whose turn raised this prompt (display-only). */
321
+ requesterDriverId?: TDriverId;
322
+ }
323
+ /** An "ask the user" request (command- or tool-issued) awaiting an answer. Serializable. */
324
+ interface IAskRequestEvent {
325
+ id: string;
326
+ request: IActionRequest;
327
+ /** REMOTE-014 E5: the driver whose turn raised this prompt (display-only). */
328
+ requesterDriverId?: TDriverId;
329
+ }
330
+ /** A pending prompt (permission or ask) that has been settled — attached surfaces dismiss it. */
331
+ interface IPromptResolvedEvent {
332
+ id: string;
333
+ /** REMOTE-014 E5: the driver who answered the prompt (server-assigned; display-only). */
334
+ answererDriverId?: TDriverId;
335
+ }
336
+ /** Emitted when a context file is found stale and re-read before a turn. */
337
+ interface IContextFileRefreshedEvent {
338
+ filePath: string;
339
+ }
340
+ /** SELFHOST-007: a checkpoint/branch lifecycle transition a surface renders. */
341
+ type TCheckpointEventKind = `checkpoint_${'created' | 'restored' | 'rolled_back'}`;
342
+ type TBranchEventKind = `branch_${'forked' | 'switched'}`;
343
+ interface IBranchEvent {
344
+ kind: TCheckpointEventKind | TBranchEventKind;
345
+ /** The checkpoint id the transition concerns. */
346
+ checkpointId: string;
347
+ /** The branch the checkpoint belongs to (or was switched/forked to). */
348
+ branchId: string;
349
+ }
350
+ /**
351
+ * SELFHOST-007: the persisted active-branch pointer — added to the resumable session record (beside
352
+ * `goal`) so a branch survives `--resume`. Pure data. The branch TREE persists in the agent-framework
353
+ * checkpoint manifest; a resume whose pointer references a `branchId`/`checkpointId` absent from that
354
+ * manifest store must degrade gracefully (fall back to the linear HEAD), not crash.
355
+ */
356
+ interface IActiveBranchPointer {
357
+ branchId: string;
358
+ checkpointId: string;
359
+ }
360
+ /** Events emitted by InteractiveSession. */
361
+ interface IInteractiveSessionEvents {
362
+ text_delta: (delta: string) => void;
363
+ tool_start: (state: IToolState) => void;
364
+ tool_end: (state: IToolState) => void;
365
+ thinking: (isThinking: boolean) => void;
366
+ complete: (result: IExecutionResult) => void;
367
+ error: (error: Error) => void;
368
+ context_update: (state: IContextWindowState) => void;
369
+ compact: (event: ICompactEvent) => void;
370
+ interrupted: (result: IExecutionResult) => void;
371
+ skill_activation: (event: ISkillActivationEvent) => void;
372
+ background_task_event: (event: TBackgroundTaskEvent) => void;
373
+ background_job_group_event: (event: TBackgroundJobGroupEvent) => void;
374
+ execution_workspace_event: (event: IExecutionWorkspaceEvent) => void;
375
+ user_message: (content: string) => void;
376
+ /** Emitted at the start of each turn with its origin (human prompt vs agent-wakeup, FLOW-002). */
377
+ turn_source: (source: TTurnSource) => void;
378
+ /** Emitted when a context file (AGENTS.md or CLAUDE.md) is refreshed due to staleness. */
379
+ context_file_refreshed: (event: IContextFileRefreshedEvent) => void;
380
+ /** Emitted for every automatic-memory pipeline event (capture, approval, retrieval). */
381
+ memory_event: (event: IMemoryEvent) => void;
382
+ /** Emitted on every autonomous goal lifecycle transition (start, per-iteration, stop) — GOAL-001. */
383
+ goal_event: (event: IGoalEvent) => void;
384
+ /** Emitted on every plan-mode lifecycle transition (created, approved, reverted) — SELFHOST-002. */
385
+ plan_event: (event: IPlanApprovalEvent) => void;
386
+ /** Emitted after every persisted checkpoint/branch transition — SELFHOST-007. */
387
+ branch_event: (event: IBranchEvent) => void;
388
+ /** REMOTE-007: a tool call awaits a permission decision; answer via `resolvePermission(id, …)`. */
389
+ permission_request: (event: IPermissionRequestEvent) => void;
390
+ /** REMOTE-007: an "ask the user" request awaits an answer; answer via `resolveAsk(id, …)`. */
391
+ ask_request: (event: IAskRequestEvent) => void;
392
+ /** REMOTE-007: a pending prompt was settled (by any surface); attached surfaces dismiss it. */
393
+ prompt_resolved: (event: IPromptResolvedEvent) => void;
394
+ /** CMD-004 Phase 2: a command-issued UI intent — the requesting surface renders it (fire-and-forget). */
395
+ ui_intent: (event: IUiIntentEvent) => void;
396
+ /** CMD-004 Phase 2: the session was renamed host-side — all surfaces update their titles. */
397
+ session_renamed: (event: ISessionRenamedEvent) => void;
398
+ /** CMD-004 Phase 2: the conversation history was cleared host-side — all surfaces refresh transcripts. */
399
+ history_cleared: () => void;
400
+ }
401
+ type TInteractiveEventName = keyof IInteractiveSessionEvents;
402
+ /**
403
+ * Lifecycle status of an autonomous goal (GOAL-001).
404
+ * `active` while the agent is pursuing it; terminal otherwise.
405
+ */
406
+ type TGoalStatus = 'active' | 'satisfied' | 'stopped';
407
+ /**
408
+ * Why an autonomous goal stopped (GOAL-001). `satisfied` = the agent signalled completion;
409
+ * `max-iterations` = the turn budget was exhausted; `cancelled` = the user stopped it;
410
+ * `no-progress` = consecutive idle turns detected a stall (convergence guard).
411
+ */
412
+ type TGoalStopReason = 'satisfied' | 'max-iterations' | 'cancelled' | 'no-progress';
413
+ /** One recorded iteration of goal pursuit (GOAL-001). */
414
+ interface IGoalProgressEntry {
415
+ iteration: number;
416
+ signal: 'continue' | 'satisfied';
417
+ reason: string;
418
+ }
419
+ /**
420
+ * Persisted state of an autonomous objective-pursuit loop (GOAL-001). Stored in the session
421
+ * record so an in-flight goal survives `--resume`.
422
+ */
423
+ interface IGoalState {
424
+ id: string;
425
+ objective: string;
426
+ status: TGoalStatus;
427
+ stopReason?: TGoalStopReason;
428
+ iterations: number;
429
+ maxIterations: number;
430
+ startedAt: string;
431
+ progress: IGoalProgressEntry[];
432
+ }
433
+ /** Observability event for the goal loop (GOAL-001). */
434
+ interface IGoalEvent {
435
+ type: 'goal_started' | 'goal_progress' | 'goal_stopped';
436
+ goal: IGoalState;
437
+ }
438
+ /** Execution status of one plan step (SELFHOST-002 plan-mode). */
439
+ type TPlanStepStatus = 'pending' | 'in-progress' | 'done';
440
+ /** One reviewable step in a plan artifact (SELFHOST-002 plan-mode). */
441
+ interface IPlanStep {
442
+ /** Stable id within the plan. */
443
+ id: string;
444
+ /** Human-readable description of the step. */
445
+ description: string;
446
+ /** Step status as the plan is executed. */
447
+ status: TPlanStepStatus;
448
+ }
449
+ /**
450
+ * Lifecycle phase of a plan artifact (SELFHOST-002). `planning` = drafted in `plan` mode (read-only
451
+ * tools); `awaiting-approval` = presented for review; `executing` = approved, edits unblocked per
452
+ * `acceptEdits` (shell still per-call confirmed); `completed` = finished (mode reverts to `plan`).
453
+ */
454
+ type TPlanPhase = 'planning' | 'awaiting-approval' | 'executing' | 'completed';
455
+ /**
456
+ * A reviewable plan/todo artifact produced during plan mode (SELFHOST-002). Persisted in the
457
+ * session record beside {@link IGoalState} so an in-flight plan survives resume. Pure data — the
458
+ * mutation block stays the existing `plan` permission mode (no artifact-carried enforcement).
459
+ */
460
+ interface IPlanArtifact {
461
+ id: string;
462
+ /** The objective the plan addresses. */
463
+ objective: string;
464
+ /** The ordered plan steps. */
465
+ steps: IPlanStep[];
466
+ /** Current lifecycle phase. */
467
+ phase: TPlanPhase;
468
+ createdAt: string;
469
+ /** Set when the plan was approved (phase → `executing`). */
470
+ approvedAt?: string;
471
+ }
472
+ /**
473
+ * Plan-mode lifecycle event (SELFHOST-002): emitted as a plan artifact is created, approved
474
+ * (mode flips `plan → acceptEdits`), or reverted (`→ plan`). Carries the artifact snapshot,
475
+ * mirroring how {@link IGoalEvent} carries the goal state. The event only OBSERVES the phase
476
+ * transition — the mutation gate stays the existing `plan` permission mode.
477
+ *
478
+ * Declared here (rather than `event-contracts.ts`, where it used to live) because it carries
479
+ * {@link IPlanArtifact}, declared in this file; `event-contracts.ts` re-exports it for
480
+ * compatibility.
481
+ */
482
+ interface IPlanApprovalEvent {
483
+ type: 'plan_created' | 'plan_approved' | 'plan_reverted';
484
+ plan: IPlanArtifact;
485
+ }
486
+ //#endregion
487
+ //#region src/session-capability-contracts.d.ts
488
+ interface ISessionLifecycle {
489
+ /** True once the underlying session has been initialized. */
490
+ readonly isInitialized: boolean;
491
+ shutdown(options?: {
492
+ reason?: string;
493
+ message?: string;
494
+ }): Promise<void>;
495
+ }
496
+ interface ISessionTurnSubmission {
497
+ submit(input: string, displayInput?: string, rawInput?: string, options?: ISubmitOptions): Promise<ITurnHandle>;
498
+ }
499
+ interface ISessionTurnControl {
500
+ abort(): void;
501
+ cancelQueue(): void;
502
+ }
503
+ interface ISessionGoal {
504
+ setGoal(objective: string, options?: {
505
+ maxIterations?: number;
506
+ noProgressLimit?: number;
507
+ }): Promise<IGoalState>;
508
+ getGoalState(): IGoalState | null;
509
+ cancelGoal(): IGoalState | null;
510
+ }
511
+ interface ISessionExecutionState {
512
+ isExecuting(): boolean;
513
+ getPendingPrompt(): string | null;
514
+ getPendingCount(): number;
515
+ }
516
+ interface ISessionDriverAttribution {
517
+ getActiveDriverId(): TDriverId | null;
518
+ }
519
+ interface ISessionConversationRead {
520
+ getMessages(): TUniversalMessage[];
521
+ getContextState(): IContextWindowState;
522
+ }
523
+ interface ISessionIdentity {
524
+ getSession(): {
525
+ getSessionId(): string;
526
+ };
527
+ }
528
+ interface ISessionWorkspaceLocation {
529
+ getCwd(): string;
530
+ }
531
+ /** Direct execution uses the same permission-wrapped runtime as model tool calls. */
532
+ interface ISessionRuntimeTools {
533
+ listRuntimeTools(): Promise<IToolSchema[]>;
534
+ invokeRuntimeTool(name: string, parameters: TToolParameters, options?: {
535
+ signal?: AbortSignal;
536
+ }): Promise<IToolExecutionResult>;
537
+ }
538
+ interface ISessionCommands {
539
+ executeCommand(name: string, args: string, source?: TCommandInvocationSource, originDriverId?: TDriverId): Promise<ICommandResult | null>;
540
+ listCommands(): ICommandListEntry[];
541
+ }
542
+ interface ISessionEvents {
543
+ on<E extends TInteractiveEventName>(event: E, handler: IInteractiveSessionEvents[E]): void;
544
+ off<E extends TInteractiveEventName>(event: E, handler: IInteractiveSessionEvents[E]): void;
545
+ }
546
+ interface ISessionPromptResolution {
547
+ resolvePermission(id: string, result: TPermissionResultValue, answererDriverId?: TDriverId): void;
548
+ resolveAsk(id: string, response: TActionResponse, answererDriverId?: TDriverId): void;
549
+ }
550
+ interface ISessionBackgroundTasks {
551
+ listBackgroundTasks(filter?: IBackgroundTaskListFilter): IBackgroundTaskState[];
552
+ getBackgroundTask(taskId: string): IBackgroundTaskState | undefined;
553
+ cancelBackgroundTask(taskId: string, reason?: string): Promise<void>;
554
+ closeBackgroundTask(taskId: string): Promise<void>;
555
+ sendBackgroundTask(taskId: string, input: IBackgroundTaskInput): Promise<void>;
556
+ readBackgroundTaskLog(taskId: string, cursor?: IBackgroundTaskLogCursor): Promise<IBackgroundTaskLogPage>;
557
+ }
558
+ interface ISessionBackgroundGroups {
559
+ listBackgroundJobGroups(): IBackgroundJobGroupState[];
560
+ getBackgroundJobGroup(groupId: string): IBackgroundJobGroupState | undefined;
561
+ createBackgroundJobGroup(input: Omit<IBackgroundJobGroupCreateRequest, 'parentSessionId'>): IBackgroundJobGroupState;
562
+ waitBackgroundJobGroup(groupId: string): Promise<IBackgroundJobGroupState>;
563
+ }
564
+ interface ISessionExecutionWorkspace {
565
+ getExecutionWorkspaceSnapshot(options?: IExecutionWorkspaceSnapshotOptions): IExecutionWorkspaceSnapshot;
566
+ }
567
+ interface ISessionAgentJobs {
568
+ listAgentDefinitions(): Array<{
569
+ name: string;
570
+ description: string;
571
+ }>;
572
+ listAgentJobs(): ISubagentJobState[];
573
+ spawnAgentJob(input: {
574
+ agentType: string;
575
+ label: string;
576
+ mode: 'foreground' | 'background';
577
+ prompt: string;
578
+ model?: string;
579
+ isolation?: TBackgroundTaskIsolation;
580
+ }): Promise<ISubagentJobState>;
581
+ sendAgentJob(taskId: string, prompt: string): Promise<void>;
582
+ cancelAgentJob(taskId: string, reason?: string): Promise<void>;
583
+ closeAgentJob(taskId: string): Promise<void>;
584
+ }
585
+ interface ISessionCapabilityMap {
586
+ lifecycle: ISessionLifecycle;
587
+ turnSubmission: ISessionTurnSubmission;
588
+ turnControl: ISessionTurnControl;
589
+ goal: ISessionGoal;
590
+ executionState: ISessionExecutionState;
591
+ driverAttribution: ISessionDriverAttribution;
592
+ conversationRead: ISessionConversationRead;
593
+ identity: ISessionIdentity;
594
+ workspaceLocation: ISessionWorkspaceLocation;
595
+ commands: ISessionCommands;
596
+ runtimeTools: ISessionRuntimeTools;
597
+ events: ISessionEvents;
598
+ promptResolution: ISessionPromptResolution;
599
+ backgroundTasks: ISessionBackgroundTasks;
600
+ backgroundGroups: ISessionBackgroundGroups;
601
+ executionWorkspace: ISessionExecutionWorkspace;
602
+ agentJobs: ISessionAgentJobs;
603
+ }
604
+ declare const SESSION_CAPABILITY_MEMBER_KEYS: Readonly<{
605
+ lifecycle: readonly ["isInitialized", "shutdown"];
606
+ turnSubmission: readonly ["submit"];
607
+ turnControl: readonly ["abort", "cancelQueue"];
608
+ goal: readonly ["setGoal", "getGoalState", "cancelGoal"];
609
+ executionState: readonly ["isExecuting", "getPendingPrompt", "getPendingCount"];
610
+ driverAttribution: readonly ["getActiveDriverId"];
611
+ conversationRead: readonly ["getMessages", "getContextState"];
612
+ identity: readonly ["getSession"];
613
+ workspaceLocation: readonly ["getCwd"];
614
+ commands: readonly ["executeCommand", "listCommands"];
615
+ runtimeTools: readonly ["listRuntimeTools", "invokeRuntimeTool"];
616
+ events: readonly ["on", "off"];
617
+ promptResolution: readonly ["resolvePermission", "resolveAsk"];
618
+ backgroundTasks: readonly ["listBackgroundTasks", "getBackgroundTask", "cancelBackgroundTask", "closeBackgroundTask", "sendBackgroundTask", "readBackgroundTaskLog"];
619
+ backgroundGroups: readonly ["listBackgroundJobGroups", "getBackgroundJobGroup", "createBackgroundJobGroup", "waitBackgroundJobGroup"];
620
+ executionWorkspace: readonly ["getExecutionWorkspaceSnapshot"];
621
+ agentJobs: readonly ["listAgentDefinitions", "listAgentJobs", "spawnAgentJob", "sendAgentJob", "cancelAgentJob", "closeAgentJob"];
622
+ }>;
623
+ type TUnionToIntersection<T> = (T extends T ? (value: T) => void : never) extends ((value: infer TIntersection) => void) ? TIntersection : never;
624
+ type TSelectedSessionPorts<TCapabilities extends Partial<ISessionCapabilityMap>> = TUnionToIntersection<Exclude<TCapabilities[keyof TCapabilities], undefined>>;
625
+ interface ISessionCapabilityHost<TCapabilities extends Partial<ISessionCapabilityMap> = Partial<ISessionCapabilityMap>> {
626
+ readonly capabilities: Readonly<TCapabilities>;
627
+ }
628
+ type TSessionCapabilityHost<TCapabilities extends Partial<ISessionCapabilityMap>> = ISessionCapabilityHost<TCapabilities> & TSelectedSessionPorts<TCapabilities>;
629
+ type TSessionCapabilityReadResult<TCapability> = Readonly<{
630
+ provided: false;
631
+ }> | Readonly<{
632
+ provided: true;
633
+ value: TCapability;
634
+ }>;
635
+ //#endregion
636
+ //#region src/session-contracts.d.ts
637
+ /** Aggregate session interface composed from its named capability ports. */
638
+ interface IInteractiveSession extends ISessionLifecycle, ISessionTurnSubmission, ISessionTurnControl, ISessionGoal, ISessionExecutionState, ISessionDriverAttribution, ISessionConversationRead, ISessionIdentity, ISessionWorkspaceLocation, ISessionCommands, ISessionRuntimeTools, ISessionEvents, ISessionPromptResolution, ISessionBackgroundTasks, ISessionBackgroundGroups, ISessionExecutionWorkspace, ISessionAgentJobs {}
639
+ /** Persisted record for a resumable interactive session. */
640
+ interface IInteractiveSessionRecord {
641
+ id: string;
642
+ name?: string;
643
+ cwd: string;
644
+ createdAt: string;
645
+ updatedAt: string;
646
+ messages: TUniversalMessage[];
647
+ history?: IHistoryEntry[];
648
+ systemPrompt?: string;
649
+ toolSchemas?: IToolSchema[];
650
+ backgroundTasks?: IBackgroundTaskState[];
651
+ backgroundTaskEvents?: TBackgroundTaskEvent[];
652
+ backgroundJobGroups?: IBackgroundJobGroupState[];
653
+ backgroundJobGroupEvents?: TBackgroundJobGroupEvent[];
654
+ sessionLoops?: ISessionLoopState[];
655
+ skillActivationEvents?: ISkillActivationEvent[];
656
+ memoryEvents?: IMemoryEvent[];
657
+ usedMemoryReferences?: IMemoryReference[];
658
+ contextReferences?: IContextReferenceItem[];
659
+ sandboxSnapshotId?: string;
660
+ /** In-flight autonomous goal, persisted so it survives resume (GOAL-001). */
661
+ goal?: IGoalState;
662
+ /** In-flight plan artifact, persisted so it survives resume (SELFHOST-002 plan-mode). */
663
+ plan?: IPlanArtifact;
664
+ /** Active checkpoint branch pointer, persisted so a branch survives resume (SELFHOST-007). */
665
+ activeBranch?: IActiveBranchPointer;
666
+ }
667
+ //#endregion
668
+ export { TDriverId as $, IGoalEvent as A, TGoalStatus as B, TSessionCapabilityHost as C, TCompactTrigger as Ct, IBranchEvent as D, IAskRequestEvent as E, IPlanApprovalEvent as F, TPlanPhase as G, TInteractiveEventName as H, IPlanArtifact as I, IPeerTurnContext as J, TPlanStepStatus as K, IPlanStep as L, IGoalState as M, IInteractiveSessionEvents as N, IContextFileRefreshedEvent as O, IPermissionRequestEvent as P, OWNER_DRIVER_ID as Q, IPromptResolvedEvent as R, SESSION_CAPABILITY_MEMBER_KEYS as S, ICompactEvent as St, IActiveBranchPointer as T, TInteractivePermissionHandler as U, TGoalStopReason as V, TPermissionResultValue as W, ISubmitOptions as X, ISessionRenamedEvent as Y, IUiIntentEvent as Z, ISessionPromptResolution as _, TSkillActivationStatus as _t, ISessionBackgroundTasks as a, isTurnNotRunError as at, ISessionTurnSubmission as b, ISessionLoopState as bt, ISessionCommands as c, IMemoryEvent as ct, ISessionEvents as d, TContextReferenceLoadType as dt, IExecutionResult as et, ISessionExecutionState as f, TContextReferenceStatus as ft, ISessionLifecycle as g, TSkillActivationSource as gt, ISessionIdentity as h, TSkillActivationMode as ht, ISessionBackgroundGroups as i, TTurnSource as it, IGoalProgressEntry as j, IDiffLine as k, ISessionConversationRead as l, IMemoryReference as lt, ISessionGoal as m, TSkillActivationInvocation as mt, IInteractiveSessionRecord as n, ITurnNotRunError as nt, ISessionCapabilityHost as o, IToolSummary as ot, ISessionExecutionWorkspace as p, TMemoryType as pt, AGENT_DRIVER_ID as q, ISessionAgentJobs as r, TTurnNotRunReason as rt, ISessionCapabilityMap as s, IContextReferenceItem as st, IInteractiveSession as t, ITurnHandle as tt, ISessionDriverAttribution as u, ISkillActivationEvent as ut, ISessionRuntimeTools as v, IPromptFileReferenceRecord as vt, TSessionCapabilityReadResult as w, ISessionWorkspaceLocation as x, TSessionLoopPhase as xt, ISessionTurnControl as y, TPromptFileReferenceReason as yt, IToolState as z };
669
+ //# sourceMappingURL=session-contracts-BVCzd3uY.d.ts.map