@opengeni/react 5.0.5-canary.3 → 5.1.0-canary.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.
@@ -2,8 +2,11 @@ import { type GenieLoadingOptions } from "../timeline/genie-loading.js";
2
2
  import type { DraftTimelineAnnotation, SessionEvent, SessionStatus } from "@opengeni/sdk";
3
3
  import { type ReactNode } from "react";
4
4
  import { type OlderHistoryLoader } from "../older-history.js";
5
+ import { type UserMessageDisclosureLabels } from "./user-message-body.js";
5
6
  import { type AgentMessageItem, type AuthNeededItem, type TimelineGroup, type TimelineItem, type RetainedArtifactLoader, type RetainedScreenshotLoader, type VideoArtifactPlaybackLoader, type ToolRegistry, type TurnSummaryOptions, type UserMessageItem } from "../timeline/index.js";
6
7
  export type MessageTimelineProps = {
8
+ /** Localized user-message disclosure actions, including custom UserMessageBody renderers. */
9
+ userMessageDisclosureLabels?: UserMessageDisclosureLabels | undefined;
7
10
  /** Raw session events (projected internally) … */
8
11
  events?: SessionEvent[] | undefined;
9
12
  /** … or pre-projected items (e.g. from `useSessionEvents().timeline`). */
@@ -113,7 +116,7 @@ export type MessageTimelineProps = {
113
116
  * cards, goal markers, and status transitions. Owns stick-to-bottom scrolling
114
117
  * with a "jump to latest" affordance when the reader scrolls back.
115
118
  */
116
- export declare function MessageTimeline({ events, items, status: _status, renderMessageActions, renderMessageText, onOpenSession, onMemoryClick, onReconnect, renderAuthNeeded, shouldRenderAuthNeeded, resolveProviderLogo, toolRegistry, loadRetainedScreenshot, loadRetainedArtifact, loadVideoArtifactPlayback, computeLabel, genieLoading, turnSummary, autoFollow, onAnnotate, draftAnnotations, onDraftAnnotationSelect, hasOlder, loadingOlder, onLoadOlder, onJumpToStart, loadingOldest, hasNewer, loadingNewer, onLoadNewer, onJumpToLatest, trailingState, emptyState, className, }: MessageTimelineProps): import("react").JSX.Element;
119
+ export declare function MessageTimeline({ userMessageDisclosureLabels, events, items, status: _status, renderMessageActions, renderMessageText, onOpenSession, onMemoryClick, onReconnect, renderAuthNeeded, shouldRenderAuthNeeded, resolveProviderLogo, toolRegistry, loadRetainedScreenshot, loadRetainedArtifact, loadVideoArtifactPlayback, computeLabel, genieLoading, turnSummary, autoFollow, onAnnotate, draftAnnotations, onDraftAnnotationSelect, hasOlder, loadingOlder, onLoadOlder, onJumpToStart, loadingOldest, hasNewer, loadingNewer, onLoadNewer, onJumpToLatest, trailingState, emptyState, className, }: MessageTimelineProps): import("react").JSX.Element;
117
120
  /**
118
121
  * Settled turns lift the final agent answer out as a sibling group. Include it
119
122
  * in "Copy turn" when present so the chip copies the full assistant reply.
@@ -2,8 +2,11 @@ import { type CSSProperties } from "react";
2
2
  import { type ClientOverride } from "../session-context.js";
3
3
  import { type ChatComposerProps } from "./chat-composer.js";
4
4
  import { type HumanInputSurfaceProps } from "./human-input-surface.js";
5
+ import type { UserMessageDisclosureLabels } from "./user-message-body.js";
5
6
  export type SessionConversationProps = ClientOverride & {
6
7
  sessionId: string;
8
+ /** Localized actions for already-sent user-message disclosure. */
9
+ userMessageDisclosureLabels?: UserMessageDisclosureLabels | undefined;
7
10
  loadSkillReview?: HumanInputSurfaceProps["loadSkillReview"];
8
11
  className?: string;
9
12
  /** Defaults to filling the host. The host owns available height. */
@@ -1,6 +1,13 @@
1
1
  import { type ReactNode } from "react";
2
2
  type RestoreDisclosureAnchor = (() => void) | null;
3
+ export type UserMessageDisclosureLabels = {
4
+ /** Collapsed disclosure action. Defaults to "Show more". */
5
+ showMore?: string | undefined;
6
+ /** Expanded disclosure action. Defaults to "Show less". */
7
+ showLess?: string | undefined;
8
+ };
3
9
  export type UserMessageDisclosureContextValue = {
10
+ labels?: UserMessageDisclosureLabels | undefined;
4
11
  expandedByMessageId: Map<string, boolean>;
5
12
  beginChange: (messageBody: HTMLElement, disclosureControl: HTMLElement) => RestoreDisclosureAnchor;
6
13
  };
@@ -21,6 +28,8 @@ export type UserMessageBodyProps = {
21
28
  text: string;
22
29
  children: ReactNode;
23
30
  className?: string | undefined;
31
+ /** Per-field overrides for timeline labels, then the English defaults. */
32
+ disclosureLabels?: UserMessageDisclosureLabels | undefined;
24
33
  };
25
34
  /**
26
35
  * Lossless disclosure boundary for already-sent user-message text.
@@ -32,5 +41,5 @@ export type UserMessageBodyProps = {
32
41
  * remembers expansion per durable message id and preserves the reader's scroll
33
42
  * anchor when height changes.
34
43
  */
35
- export declare function UserMessageBody({ messageId, text, children, className }: UserMessageBodyProps): import("react").JSX.Element;
44
+ export declare function UserMessageBody({ messageId, text, children, className, disclosureLabels, }: UserMessageBodyProps): import("react").JSX.Element;
36
45
  export {};
package/dist/composer.js CHANGED
@@ -40,7 +40,7 @@ import {
40
40
  useChatComposer,
41
41
  useChatComposerController,
42
42
  useVoiceInput
43
- } from "./chunk-V3WX3TQG.js";
43
+ } from "./chunk-45XEUVTK.js";
44
44
  import "./chunk-HQV2I5HV.js";
45
45
  import {
46
46
  BillingClassMark,
@@ -51,7 +51,7 @@ import {
51
51
  defaultModelPolicyPickerMessages
52
52
  } from "./chunk-R4KRSFGA.js";
53
53
  import "./chunk-VZTQ73XT.js";
54
- import "./chunk-6J56T3MG.js";
54
+ import "./chunk-NYESIADM.js";
55
55
  import "./chunk-PLYRL5ER.js";
56
56
  import "./chunk-KZ73RL76.js";
57
57
  import "./chunk-NEXLLTP4.js";
package/dist/index.d.ts CHANGED
@@ -131,7 +131,7 @@ export { GeneratedVideoPlayer } from "./components/generated-video-player.js";
131
131
  export type { GeneratedVideoPlayerProps } from "./components/generated-video-player.js";
132
132
  export type { MessageTimelineProps } from "./components/message-timeline.js";
133
133
  export { UserMessageBody, userMessageLikelyNeedsDisclosure } from "./components/user-message-body.js";
134
- export type { UserMessageBodyProps } from "./components/user-message-body.js";
134
+ export type { UserMessageBodyProps, UserMessageDisclosureLabels, } from "./components/user-message-body.js";
135
135
  export { Markdown, sandboxFileLocationFromHref, sandboxFilePathFromHref, } from "./components/markdown.js";
136
136
  export type { MarkdownProps, SandboxFileLocation } from "./components/markdown.js";
137
137
  export { CopyButton, CopyHoverFrame } from "./components/copy-button.js";
package/dist/index.js CHANGED
@@ -104,7 +104,7 @@ import {
104
104
  useWorkspaceModelCatalog,
105
105
  userMessageLikelyNeedsDisclosure,
106
106
  v4aToGitFileDiff
107
- } from "./chunk-7S2KWUJD.js";
107
+ } from "./chunk-WS6D5BHH.js";
108
108
  import "./chunk-YBM6CQRU.js";
109
109
  import "./chunk-5M6VTFJ5.js";
110
110
  import "./chunk-ZYRGEKWS.js";
@@ -159,7 +159,7 @@ import {
159
159
  useSlashCommands,
160
160
  useTranscription,
161
161
  useVoiceInput
162
- } from "./chunk-V3WX3TQG.js";
162
+ } from "./chunk-45XEUVTK.js";
163
163
  import {
164
164
  Tooltip,
165
165
  TooltipContent,
@@ -220,7 +220,7 @@ import {
220
220
  shouldSteerOnKey,
221
221
  shouldSubmitOnKey,
222
222
  useComposer
223
- } from "./chunk-6J56T3MG.js";
223
+ } from "./chunk-NYESIADM.js";
224
224
  import {
225
225
  COMPOSER_PAYMENT_REQUIRED_MESSAGE,
226
226
  CREDIT_EXHAUSTION_MESSAGE,
@@ -9,7 +9,7 @@ export type { MessageTimelineProps } from "./components/message-timeline.js";
9
9
  export { createOlderHistoryLoadReceipt } from "./older-history.js";
10
10
  export type { OlderHistoryLoader, OlderHistoryLoadReceipt } from "./older-history.js";
11
11
  export { UserMessageBody, userMessageLikelyNeedsDisclosure } from "./components/user-message-body.js";
12
- export type { UserMessageBodyProps } from "./components/user-message-body.js";
12
+ export type { UserMessageBodyProps, UserMessageDisclosureLabels, } from "./components/user-message-body.js";
13
13
  export { BUILT_IN_TURN_SUMMARY_FACET_IDS } from "./timeline/turn-summary.js";
14
14
  export type { BuiltInTurnSummaryFacetId, TurnSummaryContext, TurnSummaryFacet, TurnSummaryFacetConfiguration, TurnSummaryFacetResult, TurnSummaryOptions, } from "./timeline/turn-summary.js";
15
15
  export { QueueSurface } from "./components/queue-surface.js";
@@ -16,7 +16,7 @@ import {
16
16
  setStartupDetails,
17
17
  useStartupDetails,
18
18
  userMessageLikelyNeedsDisclosure
19
- } from "./chunk-7S2KWUJD.js";
19
+ } from "./chunk-WS6D5BHH.js";
20
20
  import "./chunk-YBM6CQRU.js";
