tempest-react-sdk 0.33.2 → 0.35.0

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 (87) hide show
  1. package/README.md +5 -3
  2. package/dist/components/AIChat/AIChat.cjs +2 -0
  3. package/dist/components/AIChat/AIChat.cjs.map +1 -0
  4. package/dist/components/AIChat/AIChat.js +141 -0
  5. package/dist/components/AIChat/AIChat.js.map +1 -0
  6. package/dist/components/AIChat/AIChat.module.cjs +2 -0
  7. package/dist/components/AIChat/AIChat.module.cjs.map +1 -0
  8. package/dist/components/AIChat/AIChat.module.js +58 -0
  9. package/dist/components/AIChat/AIChat.module.js.map +1 -0
  10. package/dist/components/AIChat/AIChatComposer.cjs +2 -0
  11. package/dist/components/AIChat/AIChatComposer.cjs.map +1 -0
  12. package/dist/components/AIChat/AIChatComposer.js +87 -0
  13. package/dist/components/AIChat/AIChatComposer.js.map +1 -0
  14. package/dist/components/AIChat/AIChatTurn.cjs +3 -0
  15. package/dist/components/AIChat/AIChatTurn.cjs.map +1 -0
  16. package/dist/components/AIChat/AIChatTurn.js +217 -0
  17. package/dist/components/AIChat/AIChatTurn.js.map +1 -0
  18. package/dist/components/AIChat/ai-chat-turns.cjs +2 -0
  19. package/dist/components/AIChat/ai-chat-turns.cjs.map +1 -0
  20. package/dist/components/AIChat/ai-chat-turns.js +90 -0
  21. package/dist/components/AIChat/ai-chat-turns.js.map +1 -0
  22. package/dist/perf/cache-size.cjs +2 -0
  23. package/dist/perf/cache-size.cjs.map +1 -0
  24. package/dist/perf/cache-size.js +16 -0
  25. package/dist/perf/cache-size.js.map +1 -0
  26. package/dist/perf/device.cjs +2 -0
  27. package/dist/perf/device.cjs.map +1 -0
  28. package/dist/perf/device.js +22 -0
  29. package/dist/perf/device.js.map +1 -0
  30. package/dist/perf/format.cjs +2 -0
  31. package/dist/perf/format.cjs.map +1 -0
  32. package/dist/perf/format.js +8 -0
  33. package/dist/perf/format.js.map +1 -0
  34. package/dist/perf/profiler.cjs +2 -0
  35. package/dist/perf/profiler.cjs.map +1 -0
  36. package/dist/perf/profiler.js +46 -0
  37. package/dist/perf/profiler.js.map +1 -0
  38. package/dist/styles.css +1 -1
  39. package/dist/tempest-react-sdk.cjs +1 -1
  40. package/dist/tempest-react-sdk.d.ts +626 -9
  41. package/dist/tempest-react-sdk.js +122 -114
  42. package/dist/vision/core/timing.cjs +2 -0
  43. package/dist/vision/core/timing.cjs.map +1 -0
  44. package/dist/vision/core/timing.js +24 -0
  45. package/dist/vision/core/timing.js.map +1 -0
  46. package/dist/vision/index.cjs +1 -1
  47. package/dist/vision/index.cjs.map +1 -1
  48. package/dist/vision/index.js +16 -15
  49. package/dist/vision/index.js.map +1 -1
  50. package/dist/vision/postprocess/detection.cjs +1 -1
  51. package/dist/vision/postprocess/detection.cjs.map +1 -1
  52. package/dist/vision/postprocess/detection.js +2 -2
  53. package/dist/vision/postprocess/detection.js.map +1 -1
  54. package/dist/vision/postprocess/segmentation.cjs +1 -1
  55. package/dist/vision/postprocess/segmentation.cjs.map +1 -1
  56. package/dist/vision/postprocess/segmentation.js +1 -1
  57. package/dist/vision/postprocess/segmentation.js.map +1 -1
  58. package/dist/vision/results.cjs +1 -1
  59. package/dist/vision/results.cjs.map +1 -1
  60. package/dist/vision/results.js +18 -13
  61. package/dist/vision/results.js.map +1 -1
  62. package/dist/vision/tasks/classifier.cjs +1 -1
  63. package/dist/vision/tasks/classifier.cjs.map +1 -1
  64. package/dist/vision/tasks/classifier.js +46 -39
  65. package/dist/vision/tasks/classifier.js.map +1 -1
  66. package/dist/vision/tasks/detector.cjs +1 -1
  67. package/dist/vision/tasks/detector.cjs.map +1 -1
  68. package/dist/vision/tasks/detector.js +40 -33
  69. package/dist/vision/tasks/detector.js.map +1 -1
  70. package/dist/vision/tasks/segmenter.cjs +1 -1
  71. package/dist/vision/tasks/segmenter.cjs.map +1 -1
  72. package/dist/vision/tasks/segmenter.js +35 -28
  73. package/dist/vision/tasks/segmenter.js.map +1 -1
  74. package/dist/vision.cjs +1 -1
  75. package/dist/vision.d.ts +68 -10
  76. package/dist/vision.js +19 -18
  77. package/dist/ws/create-web-socket.cjs +1 -1
  78. package/dist/ws/create-web-socket.cjs.map +1 -1
  79. package/dist/ws/create-web-socket.js +54 -37
  80. package/dist/ws/create-web-socket.js.map +1 -1
  81. package/dist/ws/use-web-socket.cjs +1 -1
  82. package/dist/ws/use-web-socket.cjs.map +1 -1
  83. package/dist/ws/use-web-socket.js +49 -18
  84. package/dist/ws/use-web-socket.js.map +1 -1
  85. package/package.json +1 -1
  86. package/template/src/lib/api.ts +27 -5
  87. package/template/src/stores/auth.ts +14 -0
