@jini-ai/ui 0.4.2 → 0.4.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # @jini-ai/ui
2
2
 
3
+ ## 0.4.3 — 2026-10-05
4
+
5
+ - MCP-UI resources can carry an answer deadline: `createUIResource`/`buildConfirmationSurface` take `expiresAtMs`, written to `MCP_UI_EXPIRES_AT_META_KEY`; `readExpiresAt` reads it back (undefined when absent or not a finite number).
6
+
3
7
  ## 0.4.2 — 2026-10-04
4
8
 
5
9
  - Internal `@jini-ai/*` dependencies are caret ranges (`workspace:^`) instead of exact pins, so a host on `@jini-ai/agentic` 0.4.1 or on a newer patch resolves a single copy without an override.
@@ -74,6 +74,16 @@ export declare const JINI_MCP_UI_METADATA_PREFIX = "x-jini-mcp-ui/";
74
74
  * `@jini-ai/chat` for the host-side consumer.
75
75
  */
76
76
  export declare const MCP_UI_ACTION_PLAN_META_KEY = "x-jini-mcp-ui/action-plan";
77
+ /**
78
+ * The `_meta` key a host reads to count down how long a surface can still be answered.
79
+ *
80
+ * A held-open question (a confirmation the tool waits on) stops being answerable when the server
81
+ * gives up waiting, but nothing in the document said when that would be, so a person could read a
82
+ * card that had already expired. The value is the deadline in epoch milliseconds on the PRODUCER's
83
+ * clock: a host whose clock runs ahead of the server's closes the card early by that skew, never late.
84
+ * See `McpUiSurfaceCard` in `@jini-ai/chat` for the host-side consumer.
85
+ */
86
+ export declare const MCP_UI_EXPIRES_AT_META_KEY = "x-jini-mcp-ui/expires-at";
77
87
  /** One action in a surface's plan — the `_meta`-safe subset of `surfaces/document.ts`'s `SurfaceAction` (no `type`: that field only affects in-frame `<form>` submission, which has no parent-DOM equivalent). */