21
21
  import "./chunk-5M6VTFJ5.js";
22
22
  import "./chunk-ZYRGEKWS.js";
@@ -24,14 +24,14 @@ import "./chunk-NOSYBS2D.js";
24
24
  import "./chunk-PAJU5KKL.js";
25
25
  import "./chunk-M2HNWZYR.js";
26
26
  import "./chunk-JVYQRRC4.js";
27
- import "./chunk-V3WX3TQG.js";
27
+ import "./chunk-45XEUVTK.js";
28
28
  import "./chunk-HQV2I5HV.js";
29
29
  import "./chunk-R4KRSFGA.js";
30
30
  import "./chunk-VZTQ73XT.js";
31
31
  import {
32
32
  createOlderHistoryLoadReceipt
33
33
  } from "./chunk-HUMIRRYI.js";
34
- import "./chunk-6J56T3MG.js";
34
+ import "./chunk-NYESIADM.js";
35
35
  import "./chunk-PLYRL5ER.js";
36
36
  import "./chunk-KZ73RL76.js";
37
37
  import "./chunk-NEXLLTP4.js";
package/dist/session.js CHANGED
@@ -35,7 +35,7 @@ import {
35
35
  shouldSteerOnKey,
36
36
  shouldSubmitOnKey,
37
37
  useComposer
38
- } from "./chunk-6J56T3MG.js";
38
+ } from "./chunk-NYESIADM.js";
39
39
  import "./chunk-PLYRL5ER.js";
