@nuvin/session 0.1.0-rc.10

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