@@ -158,6 +158,307 @@ export declare interface AccordionProps {
158
158
  className?: string;
159
159
  }
160
160
 
161
+ /**
162
+ * A conversation with a model: role-based turns, Markdown answers, a reasoning
163
+ * block, a streaming caret, per-turn actions and a composer that turns into a stop
164
+ * button while a turn is generating.
165
+ *
166
+ * This is the shape ChatGPT, Claude and DeepSeek converged on, and it is a different
167
+ * component from {@link Chat}, not a variant of it. A human thread is addressed by
168
+ * author and cares about delivery state; a model transcript is addressed by role,
169
+ * has no delivery state at all, and needs three things a human thread never does —
170
+ * partial output, reasoning separate from the answer, and re-asking.
171
+ *
172
+ * Presentational and controlled, like the rest of the SDK: it takes a list and emits
173
+ * intent (`onSend`, `onStop`, `onRegenerate`, `onEditSubmit`, `onFeedback`). The
174
+ * transport stays with the app, because "how do I stream from my backend" has a
175
+ * different answer per provider — the SDK's `createEventStream` covers SSE, `fetch`
176
+ * with a `ReadableStream` covers the rest, and either way the app owns the
177
+ * `AbortController` it hands to `onStop`.
178
+ *
179
+ * @example
180
+ * <AIChat
181
+ * messages={turns}
182
+ * pending={pending}
183
+ * onSend={(text) => ask(text)}
184
+ * onStop={() => controller.current?.abort()}
185
+ * onRegenerate={(turn) => reask(turn)}
186
+ * onFeedback={(turn, vote) => track("answer_rated", { id: turn.id, vote })}
187
+ * suggestions={["Resuma o último relatório", "Quais pedidos atrasaram?"]}
188
+ * />
189
+ */
190
+ export declare function AIChat({ messages, onSend, onStop, onRegenerate, onEditSubmit, onFeedback, onRetry, pending, suggestions, renderAvatar, renderContent, votes, header, emptyState, showSystem, defaultReasoningOpen, showLineNumbers, locale, placeholder, composerActions, composerFooter, composerDisabled, maxRows, onSendError, className, ...rest }: AIChatProps): JSX.Element;
191
+
192
+ /** A file carried by a turn — an upload on the way in, a document on the way out. */
193
+ export declare interface AIChatAttachment {
194
+ /** Stable identity. Used as the React key. */
195
+ id: string;
196
+ /** Name shown in the chip. */
197
+ name: string;
198
+ /** Size in bytes. Formatted for display when given. */
199
+ size?: number;
200
+ /** Image URL. When set the attachment renders as a thumbnail instead of a chip. */
201
+ url?: string;
202
+ /** MIME type. Used as the chip's secondary label when there is no size. */
203
+ mimeType?: string;
204
+ }
205
+
206
+ /**
207
+ * The prompt field of a conversation with a model: a textarea that grows with its
208
+ * content, sends on `Enter`, keeps `Shift+Enter` for a newline, and turns into a
209
+ * stop button while a turn is streaming.
210
+ *
211
+ * Uncontrolled on purpose. A draft changes on every keystroke, and lifting that into
212
+ * app state re-renders the whole transcript per character — with a streaming answer
213
+ * above, that is the one place where "controlled by default" costs something
214
+ * visible. Apps that need the draft (a persisted composer, a slash-command menu)
215
+ * read it from `onChange` or drive it through the ref.
216
+ *
217
+ * @example
218
+ * <AIChatComposer
219
+ * generating={generating}
220
+ * onSend={(text) => ask(text)}
221
+ * onStop={() => controller.abort()}
222
+ * footer={<small>Claude Opus 5 · pode errar</small>}
223
+ * />
224
+ */
225
+ export declare const AIChatComposer: ForwardRefExoticComponent<AIChatComposerProps & RefAttributes<AIChatComposerHandle>>;
226
+
227
+ /** Imperative handle, so a thread can focus or refill the field. */
228
+ export declare interface AIChatComposerHandle {
229
+ focus: () => void;
230
+ /** Replace the draft — used to put a prompt back in the field. */
231
+ setValue: (text: string) => void;
232
+ }
233
+
234
+ export declare interface AIChatComposerProps extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, OverriddenDomProps_5> {
235
+ /** Called with the trimmed prompt. The field clears only when this does not throw. */
236
+ onSend: (text: string) => void | Promise<void>;
237
+ /**
238
+ * Abort the turn in flight.
239
+ *
240
+ * When given together with `generating`, the send button becomes a stop button
241
+ * and `Escape` aborts too.
242
+ */
243
+ onStop?: () => void;
244
+ /** A turn is being generated. Replaces send with stop and refuses to send. */
245
+ generating?: boolean;
246
+ /** Locale for the placeholder and the button labels. Default `"pt-BR"`. */
247
+ locale?: "pt-BR" | "en";
248
+ /** Left of the send button — an attach control, a model picker, a tool toggle. */
249
+ actions?: ReactNode;
250
+ /** Under the field — a token count, the model name, a disclaimer. */
251
+ footer?: ReactNode;
252
+ /** Largest height the field grows to, in lines. Default 8. */
253
+ maxRows?: number;
254
+ /**
255
+ * Called when `onSend` rejects. The draft is kept either way.
256
+ *
257
+ * Without it the rejection is swallowed after the draft is preserved: re-throwing
258
+ * out of a DOM event handler surfaces as an unhandled promise rejection, which is
259
+ * console noise for the developer and nothing the user can act on. The visible
260
+ * signal is the prompt still sitting in the field; wire this to a toast to say why.
261
+ */
262
+ onError?: (error: unknown) => void;
263
+ }
264
+
265
+ /** One turn of a conversation with a model. */
266
+ export declare interface AIChatMessage {
267
+ /** Stable identity. Used as the React key and by every callback. */
268
+ id: string;
269
+ role: AIChatRole;
270
+ /**
271
+ * The text of the turn.
272
+ *
273
+ * An assistant turn is rendered as Markdown; a user turn is rendered as plain
274
+ * text with newlines preserved. That asymmetry is deliberate: a model emits
275
+ * Markdown by contract, while a person typing `2 * 3 * 4` did not mean to open
276
+ * an emphasis span.
277
+ */
278
+ content: string;
279
+ /**
280
+ * Reasoning the model exposed before answering — extended thinking, a
281
+ * chain-of-thought trace.
282
+ *
283
+ * Rendered in its own collapsible block above the answer, so a long trace never
284
+ * pushes the answer off screen.
285
+ */
286
+ reasoning?: string;
287
+ /**
288
+ * The turn is still arriving.
289
+ *
290
+ * Shows the caret, marks the block `aria-busy`, and hides the action row —
291
+ * copying or rating half an answer is never what somebody meant to do.
292
+ */
293
+ streaming?: boolean;
294
+ /** Generation failed. Shown under whatever streamed, with the retry control. */
295
+ error?: string;
296
+ /** Epoch milliseconds. */
297
+ createdAt?: number;
298
+ /** Model that produced the turn. Shown in the meta row of an assistant turn. */
299
+ model?: string;
300
+ attachments?: readonly AIChatAttachment[];
301
+ /** Anything the app wants to carry through to its own renderers. */
302
+ data?: Record<string, unknown>;
303
+ }
304
+
305
+ export declare interface AIChatProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_4> {
306
+ /** The transcript, **oldest first**. Never reordered by the component. */
307
+ messages: readonly AIChatMessage[];
308
+ /** Renders the composer when given. Receives the trimmed prompt. */
309
+ onSend?: (text: string) => void | Promise<void>;
310
+ /** Abort the turn in flight. Shows the stop button while generating. */
311
+ onStop?: () => void;
312
+ /** Ask again for the newest assistant turn. */
313
+ onRegenerate?: (message: AIChatMessage) => void;
314
+ /** Re-submit an edited user turn. The app decides what to drop after it. */
315
+ onEditSubmit?: (message: AIChatMessage, text: string) => void | Promise<void>;
316
+ /** Rating on an assistant turn. */
317
+ onFeedback?: (message: AIChatMessage, vote: AIChatVote) => void;
318
+ /** Retry a turn that carries an `error`. */
319
+ onRetry?: (message: AIChatMessage) => void;
320
+ /**
321
+ * The request is out and nothing has arrived yet.
322
+ *
323
+ * Distinct from a turn with `streaming: true`: apps that only push a message
324
+ * once the first token lands need somewhere to say "we asked", and without it the
325
+ * screen is frozen for however long the model takes to start.
326
+ */
327
+ pending?: boolean;
328
+ /** Prompts offered on an empty transcript. Clicking one sends it. */
329
+ suggestions?: readonly string[];
330
+ /** Avatar for a turn — an `<Avatar>`, an `<Icon>`, a logo. */
331
+ renderAvatar?: (message: AIChatMessage) => ReactNode;
332
+ /** Render a body yourself — a tool-call card, a chart, a citation list. */
333
+ renderContent?: (message: AIChatMessage) => ReactNode;
334
+ /** Ratings to show as pressed, by message id. Omit to keep them local. */
335
+ votes?: Readonly<Record<string, AIChatVote>>;
336
+ /** Rendered above the transcript, inside the panel. */
337
+ header?: ReactNode;
338
+ /** Shown when there are no turns and no suggestions. */
339
+ emptyState?: ReactNode;
340
+ /** Show `"system"` turns. Default `false`. */
341
+ showSystem?: boolean;
342
+ /** Reasoning blocks start expanded. Default `false`. */
343
+ defaultReasoningOpen?: boolean;
344
+ /** Show line numbers in fenced code. Default `false`. */
345
+ showLineNumbers?: boolean;
346
+ /** Locale for labels. Default `"pt-BR"`. */
347
+ locale?: "pt-BR" | "en";
348
+ /** Placeholder for the composer. */
349
+ placeholder?: string;
350
+ /** Extra controls inside the composer, before the send button. */
351
+ composerActions?: ReactNode;
352
+ /** Under the composer field — token count, model name, a disclaimer. */
353
+ composerFooter?: ReactNode;
354
+ /** Disable the composer — no credits, conversation archived, offline. */
355
+ composerDisabled?: boolean;
356
+ /** Largest height the composer grows to, in lines. Default 8. */
357
+ maxRows?: number;
358
+ /**
359
+ * Called when `onSend` **or** `onEditSubmit` rejects. The draft stays in the field
360
+ * either way.
361
+ */
362
+ onSendError?: (error: unknown) => void;
363
+ }
364
+
365
+ /** Who produced a turn. */
366
+ export declare type AIChatRole = "user" | "assistant" | "system";
367
+
368
+ /** Labels the conversation needs, per locale. */
369
+ export declare interface AIChatStrings {
370
+ thread: string;
371
+ empty: string;
372
+ emptyHint: string;
373
+ placeholder: string;
374
+ send: string;
375
+ stop: string;
376
+ regenerate: string;
377
+ copy: string;
378
+ copied: string;
379
+ edit: string;
380
+ save: string;
381
+ cancel: string;
382
+ editing: string;
383
+ good: string;
384
+ bad: string;
385
+ reasoning: string;
386
+ thinking: string;
387
+ generating: string;
388
+ done: string;
389
+ stopped: string;
390
+ you: string;
391
+ assistant: string;
392
+ system: string;
393
+ retry: string;
394
+ jumpToLatest: string;
395
+ attachment: string;
396
+ turnActions: string;
397
+ }
398
+
399
+ /** Locale strings for the conversation. */
400
+ export declare function aiChatStrings(locale: "pt-BR" | "en"): AIChatStrings;
401
+
402
+ /**
403
+ * One turn of a conversation with a model.
404
+ *
405
+ * Exported for apps that build their own transcript layout (a split view, a diff of
406
+ * two answers) but still want the SDK's turn: Markdown body, reasoning block,
407
+ * attachments, streaming caret, error state and the action row.
408
+ *
409
+ * @example
410
+ * <AIChatTurn message={turn} canRegenerate onRegenerate={(m) => reask(m)} />
411
+ */
412
+ export declare function AIChatTurn({ message, locale, canRegenerate, onRegenerate, onFeedback, onEditSubmit, onEditError, onRetry, renderAvatar, renderContent, vote, defaultReasoningOpen, showLineNumbers, }: AIChatTurnProps): JSX.Element;
413
+
414
+ export declare interface AIChatTurnProps {
415
+ /** The turn to render. */
416
+ message: AIChatMessage;
417
+ /** Locale for the labels. Default `"pt-BR"`. */
418
+ locale?: "pt-BR" | "en";
419
+ /**
420
+ * Offer the regenerate control.
421
+ *
422
+ * Only the newest assistant turn should get it — re-asking an older one throws
423
+ * away every turn after it, which is a different operation and needs its own
424
+ * confirmation.
425
+ */
426
+ canRegenerate?: boolean;
427
+ onRegenerate?: (message: AIChatMessage) => void;
428
+ onFeedback?: (message: AIChatMessage, vote: AIChatVote) => void;
429
+ /** Enables the edit control on a user turn. Receives the edited prompt. */
430
+ onEditSubmit?: (message: AIChatMessage, text: string) => void | Promise<void>;
431
+ /**
432
+ * Called when `onEditSubmit` rejects. The editor stays open with the draft either
433
+ * way.
434
+ *
435
+ * Without it the rejection is swallowed after the draft is preserved: re-throwing
436
+ * out of a click handler surfaces as an unhandled promise rejection, which is
437
+ * console noise for the developer and nothing the user can act on.
438
+ */
439
+ onEditError?: (error: unknown) => void;
440
+ /** Enables the retry control on a turn that carries an `error`. */
441
+ onRetry?: (message: AIChatMessage) => void;
442
+ renderAvatar?: (message: AIChatMessage) => ReactNode;
443
+ /** Render the body yourself — a tool-call card, a chart, a citation list. */
444
+ renderContent?: (message: AIChatMessage) => ReactNode;
445
+ /**
446
+ * Rating to show as pressed.
447
+ *
448
+ * Pass it to keep votes in app state (persisted across a reload); leave it out
449
+ * and the pressed state is kept locally, which is enough for a fire-and-forget
450
+ * `onFeedback`.
451
+ */
452
+ vote?: AIChatVote;
453
+ /** Reasoning blocks start expanded. Default `false`. */
454
+ defaultReasoningOpen?: boolean;
455
+ /** Show line numbers in fenced code. Default `false`. */
456
+ showLineNumbers?: boolean;
457
+ }
458
+
459
+ /** Rating an app can collect on an assistant turn. */
460
+ export declare type AIChatVote = "up" | "down";
461
+
161
462
  /**
162
463
  * Inline alert / notice with tone (info/success/warning/danger) and appearance
163
464
  * (soft/solid/outline). Accepts optional `icon`, `title`, `description` and
@@ -913,6 +1214,30 @@ export declare const CACHE_TIME: {
913
1214
  readonly LONG: number;
914
1215
  };
915
1216
 
1217
+ /**
1218
+ * How large the assets a page precached actually are.
1219
+ *
1220
+ * Reads the `Content-Length` of a stored response instead of its body:
1221
+ * materializing a cached ONNX model or WASM binary to learn its length would
1222
+ * pull tens of megabytes into memory on every measurement.
1223
+ */
1224
+ /**
1225
+ * Byte size of a response sitting in a Cache Storage bucket.
1226
+ *
1227
+ * @param cacheName The cache bucket to look in.
1228
+ * @param url The request URL the response was stored under.
1229
+ * @returns The size in bytes, or `null` when Cache Storage is unavailable,
1230
+ * the entry is absent, or the stored response carries no usable
1231
+ * `Content-Length` (a chunked transfer, typically).
1232
+ *
1233
+ * @example
1234
+ * ```typescript
1235
+ * const bytes = await cachedResponseBytes("app-models", "/models/detect.onnx");
1236
+ * console.log(bytes === null ? "—" : formatBytes(bytes)); // "12.0 MB"
1237
+ * ```
1238
+ */
1239
+ export declare function cachedResponseBytes(cacheName: string, url: string): Promise<number | null>;
1240
+
916
1241
  /** A cache-name matcher: a prefix string, a `RegExp`, or a predicate. */
