@opengeni/react 6.1.0 → 7.0.0-canary.35585322809001
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -2
- package/dist/artifacts-document.js +1 -1
- package/dist/artifacts-presentation.js +1 -1
- package/dist/artifacts-spreadsheet.js +1 -1
- package/dist/artifacts.js +3 -3
- package/dist/{browser-viewer-NTD6UIPR.js → browser-viewer-LGH4IP47.js} +3 -3
- package/dist/capability-catalog-row.d.ts +20 -0
- package/dist/capability-logo-fallback.d.ts +3 -0
- package/dist/{chunk-NOSYBS2D.js → chunk-2VHARTBL.js} +2 -1
- package/dist/{chunk-VRBL3F5E.js → chunk-5GAL23FF.js} +10 -2
- package/dist/{chunk-VRBL3F5E.js.map → chunk-5GAL23FF.js.map} +1 -1
- package/dist/chunk-5UONOQ3Y.js +635 -0
- package/dist/chunk-5UONOQ3Y.js.map +1 -0
- package/dist/{chunk-NYESIADM.js → chunk-AKOMC3VO.js} +3 -3
- package/dist/chunk-AKOMC3VO.js.map +1 -0
- package/dist/chunk-BRM6FVZA.js +302 -0
- package/dist/chunk-BRM6FVZA.js.map +1 -0
- package/dist/{chunk-TDSEILUH.js → chunk-D5NOQPLR.js} +1289 -1530
- package/dist/chunk-D5NOQPLR.js.map +1 -0
- package/dist/chunk-D7GAPJ3V.js +1558 -0
- package/dist/chunk-D7GAPJ3V.js.map +1 -0
- package/dist/{chunk-5M6VTFJ5.js → chunk-GBPCZH3Y.js} +2 -2
- package/dist/{chunk-YBM6CQRU.js → chunk-GEN54DU5.js} +4 -4
- package/dist/{chunk-UMECRJRV.js → chunk-HJ5VJ4JB.js} +21 -12
- package/dist/chunk-HJ5VJ4JB.js.map +1 -0
- package/dist/{chunk-R4KRSFGA.js → chunk-IP4BUBKH.js} +3 -3
- package/dist/{chunk-KANFU34B.js → chunk-IYUPN32E.js} +6 -2
- package/dist/chunk-IYUPN32E.js.map +1 -0
- package/dist/{chunk-L2NBTKRX.js → chunk-JKLGJQO5.js} +193 -12
- package/dist/chunk-JKLGJQO5.js.map +1 -0
- package/dist/{chunk-NLTS7JHI.js → chunk-JPHDWKZE.js} +5 -5
- package/dist/{chunk-ICA6R6TW.js → chunk-OWHPKAOV.js} +28 -20
- package/dist/chunk-OWHPKAOV.js.map +1 -0
- package/dist/{chunk-24M4YBCL.js → chunk-PNAVEK2U.js} +4 -4
- package/dist/{chunk-45XEUVTK.js → chunk-UXE5SSNN.js} +293 -463
- package/dist/chunk-UXE5SSNN.js.map +1 -0
- package/dist/{chunk-PEI6RANI.js → chunk-VR4Z73EU.js} +203 -9
- package/dist/chunk-VR4Z73EU.js.map +1 -0
- package/dist/{chunk-HUIKIDM5.js → chunk-XMXRI5JK.js} +65 -18
- package/dist/chunk-XMXRI5JK.js.map +1 -0
- package/dist/client.d.ts +1 -1
- package/dist/components/artifacts/spreadsheet-general-display.d.ts +24 -0
- package/dist/components/chat-composer.d.ts +13 -3
- package/dist/components/markdown.d.ts +4 -3
- package/dist/components/message-timeline.d.ts +7 -2
- package/dist/components/preview-loading.d.ts +2 -0
- package/dist/components/session-capability-frame.d.ts +24 -0
- package/dist/components/session-chrome.d.ts +1 -2
- package/dist/components/session-commands.d.ts +6 -0
- package/dist/components/session-connection-request.d.ts +8 -0
- package/dist/components/session-mcp-capability-card.d.ts +22 -0
- package/dist/components/timeline-search.d.ts +34 -0
- package/dist/composer.js +7 -7
- package/dist/connect-account-identity.d.ts +8 -0
- package/dist/connect-accounts.d.ts +5 -0
- package/dist/connect-chooser.d.ts +6 -0
- package/dist/connect-panel.d.ts +9 -2
- package/dist/connect-setup.d.ts +5 -1
- package/dist/connect.d.ts +5 -21
- package/dist/connect.js +1268 -584
- package/dist/connect.js.map +1 -1
- package/dist/connection-catalog.d.ts +6 -1
- package/dist/connection-discovery.d.ts +12 -0
- package/dist/connection-installed.d.ts +1 -0
- package/dist/connection-logo.d.ts +5 -2
- package/dist/connection-service-logo.d.ts +8 -0
- package/dist/connection-service-presentation.d.ts +13 -0
- package/dist/connection-skeleton.d.ts +5 -0
- package/dist/discovery-cache.d.ts +5 -0
- package/dist/hooks/use-codex-accounts.d.ts +11 -5
- package/dist/hooks/use-connect.d.ts +22 -0
- package/dist/hooks/use-session-events.d.ts +5 -0
- package/dist/hooks/use-session-mcp-approval-policy.d.ts +2 -2
- package/dist/hooks/use-workspace-sessions.d.ts +2 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.js +771 -793
- package/dist/index.js.map +1 -1
- package/dist/interaction.js +2 -2
- package/dist/machines.js +2 -2
- package/dist/mcp-connection-status.d.ts +14 -0
- package/dist/{model-policy-picker-menu-3R336DP2.js → model-policy-picker-menu-RVOQ4ZZG.js} +4 -4
- package/dist/model-policy.d.ts +6 -2
- package/dist/model-policy.js +1 -1
- package/dist/{platform-activity-row-DUE2W74J.js → platform-activity-row-HLOH7FW4.js} +9 -4
- package/dist/platform-activity-row-HLOH7FW4.js.map +1 -0
- package/dist/plugin-discovery.d.ts +6 -0
- package/dist/{queue-surface-implementation-LK3S4BIW.js → queue-surface-implementation-3RIFK2BS.js} +4 -4
- package/dist/realtime.js +22 -22
- package/dist/realtime.js.map +1 -1
- package/dist/session-auth-recommendation.d.ts +5 -0
- package/dist/session-capability-policy.d.ts +12 -0
- package/dist/session-ui.d.ts +2 -0
- package/dist/session-ui.js +14 -12
- package/dist/session.d.ts +1 -0
- package/dist/session.js +6 -4
- package/dist/skill-discovery.d.ts +11 -0
- package/dist/timeline/compaction-copy.d.ts +10 -0
- package/dist/timeline/projection.d.ts +3 -1
- package/dist/timeline/turn-summary.d.ts +2 -2
- package/dist/timeline/types.d.ts +22 -1
- package/dist/{timeline-annotation-markers-DRSTLEM6.js → timeline-annotation-markers-OY6OWR3V.js} +2 -2
- package/dist/{timeline-annotation-selection-IHLUGVND.js → timeline-annotation-selection-BOXA2TIN.js} +2 -2
- package/dist/{timeline-annotations-dialog-6Q53N5FG.js → timeline-annotations-dialog-RGY3MHL3.js} +3 -3
- package/package.json +3 -3
- package/src/assets/README.md +8 -0
- package/src/assets/gmail.ico +0 -0
- package/src/assets/outlook.ico +0 -0
- package/src/capability-catalog-row.tsx +94 -0
- package/src/capability-logo-fallback.ts +22 -0
- package/src/client.ts +0 -9
- package/src/components/artifacts/document-editor.tsx +63 -6
- package/src/components/artifacts/presentation-editor.tsx +214 -9
- package/src/components/artifacts/spreadsheet-canvas.ts +3 -8
- package/src/components/artifacts/spreadsheet-general-display.ts +43 -0
- package/src/components/artifacts/spreadsheet-grid.tsx +10 -11
- package/src/components/chat-composer.tsx +26 -3
- package/src/components/composer.tsx +10 -4
- package/src/components/human-input-form.tsx +12 -2
- package/src/components/markdown.tsx +86 -4
- package/src/components/message-timeline.tsx +104 -36
- package/src/components/model-picker.tsx +11 -3
- package/src/components/model-policy-picker-menu.tsx +10 -3
- package/src/components/preview-loading.tsx +154 -0
- package/src/components/sandbox-workspace.tsx +20 -36
- package/src/components/session-capability-frame.tsx +163 -0
- package/src/components/session-chrome.tsx +46 -77
- package/src/components/session-commands.tsx +18 -0
- package/src/components/session-connection-request.tsx +97 -0
- package/src/components/session-conversation.tsx +5 -4
- package/src/components/session-mcp-capability-card.tsx +532 -0
- package/src/components/session-status.tsx +2 -2
- package/src/components/timeline-anchor.tsx +9 -8
- package/src/components/timeline-search.tsx +168 -0
- package/src/components/user-message-body.tsx +7 -0
- package/src/connect-account-identity.tsx +34 -0
- package/src/connect-accounts.tsx +114 -52
- package/src/connect-chooser.tsx +171 -39
- package/src/connect-panel.tsx +73 -9
- package/src/connect-setup.tsx +72 -25
- package/src/connect.ts +13 -22
- package/src/connection-assets.d.ts +4 -0
- package/src/connection-catalog.tsx +61 -39
- package/src/connection-discovery.tsx +235 -0
- package/src/connection-installed.tsx +2 -0
- package/src/connection-logo.tsx +18 -10
- package/src/connection-service-logo.tsx +55 -0
- package/src/connection-service-presentation.ts +46 -0
- package/src/connection-skeleton.tsx +16 -0
- package/src/conversation-timeline.ts +1 -0
- package/src/discovery-cache.ts +42 -0
- package/src/hooks/use-codex-accounts.ts +33 -14
- package/src/hooks/use-composer.ts +4 -5
- package/src/hooks/use-connect.ts +23 -0
- package/src/hooks/use-session-events.ts +114 -1
- package/src/hooks/use-session-mcp-approval-policy.ts +13 -5
- package/src/hooks/use-workspace-sessions.ts +10 -0
- package/src/index.ts +22 -2
- package/src/mcp-connection-status.ts +35 -0
- package/src/model-policy.ts +21 -0
- package/src/plugin-details.tsx +8 -5
- package/src/plugin-discovery.tsx +92 -72
- package/src/realtime/realtime-control.tsx +6 -8
- package/src/session-auth-recommendation.ts +48 -0
- package/src/session-capability-policy.ts +83 -0
- package/src/session-ui.ts +2 -0
- package/src/session.ts +1 -0
- package/src/skill-discovery.tsx +101 -56
- package/src/timeline/compaction-copy.ts +40 -0
- package/src/timeline/platform-activity-row.tsx +8 -3
- package/src/timeline/projection.ts +74 -2
- package/src/timeline/shared.tsx +6 -1
- package/src/timeline/startup-timings.tsx +1 -1
- package/src/timeline/turn-summary.tsx +17 -3
- package/src/timeline/types.ts +22 -2
- package/styles/compiled.css +325 -27
- package/styles/connect.css +90 -15
- package/styles/index.css +46 -0
- package/styles/session-capability.css +42 -0
- package/dist/chunk-45XEUVTK.js.map +0 -1
- package/dist/chunk-HQV2I5HV.js +0 -124
- package/dist/chunk-HQV2I5HV.js.map +0 -1
- package/dist/chunk-HUIKIDM5.js.map +0 -1
- package/dist/chunk-ICA6R6TW.js.map +0 -1
- package/dist/chunk-IHQII5WO.js +0 -886
- package/dist/chunk-IHQII5WO.js.map +0 -1
- package/dist/chunk-KANFU34B.js.map +0 -1
- package/dist/chunk-L2NBTKRX.js.map +0 -1
- package/dist/chunk-NYESIADM.js.map +0 -1
- package/dist/chunk-PEI6RANI.js.map +0 -1
- package/dist/chunk-TDSEILUH.js.map +0 -1
- package/dist/chunk-UMECRJRV.js.map +0 -1
- package/dist/hooks/use-packs.d.ts +0 -32
- package/dist/platform-activity-row-DUE2W74J.js.map +0 -1
- package/src/hooks/use-packs.ts +0 -157
- /package/dist/{browser-viewer-NTD6UIPR.js.map → browser-viewer-LGH4IP47.js.map} +0 -0
- /package/dist/{chunk-NOSYBS2D.js.map → chunk-2VHARTBL.js.map} +0 -0
- /package/dist/{chunk-5M6VTFJ5.js.map → chunk-GBPCZH3Y.js.map} +0 -0
- /package/dist/{chunk-YBM6CQRU.js.map → chunk-GEN54DU5.js.map} +0 -0
- /package/dist/{chunk-R4KRSFGA.js.map → chunk-IP4BUBKH.js.map} +0 -0
- /package/dist/{chunk-NLTS7JHI.js.map → chunk-JPHDWKZE.js.map} +0 -0
- /package/dist/{chunk-24M4YBCL.js.map → chunk-PNAVEK2U.js.map} +0 -0
- /package/dist/{model-policy-picker-menu-3R336DP2.js.map → model-policy-picker-menu-RVOQ4ZZG.js.map} +0 -0
- /package/dist/{queue-surface-implementation-LK3S4BIW.js.map → queue-surface-implementation-3RIFK2BS.js.map} +0 -0
- /package/dist/{timeline-annotation-markers-DRSTLEM6.js.map → timeline-annotation-markers-OY6OWR3V.js.map} +0 -0
- /package/dist/{timeline-annotation-selection-IHLUGVND.js.map → timeline-annotation-selection-BOXA2TIN.js.map} +0 -0
- /package/dist/{timeline-annotations-dialog-6Q53N5FG.js.map → timeline-annotations-dialog-RGY3MHL3.js.map} +0 -0
|
@@ -119,19 +119,6 @@ function sourceDrivenDefaultTab(
|
|
|
119
119
|
return null;
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
function captureDegradedMessage(reason: string): string {
|
|
123
|
-
switch (reason) {
|
|
124
|
-
case "repository_discovery_timed_out":
|
|
125
|
-
return "Workspace capture is incomplete because repository discovery timed out. Live files remain authoritative.";
|
|
126
|
-
case "repository_discovery_result_limit_exceeded":
|
|
127
|
-
return "Workspace capture is incomplete because the repository limit was exceeded. Live files remain authoritative.";
|
|
128
|
-
case "repository_read_unavailable":
|
|
129
|
-
return "Workspace capture is incomplete because repository changes could not be read. Live files remain authoritative.";
|
|
130
|
-
default:
|
|
131
|
-
return "Workspace capture is incomplete because repository discovery failed. Live files remain authoritative.";
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
122
|
function WorkbenchSurfaceLoading({ name }: { name: "Browser" | "Desktop" }) {
|
|
136
123
|
return (
|
|
137
124
|
<CenteredState
|
|
@@ -555,23 +542,6 @@ export function useSandboxWorkspaceTabs(
|
|
|
555
542
|
if (advertised.length > 0) return advertised;
|
|
556
543
|
return captureState.capture?.repos.map((repo) => repo.root) ?? [];
|
|
557
544
|
}, [capabilities?.Git.repos, captureState.capture]);
|
|
558
|
-
const notifiedCaptureDegradedReason = useRef<{
|
|
559
|
-
sessionId: string;
|
|
560
|
-
reason: string | null;
|
|
561
|
-
}>({
|
|
562
|
-
sessionId,
|
|
563
|
-
reason: null,
|
|
564
|
-
});
|
|
565
|
-
if (notifiedCaptureDegradedReason.current.sessionId !== sessionId) {
|
|
566
|
-
notifiedCaptureDegradedReason.current = { sessionId, reason: null };
|
|
567
|
-
}
|
|
568
|
-
useEffect(() => {
|
|
569
|
-
const reason = captureState.degradedReason;
|
|
570
|
-
if (!reason || notifiedCaptureDegradedReason.current.reason === reason) return;
|
|
571
|
-
notifiedCaptureDegradedReason.current = { sessionId, reason };
|
|
572
|
-
onNotify?.({ kind: "error", message: captureDegradedMessage(reason) });
|
|
573
|
-
}, [sessionId, captureState.degradedReason, onNotify]);
|
|
574
|
-
|
|
575
545
|
const files = useSandboxFiles(sessionId, {
|
|
576
546
|
events,
|
|
577
547
|
// No passive Channel-A reads while cold, even after a conclusive capture
|
|
@@ -743,6 +713,7 @@ export function useSandboxWorkspaceTabs(
|
|
|
743
713
|
comparison={changesComparison}
|
|
744
714
|
onComparisonChange={setChangesComparison}
|
|
745
715
|
captureAvailable={captureAvailable}
|
|
716
|
+
captureDegraded={captureState.degradedReason !== null}
|
|
746
717
|
captureRevision={captureState.revision}
|
|
747
718
|
capturePending={capturePending}
|
|
748
719
|
liveWorkspaceExpected={liveWorkspaceExpected}
|
|
@@ -928,6 +899,7 @@ export function useSandboxWorkspaceTabs(
|
|
|
928
899
|
browserEnabled,
|
|
929
900
|
desktopEnabled,
|
|
930
901
|
captureAvailable,
|
|
902
|
+
captureState.degradedReason,
|
|
931
903
|
dirtyCount,
|
|
932
904
|
warmTerminal,
|
|
933
905
|
requestedFilePath,
|
|
@@ -1354,6 +1326,7 @@ function ChangesTabContent({
|
|
|
1354
1326
|
git,
|
|
1355
1327
|
comparison,
|
|
1356
1328
|
captureAvailable,
|
|
1329
|
+
captureDegraded,
|
|
1357
1330
|
captureRevision,
|
|
1358
1331
|
capturePending,
|
|
1359
1332
|
liveWorkspaceExpected,
|
|
@@ -1367,6 +1340,7 @@ function ChangesTabContent({
|
|
|
1367
1340
|
git: UseSandboxGitResult;
|
|
1368
1341
|
comparison: SandboxGitComparison;
|
|
1369
1342
|
captureAvailable: boolean;
|
|
1343
|
+
captureDegraded: boolean;
|
|
1370
1344
|
captureRevision: number | null;
|
|
1371
1345
|
capturePending: boolean;
|
|
1372
1346
|
liveWorkspaceExpected: boolean;
|
|
@@ -1460,6 +1434,8 @@ function ChangesTabContent({
|
|
|
1460
1434
|
}
|
|
1461
1435
|
|
|
1462
1436
|
if (!liveWorkspaceExpected && (comparison !== "working" || !captureAvailable)) {
|
|
1437
|
+
// Staged changes are live-only; a failed saved preview is not their blocker.
|
|
1438
|
+
const previewUnavailable = captureDegraded && !captureAvailable && comparison !== "staged";
|
|
1463
1439
|
return (
|
|
1464
1440
|
<CenteredState
|
|
1465
1441
|
icon={
|
|
@@ -1468,22 +1444,30 @@ function ChangesTabContent({
|
|
|
1468
1444
|
className="size-5 animate-spin motion-reduce:animate-none"
|
|
1469
1445
|
aria-hidden
|
|
1470
1446
|
/>
|
|
1447
|
+
) : previewUnavailable ? (
|
|
1448
|
+
<TriangleAlertIcon className="size-5" aria-hidden />
|
|
1471
1449
|
) : (
|
|
1472
1450
|
<CpuIcon className="size-5" aria-hidden />
|
|
1473
1451
|
)
|
|
1474
1452
|
}
|
|
1475
1453
|
>
|
|
1476
1454
|
<p className="text-og-sm font-medium text-og-fg">
|
|
1477
|
-
{workspaceWaking
|
|
1455
|
+
{workspaceWaking
|
|
1456
|
+
? "Waking workspace"
|
|
1457
|
+
: previewUnavailable
|
|
1458
|
+
? "Saved changes preview is unavailable"
|
|
1459
|
+
: "Workspace is resting"}
|
|
1478
1460
|
</p>
|
|
1479
1461
|
<p className="text-og-sm leading-5 text-og-fg-subtle">
|
|
1480
1462
|
{workspaceWaking
|
|
1481
1463
|
? "Connecting to the live working tree…"
|
|
1482
|
-
:
|
|
1483
|
-
? "
|
|
1484
|
-
: comparison === "
|
|
1485
|
-
? "Wake the sandbox to
|
|
1486
|
-
:
|
|
1464
|
+
: previewUnavailable
|
|
1465
|
+
? "Open the live workspace to view current changes."
|
|
1466
|
+
: comparison === "branch"
|
|
1467
|
+
? "Wake the sandbox to compare this branch with the remote default branch."
|
|
1468
|
+
: comparison === "staged"
|
|
1469
|
+
? "Wake the sandbox to inspect staged changes."
|
|
1470
|
+
: "No captured revision is available yet. Wake the sandbox to inspect uncommitted changes."}
|
|
1487
1471
|
</p>
|
|
1488
1472
|
{!workspaceWaking ? (
|
|
1489
1473
|
<DockActionButton onClick={onWake}>
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { CheckIcon, ShieldCheckIcon, XIcon } from "lucide-react";
|
|
2
|
+
import { Dialog } from "radix-ui";
|
|
3
|
+
import { useRef, useState, type ReactNode, type RefObject } from "react";
|
|
4
|
+
import { usePortalTokenStyle } from "../lib/use-portal-token-style";
|
|
5
|
+
|
|
6
|
+
export type SessionCapabilityFrameProps = {
|
|
7
|
+
name: string;
|
|
8
|
+
subtitle: string;
|
|
9
|
+
logo: string | null;
|
|
10
|
+
typeLabel: string;
|
|
11
|
+
description: string;
|
|
12
|
+
skill: boolean;
|
|
13
|
+
expanded: boolean;
|
|
14
|
+
complete: boolean;
|
|
15
|
+
actionLabel: string;
|
|
16
|
+
note: string;
|
|
17
|
+
onOpen(): void;
|
|
18
|
+
onClose(): void;
|
|
19
|
+
busy?: boolean;
|
|
20
|
+
opener?: RefObject<HTMLButtonElement | null>;
|
|
21
|
+
cardRef?: RefObject<HTMLElement | null>;
|
|
22
|
+
children?: ReactNode;
|
|
23
|
+
/** A catalogue row can own the opener while reusing the same details dialog. */
|
|
24
|
+
dialogOnly?: boolean;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
function Mark({ src, name }: { src: string | null; name: string }) {
|
|
28
|
+
const [failed, setFailed] = useState<string | null>(null);
|
|
29
|
+
return (
|
|
30
|
+
<span className="og-session-capability-logo" aria-hidden>
|
|
31
|
+
{src && failed !== src ? (
|
|
32
|
+
<img src={src} alt="" loading="lazy" decoding="async" onError={() => setFailed(src)} />
|
|
33
|
+
) : (
|
|
34
|
+
name.trim().slice(0, 2).toUpperCase()
|
|
35
|
+
)}
|
|
36
|
+
</span>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** The same conversation card in the console and embedded clients. Setup
|
|
41
|
+
* content owns the provider flow; this frame owns identity and protected focus. */
|
|
42
|
+
export function SessionCapabilityFrame({
|
|
43
|
+
name,
|
|
44
|
+
subtitle,
|
|
45
|
+
logo,
|
|
46
|
+
typeLabel,
|
|
47
|
+
description,
|
|
48
|
+
skill,
|
|
49
|
+
expanded,
|
|
50
|
+
complete,
|
|
51
|
+
actionLabel,
|
|
52
|
+
note,
|
|
53
|
+
onOpen,
|
|
54
|
+
onClose,
|
|
55
|
+
busy = false,
|
|
56
|
+
opener,
|
|
57
|
+
cardRef,
|
|
58
|
+
children,
|
|
59
|
+
dialogOnly = false,
|
|
60
|
+
}: SessionCapabilityFrameProps) {
|
|
61
|
+
const localOpener = useRef<HTMLButtonElement>(null);
|
|
62
|
+
const localCard = useRef<HTMLElement>(null);
|
|
63
|
+
const buttonRef = opener ?? localOpener;
|
|
64
|
+
const sectionRef = cardRef ?? localCard;
|
|
65
|
+
const portalStyle = usePortalTokenStyle(sectionRef.current);
|
|
66
|
+
const identity = (
|
|
67
|
+
<>
|
|
68
|
+
<Mark src={logo} name={name} />
|
|
69
|
+
<div className="og-session-capability-identity">
|
|
70
|
+
<h3>{name}</h3>
|
|
71
|
+
<span>{subtitle}</span>
|
|
72
|
+
</div>
|
|
73
|
+
<span className="og-session-capability-type">{typeLabel}</span>
|
|
74
|
+
</>
|
|
75
|
+
);
|
|
76
|
+
return (
|
|
77
|
+
<div className="og-session-capability">
|
|
78
|
+
<section
|
|
79
|
+
hidden={dialogOnly}
|
|
80
|
+
style={dialogOnly ? { display: "none" } : undefined}
|
|
81
|
+
ref={sectionRef}
|
|
82
|
+
tabIndex={-1}
|
|
83
|
+
aria-label={`${name} setup`}
|
|
84
|
+
data-state={complete ? "complete" : expanded ? "setup" : "suggested"}
|
|
85
|
+
className="og-session-capability-shell"
|
|
86
|
+
>
|
|
87
|
+
<div className="og-session-capability-header">
|
|
88
|
+
{identity}
|
|
89
|
+
{complete ? <CheckIcon size={16} aria-hidden /> : null}
|
|
90
|
+
</div>
|
|
91
|
+
{complete ? (
|
|
92
|
+
<p role="status" className="og-session-capability-copy">
|
|
93
|
+
{skill ? "Installed · Workspace" : "Connected · Available in this conversation"}
|
|
94
|
+
</p>
|
|
95
|
+
) : (
|
|
96
|
+
<>
|
|
97
|
+
<p className="og-session-capability-copy">{description}</p>
|
|
98
|
+
<div className="og-session-capability-actions">
|
|
99
|
+
<span>
|
|
100
|
+
<ShieldCheckIcon size={13} aria-hidden />
|
|
101
|
+
{skill ? "Guidance only · no account access" : "You choose what to authorize"}
|
|
102
|
+
</span>
|
|
103
|
+
<button
|
|
104
|
+
ref={buttonRef}
|
|
105
|
+
type="button"
|
|
106
|
+
onClick={onOpen}
|
|
107
|
+
aria-haspopup="dialog"
|
|
108
|
+
aria-expanded={expanded}
|
|
109
|
+
>
|
|
110
|
+
{actionLabel}
|
|
111
|
+
</button>
|
|
112
|
+
</div>
|
|
113
|
+
</>
|
|
114
|
+
)}
|
|
115
|
+
</section>
|
|
116
|
+
{!complete && !dialogOnly ? <p className="og-session-capability-note">{note}</p> : null}
|
|
117
|
+
<Dialog.Root
|
|
118
|
+
open={expanded && !complete}
|
|
119
|
+
onOpenChange={(open) => {
|
|
120
|
+
if (!open && !busy) onClose();
|
|
121
|
+
}}
|
|
122
|
+
>
|
|
123
|
+
<Dialog.Portal>
|
|
124
|
+
<Dialog.Overlay className="og-root og-session-capability-overlay" style={portalStyle} />
|
|
125
|
+
<Dialog.Content
|
|
126
|
+
className="og-root og-session-capability-dialog"
|
|
127
|
+
style={portalStyle}
|
|
128
|
+
onEscapeKeyDown={(event) => {
|
|
129
|
+
if (busy) event.preventDefault();
|
|
130
|
+
}}
|
|
131
|
+
onInteractOutside={(event) => {
|
|
132
|
+
if (busy) event.preventDefault();
|
|
133
|
+
}}
|
|
134
|
+
onCloseAutoFocus={(event) => {
|
|
135
|
+
event.preventDefault();
|
|
136
|
+
const target = buttonRef.current?.isConnected
|
|
137
|
+
? buttonRef.current
|
|
138
|
+
: sectionRef.current;
|
|
139
|
+
if (target?.isConnected) target.focus();
|
|
140
|
+
}}
|
|
141
|
+
>
|
|
142
|
+
<div className="og-session-capability-dialog-header">
|
|
143
|
+
<Mark src={logo} name={name} />
|
|
144
|
+
<div>
|
|
145
|
+
<Dialog.Title>{name}</Dialog.Title>
|
|
146
|
+
<Dialog.Description>
|
|
147
|
+
{typeLabel}
|
|
148
|
+
{subtitle ? ` · ${subtitle}` : ""}
|
|
149
|
+
</Dialog.Description>
|
|
150
|
+
</div>
|
|
151
|
+
{!busy ? (
|
|
152
|
+
<Dialog.Close aria-label="Close connection setup">
|
|
153
|
+
<XIcon size={18} />
|
|
154
|
+
</Dialog.Close>
|
|
155
|
+
) : null}
|
|
156
|
+
</div>
|
|
157
|
+
<div className="og-session-capability-dialog-body">{children}</div>
|
|
158
|
+
</Dialog.Content>
|
|
159
|
+
</Dialog.Portal>
|
|
160
|
+
</Dialog.Root>
|
|
161
|
+
</div>
|
|
162
|
+
);
|
|
163
|
+
}
|
|
@@ -94,7 +94,6 @@ export type SessionChromeAgentsSignal = {
|
|
|
94
94
|
};
|
|
95
95
|
|
|
96
96
|
export type SessionChromeProps = {
|
|
97
|
-
compact?: boolean;
|
|
98
97
|
/** Authoritative execution status; omitted by older embedding hosts. */
|
|
99
98
|
sessionStatus?: SessionStatus | undefined;
|
|
100
99
|
queue: UseTurnQueueResult;
|
|
@@ -432,7 +431,6 @@ function toneClass(tone: SessionChromeSignalTone, selected: boolean): string {
|
|
|
432
431
|
}
|
|
433
432
|
|
|
434
433
|
export function SessionChrome({
|
|
435
|
-
compact = false,
|
|
436
434
|
sessionStatus,
|
|
437
435
|
queue,
|
|
438
436
|
composer,
|
|
@@ -451,7 +449,7 @@ export function SessionChrome({
|
|
|
451
449
|
onActiveChange,
|
|
452
450
|
}: SessionChromeProps) {
|
|
453
451
|
const [activityRequested, setActivityOpen] = useState(
|
|
454
|
-
Boolean(
|
|
452
|
+
Boolean(defaultActive && ["incoming", "agents", "commands"].includes(defaultActive)),
|
|
455
453
|
);
|
|
456
454
|
const reactId = useId();
|
|
457
455
|
const panelId = `og-session-chrome-panel-${reactId}`;
|
|
@@ -499,8 +497,7 @@ export function SessionChrome({
|
|
|
499
497
|
);
|
|
500
498
|
const active = activeControlled !== undefined ? activeControlled : activeUncontrolled;
|
|
501
499
|
const activityOpen =
|
|
502
|
-
activityRequested ||
|
|
503
|
-
Boolean(compact && active && ["incoming", "agents", "commands"].includes(active));
|
|
500
|
+
activityRequested || Boolean(active && ["incoming", "agents", "commands"].includes(active));
|
|
504
501
|
const activityVisibleRef = useRef(activityOpen);
|
|
505
502
|
activityVisibleRef.current = activityOpen;
|
|
506
503
|
// Two independent suppressions, both occupancy-scoped:
|
|
@@ -711,12 +708,9 @@ export function SessionChrome({
|
|
|
711
708
|
|
|
712
709
|
const signalIds = signals.map((signal) => signal.id).join(",");
|
|
713
710
|
useEffect(() => {
|
|
714
|
-
if (
|
|
715
|
-
compact &&
|
|
716
|
-
!signals.some((signal) => ["incoming", "agents", "commands"].includes(signal.id))
|
|
717
|
-
)
|
|
711
|
+
if (!signals.some((signal) => ["incoming", "agents", "commands"].includes(signal.id)))
|
|
718
712
|
setActivityOpen(false);
|
|
719
|
-
}, [
|
|
713
|
+
}, [signals]);
|
|
720
714
|
useEffect(() => {
|
|
721
715
|
if (active && !signalIds.split(",").includes(active)) {
|
|
722
716
|
if (activeControlled === undefined) setActiveUncontrolled(null);
|
|
@@ -885,21 +879,9 @@ export function SessionChrome({
|
|
|
885
879
|
)}
|
|
886
880
|
style={{
|
|
887
881
|
borderRadius: "var(--_og-session-chrome-radius)",
|
|
888
|
-
background:
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
? "var(--_og-session-chrome-surface-open)"
|
|
892
|
-
: "var(--_og-session-chrome-surface)",
|
|
893
|
-
borderColor: compact
|
|
894
|
-
? "transparent"
|
|
895
|
-
: open
|
|
896
|
-
? "var(--_og-session-chrome-border-open)"
|
|
897
|
-
: "var(--_og-session-chrome-border)",
|
|
898
|
-
boxShadow: compact
|
|
899
|
-
? "none"
|
|
900
|
-
: open
|
|
901
|
-
? "var(--og-session-chrome-shadow-open)"
|
|
902
|
-
: "var(--og-session-chrome-shadow)",
|
|
882
|
+
background: "transparent",
|
|
883
|
+
borderColor: "transparent",
|
|
884
|
+
boxShadow: "none",
|
|
903
885
|
transitionDuration: "var(--og-session-chrome-duration)",
|
|
904
886
|
transitionTimingFunction: "var(--_og-session-chrome-ease)",
|
|
905
887
|
}}
|
|
@@ -915,9 +897,9 @@ export function SessionChrome({
|
|
|
915
897
|
>
|
|
916
898
|
<div
|
|
917
899
|
ref={railRef}
|
|
918
|
-
className=
|
|
900
|
+
className="relative flex flex-nowrap items-center"
|
|
919
901
|
style={{
|
|
920
|
-
gap:
|
|
902
|
+
gap: "10px",
|
|
921
903
|
}}
|
|
922
904
|
>
|
|
923
905
|
<motion.div
|
|
@@ -938,9 +920,7 @@ export function SessionChrome({
|
|
|
938
920
|
transition={{ duration: shellDuration, ease }}
|
|
939
921
|
/>
|
|
940
922
|
{signals
|
|
941
|
-
.filter(
|
|
942
|
-
(signal) => !compact || !["incoming", "agents", "commands"].includes(signal.id),
|
|
943
|
-
)
|
|
923
|
+
.filter((signal) => !["incoming", "agents", "commands"].includes(signal.id))
|
|
944
924
|
.map((signal) => {
|
|
945
925
|
const selected = active === signal.id;
|
|
946
926
|
return (
|
|
@@ -956,8 +936,8 @@ export function SessionChrome({
|
|
|
956
936
|
}
|
|
957
937
|
className={cn(
|
|
958
938
|
"group/signal relative z-[1] inline-flex min-w-0 max-w-full items-center rounded-og-md",
|
|
959
|
-
|
|
960
|
-
|
|
939
|
+
"bg-og-surface-2/60 px-0.5",
|
|
940
|
+
selected && "bg-og-surface-3",
|
|
961
941
|
)}
|
|
962
942
|
>
|
|
963
943
|
<button
|
|
@@ -968,7 +948,7 @@ export function SessionChrome({
|
|
|
968
948
|
aria-expanded={selected}
|
|
969
949
|
aria-controls={panelId}
|
|
970
950
|
aria-label={
|
|
971
|
-
|
|
951
|
+
signal.id === "goal"
|
|
972
952
|
? `Goal · ${goalState === "pursuing" ? "Running" : signal.label}`
|
|
973
953
|
: selected
|
|
974
954
|
? `Close ${signal.label}`
|
|
@@ -976,9 +956,9 @@ export function SessionChrome({
|
|
|
976
956
|
}
|
|
977
957
|
data-testid={`session-chrome-${signal.id}`}
|
|
978
958
|
data-og-session-chrome-signal={signal.id}
|
|
979
|
-
title={signal.title ??
|
|
959
|
+
title={signal.title ?? signal.label}
|
|
980
960
|
onClick={() => {
|
|
981
|
-
|
|
961
|
+
setActivityOpen(false);
|
|
982
962
|
setActive(selected ? null : signal.id);
|
|
983
963
|
}}
|
|
984
964
|
className={cn(
|
|
@@ -1007,43 +987,21 @@ export function SessionChrome({
|
|
|
1007
987
|
<span className={cn("shrink-0", toneClass(signal.tone, selected))}>
|
|
1008
988
|
{signal.icon}
|
|
1009
989
|
</span>
|
|
1010
|
-
<span
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
compact ? "min-w-0 truncate" : "shrink-0",
|
|
1014
|
-
)}
|
|
1015
|
-
>
|
|
1016
|
-
{compact && signal.id === "goal" ? "Goal · " : null}
|
|
1017
|
-
{compact && signal.id === "goal"
|
|
990
|
+
<span className={cn("font-medium text-og-fg", "min-w-0 truncate")}>
|
|
991
|
+
{signal.id === "goal" ? "Goal · " : null}
|
|
992
|
+
{signal.id === "goal"
|
|
1018
993
|
? goalState === "pursuing"
|
|
1019
994
|
? "Running"
|
|
1020
995
|
: signal.label
|
|
1021
|
-
:
|
|
1022
|
-
?
|
|
996
|
+
: signal.id === "queue"
|
|
997
|
+
? queue.error || queue.mutationError
|
|
998
|
+
? signal.label
|
|
999
|
+
: `${queuedTurns.length + optimisticQueued.length} queued`
|
|
1023
1000
|
: signal.label}
|
|
1024
1001
|
</span>
|
|
1025
|
-
{signal.detail && !compact ? (
|
|
1026
|
-
<>
|
|
1027
|
-
<span aria-hidden className="shrink-0 text-og-fg-subtle/60">
|
|
1028
|
-
·
|
|
1029
|
-
</span>
|
|
1030
|
-
<span className="min-w-0 max-w-[8.5rem] truncate text-og-fg sm:max-w-[12rem]">
|
|
1031
|
-
{signal.detail}
|
|
1032
|
-
</span>
|
|
1033
|
-
</>
|
|
1034
|
-
) : null}
|
|
1035
|
-
{selected && !compact ? (
|
|
1036
|
-
<span
|
|
1037
|
-
data-testid="session-chrome-close"
|
|
1038
|
-
className="ml-0.5 inline-flex size-4 shrink-0 items-center justify-center rounded-og-sm text-og-fg-subtle transition-colors group-hover:text-og-fg pointer-coarse:size-5"
|
|
1039
|
-
aria-hidden
|
|
1040
|
-
>
|
|
1041
|
-
<XIcon className="size-3" />
|
|
1042
|
-
</span>
|
|
1043
|
-
) : null}
|
|
1044
1002
|
</button>
|
|
1045
1003
|
{signal.id === "goal" && goal && record && !readOnly ? (
|
|
1046
|
-
<div className=
|
|
1004
|
+
<div className="flex shrink-0 items-center pr-1 pl-0.5">
|
|
1047
1005
|
{record.status === "active" || record.status === "paused" ? (
|
|
1048
1006
|
<IconAction
|
|
1049
1007
|
label={record.status === "paused" ? "Resume goal" : "Pause goal"}
|
|
@@ -1075,7 +1033,7 @@ export function SessionChrome({
|
|
|
1075
1033
|
</IconAction>
|
|
1076
1034
|
</div>
|
|
1077
1035
|
) : signal.id === "queue" && canMutateQueue && queuedTurns[0] ? (
|
|
1078
|
-
<div className=
|
|
1036
|
+
<div className="flex shrink-0 items-center pr-1 pl-0.5">
|
|
1079
1037
|
<IconAction
|
|
1080
1038
|
label="Steer first queued message"
|
|
1081
1039
|
text="Steer"
|
|
@@ -1092,11 +1050,11 @@ export function SessionChrome({
|
|
|
1092
1050
|
</div>
|
|
1093
1051
|
);
|
|
1094
1052
|
})}
|
|
1095
|
-
{
|
|
1096
|
-
signals.some((signal) => ["incoming", "agents", "commands"].includes(signal.id)) ? (
|
|
1053
|
+
{signals.some((signal) => ["incoming", "agents", "commands"].includes(signal.id)) ? (
|
|
1097
1054
|
<button
|
|
1098
1055
|
type="button"
|
|
1099
1056
|
aria-label="Session activity"
|
|
1057
|
+
aria-describedby={commandsCount > 0 ? `${panelId}-commands-count` : undefined}
|
|
1100
1058
|
title={activityOpen ? "Close activity" : "Inbox, agents and commands"}
|
|
1101
1059
|
aria-controls={panelId}
|
|
1102
1060
|
aria-expanded={activityOpen}
|
|
@@ -1105,9 +1063,11 @@ export function SessionChrome({
|
|
|
1105
1063
|
setActive(
|
|
1106
1064
|
activityOpen
|
|
1107
1065
|
? null
|
|
1108
|
-
:
|
|
1109
|
-
|
|
1110
|
-
)
|
|
1066
|
+
: commandsCount > 0 && hasCommandsPanel
|
|
1067
|
+
? "commands"
|
|
1068
|
+
: (signals.find((signal) =>
|
|
1069
|
+
["incoming", "agents", "commands"].includes(signal.id),
|
|
1070
|
+
)?.id ?? null),
|
|
1111
1071
|
);
|
|
1112
1072
|
}}
|
|
1113
1073
|
className={cn(
|
|
@@ -1119,6 +1079,17 @@ export function SessionChrome({
|
|
|
1119
1079
|
>
|
|
1120
1080
|
<ActivityIcon className="size-3.5" />
|
|
1121
1081
|
<span className="sr-only">Activity</span>
|
|
1082
|
+
{commandsCount > 0 ? (
|
|
1083
|
+
<>
|
|
1084
|
+
<span
|
|
1085
|
+
aria-hidden="true"
|
|
1086
|
+
className="size-1.5 shrink-0 animate-og-pulse rounded-full bg-og-fg-muted motion-reduce:animate-none"
|
|
1087
|
+
/>
|
|
1088
|
+
<span id={`${panelId}-commands-count`}>
|
|
1089
|
+
{commandsCount} command{commandsCount === 1 ? "" : "s"}
|
|
1090
|
+
</span>
|
|
1091
|
+
</>
|
|
1092
|
+
) : null}
|
|
1122
1093
|
{incoming.length > 0 ? (
|
|
1123
1094
|
<span className="size-1.5 rounded-full bg-og-accent" />
|
|
1124
1095
|
) : null}
|
|
@@ -1142,7 +1113,7 @@ export function SessionChrome({
|
|
|
1142
1113
|
</div>
|
|
1143
1114
|
|
|
1144
1115
|
<AnimatePresence initial={false}>
|
|
1145
|
-
{
|
|
1116
|
+
{activityOpen ? (
|
|
1146
1117
|
<motion.div
|
|
1147
1118
|
key="activity-tabs"
|
|
1148
1119
|
initial={{ height: 0, opacity: 0 }}
|
|
@@ -1201,11 +1172,9 @@ export function SessionChrome({
|
|
|
1201
1172
|
<div
|
|
1202
1173
|
className={cn(
|
|
1203
1174
|
"relative overflow-y-auto overscroll-contain",
|
|
1204
|
-
|
|
1205
|
-
?
|
|
1206
|
-
|
|
1207
|
-
: "mt-1 rounded-og-lg bg-og-surface-2/50"
|
|
1208
|
-
: "border-t border-og-border/50",
|
|
1175
|
+
activityOpen
|
|
1176
|
+
? "rounded-b-og-lg bg-og-surface-2/50"
|
|
1177
|
+
: "mt-1 rounded-og-lg bg-og-surface-2/50",
|
|
1209
1178
|
)}
|
|
1210
1179
|
style={{
|
|
1211
1180
|
maxHeight: "var(--og-session-chrome-panel-max-height)",
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useSessionBackgroundCommands,
|
|
3
|
+
type UseSessionBackgroundCommandsOptions,
|
|
4
|
+
} from "../hooks/use-session-background-commands";
|
|
5
|
+
import { SessionCommandsPanel } from "./session-commands-panel";
|
|
6
|
+
|
|
7
|
+
/** Mount in the open activity panel so closed chrome never polls commands. */
|
|
8
|
+
export function SessionCommands({
|
|
9
|
+
sessionId,
|
|
10
|
+
readOnly = false,
|
|
11
|
+
...options
|
|
12
|
+
}: UseSessionBackgroundCommandsOptions & { sessionId: string; readOnly?: boolean }) {
|
|
13
|
+
const commands = useSessionBackgroundCommands(sessionId, {
|
|
14
|
+
pollIntervalMs: 3_000,
|
|
15
|
+
...options,
|
|
16
|
+
});
|
|
17
|
+
return <SessionCommandsPanel commands={commands} readOnly={readOnly} />;
|
|
18
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from "react";
|
|
2
|
+
import type { AuthNeededItem } from "../timeline/types";
|
|
3
|
+
import { sessionAuthRecommendation } from "../session-auth-recommendation";
|
|
4
|
+
import {
|
|
5
|
+
SessionMcpCapabilityCard,
|
|
6
|
+
type SessionMcpCapabilityCardProps,
|
|
7
|
+
} from "./session-mcp-capability-card";
|
|
8
|
+
|
|
9
|
+
export type SessionConnectionRequestProps = Omit<
|
|
10
|
+
SessionMcpCapabilityCardProps,
|
|
11
|
+
"capabilityId" | "name" | "rationale"
|
|
12
|
+
> & {
|
|
13
|
+
request: AuthNeededItem;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/** Resolve native reauthorization notices with the same exact-identity rules
|
|
17
|
+
* as the console. Recommendations never supply endpoints or account authority. */
|
|
18
|
+
export function SessionConnectionRequest(props: SessionConnectionRequestProps) {
|
|
19
|
+
const [client, setClient] = useState(props.client);
|
|
20
|
+
const [generation, setGeneration] = useState(0);
|
|
21
|
+
if (client !== props.client) {
|
|
22
|
+
setClient(props.client);
|
|
23
|
+
setGeneration(generation + 1);
|
|
24
|
+
}
|
|
25
|
+
return (
|
|
26
|
+
<ScopedRequest
|
|
27
|
+
key={`${generation}:${props.workspaceId}:${props.sessionId}:${props.request.id}`}
|
|
28
|
+
{...props}
|
|
29
|
+
/>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function ScopedRequest({ request, ...props }: SessionConnectionRequestProps) {
|
|
34
|
+
const [resolved, setResolved] = useState<AuthNeededItem | null>(null);
|
|
35
|
+
const [error, setError] = useState<string | null>(null);
|
|
36
|
+
const [retry, setRetry] = useState(0);
|
|
37
|
+
const requestRef = useRef(request);
|
|
38
|
+
requestRef.current = request;
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
let current = true;
|
|
41
|
+
const event = requestRef.current;
|
|
42
|
+
setResolved(null);
|
|
43
|
+
setError(null);
|
|
44
|
+
void props.client
|
|
45
|
+
.listCapabilities(props.workspaceId)
|
|
46
|
+
.then((catalog) => {
|
|
47
|
+
if (!current) return;
|
|
48
|
+
const recommendation = sessionAuthRecommendation(event, catalog.items);
|
|
49
|
+
const candidate = catalog.items.find(
|
|
50
|
+
(entry) => entry.id === recommendation?.capability?.id,
|
|
51
|
+
);
|
|
52
|
+
if (!recommendation || candidate?.kind !== "mcp" || candidate.authKind !== "oauth2") {
|
|
53
|
+
setError(
|
|
54
|
+
"This request could not be matched to one available OAuth integration. Review its connection settings before continuing.",
|
|
55
|
+
);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
setResolved(recommendation);
|
|
59
|
+
})
|
|
60
|
+
.catch(() => {
|
|
61
|
+
if (current)
|
|
62
|
+
setError("Couldn't load connection details. Retry to check the current integration.");
|
|
63
|
+
});
|
|
64
|
+
return () => {
|
|
65
|
+
current = false;
|
|
66
|
+
};
|
|
67
|
+
}, [
|
|
68
|
+
props.client,
|
|
69
|
+
props.workspaceId,
|
|
70
|
+
request.id,
|
|
71
|
+
request.serverId,
|
|
72
|
+
request.connectionId,
|
|
73
|
+
request.authoritySource,
|
|
74
|
+
request.reason,
|
|
75
|
+
request.capability?.id,
|
|
76
|
+
retry,
|
|
77
|
+
]);
|
|
78
|
+
if (!resolved?.capability)
|
|
79
|
+
return (
|
|
80
|
+
<div className="og-session-capability-setup">
|
|
81
|
+
<p role={error ? "alert" : "status"}>{error ?? "Loading connection details…"}</p>
|
|
82
|
+
{error ? (
|
|
83
|
+
<button type="button" onClick={() => setRetry((value) => value + 1)}>
|
|
84
|
+
Retry
|
|
85
|
+
</button>
|
|
86
|
+
) : null}
|
|
87
|
+
</div>
|
|
88
|
+
);
|
|
89
|
+
return (
|
|
90
|
+
<SessionMcpCapabilityCard
|
|
91
|
+
{...props}
|
|
92
|
+
capabilityId={resolved.capability.id}
|
|
93
|
+
name={resolved.capability.name}
|
|
94
|
+
rationale={resolved.capability.rationale}
|
|
95
|
+
/>
|
|
96
|
+
);
|
|
97
|
+
}
|