78
88
  export interface McpUiActionPlanAction {
79
89
  readonly id: string;
@@ -130,8 +140,9 @@ export interface UIToolResult {
130
140
  * @param spec.preferredFrameSize - `[width, height]` CSS lengths, written to the `_meta` key mcp-ui
131
141
  * hosts read.
132
142
  * @param spec.actionPlan - See {@link McpUiActionPlan}, written to {@link MCP_UI_ACTION_PLAN_META_KEY}.
133
- * @param spec.meta - Extra `_meta` entries, merged after `preferredFrameSize`/`actionPlan` so a
134
- * caller can override either.
143
+ * @param spec.expiresAtMs - When the surface stops being answerable, written to {@link MCP_UI_EXPIRES_AT_META_KEY}.
144
+ * @param spec.meta - Extra `_meta` entries, merged after `preferredFrameSize`/`actionPlan`/`expiresAtMs`
145
+ * so a caller can override any of them.
135
146
  * @returns The `EmbeddedResource` to place in a tool result's `content` array.
136
147
  * @complexity O(1).
137
148
  */
@@ -140,6 +151,7 @@ export declare function createUIResource(spec: {
140
151
  htmlString: string;
141
152
  preferredFrameSize?: readonly [string, string];
142
153
  actionPlan?: McpUiActionPlan;
154
+ expiresAtMs?: number;
143
155
  meta?: Readonly<Record<string, unknown>>;
144
156
  }): UIResource;
145
157
  /**
@@ -189,4 +201,12 @@ export declare function readPreferredFrameSize(resource: UIResource): readonly [
189
201
  * @returns The plan, or `undefined` when absent or malformed.
190
202
  */
191
203
  export declare function readActionPlan(resource: UIResource): McpUiActionPlan | undefined;
204
+ /**
205
+ * Reads the answer deadline a resource's `_meta` may carry — see {@link MCP_UI_EXPIRES_AT_META_KEY}.
206
+ *
207
+ * @returns Epoch milliseconds, or `undefined` when absent or not a finite number — a host that gets
208
+ * `undefined` shows no countdown rather than one built on a malformed value.
209
+ * @complexity O(1).
210
+ */
211
+ export declare function readExpiresAt(resource: UIResource): number | undefined;
192
212
  //# sourceMappingURL=resource.d.ts.map
@@ -67,6 +67,16 @@ export const JINI_MCP_UI_METADATA_PREFIX = 'x-jini-mcp-ui/';
67
67
  * `@jini-ai/chat` for the host-side consumer.
68
68
  */
69
69
  export const MCP_UI_ACTION_PLAN_META_KEY = `${JINI_MCP_UI_METADATA_PREFIX}action-plan`;
70
+ /**
71
+ * The `_meta` key a host reads to count down how long a surface can still be answered.
72
+ *
73
+ * A held-open question (a confirmation the tool waits on) stops being answerable when the server
74
+ * gives up waiting, but nothing in the document said when that would be, so a person could read a
75
+ * card that had already expired. The value is the deadline in epoch milliseconds on the PRODUCER's
76
+ * clock: a host whose clock runs ahead of the server's closes the card early by that skew, never late.
77
+ * See `McpUiSurfaceCard` in `@jini-ai/chat` for the host-side consumer.
78
+ */
79
+ export const MCP_UI_EXPIRES_AT_META_KEY = `${JINI_MCP_UI_METADATA_PREFIX}expires-at`;
70
80
  /**
71
81
  * Builds a UI resource from self-contained HTML.
72
82
  *
@@ -78,8 +88,9 @@ export const MCP_UI_ACTION_PLAN_META_KEY = `${JINI_MCP_UI_METADATA_PREFIX}action
78
88
  * @param spec.preferredFrameSize - `[width, height]` CSS lengths, written to the `_meta` key mcp-ui
79
89
  * hosts read.
80
90
  * @param spec.actionPlan - See {@link McpUiActionPlan}, written to {@link MCP_UI_ACTION_PLAN_META_KEY}.
81
- * @param spec.meta - Extra `_meta` entries, merged after `preferredFrameSize`/`actionPlan` so a
82
- * caller can override either.
91
+ * @param spec.expiresAtMs - When the surface stops being answerable, written to {@link MCP_UI_EXPIRES_AT_META_KEY}.
92
+ * @param spec.meta - Extra `_meta` entries, merged after `preferredFrameSize`/`actionPlan`/`expiresAtMs`
93
+ * so a caller can override any of them.
83
94
  * @returns The `EmbeddedResource` to place in a tool result's `content` array.
84
95
  * @complexity O(1).
85
96
  */
@@ -89,6 +100,7 @@ export function createUIResource(spec) {
89
100
  ? {}
90
101
  : { [MCP_UI_PREFERRED_FRAME_SIZE_META_KEY]: [...spec.preferredFrameSize] }),
91
102
  ...(spec.actionPlan === undefined ? {} : { [MCP_UI_ACTION_PLAN_META_KEY]: spec.actionPlan }),
103
+ ...(spec.expiresAtMs === undefined ? {} : { [MCP_UI_EXPIRES_AT_META_KEY]: spec.expiresAtMs }),
92
104
  ...spec.meta,
93
105
  };
94
106
  return {
@@ -225,4 +237,15 @@ export function readActionPlan(resource) {
225
237
  }
226
238
  return { title, ...(description === undefined ? {} : { description }), actions };
227
239
  }
240
+ /**
241
+ * Reads the answer deadline a resource's `_meta` may carry — see {@link MCP_UI_EXPIRES_AT_META_KEY}.
242
+ *
243
+ * @returns Epoch milliseconds, or `undefined` when absent or not a finite number — a host that gets
244
+ * `undefined` shows no countdown rather than one built on a malformed value.
245
+ * @complexity O(1).
246
+ */
247
+ export function readExpiresAt(resource) {
248
+ const raw = resource.resource._meta?.[MCP_UI_EXPIRES_AT_META_KEY];
249
+ return typeof raw === 'number' && Number.isFinite(raw) ? raw : undefined;
250
+ }
228
251
  //# sourceMappingURL=resource.js.map
@@ -120,10 +120,13 @@ export declare function renderConfirmationDocument(spec: ConfirmationSurfaceSpec
120
120
  * @param spec.uri - The `ui://` identifier. Key it by entity and version, never by the confirmation
121
121
  * token: a URI is something a host may log, cache, or show in devtools.
122
122
  * @param spec.preferredFrameSize - `[width, height]` hint for hosts that honor it.
123
+ * @param spec.expiresAtMs - When the server stops waiting for an answer (epoch ms), so a host can
124
+ * count it down and close the card when it passes. Omit for a dialog with no deadline.
123
125
  * @complexity O(n) in the rendered length.
124
126
  */
125
127
  export declare function buildConfirmationSurface(spec: ConfirmationSurfaceSpec & {
126
128
  uri: UIResourceUri;
127
129
  preferredFrameSize?: readonly [string, string];
130
+ expiresAtMs?: number;
128
131
  }): UIResource;
129
132
  //# sourceMappingURL=confirmation.d.ts.map
@@ -313,6 +313,8 @@ ${SURFACE_SCRIPT_PRELUDE}
313
313
  * @param spec.uri - The `ui://` identifier. Key it by entity and version, never by the confirmation
314
314
  * token: a URI is something a host may log, cache, or show in devtools.
315
315
  * @param spec.preferredFrameSize - `[width, height]` hint for hosts that honor it.
316
+ * @param spec.expiresAtMs - When the server stops waiting for an answer (epoch ms), so a host can
317
+ * count it down and close the card when it passes. Omit for a dialog with no deadline.
316
318
  * @complexity O(n) in the rendered length.
317
319
  */
318
320
  export function buildConfirmationSurface(spec) {
@@ -320,6 +322,7 @@ export function buildConfirmationSurface(spec) {
320
322
  uri: spec.uri,
321
323
  htmlString: renderConfirmationDocument(spec),
322
324
  ...(spec.preferredFrameSize === undefined ? {} : { preferredFrameSize: spec.preferredFrameSize }),
325
+ ...(spec.expiresAtMs === undefined ? {} : { expiresAtMs: spec.expiresAtMs }),
323
326
  // Same title/actions the frame itself renders (via confirmationActions) — see that function's
324
327
  // doc for why this must never be a second, independently-maintained mapping. A host reads this
325
328
  // to build a parent-DOM mirror discoverable by page.find_elements; see MCP_UI_ACTION_PLAN_META_KEY.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jini-ai/ui",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "Generic, product-neutral React UI primitives and feature domains. Framework-free types, decision rules, catalogs, and host port contracts live behind ./core (no React, no DOM). The Excalidraw and Lexical editors live behind ./sketch-editor and ./lexical-rich-text-editor; the GrapesJS-backed inline HTML editor lives behind ./html-editor.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -163,7 +163,7 @@
163
163
  "tailwind-merge": "^2.6.0",
164
164
  "zod": "^3.25.76",
165
165
  "@jini-ai/agentic": "^0.4.1",
166
- "@jini-ai/core": "^0.4.0"
166
+ "@jini-ai/core": "^0.4.1"
167
167
  },
168
168
  "devDependencies": {
169
169
  "@excalidraw/excalidraw": "0.18.1",