@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.
Files changed (214) hide show
  1. package/README.md +83 -2
  2. package/dist/approvals.d.ts +2 -1
  3. package/dist/artifacts-document.js +1 -1
  4. package/dist/artifacts-presentation.js +1 -1
  5. package/dist/artifacts-spreadsheet.js +1 -1
  6. package/dist/artifacts.js +3 -3
  7. package/dist/{browser-viewer-NTD6UIPR.js → browser-viewer-LGH4IP47.js} +3 -3
  8. package/dist/capability-catalog-row.d.ts +20 -0
  9. package/dist/capability-logo-fallback.d.ts +3 -0
  10. package/dist/{chunk-NOSYBS2D.js → chunk-2VHARTBL.js} +2 -1
  11. package/dist/{chunk-VRBL3F5E.js → chunk-5GAL23FF.js} +10 -2
  12. package/dist/{chunk-VRBL3F5E.js.map → chunk-5GAL23FF.js.map} +1 -1
  13. package/dist/chunk-5UONOQ3Y.js +635 -0
  14. package/dist/chunk-5UONOQ3Y.js.map +1 -0
  15. package/dist/{chunk-NYESIADM.js → chunk-AKOMC3VO.js} +3 -3
  16. package/dist/chunk-AKOMC3VO.js.map +1 -0
  17. package/dist/chunk-BRM6FVZA.js +302 -0
  18. package/dist/chunk-BRM6FVZA.js.map +1 -0
  19. package/dist/{chunk-KANFU34B.js → chunk-DBPVUGQT.js} +11 -2
  20. package/dist/chunk-DBPVUGQT.js.map +1 -0
  21. package/dist/chunk-FHIGTPME.js +1589 -0
  22. package/dist/chunk-FHIGTPME.js.map +1 -0
  23. package/dist/{chunk-5M6VTFJ5.js → chunk-GBPCZH3Y.js} +2 -2
  24. package/dist/{chunk-YBM6CQRU.js → chunk-GEN54DU5.js} +4 -4
  25. package/dist/{chunk-UMECRJRV.js → chunk-HJ5VJ4JB.js} +21 -12
  26. package/dist/chunk-HJ5VJ4JB.js.map +1 -0
  27. package/dist/{chunk-R4KRSFGA.js → chunk-IP4BUBKH.js} +3 -3
  28. package/dist/{chunk-NLTS7JHI.js → chunk-JPHDWKZE.js} +5 -5
  29. package/dist/{chunk-TDSEILUH.js → chunk-MI6ALLLD.js} +1297 -1535
  30. package/dist/chunk-MI6ALLLD.js.map +1 -0
  31. package/dist/{chunk-ICA6R6TW.js → chunk-OWHPKAOV.js} +28 -20
  32. package/dist/chunk-OWHPKAOV.js.map +1 -0
  33. package/dist/{chunk-24M4YBCL.js → chunk-PNAVEK2U.js} +4 -4
  34. package/dist/{chunk-L2NBTKRX.js → chunk-TXCBE32L.js} +203 -19
  35. package/dist/chunk-TXCBE32L.js.map +1 -0
  36. package/dist/{chunk-45XEUVTK.js → chunk-UXE5SSNN.js} +293 -463
  37. package/dist/chunk-UXE5SSNN.js.map +1 -0
  38. package/dist/{chunk-PEI6RANI.js → chunk-VR4Z73EU.js} +203 -9
  39. package/dist/chunk-VR4Z73EU.js.map +1 -0
  40. package/dist/{chunk-HUIKIDM5.js → chunk-XMXRI5JK.js} +65 -18
  41. package/dist/chunk-XMXRI5JK.js.map +1 -0
  42. package/dist/client.d.ts +1 -1
  43. package/dist/components/artifacts/spreadsheet-general-display.d.ts +24 -0
  44. package/dist/components/chat-composer.d.ts +13 -3
  45. package/dist/components/markdown.d.ts +6 -3
  46. package/dist/components/message-timeline.d.ts +7 -2
  47. package/dist/components/preview-loading.d.ts +2 -0
  48. package/dist/components/session-capability-frame.d.ts +24 -0
  49. package/dist/components/session-chrome.d.ts +1 -2
  50. package/dist/components/session-commands.d.ts +6 -0
  51. package/dist/components/session-connection-request.d.ts +8 -0
  52. package/dist/components/session-conversation.d.ts +3 -0
  53. package/dist/components/session-mcp-capability-card.d.ts +22 -0
  54. package/dist/components/timeline-search.d.ts +34 -0
  55. package/dist/composer.js +7 -7
  56. package/dist/connect-account-identity.d.ts +8 -0
  57. package/dist/connect-accounts.d.ts +5 -0
  58. package/dist/connect-chooser.d.ts +6 -0
  59. package/dist/connect-panel.d.ts +9 -2
  60. package/dist/connect-setup.d.ts +5 -1
  61. package/dist/connect.d.ts +5 -21
  62. package/dist/connect.js +1268 -584
  63. package/dist/connect.js.map +1 -1
  64. package/dist/connection-catalog.d.ts +6 -1
  65. package/dist/connection-discovery.d.ts +12 -0
  66. package/dist/connection-installed.d.ts +1 -0
  67. package/dist/connection-logo.d.ts +5 -2
  68. package/dist/connection-service-logo.d.ts +8 -0
  69. package/dist/connection-service-presentation.d.ts +13 -0
  70. package/dist/connection-skeleton.d.ts +5 -0
  71. package/dist/discovery-cache.d.ts +5 -0
  72. package/dist/hooks/use-codex-accounts.d.ts +11 -5
  73. package/dist/hooks/use-connect.d.ts +22 -0
  74. package/dist/hooks/use-session-events.d.ts +5 -0
  75. package/dist/hooks/use-session-mcp-approval-policy.d.ts +2 -2
  76. package/dist/hooks/use-workspace-sessions.d.ts +2 -0
  77. package/dist/index.d.ts +8 -2
  78. package/dist/index.js +771 -793
  79. package/dist/index.js.map +1 -1
  80. package/dist/interaction.js +2 -2
  81. package/dist/machines.js +2 -2
  82. package/dist/mcp-connection-status.d.ts +14 -0
  83. package/dist/{model-policy-picker-menu-3R336DP2.js → model-policy-picker-menu-RVOQ4ZZG.js} +4 -4
  84. package/dist/model-policy.d.ts +6 -2
  85. package/dist/model-policy.js +1 -1
  86. package/dist/{platform-activity-row-DUE2W74J.js → platform-activity-row-HLOH7FW4.js} +9 -4
  87. package/dist/platform-activity-row-HLOH7FW4.js.map +1 -0
  88. package/dist/plugin-discovery.d.ts +6 -0
  89. package/dist/{queue-surface-implementation-LK3S4BIW.js → queue-surface-implementation-3RIFK2BS.js} +4 -4
  90. package/dist/realtime.js +22 -22
  91. package/dist/realtime.js.map +1 -1
  92. package/dist/session-auth-recommendation.d.ts +5 -0
  93. package/dist/session-capability-policy.d.ts +12 -0
  94. package/dist/session-ui.d.ts +2 -0
  95. package/dist/session-ui.js +14 -12
  96. package/dist/session.d.ts +1 -0
  97. package/dist/session.js +6 -4
  98. package/dist/skill-discovery.d.ts +11 -0
  99. package/dist/timeline/compaction-copy.d.ts +10 -0
  100. package/dist/timeline/projection.d.ts +3 -1
  101. package/dist/timeline/tool-display-name.d.ts +2 -1
  102. package/dist/timeline/turn-summary.d.ts +2 -2
  103. package/dist/timeline/types.d.ts +24 -2
  104. package/dist/{timeline-annotation-markers-DRSTLEM6.js → timeline-annotation-markers-OY6OWR3V.js} +2 -2
  105. package/dist/{timeline-annotation-selection-IHLUGVND.js → timeline-annotation-selection-BOXA2TIN.js} +2 -2
  106. package/dist/{timeline-annotations-dialog-6Q53N5FG.js → timeline-annotations-dialog-RGY3MHL3.js} +3 -3
  107. package/package.json +3 -3
  108. package/src/approvals.ts +8 -1
  109. package/src/assets/README.md +8 -0
  110. package/src/assets/gmail.ico +0 -0
  111. package/src/assets/outlook.ico +0 -0
  112. package/src/capability-catalog-row.tsx +94 -0
  113. package/src/capability-logo-fallback.ts +22 -0
  114. package/src/client.ts +0 -9
  115. package/src/components/approval-surface.tsx +12 -2
  116. package/src/components/artifacts/document-editor.tsx +63 -6
  117. package/src/components/artifacts/presentation-editor.tsx +214 -9
  118. package/src/components/artifacts/spreadsheet-canvas.ts +3 -8
  119. package/src/components/artifacts/spreadsheet-general-display.ts +43 -0
  120. package/src/components/artifacts/spreadsheet-grid.tsx +10 -11
  121. package/src/components/chat-composer.tsx +26 -3
  122. package/src/components/composer.tsx +10 -4
  123. package/src/components/human-input-form.tsx +12 -2
  124. package/src/components/markdown.tsx +133 -9
  125. package/src/components/message-timeline.tsx +104 -36
  126. package/src/components/model-picker.tsx +11 -3
  127. package/src/components/model-policy-picker-menu.tsx +10 -3
  128. package/src/components/preview-loading.tsx +154 -0
  129. package/src/components/sandbox-workspace.tsx +20 -36
  130. package/src/components/session-capability-frame.tsx +163 -0
  131. package/src/components/session-chrome.tsx +46 -77
  132. package/src/components/session-commands.tsx +18 -0
  133. package/src/components/session-connection-request.tsx +97 -0
  134. package/src/components/session-conversation.tsx +10 -5
  135. package/src/components/session-mcp-capability-card.tsx +532 -0
  136. package/src/components/session-status.tsx +2 -2
  137. package/src/components/timeline-anchor.tsx +9 -8
  138. package/src/components/timeline-search.tsx +168 -0
  139. package/src/components/user-message-body.tsx +7 -0
  140. package/src/connect-account-identity.tsx +34 -0
  141. package/src/connect-accounts.tsx +114 -52
  142. package/src/connect-chooser.tsx +171 -39
  143. package/src/connect-panel.tsx +73 -9
  144. package/src/connect-setup.tsx +72 -25
  145. package/src/connect.ts +13 -22
  146. package/src/connection-assets.d.ts +4 -0
  147. package/src/connection-catalog.tsx +61 -39
  148. package/src/connection-discovery.tsx +235 -0
  149. package/src/connection-installed.tsx +2 -0
  150. package/src/connection-logo.tsx +18 -10
  151. package/src/connection-service-logo.tsx +55 -0
  152. package/src/connection-service-presentation.ts +46 -0
  153. package/src/connection-skeleton.tsx +16 -0
  154. package/src/conversation-timeline.ts +1 -0
  155. package/src/discovery-cache.ts +42 -0
  156. package/src/hooks/use-codex-accounts.ts +33 -14
  157. package/src/hooks/use-composer.ts +4 -5
  158. package/src/hooks/use-connect.ts +23 -0
  159. package/src/hooks/use-session-events.ts +114 -1
  160. package/src/hooks/use-session-mcp-approval-policy.ts +13 -5
  161. package/src/hooks/use-workspace-sessions.ts +10 -0
  162. package/src/index.ts +22 -2
  163. package/src/mcp-connection-status.ts +35 -0
  164. package/src/model-policy.ts +21 -0
  165. package/src/plugin-details.tsx +8 -5
  166. package/src/plugin-discovery.tsx +92 -72
  167. package/src/realtime/realtime-control.tsx +6 -8
  168. package/src/session-auth-recommendation.ts +48 -0
  169. package/src/session-capability-policy.ts +83 -0
  170. package/src/session-ui.ts +2 -0
  171. package/src/session.ts +1 -0
  172. package/src/skill-discovery.tsx +101 -56
  173. package/src/timeline/compaction-copy.ts +40 -0
  174. package/src/timeline/platform-activity-row.tsx +8 -3
  175. package/src/timeline/projection.ts +78 -2
  176. package/src/timeline/rolling-activity.tsx +4 -2
  177. package/src/timeline/shared.tsx +6 -1
  178. package/src/timeline/startup-timings.tsx +1 -1
  179. package/src/timeline/tool-display-name.ts +8 -6
  180. package/src/timeline/tool-renderers.tsx +5 -3
  181. package/src/timeline/turn-summary.tsx +17 -3
  182. package/src/timeline/types.ts +24 -2
  183. package/styles/compiled.css +325 -27
  184. package/styles/connect.css +90 -15
  185. package/styles/index.css +46 -0
  186. package/styles/session-capability.css +42 -0
  187. package/dist/chunk-45XEUVTK.js.map +0 -1
  188. package/dist/chunk-HQV2I5HV.js +0 -124
  189. package/dist/chunk-HQV2I5HV.js.map +0 -1
  190. package/dist/chunk-HUIKIDM5.js.map +0 -1
  191. package/dist/chunk-ICA6R6TW.js.map +0 -1
  192. package/dist/chunk-IHQII5WO.js +0 -886
  193. package/dist/chunk-IHQII5WO.js.map +0 -1
  194. package/dist/chunk-KANFU34B.js.map +0 -1
  195. package/dist/chunk-L2NBTKRX.js.map +0 -1
  196. package/dist/chunk-NYESIADM.js.map +0 -1
  197. package/dist/chunk-PEI6RANI.js.map +0 -1
  198. package/dist/chunk-TDSEILUH.js.map +0 -1
  199. package/dist/chunk-UMECRJRV.js.map +0 -1
  200. package/dist/hooks/use-packs.d.ts +0 -32
  201. package/dist/platform-activity-row-DUE2W74J.js.map +0 -1
  202. package/src/hooks/use-packs.ts +0 -157
  203. /package/dist/{browser-viewer-NTD6UIPR.js.map → browser-viewer-LGH4IP47.js.map} +0 -0
  204. /package/dist/{chunk-NOSYBS2D.js.map → chunk-2VHARTBL.js.map} +0 -0
  205. /package/dist/{chunk-5M6VTFJ5.js.map → chunk-GBPCZH3Y.js.map} +0 -0
  206. /package/dist/{chunk-YBM6CQRU.js.map → chunk-GEN54DU5.js.map} +0 -0
  207. /package/dist/{chunk-R4KRSFGA.js.map → chunk-IP4BUBKH.js.map} +0 -0
  208. /package/dist/{chunk-NLTS7JHI.js.map → chunk-JPHDWKZE.js.map} +0 -0
  209. /package/dist/{chunk-24M4YBCL.js.map → chunk-PNAVEK2U.js.map} +0 -0
  210. /package/dist/{model-policy-picker-menu-3R336DP2.js.map → model-policy-picker-menu-RVOQ4ZZG.js.map} +0 -0
  211. /package/dist/{queue-surface-implementation-LK3S4BIW.js.map → queue-surface-implementation-3RIFK2BS.js.map} +0 -0
  212. /package/dist/{timeline-annotation-markers-DRSTLEM6.js.map → timeline-annotation-markers-OY6OWR3V.js.map} +0 -0
  213. /package/dist/{timeline-annotation-selection-IHLUGVND.js.map → timeline-annotation-selection-BOXA2TIN.js.map} +0 -0
  214. /package/dist/{timeline-annotations-dialog-6Q53N5FG.js.map → timeline-annotations-dialog-RGY3MHL3.js.map} +0 -0