917
1242
  export declare type CacheFilter = string | RegExp | ((name: string) => boolean);
918
1243
 
@@ -1936,6 +2261,46 @@ export declare interface CreateI18nOptions {
1936
2261
  messages: Catalog;
1937
2262
  }
1938
2263
 
2264
+ /**
2265
+ * Timing and cost accounting for a pipeline that runs on the user's device.
2266
+ */
2267
+ /**
2268
+ * Create a profiler for one run of a pipeline.
2269
+ *
2270
+ * Wrap each step in {@link InferenceProfiler.stage}, fold in durations you
2271
+ * already have (an SDK `speed` breakdown, say) with
2272
+ * {@link InferenceProfiler.mark}, then call `report()` once the run finishes.
2273
+ *
2274
+ * Stages are timed independently rather than as a tiling of the run, so
2275
+ * concurrent work is charged its real wall-clock span to each stage and the
2276
+ * timings can sum to more than `totalMs`. Surface that to users when you
2277
+ * render the breakdown — a bar chart implying a partition of the total would
2278
+ * be wrong for a pipeline that overlaps stages.
2279
+ *
2280
+ * @returns A profiler bound to the moment it was created.
2281
+ *
2282
+ * @example
2283
+ * ```typescript
2284
+ * import { createInferenceProfiler } from "tempest-react-sdk";
2285
+ * import { Detector } from "tempest-react-sdk/vision";
2286
+ *
2287
+ * const profiler = createInferenceProfiler();
2288
+ * const detector = await profiler.stage("load-model", () =>
2289
+ * Detector.create("/models/detect.onnx"),
2290
+ * );
2291
+ * const results = await profiler.stage("detect", () => detector.predict(blob));
2292
+ * profiler.mark("forward-pass", results[0].speed.inference);
2293
+ *
2294
+ * const report = await profiler.report({
2295
+ * models: [
2296
+ * { name: "detector", cacheName: "app-models", url: "/models/detect.onnx" },
2297
+ * ],
2298
+ * });
2299
+ * console.log(report.timings, report.totalMs, report.device, report.models);
2300
+ * ```
2301
+ */
2302
+ export declare function createInferenceProfiler(): InferenceProfiler;
2303
+
1939
2304
  /**
1940
2305
  * Trivial in-memory adapter. Suitable for tests, local development, or as a
1941
2306
  * fallback wrapping the real provider while it loads.
@@ -2456,10 +2821,36 @@ export declare interface CreateWebSocketOptions<T> {
2456
2821
  /**
2457
2822
  * Ping interval (ms). When set, the client sends `pingPayload` periodically
2458
2823
  * to keep the socket alive. Default: 0 (disabled).
2824
+ *
2825
+ * Leave it off against a `tempest-fastapi-sdk` server: that server pings on
2826
+ * its own and answers a client-sent `{"type":"ping"}` with nothing, while a
2827
+ * strict handler rejects the unknown frame. What it needs from the client
2828
+ * is the `pong` reply, which `respondToPing` sends for you.
2459
2829
  */
