@opengeni/react 7.1.0 → 7.1.2-canary.36199476632001
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/dist/artifacts-document.js +2 -2
- package/dist/artifacts-presentation.js +2 -2
- package/dist/artifacts-spreadsheet.js +2 -2
- package/dist/artifacts.js +4 -4
- package/dist/{browser-viewer-MN7MOYQT.js → browser-viewer-K2H3SLIW.js} +2 -2
- package/dist/{chunk-KCGXPP5V.js → chunk-6P7T4RPE.js} +7 -3
- package/dist/chunk-6P7T4RPE.js.map +1 -0
- package/dist/{chunk-SHRCATV6.js → chunk-7J4DUR3E.js} +12 -5
- package/dist/chunk-7J4DUR3E.js.map +1 -0
- package/dist/{chunk-UQS7BGNQ.js → chunk-ETA37UZ7.js} +82 -11
- package/dist/chunk-ETA37UZ7.js.map +1 -0
- package/dist/{chunk-VR4Z73EU.js → chunk-G2SCXNXW.js} +9 -2
- package/dist/chunk-G2SCXNXW.js.map +1 -0
- package/dist/{chunk-5UONOQ3Y.js → chunk-K3MQZO7R.js} +150 -67
- package/dist/chunk-K3MQZO7R.js.map +1 -0
- package/dist/{chunk-OWHPKAOV.js → chunk-L6MYP3QU.js} +4 -2
- package/dist/{chunk-OWHPKAOV.js.map → chunk-L6MYP3QU.js.map} +1 -1
- package/dist/{chunk-ZC2DK5SC.js → chunk-RSFCYKA7.js} +88 -7
- package/dist/chunk-RSFCYKA7.js.map +1 -0
- package/dist/{chunk-VI7HELBI.js → chunk-SJ5HE4ZA.js} +21 -2
- package/dist/chunk-SJ5HE4ZA.js.map +1 -0
- package/dist/{chunk-4ACTWOOW.js → chunk-VDSZ3AVO.js} +41 -18
- package/dist/chunk-VDSZ3AVO.js.map +1 -0
- package/dist/{chunk-XMXRI5JK.js → chunk-ZZ4744OZ.js} +128 -71
- package/dist/chunk-ZZ4744OZ.js.map +1 -0
- package/dist/components/artifacts/artifact-surface.d.ts +3 -1
- package/dist/components/artifacts/document-editor.d.ts +4 -2
- package/dist/components/artifacts/editable-document.d.ts +1 -1
- package/dist/components/artifacts/editable-presentation.d.ts +1 -1
- package/dist/components/artifacts/editable-spreadsheet.d.ts +2 -1
- package/dist/components/artifacts/presentation-editor.d.ts +4 -2
- package/dist/components/browser-viewer.d.ts +4 -1
- package/dist/components/markdown.d.ts +2 -0
- package/dist/components/session-capability-frame.d.ts +5 -1
- package/dist/composer.js +1 -1
- package/dist/connect.js +2 -2
- package/dist/hooks/use-browser-session.d.ts +3 -0
- package/dist/index.js +7 -6
- package/dist/index.js.map +1 -1
- package/dist/interaction.js +1 -1
- package/dist/session-ui.js +4 -4
- package/dist/session.js +1 -1
- package/dist/timeline/types.d.ts +2 -0
- package/package.json +5 -5
- package/src/components/artifacts/artifact-surface.tsx +39 -19
- package/src/components/artifacts/document-editor.tsx +77 -9
- package/src/components/artifacts/editable-document.tsx +3 -0
- package/src/components/artifacts/editable-presentation.tsx +3 -0
- package/src/components/artifacts/editable-spreadsheet.tsx +3 -0
- package/src/components/artifacts/presentation-editor.tsx +6 -0
- package/src/components/browser-viewer.tsx +11 -5
- package/src/components/composer-transcription-control.tsx +4 -2
- package/src/components/composer.tsx +45 -20
- package/src/components/markdown.tsx +9 -2
- package/src/components/sandbox-workspace.tsx +1 -0
- package/src/components/session-capability-frame.tsx +11 -3
- package/src/components/session-mcp-capability-card.tsx +174 -70
- package/src/hooks/use-browser-frame-stream.ts +3 -1
- package/src/hooks/use-browser-session.ts +107 -3
- package/src/hooks/use-voice-input.ts +12 -1
- package/src/timeline/compaction-copy.ts +2 -0
- package/src/timeline/parsers.ts +2 -2
- package/src/timeline/projection.ts +31 -5
- package/src/timeline/tool-renderers.tsx +105 -16
- package/src/timeline/turn-summary.tsx +10 -2
- package/src/timeline/types.ts +2 -0
- package/styles/compiled.css +6 -0
- package/styles/session-capability.css +2 -0
- package/dist/chunk-4ACTWOOW.js.map +0 -1
- package/dist/chunk-5UONOQ3Y.js.map +0 -1
- package/dist/chunk-KCGXPP5V.js.map +0 -1
- package/dist/chunk-SHRCATV6.js.map +0 -1
- package/dist/chunk-UQS7BGNQ.js.map +0 -1
- package/dist/chunk-VI7HELBI.js.map +0 -1
- package/dist/chunk-VR4Z73EU.js.map +0 -1
- package/dist/chunk-XMXRI5JK.js.map +0 -1
- package/dist/chunk-ZC2DK5SC.js.map +0 -1
- /package/dist/{browser-viewer-MN7MOYQT.js.map → browser-viewer-K2H3SLIW.js.map} +0 -0
|
@@ -92,7 +92,9 @@ function SessionCapabilityFrame({
|
|
|
92
92
|
skill,
|
|
93
93
|
expanded,
|
|
94
94
|
complete,
|
|
95
|
+
completeLabel,
|
|
95
96
|
actionLabel,
|
|
97
|
+
opensDialog = true,
|
|
96
98
|
note,
|
|
97
99
|
onOpen,
|
|
98
100
|
onClose,
|
|
@@ -131,7 +133,7 @@ function SessionCapabilityFrame({
|
|
|
131
133
|
identity,
|
|
132
134
|
complete ? /* @__PURE__ */ jsx(CheckIcon, { size: 16, "aria-hidden": true }) : null
|
|
133
135
|
] }),
|
|
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: [
|
|
136
|
+
complete ? /* @__PURE__ */ jsx("p", { role: "status", className: "og-session-capability-copy", children: completeLabel ?? (skill ? "Installed \xB7 Workspace" : "Connected \xB7 Available in this conversation") }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
135
137
|
/* @__PURE__ */ jsx("p", { className: "og-session-capability-copy", children: description }),
|
|
136
138
|
/* @__PURE__ */ jsxs("div", { className: "og-session-capability-actions", children: [
|
|
137
139
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
@@ -144,8 +146,9 @@ function SessionCapabilityFrame({
|
|
|
144
146
|
ref: buttonRef,
|
|
145
147
|
type: "button",
|
|
146
148
|
onClick: onOpen,
|
|
147
|
-
|
|
148
|
-
"aria-
|
|
149
|
+
disabled: busy,
|
|
150
|
+
"aria-haspopup": opensDialog ? "dialog" : void 0,
|
|
151
|
+
"aria-expanded": opensDialog ? expanded : void 0,
|
|
149
152
|
children: actionLabel
|
|
150
153
|
}
|
|
151
154
|
)
|
|
@@ -205,6 +208,7 @@ function SessionCapabilityFrame({
|
|
|
205
208
|
// src/components/session-mcp-capability-card.tsx
|
|
206
209
|
import {
|
|
207
210
|
authorizeConnectAttempt,
|
|
211
|
+
ConnectPopupClosedError,
|
|
208
212
|
ConnectController,
|
|
209
213
|
createBrowserConnectNavigation,
|
|
210
214
|
reserveBrowserConnectNavigation
|
|
@@ -272,22 +276,29 @@ function ScopedCard({
|
|
|
272
276
|
const [complete, setComplete] = useState2(false);
|
|
273
277
|
const [connected, setConnected] = useState2(false);
|
|
274
278
|
const [waiting, setWaiting] = useState2(false);
|
|
279
|
+
const [reconciling, setReconciling] = useState2(false);
|
|
275
280
|
const [busy, setBusy] = useState2(false);
|
|
276
281
|
const [error, setError] = useState2(null);
|
|
282
|
+
const [notice, setNotice] = useState2(null);
|
|
283
|
+
const [retryFresh, setRetryFresh] = useState2(false);
|
|
277
284
|
const [ownership, setOwnership] = useState2("workspace");
|
|
278
285
|
const lifetime = useRef2(null);
|
|
279
|
-
const
|
|
286
|
+
const authorization = useRef2(null);
|
|
287
|
+
const operation = useRef2(null);
|
|
288
|
+
const reservedPopup = useRef2(null);
|
|
280
289
|
const startKey = useRef2(crypto.randomUUID());
|
|
281
290
|
const advanceKey = useRef2(crypto.randomUUID());
|
|
291
|
+
const startInput = useRef2(null);
|
|
282
292
|
const storageKey = sessionId ? `opengeni:session-connect:${workspaceId}:${sessionId}:${capabilityId}` : `opengeni:workspace-connect:${workspaceId}:${capabilityId}`;
|
|
283
293
|
const current = () => !!lifetime.current && !lifetime.current.signal.aborted;
|
|
284
|
-
async function load() {
|
|
294
|
+
async function load(active = current) {
|
|
285
295
|
const invocation = lifetime.current;
|
|
286
296
|
const [catalog, session] = await Promise.all([
|
|
287
297
|
client.listCapabilities(workspaceId),
|
|
288
298
|
sessionId ? client.getSession(workspaceId, sessionId) : Promise.resolve(null)
|
|
289
299
|
]);
|
|
290
|
-
if (!invocation || invocation.signal.aborted || lifetime.current !== invocation
|
|
300
|
+
if (!invocation || invocation.signal.aborted || lifetime.current !== invocation || !active())
|
|
301
|
+
return null;
|
|
291
302
|
const resolved = catalog.items.find((entry) => entry.id === capabilityId);
|
|
292
303
|
if (!resolved || resolved.kind !== "mcp" || resolved.authKind !== "oauth2")
|
|
293
304
|
throw new Error(
|
|
@@ -301,11 +312,11 @@ function ScopedCard({
|
|
|
301
312
|
let accountReady = false;
|
|
302
313
|
if (resolved.enabled && resolved.connectionRef) {
|
|
303
314
|
const connections = resolved.connectionRef.subjectScope === "subject" ? await client.listOwnConnectionAccounts(workspaceId) : await client.listConnections(workspaceId);
|
|
304
|
-
if (invocation.signal.aborted || lifetime.current !== invocation) return null;
|
|
315
|
+
if (invocation.signal.aborted || lifetime.current !== invocation || !active()) return null;
|
|
305
316
|
const matches = matchingActiveMcpConnections(resolved, connections);
|
|
306
317
|
accountReady = matches.length === 1;
|
|
307
318
|
}
|
|
308
|
-
if (invocation.signal.aborted || lifetime.current !== invocation) return null;
|
|
319
|
+
if (invocation.signal.aborted || lifetime.current !== invocation || !active()) return null;
|
|
309
320
|
const selected = session?.toolPolicy.mode === "workspace_default" ? session.effectiveToolPolicy?.selectedIds : session?.tools.filter((tool) => tool.kind === "mcp").map((tool) => tool.id);
|
|
310
321
|
setConnected(accountReady);
|
|
311
322
|
setComplete(
|
|
@@ -353,19 +364,28 @@ function ScopedCard({
|
|
|
353
364
|
}, [client, item?.logoAssetPath]);
|
|
354
365
|
async function run(action) {
|
|
355
366
|
if (operation.current || !current()) return;
|
|
356
|
-
|
|
367
|
+
const pending = new AbortController();
|
|
368
|
+
operation.current = pending;
|
|
369
|
+
const active = () => current() && operation.current === pending && !pending.signal.aborted;
|
|
357
370
|
setBusy(true);
|
|
358
371
|
setError(null);
|
|
372
|
+
setNotice(null);
|
|
373
|
+
setRetryFresh(false);
|
|
359
374
|
try {
|
|
360
|
-
await action();
|
|
375
|
+
await action(active);
|
|
361
376
|
} catch (failure) {
|
|
362
|
-
if (
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
377
|
+
if (active()) {
|
|
378
|
+
if (failure instanceof ConnectPopupClosedError) setNotice(failure.message);
|
|
379
|
+
else
|
|
380
|
+
setError(
|
|
381
|
+
failure instanceof Error ? failure.message : "Connection setup could not finish. Try again."
|
|
382
|
+
);
|
|
383
|
+
}
|
|
366
384
|
} finally {
|
|
367
|
-
operation.current
|
|
368
|
-
|
|
385
|
+
if (operation.current === pending) {
|
|
386
|
+
operation.current = null;
|
|
387
|
+
if (current()) setBusy(false);
|
|
388
|
+
}
|
|
369
389
|
}
|
|
370
390
|
}
|
|
371
391
|
function remember(attemptId) {
|
|
@@ -374,15 +394,15 @@ function ScopedCard({
|
|
|
374
394
|
} catch {
|
|
375
395
|
}
|
|
376
396
|
}
|
|
377
|
-
async function reconcile(attempt) {
|
|
378
|
-
if (!
|
|
397
|
+
async function reconcile(attempt, active = current) {
|
|
398
|
+
if (!active()) return;
|
|
379
399
|
if (attempt.state !== "complete" || !attempt.account || !attempt.credentialsCommitted) return;
|
|
380
|
-
const resolved = await load();
|
|
381
|
-
if (!resolved || !
|
|
400
|
+
const resolved = await load(active);
|
|
401
|
+
if (!resolved || !active()) return;
|
|
382
402
|
const connection = (await client.listConnections(workspaceId)).find(
|
|
383
403
|
(entry) => entry.id === attempt.account.id
|
|
384
404
|
);
|
|
385
|
-
if (!
|
|
405
|
+
if (!active()) return;
|
|
386
406
|
if (!connection || connection.status !== "active" || connection.kind !== "oauth2" || connection.metadata.mcpUrl !== (resolved.mcpUrl ?? resolved.endpointUrl) || connection.subjectId !== null !== (attempt.ownership === "personal"))
|
|
387
407
|
throw new Error(
|
|
388
408
|
"The authorized account does not match this integration. Review its connection settings."
|
|
@@ -400,11 +420,12 @@ function ScopedCard({
|
|
|
400
420
|
connectionId: connection.id
|
|
401
421
|
}
|
|
402
422
|
});
|
|
403
|
-
if (!
|
|
404
|
-
const enabled = await load();
|
|
405
|
-
if (enabled &&
|
|
406
|
-
await finishConnection(enabled);
|
|
423
|
+
if (!active()) return;
|
|
424
|
+
const enabled = await load(active);
|
|
425
|
+
if (enabled && active()) {
|
|
426
|
+
await finishConnection(enabled, active);
|
|
407
427
|
}
|
|
428
|
+
if (!active()) return;
|
|
408
429
|
try {
|
|
409
430
|
sessionStorage.removeItem(storageKey);
|
|
410
431
|
} catch {
|
|
@@ -412,13 +433,13 @@ function ScopedCard({
|
|
|
412
433
|
}
|
|
413
434
|
async function open() {
|
|
414
435
|
setExpanded(true);
|
|
415
|
-
await run(async () => {
|
|
416
|
-
await load();
|
|
417
|
-
if (!
|
|
418
|
-
await recoverSavedAttempt();
|
|
436
|
+
await run(async (active) => {
|
|
437
|
+
await load(active);
|
|
438
|
+
if (!active()) return;
|
|
439
|
+
await recoverSavedAttempt(active);
|
|
419
440
|
});
|
|
420
441
|
}
|
|
421
|
-
async function recoverSavedAttempt() {
|
|
442
|
+
async function recoverSavedAttempt(active = current) {
|
|
422
443
|
let saved = null;
|
|
423
444
|
try {
|
|
424
445
|
saved = sessionStorage.getItem(storageKey);
|
|
@@ -426,19 +447,27 @@ function ScopedCard({
|
|
|
426
447
|
}
|
|
427
448
|
if (saved) {
|
|
428
449
|
const attempt = await controller.recover(saved);
|
|
429
|
-
|
|
450
|
+
if (!active()) return;
|
|
451
|
+
if (["failed", "expired", "cancelled"].includes(attempt.state)) setRetryFresh(true);
|
|
452
|
+
if (attempt.state === "complete") setReconciling(true);
|
|
453
|
+
try {
|
|
454
|
+
await reconcile(attempt, active);
|
|
455
|
+
} finally {
|
|
456
|
+
if (active()) setReconciling(false);
|
|
457
|
+
}
|
|
430
458
|
}
|
|
431
459
|
}
|
|
432
|
-
async function begin() {
|
|
433
|
-
await run(async () => {
|
|
434
|
-
if (view.attempt && ["failed", "expired", "cancelled"].includes(view.attempt.state)) {
|
|
460
|
+
async function begin(fresh = false) {
|
|
461
|
+
await run(async (active) => {
|
|
462
|
+
if (fresh || view.attempt && ["failed", "expired", "cancelled"].includes(view.attempt.state)) {
|
|
435
463
|
startKey.current = crypto.randomUUID();
|
|
436
464
|
advanceKey.current = crypto.randomUUID();
|
|
437
465
|
}
|
|
438
466
|
const reserved = reserveBrowserConnectNavigation(window);
|
|
467
|
+
reservedPopup.current = reserved.close;
|
|
439
468
|
try {
|
|
440
|
-
const resolved = await load();
|
|
441
|
-
if (!resolved || !
|
|
469
|
+
const resolved = await load(active);
|
|
470
|
+
if (!resolved || !active()) return;
|
|
442
471
|
if (resolved.connectionRef && ownership !== (resolved.connectionRef.subjectScope === "subject" ? "personal" : "workspace"))
|
|
443
472
|
throw new Error(
|
|
444
473
|
"The connection ownership changed. Review the current account before continuing."
|
|
@@ -453,13 +482,19 @@ function ScopedCard({
|
|
|
453
482
|
const connections = (await client.listConnections(workspaceId)).filter(
|
|
454
483
|
(entry) => entry.subjectId !== null && entry.kind === "oauth2" && entry.metadata.mcpUrl === mcpUrl
|
|
455
484
|
);
|
|
456
|
-
if (!
|
|
485
|
+
if (!active()) return;
|
|
457
486
|
if (connections.length > 1)
|
|
458
487
|
throw new Error(
|
|
459
488
|
"More than one personal account matches. Choose the account in connection settings before reconnecting."
|
|
460
489
|
);
|
|
461
490
|
reconnectAccountId = connections[0]?.id;
|
|
462
491
|
}
|
|
492
|
+
const input = JSON.stringify({ ownership, returnUrl, reconnectAccountId, mcpUrl });
|
|
493
|
+
if (startInput.current !== null && startInput.current !== input) {
|
|
494
|
+
startKey.current = crypto.randomUUID();
|
|
495
|
+
advanceKey.current = crypto.randomUUID();
|
|
496
|
+
}
|
|
497
|
+
startInput.current = input;
|
|
463
498
|
let attempt = await controller.begin({
|
|
464
499
|
providerId: "mcp-oauth",
|
|
465
500
|
ownership,
|
|
@@ -467,44 +502,67 @@ function ScopedCard({
|
|
|
467
502
|
idempotencyKey: startKey.current,
|
|
468
503
|
...reconnectAccountId ? { reconnectAccountId } : {}
|
|
469
504
|
});
|
|
470
|
-
if (!
|
|
505
|
+
if (!active()) return;
|
|
471
506
|
remember(attempt.id);
|
|
472
507
|
if (attempt.state === "credential_input")
|
|
473
508
|
attempt = await controller.advance(
|
|
474
509
|
{ type: "credentials", values: { mcpUrl } },
|
|
475
510
|
advanceKey.current
|
|
476
511
|
);
|
|
512
|
+
if (!active()) return;
|
|
477
513
|
if (attempt.nextAction.type === "authorize")
|
|
478
|
-
await performAuthorization(attempt, reserved.navigation);
|
|
479
|
-
else await reconcile(attempt);
|
|
514
|
+
await performAuthorization(attempt, reserved.navigation, active);
|
|
515
|
+
else await reconcile(attempt, active);
|
|
480
516
|
} finally {
|
|
517
|
+
if (reservedPopup.current === reserved.close) reservedPopup.current = null;
|
|
481
518
|
reserved.close();
|
|
482
519
|
}
|
|
483
520
|
});
|
|
484
521
|
}
|
|
485
|
-
async function performAuthorization(attempt, navigation) {
|
|
522
|
+
async function performAuthorization(attempt, navigation, active) {
|
|
523
|
+
if (!active()) return;
|
|
524
|
+
const pending = new AbortController();
|
|
525
|
+
authorization.current = pending;
|
|
526
|
+
const abortOnUnmount = () => pending.abort(lifetime.current?.signal.reason);
|
|
527
|
+
lifetime.current.signal.addEventListener("abort", abortOnUnmount, { once: true });
|
|
486
528
|
setWaiting(true);
|
|
487
529
|
try {
|
|
488
530
|
const result = await authorizeConnectAttempt(controller.transport, attempt, navigation, {
|
|
489
531
|
mode: "popup",
|
|
490
|
-
signal:
|
|
532
|
+
signal: pending.signal
|
|
491
533
|
});
|
|
492
|
-
if (!
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
534
|
+
if (!active() || !result) return;
|
|
535
|
+
setWaiting(false);
|
|
536
|
+
setReconciling(true);
|
|
537
|
+
await reconcile(result, active);
|
|
538
|
+
if (!active()) return;
|
|
539
|
+
if (result.state === "cancelled") {
|
|
540
|
+
setNotice("Sign-in was cancelled. You can try connecting again.");
|
|
541
|
+
setRetryFresh(true);
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
if (result.state !== "complete") {
|
|
545
|
+
if (["failed", "expired"].includes(result.state)) setRetryFresh(true);
|
|
496
546
|
throw new Error("Sign-in did not finish. You can try connecting again.");
|
|
547
|
+
}
|
|
497
548
|
} finally {
|
|
498
|
-
|
|
549
|
+
lifetime.current?.signal.removeEventListener("abort", abortOnUnmount);
|
|
550
|
+
if (authorization.current === pending) authorization.current = null;
|
|
551
|
+
if (active()) {
|
|
552
|
+
setReconciling(false);
|
|
553
|
+
setWaiting(false);
|
|
554
|
+
}
|
|
499
555
|
}
|
|
500
556
|
}
|
|
501
557
|
function authorize(attempt) {
|
|
502
|
-
return run(
|
|
558
|
+
return run(
|
|
559
|
+
(active) => performAuthorization(attempt, createBrowserConnectNavigation(window), active)
|
|
560
|
+
);
|
|
503
561
|
}
|
|
504
|
-
async function finishConnection(capability) {
|
|
562
|
+
async function finishConnection(capability, active = current) {
|
|
505
563
|
if (!sessionId) {
|
|
506
564
|
await onConfigured?.();
|
|
507
|
-
if (!
|
|
565
|
+
if (!active()) return;
|
|
508
566
|
setComplete(true);
|
|
509
567
|
setExpanded(false);
|
|
510
568
|
onClose?.();
|
|
@@ -514,29 +572,44 @@ function ScopedCard({
|
|
|
514
572
|
const selected = (await client.listConnections(workspaceId)).find(
|
|
515
573
|
(entry) => entry.id === capability.connectionRef?.connectionId
|
|
516
574
|
);
|
|
517
|
-
if (!
|
|
575
|
+
if (!active()) return;
|
|
518
576
|
if (!selected || selected.status !== "active")
|
|
519
577
|
throw new Error("This account needs reconnection before it can be used here.");
|
|
520
578
|
}
|
|
521
579
|
if (capability.connectionRef?.subjectScope === "subject") {
|
|
522
580
|
const accounts = await client.listOwnConnectionAccounts(workspaceId);
|
|
523
|
-
if (!
|
|
581
|
+
if (!active()) return;
|
|
524
582
|
if (matchingActiveMcpConnections(capability, accounts).length === 0)
|
|
525
583
|
throw new Error("Your account needs reconnection before it can be used here.");
|
|
526
584
|
}
|
|
527
|
-
if (!
|
|
528
|
-
await attachSessionCapability(client, workspaceId, sessionId, capability,
|
|
529
|
-
if (!
|
|
585
|
+
if (!active()) return;
|
|
586
|
+
await attachSessionCapability(client, workspaceId, sessionId, capability, active);
|
|
587
|
+
if (!active()) return;
|
|
530
588
|
await onConfigured?.();
|
|
531
|
-
if (!
|
|
589
|
+
if (!active()) return;
|
|
532
590
|
setComplete(true);
|
|
533
591
|
setExpanded(false);
|
|
534
592
|
}
|
|
535
593
|
async function useHere() {
|
|
536
|
-
await run(async () => {
|
|
537
|
-
if (item) await finishConnection(item);
|
|
594
|
+
await run(async (active) => {
|
|
595
|
+
if (item) await finishConnection(item, active);
|
|
538
596
|
});
|
|
539
597
|
}
|
|
598
|
+
function close() {
|
|
599
|
+
const pending = operation.current;
|
|
600
|
+
if (pending) {
|
|
601
|
+
operation.current = null;
|
|
602
|
+
pending.abort(new ConnectPopupClosedError());
|
|
603
|
+
authorization.current?.abort(new ConnectPopupClosedError());
|
|
604
|
+
authorization.current = null;
|
|
605
|
+
reservedPopup.current?.();
|
|
606
|
+
setBusy(false);
|
|
607
|
+
setWaiting(false);
|
|
608
|
+
setReconciling(false);
|
|
609
|
+
}
|
|
610
|
+
setExpanded(false);
|
|
611
|
+
onClose?.();
|
|
612
|
+
}
|
|
540
613
|
return /* @__PURE__ */ jsx2(
|
|
541
614
|
SessionCapabilityFrame,
|
|
542
615
|
{
|
|
@@ -551,20 +624,28 @@ function ScopedCard({
|
|
|
551
624
|
actionLabel: connected ? sessionId ? "Use in this conversation" : "Connected" : `Connect ${item?.name ?? name}`,
|
|
552
625
|
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
626
|
onOpen: () => void open(),
|
|
554
|
-
onClose:
|
|
555
|
-
setExpanded(false);
|
|
556
|
-
onClose?.();
|
|
557
|
-
},
|
|
558
|
-
busy: busy || view.busy,
|
|
627
|
+
onClose: close,
|
|
559
628
|
dialogOnly,
|
|
560
629
|
children: /* @__PURE__ */ jsxs2("div", { className: "og-session-capability-setup", children: [
|
|
561
630
|
error ? /* @__PURE__ */ jsx2("p", { role: "alert", children: error }) : null,
|
|
631
|
+
notice ? /* @__PURE__ */ jsx2("p", { role: "status", className: "og-session-capability-notice", children: notice }) : null,
|
|
562
632
|
!item ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
563
633
|
/* @__PURE__ */ jsx2("p", { role: "status", children: busy ? "Loading connection details\u2026" : "Connection details are unavailable." }),
|
|
564
634
|
/* @__PURE__ */ jsx2("button", { disabled: busy, onClick: () => void open(), children: "Retry" })
|
|
565
635
|
] }) : /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
566
636
|
/* @__PURE__ */ jsx2("p", { children: item.description || rationale }),
|
|
567
|
-
busy ? /* @__PURE__ */
|
|
637
|
+
busy ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
638
|
+
/* @__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.` : reconciling ? "Finishing your connection\u2026" : "Preparing your connection\u2026" }),
|
|
639
|
+
waiting ? /* @__PURE__ */ jsx2(
|
|
640
|
+
"button",
|
|
641
|
+
{
|
|
642
|
+
type: "button",
|
|
643
|
+
className: "og-session-capability-stop",
|
|
644
|
+
onClick: () => authorization.current?.abort(new ConnectPopupClosedError()),
|
|
645
|
+
children: "Stop waiting"
|
|
646
|
+
}
|
|
647
|
+
) : null
|
|
648
|
+
] }) : !connected ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
568
649
|
!item.connectionRef ? /* @__PURE__ */ jsxs2("fieldset", { disabled: busy, children: [
|
|
569
650
|
/* @__PURE__ */ jsx2("legend", { children: "Who can use this connection?" }),
|
|
570
651
|
/* @__PURE__ */ jsxs2("label", { children: [
|
|
@@ -598,10 +679,12 @@ function ScopedCard({
|
|
|
598
679
|
{
|
|
599
680
|
className: "og-session-capability-primary",
|
|
600
681
|
onClick: () => {
|
|
601
|
-
if (
|
|
682
|
+
if (notice || retryFresh) void begin(true);
|
|
683
|
+
else if (view.attempt?.nextAction.type === "authorize" && view.attempt.ownership === ownership)
|
|
684
|
+
void authorize(view.attempt);
|
|
602
685
|
else void begin();
|
|
603
686
|
},
|
|
604
|
-
children: error && view.attempt?.nextAction.type === "authorize" ? "Try signing in again" : `Continue to ${item.name}`
|
|
687
|
+
children: retryFresh || (error || notice) && view.attempt?.nextAction.type === "authorize" ? "Try signing in again" : `Continue to ${item.name}`
|
|
605
688
|
}
|
|
606
689
|
)
|
|
607
690
|
] }) : null,
|
|
@@ -632,4 +715,4 @@ export {
|
|
|
632
715
|
SessionMcpCapabilityCard,
|
|
633
716
|
McpConnectionCard
|
|
634
717
|
};
|
|
635
|
-
//# sourceMappingURL=chunk-
|
|
718
|
+
//# sourceMappingURL=chunk-K3MQZO7R.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hooks/use-connect.ts","../src/session-capability-policy.ts","../src/components/session-capability-frame.tsx","../src/components/session-mcp-capability-card.tsx","../src/mcp-connection-status.ts"],"sourcesContent":["import type { ConnectController } from \"@opengeni/connect\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\n/** Internal consumers import the hook directly so setup surfaces stay lazy. */\nexport function useConnect(controller: ConnectController) {\n const snapshot = useSyncExternalStore(\n controller.subscribe,\n controller.getSnapshot,\n controller.getSnapshot,\n );\n const actions = useMemo(\n () => ({\n begin: controller.begin.bind(controller),\n recover: controller.recover.bind(controller),\n refresh: controller.refresh.bind(controller),\n waitForAction: controller.waitForAction.bind(controller),\n advance: controller.advance.bind(controller),\n cancel: controller.cancel.bind(controller),\n }),\n [controller],\n );\n return useMemo(() => ({ ...snapshot, ...actions }), [snapshot, actions]);\n}\n","import type { FirstPartyMcpToolName, CapabilityCatalogItem } from \"@opengeni/sdk\";\nimport type { OpenGeniBrowserClient as OpenGeniClient } from \"@opengeni/sdk/browser\";\n\n/** Catalog tool discovery may be lazy; selecting the installed server does not\n * require its individual tool inventory to have been fetched. */\nexport function sessionCapabilityTools(item: CapabilityCatalogItem) {\n const serverId = item.kind === \"mcp\" ? item.runtime?.mcpServerId : undefined;\n return serverId && !item.tools.some((tool) => tool.kind === \"mcp\" && tool.id === serverId)\n ? [...item.tools, { kind: \"mcp\" as const, id: serverId }]\n : item.tools;\n}\n\n/** A connection never resets the human's existing tool selection. Default-mode\n * sessions discover newly enabled servers at admission; explicit/inherited\n * policies add only this reviewed capability, with the existing CAS fence. */\nexport async function attachSessionCapability(\n client: OpenGeniClient,\n workspaceId: string,\n sessionId: string,\n item: CapabilityCatalogItem,\n stillCurrent: () => boolean = () => true,\n): Promise<void> {\n const tools = sessionCapabilityTools(item);\n if (item.kind === \"skill\" || tools.length === 0) return;\n if (!stillCurrent()) throw new Error(\"Connection setup was interrupted.\");\n const session = await client.getSession(workspaceId, sessionId);\n if (!stillCurrent()) throw new Error(\"Connection setup was interrupted.\");\n // Session.tools includes mandatory runtime servers, which must never be\n // echoed into the human's explicit selection.\n let existing = session.tools.filter(\n (tool) => !session.effectiveToolPolicy?.mandatoryIds?.includes(tool.id),\n );\n if (session.toolPolicy.mode === \"workspace_default\") {\n const policy = session.effectiveToolPolicy;\n if (!policy || policy.idsTruncated)\n throw new Error(\n \"Connected, but the full session tool selection could not be read. Review the Tools picker before continuing.\",\n );\n // A workspace may choose a restricted default instead of all enabled servers.\n // Preserve that exact selection if this connection needs an explicit addition.\n // selectedIds contains only explicit additions, and is normally empty for\n // automatic selection. Compare against the resolved defaults instead.\n existing = policy.effectiveIds\n .filter((id) => !policy.mandatoryIds.includes(id))\n .map((id) => ({ kind: \"mcp\" as const, id }));\n }\n const additions = tools.filter(\n (tool) => !existing.some((current) => current.kind === tool.kind && current.id === tool.id),\n );\n const recommended = Array.isArray(item.metadata?.firstPartyMcpTools)\n ? (item.metadata.firstPartyMcpTools.filter(\n (name): name is string => typeof name === \"string\",\n ) as FirstPartyMcpToolName[])\n : [];\n const firstParty = [...new Set([...session.firstPartyMcpTools, ...recommended])];\n if (additions.length === 0 && firstParty.length === session.firstPartyMcpTools.length) return;\n await client.updateSessionToolPolicy(workspaceId, sessionId, {\n mode: \"explicit\",\n tools: [...existing, ...additions],\n firstPartyMcpTools: firstParty,\n expectedVersion: session.toolPolicyVersion,\n });\n}\n\n/** Native OAuth callbacks have already saved the provider connection. Finish\n * the separate, version-fenced session tool selection before reporting success. */\nexport async function completeSessionCapabilityOAuth(\n client: OpenGeniClient,\n workspaceId: string,\n sessionId: string,\n capabilityId: string | null,\n): Promise<void> {\n if (!capabilityId)\n throw new Error(\n \"The authorized integration could not be identified. Review its connection card to finish setup.\",\n );\n const connected = (await client.listCapabilities(workspaceId)).items.find(\n (item) => item.id === capabilityId,\n );\n if (!connected?.enabled)\n throw new Error(\"The connection was authorized, but enabling its tools could not be verified.\");\n await attachSessionCapability(client, workspaceId, sessionId, connected);\n}\n","import { CheckIcon, ShieldCheckIcon, XIcon } from \"lucide-react\";\nimport { Dialog } from \"radix-ui\";\nimport { useRef, useState, type ReactNode, type RefObject } from \"react\";\nimport { usePortalTokenStyle } from \"../lib/use-portal-token-style\";\n\nexport type SessionCapabilityFrameProps = {\n name: string;\n subtitle: string;\n logo: string | null;\n typeLabel: string;\n description: string;\n skill: boolean;\n expanded: boolean;\n complete: boolean;\n /** Completion copy must reflect the provider's actual scope of access. */\n completeLabel?: string;\n actionLabel: string;\n /** Direct navigation actions should not announce a dialog on the card. */\n opensDialog?: boolean;\n note: string;\n onOpen(): void;\n onClose(): void;\n busy?: boolean;\n opener?: RefObject<HTMLButtonElement | null>;\n cardRef?: RefObject<HTMLElement | null>;\n children?: ReactNode;\n /** A catalogue row can own the opener while reusing the same details dialog. */\n dialogOnly?: boolean;\n};\n\nfunction Mark({ src, name }: { src: string | null; name: string }) {\n const [failed, setFailed] = useState<string | null>(null);\n return (\n <span className=\"og-session-capability-logo\" aria-hidden>\n {src && failed !== src ? (\n <img src={src} alt=\"\" loading=\"lazy\" decoding=\"async\" onError={() => setFailed(src)} />\n ) : (\n name.trim().slice(0, 2).toUpperCase()\n )}\n </span>\n );\n}\n\n/** The same conversation card in the console and embedded clients. Setup\n * content owns the provider flow; this frame owns identity and protected focus. */\nexport function SessionCapabilityFrame({\n name,\n subtitle,\n logo,\n typeLabel,\n description,\n skill,\n expanded,\n complete,\n completeLabel,\n actionLabel,\n opensDialog = true,\n note,\n onOpen,\n onClose,\n busy = false,\n opener,\n cardRef,\n children,\n dialogOnly = false,\n}: SessionCapabilityFrameProps) {\n const localOpener = useRef<HTMLButtonElement>(null);\n const localCard = useRef<HTMLElement>(null);\n const buttonRef = opener ?? localOpener;\n const sectionRef = cardRef ?? localCard;\n const portalStyle = usePortalTokenStyle(sectionRef.current);\n const identity = (\n <>\n <Mark src={logo} name={name} />\n <div className=\"og-session-capability-identity\">\n <h3>{name}</h3>\n <span>{subtitle}</span>\n </div>\n <span className=\"og-session-capability-type\">{typeLabel}</span>\n </>\n );\n return (\n <div className=\"og-session-capability\">\n <section\n hidden={dialogOnly}\n style={dialogOnly ? { display: \"none\" } : undefined}\n ref={sectionRef}\n tabIndex={-1}\n aria-label={`${name} setup`}\n data-state={complete ? \"complete\" : expanded ? \"setup\" : \"suggested\"}\n className=\"og-session-capability-shell\"\n >\n <div className=\"og-session-capability-header\">\n {identity}\n {complete ? <CheckIcon size={16} aria-hidden /> : null}\n </div>\n {complete ? (\n <p role=\"status\" className=\"og-session-capability-copy\">\n {completeLabel ??\n (skill ? \"Installed · Workspace\" : \"Connected · Available in this conversation\")}\n </p>\n ) : (\n <>\n <p className=\"og-session-capability-copy\">{description}</p>\n <div className=\"og-session-capability-actions\">\n <span>\n <ShieldCheckIcon size={13} aria-hidden />\n {skill ? \"Guidance only · no account access\" : \"You choose what to authorize\"}\n </span>\n <button\n ref={buttonRef}\n type=\"button\"\n onClick={onOpen}\n disabled={busy}\n aria-haspopup={opensDialog ? \"dialog\" : undefined}\n aria-expanded={opensDialog ? expanded : undefined}\n >\n {actionLabel}\n </button>\n </div>\n </>\n )}\n </section>\n {!complete && !dialogOnly ? <p className=\"og-session-capability-note\">{note}</p> : null}\n <Dialog.Root\n open={expanded && !complete}\n onOpenChange={(open) => {\n if (!open && !busy) onClose();\n }}\n >\n <Dialog.Portal>\n <Dialog.Overlay className=\"og-root og-session-capability-overlay\" style={portalStyle} />\n <Dialog.Content\n className=\"og-root og-session-capability-dialog\"\n style={portalStyle}\n onEscapeKeyDown={(event) => {\n if (busy) event.preventDefault();\n }}\n onInteractOutside={(event) => {\n if (busy) event.preventDefault();\n }}\n onCloseAutoFocus={(event) => {\n event.preventDefault();\n const target = buttonRef.current?.isConnected\n ? buttonRef.current\n : sectionRef.current;\n if (target?.isConnected) target.focus();\n }}\n >\n <div className=\"og-session-capability-dialog-header\">\n <Mark src={logo} name={name} />\n <div>\n <Dialog.Title>{name}</Dialog.Title>\n <Dialog.Description>\n {typeLabel}\n {subtitle ? ` · ${subtitle}` : \"\"}\n </Dialog.Description>\n </div>\n {!busy ? (\n <Dialog.Close aria-label=\"Close connection setup\">\n <XIcon size={18} />\n </Dialog.Close>\n ) : null}\n </div>\n <div className=\"og-session-capability-dialog-body\">{children}</div>\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n </div>\n );\n}\n","import {\n authorizeConnectAttempt,\n ConnectPopupClosedError,\n ConnectController,\n createBrowserConnectNavigation,\n reserveBrowserConnectNavigation,\n type ConnectAttempt,\n type ConnectNavigation,\n type ConnectOwnership,\n} from \"@opengeni/connect\";\nimport type { CapabilityCatalogItem } from \"@opengeni/sdk\";\nimport type { OpenGeniBrowserClient as OpenGeniClient } from \"@opengeni/sdk/browser\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { useConnect } from \"../hooks/use-connect\";\nimport { attachSessionCapability, sessionCapabilityTools } from \"../session-capability-policy\";\nimport { SessionCapabilityFrame } from \"./session-capability-frame\";\nimport { matchingActiveMcpConnections } from \"../mcp-connection-status\";\n\nexport type SessionMcpCapabilityCardProps = {\n client: OpenGeniClient;\n workspaceId: string;\n sessionId: string;\n capabilityId: string;\n name: string;\n rationale?: string;\n /** Exact host route; no console-specific routing is assumed. */\n returnUrl: string;\n onConfigured?: (() => void | Promise<void>) | undefined;\n};\n\nexport type McpConnectionCardProps = Omit<SessionMcpCapabilityCardProps, \"sessionId\"> & {\n /** Omit for connection management: no session tool selection is written. */\n sessionId?: string;\n dialogOnly?: boolean;\n onClose?: (() => void) | undefined;\n};\n\n/** Native OAuth recommendation flow. Identity and endpoint come from the live\n * catalog, never from model-authored recommendation text. */\nexport function SessionMcpCapabilityCard(props: SessionMcpCapabilityCardProps) {\n return <McpConnectionCard {...props} />;\n}\n\nexport function McpConnectionCard(props: McpConnectionCardProps) {\n const [client, setClient] = useState(props.client);\n const [generation, setGeneration] = useState(0);\n if (client !== props.client) {\n setClient(props.client);\n setGeneration(generation + 1);\n }\n return (\n <ScopedCard\n key={`${generation}:${props.workspaceId}:${props.sessionId}:${props.capabilityId}`}\n {...props}\n />\n );\n}\n\nfunction ScopedCard({\n client,\n workspaceId,\n sessionId,\n capabilityId,\n name,\n rationale = \"\",\n returnUrl,\n onConfigured,\n dialogOnly = false,\n onClose,\n}: McpConnectionCardProps) {\n const [controller] = useState(\n () => new ConnectController(client.connectTransport(), workspaceId),\n );\n const view = useConnect(controller);\n const [item, setItem] = useState<CapabilityCatalogItem | null>(null);\n const [logo, setLogo] = useState<string | null>(null);\n const [expanded, setExpanded] = useState(dialogOnly);\n const [complete, setComplete] = useState(false);\n const [connected, setConnected] = useState(false);\n const [waiting, setWaiting] = useState(false);\n const [reconciling, setReconciling] = useState(false);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [notice, setNotice] = useState<string | null>(null);\n const [retryFresh, setRetryFresh] = useState(false);\n const [ownership, setOwnership] = useState<ConnectOwnership>(\"workspace\");\n const lifetime = useRef<AbortController | null>(null);\n const authorization = useRef<AbortController | null>(null);\n const operation = useRef<AbortController | null>(null);\n const reservedPopup = useRef<(() => void) | null>(null);\n const startKey = useRef(crypto.randomUUID());\n const advanceKey = useRef(crypto.randomUUID());\n const startInput = useRef<string | null>(null);\n const storageKey = sessionId\n ? `opengeni:session-connect:${workspaceId}:${sessionId}:${capabilityId}`\n : `opengeni:workspace-connect:${workspaceId}:${capabilityId}`;\n const current = () => !!lifetime.current && !lifetime.current.signal.aborted;\n\n async function load(active: () => boolean = current) {\n const invocation = lifetime.current;\n const [catalog, session] = await Promise.all([\n client.listCapabilities(workspaceId),\n sessionId ? client.getSession(workspaceId, sessionId) : Promise.resolve(null),\n ]);\n if (!invocation || invocation.signal.aborted || lifetime.current !== invocation || !active())\n return null;\n const resolved = catalog.items.find((entry) => entry.id === capabilityId);\n if (!resolved || resolved.kind !== \"mcp\" || resolved.authKind !== \"oauth2\")\n throw new Error(\n \"This recommendation is not an available OAuth MCP integration. Review the current connection catalog.\",\n );\n setItem(resolved);\n if (resolved.connectionRef)\n setOwnership(resolved.connectionRef.subjectScope === \"subject\" ? \"personal\" : \"workspace\");\n else if (!item && resolved.metadata?.defaultConnectionOwnership === \"personal\")\n setOwnership(\"personal\");\n let accountReady = false;\n if (resolved.enabled && resolved.connectionRef) {\n const connections =\n resolved.connectionRef.subjectScope === \"subject\"\n ? await client.listOwnConnectionAccounts(workspaceId)\n : await client.listConnections(workspaceId);\n if (invocation.signal.aborted || lifetime.current !== invocation || !active()) return null;\n const matches = matchingActiveMcpConnections(resolved, connections);\n accountReady = matches.length === 1;\n }\n if (invocation.signal.aborted || lifetime.current !== invocation || !active()) return null;\n const selected =\n session?.toolPolicy.mode === \"workspace_default\"\n ? session.effectiveToolPolicy?.selectedIds\n : session?.tools.filter((tool) => tool.kind === \"mcp\").map((tool) => tool.id);\n setConnected(accountReady);\n setComplete(\n accountReady &&\n !!selected &&\n sessionCapabilityTools(resolved).every((tool) => selected.includes(tool.id)),\n );\n return resolved;\n }\n\n useEffect(() => {\n const abort = new AbortController();\n lifetime.current = abort;\n // Mount reads are scoped to this effect, not to the user-action lock.\n // Strict Mode may cancel the first mount while its promise is still in\n // flight; that must not suppress the replacement mount's initialization.\n if (dialogOnly) setBusy(true);\n void (async () => {\n await load();\n if (abort.signal.aborted || !dialogOnly) return;\n await recoverSavedAttempt();\n })()\n .catch((failure) => {\n if (!abort.signal.aborted)\n setError(\n failure instanceof Error ? failure.message : \"Couldn't load connection details.\",\n );\n })\n .finally(() => {\n if (!abort.signal.aborted && dialogOnly) setBusy(false);\n });\n return () => {\n abort.abort();\n };\n // ScopedCard remounts for client/workspace/session/capability changes.\n // These reads initialize that scope; rerunning on action closures would\n // cancel initialization whenever its own state updates render the card.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, workspaceId, sessionId, capabilityId, dialogOnly]);\n\n useEffect(() => {\n const path = item?.logoAssetPath;\n setLogo(null);\n if (!path?.startsWith(\"catalog-assets/\")) return;\n const abort = new AbortController();\n let objectUrl: string | null = null;\n // Embeds can require authentication even for the API's public catalog\n // asset route. Use the client's transport instead of an unauthenticated img.\n void client\n .downloadCatalogAsset(path, { signal: abort.signal })\n .then((blob) => {\n if (abort.signal.aborted || !blob.type.startsWith(\"image/\") || blob.size > 2_000_000)\n return;\n objectUrl = URL.createObjectURL(blob);\n setLogo(objectUrl);\n })\n .catch(() => {\n /* Keep the provider's initials if its passive mark is unavailable. */\n });\n return () => {\n abort.abort();\n if (objectUrl) URL.revokeObjectURL(objectUrl);\n };\n }, [client, item?.logoAssetPath]);\n\n async function run(action: (active: () => boolean) => Promise<void>) {\n if (operation.current || !current()) return;\n const pending = new AbortController();\n operation.current = pending;\n const active = () => current() && operation.current === pending && !pending.signal.aborted;\n setBusy(true);\n setError(null);\n setNotice(null);\n setRetryFresh(false);\n try {\n await action(active);\n } catch (failure) {\n if (active()) {\n if (failure instanceof ConnectPopupClosedError) setNotice(failure.message);\n else\n setError(\n failure instanceof Error\n ? failure.message\n : \"Connection setup could not finish. Try again.\",\n );\n }\n } finally {\n if (operation.current === pending) {\n operation.current = null;\n if (current()) setBusy(false);\n }\n }\n }\n\n function remember(attemptId: string) {\n // An opaque recovery hint only. The backend rechecks the authenticated\n // owner on recover; this value never grants access or proves completion.\n try {\n sessionStorage.setItem(storageKey, attemptId);\n } catch {\n /* Storage may be disabled. */\n }\n }\n\n async function reconcile(attempt: ConnectAttempt, active: () => boolean = current) {\n if (!active()) return;\n if (attempt.state !== \"complete\" || !attempt.account || !attempt.credentialsCommitted) return;\n const resolved = await load(active);\n if (!resolved || !active()) return;\n const connection = (await client.listConnections(workspaceId)).find(\n (entry) => entry.id === attempt.account!.id,\n );\n if (!active()) return;\n if (\n !connection ||\n connection.status !== \"active\" ||\n connection.kind !== \"oauth2\" ||\n connection.metadata.mcpUrl !== (resolved.mcpUrl ?? resolved.endpointUrl) ||\n (connection.subjectId !== null) !== (attempt.ownership === \"personal\")\n )\n throw new Error(\n \"The authorized account does not match this integration. Review its connection settings.\",\n );\n const previous = resolved.connectionRef;\n if (\n resolved.enabled &&\n previous?.subjectScope !== \"subject\" &&\n previous?.connectionId &&\n previous.connectionId !== connection.id\n )\n throw new Error(\n \"This integration's selected account changed during setup. Review it before continuing.\",\n );\n await client.enableCapability(workspaceId, capabilityId, {\n connectionRef:\n attempt.ownership === \"personal\"\n ? { providerDomain: connection.providerDomain, kind: \"oauth2\", subjectScope: \"subject\" }\n : {\n providerDomain: connection.providerDomain,\n kind: \"oauth2\",\n subjectScope: \"workspace\",\n connectionId: connection.id,\n },\n });\n if (!active()) return;\n const enabled = await load(active);\n if (enabled && active()) {\n await finishConnection(enabled, active);\n }\n if (!active()) return;\n try {\n sessionStorage.removeItem(storageKey);\n } catch {\n /* Recovery hint only. */\n }\n }\n\n async function open() {\n setExpanded(true);\n await run(async (active) => {\n await load(active);\n if (!active()) return;\n await recoverSavedAttempt(active);\n });\n }\n\n async function recoverSavedAttempt(active: () => boolean = current) {\n let saved: string | null = null;\n try {\n saved = sessionStorage.getItem(storageKey);\n } catch {\n /* No persisted attempt. */\n }\n if (saved) {\n const attempt = await controller.recover(saved);\n if (!active()) return;\n if ([\"failed\", \"expired\", \"cancelled\"].includes(attempt.state)) setRetryFresh(true);\n if (attempt.state === \"complete\") setReconciling(true);\n try {\n await reconcile(attempt, active);\n } finally {\n if (active()) setReconciling(false);\n }\n }\n }\n\n async function begin(fresh = false) {\n await run(async (active) => {\n if (\n fresh ||\n (view.attempt && [\"failed\", \"expired\", \"cancelled\"].includes(view.attempt.state))\n ) {\n startKey.current = crypto.randomUUID();\n advanceKey.current = crypto.randomUUID();\n }\n const reserved = reserveBrowserConnectNavigation(window);\n reservedPopup.current = reserved.close;\n try {\n const resolved = await load(active);\n if (!resolved || !active()) return;\n if (\n resolved.connectionRef &&\n ownership !==\n (resolved.connectionRef.subjectScope === \"subject\" ? \"personal\" : \"workspace\")\n )\n throw new Error(\n \"The connection ownership changed. Review the current account before continuing.\",\n );\n const mcpUrl = resolved.mcpUrl ?? resolved.endpointUrl;\n if (!mcpUrl)\n throw new Error(\n \"The current catalog has no authorization endpoint for this integration.\",\n );\n // Never silently replace an already selected account. Reauthorization\n // stays on its exact native connection ID.\n let reconnectAccountId = resolved.connectionRef?.connectionId ?? undefined;\n if (resolved.connectionRef?.subjectScope === \"subject\") {\n const connections = (await client.listConnections(workspaceId)).filter(\n (entry) =>\n entry.subjectId !== null &&\n entry.kind === \"oauth2\" &&\n entry.metadata.mcpUrl === mcpUrl,\n );\n if (!active()) return;\n if (connections.length > 1)\n throw new Error(\n \"More than one personal account matches. Choose the account in connection settings before reconnecting.\",\n );\n reconnectAccountId = connections[0]?.id;\n }\n // A closed request can still have reached the server. Keep its key for\n // an exact replay, but never reuse it when ownership or another input\n // changes while the user reopens setup.\n const input = JSON.stringify({ ownership, returnUrl, reconnectAccountId, mcpUrl });\n if (startInput.current !== null && startInput.current !== input) {\n startKey.current = crypto.randomUUID();\n advanceKey.current = crypto.randomUUID();\n }\n startInput.current = input;\n let attempt = await controller.begin({\n providerId: \"mcp-oauth\",\n ownership,\n returnUrl,\n idempotencyKey: startKey.current,\n ...(reconnectAccountId ? { reconnectAccountId } : {}),\n });\n if (!active()) return;\n remember(attempt.id);\n if (attempt.state === \"credential_input\")\n attempt = await controller.advance(\n { type: \"credentials\", values: { mcpUrl } },\n advanceKey.current,\n );\n if (!active()) return;\n if (attempt.nextAction.type === \"authorize\")\n await performAuthorization(attempt, reserved.navigation, active);\n else await reconcile(attempt, active);\n } finally {\n if (reservedPopup.current === reserved.close) reservedPopup.current = null;\n reserved.close();\n }\n });\n }\n\n async function performAuthorization(\n attempt: ConnectAttempt,\n navigation: ConnectNavigation,\n active: () => boolean,\n ) {\n if (!active()) return;\n const pending = new AbortController();\n authorization.current = pending;\n const abortOnUnmount = () => pending.abort(lifetime.current?.signal.reason);\n lifetime.current!.signal.addEventListener(\"abort\", abortOnUnmount, { once: true });\n setWaiting(true);\n try {\n const result = await authorizeConnectAttempt(controller.transport, attempt, navigation, {\n mode: \"popup\",\n signal: pending.signal,\n });\n if (!active() || !result) return;\n setWaiting(false);\n setReconciling(true);\n await reconcile(result, active);\n if (!active()) return;\n if (result.state === \"cancelled\") {\n setNotice(\"Sign-in was cancelled. You can try connecting again.\");\n setRetryFresh(true);\n return;\n }\n if (result.state !== \"complete\") {\n if ([\"failed\", \"expired\"].includes(result.state)) setRetryFresh(true);\n throw new Error(\"Sign-in did not finish. You can try connecting again.\");\n }\n } finally {\n lifetime.current?.signal.removeEventListener(\"abort\", abortOnUnmount);\n if (authorization.current === pending) authorization.current = null;\n if (active()) {\n setReconciling(false);\n setWaiting(false);\n }\n }\n }\n\n function authorize(attempt: ConnectAttempt) {\n // run invokes action synchronously, retaining the browser click gesture.\n return run((active) =>\n performAuthorization(attempt, createBrowserConnectNavigation(window), active),\n );\n }\n\n async function finishConnection(\n capability: CapabilityCatalogItem,\n active: () => boolean = current,\n ) {\n if (!sessionId) {\n // Connection management does not select session tools.\n await onConfigured?.();\n if (!active()) return;\n setComplete(true);\n setExpanded(false);\n onClose?.();\n return;\n }\n if (capability.connectionRef && capability.connectionRef.subjectScope !== \"subject\") {\n const selected = (await client.listConnections(workspaceId)).find(\n (entry) => entry.id === capability.connectionRef?.connectionId,\n );\n if (!active()) return;\n if (!selected || selected.status !== \"active\")\n throw new Error(\"This account needs reconnection before it can be used here.\");\n }\n if (capability.connectionRef?.subjectScope === \"subject\") {\n const accounts = await client.listOwnConnectionAccounts(workspaceId);\n if (!active()) return;\n if (matchingActiveMcpConnections(capability, accounts).length === 0)\n throw new Error(\"Your account needs reconnection before it can be used here.\");\n }\n if (!active()) return;\n await attachSessionCapability(client, workspaceId, sessionId, capability, active);\n if (!active()) return;\n await onConfigured?.();\n if (!active()) return;\n setComplete(true);\n setExpanded(false);\n }\n\n async function useHere() {\n await run(async (active) => {\n if (item) await finishConnection(item, active);\n });\n }\n\n function close() {\n const pending = operation.current;\n if (pending) {\n operation.current = null;\n pending.abort(new ConnectPopupClosedError());\n authorization.current?.abort(new ConnectPopupClosedError());\n authorization.current = null;\n reservedPopup.current?.();\n setBusy(false);\n setWaiting(false);\n setReconciling(false);\n }\n setExpanded(false);\n onClose?.();\n }\n\n return (\n <SessionCapabilityFrame\n name={item?.name ?? name}\n subtitle={item?.providerDomain ?? \"\"}\n logo={logo}\n typeLabel=\"MCP server\"\n description={item?.description || rationale}\n skill={false}\n expanded={expanded}\n complete={complete}\n actionLabel={\n connected\n ? sessionId\n ? \"Use in this conversation\"\n : \"Connected\"\n : `Connect ${item?.name ?? name}`\n }\n note={\n sessionId\n ? \"Review access before signing in. You'll return to this conversation after authorization.\"\n : \"Review access before signing in. You'll return here after authorization.\"\n }\n onOpen={() => void open()}\n onClose={close}\n dialogOnly={dialogOnly}\n >\n <div className=\"og-session-capability-setup\">\n {error ? <p role=\"alert\">{error}</p> : null}\n {notice ? (\n <p role=\"status\" className=\"og-session-capability-notice\">\n {notice}\n </p>\n ) : null}\n {!item ? (\n <>\n <p role=\"status\">\n {busy ? \"Loading connection details…\" : \"Connection details are unavailable.\"}\n </p>\n <button disabled={busy} onClick={() => void open()}>\n Retry\n </button>\n </>\n ) : (\n <>\n <p>{item.description || rationale}</p>\n {busy ? (\n <>\n <p role=\"status\" className=\"og-session-capability-progress\">\n {waiting\n ? `Finish signing in with ${item.name} in the opened window. This will close automatically when you’re connected.`\n : reconciling\n ? \"Finishing your connection…\"\n : \"Preparing your connection…\"}\n </p>\n {waiting ? (\n <button\n type=\"button\"\n className=\"og-session-capability-stop\"\n onClick={() => authorization.current?.abort(new ConnectPopupClosedError())}\n >\n Stop waiting\n </button>\n ) : null}\n </>\n ) : !connected ? (\n <>\n {!item.connectionRef ? (\n <fieldset disabled={busy}>\n <legend>Who can use this connection?</legend>\n <label>\n <input\n type=\"radio\"\n name={`${capabilityId}-ownership`}\n checked={ownership === \"workspace\"}\n onChange={() => setOwnership(\"workspace\")}\n />\n Everyone in this workspace\n </label>\n <label>\n <input\n type=\"radio\"\n name={`${capabilityId}-ownership`}\n checked={ownership === \"personal\"}\n onChange={() => setOwnership(\"personal\")}\n />\n Only me\n </label>\n </fieldset>\n ) : null}\n <p className=\"og-session-capability-scope\">\n {ownership === \"workspace\"\n ? sessionId\n ? \"This connection will be available to your workspace and used in this conversation.\"\n : \"This connection will be available to your workspace.\"\n : \"This connection belongs to you. Your messages can use it; other participants use their own accounts.\"}\n </p>\n <button\n className=\"og-session-capability-primary\"\n onClick={() => {\n if (notice || retryFresh) void begin(true);\n else if (\n view.attempt?.nextAction.type === \"authorize\" &&\n view.attempt.ownership === ownership\n )\n void authorize(view.attempt);\n else void begin();\n }}\n >\n {retryFresh ||\n ((error || notice) && view.attempt?.nextAction.type === \"authorize\")\n ? \"Try signing in again\"\n : `Continue to ${item.name}`}\n </button>\n </>\n ) : null}\n {connected && !busy ? (\n <>\n <p className=\"og-session-capability-scope\">\n {sessionId\n ? \"Your account is connected. Enable it for this conversation to finish.\"\n : \"Your account is connected.\"}\n </p>\n <button\n className=\"og-session-capability-primary\"\n disabled={busy || view.busy}\n onClick={() => void useHere()}\n >\n {sessionId ? \"Use in this conversation\" : \"Done\"}\n </button>\n </>\n ) : null}\n </>\n )}\n </div>\n </SessionCapabilityFrame>\n );\n}\n","import type { CapabilityCatalogItem, ConnectionMetadata } from \"@opengeni/sdk\";\n\n/** Status only; runtime use is authorized for the authenticated initiating user. */\nexport function matchingActiveMcpConnections(\n item: CapabilityCatalogItem,\n connections: ConnectionMetadata[],\n) {\n return matchingMcpConnections(item, connections).filter((entry) => entry.status === \"active\");\n}\n\nfunction matchingMcpConnections(item: CapabilityCatalogItem, connections: ConnectionMetadata[]) {\n const ref = item.connectionRef;\n if (!item.enabled || !ref) return [];\n return connections.filter(\n (entry) =>\n entry.status !== \"revoked\" &&\n entry.kind === \"oauth2\" &&\n entry.metadata.mcpUrl === (item.mcpUrl ?? item.endpointUrl) &&\n (ref.subjectScope !== \"subject\"\n ? entry.id === ref.connectionId && entry.subjectId === null\n : entry.subjectId !== null),\n );\n}\n\n/** Installation availability is not account readiness. Revoked history is not actionable. */\nexport function mcpConnectionDiscoveryState(\n item: CapabilityCatalogItem,\n connections: ConnectionMetadata[],\n) {\n const matching = matchingMcpConnections(item, connections);\n const active = matching.filter((entry) => entry.status === \"active\");\n if (active.length === 1) return { status: \"added\", label: \"Connected\" } as const;\n if (matching.length > 0) return { status: \"attention\", label: \"Review connection\" } as const;\n return { status: \"available\", label: \"Connect\" } as const;\n}\n"],"mappings":"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","names":["useRef","useState","Fragment","jsx","jsxs","useState","useRef"]}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
editableArtifactAccessRevoked,
|
|
5
5
|
editableArtifactStatusLabel,
|
|
6
6
|
useEditableArtifactView
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-6P7T4RPE.js";
|
|
8
8
|
import {
|
|
9
9
|
cn
|
|
10
10
|
} from "./chunk-22KP6LR5.js";
|
|
@@ -2524,6 +2524,7 @@ function EditableSpreadsheetGrid({
|
|
|
2524
2524
|
function EditableSpreadsheetArtifactSurface({
|
|
2525
2525
|
session,
|
|
2526
2526
|
title = "Workbook",
|
|
2527
|
+
showHeader,
|
|
2527
2528
|
subtitle,
|
|
2528
2529
|
actions,
|
|
2529
2530
|
initialSheetId,
|
|
@@ -2599,6 +2600,7 @@ function EditableSpreadsheetArtifactSurface({
|
|
|
2599
2600
|
{
|
|
2600
2601
|
modality: "spreadsheet",
|
|
2601
2602
|
title,
|
|
2603
|
+
showHeader,
|
|
2602
2604
|
subtitle: subtitle ?? (accessRevoked ? editableArtifactStatusLabel(view) : metadata ? `${sheets.length} sheet${sheets.length === 1 ? "" : "s"}` : editableArtifactStatusLabel(view)),
|
|
2603
2605
|
actions,
|
|
2604
2606
|
footer: accessRevoked ? void 0 : footer,
|
|
@@ -2833,4 +2835,4 @@ export {
|
|
|
2833
2835
|
EditableSpreadsheetGrid,
|
|
2834
2836
|
EditableSpreadsheetArtifactSurface
|
|
2835
2837
|
};
|
|
2836
|
-
//# sourceMappingURL=chunk-
|
|
2838
|
+
//# sourceMappingURL=chunk-L6MYP3QU.js.map
|