@ggui-ai/mcp-server 0.1.0-rc.1

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 (141) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +48 -0
  3. package/dist/admin-blueprints-transport.d.ts +114 -0
  4. package/dist/admin-blueprints-transport.d.ts.map +1 -0
  5. package/dist/admin-blueprints-transport.js +118 -0
  6. package/dist/admin-oauth-providers-transport.d.ts +40 -0
  7. package/dist/admin-oauth-providers-transport.d.ts.map +1 -0
  8. package/dist/admin-oauth-providers-transport.js +263 -0
  9. package/dist/auth.d.ts +39 -0
  10. package/dist/auth.d.ts.map +1 -0
  11. package/dist/auth.js +75 -0
  12. package/dist/build-mcp.d.ts +128 -0
  13. package/dist/build-mcp.d.ts.map +1 -0
  14. package/dist/build-mcp.js +113 -0
  15. package/dist/code-store-fs.d.ts +19 -0
  16. package/dist/code-store-fs.d.ts.map +1 -0
  17. package/dist/code-store-fs.js +98 -0
  18. package/dist/console-auth.d.ts +139 -0
  19. package/dist/console-auth.d.ts.map +1 -0
  20. package/dist/console-auth.js +102 -0
  21. package/dist/console-cache.d.ts +78 -0
  22. package/dist/console-cache.d.ts.map +1 -0
  23. package/dist/console-cache.js +105 -0
  24. package/dist/console-headers.d.ts +124 -0
  25. package/dist/console-headers.d.ts.map +1 -0
  26. package/dist/console-headers.js +49 -0
  27. package/dist/console-llm-trace.d.ts +66 -0
  28. package/dist/console-llm-trace.d.ts.map +1 -0
  29. package/dist/console-llm-trace.js +105 -0
  30. package/dist/console-payloads.d.ts +67 -0
  31. package/dist/console-payloads.d.ts.map +1 -0
  32. package/dist/console-payloads.js +105 -0
  33. package/dist/console-theme-routes.d.ts +111 -0
  34. package/dist/console-theme-routes.d.ts.map +1 -0
  35. package/dist/console-theme-routes.js +202 -0
  36. package/dist/console-timeline.d.ts +45 -0
  37. package/dist/console-timeline.d.ts.map +1 -0
  38. package/dist/console-timeline.js +169 -0
  39. package/dist/console-validator.d.ts +67 -0
  40. package/dist/console-validator.d.ts.map +1 -0
  41. package/dist/console-validator.js +105 -0
  42. package/dist/console-welcome.d.ts +7 -0
  43. package/dist/console-welcome.d.ts.map +1 -0
  44. package/dist/console-welcome.js +221 -0
  45. package/dist/csrf-middleware.d.ts +55 -0
  46. package/dist/csrf-middleware.d.ts.map +1 -0
  47. package/dist/csrf-middleware.js +138 -0
  48. package/dist/email-login.d.ts +174 -0
  49. package/dist/email-login.d.ts.map +1 -0
  50. package/dist/email-login.js +254 -0
  51. package/dist/email-resend.d.ts +29 -0
  52. package/dist/email-resend.d.ts.map +1 -0
  53. package/dist/email-resend.js +71 -0
  54. package/dist/email-sender-from-env.d.ts +34 -0
  55. package/dist/email-sender-from-env.d.ts.map +1 -0
  56. package/dist/email-sender-from-env.js +112 -0
  57. package/dist/email-smtp.d.ts +42 -0
  58. package/dist/email-smtp.d.ts.map +1 -0
  59. package/dist/email-smtp.js +81 -0
  60. package/dist/index.d.ts +102 -0
  61. package/dist/index.d.ts.map +1 -0
  62. package/dist/index.js +122 -0
  63. package/dist/instructions-presets.d.ts +112 -0
  64. package/dist/instructions-presets.d.ts.map +1 -0
  65. package/dist/instructions-presets.js +195 -0
  66. package/dist/llm-backed-negotiator.d.ts +178 -0
  67. package/dist/llm-backed-negotiator.d.ts.map +1 -0
  68. package/dist/llm-backed-negotiator.js +579 -0
  69. package/dist/logger.d.ts +23 -0
  70. package/dist/logger.d.ts.map +1 -0
  71. package/dist/logger.js +41 -0
  72. package/dist/mcp-apps-inbound.d.ts +86 -0
  73. package/dist/mcp-apps-inbound.d.ts.map +1 -0
  74. package/dist/mcp-apps-inbound.js +278 -0
  75. package/dist/mcp-apps-outbound.d.ts +448 -0
  76. package/dist/mcp-apps-outbound.d.ts.map +1 -0
  77. package/dist/mcp-apps-outbound.js +1163 -0
  78. package/dist/mcp-mounts.d.ts +239 -0
  79. package/dist/mcp-mounts.d.ts.map +1 -0
  80. package/dist/mcp-mounts.js +222 -0
  81. package/dist/oauth-login-types.d.ts +160 -0
  82. package/dist/oauth-login-types.d.ts.map +1 -0
  83. package/dist/oauth-login-types.js +9 -0
  84. package/dist/oauth-login.d.ts +77 -0
  85. package/dist/oauth-login.d.ts.map +1 -0
  86. package/dist/oauth-login.js +455 -0
  87. package/dist/oauth-providers/github.d.ts +17 -0
  88. package/dist/oauth-providers/github.d.ts.map +1 -0
  89. package/dist/oauth-providers/github.js +89 -0
  90. package/dist/oauth-providers/google.d.ts +18 -0
  91. package/dist/oauth-providers/google.d.ts.map +1 -0
  92. package/dist/oauth-providers/google.js +59 -0
  93. package/dist/oauth-providers-store.d.ts +32 -0
  94. package/dist/oauth-providers-store.d.ts.map +1 -0
  95. package/dist/oauth-providers-store.js +291 -0
  96. package/dist/oauth.d.ts +347 -0
  97. package/dist/oauth.d.ts.map +1 -0
  98. package/dist/oauth.js +686 -0
  99. package/dist/pairing-transport.d.ts +99 -0
  100. package/dist/pairing-transport.d.ts.map +1 -0
  101. package/dist/pairing-transport.js +223 -0
  102. package/dist/rate-limit-middleware.d.ts +36 -0
  103. package/dist/rate-limit-middleware.d.ts.map +1 -0
  104. package/dist/rate-limit-middleware.js +57 -0
  105. package/dist/render-gate.d.ts +87 -0
  106. package/dist/render-gate.d.ts.map +1 -0
  107. package/dist/render-gate.js +77 -0
  108. package/dist/render-rate-limit.d.ts +59 -0
  109. package/dist/render-rate-limit.d.ts.map +1 -0
  110. package/dist/render-rate-limit.js +73 -0
  111. package/dist/render-signing.d.ts +98 -0
  112. package/dist/render-signing.d.ts.map +1 -0
  113. package/dist/render-signing.js +113 -0
  114. package/dist/request-context.d.ts +113 -0
  115. package/dist/request-context.d.ts.map +1 -0
  116. package/dist/request-context.js +154 -0
  117. package/dist/reserved-validators.d.ts +22 -0
  118. package/dist/reserved-validators.d.ts.map +1 -0
  119. package/dist/reserved-validators.js +101 -0
  120. package/dist/schema-compat.d.ts +167 -0
  121. package/dist/schema-compat.d.ts.map +1 -0
  122. package/dist/schema-compat.js +187 -0
  123. package/dist/security-headers-middleware.d.ts +38 -0
  124. package/dist/security-headers-middleware.d.ts.map +1 -0
  125. package/dist/security-headers-middleware.js +30 -0
  126. package/dist/server.d.ts +2060 -0
  127. package/dist/server.d.ts.map +1 -0
  128. package/dist/server.js +6338 -0
  129. package/dist/session-channel.d.ts +651 -0
  130. package/dist/session-channel.d.ts.map +1 -0
  131. package/dist/session-channel.js +1756 -0
  132. package/dist/storage.d.ts +89 -0
  133. package/dist/storage.d.ts.map +1 -0
  134. package/dist/storage.js +171 -0
  135. package/dist/thread-transport.d.ts +118 -0
  136. package/dist/thread-transport.d.ts.map +1 -0
  137. package/dist/thread-transport.js +478 -0
  138. package/dist/user-session-auth.d.ts +167 -0
  139. package/dist/user-session-auth.d.ts.map +1 -0
  140. package/dist/user-session-auth.js +148 -0
  141. package/package.json +76 -0
