summaryrefslogtreecommitdiffhomepage
path: root/.dispatch/ui-contract.reference.md
diff options
context:
space:
mode:
Diffstat (limited to '.dispatch/ui-contract.reference.md')
-rw-r--r--.dispatch/ui-contract.reference.md54
1 files changed, 51 insertions, 3 deletions
diff --git a/.dispatch/ui-contract.reference.md b/.dispatch/ui-contract.reference.md
index 3962fc1..00d354f 100644
--- a/.dispatch/ui-contract.reference.md
+++ b/.dispatch/ui-contract.reference.md
@@ -6,6 +6,13 @@
> file is for READING only.
>
> **Orchestrator:** this is a SNAPSHOT — regenerate it whenever `ui-contract` changes.
+>
+> **2026-06 delta (cache-warming handoff):** adds the `NumberField` variant (`kind:"number"`) to
+> the `SurfaceField` union, and an OPTIONAL `conversationId?` to `SubscribeMessage` /
+> `UnsubscribeMessage` / `InvokeMessage` / `SurfaceMessage` / `SurfaceUpdate` so a surface can be
+> CONVERSATION-SCOPED (state differs per conversation, e.g. `cache-warming`) vs GLOBAL (one state for
+> all, e.g. `loaded-extensions`). All additive / backward-compatible: a global surface omits
+> `conversationId` and behaves exactly as before. (Backend left the package version at `0.1.0`.)
```ts
/**
@@ -37,6 +44,7 @@ export type SurfaceField =
| ProgressField
| SelectorField
| StatField
+ | NumberField
| ButtonField
| CustomField;
@@ -71,6 +79,24 @@ export interface StatField {
readonly value: string;
}
+/**
+ * A settable numeric value plus the action that sets it — the free-value
+ * counterpart to `selector` (which is a fixed enum). Optional `min`/`max`/`step`
+ * are SEMANTIC bounds a client may use to validate/step input; `unit` is a
+ * display hint (e.g. "ms", "s"). The client posts the new number as the action
+ * payload. Unlike `progress`/`stat` (read-only), this field is interactive.
+ */
+export interface NumberField {
+ readonly kind: "number";
+ readonly label: string;
+ readonly value: number;
+ readonly min?: number;
+ readonly max?: number;
+ readonly step?: number;
+ readonly unit?: string;
+ readonly action: ActionRef;
+}
+
/** A labelled action trigger. */
export interface ButtonField {
readonly kind: "button";
@@ -106,10 +132,15 @@ export interface SurfaceCatalogEntry {
/** The surface catalog: the list of available surfaces a client can choose to show. */
export type SurfaceCatalog = readonly SurfaceCatalogEntry[];
-/** A live update for a subscribed surface. v1 carries the full new spec. */
+/**
+ * A live update for a subscribed surface. v1 carries the full new spec.
+ * `conversationId` is present only for a CONVERSATION-SCOPED surface (tells the
+ * client which conversation this update is for); a global surface omits it.
+ */
export interface SurfaceUpdate {
readonly surfaceId: string;
readonly spec: SurfaceSpec;
+ readonly conversationId?: string;
}
// ── Surface WebSocket protocol (slice 1: surfaces only) ──────────────────────
@@ -117,22 +148,34 @@ export interface SurfaceUpdate {
/** A client → server message on the surface channel. */
export type SurfaceClientMessage = SubscribeMessage | UnsubscribeMessage | InvokeMessage;
+/**
+ * Begin receiving live updates for a surface. For a CONVERSATION-SCOPED surface,
+ * include the `conversationId` whose state you want; omit it for a global surface.
+ */
export interface SubscribeMessage {
readonly type: "subscribe";
readonly surfaceId: string;
+ readonly conversationId?: string;
}
+/** Stop receiving updates for a surface (and the same `conversationId`, if scoped). */
export interface UnsubscribeMessage {
readonly type: "unsubscribe";
readonly surfaceId: string;
+ readonly conversationId?: string;
}
-/** Invoke a field's action; `payload` is the new value (e.g. a toggle's boolean). */
+/**
+ * Invoke a field's action; `payload` is the new value (e.g. a toggle's boolean, a
+ * `number` field's new number). For a conversation-scoped surface, include the
+ * `conversationId` the action targets.
+ */
export interface InvokeMessage {
readonly type: "invoke";
readonly surfaceId: string;
readonly actionId: string;
readonly payload?: unknown;
+ readonly conversationId?: string;
}
/** A server → client message on the surface channel. */
@@ -148,10 +191,15 @@ export interface CatalogMessage {
readonly catalog: SurfaceCatalog;
}
-/** The full current spec for a surface the client just subscribed to. */
+/**
+ * The full current spec for a surface the client just subscribed to.
+ * `conversationId` echoes the subscribe's conversation for a conversation-scoped
+ * surface (so the client routes it), and is absent for a global surface.
+ */
export interface SurfaceMessage {
readonly type: "surface";
readonly spec: SurfaceSpec;
+ readonly conversationId?: string;
}
/** A live update for a subscribed surface. */