2460
2830
  pingInterval?: number;
2461
2831
  /** Payload sent on each ping. Default: `JSON.stringify({ type: "ping" })`. */
2462
2832
  pingPayload?: string | Blob | BufferSource;
2833
+ /**
2834
+ * Reply to a server `{"type":"ping"}` with `pongPayload`. Default: true.
2835
+ *
2836
+ * `tempest-fastapi-sdk` closes a socket with code `4408` when no `pong`
2837
+ * arrives within `WS_HEARTBEAT_TIMEOUT_SECONDS`, so a client that stays
2838
+ * silent is dropped once per timeout. The ping is still forwarded to
2839
+ * `onMessage` — the reply is sent before your handler runs.
2840
+ */
2841
+ respondToPing?: boolean;
2842
+ /** Payload sent in reply to a server ping. Default: `JSON.stringify({ type: "pong" })`. */
2843
+ pongPayload?: string | Blob | BufferSource;
2844
+ /**
2845
+ * Buffer payloads sent while the socket is not open and flush them on the
2846
+ * next `open`. Default: false — `send()` returns false and drops.
2847
+ *
2848
+ * Without it, an action fired during reconnect backoff vanishes and the UI
2849
+ * cannot tell "never sent" from "sent and ignored".
2850
+ */
2851
+ queueWhileClosed?: boolean;
2852
+ /** Cap on buffered payloads when `queueWhileClosed` is on. Default: 100. */
2853
+ maxQueuedMessages?: number;
2463
2854
  /** Parse incoming frames. Default: JSON with raw-string fallback. */