@@ -0,0 +1,651 @@
1
+ /**
2
+ * OSS live channel — live session plane over WebSocket.
3
+ *
4
+ * The live channel is where the typed-channel contract is enforced on
5
+ * live traffic between the server and the user. It co-hosts on the
6
+ * same Express server as `/mcp` and reuses the same
7
+ * `@ggui-ai/mcp-server-handlers/session-mutations` helpers that the
8
+ * closed hosted server consumes.
9
+ *
10
+ * Scope:
11
+ *
12
+ * - `subscribe` → auth, resolve-or-create session, register subscriber,
13
+ * reply `ack` with the session's current stack + sequence.
14
+ * - `action` → inbound user action carried as an {@link ActionEnvelope}.
15
+ * Gated through `assertEventAllowed` (allowlist) +
16
+ * `assertActionContract` (payload, for data:submit). Persisted to
17
+ * SessionStore as a typed session event.
18
+ * - `ping`/`pong` → heartbeat parity with hosted.
19
+ * - `close`/socket-close → clean subscriber teardown.
20
+ * - `sendToSession(sessionId, data)` → outbound fan-out API for
21
+ * mutation handlers (ggui_emit / connector `ctx.send`). Validated
22
+ * through `assertStreamContract` before delivery.
23
+ *
24
+ * `props_update`: mount handlers dispatched through the wired-action
25
+ * router can call `ctx.sendPropsUpdate(stackItemId, props)` to fan a
26
+ * `{type:'props_update'}` frame to live subscribers without going
27
+ * through a refresh-stream path. Reaches the renderer's existing
28
+ * `props_update` branch in `iframe-runtime` and applies new props
29
+ * in-place. This seam is scoped to mount tools; the agent-driven
30
+ * `ggui_update` path is handled separately.
31
+ *
32
+ * Not handled here:
33
+ *
34
+ * - Pattern-B daemon-agent notification stream (GET /mcp SSE).
35
+ * - Short-lived session-token mint/consume — that's ggui_push-gated.
36
+ * Dev-mode auth (any bearer via existing AuthAdapter) matches the
37
+ * `/mcp` endpoint's shape and is operator-replaceable.
38
+ */
39
+ import type { IncomingMessage } from 'node:http';
40
+ import type { Duplex } from 'node:stream';
41
+ import type { JsonObject, ReservedChannelValidator, SanitizeCausedBy, SessionStackEntry } from '@ggui-ai/protocol';
42
+ import type { AuthAdapter, SessionStore, SessionStreamBuffer, StreamEnvelopeInput, StreamFanout, TelemetrySink } from '@ggui-ai/mcp-server-core';
43
+ import type { Logger } from './logger.js';
44
+ /** Default URL path for the channel endpoint. Operators can override. */
45
+ export declare const DEFAULT_SESSION_CHANNEL_PATH = "/ws";
46
+ /**
47
+ * Opt-in plumbing for the `channel_subscribe` polling loop. When this
48
+ * field is set on {@link SessionChannelOptions}, channel subscribes
49
+ * whose `source.tool` is in {@link allowlist} are accepted and the
50
+ * server begins polling. When absent, every `channel_subscribe`
51
+ * returns `CHANNEL_NOT_LOCAL` so the iframe falls back to direct
52
+ * polling via the MCP host proxy.
53
+ */
54
+ export interface SessionChannelLocalToolsOptions {
55
+ /**
56
+ * Whitelist of `source.tool` names this channel can poll. Must mirror
57
+ * the value the host advertises on
58
+ * `handshake.serverCapabilities.streamWebSocketLocalTools` so the
59
+ * iframe + server agree on which channels use the WS fan-out path.
60
+ * Tools NOT in this list are rejected with `CHANNEL_NOT_LOCAL` (the
61
+ * iframe falls back to direct polling).
62
+ */
63
+ readonly allowlist: readonly string[];
64
+ /**
65
+ * Synchronous resolver invoked at poll time. Returns the tool's
66
+ * structured output (validated against `streamSpec[ch].schema`
67
+ * client-side; server-side schema validation is deferred to the
68
+ * future `validateContract` slice). Implementations typically
69
+ * delegate to the same in-process tool registry that backs `/mcp`.
70
+ *
71
+ * Throwing surfaces `POLL_FAILED` on the subscriber's
72
+ * `channel_error` channel without canceling the poll loop —
73
+ * transient tool failures are recoverable.
74
+ */
75
+ invoke(name: string, input: unknown): Promise<unknown>;
76
+ /**
77
+ * Optional poll cadence policy. `defaultMs` applies when the client
78
+ * doesn't supply a `pollIntervalMs`; `floorMs`/`ceilingMs` clamp
79
+ * client-supplied values. Defaults:
80
+ * `{floorMs: 1000, ceilingMs: 60000, defaultMs: 10000}`.
81
+ */
82
+ readonly pollCadence?: {
83
+ readonly floorMs?: number;
84
+ readonly ceilingMs?: number;
85
+ readonly defaultMs?: number;
86
+ };
87
+ }
88
+ /**
89
+ * Bootstrap-auth plumbing for the live-channel endpoint.
90
+ *
91
+ * The channel accepts a bootstrap credential on the `subscribe`
92
+ * message (`SubscribePayload.bootstrap`). When present:
93
+ *
94
+ * 1. `verify(token)` is called. Must return the bound
95
+ * `{sessionId, appId}` on success, or `null` on any failure
96
+ * (invalid sig, expired, wrong kind, replayed, etc.).
97
+ * 2. The bound `sessionId` MUST match the one on the subscribe
98
+ * payload. Mismatches are rejected with a clean error.
99
+ * 3. On success, the server mints a reconnect credential via
100
+ * `issueSessionToken(sessionId, appId)` and returns it in
101
+ * `AckPayload.sessionToken`. The iframe stores this for WS
102
+ * reconnects via the normal bearer path.
103
+ *
104
+ * Bootstrap auth is MUTUALLY EXCLUSIVE with the upstream `AuthAdapter`
105
+ * bearer path at subscribe time — when a bootstrap token is present,
106
+ * the identity resolved at the HTTP upgrade is IGNORED in favor of
107
+ * the bootstrap-derived identity. This is intentional: MCP Apps
108
+ * iframes don't have a long-lived bearer; the bootstrap IS the auth.
109
+ */
110
+ /**
111
+ * Verify failure shape — distinguished so the channel server can map
112
+ * `'expired'` to `BOOTSTRAP_EXPIRED` (client SHOULD refresh) vs
113
+ * `'invalid'` to `BOOTSTRAP_INVALID` (client MUST re-handshake).
114
+ *
115
+ * G14 (2026-05-23): bootstrap envelopes are no longer single-use. A
116
+ * signature-valid + unexpired token authenticates EVERY subscribe
117
+ * within the TTL window; transient WS drops reconnect without a fresh
118
+ * handshake. Past expiry, the iframe MAY refresh via the
119
+ * {@link refresh} surface; past the refresh window, fresh handshake.
120
+ */
121
+ export type SessionChannelBootstrapVerifyResult = {
122
+ readonly ok: true;
123
+ readonly sessionId: string;
124
+ readonly appId: string;
125
+ } | {
126
+ readonly ok: false;
127
+ readonly reason: 'expired' | 'invalid';
128
+ };
129
+ /**
130
+ * Result of {@link SessionChannelBootstrap.refresh}.
131
+ *
132
+ * - `ok: true`: caller swaps the old envelope for `token` and resumes.
133
+ * - `ok: false`: caller MUST re-handshake (refresh window closed,
134
+ * tampered envelope, etc.).
135
+ */
136
+ export type SessionChannelBootstrapRefreshResult = {
137
+ readonly ok: true;
138
+ readonly token: string;
139
+ readonly expiresAt: string;
140
+ } | {
141
+ readonly ok: false;
142
+ readonly reason: 'window_closed' | 'invalid';
143
+ };
144
+ export interface SessionChannelBootstrap {
145
+ /**
146
+ * Verify a `SubscribePayload.bootstrap` token.
147
+ *
148
+ * Returns the bound identity on success, or a discriminated failure.
149
+ * The channel server maps `'expired'` to `BOOTSTRAP_EXPIRED` so the
150
+ * iframe can branch on refresh-vs-rehandshake, and `'invalid'` to
151
+ * `BOOTSTRAP_INVALID` for tamper / format / kind failures (no
152
+ * refresh on those).
153
+ */
154
+ verify(token: string): SessionChannelBootstrapVerifyResult;
155
+ /**
156
+ * Mint a longer-lived reconnect credential to return in
157
+ * `AckPayload.sessionToken`. Called only after a successful
158
+ * `verify()` on a bootstrap subscribe.
159
+ */
160
+ issueSessionToken(sessionId: string, appId: string): string;
161
+ /**
162
+ * Refresh a (possibly-expired-but-signature-valid) bootstrap envelope
163
+ * into a new envelope with a fresh TTL. Used by the
164
+ * `ggui_runtime_refresh_bootstrap` MCP tool — iframes that see their
165
+ * bootstrap drift out of the TTL window swap in the refreshed
166
+ * envelope without going back through `ggui_push`.
167
+ *
168
+ * Stateless: verifies HMAC against the same secret used at mint,
169
+ * checks the refresh window against the ORIGINAL `iat`, and mints
170
+ * a fresh bootstrap envelope bound to the SAME `(sessionId, appId)`.
171
+ * Past the refresh window the result is `{ok:false, reason:
172
+ * 'window_closed'}`; tampered envelopes are `{ok:false, reason:
173
+ * 'invalid'}`.
174
+ */
175
+ refresh(token: string): SessionChannelBootstrapRefreshResult;
176
+ }
177
+ /**
178
+ * Default timeout for a single wired-tool invocation, in ms. Operators
179
+ * override via {@link SessionChannelOptions.wiredActionTimeoutMs}; the
180
+ * 30 s ceiling is a honest non-promise: long-running tools MUST design
181
+ * their own completion path (streaming, polling).
182
+ */
183
+ export declare const DEFAULT_WIRED_TOOL_TIMEOUT_MS = 30000;
184
+ /**
185
+ * Opt-in wired-action dispatch surface. When present on a session
186
+ * channel, `data:submit` envelopes whose declared `actionSpec
187
+ * [name].tool` resolves against this router fire the named tool
188
+ * in-process after validation, and the router's return value flows
189
+ * back onto the session through a refresh-stream emission (see the
190
+ * {@link import('@ggui-ai/protocol').StreamChannelEntry.tool} field).
191
+ *
192
+ * This is the agent-free contract-execution path — "zero agent code"
193
+ * lands here. In OSS `ggui serve`, the CLI composes a router that
194
+ * delegates to the same handler bundle `/mcp` uses (ggui-native +
195
+ * mounts). Hosted deployments that want the same behavior compose
196
+ * their own.
197
+ *
198
+ * Intentionally minimal surface:
199
+ * - `has(name)` separates "tool absent" (TOOL_NOT_FOUND envelope,
200
+ * recoverable) from "tool handler threw" (TOOL_THREW envelope,
201
+ * isolated). The channel server uses the split to pick the error
202
+ * code BEFORE invoking.
203
+ * - `invoke(name, input)` returns `unknown` — the router doesn't
204
+ * impose a shape, the refresh emission validates against the
205
+ * declared `streamSpec[*].schema`.
206
+ *
207
+ * Thread-safety: implementations MUST tolerate concurrent invocations
208
+ * for the same or different tools. The session channel fires no retry;
209
+ * the router's handler is the sole execution.
210
+ */
211
+ /**
212
+ * Per-invocation context the wired-action dispatcher hands the router.
213
+ * The session-channel server constructs this at dispatch time from
214
+ * the active session + stack item, then closes
215
+ * `sendPropsUpdate` over the channel's outbound fan-out so the mount
216
+ * handler can push a `props_update` frame to live subscribers without
217
+ * routing through a refresh-stream tool.
218
+ *
219
+ * Why this is its own type, not threaded through `HandlerContext`:
220
+ * `HandlerContext` (in `@ggui-ai/mcp-server-handlers`) is the canonical
221
+ * shape every shared handler — ggui-native AND mounted — accepts. It
222
+ * stays narrow on purpose (`appId`, `requestId`, optional `apiKeyHash`)
223
+ * so the surface a host implements is stable. Wired-action runtime
224
+ * fields (`sessionId`, `stackItemId`, `sendPropsUpdate`) are dispatcher-
225
+ * specific — only mount tools invoked through the wired-action router
226
+ * see them, only at dispatch time. Passing them as a third arg to
227
+ * `invoke` keeps the canonical handler shape untouched and makes
228
+ * "this code reaches a wired dispatch path" syntactically obvious.
229
+ *
230
+ * The composer in `mcp-mounts.ts::composeWiredActionRouterFromMounts`
231
+ * synthesizes a runtime ctx for the mount handler that satisfies
232
+ * `HandlerContext` AND structurally carries these wired fields, so a
233
+ * mount fixture can read `ctx.sendPropsUpdate` / `ctx.stackItemId` from the
234
+ * same `ctx` argument the canonical `HandlerContext` sig types — no
235
+ * cast, no widening of the static type.
236
+ */
237
+ export interface WiredActionContext {
238
+ /** The session this dispatch is bound to. Sourced from the live
239
+ * subscriber + the action envelope's spoof-guarded `sessionId`. */
240
+ readonly sessionId: string;
241
+ /** The active stack item's stackItemId at dispatch time. Mounts that
242
+ * fire `sendPropsUpdate` typically pass this verbatim — only a
243
+ * mount that intentionally targets a sibling stack entry would
244
+ * pick a different value. */
245
+ readonly stackItemId: string;
246
+ /**
247
+ * Push a `{type:'props_update', payload:{stackItemId, props}}` frame to
248
+ * every live subscriber bound to this dispatcher's `sessionId`. The
249
+ * call closes over the `SessionChannelServer.sendPropsUpdate` method,
250
+ * scoped to the active session for safety — even if a buggy mount
251
+ * picks a `stackItemId` that doesn't exist on the session, the channel
252
+ * server's own validation no-ops the fan-out (same posture as
253
+ * `notifyStackPush` orphan handling).
254
+ *
255
+ * Best-effort: per-subscriber send failures are swallowed; a closed
256
+ * socket is a no-op.
257
+ */
258
+ sendPropsUpdate(stackItemId: string, props: JsonObject): void;
259
+ }
260
+ export interface WiredActionRouter {
261
+ /** Returns `true` when the named tool has a registered handler. Used
262
+ * to emit a clean `TOOL_NOT_FOUND` envelope before invoking — an
263
+ * "invoke unknown tool" would throw through router internals, but
264
+ * the error surface would be less specific. */
265
+ has(toolName: string): boolean;
266
+ /**
267
+ * Invoke the named tool with the given input + per-dispatch wired
268
+ * context. The channel server wraps this call in a timeout +
269
+ * try/catch; implementations SHOULD NOT add their own retry or
270
+ * timeout layer on top.
271
+ *
272
+ * `ctx.sendPropsUpdate` is closed over the active session — mounts
273
+ * fire it to push props to live subscribers without an extra refresh
274
+ * round-trip. Refresh-stream invocations (the post-action pass that
275
+ * fires every declared `streamSpec[*].tool`) reuse the SAME ctx —
276
+ * a refresh tool that wants to emit a props_update can do so, though
277
+ * the canonical surface is the action tool itself.
278
+ */
279
+ invoke(toolName: string, input: Record<string, unknown>, ctx: WiredActionContext): Promise<unknown>;
280
+ }
281
+ export interface SessionChannelOptions {
282
+ /** Required — the session backing store (typically `InMemorySessionStore`). */
283
+ readonly sessionStore: SessionStore;
284
+ /**
285
+ * Required — the same `AuthAdapter` the `/mcp` endpoint uses. Any
286
+ * failure during `subscribe` rejects the upgrade with HTTP 401.
287
+ */
288
+ readonly auth: AuthAdapter;
289
+ /**
290
+ * Maps resolved identity → tenant appId. Defaults to
291
+ * `defaultAppIdFromIdentity` — same mapping the `/mcp` endpoint uses.
292
+ */
293
+ /** Structured logger. */
294
+ readonly logger: Logger;
295
+ /** URL path to mount on. Defaults to `/ws`. */
296
+ readonly path?: string;
297
+ /**
298
+ * Outbound stream replay buffer. Defaults to a fresh
299
+ * `InMemorySessionStreamBuffer` when omitted — fine for OSS
300
+ * zero-config / dev. Persistent adapters bind via the same
301
+ * `SessionStreamBuffer` interface when they land.
302
+ *
303
+ * Each channel instance owns its own seq cursor space; sharing a
304
+ * buffer across two channels in the same process would couple their
305
+ * sequences in confusing ways.
306
+ */
307
+ readonly streamBuffer?: SessionStreamBuffer;
308
+ /**
309
+ * Live-tail pub/sub for outbound live-channel frames. Defaults to a
310
+ * fresh `InProcessStreamFanout` (in-memory, single-process). Hosted
311
+ * deployments bind a `RedisPubSubFanout` here for multi-process
312
+ * fan-out.
313
+ *
314
+ * The channel server uses the seam to publish every fanout-eligible
315
+ * envelope and to subscribe one async iterator per WebSocket
316
+ * subscriber — no in-process Map walk; the seam owns routing.
317
+ */
318
+ readonly streamFanout?: StreamFanout;
319
+ /**
320
+ * Optional bootstrap-auth plumbing. When present, the channel
321
+ * accepts `SubscribePayload.bootstrap` and issues reconnect
322
+ * credentials in `AckPayload.sessionToken`. When absent, bootstrap
323
+ * tokens are rejected with `BOOTSTRAP_NOT_SUPPORTED`.
324
+ */
325
+ readonly bootstrap?: SessionChannelBootstrap;
326
+ /**
327
+ * Optional console cookie-auth plumbing. When present, the
328
+ * channel upgrade looks for the configured cookie on the incoming
329
+ * request. A valid cookie binds the identity as a `builder` and
330
+ * scopes the subscriber to the cookie's `sessionId` — any
331
+ * `subscribe.sessionId` mismatch is rejected with
332
+ * `DEVTOOL_COOKIE_SESSION_MISMATCH`.
333
+ *
334
+ * Absent = cookie auth disabled on this channel. Cookies are never
335
+ * auto-enabled; the server's console composition decides.
336
+ *
337
+ * Design boundary: this auth plane is MUTUALLY EXCLUSIVE with
338
+ * bootstrap auth at upgrade time. When both are configured, the
339
+ * bootstrap path (via `?bootstrap=` query) wins; cookie is only
340
+ * consulted for standard upgrades.
341
+ */
342
+ readonly cookieAuth?: SessionChannelCookieAuth;
343
+ /**
344
+ * Opt-in wired-action dispatch router. When present, validated
345
+ * `data:submit` envelopes whose declared `actionSpec[name]
346
+ * .tool` names a tool the router knows fire the tool in-process and
347
+ * emit any declared refresh on the session. See
348
+ * {@link WiredActionRouter}.
349
+ *
350
+ * Absent (the default) = the server relays inbound actions to the
351
+ * session store for agent pickup and emits no synthetic stream
352
+ * frames. Matches pre-Slice-11.5 behavior — no regression surface.
353
+ */
354
+ readonly wiredActionRouter?: WiredActionRouter;
355
+ /**
356
+ * Per-call timeout for wired-tool invocations, in milliseconds.
357
+ * Defaults to {@link DEFAULT_WIRED_TOOL_TIMEOUT_MS} (30 s). Applied
358
+ * identically to the initial action tool AND to each refresh-stream
359
+ * tool. On timeout, a `TOOL_TIMEOUT` envelope emits on
360
+ * `_ggui:contract-error` and the session channel keeps running.
361
+ */
362
+ readonly wiredActionTimeoutMs?: number;
363
+ /**
364
+ * Override the default sanitizer applied to the stringified original
365
+ * error before it's written to `ContractErrorPayload.error.causedBy`.
366
+ *
367
+ * Defaults to `@ggui-ai/protocol::sanitizeCausedBy` (redacts Bearer
368
+ * tokens, query-param secrets, common env-var patterns, truncates at
369
+ * 2KB). Operators running in locked-down environments can pass a
370
+ * stricter function — e.g., one that returns an empty string to
371
+ * disable `causedBy` entirely, or one that layers additional
372
+ * patterns on top of the defaults.
373
+ *
374
+ * The contract-error envelope flows on `_ggui:contract-error` with
375
+ * `replay: 'all'`, so anything that lands in `causedBy` persists in
376
+ * the session ring buffer and surfaces in SessionInspector. Accepting
377
+ * raw `err.stack` verbatim is a credential-leak footgun; the default
378
+ * sanitizer is load-bearing.
379
+ */
380
+ readonly sanitizeCausedBy?: SanitizeCausedBy;
381
+ /**
382
+ * Reserved-channel payload validators for channels whose shape is
383
+ * NOT protocol-owned (Item 4 injection pattern). The primary
384
+ * consumer is `_ggui:preview` — the server composes a
385
+ * {@link ReservedChannelValidator} adapting
386
+ * `@ggui-ai/preview-a2ui::parseServerMessage` so malformed A2UI
387
+ * frames emitted on the preview channel reject at the fan-out
388
+ * boundary instead of landing in the subscriber's renderer.
389
+ *
390
+ * Lookup inside {@link validateStreamData} consults this map FIRST,
391
+ * then the protocol-shipped `BUILTIN_RESERVED_VALIDATORS` (which
392
+ * validates `_ggui:contract-error`), then falls through to
393
+ * `{valid: true}` when a known reserved channel has no validator.
394
+ *
395
+ * Absent = no `_ggui:preview` validation (documented degradation for
396
+ * implementations without the preview package); `_ggui:contract-
397
+ * error` is always validated via the built-in.
398
+ */
399
+ readonly extraReservedValidators?: ReadonlyMap<string, ReservedChannelValidator>;
400
+ /**
401
+ * Optional {@link TelemetrySink} for live-channel operational signals
402
+ * (C12). When present, the channel emits `wired-tool.invoked` events
403
+ * on successful wired-tool dispatches — operational counts +
404
+ * durations for OTLP / CloudWatch / Datadog forwarders. Defaults
405
+ * to {@link NoopTelemetrySink} (swallow silently).
406
+ *
407
+ * Deliberately separate from the renderer's client-side
408
+ * `ObservabilityEvent` surface: same event name, two independent
409
+ * consumers (backend metrics vs host inspector UI). See C12 plan +
410
+ * the TelemetrySink docstring for the sync/lossy contract.
411
+ */
412
+ readonly telemetry?: TelemetrySink;
413
+ /**
414
+ * Opt-in `channel_subscribe` plumbing for `streamSpec[*].source.tool`
415
+ * fan-out. When present, channel subscribes whose
416
+ * `source.tool` is in `allowlist` are accepted and the server begins
417
+ * polling. When absent, every `channel_subscribe` returns
418
+ * `CHANNEL_NOT_LOCAL` so the iframe falls back to direct polling via
419
+ * the MCP host proxy.
420
+ *
421
+ * Same `allowlist` MUST be advertised on
422
+ * `handshake.serverCapabilities.streamWebSocketLocalTools` so iframe
423
+ * + server agree on which channels use the WS fan-out path.
424
+ */
425
+ readonly streamWebSocketLocalTools?: SessionChannelLocalToolsOptions;
426
+ /**
427
+ * Protocol-version handshake policy. Governs server behavior when a
428
+ * subscribe declares a `supportedVersions` list that does NOT
429
+ * contain this server's {@link PROTOCOL_SCHEMA_VERSION}.
430
+ *
431
+ * - `'reject'` (default): server emits
432
+ * `{type:'error', payload.code: 'UPGRADE_REQUIRED'}` AND closes
433
+ * the underlying WebSocket. The caller cannot accidentally
434
+ * proceed against a version-mismatched session. This is the
435
+ * canonical posture for first-party servers.
436
+ * - `'advisory'` (opt-out): server emits `UPGRADE_REQUIRED`
437
+ * but keeps the connection open — the subscribe stops (no ack,
438
+ * no stack, no replay). Existing clients that ignore the error
439
+ * code continue to interoperate exactly as pre-handshake.
440
+ * Use only for controlled migration windows during which
441
+ * legacy-version clients must remain attached.
442
+ *
443
+ * Absent `payload.supportedVersions` always passes through — the
444
+ * handshake is fully opt-in on the client side. `serverVersion` is
445
+ * stamped into every successful ack regardless of policy.
446
+ *
447
+ * Switching between `'advisory'` and `'reject'` is a config change,
448
+ * not a schema change — the wire fields and error code ship
449
+ * identically in both modes.
450
+ */
451
+ readonly versionPolicy?: 'advisory' | 'reject';
452
+ }
453
+ /**
454
+ * Cookie-based authentication for the live-channel upgrade. Used
455
+ * exclusively by the same-origin console viewer; see
456
+ * `console-auth.ts` for the single consumer today.
457
+ */
458
+ export interface SessionChannelCookieAuth {
459
+ /**
460
+ * Read the raw cookie value for THIS server's console cookie
461
+ * from the incoming request headers. Returns `null` when the
462
+ * cookie is absent or malformed.
463
+ */
464
+ readCookie(headers: import('node:http').IncomingHttpHeaders): string | null;
465
+ /**
466
+ * Verify a cookie value and return the bound session/app. Returns
467
+ * `null` on any failure (signature, expiry, wrong kind). Never
468
+ * throws.
469
+ */
470
+ verify(cookieValue: string): {
471
+ sessionId: string;
472
+ appId: string;
473
+ } | null;
474
+ }
475
+ export interface SessionChannelServer {
476
+ /** The URL path the channel accepts upgrade requests on. */
477
+ readonly path: string;
478
+ /**
479
+ * Wire this into the HTTP server's `upgrade` event. Rejects with 401
480
+ * on auth failure; otherwise completes the WS handshake and wires
481
+ * the subscriber.
482
+ */
483
+ handleUpgrade(req: IncomingMessage, socket: Duplex, head: Buffer): void;
484
+ /**
485
+ * Deliver a stream envelope to every subscriber of `delivery.sessionId`.
486
+ *
487
+ * Outbound fan-out enforcement point — the delivery's `payload` is
488
+ * validated against the active stack item's streamSpec via
489
+ * `assertStreamContract` before any subscriber receives it.
490
+ *
491
+ * Sequencing + replay behavior:
492
+ * 1. Payload validated against the active stack item's streamSpec.
493
+ * 2. The replay buffer assigns a session-scoped monotonic `seq` and
494
+ * (conditionally) stores the stamped envelope per the channel's
495
+ * replay policy (`'none'` skip / `'latest'` single-slot /
496
+ * `'all'` FIFO ring).
497
+ * 3. The stamped envelope fans out to every subscriber for the
498
+ * session, skipping any whose initial replay already covered
499
+ * this seq (prevents double delivery on reconnect).
500
+ *
501
+ * The caller supplies `StreamEnvelopeInput` (no seq); the server
502
+ * stamps. Returns the stamped `seq` for callers that need to thread
503
+ * ordering back to their own response (e.g., `ggui_emit`'s wire
504
+ * output). When the channel's replay policy was `'none'`, seq is
505
+ * still assigned (so fan-out has a stable cursor) but nothing is
506
+ * stored — the seq still surfaces here so the caller has the same
507
+ * shape regardless of replay policy.
508
+ *
509
+ * Throws `ContractViolationError` on payload mismatch; transport
510
+ * errors are logged but not propagated (per-subscriber best-effort).
511
+ */
512
+ sendToSession(delivery: StreamEnvelopeInput): Promise<{
513
+ seq: number;
514
+ }>;
515
+ /**
516
+ * Fan a `{type:'push', payload:{stackItem, matchType?}}` wire frame
517
+ * to every subscriber currently bound to `sessionId`. Use this to
518
+ * notify already-subscribed clients about a stack mutation that
519
+ * happened AFTER they subscribed — the initial `ack.stack` snapshot
520
+ * covers state at subscribe time only, so without an explicit notify
521
+ * a second-turn `appendStackItem` is invisible to the live client.
522
+ *
523
+ * The `B1` regression context (2026-04-22 QA pass): the chat surface
524
+ * in `/chat` reuses one session across turns. The first turn's push
525
+ * subscribed AFTER `appendStackItem` ran, so the ack carried the
526
+ * entry. The second turn's push appended on the live session — the
527
+ * subscriber never heard about the new entry, the inline UI slot
528
+ * stayed in "Waiting for session channel replay…" indefinitely.
529
+ * `notifyStackPush` closes that gap. Best-effort: per-subscriber
530
+ * send failures are swallowed (same posture as `sendToSession`).
531
+ *
532
+ * NOT durable. Frames are not stamped through the replay buffer —
533
+ * fresh subscribers still get the current stack via `ack.stack` on
534
+ * subscribe. A new tab opening mid-session reads the latest stack
535
+ * from the snapshot; live tabs read the delta from this notify.
536
+ *
537
+ * Subscribers received via `register()` are tracked in
538
+ * `subscribersBySession`; this helper iterates the bound set and
539
+ * skips closed sockets via the `send()` helper's existing guard.
540
+ * Callers ARE responsible for ordering — call after the underlying
541
+ * `sessionStore.appendStackItem` resolves so the snapshot a
542
+ * concurrent fresh subscriber observes still includes the entry.
543
+ */
544
+ notifyStackPush(sessionId: string, stackItem: SessionStackEntry, matchType?: string): void;
545
+ /**
546
+ * Prime every declared streamSpec channel on `stackItem` that carries a
547
+ * `tool` refresh hint. Invokes each refresh tool via the bound
548
+ * wiredActionRouter with the empty refresh input, validates the result
549
+ * against the channel's schema, and fans it out so subscribers see an
550
+ * initial value instead of `latest = undefined`.
551
+ *
552
+ * Intended for seed-a-session mount paths (console try-live, agent-
553
+ * initiated bootstraps that append a stack item without a driving
554
+ * action). Without this, blueprints with `streamSpec[channel].tool`
555
+ * render their empty-state branch because the channel has no live
556
+ * delivery — operators see "waiting for data" UI even when the
557
+ * refresh tool would have produced initial content.
558
+ *
559
+ * Same isolation posture as the action-driven refresh pass: one
560
+ * broken refresh MUST NOT block others; per-channel failures log a
561
+ * warning but don't throw. No-op when no wiredActionRouter is
562
+ * configured, when `stackItem.streamSpec` is absent, or when every
563
+ * channel lacks a `.tool` hint.
564
+ *
565
+ * Ordering: callers should invoke AFTER the stack item is persisted
566
+ * so `sendToSession`'s active-stack-item lookup resolves. The
567
+ * `try-live` endpoint awaits this before returning the shortCode so
568
+ * the viewer SPA subscribes with the initial envelope already
569
+ * buffered on the session's stream-buffer replay state.
570
+ */
571
+ primeStreams(sessionId: string, stackItem: SessionStackEntry): Promise<void>;
572
+ /**
573
+ * Fan a `{type:'props_update', payload:{stackItemId, props}}` wire frame
574
+ * to every subscriber currently bound to `sessionId`. Mount tools
575
+ * dispatched through {@link WiredActionRouter} call this via
576
+ * `WiredActionContext.sendPropsUpdate` so a wired action that
577
+ * mutates server-side state can replace renderer props in-place
578
+ * without going through a refresh-stream tool.
579
+ *
580
+ * Validation posture (mirrors `notifyStackPush`'s "best-effort orphan
581
+ * no-op"):
582
+ * 1. Look up the session via `sessionStore.get`. Absent → log
583
+ * `session_channel_props_update_orphan` and return — the wire
584
+ * validator on the renderer side would reject a frame for an
585
+ * unknown session anyway.
586
+ * 2. Look up the target stack entry by `stackItemId` in the loaded
587
+ * session's stack. Absent → log
588
+ * `session_channel_props_update_pageid_unknown` and return.
589
+ * 3. Iterate the flat WS-subscriber set, filter to subscribers
590
+ * whose `sessionId` matches, and `send()` the frame. Closed
591
+ * sockets are skipped silently by `send()`.
592
+ *
593
+ * NOT routed through StreamFanout — `type: 'props_update'` is a
594
+ * distinct WebSocket message type, not a stream envelope. Stream
595
+ * envelopes flow on `data` frames and have a `seq` cursor; props
596
+ * updates are ephemeral and follow `notifyStackPush`'s pattern
597
+ * (live-only, no replay-buffer stamping). A new subscriber that
598
+ * connects mid-session reads current `props` from the stack
599
+ * snapshot delivered in `ack.stack`.
600
+ *
601
+ * Schema validation against `propsSpec`: NOT enforced server-side
602
+ * here. The renderer validates inbound props via
603
+ * `validateInboundPropsPayload` against the cached
604
+ * `stackItem.propsSpec` before applying — defense-in-depth at the
605
+ * receiving boundary. Server-side enforcement is reserved for the
606
+ * future agent-driven `ggui_update` path; the mount-tool seam is
607
+ * trusted-runtime today (mounts execute in-process, same trust
608
+ * boundary as ggui-native handlers).
609
+ */
610
+ sendPropsUpdate(sessionId: string, stackItemId: string, props: JsonObject): Promise<void>;
611
+ /**
612
+ * Fan a `{type:'drain_ack', payload:{sessionId, appId, stackItemId,
613
+ * eventId, drainedAt}}` wire frame to every subscriber currently
614
+ * bound to `sessionId`.
615
+ *
616
+ * Fired by `createGguiConsumeHandler` once per drained
617
+ * `PendingEvent` so the iframe-runtime can cancel the matching
618
+ * per-action 10s claim timer + resolve the toast as `consumed`.
619
+ * Implements the `DrainAckNotifier` contract from
620
+ * `@ggui-ai/mcp-server-handlers`.
621
+ *
622
+ * Same posture as `notifyStackPush` / `sendPropsUpdate` — live-only,
623
+ * no replay-buffer stamping. Subscribers that connect AFTER the
624
+ * drain see the next consume's snapshot rather than the missed
625
+ * frame; the iframe's claim timer + atomic-pop primitive backstop
626
+ * any frame loss.
627
+ */
628
+ sendDrainAck(args: {
629
+ readonly sessionId: string;
630
+ readonly appId: string;
631
+ readonly stackItemId: string;
632
+ readonly eventId: string;
633
+ readonly drainedAt: string;
634
+ }): void;
635
+ /** Number of live subscribers. Useful for health / debug introspection. */
636
+ readonly subscriberCount: number;
637
+ /** Number of distinct sessions with at least one subscriber. */
638
+ readonly sessionCount: number;
639
+ /**
640
+ * Close every live subscriber + the underlying ws server. Idempotent.
641
+ */
642
+ close(): Promise<void>;
643
+ }
644
+ /**
645
+ * Build an OSS live-channel server. The returned object is designed to be
646
+ * composed into `createGguiServer` — see `server.ts` for the wire-up.
647
+ */
648
+ export declare function createSessionChannelServer(opts: SessionChannelOptions): SessionChannelServer;
649
+ /** Fabricate a request id for live-channel ops so logs correlate. */
650
+ export declare function newRequestId(): string;
651
+ //# sourceMappingURL=session-channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-channel.d.ts","sourceRoot":"","sources":["../src/session-channel.ts"],"names":[],"mappings":"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"}