@nuvin/session 0.1.0-rc.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-3IPZO7LP.js +66 -0
- package/dist/chunk-7G3R25NS.js +6 -0
- package/dist/chunk-DGC7JSCG.js +0 -0
- package/dist/chunk-FR3R66RD.js +678 -0
- package/dist/chunk-UVJIG4DT.js +17 -0
- package/dist/client/directory.d.ts +141 -0
- package/dist/client/directory.d.ts.map +1 -0
- package/dist/client/endpoint.d.ts +33 -0
- package/dist/client/endpoint.d.ts.map +1 -0
- package/dist/client/index.d.ts +8 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +1060 -0
- package/dist/client/session-client.d.ts +60 -0
- package/dist/client/session-client.d.ts.map +1 -0
- package/dist/client/socket.d.ts +38 -0
- package/dist/client/socket.d.ts.map +1 -0
- package/dist/client/transport.d.ts +9 -0
- package/dist/client/transport.d.ts.map +1 -0
- package/dist/client/uds-socket.d.ts +23 -0
- package/dist/client/uds-socket.d.ts.map +1 -0
- package/dist/client/websocket.d.ts +54 -0
- package/dist/client/websocket.d.ts.map +1 -0
- package/dist/controller/agent-channel.d.ts +58 -0
- package/dist/controller/agent-channel.d.ts.map +1 -0
- package/dist/controller/index.d.ts +3 -0
- package/dist/controller/index.d.ts.map +1 -0
- package/dist/controller/index.js +441 -0
- package/dist/controller/session-controller.d.ts +147 -0
- package/dist/controller/session-controller.d.ts.map +1 -0
- package/dist/controller/test-utils.d.ts +15 -0
- package/dist/controller/test-utils.d.ts.map +1 -0
- package/dist/grant/index.d.ts +33 -0
- package/dist/grant/index.d.ts.map +1 -0
- package/dist/grant/index.js +12 -0
- package/dist/protocol/index.d.ts +3 -0
- package/dist/protocol/index.d.ts.map +1 -0
- package/dist/protocol/index.js +7 -0
- package/dist/protocol/types.d.ts +855 -0
- package/dist/protocol/types.d.ts.map +1 -0
- package/dist/protocol/version.d.ts +8 -0
- package/dist/protocol/version.d.ts.map +1 -0
- package/dist/state/approvals.d.ts +34 -0
- package/dist/state/approvals.d.ts.map +1 -0
- package/dist/state/dir-access.d.ts +9 -0
- package/dist/state/dir-access.d.ts.map +1 -0
- package/dist/state/index.d.ts +6 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +48 -0
- package/dist/state/json.d.ts +7 -0
- package/dist/state/json.d.ts.map +1 -0
- package/dist/state/messages.d.ts +105 -0
- package/dist/state/messages.d.ts.map +1 -0
- package/dist/state/session.d.ts +9 -0
- package/dist/state/session.d.ts.map +1 -0
- package/dist/state/tool-preview.d.ts +31 -0
- package/dist/state/tool-preview.d.ts.map +1 -0
- package/dist/state/tool-preview.js +300 -0
- package/dist/state/workflow-view.d.ts +10 -0
- package/dist/state/workflow-view.d.ts.map +1 -0
- package/dist/test-utils/fake-relay.d.ts +24 -0
- package/dist/test-utils/fake-relay.d.ts.map +1 -0
- package/dist/test-utils/index.d.ts +2 -0
- package/dist/test-utils/index.d.ts.map +1 -0
- package/dist/test-utils/index.js +250 -0
- package/dist/ui/history-grouping.d.ts +36 -0
- package/dist/ui/history-grouping.d.ts.map +1 -0
- package/dist/ui/index.d.ts +3 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +135 -0
- package/dist/ui/picker-rows.d.ts +62 -0
- package/dist/ui/picker-rows.d.ts.map +1 -0
- package/package.json +70 -0
|
@@ -0,0 +1,855 @@
|
|
|
1
|
+
import type { AgentMetricsSnapshot } from "@nuvin/agent-core/agent";
|
|
2
|
+
import type { AgentEvent, AgentInput, AskUserAnswers, AskUserQuestionRequest, JsonObject, JsonValue } from "@nuvin/agent-core/shared";
|
|
3
|
+
import type { ApprovalQueueState } from "../state/approvals.ts";
|
|
4
|
+
import type { MessageState, ToolMessageStatus } from "../state/messages.ts";
|
|
5
|
+
/** Delegated child-agent context, mirrored from the agent channel. */
|
|
6
|
+
export type WireDelegationScope = {
|
|
7
|
+
agentId: string;
|
|
8
|
+
parentToolCallId: string;
|
|
9
|
+
};
|
|
10
|
+
/** A tool call wants a path outside allowedDirs; the user may grant a dir. */
|
|
11
|
+
export type DirAccessRequest = {
|
|
12
|
+
/** Absolute resolved path the tool asked for. */
|
|
13
|
+
requestedPath: string;
|
|
14
|
+
/** Default grant offered to the user (parent dir for file paths). */
|
|
15
|
+
proposedDir: string;
|
|
16
|
+
};
|
|
17
|
+
/** Wire-safe pending approval: IDs and display data only — no resolve fn. */
|
|
18
|
+
export type ApprovalDescriptor = {
|
|
19
|
+
agentId: string;
|
|
20
|
+
/** Present when this approval is a directory-access grant prompt. */
|
|
21
|
+
dirAccess?: DirAccessRequest;
|
|
22
|
+
input?: JsonObject;
|
|
23
|
+
nickname?: string;
|
|
24
|
+
parentToolCallId?: string;
|
|
25
|
+
summary: string;
|
|
26
|
+
toolCallId: string;
|
|
27
|
+
toolName: string;
|
|
28
|
+
};
|
|
29
|
+
/** Wire-safe pending question. */
|
|
30
|
+
export type QuestionDescriptor = {
|
|
31
|
+
questionId: string;
|
|
32
|
+
request: AskUserQuestionRequest;
|
|
33
|
+
};
|
|
34
|
+
/** Display metadata replicated to clients alongside session state. */
|
|
35
|
+
export type SessionMeta = {
|
|
36
|
+
approvalMode: string;
|
|
37
|
+
/**
|
|
38
|
+
* Total context-window token budget for the active model, when known. Absent
|
|
39
|
+
* when no provider/model is configured or the model's limit is unknown
|
|
40
|
+
* (spec §4.3). The TUI uses it to render the context gauge.
|
|
41
|
+
*/
|
|
42
|
+
contextWindowLimit?: number;
|
|
43
|
+
cwd: string;
|
|
44
|
+
modelName: string;
|
|
45
|
+
/** Active main-agent persona id (spec §4.3); `"default"` for the built-in coordinator. */
|
|
46
|
+
persona: string;
|
|
47
|
+
/**
|
|
48
|
+
* Active config profile the daemon runtime resolves config/agents/workspaces
|
|
49
|
+
* under (the `profiles.yaml` active profile). Display-only — clients render it
|
|
50
|
+
* as a header indicator. Omitted for the built-in `"default"` profile so the
|
|
51
|
+
* common case carries nothing on the wire.
|
|
52
|
+
*/
|
|
53
|
+
profile?: string;
|
|
54
|
+
/**
|
|
55
|
+
* Resolved workspace name for this session (spec §7 — fixed at session
|
|
56
|
+
* creation). The session's active provider/model are fully determined by this
|
|
57
|
+
* workspace. Absent on legacy/host-less seeds that did not resolve one.
|
|
58
|
+
*/
|
|
59
|
+
workspace?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Current human-readable session topic; absent until the first user message
|
|
62
|
+
* or an UpdateTopic call sets it.
|
|
63
|
+
*/
|
|
64
|
+
topic?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Active provider reasoning (thinking) level (LOW/MEDIUM/HIGH), display-only.
|
|
67
|
+
* Absent when thinking is OFF/unset so the common case carries nothing on the
|
|
68
|
+
* wire. Clients render it as a suffix to the model name.
|
|
69
|
+
*/
|
|
70
|
+
thinking?: string;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Wire-safe descriptor for a server-executed slash command. The daemon sends
|
|
74
|
+
* these in the welcome frame (spec §4.1); in-process they ride the attach
|
|
75
|
+
* snapshot. The Composer merges these with client-local command names for
|
|
76
|
+
* autocomplete. No execution logic crosses the wire — only display metadata.
|
|
77
|
+
*/
|
|
78
|
+
export type SlashCommandDescriptor = {
|
|
79
|
+
name: string;
|
|
80
|
+
description: string;
|
|
81
|
+
argumentHint?: string;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Raw model-completion data for the `/model` autocomplete popup, returned by
|
|
85
|
+
* the `complete-models` command (spec §6). The daemon gathers it from its
|
|
86
|
+
* runtime (authenticated providers + each provider's live model list + recent
|
|
87
|
+
* selections); the client builds the grouped ComboBox items. JSON-safe by rule
|
|
88
|
+
* — the round-trip test guards it.
|
|
89
|
+
*/
|
|
90
|
+
export type ModelCompletion = {
|
|
91
|
+
/** Authenticated providers, in registration order. */
|
|
92
|
+
providers: string[];
|
|
93
|
+
/** Per-provider model lists, keyed by provider. */
|
|
94
|
+
perProvider: Record<string, {
|
|
95
|
+
id: string;
|
|
96
|
+
name?: string;
|
|
97
|
+
}[]>;
|
|
98
|
+
/** Recently selected models (most recent first), for the "Recent" group. */
|
|
99
|
+
recentModels: {
|
|
100
|
+
provider: string;
|
|
101
|
+
model: string;
|
|
102
|
+
}[];
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* The replicated session state. Everything here survives JSON round-trip.
|
|
106
|
+
* The server holds exactly this plus private side tables (resolvers, queue
|
|
107
|
+
* texts, abort controller) that never cross the wire.
|
|
108
|
+
*/
|
|
109
|
+
export type SessionViewState = {
|
|
110
|
+
approval: ApprovalQueueState<ApprovalDescriptor>;
|
|
111
|
+
/**
|
|
112
|
+
* Active MCP OAuth login flow (spec §10/§12), or null when no login is in
|
|
113
|
+
* flight. Set/cleared by `auth-flow` events; the client renders McpAuthModal
|
|
114
|
+
* from it. NOT part of the message transcript.
|
|
115
|
+
*/
|
|
116
|
+
authFlow: McpAuthFlowState | null;
|
|
117
|
+
busy: boolean;
|
|
118
|
+
messages: MessageState;
|
|
119
|
+
meta: SessionMeta;
|
|
120
|
+
/**
|
|
121
|
+
* Latest replicated agent metrics (token/usage counters), or null before the
|
|
122
|
+
* first `metrics` event (spec §4.3). The TUI renders this in the status
|
|
123
|
+
* footer; it is NOT part of the message transcript.
|
|
124
|
+
*/
|
|
125
|
+
metrics: AgentMetricsSnapshot | null;
|
|
126
|
+
queuedCount: number;
|
|
127
|
+
/**
|
|
128
|
+
* Messages waiting in the auto-send queue while a turn runs, in send order.
|
|
129
|
+
* Reduced from `turn-status.queued`; UI-only, never agent context. `[]` when
|
|
130
|
+
* nothing is queued.
|
|
131
|
+
*/
|
|
132
|
+
queued: QueuedMessageView[];
|
|
133
|
+
/**
|
|
134
|
+
* Reduced live summaries of background workflow runs, keyed by runId (spec
|
|
135
|
+
* §8.2/§8.3). Folded from `workflow-progress` events; UI-only, NEVER part of
|
|
136
|
+
* the message transcript or agent context. `{}` until the first run emits.
|
|
137
|
+
*/
|
|
138
|
+
workflows: Record<string, WorkflowViewState>;
|
|
139
|
+
question: {
|
|
140
|
+
active: QuestionDescriptor | null;
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
export type SessionSnapshot = {
|
|
144
|
+
seq: number;
|
|
145
|
+
state: SessionViewState;
|
|
146
|
+
/**
|
|
147
|
+
* Descriptors for server-executed slash commands, surfaced to the client for
|
|
148
|
+
* Composer autocomplete. In-process this is the stand-in for the daemon's
|
|
149
|
+
* `welcome.serverCommands` (spec §4.1). Empty when the host registers none.
|
|
150
|
+
*/
|
|
151
|
+
serverCommands: SlashCommandDescriptor[];
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* Why an approval settled without (or with) a human decision.
|
|
155
|
+
* "client": a connected client decided via decide-approval.
|
|
156
|
+
* "abort": the turn ended (user abort, error, or session close) and pending
|
|
157
|
+
* approvals were flushed as rejected without a decision.
|
|
158
|
+
*/
|
|
159
|
+
export type ApprovalSettledBy = "abort" | "client";
|
|
160
|
+
/**
|
|
161
|
+
* Wire-safe MCP OAuth login flow state (spec §10/§12). The daemon drives the
|
|
162
|
+
* flow and publishes each state change as an `auth-flow` event; the client
|
|
163
|
+
* renders the URL/status and opens the URL itself. The server-side cancel
|
|
164
|
+
* handle never crosses the wire — clients abort via the `cancel-auth-flow`
|
|
165
|
+
* command. `null` clears the modal (login completed, errored, or cancelled).
|
|
166
|
+
*/
|
|
167
|
+
export type McpAuthFlowState = {
|
|
168
|
+
serverName: string;
|
|
169
|
+
status: string;
|
|
170
|
+
/** Authorization URL the client opens / displays. Absent before the redirect. */
|
|
171
|
+
url?: string;
|
|
172
|
+
} | null;
|
|
173
|
+
/** Coarse per-step status surfaced in the titled tree (§8.3). */
|
|
174
|
+
export type WorkflowNodeWireStatus = "running" | "done" | "failed" | "skipped" | "stopped";
|
|
175
|
+
/** One node in the coarse titled tree (phase → titled steps). No transcript. */
|
|
176
|
+
export type WorkflowStatusNode = {
|
|
177
|
+
title: string;
|
|
178
|
+
status?: WorkflowNodeWireStatus;
|
|
179
|
+
children?: WorkflowStatusNode[];
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* The reduced, UI-facing summary of one run (§8.3). The reducer folds each
|
|
183
|
+
* `WorkflowProgressDelta` into this copy-on-write. It is the SAME model
|
|
184
|
+
* `WorkflowStatus` reads — titles/phases/statuses/counts/tokens only, NEVER
|
|
185
|
+
* prompts, tool-calls, agent messages, or node outputs.
|
|
186
|
+
*/
|
|
187
|
+
export type WorkflowViewState = {
|
|
188
|
+
runId: string;
|
|
189
|
+
status: "running" | "completed" | "failed" | "stopped";
|
|
190
|
+
/** Phase of the most recently started node, for a one-line live header. */
|
|
191
|
+
currentPhase?: string;
|
|
192
|
+
/** Phase → titled steps → latest status (§7.3 tree). */
|
|
193
|
+
tree: WorkflowStatusNode[];
|
|
194
|
+
/** Per-node-kind started counts (e.g. {agent: 3, transform: 1}). */
|
|
195
|
+
counts: Record<string, number>;
|
|
196
|
+
/** Summed `tokens` across finished nodes. */
|
|
197
|
+
tokens: number;
|
|
198
|
+
/** Highest `seq` folded in; lets clients dedupe replay vs live. */
|
|
199
|
+
lastSeq: number;
|
|
200
|
+
/**
|
|
201
|
+
* nodeId → [phase, title] index, so an incremental `node-finished` delta can
|
|
202
|
+
* re-locate its tree position (the tree keys on title, not nodeId). JSON-safe;
|
|
203
|
+
* UI-only; carries no transcript.
|
|
204
|
+
*/
|
|
205
|
+
nodeKeys: Record<string, [string, string]>;
|
|
206
|
+
};
|
|
207
|
+
/**
|
|
208
|
+
* The wire form of one journal event (spec §7.2). Discriminated on `type`;
|
|
209
|
+
* mirrors @nuvin/workflow's JournalEvent member-for-member but with
|
|
210
|
+
* payload-bearing fields typed JsonValue (JSON-safe by rule — the json-safety
|
|
211
|
+
* test guards every member). Large prompts/outputs are NOT inlined: they ride
|
|
212
|
+
* as `promptRef`/`outputRef` strings the client fetches on demand.
|
|
213
|
+
*/
|
|
214
|
+
export type WorkflowProgressDelta = {
|
|
215
|
+
type: "run-started";
|
|
216
|
+
seq: number;
|
|
217
|
+
at: number;
|
|
218
|
+
runId: string;
|
|
219
|
+
file: string;
|
|
220
|
+
args: JsonValue;
|
|
221
|
+
irDigest: string;
|
|
222
|
+
} | {
|
|
223
|
+
type: "node-started";
|
|
224
|
+
seq: number;
|
|
225
|
+
at: number;
|
|
226
|
+
nodeId: string;
|
|
227
|
+
kind: string;
|
|
228
|
+
phase?: string;
|
|
229
|
+
title?: string;
|
|
230
|
+
instanceKey?: string;
|
|
231
|
+
roundKey?: string;
|
|
232
|
+
inputsDigest: string;
|
|
233
|
+
} | {
|
|
234
|
+
type: "agent-prompt";
|
|
235
|
+
seq: number;
|
|
236
|
+
at: number;
|
|
237
|
+
nodeId: string;
|
|
238
|
+
promptRef: string;
|
|
239
|
+
} | {
|
|
240
|
+
type: "agent-step";
|
|
241
|
+
seq: number;
|
|
242
|
+
at: number;
|
|
243
|
+
nodeId: string;
|
|
244
|
+
kind: "model_request" | "tool_call" | "tool_result" | "assistant_message";
|
|
245
|
+
detail?: JsonValue;
|
|
246
|
+
} | {
|
|
247
|
+
type: "agent-output";
|
|
248
|
+
seq: number;
|
|
249
|
+
at: number;
|
|
250
|
+
nodeId: string;
|
|
251
|
+
outputRef: string;
|
|
252
|
+
model?: string;
|
|
253
|
+
tokens?: number;
|
|
254
|
+
} | {
|
|
255
|
+
type: "fanout-expanded";
|
|
256
|
+
seq: number;
|
|
257
|
+
at: number;
|
|
258
|
+
nodeId: string;
|
|
259
|
+
n: number;
|
|
260
|
+
keys: string[];
|
|
261
|
+
} | {
|
|
262
|
+
type: "gate-decided";
|
|
263
|
+
seq: number;
|
|
264
|
+
at: number;
|
|
265
|
+
nodeId: string;
|
|
266
|
+
branch: string;
|
|
267
|
+
} | {
|
|
268
|
+
type: "loop-round";
|
|
269
|
+
seq: number;
|
|
270
|
+
at: number;
|
|
271
|
+
nodeId: string;
|
|
272
|
+
round: number;
|
|
273
|
+
until: boolean;
|
|
274
|
+
} | {
|
|
275
|
+
type: "node-finished";
|
|
276
|
+
seq: number;
|
|
277
|
+
at: number;
|
|
278
|
+
nodeId: string;
|
|
279
|
+
status: "ran" | "replayed" | "skipped" | "retried" | "fallback" | "failed" | "aborted";
|
|
280
|
+
outputDigest: string;
|
|
281
|
+
instanceKey?: string;
|
|
282
|
+
roundKey?: string;
|
|
283
|
+
durationMs?: number;
|
|
284
|
+
tokens?: number;
|
|
285
|
+
} | {
|
|
286
|
+
type: "run-finished";
|
|
287
|
+
seq: number;
|
|
288
|
+
at: number;
|
|
289
|
+
status: "completed" | "failed" | "stopped";
|
|
290
|
+
summary?: JsonValue;
|
|
291
|
+
};
|
|
292
|
+
/**
|
|
293
|
+
* A message submitted during an active turn and waiting in the controller's
|
|
294
|
+
* auto-send queue (spec: removable-queued-messages). `id` is a controller-local
|
|
295
|
+
* monotonic handle used to cancel a specific item via the `dequeue` command.
|
|
296
|
+
*/
|
|
297
|
+
export type QueuedMessageView = {
|
|
298
|
+
id: string;
|
|
299
|
+
displayText: string;
|
|
300
|
+
attachmentLabels?: string[];
|
|
301
|
+
};
|
|
302
|
+
export type ServerEventBody = {
|
|
303
|
+
type: "agent-event";
|
|
304
|
+
event: AgentEvent;
|
|
305
|
+
scope?: WireDelegationScope;
|
|
306
|
+
/**
|
|
307
|
+
* Set on `tool_call` events to carry the initial status decided by the
|
|
308
|
+
* controller. Auto-approved tools arrive as ONE event with
|
|
309
|
+
* `toolStatus: "approved"` and never produce approval-requested
|
|
310
|
+
* (anti-flash rule, spec §4.5).
|
|
311
|
+
*/
|
|
312
|
+
toolStatus?: ToolMessageStatus;
|
|
313
|
+
} | {
|
|
314
|
+
type: "user-message";
|
|
315
|
+
text: string;
|
|
316
|
+
attachmentLabels?: string[];
|
|
317
|
+
} | {
|
|
318
|
+
type: "approval-requested";
|
|
319
|
+
approval: ApprovalDescriptor;
|
|
320
|
+
} | {
|
|
321
|
+
type: "approval-settled";
|
|
322
|
+
by: ApprovalSettledBy;
|
|
323
|
+
status: "approved" | "rejected";
|
|
324
|
+
toolCallId: string;
|
|
325
|
+
} | {
|
|
326
|
+
type: "question-asked";
|
|
327
|
+
question: QuestionDescriptor;
|
|
328
|
+
} | {
|
|
329
|
+
type: "question-settled";
|
|
330
|
+
questionId: string;
|
|
331
|
+
} | {
|
|
332
|
+
type: "turn-status";
|
|
333
|
+
busy: boolean;
|
|
334
|
+
queuedCount: number;
|
|
335
|
+
queued?: QueuedMessageView[];
|
|
336
|
+
} | {
|
|
337
|
+
type: "info";
|
|
338
|
+
message: string;
|
|
339
|
+
} | {
|
|
340
|
+
type: "error";
|
|
341
|
+
message: string;
|
|
342
|
+
} | {
|
|
343
|
+
type: "session-meta";
|
|
344
|
+
meta: SessionMeta;
|
|
345
|
+
} | {
|
|
346
|
+
/**
|
|
347
|
+
* Live agent metrics (token/usage counters), throttled to ~1/s during a
|
|
348
|
+
* turn and flushed once when the turn ends (spec §4.3). The snapshot is
|
|
349
|
+
* the JSON-safe AgentMetricsSnapshot from @nuvin/agent-core; AgentEvent's
|
|
350
|
+
* wire-frozen rule applies here too — changes require a PROTOCOL_VERSION
|
|
351
|
+
* bump enforced by the json-safety test.
|
|
352
|
+
*/
|
|
353
|
+
type: "metrics";
|
|
354
|
+
snapshot: AgentMetricsSnapshot;
|
|
355
|
+
} | {
|
|
356
|
+
/**
|
|
357
|
+
* MCP OAuth login flow update (spec §10/§12). Carries the wire-safe
|
|
358
|
+
* `McpAuthFlowState`; the client renders `McpAuthModal` from it and opens
|
|
359
|
+
* the URL client-side. The host emits these from its `McpAuthController`
|
|
360
|
+
* subscription. JSON-safe by rule (json-safety test covers it).
|
|
361
|
+
*/
|
|
362
|
+
type: "auth-flow";
|
|
363
|
+
flow: McpAuthFlowState;
|
|
364
|
+
} | {
|
|
365
|
+
/**
|
|
366
|
+
* UI progress for a background workflow run (spec §8.2). emit-only — the
|
|
367
|
+
* reducer folds `delta` into `state.workflows[runId]`; it NEVER calls
|
|
368
|
+
* submit and never touches agent messages. JSON-safe by rule (json-safety
|
|
369
|
+
* test covers it). `delta` is one journal event minus offloaded payloads.
|
|
370
|
+
*/
|
|
371
|
+
type: "workflow-progress";
|
|
372
|
+
runId: string;
|
|
373
|
+
delta: WorkflowProgressDelta;
|
|
374
|
+
} | {
|
|
375
|
+
type: "state-reset";
|
|
376
|
+
state: SessionViewState;
|
|
377
|
+
};
|
|
378
|
+
export type ServerEvent = ServerEventBody & {
|
|
379
|
+
/** Epoch ms assigned by the controller; reducers use this as "now". */
|
|
380
|
+
at: number;
|
|
381
|
+
/** Monotonic per-session sequence number. */
|
|
382
|
+
seq: number;
|
|
383
|
+
};
|
|
384
|
+
export type ClientCommand = {
|
|
385
|
+
id: string;
|
|
386
|
+
type: "submit";
|
|
387
|
+
input: AgentInput;
|
|
388
|
+
displayText: string;
|
|
389
|
+
attachmentLabels?: string[];
|
|
390
|
+
} | {
|
|
391
|
+
id: string;
|
|
392
|
+
type: "decide-approval";
|
|
393
|
+
toolCallId: string;
|
|
394
|
+
decision: "a" | "n" | "y";
|
|
395
|
+
comment?: string;
|
|
396
|
+
/** Dir-access approvals only: the user-edited grant directory. */
|
|
397
|
+
grantDir?: string;
|
|
398
|
+
} | {
|
|
399
|
+
id: string;
|
|
400
|
+
type: "answer-question";
|
|
401
|
+
questionId: string;
|
|
402
|
+
answers: AskUserAnswers;
|
|
403
|
+
} | {
|
|
404
|
+
id: string;
|
|
405
|
+
type: "abort";
|
|
406
|
+
} | {
|
|
407
|
+
id: string;
|
|
408
|
+
type: "dequeue";
|
|
409
|
+
queuedId: string;
|
|
410
|
+
} | {
|
|
411
|
+
id: string;
|
|
412
|
+
type: "slash-command";
|
|
413
|
+
raw: string;
|
|
414
|
+
} | {
|
|
415
|
+
id: string;
|
|
416
|
+
type: "complete-path";
|
|
417
|
+
prefix: string;
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Fetch the available models for the `/model` autocomplete popup (spec §6).
|
|
421
|
+
* The ack `result` is a {@link ModelCompletion}. Carries no payload — the
|
|
422
|
+
* daemon reads its own runtime config. Answered by the attached host; an
|
|
423
|
+
* empty completion is returned when no host is attached.
|
|
424
|
+
*/
|
|
425
|
+
| {
|
|
426
|
+
id: string;
|
|
427
|
+
type: "complete-models";
|
|
428
|
+
} | {
|
|
429
|
+
id: string;
|
|
430
|
+
type: "load-history";
|
|
431
|
+
historyId: string;
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Ask the daemon to re-read provider keys / config from the shared config
|
|
435
|
+
* dir after local onboarding wrote them (spec §10/§12). Acked once the
|
|
436
|
+
* reload completes; carries no payload — the daemon re-reads its own files.
|
|
437
|
+
*/
|
|
438
|
+
| {
|
|
439
|
+
id: string;
|
|
440
|
+
type: "reload-config";
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Abort the in-flight MCP OAuth login (spec §10). The daemon invokes the
|
|
444
|
+
* live cancel handle on its `McpAuthController`, which rejects the pending
|
|
445
|
+
* wait-for-callback and publishes a cleared `auth-flow` event. Carries no
|
|
446
|
+
* payload. Acked ok when a host is attached; unsupported otherwise.
|
|
447
|
+
*/
|
|
448
|
+
| {
|
|
449
|
+
id: string;
|
|
450
|
+
type: "cancel-auth-flow";
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Fetch a paginated raw slice of a run's journal as wire deltas (spec §8.2,
|
|
454
|
+
* D7). Session-scoped — answered only after `attach`. `sinceSeq` is the first
|
|
455
|
+
* seq to include (default 0). The ack `result` is
|
|
456
|
+
* `{ events: WorkflowProgressDelta[]; nextSeq?: number }`; page size 500. The
|
|
457
|
+
* client renders the collapsible audit tree from these (rendering is
|
|
458
|
+
* client-side, mirroring the reducer).
|
|
459
|
+
*/
|
|
460
|
+
| {
|
|
461
|
+
id: string;
|
|
462
|
+
type: "get-workflow-trace";
|
|
463
|
+
runId: string;
|
|
464
|
+
sinceSeq?: number;
|
|
465
|
+
};
|
|
466
|
+
export type CommandAck = {
|
|
467
|
+
type: "ack";
|
|
468
|
+
id: string;
|
|
469
|
+
ok: boolean;
|
|
470
|
+
error?: {
|
|
471
|
+
code: string;
|
|
472
|
+
message: string;
|
|
473
|
+
};
|
|
474
|
+
/**
|
|
475
|
+
* Optional request/response payload (e.g. `complete-path` returns a string[]
|
|
476
|
+
* of completions). JSON-safe by rule; the round-trip test guards it.
|
|
477
|
+
*/
|
|
478
|
+
result?: JsonValue;
|
|
479
|
+
};
|
|
480
|
+
/** Everything a server sends over a transport. */
|
|
481
|
+
export type ServerFrame = ServerEvent | CommandAck | {
|
|
482
|
+
type: "snapshot";
|
|
483
|
+
snapshot: SessionSnapshot;
|
|
484
|
+
};
|
|
485
|
+
/** Session lifecycle state surfaced by list-sessions (spec §4.2). */
|
|
486
|
+
export type SessionStatus = "awaiting-approval" | "busy" | "idle";
|
|
487
|
+
/** Session metadata returned by list-sessions / create-session (spec §4.2). */
|
|
488
|
+
export type SessionDescriptor = {
|
|
489
|
+
id: string;
|
|
490
|
+
name: string;
|
|
491
|
+
cwd: string;
|
|
492
|
+
/** Resolved workspace name for this session (spec §7). */
|
|
493
|
+
workspace?: string;
|
|
494
|
+
/** Resolved config profile for this session (spec §7). */
|
|
495
|
+
profile?: string;
|
|
496
|
+
model: string;
|
|
497
|
+
status: SessionStatus;
|
|
498
|
+
attachedClients: number;
|
|
499
|
+
/** Epoch ms. */
|
|
500
|
+
createdAt: number;
|
|
501
|
+
/** Epoch ms of the last ServerEvent this session emitted. */
|
|
502
|
+
lastActivityAt: number;
|
|
503
|
+
/** Current human-readable session topic; absent until set by the first user message or UpdateTopic. */
|
|
504
|
+
topic?: string;
|
|
505
|
+
/**
|
|
506
|
+
* First line of the most recent user message (trimmed, truncated), if any.
|
|
507
|
+
* Used as the dashboard title fallback when no topic is set yet (spec §4):
|
|
508
|
+
* topic → lastMessage → name. Absent when the session has no user turn.
|
|
509
|
+
*/
|
|
510
|
+
lastMessage?: string;
|
|
511
|
+
};
|
|
512
|
+
/**
|
|
513
|
+
* The signed payload inside a relay grant (relay spec §7): a short-lived
|
|
514
|
+
* permission slip minted per client connection. Timestamps are epoch ms.
|
|
515
|
+
* The wire form is `base64url(JSON payload) + "." + base64url(signature)`;
|
|
516
|
+
* sign/verify live in the Node-only @nuvin/session/grant module — this type
|
|
517
|
+
* is here so browser-safe code can name the shape without touching crypto.
|
|
518
|
+
*/
|
|
519
|
+
export type GrantPayload = {
|
|
520
|
+
/** The grant is only valid for this daemon. */
|
|
521
|
+
daemonId: string;
|
|
522
|
+
/** Clerk user id of who is connecting (authz + audit). */
|
|
523
|
+
userId: string;
|
|
524
|
+
/** Unique per grant, for logging/audit. */
|
|
525
|
+
grantId: string;
|
|
526
|
+
/** Epoch ms. Must not be absurdly in the future (±5 min skew window). */
|
|
527
|
+
issuedAt: number;
|
|
528
|
+
/** Epoch ms. Gates ONLY the handshake — established sessions live on. */
|
|
529
|
+
expiresAt: number;
|
|
530
|
+
};
|
|
531
|
+
/**
|
|
532
|
+
* Server → daemon frames on the relay CONTROL WebSocket (relay spec §4/§8.2).
|
|
533
|
+
* This is the relay control plane, NOT the session protocol: these frames
|
|
534
|
+
* never ride a daemon session socket, are not part of DaemonClientMessage /
|
|
535
|
+
* DaemonServerMessage, and are NOT covered by the PROTOCOL_VERSION exact-match
|
|
536
|
+
* handshake (the control connection authenticates via device token instead).
|
|
537
|
+
* Shared here so @nuvin/server and @nuvin/daemon agree on the envelope shape
|
|
538
|
+
* (relay spec §5: the server depends on @nuvin/session for protocol types only).
|
|
539
|
+
*/
|
|
540
|
+
/** Methods the relay may RPC to a daemon over the control connection (spec §4.1).
|
|
541
|
+
* Params/results are method-specific and typed at each call site / handler. */
|
|
542
|
+
export type RelayRpcMethod = "get-transcript" | "list-history" | "delete-session" | "list-workspaces" | "create-workspace";
|
|
543
|
+
export type RelayControlMessage =
|
|
544
|
+
/** Dial wss://{server}/tunnel/{channelId} now — a client is waiting (spec §9.1). */
|
|
545
|
+
{
|
|
546
|
+
type: "open-channel";
|
|
547
|
+
channelId: string;
|
|
548
|
+
}
|
|
549
|
+
/** Registration revoked: close tunnels, drop control, clear local relay config (spec §8.2/§10). */
|
|
550
|
+
| {
|
|
551
|
+
type: "revoked";
|
|
552
|
+
}
|
|
553
|
+
/** Relay → daemon request/reply (spec §4.1). Correlated by `rpcId`. */
|
|
554
|
+
| {
|
|
555
|
+
type: "rpc";
|
|
556
|
+
rpcId: string;
|
|
557
|
+
method: RelayRpcMethod;
|
|
558
|
+
params: unknown;
|
|
559
|
+
};
|
|
560
|
+
/**
|
|
561
|
+
* Daemon → relay control frames (spec §4.1). The daemon pushes its live-session
|
|
562
|
+
* list (relay caches it for GET /api/daemons) and replies to relay RPCs.
|
|
563
|
+
*/
|
|
564
|
+
export type DaemonControlMessage = {
|
|
565
|
+
type: "sessions";
|
|
566
|
+
sessions: SessionDescriptor[];
|
|
567
|
+
} | {
|
|
568
|
+
type: "rpc-result";
|
|
569
|
+
rpcId: string;
|
|
570
|
+
ok: true;
|
|
571
|
+
result: unknown;
|
|
572
|
+
} | {
|
|
573
|
+
type: "rpc-result";
|
|
574
|
+
rpcId: string;
|
|
575
|
+
ok: false;
|
|
576
|
+
error: string;
|
|
577
|
+
};
|
|
578
|
+
/**
|
|
579
|
+
* First frame on every daemon socket, client → daemon. The credential travels
|
|
580
|
+
* HERE and never in the URL (query strings leak into proxy logs — spec §4.1).
|
|
581
|
+
* Two credential variants (relay spec §8.3, ONE protocol bump):
|
|
582
|
+
* - `token`: the daemon's bearer token — UDS/TCP sockets only.
|
|
583
|
+
* - `grant`: an Ed25519-signed, short-lived permission slip minted by the
|
|
584
|
+
* relay server — relay-sourced sockets only. Opaque to clients; verified on
|
|
585
|
+
* the daemon (@nuvin/session/grant). The `?: never` markers make the two
|
|
586
|
+
* variants mutually exclusive while keeping property access narrowable.
|
|
587
|
+
*/
|
|
588
|
+
export type HelloFrame = {
|
|
589
|
+
type: "hello";
|
|
590
|
+
protocolVersion: number;
|
|
591
|
+
} & ({
|
|
592
|
+
token: string;
|
|
593
|
+
grant?: never;
|
|
594
|
+
} | {
|
|
595
|
+
grant: string;
|
|
596
|
+
token?: never;
|
|
597
|
+
});
|
|
598
|
+
/**
|
|
599
|
+
* Successful handshake reply. Version policy is EXACT match on
|
|
600
|
+
* PROTOCOL_VERSION; serverCommands feed the Composer autocomplete (spec §4.1).
|
|
601
|
+
*/
|
|
602
|
+
export type WelcomeFrame = {
|
|
603
|
+
type: "welcome";
|
|
604
|
+
protocolVersion: number;
|
|
605
|
+
daemonVersion: string;
|
|
606
|
+
serverCommands: SlashCommandDescriptor[];
|
|
607
|
+
};
|
|
608
|
+
/** Handshake refusal; the daemon closes the socket after sending it. */
|
|
609
|
+
export type RejectedFrame = {
|
|
610
|
+
type: "rejected";
|
|
611
|
+
reason: "auth" | "version";
|
|
612
|
+
};
|
|
613
|
+
/**
|
|
614
|
+
* A profile as advertised to directory clients (per-daemon). Returned as a
|
|
615
|
+
* JSON-safe array in a `CommandAck.result` by the `list-profiles` command.
|
|
616
|
+
* `active` ⇒ the daemon's currently-resolved active profile. Distinct from
|
|
617
|
+
* config's richer ProfileMetadata.
|
|
618
|
+
*/
|
|
619
|
+
export type ProfileSummary = {
|
|
620
|
+
name: string;
|
|
621
|
+
active: boolean;
|
|
622
|
+
description?: string;
|
|
623
|
+
};
|
|
624
|
+
/**
|
|
625
|
+
* A provider as advertised to directory clients (web spec §7). Returned as a
|
|
626
|
+
* JSON-safe array in a `CommandAck.result` by the `list-providers` command.
|
|
627
|
+
* `id` is the provider's config name; `label` is display copy (the name in
|
|
628
|
+
* v1); `hasAuth` mirrors the config store's entry-scoped credential flag.
|
|
629
|
+
*/
|
|
630
|
+
export type ProviderSummary = {
|
|
631
|
+
id: string;
|
|
632
|
+
label: string;
|
|
633
|
+
hasAuth: boolean;
|
|
634
|
+
isDefault: boolean;
|
|
635
|
+
};
|
|
636
|
+
/**
|
|
637
|
+
* A workspace as advertised to directory clients (spec §7). Returned (as a
|
|
638
|
+
* JSON-safe array in a `CommandAck.result`) by the `list-workspaces` command,
|
|
639
|
+
* and singly by `create-workspace`. Distinct from config's richer
|
|
640
|
+
* `WorkspaceMetadata`: this is the wire-facing projection.
|
|
641
|
+
*/
|
|
642
|
+
export type WorkspaceSummary = {
|
|
643
|
+
name: string;
|
|
644
|
+
root: string;
|
|
645
|
+
adhoc: boolean;
|
|
646
|
+
sessionCount: number;
|
|
647
|
+
};
|
|
648
|
+
/** Pre-attach session management commands (spec §4.2). */
|
|
649
|
+
export type DaemonCommand = {
|
|
650
|
+
id: string;
|
|
651
|
+
type: "list-sessions";
|
|
652
|
+
} | {
|
|
653
|
+
id: string;
|
|
654
|
+
type: "list-history";
|
|
655
|
+
profile?: string;
|
|
656
|
+
cwd?: string;
|
|
657
|
+
} | {
|
|
658
|
+
id: string;
|
|
659
|
+
type: "create-session";
|
|
660
|
+
name?: string;
|
|
661
|
+
cwd: string;
|
|
662
|
+
workspace?: string;
|
|
663
|
+
/**
|
|
664
|
+
* Client-driven config profile (e.g. the local CLI's `--profile`). The
|
|
665
|
+
* daemon stays profile-agnostic and CONSUMES this only at session
|
|
666
|
+
* creation: the per-session runtime resolves config/agents under it.
|
|
667
|
+
* Omitted ⇒ the daemon's `profiles.yaml` active profile.
|
|
668
|
+
*/
|
|
669
|
+
profile?: string;
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Switch-and-resume (spec §3/§7): rehydrate a COLD history id into a NEW live
|
|
673
|
+
* SessionController and reply with a `session-created` frame carrying the live
|
|
674
|
+
* descriptor. The cold transcript has no daemon-side cwd, so the caller
|
|
675
|
+
* supplies the `cwd` the rehydrated runtime runs in. IDEMPOTENT daemon-side:
|
|
676
|
+
* resuming an already-live id returns the existing live session (no duplicate).
|
|
677
|
+
*/
|
|
678
|
+
| {
|
|
679
|
+
id: string;
|
|
680
|
+
type: "resume-session";
|
|
681
|
+
historyId: string;
|
|
682
|
+
cwd: string;
|
|
683
|
+
name?: string;
|
|
684
|
+
workspace?: string;
|
|
685
|
+
/** Client-driven config profile, consumed at session creation (see create-session). */
|
|
686
|
+
profile?: string;
|
|
687
|
+
} | {
|
|
688
|
+
id: string;
|
|
689
|
+
type: "attach";
|
|
690
|
+
sessionId: string;
|
|
691
|
+
lastSeq?: number;
|
|
692
|
+
} | {
|
|
693
|
+
id: string;
|
|
694
|
+
type: "kill-session";
|
|
695
|
+
sessionId: string;
|
|
696
|
+
delete?: boolean;
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Permanently delete a cold session transcript from the daemon's SessionStore
|
|
700
|
+
* (spec §8). Acked ok when something was deleted; `unknown-history` when the
|
|
701
|
+
* id was already gone. Refuses to delete live sessions — kill-session first
|
|
702
|
+
* (returns `history-live`).
|
|
703
|
+
*/
|
|
704
|
+
| {
|
|
705
|
+
id: string;
|
|
706
|
+
type: "delete-history";
|
|
707
|
+
historyId: string;
|
|
708
|
+
workspace: string;
|
|
709
|
+
profile?: string;
|
|
710
|
+
}
|
|
711
|
+
/** Start the daemon-hosted web UI on `port` (default 3000). Replies `ack`
|
|
712
|
+
* with result { running, url, port } or an EADDRINUSE error (spec §4.5). */
|
|
713
|
+
| {
|
|
714
|
+
id: string;
|
|
715
|
+
type: "web-start";
|
|
716
|
+
port?: number;
|
|
717
|
+
}
|
|
718
|
+
/** Stop the daemon-hosted web UI. Replies `ack` with result { running:false }. */
|
|
719
|
+
| {
|
|
720
|
+
id: string;
|
|
721
|
+
type: "web-stop";
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* List the daemon's workspaces (spec §7). Pre-attach, directory-level. Replies
|
|
725
|
+
* with an `ack` whose `result` is a {@link WorkspaceSummary}[]. Per-daemon: the
|
|
726
|
+
* web new-session screen issues this against the SELECTED server's socket.
|
|
727
|
+
* `profile` omitted ⇒ the daemon's active profile.
|
|
728
|
+
*/
|
|
729
|
+
| {
|
|
730
|
+
id: string;
|
|
731
|
+
type: "list-workspaces";
|
|
732
|
+
profile?: string;
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* Create a named workspace on the daemon (spec §7). `root` omitted ⇒ the daemon
|
|
736
|
+
* provisions an isolated `workdir/`. `profile` omitted ⇒ active profile. Replies
|
|
737
|
+
* with an `ack` whose `result` is the created {@link WorkspaceSummary}; ack
|
|
738
|
+
* `ok:false` `workspace-exists` on duplicate.
|
|
739
|
+
*/
|
|
740
|
+
| {
|
|
741
|
+
id: string;
|
|
742
|
+
type: "create-workspace";
|
|
743
|
+
name: string;
|
|
744
|
+
root?: string;
|
|
745
|
+
profile?: string;
|
|
746
|
+
}
|
|
747
|
+
/**
|
|
748
|
+
* List the daemon's config profiles (spec §7-style, per-daemon). Pre-attach,
|
|
749
|
+
* directory-level. Replies with an `ack` whose `result` is a {@link ProfileSummary}[].
|
|
750
|
+
*/
|
|
751
|
+
| {
|
|
752
|
+
id: string;
|
|
753
|
+
type: "list-profiles";
|
|
754
|
+
}
|
|
755
|
+
/**
|
|
756
|
+
* Provider-config management (relay spec §8.4, web spec §7): pre-attach,
|
|
757
|
+
* directory-level, so the cloud web UI can configure a REMOTE daemon over
|
|
758
|
+
* the protocol. Mirrors the CLI web server's /api/providers* REST surface.
|
|
759
|
+
* Replies with an `ack` whose `result` is a {@link ProviderSummary}[].
|
|
760
|
+
*/
|
|
761
|
+
| {
|
|
762
|
+
id: string;
|
|
763
|
+
type: "list-providers";
|
|
764
|
+
}
|
|
765
|
+
/** Set the daemon's default (active) provider. Acks ok; mutations reload running sessions like `reload-config`. */
|
|
766
|
+
| {
|
|
767
|
+
id: string;
|
|
768
|
+
type: "set-default-provider";
|
|
769
|
+
providerId: string;
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Set a provider's credential (API key). The credential transits the wire
|
|
773
|
+
* (TLS / spliced relay frames — accepted v1 threat, web spec §7) and is
|
|
774
|
+
* stored only in the daemon's config store.
|
|
775
|
+
*/
|
|
776
|
+
| {
|
|
777
|
+
id: string;
|
|
778
|
+
type: "set-provider-auth";
|
|
779
|
+
providerId: string;
|
|
780
|
+
credential: string;
|
|
781
|
+
}
|
|
782
|
+
/** Remove a provider's stored credential. */
|
|
783
|
+
| {
|
|
784
|
+
id: string;
|
|
785
|
+
type: "clear-provider-auth";
|
|
786
|
+
providerId: string;
|
|
787
|
+
};
|
|
788
|
+
/**
|
|
789
|
+
* A cold/resumable session from the daemon's JSONL SessionStore (spec §8).
|
|
790
|
+
* Display-only metadata; resuming it sends a `load-history` command after
|
|
791
|
+
* attaching to a (new or existing) live session.
|
|
792
|
+
*/
|
|
793
|
+
export type HistorySummary = {
|
|
794
|
+
id: string;
|
|
795
|
+
title: string;
|
|
796
|
+
/** Epoch ms of the last write to the session dir. */
|
|
797
|
+
updatedAt: number;
|
|
798
|
+
parentSessionId?: string;
|
|
799
|
+
/** Owning workspace name — the group key for /history (spec §5.1). */
|
|
800
|
+
workspace: string;
|
|
801
|
+
/** Workspace root path, for clients with no local registry (web). */
|
|
802
|
+
workspaceRoot?: string;
|
|
803
|
+
};
|
|
804
|
+
/** Reply to list-history; `id` echoes the command id. */
|
|
805
|
+
export type HistoryListFrame = {
|
|
806
|
+
type: "history-list";
|
|
807
|
+
id: string;
|
|
808
|
+
sessions: HistorySummary[];
|
|
809
|
+
/** Set only when the client sent a cwd that resolved to a workspace. */
|
|
810
|
+
currentWorkspace?: string;
|
|
811
|
+
};
|
|
812
|
+
/**
|
|
813
|
+
* A paginated slice of cold history (spec §4.3): the `list-history` RPC result,
|
|
814
|
+
* the `GET /api/daemons/:id/history` body, and the cloud `fetchHistory()` return.
|
|
815
|
+
* `nextCursor` is an OPAQUE token — present only when more pages remain (decision
|
|
816
|
+
* §10.2: cursor, not offset). `currentWorkspace` is echoed when the caller sent a
|
|
817
|
+
* cwd that resolved to a workspace.
|
|
818
|
+
*/
|
|
819
|
+
export type HistoryPage = {
|
|
820
|
+
sessions: HistorySummary[];
|
|
821
|
+
nextCursor?: string;
|
|
822
|
+
currentWorkspace?: string;
|
|
823
|
+
};
|
|
824
|
+
/** Reply to list-sessions; `id` echoes the command id. */
|
|
825
|
+
export type SessionListFrame = {
|
|
826
|
+
type: "session-list";
|
|
827
|
+
id: string;
|
|
828
|
+
sessions: SessionDescriptor[];
|
|
829
|
+
};
|
|
830
|
+
/** Reply to create-session; `id` echoes the command id. */
|
|
831
|
+
export type SessionCreatedFrame = {
|
|
832
|
+
type: "session-created";
|
|
833
|
+
id: string;
|
|
834
|
+
session: SessionDescriptor;
|
|
835
|
+
};
|
|
836
|
+
/**
|
|
837
|
+
* Reply to attach when lastSeq is still inside the ring buffer: every missed
|
|
838
|
+
* event in seq order (spec §4.6). The client reduces them exactly like live
|
|
839
|
+
* events; an empty list means nothing was missed. When the buffer no longer
|
|
840
|
+
* covers the gap the daemon answers with a snapshot frame instead.
|
|
841
|
+
*/
|
|
842
|
+
export type ReplayFrame = {
|
|
843
|
+
type: "replay";
|
|
844
|
+
events: ServerEvent[];
|
|
845
|
+
};
|
|
846
|
+
/** The daemon detached this client (e.g. the session was killed — spec §8). */
|
|
847
|
+
export type DetachedFrame = {
|
|
848
|
+
type: "detached";
|
|
849
|
+
reason: string;
|
|
850
|
+
};
|
|
851
|
+
/** Everything a client may send over a daemon socket. */
|
|
852
|
+
export type DaemonClientMessage = ClientCommand | DaemonCommand | HelloFrame;
|
|
853
|
+
/** Everything a daemon may send over a socket. */
|
|
854
|
+
export type DaemonServerMessage = DetachedFrame | HistoryListFrame | RejectedFrame | ReplayFrame | ServerFrame | SessionCreatedFrame | SessionListFrame | WelcomeFrame;
|
|
855
|
+
//# sourceMappingURL=types.d.ts.map
|