2464
2855
  parser?: (raw: string) => T;
2465
2856
  onOpen?: (event: Event) => void;
@@ -2855,6 +3246,31 @@ export declare interface DescriptionListProps extends HTMLAttributes<HTMLDListEl
2855
3246
  items: DescriptionListItem[];
2856
3247
  }
2857
3248
 
3249
+ /**
3250
+ * Shapes describing what an on-device inference run cost.
3251
+ *
3252
+ * The browser exposes no energy counter and no FLOP counter, so "cost" here
3253
+ * is assembled from what a page can actually observe: how long each stage
3254
+ * took, how much parallelism and memory the device reports, and how large the
3255
+ * cached model weights are. Anything the platform does not expose stays
3256
+ * `null` — a UI can then render "—" instead of a fabricated number.
3257
+ */
3258
+ /**
3259
+ * Device capabilities as reported by the browser.
3260
+ *
3261
+ * Every field is best-effort. `deviceMemoryGb` and `jsHeapUsedMb` come from
3262
+ * Chromium-only APIs (`navigator.deviceMemory`, `performance.memory`) and are
3263
+ * `null` everywhere else, including Firefox and Safari.
3264
+ */
3265
+ export declare interface DeviceProfile {
3266
+ /** Logical cores available to workers, or `null` when unreported. */
3267
+ hardwareConcurrency: number | null;
3268
+ /** Approximate device RAM in GiB (coarse, Chromium-only), or `null`. */
3269
+ deviceMemoryGb: number | null;
3270
+ /** Used JS heap in MiB (Chromium-only), or `null`. */
3271
+ jsHeapUsedMb: number | null;
3272
+ }
3273
+
2858
3274
  export declare interface DisclosureHandlers {
2859
3275
  open: () => void;
2860
3276
  close: () => void;
@@ -3316,7 +3732,7 @@ export declare interface Filter {
3316
3732
  */
3317
3733
  export declare function FilterBar({ fields, value, onChange, locale, actions, className, ...rest }: FilterBarProps): JSX.Element;
3318
3734
 
3319
- export declare interface FilterBarProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_7> {
3735
+ export declare interface FilterBarProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_9> {
3320
3736
  /** Fields the user may filter by. */
3321
3737
  fields: readonly FilterField[];
3322
3738
  /** Applied filters. Controlled. */
@@ -3574,6 +3990,31 @@ export declare function formatDate(value: string | Date): string;
3574
3990
  */
3575
3991
  export declare function formatDateTime(value: string | Date): string;
3576
3992
 
3993
+ /**
3994
+ * Rendering helpers for the numbers a profiler produces.
3995
+ */
3996
+ /**
3997
+ * Format a millisecond duration for display.
3998
+ *
3999
+ * Sub-second values keep millisecond resolution — the interesting range for a
4000
+ * single forward pass — and anything longer switches to seconds so a cold
4001
+ * start that pays a model download does not read as a five-digit number.
4002
+ * Durations under `1 ms` render as `"<1 ms"` rather than `"0 ms"`, which
4003
+ * would read as "not measured".
4004
+ *
4005
+ * @param value Duration in milliseconds.
4006
+ * @returns The formatted string, or `"—"` for a non-finite or negative input.
4007
+ *
4008
+ * @example
4009
+ * ```typescript
4010
+ * formatDurationMs(0.04); // "<1 ms"
4011
+ * formatDurationMs(142.6); // "143 ms"
4012
+ * formatDurationMs(4321); // "4.32 s"
4013
+ * formatDurationMs(NaN); // "—"
4014
+ * ```
4015
+ */
4016
+ export declare function formatDurationMs(value: number): string;
4017
+
3577
4018
  /**
3578
4019
  * Format a fraction (0-1) as a percentage with one decimal.
3579
4020
  *
@@ -4151,6 +4592,70 @@ export declare interface ImageProps extends Omit<ImgHTMLAttributes<HTMLImageElem
4151
4592
  lazy?: boolean;
4152
4593
  }
4153
4594
 
4595
+ /**
4596
+ * Records how long each stage of a pipeline took.
4597
+ *
4598
+ * Stages are measured **independently**, not as a tiling of the whole run:
4599
+ * two stages started concurrently are each charged their full wall-clock
4600
+ * span, so the sum can exceed {@link InferenceReport.totalMs}. That is the
4601
+ * honest reading for a pipeline that decodes an image while the model
4602
+ * sessions are still loading.
4603
+ */
4604
+ export declare interface InferenceProfiler {
4605
+ /**
4606
+ * Run an async stage and record its duration.
4607
+ *
4608
+ * @param name Stage label used as the key in the report.
4609
+ * @param run The work to time.
4610
+ * @returns Whatever `run` resolved to.
4611
+ */
4612
+ stage<T>(name: string, run: () => Promise<T>): Promise<T>;
4613
+ /**
4614
+ * Run a synchronous stage and record its duration.
4615
+ *
4616
+ * @param name Stage label used as the key in the report.
4617
+ * @param run The work to time.
4618
+ * @returns Whatever `run` returned.
4619
+ */
4620
+ stageSync<T>(name: string, run: () => T): T;
4621
+ /**
4622
+ * Record a duration measured elsewhere — a `speed` breakdown returned by
4623
+ * `tempest-react-sdk/vision`, for instance.
4624
+ *
4625
+ * Repeated names accumulate, so folding two passes of the same kind into
4626
+ * one row is a matter of calling `mark` twice.
4627
+ *
4628
+ * @param name Stage label used as the key in the report.
4629
+ * @param durationMs How long it took, in milliseconds.
4630
+ */
4631
+ mark(name: string, durationMs: number): void;
4632
+ /**
4633
+ * Assemble the report for everything recorded so far.
4634
+ *
4635
+ * @param options Which models to size up in Cache Storage.
4636
+ * @returns The finished report.
4637
+ */
4638
+ report(options?: InferenceReportOptions): Promise<InferenceReport>;
4639
+ }
4640
+
4641
+ /** What one profiled run cost. */
4642
+ export declare interface InferenceReport {
4643
+ /** Duration in milliseconds per stage name, in the order first recorded. */
4644
+ timings: Readonly<Record<string, number>>;
4645
+ /** Milliseconds from profiler creation to the `report()` call. */
4646
+ totalMs: number;
4647
+ device: DeviceProfile;
4648
+ models: readonly ProfiledModelSize[];
4649
+ /** Epoch millis at which the report was assembled. */
4650
+ measuredAt: number;
4651
+ }
4652
+
4653
+ /** Options for {@link InferenceProfiler.report}. */
4654
+ export declare interface InferenceReportOptions {
4655
+ /** Models to measure in Cache Storage. Omit to report none. */
4656
+ models?: readonly ProfiledModel[];
4657
+ }
4658
+
4154
4659
  export declare interface InMemoryFlagsOptions {
4155
4660
  initial?: Record<string, FlagValue>;
4156
4661
  }
@@ -4459,6 +4964,9 @@ export declare function isDefined<T>(value: T | null | undefined): value is T;
4459
4964
  */
4460
4965
  export declare function isEmpty(value: unknown): boolean;
4461
4966
 
4967
+ /** Whether any turn in the thread is still streaming. */
4968
+ export declare function isGenerating(messages: readonly AIChatMessage[]): boolean;
4969
+
4462
4970
  /**
4463
4971
  * Detects iOS / iPadOS Safari, including modern iPads that report `MacIntel`
4464
4972
  * plus multi-touch instead of an `iPad` user agent.
@@ -4695,6 +5203,15 @@ export declare interface LabelProps extends LabelHTMLAttributes<HTMLLabelElement
4695
5203
  required?: boolean;
4696
5204
  }
4697
5205
 
5206
+ /**
5207
+ * Id of the newest assistant turn, or `null` when there is none.
5208
+ *
5209
+ * Only that turn gets the regenerate control: re-asking an older one would throw
5210
+ * away every turn after it, which is a different operation ("branch here") and
5211
+ * needs its own confirmation.
5212
+ */
5213
+ export declare function lastAssistantId(messages: readonly AIChatMessage[]): string | null;
5214
+
4698
5215
  /**
4699
5216
  * Conflict-resolution helpers for the `applyRemote` callback of
4700
5217
  * {@link createOfflineSync}. Each takes the current local record (or
@@ -5024,7 +5541,7 @@ export declare type MarkdownInline = {
5024
5541
  type: "break";
5025
5542
  };
5026
5543
 
5027
- export declare interface MarkdownProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_6> {
5544
+ export declare interface MarkdownProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_8> {
5028
5545
  /** The Markdown source. */
5029
5546
  source: string;
5030
5547
  /**
@@ -5062,7 +5579,7 @@ export declare interface MarkdownProps extends Omit<HTMLAttributes<HTMLDivElemen
5062
5579
  */
5063
5580
  export declare function Masonry<T>({ items, children, itemKey, columns, gap, className, style, ...rest }: MasonryProps<T>): JSX.Element;
5064
5581
 
5065
- export declare interface MasonryProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_5> {
5582
+ export declare interface MasonryProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_7> {
5066
5583
  /** What to lay out. */
5067
5584
  items: readonly T[];
5068
5585
  /** Render one card. */
@@ -6021,16 +6538,22 @@ declare type OverriddenDomProps_2 = "children" | "onSubmit";
6021
6538
  declare type OverriddenDomProps_3 = "onSubmit" | "value" | "defaultValue" | "rows";
6022
6539
 
6023
6540
  /** DOM attributes this component redefines. */
6024
- declare type OverriddenDomProps_4 = "children" | "onChange" | "defaultValue";
6541
+ declare type OverriddenDomProps_4 = "children" | "onSubmit";
6542
+
6543
+ /** DOM attributes the composer redefines. */
6544
+ declare type OverriddenDomProps_5 = "onSubmit" | "value" | "defaultValue" | "rows";
6545
+
6546
+ /** DOM attributes this component redefines. */
6547
+ declare type OverriddenDomProps_6 = "children" | "onChange" | "defaultValue";
6025
6548
 
6026
6549
  /** DOM attributes this component redefines. */
6027
- declare type OverriddenDomProps_5 = "children";
6550
+ declare type OverriddenDomProps_7 = "children";
6028
6551
 
6029
6552
  /** DOM attributes this component redefines. */
6030
- declare type OverriddenDomProps_6 = "children";
6553
+ declare type OverriddenDomProps_8 = "children";
6031
6554
 
6032
6555
  /** DOM attributes this component redefines. */
6033
- declare type OverriddenDomProps_7 = "children" | "onChange";
6556
+ declare type OverriddenDomProps_9 = "children" | "onChange";
6034
6557
 
6035
6558
  /**
6036
6559
  * Page wrapper with header + (optional) toolbar + content + footer. Pairs
@@ -6388,6 +6911,23 @@ export declare interface PostHogLike {
6388
6911
  reset?: () => void;
6389
6912
  }
6390
6913
 
6914
+ /** A model whose cached size should appear in the report. */
6915
+ export declare interface ProfiledModel {
6916
+ /** Label for the report row, e.g. `"detector"`. */
6917
+ name: string;
6918
+ /** Cache Storage bucket holding the response, e.g. `"app-models"`. */
6919
+ cacheName: string;
6920
+ /** Request URL the model was cached under. */
6921
+ url: string;
6922
+ }
6923
+
6924
+ /** A model's size as found in the cache. */
6925
+ export declare interface ProfiledModelSize {
6926
+ name: string;
6927
+ /** Size in bytes, or `null` when uncached or the size is unreported. */
6928
+ bytes: number | null;
6929
+ }
6930
+
6391
6931
  /**
6392
6932
  * Linear progress bar with determinate / indeterminate modes.
6393
6933
  *
@@ -6705,6 +7245,22 @@ export declare interface RatingStarsProps {
6705
7245
  */
6706
7246
  export declare function readableForeground(background: string, light?: string, dark?: string): string;
6707
7247
 
7248
+ /**
7249
+ * Sample the device capabilities the browser reports.
7250
+ *
7251
+ * Safe to call during SSR: without a `navigator` every field is `null`.
7252
+ *
7253
+ * @returns The profile, with `null` for anything this platform withholds.
7254
+ *
7255
+ * @example
7256
+ * ```typescript
7257
+ * const device = readDeviceProfile();
7258
+ * console.log(device.hardwareConcurrency); // 8
7259
+ * console.log(device.deviceMemoryGb); // 8 on Chromium, null on Safari
7260
+ * ```
7261
+ */
7262
+ export declare function readDeviceProfile(): DeviceProfile;
7263
+
6708
7264
  /**
6709
7265
  * Read a token's computed value from an element (default: `<html>`).
6710
7266
  *
@@ -7026,6 +7582,9 @@ export declare interface RoleAccessControlConfig {
7026
7582
  role?: string | string[];
7027
7583
  }
7028
7584
 
7585
+ /** Role label used in the turn header and by screen readers. */
7586
+ export declare function roleLabel(role: AIChatRole, strings: AIChatStrings): string;
7587
+
7029
7588
  export { Route }
7030
7589
 
7031
7590
  /**
@@ -8188,6 +8747,21 @@ export declare type TagSize = "sm" | "md" | "lg";
8188
8747
 
8189
8748
  export declare type TagVariant = "neutral" | "primary" | "success" | "warning" | "danger" | "info";
8190
8749
 
8750
+ /**
8751
+ * A value that changes whenever the tail of the thread grows.
8752
+ *
8753
+ * The scroll effect cannot depend on the `messages` array alone. Streaming appends
8754
+ * to the **last** turn, and an app that mutates that object in place — or that
8755
+ * re-renders from a store holding the same array identity — would keep the same
8756
+ * dependency while the text grows, so the view would stop following the answer.
8757
+ * Length of the array, identity of the tail and length of its text together cover
8758
+ * both shapes.
8759
+ *
8760
+ * @param messages - The thread, oldest first.
8761
+ * @returns An opaque signature; compare with `===`.
8762
+ */
8763
+ export declare function tailSignature(messages: readonly AIChatMessage[]): string;
8764
+
8191
8765
  export declare interface TelemetryAdapter {
8192
8766
  /** Optional. Called when the provider mounts. */
8193
8767
  init?: () => void | Promise<void>;
@@ -8872,7 +9446,7 @@ export declare interface TransferItem {
8872
9446
  data?: Record<string, unknown>;
8873
9447
  }
8874
9448
 
8875
- export declare interface TransferProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_4> {
9449
+ export declare interface TransferProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_6> {
8876
9450
  /** The whole catalogue. Both panes are derived from it. */
8877
9451
  items: readonly TransferItem[];
8878
9452
  /** Ids on the target side. Controlled. */
@@ -9021,6 +9595,15 @@ export declare interface TruncateTextProps extends HTMLAttributes<HTMLDivElement
9021
9595
  children: ReactNode;
9022
9596
  }
9023
9597
 
9598
+ /**
9599
+ * Clock label for a turn — the time, not a relative phrase.
9600
+ *
9601
+ * A transcript is read top to bottom in one sitting, so "há 2 minutos" on every turn
9602
+ * is noise that also has to be re-rendered on a timer. The wall clock is stable and
9603
+ * enough to answer the only question anyone asks of it ("was this today?").
9604
+ */
9605
+ export declare function turnTime(timestamp: number, locale?: "pt-BR" | "en"): string;
9606
+
9024
9607
  /** Sentence for the typing indicator, or `null` when nobody is typing. */
9025
9608
  export declare function typingLabel(names: readonly string[], locale?: "pt-BR" | "en"): string | null;
9026
9609
 
@@ -10782,6 +11365,17 @@ export { useWatch }
10782
11365
  /**
10783
11366
  * React hook around {@link createWebSocket}. Manages the connection lifecycle
10784
11367
  * for the host component and tears it down on unmount.
11368
+ *
11369
+ * Every callback is read through a ref, so `onOpen` / `onMessage` / `onClose` /
11370
+ * `onError` always run the latest closure — an inline arrow function is fine
11371
+ * and never reopens the socket. Connection-shaping options (`protocols`,
11372
+ * `maxRetries`, `initialBackoff`, `maxBackoff`, `pingInterval`,
11373
+ * `queueWhileClosed`) are baked into the connection, so changing one reopens
11374
+ * it with the new value rather than being silently ignored.
11375
+ *
11376
+ * @param url - Full ws:// or wss:// URL.
11377
+ * @param options - Connection configuration and callbacks.
11378
+ * @returns Status, last frame, and the `send` / `reconnect` controls.
10785
11379
  */
10786
11380
  export declare function useWebSocket<T = unknown>(url: string, options?: UseWebSocketOptions<T>): UseWebSocketResult<T>;
10787
11381
 
@@ -10792,7 +11386,15 @@ export declare interface UseWebSocketOptions<T> extends Omit<CreateWebSocketOpti
10792
11386
 
10793
11387
  export declare interface UseWebSocketResult<T> {
10794
11388
  status: WebSocketStatus;
10795
- /** Last decoded frame received. */
11389
+ /**
11390
+ * Last decoded frame received.
11391
+ *
11392
+ * A snapshot, not a stream: two frames arriving in the same tick collapse
11393
+ * into a single render and only the later one is ever visible. One server
11394
+ * action often emits several frames in a row, so anything that must see
11395
+ * every message has to use `onMessage`, which fires once per frame. Read
11396
+ * `lastMessage` for "what is the current state" rendering only.
11397
+ */
10796
11398
  lastMessage: WebSocketMessage<T> | null;
10797
11399
  /** Send a payload through the active connection. Returns false when not open. */
10798
11400
  send: (payload: string | Blob | BufferSource) => boolean;
@@ -10995,6 +11597,21 @@ export declare interface VirtualTableSort<T> {
10995
11597
 
10996
11598
  export declare type VirtualTableSortDirection = "asc" | "desc";
10997
11599
 
11600
+ /**
11601
+ * Turns to render, in order.
11602
+ *
11603
+ * System turns are dropped unless asked for: a system prompt is configuration, and
11604
+ * an app that shows it by default leaks its own instructions into the transcript.
11605
+ *
11606
+ * @param params.messages - The thread, oldest first. Never reordered.
11607
+ * @param params.showSystem - Keep `"system"` turns. Default `false`.
11608
+ * @returns The visible turns, in the given order.
11609
+ */
11610
+ export declare function visibleTurns({ messages, showSystem, }: {
11611
+ messages: readonly AIChatMessage[];
11612
+ showSystem?: boolean;
11613
+ }): AIChatMessage[];
11614
+
10998
11615
  /**
10999
11616
  * Render content that is hidden visually but remains available to screen
11000
11617
  * readers — the standard "sr-only" pattern. Useful for accessible labels on