@opengeni/react 5.0.5-canary.2 → 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.
- package/README.md +13 -1
- package/dist/{chunk-V3WX3TQG.js → chunk-45XEUVTK.js} +2 -2
- package/dist/{chunk-6J56T3MG.js → chunk-NYESIADM.js} +14 -5
- package/dist/chunk-NYESIADM.js.map +1 -0
- package/dist/{chunk-H63SQTGI.js → chunk-WS6D5BHH.js} +37 -19
- package/dist/chunk-WS6D5BHH.js.map +1 -0
- package/dist/components/message-timeline.d.ts +4 -1
- package/dist/components/session-conversation.d.ts +3 -0
- package/dist/components/user-message-body.d.ts +10 -1
- package/dist/composer.js +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -3
- package/dist/session-ui.d.ts +1 -1
- package/dist/session-ui.js +3 -3
- package/dist/session.js +1 -1
- package/package.json +3 -3
- package/src/components/message-timeline.tsx +49 -29
- package/src/components/session-conversation.tsx +5 -0
- package/src/components/user-message-body.tsx +20 -2
- package/src/hooks/use-composer.ts +15 -2
- package/src/index.ts +4 -1
- package/src/session-ui.ts +4 -1
- package/dist/chunk-6J56T3MG.js.map +0 -1
- package/dist/chunk-H63SQTGI.js.map +0 -1
- /package/dist/{chunk-V3WX3TQG.js.map → chunk-45XEUVTK.js.map} +0 -0
|
@@ -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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
223
|
+
} from "./chunk-NYESIADM.js";
|
|
224
224
|
import {
|
|
225
225
|
COMPOSER_PAYMENT_REQUIRED_MESSAGE,
|
|
226
226
|
CREDIT_EXHAUSTION_MESSAGE,
|
package/dist/session-ui.d.ts
CHANGED
|
@@ -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";
|
package/dist/session-ui.js
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
setStartupDetails,
|
|
17
17
|
useStartupDetails,
|
|
18
18
|
userMessageLikelyNeedsDisclosure
|
|
19
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/react",
|
|
3
|
-
"version": "5.0
|
|
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.
|
|
137
|
-
"@opengeni/sdk": "^5.0
|
|
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
|
-
[
|
|
931
|
+
[
|
|
932
|
+
beginUserMessageDisclosureChange,
|
|
933
|
+
userMessageDisclosureLabels?.showMore,
|
|
934
|
+
userMessageDisclosureLabels?.showLess,
|
|
935
|
+
],
|
|
924
936
|
);
|
|
925
937
|
const timelineGroupEntryContext = useMemo<TimelineGroupEntryContext>(
|
|
926
938
|
() => ({
|
|
@@ -2393,41 +2405,49 @@ const TimelineGroupEntry = memo(function TimelineGroupEntry({
|
|
|
2393
2405
|
nextGroup.item.phase === "compacted"
|
|
2394
2406
|
? 1
|
|
2395
2407
|
: 0;
|
|
2408
|
+
const content = (
|
|
2409
|
+
<TimelineGroupView
|
|
2410
|
+
{...behavior}
|
|
2411
|
+
group={group}
|
|
2412
|
+
foldLiveCluster={isAgentProgress(nextGroup)}
|
|
2413
|
+
startupDismissed={startupDismissed}
|
|
2414
|
+
trailingAgentText={trailingAgentTextAfterTurn(group, nextGroup)}
|
|
2415
|
+
contextCompactionCount={contextCompactionCount > 0 ? contextCompactionCount : undefined}
|
|
2416
|
+
/>
|
|
2417
|
+
);
|
|
2396
2418
|
return (
|
|
2397
2419
|
<GenieLoadingOptionsContext.Provider value={behavior.genieLoading}>
|
|
2398
2420
|
<div data-og-timeline-group-anchor="" data-og-group-key={groupKey}>
|
|
2399
2421
|
<EntranceAnimationProvider value={entranceEnabled} liveValue={liveEntranceEnabled}>
|
|
2400
2422
|
<TimelineGroupRenderBoundary resetKeys={[group, behavior]}>
|
|
2401
2423
|
<UserMessageDisclosureProvider value={userMessageDisclosureContext}>
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
{...behavior}
|
|
2421
|
-
group={group}
|
|
2422
|
-
foldLiveCluster={isAgentProgress(nextGroup)}
|
|
2423
|
-
startupDismissed={startupDismissed}
|
|
2424
|
-
trailingAgentText={trailingAgentTextAfterTurn(group, nextGroup)}
|
|
2425
|
-
contextCompactionCount={
|
|
2426
|
-
contextCompactionCount > 0 ? contextCompactionCount : undefined
|
|
2424
|
+
{/* Item groups never switch the preparation/content key. Keep their
|
|
2425
|
+
DOM shell without mounting inert presence and motion lifecycles
|
|
2426
|
+
for every historical message in a prepend. */}
|
|
2427
|
+
{group.kind === "item" ? (
|
|
2428
|
+
<div>{content}</div>
|
|
2429
|
+
) : (
|
|
2430
|
+
<AnimatePresence initial={false}>
|
|
2431
|
+
<motion.div
|
|
2432
|
+
key={
|
|
2433
|
+
!startupDismissed &&
|
|
2434
|
+
group.kind === "activity" &&
|
|
2435
|
+
group.items.every(
|
|
2436
|
+
(item) =>
|
|
2437
|
+
item.kind === "startup-phase" ||
|
|
2438
|
+
(item.kind === "reasoning" && !item.text.trim()),
|
|
2439
|
+
)
|
|
2440
|
+
? "preparation"
|
|
2441
|
+
: "content"
|
|
2427
2442
|
}
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2443
|
+
initial={false}
|
|
2444
|
+
exit={{ opacity: 0, height: 0 }}
|
|
2445
|
+
transition={{ duration: reducedMotion ? 0 : 0.2 }}
|
|
2446
|
+
>
|
|
2447
|
+
{content}
|
|
2448
|
+
</motion.div>
|
|
2449
|
+
</AnimatePresence>
|
|
2450
|
+
)}
|
|
2431
2451
|
</UserMessageDisclosureProvider>
|
|
2432
2452
|
</TimelineGroupRenderBoundary>
|
|
2433
2453
|
</EntranceAnimationProvider>
|
|
@@ -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({
|
|
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
|
|
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
|
-
|
|
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 {
|
|
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 {
|
|
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,
|