40
40
  import "./chunk-KZ73RL76.js";
41
41
  import "./chunk-NEXLLTP4.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/react",
3
- "version": "5.0.5-canary.3",
3
+ "version": "5.1.0-canary.0",
4
4
  "description": "React hooks and styled components for OpenGeni: live session streaming, chat composer, message timeline, session status, and fleet views — token-themed (CSS variables), dark-first, built on Tailwind v4 + Radix + Motion.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -133,8 +133,8 @@
133
133
  "@dnd-kit/utilities": "3.2.2",
134
134
  "@fontsource-variable/noto-sans-arabic": "5.2.10",
135
135
  "@fontsource-variable/noto-sans-jp": "5.2.10",
136
- "@opengeni/connect": "^0.2.0-canary.5",
137
- "@opengeni/sdk": "^5.0.5-canary.3",
136
+ "@opengeni/connect": "^0.2.0-canary.6",
137
+ "@opengeni/sdk": "^5.1.0-canary.0",
138
138
  "clsx": "^2.1.1",
139
139
  "dequal": "2.0.3",
140
140
  "lucide-react": "^1.8.0",
@@ -62,6 +62,7 @@ import {
62
62
  UserMessageBody,
63
63
  UserMessageDisclosureProvider,
64
64
  type UserMessageDisclosureContextValue,
65
+ type UserMessageDisclosureLabels,
65
66
  } from "./user-message-body";
