@opengeni/react 6.1.0 → 7.0.0-canary.35625901699001
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 +83 -2
- package/dist/approvals.d.ts +2 -1
- package/dist/artifacts-document.js +1 -1
- package/dist/artifacts-presentation.js +1 -1
- package/dist/artifacts-spreadsheet.js +1 -1
- package/dist/artifacts.js +3 -3
- package/dist/{browser-viewer-NTD6UIPR.js → browser-viewer-LGH4IP47.js} +3 -3
- package/dist/capability-catalog-row.d.ts +20 -0
- package/dist/capability-logo-fallback.d.ts +3 -0
- package/dist/{chunk-NOSYBS2D.js → chunk-2VHARTBL.js} +2 -1
- package/dist/{chunk-VRBL3F5E.js → chunk-5GAL23FF.js} +10 -2
- package/dist/{chunk-VRBL3F5E.js.map → chunk-5GAL23FF.js.map} +1 -1
- package/dist/chunk-5UONOQ3Y.js +635 -0
- package/dist/chunk-5UONOQ3Y.js.map +1 -0
- package/dist/{chunk-NYESIADM.js → chunk-AKOMC3VO.js} +3 -3
- package/dist/chunk-AKOMC3VO.js.map +1 -0
- package/dist/chunk-BRM6FVZA.js +302 -0
- package/dist/chunk-BRM6FVZA.js.map +1 -0
- package/dist/{chunk-KANFU34B.js → chunk-DBPVUGQT.js} +11 -2
- package/dist/chunk-DBPVUGQT.js.map +1 -0
- package/dist/chunk-FHIGTPME.js +1589 -0
- package/dist/chunk-FHIGTPME.js.map +1 -0
- package/dist/{chunk-5M6VTFJ5.js → chunk-GBPCZH3Y.js} +2 -2
- package/dist/{chunk-YBM6CQRU.js → chunk-GEN54DU5.js} +4 -4
- package/dist/{chunk-UMECRJRV.js → chunk-HJ5VJ4JB.js} +21 -12
- package/dist/chunk-HJ5VJ4JB.js.map +1 -0
- package/dist/{chunk-R4KRSFGA.js → chunk-IP4BUBKH.js} +3 -3
- package/dist/{chunk-NLTS7JHI.js → chunk-JPHDWKZE.js} +5 -5
- package/dist/{chunk-TDSEILUH.js → chunk-MI6ALLLD.js} +1297 -1535
- package/dist/chunk-MI6ALLLD.js.map +1 -0
- package/dist/{chunk-ICA6R6TW.js → chunk-OWHPKAOV.js} +28 -20
- package/dist/chunk-OWHPKAOV.js.map +1 -0
- package/dist/{chunk-24M4YBCL.js → chunk-PNAVEK2U.js} +4 -4
- package/dist/{chunk-L2NBTKRX.js → chunk-TXCBE32L.js} +203 -19
- package/dist/chunk-TXCBE32L.js.map +1 -0
- package/dist/{chunk-45XEUVTK.js → chunk-UXE5SSNN.js} +293 -463
- package/dist/chunk-UXE5SSNN.js.map +1 -0
- package/dist/{chunk-PEI6RANI.js → chunk-VR4Z73EU.js} +203 -9
- package/dist/chunk-VR4Z73EU.js.map +1 -0
- package/dist/{chunk-HUIKIDM5.js → chunk-XMXRI5JK.js} +65 -18
- package/dist/chunk-XMXRI5JK.js.map +1 -0
- package/dist/client.d.ts +1 -1
- package/dist/components/artifacts/spreadsheet-general-display.d.ts +24 -0
- package/dist/components/chat-composer.d.ts +13 -3
- package/dist/components/markdown.d.ts +6 -3
- package/dist/components/message-timeline.d.ts +7 -2
- package/dist/components/preview-loading.d.ts +2 -0
- package/dist/components/session-capability-frame.d.ts +24 -0
- package/dist/components/session-chrome.d.ts +1 -2
- package/dist/components/session-commands.d.ts +6 -0
- package/dist/components/session-connection-request.d.ts +8 -0
- package/dist/components/session-conversation.d.ts +3 -0
- package/dist/components/session-mcp-capability-card.d.ts +22 -0
- package/dist/components/timeline-search.d.ts +34 -0
- package/dist/composer.js +7 -7
- package/dist/connect-account-identity.d.ts +8 -0
- package/dist/connect-accounts.d.ts +5 -0
- package/dist/connect-chooser.d.ts +6 -0
- package/dist/connect-panel.d.ts +9 -2
- package/dist/connect-setup.d.ts +5 -1
- package/dist/connect.d.ts +5 -21
- package/dist/connect.js +1268 -584
- package/dist/connect.js.map +1 -1
- package/dist/connection-catalog.d.ts +6 -1
- package/dist/connection-discovery.d.ts +12 -0
- package/dist/connection-installed.d.ts +1 -0
- package/dist/connection-logo.d.ts +5 -2
- package/dist/connection-service-logo.d.ts +8 -0
- package/dist/connection-service-presentation.d.ts +13 -0
- package/dist/connection-skeleton.d.ts +5 -0
- package/dist/discovery-cache.d.ts +5 -0
- package/dist/hooks/use-codex-accounts.d.ts +11 -5
- package/dist/hooks/use-connect.d.ts +22 -0
- package/dist/hooks/use-session-events.d.ts +5 -0
- package/dist/hooks/use-session-mcp-approval-policy.d.ts +2 -2
- package/dist/hooks/use-workspace-sessions.d.ts +2 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.js +771 -793
- package/dist/index.js.map +1 -1
- package/dist/interaction.js +2 -2
- package/dist/machines.js +2 -2
- package/dist/mcp-connection-status.d.ts +14 -0
- package/dist/{model-policy-picker-menu-3R336DP2.js → model-policy-picker-menu-RVOQ4ZZG.js} +4 -4
- package/dist/model-policy.d.ts +6 -2
- package/dist/model-policy.js +1 -1
- package/dist/{platform-activity-row-DUE2W74J.js → platform-activity-row-HLOH7FW4.js} +9 -4
- package/dist/platform-activity-row-HLOH7FW4.js.map +1 -0
- package/dist/plugin-discovery.d.ts +6 -0
- package/dist/{queue-surface-implementation-LK3S4BIW.js → queue-surface-implementation-3RIFK2BS.js} +4 -4
- package/dist/realtime.js +22 -22
- package/dist/realtime.js.map +1 -1
- package/dist/session-auth-recommendation.d.ts +5 -0
- package/dist/session-capability-policy.d.ts +12 -0
- package/dist/session-ui.d.ts +2 -0
- package/dist/session-ui.js +14 -12
- package/dist/session.d.ts +1 -0
- package/dist/session.js +6 -4
- package/dist/skill-discovery.d.ts +11 -0
- package/dist/timeline/compaction-copy.d.ts +10 -0
- package/dist/timeline/projection.d.ts +3 -1
- package/dist/timeline/tool-display-name.d.ts +2 -1
- package/dist/timeline/turn-summary.d.ts +2 -2
- package/dist/timeline/types.d.ts +24 -2
- package/dist/{timeline-annotation-markers-DRSTLEM6.js → timeline-annotation-markers-OY6OWR3V.js} +2 -2
- package/dist/{timeline-annotation-selection-IHLUGVND.js → timeline-annotation-selection-BOXA2TIN.js} +2 -2
- package/dist/{timeline-annotations-dialog-6Q53N5FG.js → timeline-annotations-dialog-RGY3MHL3.js} +3 -3
- package/package.json +3 -3
- package/src/approvals.ts +8 -1
- package/src/assets/README.md +8 -0
- package/src/assets/gmail.ico +0 -0
- package/src/assets/outlook.ico +0 -0
- package/src/capability-catalog-row.tsx +94 -0
- package/src/capability-logo-fallback.ts +22 -0
- package/src/client.ts +0 -9
- package/src/components/approval-surface.tsx +12 -2
- package/src/components/artifacts/document-editor.tsx +63 -6
- package/src/components/artifacts/presentation-editor.tsx +214 -9
- package/src/components/artifacts/spreadsheet-canvas.ts +3 -8
- package/src/components/artifacts/spreadsheet-general-display.ts +43 -0
- package/src/components/artifacts/spreadsheet-grid.tsx +10 -11
- package/src/components/chat-composer.tsx +26 -3
- package/src/components/composer.tsx +10 -4
- package/src/components/human-input-form.tsx +12 -2
- package/src/components/markdown.tsx +133 -9
- package/src/components/message-timeline.tsx +104 -36
- package/src/components/model-picker.tsx +11 -3
- package/src/components/model-policy-picker-menu.tsx +10 -3
- package/src/components/preview-loading.tsx +154 -0
- package/src/components/sandbox-workspace.tsx +20 -36
- package/src/components/session-capability-frame.tsx +163 -0
- package/src/components/session-chrome.tsx +46 -77
- package/src/components/session-commands.tsx +18 -0
- package/src/components/session-connection-request.tsx +97 -0
- package/src/components/session-conversation.tsx +10 -5
- package/src/components/session-mcp-capability-card.tsx +532 -0
- package/src/components/session-status.tsx +2 -2
- package/src/components/timeline-anchor.tsx +9 -8
- package/src/components/timeline-search.tsx +168 -0
- package/src/components/user-message-body.tsx +7 -0
- package/src/connect-account-identity.tsx +34 -0
- package/src/connect-accounts.tsx +114 -52
- package/src/connect-chooser.tsx +171 -39
- package/src/connect-panel.tsx +73 -9
- package/src/connect-setup.tsx +72 -25
- package/src/connect.ts +13 -22
- package/src/connection-assets.d.ts +4 -0
- package/src/connection-catalog.tsx +61 -39
- package/src/connection-discovery.tsx +235 -0
- package/src/connection-installed.tsx +2 -0
- package/src/connection-logo.tsx +18 -10
- package/src/connection-service-logo.tsx +55 -0
- package/src/connection-service-presentation.ts +46 -0
- package/src/connection-skeleton.tsx +16 -0
- package/src/conversation-timeline.ts +1 -0
- package/src/discovery-cache.ts +42 -0
- package/src/hooks/use-codex-accounts.ts +33 -14
- package/src/hooks/use-composer.ts +4 -5
- package/src/hooks/use-connect.ts +23 -0
- package/src/hooks/use-session-events.ts +114 -1
- package/src/hooks/use-session-mcp-approval-policy.ts +13 -5
- package/src/hooks/use-workspace-sessions.ts +10 -0
- package/src/index.ts +22 -2
- package/src/mcp-connection-status.ts +35 -0
- package/src/model-policy.ts +21 -0
- package/src/plugin-details.tsx +8 -5
- package/src/plugin-discovery.tsx +92 -72
- package/src/realtime/realtime-control.tsx +6 -8
- package/src/session-auth-recommendation.ts +48 -0
- package/src/session-capability-policy.ts +83 -0
- package/src/session-ui.ts +2 -0
- package/src/session.ts +1 -0
- package/src/skill-discovery.tsx +101 -56
- package/src/timeline/compaction-copy.ts +40 -0
- package/src/timeline/platform-activity-row.tsx +8 -3
- package/src/timeline/projection.ts +78 -2
- package/src/timeline/rolling-activity.tsx +4 -2
- package/src/timeline/shared.tsx +6 -1
- package/src/timeline/startup-timings.tsx +1 -1
- package/src/timeline/tool-display-name.ts +8 -6
- package/src/timeline/tool-renderers.tsx +5 -3
- package/src/timeline/turn-summary.tsx +17 -3
- package/src/timeline/types.ts +24 -2
- package/styles/compiled.css +325 -27
- package/styles/connect.css +90 -15
- package/styles/index.css +46 -0
- package/styles/session-capability.css +42 -0
- package/dist/chunk-45XEUVTK.js.map +0 -1
- package/dist/chunk-HQV2I5HV.js +0 -124
- package/dist/chunk-HQV2I5HV.js.map +0 -1
- package/dist/chunk-HUIKIDM5.js.map +0 -1
- package/dist/chunk-ICA6R6TW.js.map +0 -1
- package/dist/chunk-IHQII5WO.js +0 -886
- package/dist/chunk-IHQII5WO.js.map +0 -1
- package/dist/chunk-KANFU34B.js.map +0 -1
- package/dist/chunk-L2NBTKRX.js.map +0 -1
- package/dist/chunk-NYESIADM.js.map +0 -1
- package/dist/chunk-PEI6RANI.js.map +0 -1
- package/dist/chunk-TDSEILUH.js.map +0 -1
- package/dist/chunk-UMECRJRV.js.map +0 -1
- package/dist/hooks/use-packs.d.ts +0 -32
- package/dist/platform-activity-row-DUE2W74J.js.map +0 -1
- package/src/hooks/use-packs.ts +0 -157
- /package/dist/{browser-viewer-NTD6UIPR.js.map → browser-viewer-LGH4IP47.js.map} +0 -0
- /package/dist/{chunk-NOSYBS2D.js.map → chunk-2VHARTBL.js.map} +0 -0
- /package/dist/{chunk-5M6VTFJ5.js.map → chunk-GBPCZH3Y.js.map} +0 -0
- /package/dist/{chunk-YBM6CQRU.js.map → chunk-GEN54DU5.js.map} +0 -0
- /package/dist/{chunk-R4KRSFGA.js.map → chunk-IP4BUBKH.js.map} +0 -0
- /package/dist/{chunk-NLTS7JHI.js.map → chunk-JPHDWKZE.js.map} +0 -0
- /package/dist/{chunk-24M4YBCL.js.map → chunk-PNAVEK2U.js.map} +0 -0
- /package/dist/{model-policy-picker-menu-3R336DP2.js.map → model-policy-picker-menu-RVOQ4ZZG.js.map} +0 -0
- /package/dist/{queue-surface-implementation-LK3S4BIW.js.map → queue-surface-implementation-3RIFK2BS.js.map} +0 -0
- /package/dist/{timeline-annotation-markers-DRSTLEM6.js.map → timeline-annotation-markers-OY6OWR3V.js.map} +0 -0
- /package/dist/{timeline-annotation-selection-IHLUGVND.js.map → timeline-annotation-selection-BOXA2TIN.js.map} +0 -0
- /package/dist/{timeline-annotations-dialog-6Q53N5FG.js.map → timeline-annotations-dialog-RGY3MHL3.js.map} +0 -0
package/dist/session.js
CHANGED
|
@@ -10,9 +10,10 @@ import {
|
|
|
10
10
|
useSessionControl,
|
|
11
11
|
useSessionLineage,
|
|
12
12
|
useSessionMcpApprovalPolicy
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-DBPVUGQT.js";
|
|
14
14
|
import {
|
|
15
15
|
buildTimeline,
|
|
16
|
+
conversationTimeline,
|
|
16
17
|
createOlderHistoryLoadReceipt,
|
|
17
18
|
creditExhaustedFromEvents,
|
|
18
19
|
extractSessionRef,
|
|
@@ -28,22 +29,23 @@ import {
|
|
|
28
29
|
useSession,
|
|
29
30
|
useSessionEvents,
|
|
30
31
|
useTurnQueue
|
|
31
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-TXCBE32L.js";
|
|
32
33
|
import {
|
|
33
34
|
FILE_ONLY_MESSAGE_TEXT,
|
|
34
35
|
composeSendInput,
|
|
35
36
|
shouldSteerOnKey,
|
|
36
37
|
shouldSubmitOnKey,
|
|
37
38
|
useComposer
|
|
38
|
-
} from "./chunk-
|
|
39
|
-
import "./chunk-PLYRL5ER.js";
|
|
39
|
+
} from "./chunk-AKOMC3VO.js";
|
|
40
40
|
import "./chunk-KZ73RL76.js";
|
|
41
|
+
import "./chunk-PLYRL5ER.js";
|
|
41
42
|
import "./chunk-NEXLLTP4.js";
|
|
42
43
|
export {
|
|
43
44
|
FILE_ONLY_MESSAGE_TEXT,
|
|
44
45
|
approvalsFromRequiresAction,
|
|
45
46
|
buildTimeline,
|
|
46
47
|
composeSendInput,
|
|
48
|
+
conversationTimeline,
|
|
47
49
|
createEmbeddedSessionClient,
|
|
48
50
|
createOlderHistoryLoadReceipt,
|
|
49
51
|
creditExhaustedFromEvents,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type CapabilityCatalogStatus } from "./capability-catalog-row.js";
|
|
1
2
|
export type SkillDiscoveryItem = {
|
|
2
3
|
id: string;
|
|
3
4
|
name: string;
|
|
@@ -23,6 +24,16 @@ export type SkillDiscoveryProps = {
|
|
|
23
24
|
query: string;
|
|
24
25
|
onImport: (url: string) => void;
|
|
25
26
|
canManage: boolean;
|
|
27
|
+
localSkills?: readonly {
|
|
28
|
+
id: string;
|
|
29
|
+
name: string;
|
|
30
|
+
description?: string;
|
|
31
|
+
status?: CapabilityCatalogStatus;
|
|
32
|
+
statusLabel?: string;
|
|
33
|
+
onOpen: () => void;
|
|
34
|
+
}[];
|
|
35
|
+
resultLimit?: number;
|
|
36
|
+
onShowMore?: () => void;
|
|
26
37
|
onSearch?: (() => void) | undefined;
|
|
27
38
|
};
|
|
28
39
|
/** Host-owned query and import flow; browse presentation is reusable independently. */
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ContextCompactionItem } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Subtitle for a settled compaction landmark. A definitive provider rejection
|
|
4
|
+
* repeats deterministically for the same conversation, so it names the
|
|
5
|
+
* rejected field and withholds the generic retry promise; every other skip
|
|
6
|
+
* keeps its existing copy.
|
|
7
|
+
*/
|
|
8
|
+
export declare function compactionSkipSubtitle(reason: string | null, providerRejection?: ContextCompactionItem["providerRejection"]): string;
|
|
9
|
+
/** `HTTP 400 invalid_request_error, param input[3].encrypted_content`; identifiers only. */
|
|
10
|
+
export declare function describeCompactionProviderRejection(rejection: NonNullable<ContextCompactionItem["providerRejection"]>): string;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { type SessionEvent, type SessionStatus } from "@opengeni/sdk";
|
|
2
2
|
import type { TimelineGroup, TimelineItem } from "./types.js";
|
|
3
3
|
export { toolDisplayName, mcpToolLeaf, toolMatchesLeaf } from "./tool-display-name.js";
|
|
4
|
-
export declare function buildTimeline(events: SessionEvent[]
|
|
4
|
+
export declare function buildTimeline(events: SessionEvent[], options?: {
|
|
5
|
+
partialStart?: boolean;
|
|
6
|
+
}): TimelineItem[];
|
|
5
7
|
/**
|
|
6
8
|
* Codex subscription web search can return private citation handles without
|
|
7
9
|
* the URL annotation table that would make them resolvable. Keep the canonical
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* and bare `session_create` resolve the same UI — without inventing previews
|
|
7
7
|
* from argument JSON.
|
|
8
8
|
*/
|
|
9
|
+
import type { ToolDisplayMetadata } from "@opengeni/sdk";
|
|
9
10
|
/** Leaf tool name after the first `__` server boundary (or the whole name). */
|
|
10
11
|
export declare function mcpToolLeaf(name: string): string;
|
|
11
12
|
/**
|
|
@@ -18,4 +19,4 @@ export declare function toolMatchesLeaf(wireName: string, leaf: string): boolean
|
|
|
18
19
|
* Readable label for a tool call ("session_create" / "opengeni__session_create"
|
|
19
20
|
* → "Session create"). Title-cases the first character of the leaf phrase.
|
|
20
21
|
*/
|
|
21
|
-
export declare function toolDisplayName(name: string): string;
|
|
22
|
+
export declare function toolDisplayName(name: string, display?: ToolDisplayMetadata): string;
|
|
@@ -65,8 +65,8 @@ export type TurnSummaryProps = {
|
|
|
65
65
|
items: ActivityItem[];
|
|
66
66
|
/**
|
|
67
67
|
* The settled verdict — or absent for a completed CLUSTER of a still-running
|
|
68
|
-
* turn, which folds neutrally
|
|
69
|
-
*
|
|
68
|
+
* turn, which folds neutrally. Only unfinished activity inside this summary
|
|
69
|
+
* animates; the parent turn may still be composing a response elsewhere.
|
|
70
70
|
*/
|
|
71
71
|
outcome?: TurnOutcome | undefined;
|
|
72
72
|
/** A short failure reason shown inline on a failed chip (never hidden). */
|
package/dist/timeline/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { HumanInputQuestion, HumanInputResponse, MediaGenerationResult, ResourceRef, SessionStatus, TimelineAnnotation, TimelineAnnotationSource, ToolAuthNeededPayload, ToolRef } from "@opengeni/sdk";
|
|
1
|
+
import type { HumanInputQuestion, HumanInputResponse, MediaGenerationResult, ResourceRef, SessionStatus, TimelineAnnotation, TimelineAnnotationSource, ToolAuthNeededPayload, ToolRef, ToolDisplayMetadata } from "@opengeni/sdk";
|
|
2
2
|
export type TimelineAnnotationSourceDescriptor = Omit<TimelineAnnotationSource, "startOffset" | "endOffset" | "contextBefore" | "contextAfter"> & {
|
|
3
3
|
text: string;
|
|
4
4
|
};
|
|
@@ -97,6 +97,7 @@ export type ToolCallItem = {
|
|
|
97
97
|
turnId: string | null;
|
|
98
98
|
callId: string | null;
|
|
99
99
|
name: string;
|
|
100
|
+
display?: ToolDisplayMetadata;
|
|
100
101
|
arguments: unknown;
|
|
101
102
|
output: unknown;
|
|
102
103
|
truncation?: ToolCallTruncation | null;
|
|
@@ -301,10 +302,22 @@ export type ContextCompactionItem = {
|
|
|
301
302
|
estimatedTokensBefore: number | null;
|
|
302
303
|
estimatedTokensAfter: number | null;
|
|
303
304
|
skipReason: string | null;
|
|
305
|
+
/**
|
|
306
|
+
* Present only for a `summarization_failed` skip where the provider
|
|
307
|
+
* definitively rejected the compaction request. Content-free identifiers.
|
|
308
|
+
*/
|
|
309
|
+
providerRejection: ContextCompactionProviderRejection | null;
|
|
304
310
|
/** Provider implementation id for debug disclosure only. */
|
|
305
311
|
implementation: string | null;
|
|
306
312
|
occurredAt: string;
|
|
307
313
|
};
|
|
314
|
+
export type ContextCompactionProviderRejection = {
|
|
315
|
+
httpStatus: number;
|
|
316
|
+
type: string | null;
|
|
317
|
+
code: string | null;
|
|
318
|
+
param: string | null;
|
|
319
|
+
requestId: string | null;
|
|
320
|
+
};
|
|
308
321
|
export type MachineInputMember = {
|
|
309
322
|
id: string;
|
|
310
323
|
kind: "scheduled_occurrence" | "goal_continuation" | "background_command_result" | "session_wait_timeout" | "agent_message" | "agent_steer_instruction" | "child_terminal_result" | "media_generation_result" | "child_requires_action" | "child_requires_action_resolved" | "child_paused" | "child_waiting_capacity" | "child_progress";
|
|
@@ -340,6 +353,9 @@ export type AuthNeededItem = {
|
|
|
340
353
|
turnId: string | null;
|
|
341
354
|
/** The runtime surface that requested recovery, when the event is an MCP auth signal. */
|
|
342
355
|
serverId: string | null;
|
|
356
|
+
/** Explicit recovery identity; never inferred from an opaque execution alias. */
|
|
357
|
+
canonicalServerId?: string | null;
|
|
358
|
+
connectionSubjectScope?: "workspace" | "subject" | null;
|
|
343
359
|
/** Durable event family that produced this notice. */
|
|
344
360
|
source?: "tool" | "credential" | "capability" | undefined;
|
|
345
361
|
/** The connection's registrable domain, e.g. "linear.app". */
|
|
@@ -372,7 +388,13 @@ export type TurnEndItem = {
|
|
|
372
388
|
failureText: string | null;
|
|
373
389
|
occurredAt: string;
|
|
374
390
|
};
|
|
375
|
-
export type TimelineItem = UserMessageItem | HumanInputItem | AgentMessageItem | ReasoningItem | ToolCallItem | WorkerItem | WorkerCompletionItem | SandboxItem | StartupPhaseItem | SessionStatusItem | GoalItem | NoticeItem | ContextCompactionItem | MachineInputBatchItem | AuthNeededItem | MemoryItem | KnowledgeItem | FleetDecisionItem | TurnEndItem
|
|
391
|
+
export type TimelineItem = (UserMessageItem | HumanInputItem | AgentMessageItem | ReasoningItem | ToolCallItem | WorkerItem | WorkerCompletionItem | SandboxItem | StartupPhaseItem | SessionStatusItem | GoalItem | NoticeItem | ContextCompactionItem | MachineInputBatchItem | AuthNeededItem | MemoryItem | KnowledgeItem | FleetDecisionItem | TurnEndItem) & {
|
|
392
|
+
/** Durable identities, independent of renderer/reconciliation keys. */
|
|
393
|
+
sourceEvents?: readonly {
|
|
394
|
+
eventId: string;
|
|
395
|
+
sequence: number;
|
|
396
|
+
}[] | undefined;
|
|
397
|
+
};
|
|
376
398
|
/** Activity items cluster between chat messages (reasoning, tools, workers, sandbox, memory). */
|
|
377
399
|
export type ActivityItem = ReasoningItem | ToolCallItem | WorkerItem | SandboxItem | StartupPhaseItem | MemoryItem | KnowledgeItem | FleetDecisionItem;
|
|
378
400
|
export type TimelineGroup = {
|
package/dist/{timeline-annotation-markers-DRSTLEM6.js → timeline-annotation-markers-OY6OWR3V.js}
RENAMED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
cssEscapeAttribute,
|
|
12
12
|
matchingQuoteInSource,
|
|
13
13
|
occurrenceOffsets
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-2VHARTBL.js";
|
|
15
15
|
import {
|
|
16
16
|
cn
|
|
17
17
|
} from "./chunk-22KP6LR5.js";
|
|
@@ -162,4 +162,4 @@ export {
|
|
|
162
162
|
TimelineAnnotationMarkers,
|
|
163
163
|
timeline_annotation_markers_default as default
|
|
164
164
|
};
|
|
165
|
-
//# sourceMappingURL=timeline-annotation-markers-
|
|
165
|
+
//# sourceMappingURL=timeline-annotation-markers-OY6OWR3V.js.map
|
package/dist/{timeline-annotation-selection-IHLUGVND.js → timeline-annotation-selection-BOXA2TIN.js}
RENAMED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
quoteOccurrenceIndex,
|
|
6
6
|
truncateAnnotationQuote,
|
|
7
7
|
visibleClientRect
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-2VHARTBL.js";
|
|
9
9
|
import {
|
|
10
10
|
usePortalTokenStyle
|
|
11
11
|
} from "./chunk-VZTQ73XT.js";
|
|
@@ -233,4 +233,4 @@ export {
|
|
|
233
233
|
TimelineAnnotationSelection,
|
|
234
234
|
timeline_annotation_selection_default as default
|
|
235
235
|
};
|
|
236
|
-
//# sourceMappingURL=timeline-annotation-selection-
|
|
236
|
+
//# sourceMappingURL=timeline-annotation-selection-BOXA2TIN.js.map
|
package/dist/{timeline-annotations-dialog-6Q53N5FG.js → timeline-annotations-dialog-RGY3MHL3.js}
RENAMED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
AnnotationNoteField,
|
|
4
4
|
AnnotationNotePreview,
|
|
5
5
|
AnnotationQuoteSourceButton
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-GBPCZH3Y.js";
|
|
7
7
|
import {
|
|
8
8
|
ANNOTATION_REVIEW_DIALOG_WIDTH_PX,
|
|
9
9
|
clampAnnotationDialogPlacement,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
import {
|
|
13
13
|
annotationDisplayOrdinal,
|
|
14
14
|
cssEscapeAttribute
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-2VHARTBL.js";
|
|
16
16
|
import {
|
|
17
17
|
usePortalTokenStyle
|
|
18
18
|
} from "./chunk-VZTQ73XT.js";
|
|
@@ -259,4 +259,4 @@ export {
|
|
|
259
259
|
TimelineAnnotationsDialog,
|
|
260
260
|
timeline_annotations_dialog_default as default
|
|
261
261
|
};
|
|
262
|
-
//# sourceMappingURL=timeline-annotations-dialog-
|
|
262
|
+
//# sourceMappingURL=timeline-annotations-dialog-RGY3MHL3.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0-canary.35625901699001",
|
|
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.
|
|
137
|
-
"@opengeni/sdk": "^
|
|
136
|
+
"@opengeni/connect": "^0.3.0-canary.35625901699001",
|
|
137
|
+
"@opengeni/sdk": "^7.0.0-canary.35625901699001",
|
|
138
138
|
"clsx": "^2.1.1",
|
|
139
139
|
"dequal": "2.0.3",
|
|
140
140
|
"lucide-react": "^1.8.0",
|
package/src/approvals.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
parseToolDisplayMetadata,
|
|
3
|
+
type ToolDisplayMetadata,
|
|
4
|
+
type SessionEvent,
|
|
5
|
+
} from "@opengeni/sdk";
|
|
2
6
|
|
|
3
7
|
/* ----------------------------------------------------------------------------
|
|
4
8
|
Pending-approvals projection
|
|
@@ -26,6 +30,7 @@ export type PendingApproval = {
|
|
|
26
30
|
id: string;
|
|
27
31
|
/** Tool/function name awaiting the decision. */
|
|
28
32
|
name: string;
|
|
33
|
+
display?: ToolDisplayMetadata;
|
|
29
34
|
arguments?: unknown;
|
|
30
35
|
/** The raw approval entry from the `session.requiresAction` payload. */
|
|
31
36
|
raw?: unknown;
|
|
@@ -49,11 +54,13 @@ export function approvalsFromRequiresAction(payload: unknown): PendingApproval[]
|
|
|
49
54
|
raw.rawItem && typeof raw.rawItem === "object"
|
|
50
55
|
? (raw.rawItem as Record<string, unknown>)
|
|
51
56
|
: {};
|
|
57
|
+
const display = parseToolDisplayMetadata(raw.display);
|
|
52
58
|
return {
|
|
53
59
|
// Mirror the runtime's canonical interruption identity before retaining
|
|
54
60
|
// the legacy top-level callId fallback for already-normalized payloads.
|
|
55
61
|
id: String(rawItem.callId ?? rawItem.id ?? raw.id ?? raw.callId ?? raw.name ?? index),
|
|
56
62
|
name: String(raw.name ?? raw.toolName ?? rawItem.name ?? "approval"),
|
|
63
|
+
...(display ? { display } : {}),
|
|
57
64
|
arguments: raw.arguments ?? rawItem.arguments,
|
|
58
65
|
raw: approval,
|
|
59
66
|
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Service marks
|
|
2
|
+
|
|
3
|
+
These provider-owned marks identify the connected service; they do not imply endorsement.
|
|
4
|
+
|
|
5
|
+
- `gmail.ico`: existing Gmail service mark.
|
|
6
|
+
- `outlook.ico`: https://outlook.live.com/favicon.ico (retrieved 2026-09-20).
|
|
7
|
+
|
|
8
|
+
The React package bundles these assets so embedding hosts do not need matching public paths or make third-party image requests for these marks.
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { ComponentPropsWithoutRef, ReactNode } from "react";
|
|
2
|
+
import { AlertTriangleIcon, CheckIcon, Loader2Icon, PlusIcon } from "lucide-react";
|
|
3
|
+
|
|
4
|
+
export type CapabilityCatalogStatus =
|
|
5
|
+
| "available"
|
|
6
|
+
| "added"
|
|
7
|
+
| "attention"
|
|
8
|
+
| "unavailable"
|
|
9
|
+
| "loading";
|
|
10
|
+
|
|
11
|
+
export type CapabilityCatalogRowProps = Omit<
|
|
12
|
+
ComponentPropsWithoutRef<"button">,
|
|
13
|
+
"children" | "onClick" | "name"
|
|
14
|
+
> & {
|
|
15
|
+
name: string;
|
|
16
|
+
description?: string | undefined;
|
|
17
|
+
icon?: ReactNode;
|
|
18
|
+
status?: CapabilityCatalogStatus;
|
|
19
|
+
statusLabel?: string | undefined;
|
|
20
|
+
/** Preserve opaque host status text when adopting this row without typed health. */
|
|
21
|
+
showStatusLabel?: boolean;
|
|
22
|
+
onOpen: () => void;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const labels: Record<CapabilityCatalogStatus, string> = {
|
|
26
|
+
available: "Available to add",
|
|
27
|
+
added: "Added",
|
|
28
|
+
attention: "Needs attention",
|
|
29
|
+
unavailable: "Unavailable",
|
|
30
|
+
loading: "Working",
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/** A display-only state. The entire catalog row is the action, never this glyph. */
|
|
34
|
+
export function CapabilityCatalogIndicator({
|
|
35
|
+
status = "available",
|
|
36
|
+
label,
|
|
37
|
+
showLabel = false,
|
|
38
|
+
}: {
|
|
39
|
+
status?: CapabilityCatalogStatus;
|
|
40
|
+
label?: string | undefined;
|
|
41
|
+
showLabel?: boolean;
|
|
42
|
+
}) {
|
|
43
|
+
const Icon =
|
|
44
|
+
status === "added"
|
|
45
|
+
? CheckIcon
|
|
46
|
+
: status === "attention" || status === "unavailable"
|
|
47
|
+
? AlertTriangleIcon
|
|
48
|
+
: status === "loading"
|
|
49
|
+
? Loader2Icon
|
|
50
|
+
: PlusIcon;
|
|
51
|
+
return (
|
|
52
|
+
<span className="og-capability-catalog-indicator" data-status={status}>
|
|
53
|
+
<Icon aria-hidden="true" />
|
|
54
|
+
<span
|
|
55
|
+
className={
|
|
56
|
+
showLabel || status === "attention" || status === "unavailable"
|
|
57
|
+
? "og-capability-catalog-notice"
|
|
58
|
+
: "og-capability-catalog-sr-only"
|
|
59
|
+
}
|
|
60
|
+
>
|
|
61
|
+
{label ?? labels[status]}
|
|
62
|
+
</span>
|
|
63
|
+
</span>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Shared by connections, skills, and plugins: one row, one focus target, one action. */
|
|
68
|
+
export function CapabilityCatalogRow({
|
|
69
|
+
name,
|
|
70
|
+
description,
|
|
71
|
+
icon,
|
|
72
|
+
status = "available",
|
|
73
|
+
statusLabel,
|
|
74
|
+
showStatusLabel = false,
|
|
75
|
+
onOpen,
|
|
76
|
+
className = "",
|
|
77
|
+
...props
|
|
78
|
+
}: CapabilityCatalogRowProps) {
|
|
79
|
+
return (
|
|
80
|
+
<button
|
|
81
|
+
{...props}
|
|
82
|
+
type="button"
|
|
83
|
+
className={`og-capability-catalog-row ${className}`}
|
|
84
|
+
onClick={onOpen}
|
|
85
|
+
>
|
|
86
|
+
{icon ? <span className="og-capability-catalog-icon">{icon}</span> : null}
|
|
87
|
+
<span className="og-capability-catalog-copy">
|
|
88
|
+
<strong>{name}</strong>
|
|
89
|
+
{description ? <span>{description}</span> : null}
|
|
90
|
+
</span>
|
|
91
|
+
<CapabilityCatalogIndicator status={status} label={statusLabel} showLabel={showStatusLabel} />
|
|
92
|
+
</button>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { CapabilityCatalogItem } from "@opengeni/sdk";
|
|
2
|
+
import gmailLogo from "./assets/gmail.ico";
|
|
3
|
+
|
|
4
|
+
/** Passive catalogue identity, shared by embedded and console surfaces. */
|
|
5
|
+
export function capabilityLogoFallback(
|
|
6
|
+
item: Pick<CapabilityCatalogItem, "id"> &
|
|
7
|
+
Partial<Pick<CapabilityCatalogItem, "metadata" | "mcpUrl">>,
|
|
8
|
+
): string | null {
|
|
9
|
+
if (
|
|
10
|
+
item.id.startsWith("mcp:integrations-sh:gmailmcp-googleapis-com-") ||
|
|
11
|
+
item.mcpUrl === "https://gmailmcp.googleapis.com/mcp/v1"
|
|
12
|
+
)
|
|
13
|
+
return gmailLogo;
|
|
14
|
+
const original = item.metadata?.originalLogoUrl;
|
|
15
|
+
if (typeof original !== "string") return null;
|
|
16
|
+
try {
|
|
17
|
+
const url = new URL(original);
|
|
18
|
+
return url.protocol === "https:" || url.protocol === "http:" ? url.href : null;
|
|
19
|
+
} catch {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
package/src/client.ts
CHANGED
|
@@ -84,15 +84,6 @@ export type SessionClientLike = Pick<
|
|
|
84
84
|
| "verifyRigChange"
|
|
85
85
|
| "promoteRigChange"
|
|
86
86
|
| "verifyRig"
|
|
87
|
-
// Packs
|
|
88
|
-
| "listPacks"
|
|
89
|
-
| "registerPack"
|
|
90
|
-
| "enablePack"
|
|
91
|
-
| "previewPackInstallation"
|
|
92
|
-
| "installPack"
|
|
93
|
-
| "previewPackUninstall"
|
|
94
|
-
| "uninstallPack"
|
|
95
|
-
| "deletePack"
|
|
96
87
|
// Workspaces + billing
|
|
97
88
|
| "listWorkspaces"
|
|
98
89
|
| "createWorkspace"
|
|
@@ -2,6 +2,7 @@ import { CheckIcon, ShieldCheckIcon, XIcon } from "lucide-react";
|
|
|
2
2
|
import { useEffect, useId, useRef, useState, type ReactNode } from "react";
|
|
3
3
|
import type { PendingApproval } from "../approvals";
|
|
4
4
|
import { cn } from "../lib/cn";
|
|
5
|
+
import { toolDisplayName } from "../timeline/tool-display-name";
|
|
5
6
|
|
|
6
7
|
export type ApprovalSurfaceMessages = {
|
|
7
8
|
title: string;
|
|
@@ -20,7 +21,10 @@ export const defaultApprovalSurfaceMessages: ApprovalSurfaceMessages = {
|
|
|
20
21
|
reject: "Reject",
|
|
21
22
|
approving: "Approving…",
|
|
22
23
|
rejecting: "Rejecting…",
|
|
23
|
-
formatToolName: (name) =>
|
|
24
|
+
formatToolName: (name) =>
|
|
25
|
+
name.includes("__") || /^[a-f0-9]{64}$/.test(name)
|
|
26
|
+
? toolDisplayName(name)
|
|
27
|
+
: name.replaceAll("_", " ").replaceAll(".", " › "),
|
|
24
28
|
};
|
|
25
29
|
|
|
26
30
|
export type ApprovalSurfaceProps = {
|
|
@@ -154,8 +158,14 @@ export function ApprovalSurface({
|
|
|
154
158
|
) : (
|
|
155
159
|
<>
|
|
156
160
|
<p className="text-og-sm font-medium text-og-fg">
|
|
157
|
-
{
|
|
161
|
+
{approval.display?.title ??
|
|
162
|
+
messages.formatToolName(approval.display?.toolName ?? approval.name)}
|
|
158
163
|
</p>
|
|
164
|
+
{approval.display?.accountLabel ? (
|
|
165
|
+
<p className="mt-1 break-words text-og-xs text-og-fg-muted">
|
|
166
|
+
{approval.display.accountLabel}
|
|
167
|
+
</p>
|
|
168
|
+
) : null}
|
|
159
169
|
{argumentsPreview !== null ? (
|
|
160
170
|
<pre className="mt-2 max-h-48 overflow-auto whitespace-pre-wrap break-words rounded-og-sm bg-og-surface-2 p-2 font-mono text-og-xs text-og-fg-muted">
|
|
161
171
|
{argumentsPreview}
|
|
@@ -1261,6 +1261,7 @@ const ParagraphLeaf = memo(
|
|
|
1261
1261
|
onKeyDown,
|
|
1262
1262
|
}: ParagraphLeafProps) {
|
|
1263
1263
|
const composing = useRef(false);
|
|
1264
|
+
const suppressNextEnter = useRef(false);
|
|
1264
1265
|
const Tag = headingTag(paragraph.style.headingLevel);
|
|
1265
1266
|
const label =
|
|
1266
1267
|
paragraph.style.list?.kind === "number"
|
|
@@ -1292,6 +1293,15 @@ const ParagraphLeaf = memo(
|
|
|
1292
1293
|
}}
|
|
1293
1294
|
onCompositionEnd={(event) => {
|
|
1294
1295
|
composing.current = false;
|
|
1296
|
+
// IME commit Enter often arrives in the same turn as compositionend.
|
|
1297
|
+
// Suppress that key so it cannot also insert a trailing newline, but
|
|
1298
|
+
// clear before the next task so a later explicit Enter still works.
|
|
1299
|
+
suppressNextEnter.current = true;
|
|
1300
|
+
queueMicrotask(() => {
|
|
1301
|
+
suppressNextEnter.current = false;
|
|
1302
|
+
});
|
|
1303
|
+
syncTrailingBreak(event.currentTarget);
|
|
1304
|
+
stabilizeCaretAfterTrailingNewline(event.currentTarget);
|
|
1295
1305
|
onInput(paragraph, event.currentTarget.textContent ?? "");
|
|
1296
1306
|
onSelection(paragraph);
|
|
1297
1307
|
}}
|
|
@@ -1316,15 +1326,18 @@ const ParagraphLeaf = memo(
|
|
|
1316
1326
|
onKeyDown={(event) => {
|
|
1317
1327
|
onKeyDown(event, paragraph);
|
|
1318
1328
|
if (event.defaultPrevented || readOnly) return;
|
|
1319
|
-
if (event.key
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1329
|
+
if (event.key !== "Enter" || event.metaKey || event.ctrlKey || event.altKey) return;
|
|
1330
|
+
if (isDocumentImeComposing(event, composing.current)) return;
|
|
1331
|
+
event.preventDefault();
|
|
1332
|
+
if (suppressNextEnter.current) return;
|
|
1333
|
+
insertPlainText(event.currentTarget, "\n");
|
|
1334
|
+
onInput(paragraph, event.currentTarget.textContent ?? "");
|
|
1335
|
+
onSelection(paragraph);
|
|
1325
1336
|
}}
|
|
1326
1337
|
onInput={(event) => {
|
|
1327
1338
|
if (!composing.current && !(event.nativeEvent as InputEvent).isComposing) {
|
|
1339
|
+
syncTrailingBreak(event.currentTarget);
|
|
1340
|
+
stabilizeCaretAfterTrailingNewline(event.currentTarget);
|
|
1328
1341
|
onInput(paragraph, event.currentTarget.textContent ?? "");
|
|
1329
1342
|
}
|
|
1330
1343
|
}}
|
|
@@ -1348,6 +1361,9 @@ const ParagraphLeaf = memo(
|
|
|
1348
1361
|
{segment.text}
|
|
1349
1362
|
</span>
|
|
1350
1363
|
))}
|
|
1364
|
+
{segments.at(-1)?.text.endsWith("\n") ? (
|
|
1365
|
+
<br data-og-trailing-break="" aria-hidden="true" />
|
|
1366
|
+
) : null}
|
|
1351
1367
|
</Tag>
|
|
1352
1368
|
);
|
|
1353
1369
|
},
|
|
@@ -1753,6 +1769,45 @@ function selectionOffsets(root: HTMLElement | undefined): { start: number; end:
|
|
|
1753
1769
|
};
|
|
1754
1770
|
}
|
|
1755
1771
|
|
|
1772
|
+
const TRAILING_BREAK_ATTR = "data-og-trailing-break";
|
|
1773
|
+
|
|
1774
|
+
function isDocumentImeComposing(
|
|
1775
|
+
event: ReactKeyboardEvent<HTMLElement>,
|
|
1776
|
+
composing: boolean,
|
|
1777
|
+
): boolean {
|
|
1778
|
+
const native = event.nativeEvent;
|
|
1779
|
+
return composing || native.isComposing === true || native.keyCode === 229;
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
function syncTrailingBreak(root: HTMLElement): void {
|
|
1783
|
+
const existing = root.querySelector(`br[${TRAILING_BREAK_ATTR}]`);
|
|
1784
|
+
const needsBreak = (root.textContent ?? "").endsWith("\n");
|
|
1785
|
+
if (needsBreak && !existing) {
|
|
1786
|
+
const br = globalThis.document.createElement("br");
|
|
1787
|
+
br.setAttribute(TRAILING_BREAK_ATTR, "");
|
|
1788
|
+
br.setAttribute("aria-hidden", "true");
|
|
1789
|
+
root.appendChild(br);
|
|
1790
|
+
} else if (!needsBreak && existing) {
|
|
1791
|
+
existing.remove();
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1795
|
+
function stabilizeCaretAfterTrailingNewline(root: HTMLElement): void {
|
|
1796
|
+
const text = root.textContent ?? "";
|
|
1797
|
+
if (!text.endsWith("\n")) return;
|
|
1798
|
+
const selection = globalThis.getSelection?.();
|
|
1799
|
+
if (!selection || selection.rangeCount === 0 || !selection.isCollapsed) return;
|
|
1800
|
+
const offsets = selectionOffsets(root);
|
|
1801
|
+
if (!offsets || offsets.start !== text.length) return;
|
|
1802
|
+
const br = root.querySelector(`br[${TRAILING_BREAK_ATTR}]`);
|
|
1803
|
+
if (!br) return;
|
|
1804
|
+
const range = globalThis.document.createRange();
|
|
1805
|
+
range.setStartBefore(br);
|
|
1806
|
+
range.collapse(true);
|
|
1807
|
+
selection.removeAllRanges();
|
|
1808
|
+
selection.addRange(range);
|
|
1809
|
+
}
|
|
1810
|
+
|
|
1756
1811
|
function insertPlainText(root: HTMLElement, text: string): void {
|
|
1757
1812
|
const selection = globalThis.getSelection?.();
|
|
1758
1813
|
if (!selection || selection.rangeCount === 0) return;
|
|
@@ -1761,10 +1816,12 @@ function insertPlainText(root: HTMLElement, text: string): void {
|
|
|
1761
1816
|
range.deleteContents();
|
|
1762
1817
|
const node = globalThis.document.createTextNode(text);
|
|
1763
1818
|
range.insertNode(node);
|
|
1819
|
+
syncTrailingBreak(root);
|
|
1764
1820
|
range.setStartAfter(node);
|
|
1765
1821
|
range.collapse(true);
|
|
1766
1822
|
selection.removeAllRanges();
|
|
1767
1823
|
selection.addRange(range);
|
|
1824
|
+
stabilizeCaretAfterTrailingNewline(root);
|
|
1768
1825
|
}
|
|
1769
1826
|
|
|
1770
1827
|
function restoreSelection(
|