@@ -0,0 +1,635 @@
1
+ import {
2
+ usePortalTokenStyle
3
+ } from "./chunk-VZTQ73XT.js";
4
+
5
+ // src/hooks/use-connect.ts
6
+ import { useMemo, useSyncExternalStore } from "react";
7
+ function useConnect(controller) {
8
+ const snapshot = useSyncExternalStore(
9
+ controller.subscribe,
10
+ controller.getSnapshot,
11
+ controller.getSnapshot
12
+ );
13
+ const actions = useMemo(
14
+ () => ({
15
+ begin: controller.begin.bind(controller),
16
+ recover: controller.recover.bind(controller),
17
+ refresh: controller.refresh.bind(controller),
18
+ waitForAction: controller.waitForAction.bind(controller),
19
+ advance: controller.advance.bind(controller),
20
+ cancel: controller.cancel.bind(controller)
21
+ }),
22
+ [controller]
23
+ );
24
+ return useMemo(() => ({ ...snapshot, ...actions }), [snapshot, actions]);
25
+ }
26
+
27
+ // src/session-capability-policy.ts
28
+ function sessionCapabilityTools(item) {
29
+ const serverId = item.kind === "mcp" ? item.runtime?.mcpServerId : void 0;
30
+ return serverId && !item.tools.some((tool) => tool.kind === "mcp" && tool.id === serverId) ? [...item.tools, { kind: "mcp", id: serverId }] : item.tools;
31
+ }
32
+ async function attachSessionCapability(client, workspaceId, sessionId, item, stillCurrent = () => true) {
33
+ const tools = sessionCapabilityTools(item);
34
+ if (item.kind === "skill" || tools.length === 0) return;
35
+ if (!stillCurrent()) throw new Error("Connection setup was interrupted.");
36
+ const session = await client.getSession(workspaceId, sessionId);
37
+ if (!stillCurrent()) throw new Error("Connection setup was interrupted.");
38
+ let existing = session.tools.filter(
39
+ (tool) => !session.effectiveToolPolicy?.mandatoryIds?.includes(tool.id)
40
+ );
41
+ if (session.toolPolicy.mode === "workspace_default") {
42
+ const policy = session.effectiveToolPolicy;
43
+ if (!policy || policy.idsTruncated)
44
+ throw new Error(
45
+ "Connected, but the full session tool selection could not be read. Review the Tools picker before continuing."
46
+ );
47
+ existing = policy.effectiveIds.filter((id) => !policy.mandatoryIds.includes(id)).map((id) => ({ kind: "mcp", id }));
48
+ }
49
+ const additions = tools.filter(
50
+ (tool) => !existing.some((current) => current.kind === tool.kind && current.id === tool.id)
51
+ );
52
+ const recommended = Array.isArray(item.metadata?.firstPartyMcpTools) ? item.metadata.firstPartyMcpTools.filter(
53
+ (name) => typeof name === "string"
54
+ ) : [];
55
+ const firstParty = [.../* @__PURE__ */ new Set([...session.firstPartyMcpTools, ...recommended])];
56
+ if (additions.length === 0 && firstParty.length === session.firstPartyMcpTools.length) return;
57
+ await client.updateSessionToolPolicy(workspaceId, sessionId, {
58
+ mode: "explicit",
59
+ tools: [...existing, ...additions],
60
+ firstPartyMcpTools: firstParty,
61
+ expectedVersion: session.toolPolicyVersion
62
+ });
63
+ }
64
+ async function completeSessionCapabilityOAuth(client, workspaceId, sessionId, capabilityId) {
65
+ if (!capabilityId)
66
+ throw new Error(
67
+ "The authorized integration could not be identified. Review its connection card to finish setup."
68
+ );
69
+ const connected = (await client.listCapabilities(workspaceId)).items.find(
70
+ (item) => item.id === capabilityId
71
+ );
72
+ if (!connected?.enabled)
73
+ throw new Error("The connection was authorized, but enabling its tools could not be verified.");
74
+ await attachSessionCapability(client, workspaceId, sessionId, connected);
75
+ }
76
+
77
+ // src/components/session-capability-frame.tsx
78
+ import { CheckIcon, ShieldCheckIcon, XIcon } from "lucide-react";
79
+ import { Dialog } from "radix-ui";
80
+ import { useRef, useState } from "react";
81
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
82
+ function Mark({ src, name }) {
83
+ const [failed, setFailed] = useState(null);
84
+ return /* @__PURE__ */ jsx("span", { className: "og-session-capability-logo", "aria-hidden": true, children: src && failed !== src ? /* @__PURE__ */ jsx("img", { src, alt: "", loading: "lazy", decoding: "async", onError: () => setFailed(src) }) : name.trim().slice(0, 2).toUpperCase() });
85
+ }
86
+ function SessionCapabilityFrame({
87
+ name,
88
+ subtitle,
89
+ logo,
90
+ typeLabel,
91
+ description,
92
+ skill,
93
+ expanded,
94
+ complete,
95
+ actionLabel,
96
+ note,
97
+ onOpen,
98
+ onClose,
99
+ busy = false,
100
+ opener,
101
+ cardRef,
102
+ children,
103
+ dialogOnly = false
104
+ }) {
105
+ const localOpener = useRef(null);
106
+ const localCard = useRef(null);
107
+ const buttonRef = opener ?? localOpener;
108
+ const sectionRef = cardRef ?? localCard;
109
+ const portalStyle = usePortalTokenStyle(sectionRef.current);
110
+ const identity = /* @__PURE__ */ jsxs(Fragment, { children: [
111
+ /* @__PURE__ */ jsx(Mark, { src: logo, name }),
112
+ /* @__PURE__ */ jsxs("div", { className: "og-session-capability-identity", children: [
113
+ /* @__PURE__ */ jsx("h3", { children: name }),
114
+ /* @__PURE__ */ jsx("span", { children: subtitle })
115
+ ] }),
116
+ /* @__PURE__ */ jsx("span", { className: "og-session-capability-type", children: typeLabel })
117
+ ] });
118
+ return /* @__PURE__ */ jsxs("div", { className: "og-session-capability", children: [
119
+ /* @__PURE__ */ jsxs(
120
+ "section",
121
+ {
122
+ hidden: dialogOnly,
123
+ style: dialogOnly ? { display: "none" } : void 0,
124
+ ref: sectionRef,
125
+ tabIndex: -1,
126
+ "aria-label": `${name} setup`,
127
+ "data-state": complete ? "complete" : expanded ? "setup" : "suggested",
128
+ className: "og-session-capability-shell",
129
+ children: [
130
+ /* @__PURE__ */ jsxs("div", { className: "og-session-capability-header", children: [
131
+ identity,
132
+ complete ? /* @__PURE__ */ jsx(CheckIcon, { size: 16, "aria-hidden": true }) : null
133
+ ] }),
134
+ complete ? /* @__PURE__ */ jsx("p", { role: "status", className: "og-session-capability-copy", children: skill ? "Installed \xB7 Workspace" : "Connected \xB7 Available in this conversation" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
135
+ /* @__PURE__ */ jsx("p", { className: "og-session-capability-copy", children: description }),
136
+ /* @__PURE__ */ jsxs("div", { className: "og-session-capability-actions", children: [
137
+ /* @__PURE__ */ jsxs("span", { children: [
138
+ /* @__PURE__ */ jsx(ShieldCheckIcon, { size: 13, "aria-hidden": true }),
139
+ skill ? "Guidance only \xB7 no account access" : "You choose what to authorize"
140
+ ] }),
141
+ /* @__PURE__ */ jsx(
142
+ "button",
143
+ {
144
+ ref: buttonRef,
145
+ type: "button",
146
+ onClick: onOpen,
147
+ "aria-haspopup": "dialog",
148
+ "aria-expanded": expanded,
149
+ children: actionLabel
150
+ }
151
+ )
152
+ ] })
153
+ ] })
154
+ ]
155
+ }
156
+ ),
157
+ !complete && !dialogOnly ? /* @__PURE__ */ jsx("p", { className: "og-session-capability-note", children: note }) : null,
158
+ /* @__PURE__ */ jsx(
159
+ Dialog.Root,
160
+ {
161
+ open: expanded && !complete,
162
+ onOpenChange: (open) => {
163
+ if (!open && !busy) onClose();
164
+ },
165
+ children: /* @__PURE__ */ jsxs(Dialog.Portal, { children: [
166
+ /* @__PURE__ */ jsx(Dialog.Overlay, { className: "og-root og-session-capability-overlay", style: portalStyle }),
167
+ /* @__PURE__ */ jsxs(
168
+ Dialog.Content,
169
+ {
170
+ className: "og-root og-session-capability-dialog",
171
+ style: portalStyle,
172
+ onEscapeKeyDown: (event) => {
173
+ if (busy) event.preventDefault();
174
+ },
175
+ onInteractOutside: (event) => {
176
+ if (busy) event.preventDefault();
177
+ },
178
+ onCloseAutoFocus: (event) => {
179
+ event.preventDefault();
180
+ const target = buttonRef.current?.isConnected ? buttonRef.current : sectionRef.current;
181
+ if (target?.isConnected) target.focus();
182
+ },
183
+ children: [
184
+ /* @__PURE__ */ jsxs("div", { className: "og-session-capability-dialog-header", children: [
185
+ /* @__PURE__ */ jsx(Mark, { src: logo, name }),
186
+ /* @__PURE__ */ jsxs("div", { children: [
187
+ /* @__PURE__ */ jsx(Dialog.Title, { children: name }),
188
+ /* @__PURE__ */ jsxs(Dialog.Description, { children: [
189
+ typeLabel,
190
+ subtitle ? ` \xB7 ${subtitle}` : ""
191
+ ] })
192
+ ] }),
193
+ !busy ? /* @__PURE__ */ jsx(Dialog.Close, { "aria-label": "Close connection setup", children: /* @__PURE__ */ jsx(XIcon, { size: 18 }) }) : null
194
+ ] }),
195
+ /* @__PURE__ */ jsx("div", { className: "og-session-capability-dialog-body", children })
196
+ ]
197
+ }
198
+ )
199
+ ] })
200
+ }
201
+ )
202
+ ] });
203
+ }
204
+
205
+ // src/components/session-mcp-capability-card.tsx
206
+ import {
207
+ authorizeConnectAttempt,
208
+ ConnectController,
209
+ createBrowserConnectNavigation,
210
+ reserveBrowserConnectNavigation
211
+ } from "@opengeni/connect";
212
+ import { useEffect, useRef as useRef2, useState as useState2 } from "react";
213
+
214
+ // src/mcp-connection-status.ts
215
+ function matchingActiveMcpConnections(item, connections) {
216
+ return matchingMcpConnections(item, connections).filter((entry) => entry.status === "active");
217
+ }
218
+ function matchingMcpConnections(item, connections) {
219
+ const ref = item.connectionRef;
220
+ if (!item.enabled || !ref) return [];
221
+ return connections.filter(
222
+ (entry) => entry.status !== "revoked" && entry.kind === "oauth2" && entry.metadata.mcpUrl === (item.mcpUrl ?? item.endpointUrl) && (ref.subjectScope !== "subject" ? entry.id === ref.connectionId && entry.subjectId === null : entry.subjectId !== null)
223
+ );
224
+ }
225
+ function mcpConnectionDiscoveryState(item, connections) {
226
+ const matching = matchingMcpConnections(item, connections);
227
+ const active = matching.filter((entry) => entry.status === "active");
228
+ if (active.length === 1) return { status: "added", label: "Connected" };
229
+ if (matching.length > 0) return { status: "attention", label: "Review connection" };
230
+ return { status: "available", label: "Connect" };
231
+ }
232
+
233
+ // src/components/session-mcp-capability-card.tsx
234
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
235
+ function SessionMcpCapabilityCard(props) {
236
+ return /* @__PURE__ */ jsx2(McpConnectionCard, { ...props });
237
+ }
238
+ function McpConnectionCard(props) {
239
+ const [client, setClient] = useState2(props.client);
240
+ const [generation, setGeneration] = useState2(0);
241
+ if (client !== props.client) {
242
+ setClient(props.client);
243
+ setGeneration(generation + 1);
244
+ }
245
+ return /* @__PURE__ */ jsx2(
246
+ ScopedCard,
247
+ {
248
+ ...props
249
+ },
250
+ `${generation}:${props.workspaceId}:${props.sessionId}:${props.capabilityId}`
251
+ );
252
+ }
253
+ function ScopedCard({
254
+ client,
255
+ workspaceId,
256
+ sessionId,
257
+ capabilityId,
258
+ name,
259
+ rationale = "",
260
+ returnUrl,
261
+ onConfigured,
262
+ dialogOnly = false,
263
+ onClose
264
+ }) {
265
+ const [controller] = useState2(
266
+ () => new ConnectController(client.connectTransport(), workspaceId)
267
+ );
268
+ const view = useConnect(controller);
269
+ const [item, setItem] = useState2(null);
270
+ const [logo, setLogo] = useState2(null);
271
+ const [expanded, setExpanded] = useState2(dialogOnly);
272
+ const [complete, setComplete] = useState2(false);
273
+ const [connected, setConnected] = useState2(false);
274
+ const [waiting, setWaiting] = useState2(false);
275
+ const [busy, setBusy] = useState2(false);
276
+ const [error, setError] = useState2(null);
277
+ const [ownership, setOwnership] = useState2("workspace");
278
+ const lifetime = useRef2(null);
279
+ const operation = useRef2(false);
280
+ const startKey = useRef2(crypto.randomUUID());
281
+ const advanceKey = useRef2(crypto.randomUUID());
282
+ const storageKey = sessionId ? `opengeni:session-connect:${workspaceId}:${sessionId}:${capabilityId}` : `opengeni:workspace-connect:${workspaceId}:${capabilityId}`;
283
+ const current = () => !!lifetime.current && !lifetime.current.signal.aborted;
284
+ async function load() {
285
+ const invocation = lifetime.current;
286
+ const [catalog, session] = await Promise.all([
287
+ client.listCapabilities(workspaceId),
288
+ sessionId ? client.getSession(workspaceId, sessionId) : Promise.resolve(null)
289
+ ]);
290
+ if (!invocation || invocation.signal.aborted || lifetime.current !== invocation) return null;
291
+ const resolved = catalog.items.find((entry) => entry.id === capabilityId);
292
+ if (!resolved || resolved.kind !== "mcp" || resolved.authKind !== "oauth2")
293
+ throw new Error(
294
+ "This recommendation is not an available OAuth MCP integration. Review the current connection catalog."
295
+ );
296
+ setItem(resolved);
297
+ if (resolved.connectionRef)
298
+ setOwnership(resolved.connectionRef.subjectScope === "subject" ? "personal" : "workspace");
299
+ else if (!item && resolved.metadata?.defaultConnectionOwnership === "personal")
300
+ setOwnership("personal");
301
+ let accountReady = false;
302
+ if (resolved.enabled && resolved.connectionRef) {
303
+ const connections = resolved.connectionRef.subjectScope === "subject" ? await client.listOwnConnectionAccounts(workspaceId) : await client.listConnections(workspaceId);
304
+ if (invocation.signal.aborted || lifetime.current !== invocation) return null;
305
+ const matches = matchingActiveMcpConnections(resolved, connections);
306
+ accountReady = matches.length === 1;
307
+ }
308
+ if (invocation.signal.aborted || lifetime.current !== invocation) return null;
309
+ const selected = session?.toolPolicy.mode === "workspace_default" ? session.effectiveToolPolicy?.selectedIds : session?.tools.filter((tool) => tool.kind === "mcp").map((tool) => tool.id);
310
+ setConnected(accountReady);
311
+ setComplete(
312
+ accountReady && !!selected && sessionCapabilityTools(resolved).every((tool) => selected.includes(tool.id))
313
+ );
314
+ return resolved;
315
+ }
316
+ useEffect(() => {
317
+ const abort = new AbortController();
318
+ lifetime.current = abort;
319
+ if (dialogOnly) setBusy(true);
320
+ void (async () => {
321
+ await load();
322
+ if (abort.signal.aborted || !dialogOnly) return;
323
+ await recoverSavedAttempt();
324
+ })().catch((failure) => {
325
+ if (!abort.signal.aborted)
326
+ setError(
327
+ failure instanceof Error ? failure.message : "Couldn't load connection details."
328
+ );
329
+ }).finally(() => {
330
+ if (!abort.signal.aborted && dialogOnly) setBusy(false);
331
+ });
332
+ return () => {
333
+ abort.abort();
334
+ };
335
+ }, [client, workspaceId, sessionId, capabilityId, dialogOnly]);
336
+ useEffect(() => {
337
+ const path = item?.logoAssetPath;
338
+ setLogo(null);
339
+ if (!path?.startsWith("catalog-assets/")) return;
340
+ const abort = new AbortController();
341
+ let objectUrl = null;
342
+ void client.downloadCatalogAsset(path, { signal: abort.signal }).then((blob) => {
343
+ if (abort.signal.aborted || !blob.type.startsWith("image/") || blob.size > 2e6)
344
+ return;
345
+ objectUrl = URL.createObjectURL(blob);
346
+ setLogo(objectUrl);
347
+ }).catch(() => {
348
+ });
349
+ return () => {
350
+ abort.abort();
351
+ if (objectUrl) URL.revokeObjectURL(objectUrl);
352
+ };
353
+ }, [client, item?.logoAssetPath]);
354
+ async function run(action) {
355
+ if (operation.current || !current()) return;
356
+ operation.current = true;
357
+ setBusy(true);
358
+ setError(null);
359
+ try {
360
+ await action();
361
+ } catch (failure) {
362
+ if (current())
363
+ setError(
364
+ failure instanceof Error ? failure.message : "Connection setup could not finish. Try again."
365
+ );
366
+ } finally {
367
+ operation.current = false;
368
+ if (current()) setBusy(false);
369
+ }
370
+ }
371
+ function remember(attemptId) {
372
+ try {
373
+ sessionStorage.setItem(storageKey, attemptId);
374
+ } catch {
375
+ }
376
+ }
377
+ async function reconcile(attempt) {
378
+ if (!current()) return;
379
+ if (attempt.state !== "complete" || !attempt.account || !attempt.credentialsCommitted) return;
380
+ const resolved = await load();
381
+ if (!resolved || !current()) return;
382
+ const connection = (await client.listConnections(workspaceId)).find(
383
+ (entry) => entry.id === attempt.account.id
384
+ );
385
+ if (!current()) return;
386
+ if (!connection || connection.status !== "active" || connection.kind !== "oauth2" || connection.metadata.mcpUrl !== (resolved.mcpUrl ?? resolved.endpointUrl) || connection.subjectId !== null !== (attempt.ownership === "personal"))
387
+ throw new Error(
388
+ "The authorized account does not match this integration. Review its connection settings."
389
+ );
390
+ const previous = resolved.connectionRef;
391
+ if (resolved.enabled && previous?.subjectScope !== "subject" && previous?.connectionId && previous.connectionId !== connection.id)
392
+ throw new Error(
393
+ "This integration's selected account changed during setup. Review it before continuing."
394
+ );
395
+ await client.enableCapability(workspaceId, capabilityId, {
396
+ connectionRef: attempt.ownership === "personal" ? { providerDomain: connection.providerDomain, kind: "oauth2", subjectScope: "subject" } : {
397
+ providerDomain: connection.providerDomain,
398
+ kind: "oauth2",
399
+ subjectScope: "workspace",
400
+ connectionId: connection.id
401
+ }
402
+ });
403
+ if (!current()) return;
404
+ const enabled = await load();
405
+ if (enabled && current()) {
406
+ await finishConnection(enabled);
407
+ }
408
+ try {
409
+ sessionStorage.removeItem(storageKey);
410
+ } catch {
411
+ }
412
+ }
413
+ async function open() {
414
+ setExpanded(true);
415
+ await run(async () => {
416
+ await load();
417
+ if (!current()) return;
418
+ await recoverSavedAttempt();
419
+ });
420
+ }
421
+ async function recoverSavedAttempt() {
422
+ let saved = null;
423
+ try {
424
+ saved = sessionStorage.getItem(storageKey);
425
+ } catch {
426
+ }
427
+ if (saved) {
428
+ const attempt = await controller.recover(saved);
429
+ await reconcile(attempt);
430
+ }
431
+ }
432
+ async function begin() {
433
+ await run(async () => {
434
+ if (view.attempt && ["failed", "expired", "cancelled"].includes(view.attempt.state)) {
435
+ startKey.current = crypto.randomUUID();
436
+ advanceKey.current = crypto.randomUUID();
437
+ }
438
+ const reserved = reserveBrowserConnectNavigation(window);
439
+ try {
440
+ const resolved = await load();
441
+ if (!resolved || !current()) return;
442
+ if (resolved.connectionRef && ownership !== (resolved.connectionRef.subjectScope === "subject" ? "personal" : "workspace"))
443
+ throw new Error(
444
+ "The connection ownership changed. Review the current account before continuing."
445
+ );
446
+ const mcpUrl = resolved.mcpUrl ?? resolved.endpointUrl;
447
+ if (!mcpUrl)
448
+ throw new Error(
449
+ "The current catalog has no authorization endpoint for this integration."
450
+ );
451
+ let reconnectAccountId = resolved.connectionRef?.connectionId ?? void 0;
452
+ if (resolved.connectionRef?.subjectScope === "subject") {
453
+ const connections = (await client.listConnections(workspaceId)).filter(
454
+ (entry) => entry.subjectId !== null && entry.kind === "oauth2" && entry.metadata.mcpUrl === mcpUrl
455
+ );
456
+ if (!current()) return;
457
+ if (connections.length > 1)
458
+ throw new Error(
459
+ "More than one personal account matches. Choose the account in connection settings before reconnecting."
460
+ );
461
+ reconnectAccountId = connections[0]?.id;
462
+ }
463
+ let attempt = await controller.begin({
464
+ providerId: "mcp-oauth",
465
+ ownership,
466
+ returnUrl,
467
+ idempotencyKey: startKey.current,
468
+ ...reconnectAccountId ? { reconnectAccountId } : {}
469
+ });
470
+ if (!current()) return;
471
+ remember(attempt.id);
472
+ if (attempt.state === "credential_input")
473
+ attempt = await controller.advance(
474
+ { type: "credentials", values: { mcpUrl } },
475
+ advanceKey.current
476
+ );
477
+ if (attempt.nextAction.type === "authorize")
478
+ await performAuthorization(attempt, reserved.navigation);
479
+ else await reconcile(attempt);
480
+ } finally {
481
+ reserved.close();
482
+ }
483
+ });
484
+ }
485
+ async function performAuthorization(attempt, navigation) {
486
+ setWaiting(true);
487
+ try {
488
+ const result = await authorizeConnectAttempt(controller.transport, attempt, navigation, {
489
+ mode: "popup",
490
+ signal: lifetime.current.signal
491
+ });
492
+ if (!current() || !result) return;
493
+ await controller.refresh();
494
+ await reconcile(result);
495
+ if (result.state !== "complete")
496
+ throw new Error("Sign-in did not finish. You can try connecting again.");
497
+ } finally {
498
+ if (current()) setWaiting(false);
499
+ }
500
+ }
501
+ function authorize(attempt) {
502
+ return run(() => performAuthorization(attempt, createBrowserConnectNavigation(window)));
503
+ }
504
+ async function finishConnection(capability) {
505
+ if (!sessionId) {
506
+ await onConfigured?.();
507
+ if (!current()) return;
508
+ setComplete(true);
509
+ setExpanded(false);
510
+ onClose?.();
511
+ return;
512
+ }
513
+ if (capability.connectionRef && capability.connectionRef.subjectScope !== "subject") {
514
+ const selected = (await client.listConnections(workspaceId)).find(
515
+ (entry) => entry.id === capability.connectionRef?.connectionId
516
+ );
517
+ if (!current()) return;
518
+ if (!selected || selected.status !== "active")
519
+ throw new Error("This account needs reconnection before it can be used here.");
520
+ }
521
+ if (capability.connectionRef?.subjectScope === "subject") {
522
+ const accounts = await client.listOwnConnectionAccounts(workspaceId);
523
+ if (!current()) return;
524
+ if (matchingActiveMcpConnections(capability, accounts).length === 0)
525
+ throw new Error("Your account needs reconnection before it can be used here.");
526
+ }
527
+ if (!current()) return;
528
+ await attachSessionCapability(client, workspaceId, sessionId, capability, current);
529
+ if (!current()) return;
530
+ await onConfigured?.();
531
+ if (!current()) return;
532
+ setComplete(true);
533
+ setExpanded(false);
534
+ }
535
+ async function useHere() {
536
+ await run(async () => {
537
+ if (item) await finishConnection(item);
538
+ });
539
+ }
540
+ return /* @__PURE__ */ jsx2(
541
+ SessionCapabilityFrame,
542
+ {
543
+ name: item?.name ?? name,
544
+ subtitle: item?.providerDomain ?? "",
545
+ logo,
546
+ typeLabel: "MCP server",
547
+ description: item?.description || rationale,
548
+ skill: false,
549
+ expanded,
550
+ complete,
551
+ actionLabel: connected ? sessionId ? "Use in this conversation" : "Connected" : `Connect ${item?.name ?? name}`,
552
+ note: sessionId ? "Review access before signing in. You'll return to this conversation after authorization." : "Review access before signing in. You'll return here after authorization.",
553
+ onOpen: () => void open(),
554
+ onClose: () => {
555
+ setExpanded(false);
556
+ onClose?.();
557
+ },
558
+ busy: busy || view.busy,
559
+ dialogOnly,
560
+ children: /* @__PURE__ */ jsxs2("div", { className: "og-session-capability-setup", children: [
561
+ error ? /* @__PURE__ */ jsx2("p", { role: "alert", children: error }) : null,
562
+ !item ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
563
+ /* @__PURE__ */ jsx2("p", { role: "status", children: busy ? "Loading connection details\u2026" : "Connection details are unavailable." }),
564
+ /* @__PURE__ */ jsx2("button", { disabled: busy, onClick: () => void open(), children: "Retry" })
565
+ ] }) : /* @__PURE__ */ jsxs2(Fragment2, { children: [
566
+ /* @__PURE__ */ jsx2("p", { children: item.description || rationale }),
567
+ busy ? /* @__PURE__ */ jsx2("p", { role: "status", className: "og-session-capability-progress", children: waiting ? `Finish signing in with ${item.name} in the opened window. This will close automatically when you\u2019re connected.` : "Preparing your connection\u2026" }) : !connected ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
568
+ !item.connectionRef ? /* @__PURE__ */ jsxs2("fieldset", { disabled: busy, children: [
569
+ /* @__PURE__ */ jsx2("legend", { children: "Who can use this connection?" }),
570
+ /* @__PURE__ */ jsxs2("label", { children: [
571
+ /* @__PURE__ */ jsx2(
572
+ "input",
573
+ {
574
+ type: "radio",
575
+ name: `${capabilityId}-ownership`,
576
+ checked: ownership === "workspace",
577
+ onChange: () => setOwnership("workspace")
578
+ }
579
+ ),
580
+ "Everyone in this workspace"
581
+ ] }),
582
+ /* @__PURE__ */ jsxs2("label", { children: [
583
+ /* @__PURE__ */ jsx2(
584
+ "input",
585
+ {
586
+ type: "radio",
587
+ name: `${capabilityId}-ownership`,
588
+ checked: ownership === "personal",
589
+ onChange: () => setOwnership("personal")
590
+ }
591
+ ),
592
+ "Only me"
593
+ ] })
594
+ ] }) : null,
595
+ /* @__PURE__ */ jsx2("p", { className: "og-session-capability-scope", children: ownership === "workspace" ? sessionId ? "This connection will be available to your workspace and used in this conversation." : "This connection will be available to your workspace." : "This connection belongs to you. Your messages can use it; other participants use their own accounts." }),
596
+ /* @__PURE__ */ jsx2(
597
+ "button",
598
+ {
599
+ className: "og-session-capability-primary",
600
+ onClick: () => {
601
+ if (view.attempt?.nextAction.type === "authorize") void authorize(view.attempt);
602
+ else void begin();
603
+ },
604
+ children: error && view.attempt?.nextAction.type === "authorize" ? "Try signing in again" : `Continue to ${item.name}`
605
+ }
606
+ )
607
+ ] }) : null,
608
+ connected && !busy ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
609
+ /* @__PURE__ */ jsx2("p", { className: "og-session-capability-scope", children: sessionId ? "Your account is connected. Enable it for this conversation to finish." : "Your account is connected." }),
610
+ /* @__PURE__ */ jsx2(
611
+ "button",
612
+ {
613
+ className: "og-session-capability-primary",
614
+ disabled: busy || view.busy,
615
+ onClick: () => void useHere(),
616
+ children: sessionId ? "Use in this conversation" : "Done"
617
+ }
618
+ )
619
+ ] }) : null
620
+ ] })
621
+ ] })
622
+ }
623
+ );
624
+ }
625
+
626
+ export {
627
+ useConnect,
628
+ attachSessionCapability,
629
+ completeSessionCapabilityOAuth,
630
+ SessionCapabilityFrame,
631
+ mcpConnectionDiscoveryState,
632
+ SessionMcpCapabilityCard,
633
+ McpConnectionCard
634
+ };
635
+ //# sourceMappingURL=chunk-5UONOQ3Y.js.map