66
67
  import {
67
68
  createTipFollowState,
@@ -128,6 +129,8 @@ const TimelineAnnotationSelection = lazy(() => import("./timeline-annotation-sel
128
129
  const TimelineAnnotationMarkers = lazy(() => import("./timeline-annotation-markers"));
129
130
 
130
131
  export type MessageTimelineProps = {
132
+ /** Localized user-message disclosure actions, including custom UserMessageBody renderers. */
133
+ userMessageDisclosureLabels?: UserMessageDisclosureLabels | undefined;
131
134
  /** Raw session events (projected internally) … */
132
135
  events?: SessionEvent[] | undefined;
133
136
  /** … or pre-projected items (e.g. from `useSessionEvents().timeline`). */
@@ -404,6 +407,7 @@ function cssEscapeAttribute(value: string): string {
404
407
  * with a "jump to latest" affordance when the reader scrolls back.
405
408
  */
406
409
  export function MessageTimeline({
410
+ userMessageDisclosureLabels,
407
411
  events,
408
412
  items,
409
413
  status: _status,
@@ -919,8 +923,16 @@ export function MessageTimeline({
919
923
  () => ({
920
924
  expandedByMessageId: userMessageDisclosureMemoryRef.current,
921
925
  beginChange: beginUserMessageDisclosureChange,
926
+ labels: {
927
+ showMore: userMessageDisclosureLabels?.showMore,
928
+ showLess: userMessageDisclosureLabels?.showLess,
929
+ },
922
930
  }),
923
- [beginUserMessageDisclosureChange],
931
+ [
932
+ beginUserMessageDisclosureChange,
933
+ userMessageDisclosureLabels?.showMore,
934
+ userMessageDisclosureLabels?.showLess,
935
+ ],
924
936
  );
925
937
  const timelineGroupEntryContext = useMemo<TimelineGroupEntryContext>(
926
938
  () => ({
@@ -11,11 +11,14 @@ import { ChatComposer, type ChatComposerProps } from "./chat-composer";
11
11
  import { QueueSurface } from "./queue-surface";
12
12
  import { HumanInputSurface, type HumanInputSurfaceProps } from "./human-input-surface";
13
13
  import { MessageTimeline } from "./message-timeline";
14
+ import type { UserMessageDisclosureLabels } from "./user-message-body";
14
15
  import { conversationTimeline } from "../conversation-timeline";
15
16
  import { cn } from "../lib/cn";
16
17
 
17
18
  export type SessionConversationProps = ClientOverride & {
18
19
  sessionId: string;
20
+ /** Localized actions for already-sent user-message disclosure. */
21
+ userMessageDisclosureLabels?: UserMessageDisclosureLabels | undefined;
19
22
  loadSkillReview?: HumanInputSurfaceProps["loadSkillReview"];
20
23
  className?: string;
21
24
  /** Defaults to filling the host. The host owns available height. */
@@ -32,6 +35,7 @@ export function SessionConversation(props: SessionConversationProps) {
32
35
 
33
36
  function Conversation({
34
37
  sessionId,
38
+ userMessageDisclosureLabels,
35
39
  loadSkillReview,
36
40
  client,
37
41
  workspaceId,
@@ -71,6 +75,7 @@ function Conversation({
71
75
  >
72
76
  {error && <p role="alert">{error.message}</p>}
73
77
  <MessageTimeline
78
+ userMessageDisclosureLabels={userMessageDisclosureLabels}
74
79
  className="min-h-0 flex-1"
75
80
  items={conversationTimeline(feed.timeline, queue, composer)}
76
81
  status={status}
@@ -190,7 +190,15 @@ function observeSharedResize(element: Element, callback: () => void): (() => voi
190
190
  };
191
191
  }
192
192
 
193
+ export type UserMessageDisclosureLabels = {
194
+ /** Collapsed disclosure action. Defaults to "Show more". */
195
+ showMore?: string | undefined;
196
+ /** Expanded disclosure action. Defaults to "Show less". */
197
+ showLess?: string | undefined;
198
+ };
199
+
193
200
  export type UserMessageDisclosureContextValue = {
201
+ labels?: UserMessageDisclosureLabels | undefined;
194
202
  expandedByMessageId: Map<string, boolean>;
195
203
  beginChange: (
196
204
  messageBody: HTMLElement,
@@ -235,6 +243,8 @@ export type UserMessageBodyProps = {
235
243
  text: string;
236
244
  children: ReactNode;
237
245
  className?: string | undefined;
246
+ /** Per-field overrides for timeline labels, then the English defaults. */
247
+ disclosureLabels?: UserMessageDisclosureLabels | undefined;
238
248
  };
239
249
 
240
250
  /**
@@ -247,7 +257,13 @@ export type UserMessageBodyProps = {
247
257
  * remembers expansion per durable message id and preserves the reader's scroll
248
258
  * anchor when height changes.
249
259
  */
250
- export function UserMessageBody({ messageId, text, children, className }: UserMessageBodyProps) {
260
+ export function UserMessageBody({
261
+ messageId,
262
+ text,
263
+ children,
264
+ className,
265
+ disclosureLabels,
266
+ }: UserMessageBodyProps) {
251
267
  const disclosure = useContext(UserMessageDisclosureContext);
252
268
  const [expanded, setExpanded] = useState(
253
269
  () => disclosure?.expandedByMessageId.get(messageId) ?? false,
@@ -454,7 +470,9 @@ export function UserMessageBody({ messageId, text, children, className }: UserMe
454
470
  className="mt-1.5 inline-flex min-h-7 items-center rounded-og-sm px-1.5 text-og-xs font-medium text-og-fg-muted outline-hidden transition-colors hover:bg-og-surface-3/60 hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent/45 pointer-coarse:min-h-11"
455
471
  onClick={(event) => toggle(event.currentTarget)}
456
472
  >
457
- {expanded ? "Show less" : "Show more"}
473
+ {expanded
474
+ ? (disclosureLabels?.showLess ?? disclosure?.labels?.showLess ?? "Show less")
475
+ : (disclosureLabels?.showMore ?? disclosure?.labels?.showMore ?? "Show more")}
458
476
  </button>
459
477
  </div>
460
478
  );
@@ -677,6 +677,8 @@ export function useComposer(
677
677
  const [acceptedControl, setAcceptedControl] = useState<EffectiveSessionControl | null>(null);
678
678
  const [resuming, setResuming] = useState(false);
679
679
  const [error, setError] = useState<Error | null>(null);
680
+ // Background draft reads recover independently of Send/Steer/control failures.
681
+ const [draftReadError, setDraftReadError] = useState<Error | null>(null);
680
682
  const [draft, setDraft] = useState<ComposerDraft | null>(null);
681
683
  const [draftLoading, setDraftLoading] = useState(Boolean(sessionId) && durableDrafts);
682
684
  const [draftSaving, setDraftSaving] = useState(false);
@@ -794,6 +796,7 @@ export function useComposer(
794
796
  setAcceptedControl(null);
795
797
  setResuming(false);
796
798
  setError(null);
799
+ setDraftReadError(null);
797
800
  setDraft(null);
798
801
  setDraftLoading(Boolean(sessionId) && durableDrafts);
799
802
  setDraftSaving(false);
@@ -920,6 +923,7 @@ export function useComposer(
920
923
  if (targetKeyRef.current !== targetKey) return;
921
924
  if (!sessionId || !durableDrafts) {
922
925
  setDraftLoading(false);
926
+ setDraftReadError(null);
923
927
  return;
924
928
  }
925
929
  let retry = draftReadRetryRef.current;
@@ -993,6 +997,8 @@ export function useComposer(
993
997
  if (retry.timer !== null) clearTimeout(retry.timer);
994
998
  retry.failures = 0;
995
999
  retry.timer = null;
1000
+ // Recovery also counts when the server returns the same draft revision.
1001
+ setDraftReadError(null);
996
1002
  const currentRevision = draftRef.current?.revision ?? -1;
997
1003
  // Reconnect and client-generation effects can legitimately ask for the
998
1004
  // draft again. A same-revision response is not new authority: publishing
@@ -1045,12 +1051,18 @@ export function useComposer(
1045
1051
  }
1046
1052
  } catch (cause) {
1047
1053
  if (
1054
+ !requestAbort.signal.aborted &&
1048
1055
  generation === targetGeneration.current &&
1049
1056
  targetKeyRef.current === targetKey &&
1050
1057
  readTicket === draftReadGeneration.current
1051
1058
  ) {
1052
- setError(asError(cause));
1059
+ const problem = asError(cause);
1060
+ const timedOut = problem.name === "TimeoutError";
1061
+ setDraftReadError(
1062
+ timedOut ? new Error("Draft sync timed out. Retrying…", { cause }) : problem,
1063
+ );
1053
1064
  if (
1065
+ timedOut ||
1054
1066
  cause instanceof TypeError ||
1055
1067
  (cause && typeof cause === "object" && "retryable" in cause && cause.retryable === true)
1056
1068
  ) {
@@ -2639,6 +2651,7 @@ export function useComposer(
2639
2651
  const clearError = useCallback(() => {
2640
2652
  if (targetKeyRef.current !== targetKey) return;
2641
2653
  setError(null);
2654
+ setDraftReadError(null);
2642
2655
  setDraftConflict(null);
2643
2656
  }, [targetKey]);
2644
2657
  // `valueRef` is the synchronous composer authority. React state exists to
@@ -2706,7 +2719,7 @@ export function useComposer(
2706
2719
  resolveDraftConflict,
2707
2720
  restoredResources: identityMatches ? restoredResources : [],
2708
2721
  removeRestoredResource,
2709
- error: identityMatches ? error : null,
2722
+ error: identityMatches ? (error ?? draftReadError) : null,
2710
2723
  clearError,
2711
2724
  };
2712
2725
  }
package/src/index.ts CHANGED
@@ -511,7 +511,10 @@ export { GeneratedVideoPlayer } from "./components/generated-video-player";
511
511
  export type { GeneratedVideoPlayerProps } from "./components/generated-video-player";
512
512
  export type { MessageTimelineProps } from "./components/message-timeline";
513
513
  export { UserMessageBody, userMessageLikelyNeedsDisclosure } from "./components/user-message-body";
514
- export type { UserMessageBodyProps } from "./components/user-message-body";
514
+ export type {
515
+ UserMessageBodyProps,
516
+ UserMessageDisclosureLabels,
517
+ } from "./components/user-message-body";
515
518
  export {
516
519
  Markdown,
517
520
  sandboxFileLocationFromHref,
package/src/session-ui.ts CHANGED
@@ -16,7 +16,10 @@ export type { MessageTimelineProps } from "./components/message-timeline";
16
16
  export { createOlderHistoryLoadReceipt } from "./older-history";
17
17
  export type { OlderHistoryLoader, OlderHistoryLoadReceipt } from "./older-history";
18
18
  export { UserMessageBody, userMessageLikelyNeedsDisclosure } from "./components/user-message-body";
19
- export type { UserMessageBodyProps } from "./components/user-message-body";
19
+ export type {
20
+ UserMessageBodyProps,
21
+ UserMessageDisclosureLabels,
22
+ } from "./components/user-message-body";
20
23
  export { BUILT_IN_TURN_SUMMARY_FACET_IDS } from "./timeline/turn-summary";
21
24
  export type {
22
25
  BuiltInTurnSummaryFacetId,