@opengeni/react 6.0.0-canary.1 → 6.1.0-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +17 -0
  2. package/dist/capability-catalog-row.d.ts +20 -0
  3. package/dist/{chunk-VRBL3F5E.js → chunk-5GAL23FF.js} +10 -2
  4. package/dist/{chunk-VRBL3F5E.js.map → chunk-5GAL23FF.js.map} +1 -1
  5. package/dist/{chunk-IHQII5WO.js → chunk-G5JFM6ZE.js} +29 -4
  6. package/dist/chunk-G5JFM6ZE.js.map +1 -0
  7. package/dist/{chunk-UMECRJRV.js → chunk-HJ5VJ4JB.js} +21 -12
  8. package/dist/chunk-HJ5VJ4JB.js.map +1 -0
  9. package/dist/{chunk-R4KRSFGA.js → chunk-IP4BUBKH.js} +3 -3
  10. package/dist/{chunk-CC7AVRIJ.js → chunk-KZ4QDBGM.js} +87 -14
  11. package/dist/chunk-KZ4QDBGM.js.map +1 -0
  12. package/dist/{chunk-PZ27MCZP.js → chunk-L5VJYZIW.js} +34 -4
  13. package/dist/chunk-L5VJYZIW.js.map +1 -0
  14. package/dist/{chunk-45XEUVTK.js → chunk-UWVY3OXF.js} +12 -5
  15. package/dist/chunk-UWVY3OXF.js.map +1 -0
  16. package/dist/components/message-timeline.d.ts +2 -2
  17. package/dist/composer.js +4 -4
  18. package/dist/connect-panel.d.ts +2 -1
  19. package/dist/connect-setup.d.ts +3 -1
  20. package/dist/connect.d.ts +1 -0
  21. package/dist/connect.js +620 -424
  22. package/dist/connect.js.map +1 -1
  23. package/dist/connection-catalog.d.ts +6 -1
  24. package/dist/connection-installed.d.ts +1 -0
  25. package/dist/connection-logo.d.ts +4 -2
  26. package/dist/discovery-cache.d.ts +5 -0
  27. package/dist/index.js +7 -7
  28. package/dist/{model-policy-picker-menu-3R336DP2.js → model-policy-picker-menu-RVOQ4ZZG.js} +4 -4
  29. package/dist/model-policy.d.ts +6 -2
  30. package/dist/model-policy.js +1 -1
  31. package/dist/plugin-discovery.d.ts +4 -0
  32. package/dist/realtime.js +2 -2
  33. package/dist/session-ui.js +6 -6
  34. package/dist/session.js +1 -1
  35. package/dist/skill-discovery.d.ts +11 -0
  36. package/dist/timeline/projection.d.ts +3 -1
  37. package/dist/timeline/turn-summary.d.ts +2 -2
  38. package/package.json +3 -3
  39. package/src/capability-catalog-row.tsx +94 -0
  40. package/src/components/markdown.tsx +32 -3
  41. package/src/components/message-timeline.tsx +88 -4
  42. package/src/components/model-picker.tsx +11 -3
  43. package/src/components/model-policy-picker-menu.tsx +10 -3
  44. package/src/components/session-conversation.tsx +1 -3
  45. package/src/components/session-status.tsx +2 -2
  46. package/src/connect-panel.tsx +19 -8
  47. package/src/connect-setup.tsx +49 -14
  48. package/src/connect.ts +6 -0
  49. package/src/connection-catalog.tsx +61 -39
  50. package/src/connection-installed.tsx +2 -0
  51. package/src/connection-logo.tsx +14 -10
  52. package/src/discovery-cache.ts +42 -0
  53. package/src/hooks/use-session-events.ts +24 -2
  54. package/src/model-policy.ts +21 -0
  55. package/src/plugin-details.tsx +8 -5
  56. package/src/plugin-discovery.tsx +87 -71
  57. package/src/skill-discovery.tsx +101 -56
  58. package/src/timeline/projection.ts +31 -1
  59. package/src/timeline/turn-summary.tsx +3 -3
  60. package/styles/compiled.css +27 -0
  61. package/styles/connect.css +56 -15
  62. package/dist/chunk-45XEUVTK.js.map +0 -1
  63. package/dist/chunk-CC7AVRIJ.js.map +0 -1
  64. package/dist/chunk-IHQII5WO.js.map +0 -1
  65. package/dist/chunk-PZ27MCZP.js.map +0 -1
  66. package/dist/chunk-UMECRJRV.js.map +0 -1
  67. /package/dist/{chunk-R4KRSFGA.js.map → chunk-IP4BUBKH.js.map} +0 -0
  68. /package/dist/{model-policy-picker-menu-3R336DP2.js.map → model-policy-picker-menu-RVOQ4ZZG.js.map} +0 -0
package/dist/connect.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import "./chunk-IWIDV7SB.js";
2
2
  import {
3
3
  Markdown
4
- } from "./chunk-IHQII5WO.js";
4
+ } from "./chunk-G5JFM6ZE.js";
5
5
  import {
6
6
  copyTextToClipboard
7
7
  } from "./chunk-JVYQRRC4.js";
@@ -12,15 +12,117 @@ import "./chunk-22KP6LR5.js";
12
12
  // src/connect.ts
13
13
  import { useMemo, useSyncExternalStore } from "react";
14
14
 
15
+ // src/capability-catalog-row.tsx
16
+ import { AlertTriangleIcon, CheckIcon, Loader2Icon, PlusIcon } from "lucide-react";
17
+ import { jsx, jsxs } from "react/jsx-runtime";
18
+ var labels = {
19
+ available: "Available to add",
20
+ added: "Added",
21
+ attention: "Needs attention",
22
+ unavailable: "Unavailable",
23
+ loading: "Working"
24
+ };
25
+ function CapabilityCatalogIndicator({
26
+ status = "available",
27
+ label,
28
+ showLabel = false
29
+ }) {
30
+ const Icon = status === "added" ? CheckIcon : status === "attention" || status === "unavailable" ? AlertTriangleIcon : status === "loading" ? Loader2Icon : PlusIcon;
31
+ return /* @__PURE__ */ jsxs("span", { className: "og-capability-catalog-indicator", "data-status": status, children: [
32
+ /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" }),
33
+ /* @__PURE__ */ jsx(
34
+ "span",
35
+ {
36
+ className: showLabel || status === "attention" || status === "unavailable" ? "og-capability-catalog-notice" : "og-capability-catalog-sr-only",
37
+ children: label ?? labels[status]
38
+ }
39
+ )
40
+ ] });
41
+ }
42
+ function CapabilityCatalogRow({
43
+ name,
44
+ description,
45
+ icon,
46
+ status = "available",
47
+ statusLabel,
48
+ showStatusLabel = false,
49
+ onOpen,
50
+ className = "",
51
+ ...props
52
+ }) {
53
+ return /* @__PURE__ */ jsxs(
54
+ "button",
55
+ {
56
+ ...props,
57
+ type: "button",
58
+ className: `og-capability-catalog-row ${className}`,
59
+ onClick: onOpen,
60
+ children: [
61
+ icon ? /* @__PURE__ */ jsx("span", { className: "og-capability-catalog-icon", children: icon }) : null,
62
+ /* @__PURE__ */ jsxs("span", { className: "og-capability-catalog-copy", children: [
63
+ /* @__PURE__ */ jsx("strong", { children: name }),
64
+ description ? /* @__PURE__ */ jsx("span", { children: description }) : null
65
+ ] }),
66
+ /* @__PURE__ */ jsx(CapabilityCatalogIndicator, { status, label: statusLabel, showLabel: showStatusLabel })
67
+ ]
68
+ }
69
+ );
70
+ }
71
+
15
72
  // src/skill-discovery.tsx
16
73
  import { useEffect, useState } from "react";
17
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
74
+
75
+ // src/discovery-cache.ts
76
+ function createDiscoveryCache(ttlMs = 6e4, capacity = 64) {
77
+ const clients = /* @__PURE__ */ new WeakMap();
78
+ return {
79
+ peek(client, key) {
80
+ const entry = clients.get(client)?.get(key);
81
+ return entry && entry.expires > Date.now() ? entry.value : void 0;
82
+ },
83
+ read(client, key, fetch) {
84
+ let entries = clients.get(client);
85
+ if (!entries) {
86
+ entries = /* @__PURE__ */ new Map();
87
+ clients.set(client, entries);
88
+ }
89
+ const existing = entries.get(key);
90
+ if (existing && existing.expires > Date.now()) return existing.pending;
91
+ entries.delete(key);
92
+ while (entries.size >= capacity) entries.delete(entries.keys().next().value);
93
+ const entry = {
94
+ expires: Date.now() + ttlMs,
95
+ value: void 0,
96
+ pending: Promise.resolve().then(fetch)
97
+ };
98
+ entries.set(key, entry);
99
+ entry.pending = entry.pending.then(
100
+ (value) => {
101
+ entry.value = value;
102
+ entry.expires = Date.now() + ttlMs;
103
+ return value;
104
+ },
105
+ (error) => {
106
+ if (entries.get(key) === entry) entries.delete(key);
107
+ throw error;
108
+ }
109
+ );
110
+ return entry.pending;
111
+ }
112
+ };
113
+ }
114
+
115
+ // src/skill-discovery.tsx
116
+ import { BookOpenIcon } from "lucide-react";
117
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
118
+ var discoveryCache = createDiscoveryCache();
18
119
  function SkillDiscovery(props) {
19
120
  const query = props.query.trim();
20
- return /* @__PURE__ */ jsxs("section", { className: "og-skill-discovery", "aria-label": "Discover skills", children: [
21
- /* @__PURE__ */ jsxs("header", { children: [
22
- /* @__PURE__ */ jsx("h3", { children: "Discover skills" }),
23
- /* @__PURE__ */ jsx(
121
+ const discoveryQuery = query || "agent";
122
+ return /* @__PURE__ */ jsxs2("section", { className: "og-skill-discovery", "aria-label": "Discover skills", children: [
123
+ /* @__PURE__ */ jsxs2("header", { children: [
124
+ /* @__PURE__ */ jsx2("h3", { children: props.resultLimit ? "Skills" : query ? "Search skills" : "Browse skills" }),
125
+ !props.resultLimit ? /* @__PURE__ */ jsx2(
24
126
  "a",
25
127
  {
26
128
  href: "https://skills.sh/",
@@ -29,12 +131,20 @@ function SkillDiscovery(props) {
29
131
  className: "og-skill-discovery-browse",
30
132
  children: "Browse skills.sh \u2197"
31
133
  }
32
- )
134
+ ) : null
33
135
  ] }),
34
- !query && props.onSearch ? /* @__PURE__ */ jsx("button", { type: "button", className: "og-skill-discovery-search", onClick: props.onSearch, children: "Search skills" }) : null,
35
- /* @__PURE__ */ jsx(DiscoveryResults, { ...props, query }, `${props.workspaceId}:${query}`)
136
+ !query ? /* @__PURE__ */ jsx2("p", { children: "Agent skills from skills.sh. Search above for another topic." }) : query.length < 2 ? /* @__PURE__ */ jsx2("p", { children: "Enter at least two characters to search skills.sh." }) : null,
137
+ /* @__PURE__ */ jsx2(
138
+ DiscoveryResults,
139
+ {
140
+ ...props,
141
+ query: discoveryQuery
142
+ },
143
+ `${props.workspaceId}:${discoveryQuery}`
144
+ )
36
145
  ] });
37
146
  }
147
+ var EMPTY_LOCAL_SKILLS = [];
38
148
  var EMPTY_INSTALLED_SKILLS = [];
39
149
  function DiscoveryResults({
40
150
  client,
@@ -42,21 +152,31 @@ function DiscoveryResults({
42
152
  query,
43
153
  canManage,
44
154
  onImport,
155
+ resultLimit,
156
+ onShowMore,
157
+ localSkills = EMPTY_LOCAL_SKILLS,
45
158
  installedSkills = EMPTY_INSTALLED_SKILLS
46
159
  }) {
47
- const [result, setResult] = useState(null);
48
- const [loading, setLoading] = useState(query.length >= 2);
160
+ const cacheKey = JSON.stringify([workspaceId, query]);
161
+ const cached = discoveryCache.peek(client, cacheKey);
162
+ const [result, setResult] = useState(cached ?? null);
163
+ const [loading, setLoading] = useState(query.length >= 2 && !cached);
49
164
  const [error, setError] = useState(false);
50
165
  const [retry, setRetry] = useState(0);
51
166
  useEffect(() => {
52
167
  let active = true;
53
168
  setError(false);
54
169
  if (query.length < 2) return;
55
- setLoading(true);
170
+ const existing = discoveryCache.peek(client, cacheKey);
171
+ setLoading(!existing);
56
172
  let timer;
57
173
  const search = async (attempt) => {
58
174
  try {
59
- const data = await client.searchPublicSkills(workspaceId, query);
175
+ const data = await discoveryCache.read(
176
+ client,
177
+ cacheKey,
178
+ () => client.searchPublicSkills(workspaceId, query)
179
+ );
60
180
  if (!active) return;
61
181
  setResult(data);
62
182
  setLoading(false);
@@ -72,54 +192,64 @@ function DiscoveryResults({
72
192
  setLoading(false);
73
193
  }
74
194
  };
75
- timer = setTimeout(() => void search(0), 300);
195
+ timer = setTimeout(() => void search(0), existing ? 0 : 300);
76
196
  return () => {
77
197
  active = false;
78
198
  clearTimeout(timer);
79
199
  };
80
- }, [client, workspaceId, query, retry]);
81
- return /* @__PURE__ */ jsxs("div", { "aria-busy": loading, children: [
82
- /* @__PURE__ */ jsx("div", { className: "og-skill-discovery-grid", children: result?.items.map((skill) => {
83
- const installed = installedSkills.some(
84
- (entry) => entry.sourceUrl.replace(/\/$/, "").toLowerCase() === skill.url.toLowerCase() || entry.repositoryUrl.replace(/\/$/, "").toLowerCase() === `https://github.com/${skill.source}`.toLowerCase() && entry.name.toLowerCase() === skill.name.toLowerCase()
85
- );
86
- return /* @__PURE__ */ jsxs(
87
- "button",
200
+ }, [client, workspaceId, query, cacheKey, retry]);
201
+ const remoteSkills = result?.items.filter(
202
+ (skill) => !localSkills.some((local) => local.name.toLowerCase() === skill.name.toLowerCase())
203
+ ) ?? [];
204
+ return /* @__PURE__ */ jsxs2("div", { "aria-busy": loading, children: [
205
+ /* @__PURE__ */ jsxs2("div", { className: "og-skill-discovery-grid", children: [
206
+ localSkills.slice(0, resultLimit).map((skill) => /* @__PURE__ */ jsx2(
207
+ CapabilityCatalogRow,
88
208
  {
89
- type: "button",
90
- className: "og-skill-discovery-item",
91
- disabled: !canManage,
92
- onClick: () => onImport(skill.url),
93
- children: [
94
- /* @__PURE__ */ jsxs("span", { className: "og-skill-discovery-copy", children: [
95
- /* @__PURE__ */ jsx("strong", { children: skill.name }),
96
- /* @__PURE__ */ jsx("span", { children: skill.source }),
97
- /* @__PURE__ */ jsxs("small", { children: [
98
- skill.installs.toLocaleString(),
99
- " installs"
100
- ] })
101
- ] }),
102
- /* @__PURE__ */ jsx("span", { className: "og-skill-discovery-action", children: installed ? /* @__PURE__ */ jsxs(Fragment, { children: [
103
- /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u2713 " }),
104
- "Installed"
105
- ] }) : !canManage ? "Admin required" : "Preview \u2192" })
106
- ]
209
+ name: skill.name,
210
+ description: skill.description,
211
+ icon: /* @__PURE__ */ jsx2(BookOpenIcon, { "aria-hidden": "true" }),
212
+ status: skill.status ?? "added",
213
+ statusLabel: skill.statusLabel,
214
+ onOpen: skill.onOpen
107
215
  },
108
216
  skill.id
109
- );
110
- }) }),
111
- loading ? /* @__PURE__ */ jsx("p", { role: "status", children: "Loading skills\u2026" }) : null,
112
- error ? /* @__PURE__ */ jsxs("div", { role: "alert", className: "og-skill-discovery-error", children: [
217
+ )),
218
+ remoteSkills.slice(
219
+ 0,
220
+ resultLimit === void 0 ? void 0 : Math.max(0, resultLimit - localSkills.length)
221
+ ).map((skill) => {
222
+ const installed = installedSkills.some(
223
+ (entry) => entry.sourceUrl.replace(/\/$/, "").toLowerCase() === skill.url.toLowerCase() || entry.repositoryUrl.replace(/\/$/, "").toLowerCase() === `https://github.com/${skill.source}`.toLowerCase() && entry.name.toLowerCase() === skill.name.toLowerCase()
224
+ );
225
+ return /* @__PURE__ */ jsx2(
226
+ CapabilityCatalogRow,
227
+ {
228
+ disabled: !canManage,
229
+ name: skill.name,
230
+ description: skill.source,
231
+ icon: /* @__PURE__ */ jsx2(BookOpenIcon, { "aria-hidden": "true" }),
232
+ status: !canManage ? "unavailable" : installed ? "added" : "available",
233
+ statusLabel: !canManage ? "Admin required" : installed ? "Installed" : "Available to add",
234
+ onOpen: () => onImport(skill.url)
235
+ },
236
+ skill.id
237
+ );
238
+ })
239
+ ] }),
240
+ resultLimit && remoteSkills.length + localSkills.length > resultLimit && !loading ? /* @__PURE__ */ jsx2("button", { className: "og-catalog-more", type: "button", onClick: onShowMore, children: "View all skills" }) : null,
241
+ loading ? /* @__PURE__ */ jsx2("p", { role: "status", children: "Loading skills\u2026" }) : null,
242
+ error ? /* @__PURE__ */ jsxs2("div", { role: "alert", className: "og-skill-discovery-error", children: [
113
243
  "Could not load skills.",
114
- /* @__PURE__ */ jsx("button", { type: "button", onClick: () => setRetry((value) => value + 1), children: "Retry" })
244
+ /* @__PURE__ */ jsx2("button", { type: "button", onClick: () => setRetry((value) => value + 1), children: "Retry" })
115
245
  ] }) : null,
116
- result && !result.items.length && !loading && !error ? /* @__PURE__ */ jsx("p", { role: "status", children: "No skills found. Try a different search." }) : null
246
+ result && !remoteSkills.length && !localSkills.length && !loading && !error ? /* @__PURE__ */ jsx2("p", { role: "status", children: "No skills found. Try a different search." }) : null
117
247
  ] });
118
248
  }
119
249
 
120
250
  // src/connect-setup.tsx
121
251
  import { useState as useState2 } from "react";
122
- import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
252
+ import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
123
253
  var setupStatus = {
124
254
  ready: "Ready to connect",
125
255
  requires_user_action: "Authorize your account",
@@ -152,9 +282,15 @@ function ConnectSetup(props) {
152
282
  setScope(props.controller);
153
283
  setGeneration(generation + 1);
154
284
  }
155
- return /* @__PURE__ */ jsx2(ScopedSetup, { ...props }, generation);
285
+ return /* @__PURE__ */ jsx3(ScopedSetup, { ...props }, generation);
156
286
  }
157
- function ScopedSetup({ controller, onAuthorize, onBrowseResources, className }) {
287
+ function ScopedSetup({
288
+ controller,
289
+ onAuthorize,
290
+ onBrowseResources,
291
+ className,
292
+ authorizeLabel = "Authorize connection"
293
+ }) {
158
294
  const view = useConnect(controller);
159
295
  const [localError, setLocalError] = useState2(false);
160
296
  const invoke = (operation) => {
@@ -167,7 +303,14 @@ function ScopedSetup({ controller, onAuthorize, onBrowseResources, className })
167
303
  };
168
304
  const attempt = view.attempt;
169
305
  if (!attempt)
170
- return /* @__PURE__ */ jsx2("section", { className, "aria-label": "Connection setup", children: /* @__PURE__ */ jsx2("p", { role: "status", children: "Choose a connection to begin." }) });
306
+ return /* @__PURE__ */ jsx3(
307
+ "section",
308
+ {
309
+ className: ["og-connect-setup", className].filter(Boolean).join(" "),
310
+ "aria-label": "Connection setup",
311
+ children: /* @__PURE__ */ jsx3("p", { role: "status", children: "Choose a connection to begin." })
312
+ }
313
+ );
171
314
  const action = attempt.nextAction;
172
315
  const verificationUrl = deviceVerificationUrl(action);
173
316
  const terminal = ["complete", "cancelled", "expired"].includes(attempt.state);
@@ -206,173 +349,198 @@ function ScopedSetup({ controller, onAuthorize, onBrowseResources, className })
206
349
  );
207
350
  }
208
351
  };
209
- return /* @__PURE__ */ jsxs2("section", { className, "aria-label": "Connection setup", "aria-busy": view.busy, children: [
210
- /* @__PURE__ */ jsxs2("p", { children: [
211
- "Ownership: ",
212
- attempt.ownership === "personal" ? "Personal" : "Workspace"
213
- ] }),
214
- /* @__PURE__ */ jsx2("p", { role: "status", children: setupStatus[attempt.state] }),
215
- attempt.account && /* @__PURE__ */ jsxs2("p", { children: [
216
- "Account: ",
217
- attempt.account.label
218
- ] }),
219
- (localError || view.error || attempt.error) && /* @__PURE__ */ jsx2("p", { role: "alert", children: attempt.error?.code === "source_changed" ? "The integration source changed. Review the new operations before installing." : "Connection setup could not continue. Refresh its status before trying again." }),
220
- !terminal && /* @__PURE__ */ jsx2("form", { onSubmit: submit, autoComplete: "off", children: /* @__PURE__ */ jsxs2("fieldset", { disabled: view.busy, children: [
221
- /* @__PURE__ */ jsx2("legend", { children: "Connection details" }),
222
- attempt.state === "connected_but_incomplete" && action.type === "none" && /* @__PURE__ */ jsx2(
223
- "button",
224
- {
225
- type: "button",
226
- onClick: () => invoke(() => view.advance({ type: "retry" }, crypto.randomUUID())),
227
- children: "Review integration operations"
228
- }
229
- ),
230
- action.type === "credentials" && action.fields.map((field, i) => /* @__PURE__ */ jsxs2("label", { children: [
231
- field.label,
232
- field.options ? /* @__PURE__ */ jsxs2("select", { name: `field-${i}`, required: field.required, defaultValue: "", children: [
233
- /* @__PURE__ */ jsx2("option", { value: "", children: field.required ? "Choose an option" : "No account (public service)" }),
234
- field.options.map((option) => /* @__PURE__ */ jsx2("option", { value: option.value, children: option.label }, option.value))
235
- ] }) : /* @__PURE__ */ jsx2(
236
- "input",
237
- {
238
- name: `field-${i}`,
239
- type: field.secret ? "password" : "text",
240
- required: field.required,
241
- autoComplete: "off"
242
- }
243
- )
244
- ] }, field.name)),
245
- action.type === "select_account" && /* @__PURE__ */ jsxs2("label", { children: [
246
- "Account",
247
- /* @__PURE__ */ jsxs2("select", { name: "account", required: true, defaultValue: "", children: [
248
- /* @__PURE__ */ jsx2("option", { value: "", disabled: true, children: "Choose an account" }),
249
- action.accounts.map((account) => /* @__PURE__ */ jsxs2(
250
- "option",
251
- {
252
- value: account.id,
253
- disabled: account.status === "disabled",
254
- children: [
255
- account.label,
256
- " \u2014 ",
257
- account.id,
258
- " (",
259
- account.ownership,
260
- ")"
261
- ]
262
- },
263
- account.id
264
- ))
265
- ] })
266
- ] }),
267
- action.type === "select_resources" && action.resources.map((resource) => /* @__PURE__ */ jsxs2("label", { children: [
268
- /* @__PURE__ */ jsx2("input", { type: "checkbox", name: "resource", value: resource.id }),
269
- resource.label,
270
- " (",
271
- resource.kind,
272
- ")"
273
- ] }, resource.id)),
274
- action.type === "select_resources" && action.cursor && /* @__PURE__ */ jsxs2(Fragment2, { children: [
275
- /* @__PURE__ */ jsx2("p", { children: "More resources are available. Review all pages before submitting a selection." }),
276
- onBrowseResources && /* @__PURE__ */ jsx2(
277
- "button",
278
- {
279
- type: "button",
280
- onClick: () => invoke(() => onBrowseResources(structuredClone(attempt))),
281
- children: "Browse all resources"
282
- }
283
- )
284
- ] }),
285
- action.type === "preview" && /* @__PURE__ */ jsxs2(Fragment2, { children: [
286
- /* @__PURE__ */ jsx2("p", { children: "Select the operations to install." }),
287
- action.operations.map((operation) => /* @__PURE__ */ jsxs2("label", { children: [
288
- /* @__PURE__ */ jsx2("input", { type: "checkbox", name: "operation", value: operation.id }),
289
- operation.label,
290
- " (",
291
- operation.kind,
292
- ")"
293
- ] }, operation.id))
294
- ] }),
295
- ["credentials", "select_account", "select_resources", "preview"].includes(
296
- action.type
297
- ) && /* @__PURE__ */ jsx2(
298
- "button",
299
- {
300
- type: "submit",
301
- disabled: action.type === "select_resources" && Boolean(action.cursor),
302
- children: action.type === "preview" ? "Install selected operations" : "Continue"
303
- }
304
- ),
305
- action.type === "authorize" && /* @__PURE__ */ jsx2(
306
- "button",
307
- {
308
- type: "button",
309
- onClick: () => invoke(() => onAuthorize(structuredClone(attempt))),
310
- children: "Authorize connection"
311
- }
312
- ),
313
- action.type === "wait" && /* @__PURE__ */ jsxs2(Fragment2, { children: [
314
- action.userCode && /* @__PURE__ */ jsxs2("p", { children: [
315
- "Verification code: ",
316
- /* @__PURE__ */ jsx2("code", { children: action.userCode })
352
+ return /* @__PURE__ */ jsxs3(
353
+ "section",
354
+ {
355
+ className: ["og-connect-setup", className].filter(Boolean).join(" "),
356
+ "aria-label": "Connection setup",
357
+ "aria-busy": view.busy,
358
+ children: [
359
+ /* @__PURE__ */ jsxs3("div", { className: "og-connect-setup-summary", children: [
360
+ /* @__PURE__ */ jsx3("p", { className: "og-connect-setup-scope", children: attempt.ownership === "personal" ? "Personal connection" : "Workspace connection" }),
361
+ /* @__PURE__ */ jsx3("p", { role: "status", className: "og-connect-setup-status", children: setupStatus[attempt.state] }),
362
+ /* @__PURE__ */ jsx3("p", { className: "og-connect-setup-description", children: attempt.ownership === "personal" ? "Only your work can use this connection." : "Work in this workspace can use this connection." })
317
363
  ] }),
318
- /* @__PURE__ */ jsx2("p", { children: "Complete provider authorization, then check the connection status." }),
319
- verificationUrl && /* @__PURE__ */ jsx2("a", { href: verificationUrl, target: "_blank", rel: "noopener noreferrer", children: "Open provider verification page (new tab)" })
320
- ] }),
321
- /* @__PURE__ */ jsx2("button", { type: "button", onClick: () => invoke(() => view.refresh()), children: "Check status" }),
322
- /* @__PURE__ */ jsx2("button", { type: "button", onClick: () => invoke(() => view.cancel(crypto.randomUUID())), children: "Cancel setup" })
323
- ] }) }, `${attempt.id}:${attempt.revision}`)
324
- ] });
364
+ attempt.account && /* @__PURE__ */ jsxs3("p", { children: [
365
+ "Account: ",
366
+ attempt.account.label
367
+ ] }),
368
+ (localError || view.error || attempt.error) && /* @__PURE__ */ jsx3("p", { role: "alert", children: attempt.error?.code === "source_changed" ? "The integration source changed. Review the new operations before installing." : "Connection setup could not continue. Refresh its status before trying again." }),
369
+ !terminal && /* @__PURE__ */ jsx3("form", { onSubmit: submit, autoComplete: "off", children: /* @__PURE__ */ jsxs3("fieldset", { disabled: view.busy, children: [
370
+ ["credentials", "select_account", "select_resources", "preview"].includes(
371
+ action.type
372
+ ) ? /* @__PURE__ */ jsx3("legend", { children: "Connection details" }) : null,
373
+ attempt.state === "connected_but_incomplete" && action.type === "none" && /* @__PURE__ */ jsx3(
374
+ "button",
375
+ {
376
+ type: "button",
377
+ className: "og-connect-setup-primary",
378
+ onClick: () => invoke(() => view.advance({ type: "retry" }, crypto.randomUUID())),
379
+ children: "Review integration operations"
380
+ }
381
+ ),
382
+ action.type === "credentials" && action.fields.map((field, i) => /* @__PURE__ */ jsxs3("label", { children: [
383
+ field.label,
384
+ field.options ? /* @__PURE__ */ jsxs3("select", { name: `field-${i}`, required: field.required, defaultValue: "", children: [
385
+ /* @__PURE__ */ jsx3("option", { value: "", children: field.required ? "Choose an option" : "No account (public service)" }),
386
+ field.options.map((option) => /* @__PURE__ */ jsx3("option", { value: option.value, children: option.label }, option.value))
387
+ ] }) : /* @__PURE__ */ jsx3(
388
+ "input",
389
+ {
390
+ name: `field-${i}`,
391
+ type: field.secret ? "password" : "text",
392
+ required: field.required,
393
+ autoComplete: "off"
394
+ }
395
+ )
396
+ ] }, field.name)),
397
+ action.type === "select_account" && /* @__PURE__ */ jsxs3("label", { children: [
398
+ "Account",
399
+ /* @__PURE__ */ jsxs3("select", { name: "account", required: true, defaultValue: "", children: [
400
+ /* @__PURE__ */ jsx3("option", { value: "", disabled: true, children: "Choose an account" }),
401
+ action.accounts.map((account) => /* @__PURE__ */ jsxs3(
402
+ "option",
403
+ {
404
+ value: account.id,
405
+ disabled: account.status === "disabled",
406
+ children: [
407
+ account.label,
408
+ " \u2014 ",
409
+ account.id,
410
+ " (",
411
+ account.ownership,
412
+ ")"
413
+ ]
414
+ },
415
+ account.id
416
+ ))
417
+ ] })
418
+ ] }),
419
+ action.type === "select_resources" && action.resources.map((resource) => /* @__PURE__ */ jsxs3("label", { children: [
420
+ /* @__PURE__ */ jsx3("input", { type: "checkbox", name: "resource", value: resource.id }),
421
+ resource.label,
422
+ " (",
423
+ resource.kind,
424
+ ")"
425
+ ] }, resource.id)),
426
+ action.type === "select_resources" && action.cursor && /* @__PURE__ */ jsxs3(Fragment, { children: [
427
+ /* @__PURE__ */ jsx3("p", { children: "More resources are available. Review all pages before submitting a selection." }),
428
+ onBrowseResources && /* @__PURE__ */ jsx3(
429
+ "button",
430
+ {
431
+ type: "button",
432
+ onClick: () => invoke(() => onBrowseResources(structuredClone(attempt))),
433
+ children: "Browse all resources"
434
+ }
435
+ )
436
+ ] }),
437
+ action.type === "preview" && /* @__PURE__ */ jsxs3(Fragment, { children: [
438
+ /* @__PURE__ */ jsx3("p", { children: "Select the operations to install." }),
439
+ action.operations.map((operation) => /* @__PURE__ */ jsxs3("label", { children: [
440
+ /* @__PURE__ */ jsx3("input", { type: "checkbox", name: "operation", value: operation.id }),
441
+ operation.label,
442
+ " (",
443
+ operation.kind,
444
+ ")"
445
+ ] }, operation.id))
446
+ ] }),
447
+ ["credentials", "select_account", "select_resources", "preview"].includes(
448
+ action.type
449
+ ) && /* @__PURE__ */ jsx3(
450
+ "button",
451
+ {
452
+ type: "submit",
453
+ className: "og-connect-setup-primary",
454
+ disabled: action.type === "select_resources" && Boolean(action.cursor),
455
+ children: action.type === "preview" ? "Install selected operations" : "Continue"
456
+ }
457
+ ),
458
+ action.type === "authorize" && /* @__PURE__ */ jsx3(
459
+ "button",
460
+ {
461
+ type: "button",
462
+ className: "og-connect-setup-primary",
463
+ onClick: () => invoke(() => onAuthorize(structuredClone(attempt))),
464
+ children: authorizeLabel
465
+ }
466
+ ),
467
+ action.type === "wait" && /* @__PURE__ */ jsxs3(Fragment, { children: [
468
+ action.userCode && /* @__PURE__ */ jsxs3("p", { children: [
469
+ "Verification code: ",
470
+ /* @__PURE__ */ jsx3("code", { children: action.userCode })
471
+ ] }),
472
+ /* @__PURE__ */ jsx3("p", { children: "Complete provider authorization, then check the connection status." }),
473
+ verificationUrl && /* @__PURE__ */ jsx3("a", { href: verificationUrl, target: "_blank", rel: "noopener noreferrer", children: "Open provider verification page (new tab)" })
474
+ ] }),
475
+ /* @__PURE__ */ jsxs3("div", { className: "og-connect-setup-secondary", children: [
476
+ /* @__PURE__ */ jsx3("button", { type: "button", onClick: () => invoke(() => view.refresh()), children: "Check status" }),
477
+ /* @__PURE__ */ jsx3("button", { type: "button", onClick: () => invoke(() => view.cancel(crypto.randomUUID())), children: "Cancel setup" })
478
+ ] })
479
+ ] }) }, `${attempt.id}:${attempt.revision}`)
480
+ ]
481
+ }
482
+ );
325
483
  }
326
484
 
327
485
  // src/connection-catalog.tsx
328
- import { Fragment as Fragment3, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
329
- function ConnectionDetailsIndicator() {
330
- return /* @__PURE__ */ jsx3("span", { "aria-hidden": true, className: "og-connection-group-chevron", children: "\u203A" });
331
- }
486
+ import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
332
487
  function ConnectionOptionRow({ option }) {
333
- return /* @__PURE__ */ jsxs3("div", { className: "og-connection-catalog-action-row og-connection-option", children: [
334
- /* @__PURE__ */ jsxs3("button", { type: "button", className: "og-connection-catalog-row", onClick: option.onOpen, children: [
335
- /* @__PURE__ */ jsxs3("span", { className: "og-connection-catalog-copy", children: [
336
- /* @__PURE__ */ jsx3("strong", { children: option.name }),
337
- /* @__PURE__ */ jsx3("span", { children: option.description })
338
- ] }),
339
- /* @__PURE__ */ jsx3("span", { className: "og-connection-catalog-status", children: option.status }),
340
- !option.action ? /* @__PURE__ */ jsx3(ConnectionDetailsIndicator, {}) : null
341
- ] }),
342
- option.action ? /* @__PURE__ */ jsx3("span", { className: "og-connection-option-action", children: option.action }) : null
488
+ return /* @__PURE__ */ jsxs4("div", { className: "og-connection-catalog-action-row og-connection-option", children: [
489
+ /* @__PURE__ */ jsx4(
490
+ CapabilityCatalogRow,
491
+ {
492
+ name: option.name,
493
+ description: option.description,
494
+ status: option.state ?? (option.connected ? "added" : "available"),
495
+ statusLabel: option.status,
496
+ showStatusLabel: option.state === void 0,
497
+ onOpen: option.onOpen
498
+ }
499
+ ),
500
+ option.action ? /* @__PURE__ */ jsx4("span", { className: "og-connection-option-action", children: option.action }) : null
343
501
  ] });
344
502
  }
345
503
  function ConnectionServiceRow({ service }) {
346
504
  if (!service.options.length) return null;
347
505
  const connected = service.options.filter((option) => option.connected).length;
348
- const identity = /* @__PURE__ */ jsxs3(Fragment3, { children: [
349
- /* @__PURE__ */ jsx3("span", { className: "og-connection-catalog-logo", children: service.logo }),
350
- /* @__PURE__ */ jsxs3("span", { className: "og-connection-catalog-copy", children: [
351
- /* @__PURE__ */ jsx3("strong", { children: service.name }),
352
- /* @__PURE__ */ jsx3("span", { children: service.options.length === 1 ? service.options[0]?.description : service.options.map((option) => option.name).join(" \xB7 ") })
506
+ const attention = service.options.find(
507
+ (option) => option.state === "attention" || option.state === "unavailable"
508
+ );
509
+ const groupState = attention?.state ?? (service.options.some((option) => option.state === "loading") ? "loading" : connected === service.options.length ? "added" : "available");
510
+ const identity = /* @__PURE__ */ jsxs4(Fragment2, { children: [
511
+ /* @__PURE__ */ jsx4("span", { className: "og-capability-catalog-icon", children: service.logo }),
512
+ /* @__PURE__ */ jsxs4("span", { className: "og-capability-catalog-copy", children: [
513
+ /* @__PURE__ */ jsx4("strong", { children: service.name }),
514
+ /* @__PURE__ */ jsx4("span", { children: service.options.length === 1 ? service.options[0]?.description : service.options.map((option) => option.name).join(" \xB7 ") })
353
515
  ] }),
354
- /* @__PURE__ */ jsx3("span", { className: "og-connection-catalog-status", children: service.options.length === 1 ? service.options[0]?.status : `${connected} of ${service.options.length} connected` })
516
+ /* @__PURE__ */ jsx4(
517
+ CapabilityCatalogIndicator,
518
+ {
519
+ status: groupState,
520
+ label: attention?.status ?? `${connected} of ${service.options.length} added`
521
+ }
522
+ )
355
523
  ] });
356
- return service.options.length === 1 ? /* @__PURE__ */ jsxs3("div", { className: "og-connection-catalog-action-row", children: [
357
- /* @__PURE__ */ jsxs3(
358
- "button",
524
+ return service.options.length === 1 ? /* @__PURE__ */ jsxs4("div", { className: "og-connection-catalog-action-row", children: [
525
+ /* @__PURE__ */ jsx4(
526
+ CapabilityCatalogRow,
359
527
  {
360
- type: "button",
361
- className: "og-connection-catalog-row",
362
- onClick: service.options[0].onOpen,
363
- children: [
364
- identity,
365
- !service.options[0]?.action ? /* @__PURE__ */ jsx3(ConnectionDetailsIndicator, {}) : null
366
- ]
528
+ name: service.name,
529
+ description: service.options[0].description,
530
+ icon: service.logo,
531
+ status: service.options[0].state ?? (connected ? "added" : "available"),
532
+ statusLabel: service.options[0].status,
533
+ showStatusLabel: service.options[0].state === void 0,
534
+ onOpen: service.options[0].onOpen
367
535
  }
368
536
  ),
369
537
  service.options[0]?.action
370
- ] }) : /* @__PURE__ */ jsxs3("details", { className: "og-connection-catalog-service", children: [
371
- /* @__PURE__ */ jsxs3("summary", { className: "og-connection-catalog-row", children: [
538
+ ] }) : /* @__PURE__ */ jsxs4("details", { className: "og-connection-catalog-service", children: [
539
+ /* @__PURE__ */ jsxs4("summary", { className: "og-capability-catalog-row", children: [
372
540
  identity,
373
- /* @__PURE__ */ jsx3("span", { "aria-hidden": true, className: "og-connection-group-chevron", children: "\u2304" })
541
+ /* @__PURE__ */ jsx4("span", { "aria-hidden": true, className: "og-connection-group-chevron", children: "\u2304" })
374
542
  ] }),
375
- /* @__PURE__ */ jsx3("div", { className: "og-connection-catalog-options", children: service.options.map((option) => /* @__PURE__ */ jsx3(ConnectionOptionRow, { option }, option.id)) })
543
+ /* @__PURE__ */ jsx4("div", { className: "og-connection-catalog-options", children: service.options.map((option) => /* @__PURE__ */ jsx4(ConnectionOptionRow, { option }, option.id)) })
376
544
  ] });
377
545
  }
378
546
  function ConnectionCatalog({
@@ -380,6 +548,8 @@ function ConnectionCatalog({
380
548
  query = "",
381
549
  columns = 1,
382
550
  grouped = true,
551
+ resultLimit,
552
+ onShowMore,
383
553
  className = "",
384
554
  emptyMessage = "No connections match your search."
385
555
  }) {
@@ -395,12 +565,15 @@ function ConnectionCatalog({
395
565
  const visible = entries.filter(
396
566
  (service) => [service.name, ...service.options.flatMap((option) => [option.name, option.description ?? ""])].join(" ").toLowerCase().includes(search)
397
567
  );
398
- return /* @__PURE__ */ jsx3("div", { className: `og-connection-catalog ${className}`, "data-columns": columns, children: visible.length ? visible.map((service) => /* @__PURE__ */ jsx3(ConnectionServiceRow, { service }, service.id)) : /* @__PURE__ */ jsx3("p", { role: "status", children: emptyMessage }) });
568
+ return /* @__PURE__ */ jsxs4(Fragment2, { children: [
569
+ /* @__PURE__ */ jsx4("div", { className: `og-connection-catalog ${className}`, "data-columns": columns, children: visible.length ? visible.slice(0, resultLimit).map((service) => /* @__PURE__ */ jsx4(ConnectionServiceRow, { service }, service.id)) : /* @__PURE__ */ jsx4("p", { role: "status", children: emptyMessage }) }),
570
+ resultLimit && visible.length > resultLimit ? /* @__PURE__ */ jsx4("button", { className: "og-catalog-more", type: "button", onClick: onShowMore, children: "View all connections" }) : null
571
+ ] });
399
572
  }
400
573
 
401
574
  // src/connect-chooser.tsx
402
575
  import { useEffect as useEffect2, useState as useState3 } from "react";
403
- import { Fragment as Fragment4, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
576
+ import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
404
577
  function ConnectChooser(props) {
405
578
  const [scope, setScope] = useState3(props.controller);
406
579
  const [generation, setGeneration] = useState3(0);
@@ -408,7 +581,7 @@ function ConnectChooser(props) {
408
581
  setScope(props.controller);
409
582
  setGeneration(generation + 1);
410
583
  }
411
- return /* @__PURE__ */ jsx4(ScopedChooser, { ...props }, generation);
584
+ return /* @__PURE__ */ jsx5(ScopedChooser, { ...props }, generation);
412
585
  }
413
586
  function ScopedChooser({
414
587
  controller,
@@ -451,22 +624,22 @@ function ScopedChooser({
451
624
  setFailed(true);
452
625
  }
453
626
  };
454
- return /* @__PURE__ */ jsxs4(
627
+ return /* @__PURE__ */ jsxs5(
455
628
  "section",
456
629
  {
457
630
  className,
458
631
  "aria-label": "Choose a connection",
459
632
  "aria-busy": view.busy || !catalog && !failed,
460
633
  children: [
461
- failed && /* @__PURE__ */ jsx4("p", { role: "alert", children: "Connections could not be loaded or started. Check setup status before retrying." }),
462
- !catalog && !failed && /* @__PURE__ */ jsx4("p", { role: "status", children: "Loading connections\u2026" }),
463
- catalog?.length === 0 && /* @__PURE__ */ jsx4("p", { role: "status", children: "No connections are available." }),
464
- Boolean(catalog?.length) && /* @__PURE__ */ jsx4("form", { onSubmit: submit, children: /* @__PURE__ */ jsxs4("fieldset", { disabled: view.busy, children: [
465
- /* @__PURE__ */ jsx4("legend", { children: "Provider and ownership" }),
466
- presentation === "catalog" && !provider ? /* @__PURE__ */ jsxs4(Fragment4, { children: [
467
- /* @__PURE__ */ jsxs4("label", { children: [
634
+ failed && /* @__PURE__ */ jsx5("p", { role: "alert", children: "Connections could not be loaded or started. Check setup status before retrying." }),
635
+ !catalog && !failed && /* @__PURE__ */ jsx5("p", { role: "status", children: "Loading connections\u2026" }),
636
+ catalog?.length === 0 && /* @__PURE__ */ jsx5("p", { role: "status", children: "No connections are available." }),
637
+ Boolean(catalog?.length) && /* @__PURE__ */ jsx5("form", { onSubmit: submit, children: /* @__PURE__ */ jsxs5("fieldset", { disabled: view.busy, children: [
638
+ /* @__PURE__ */ jsx5("legend", { children: "Provider and ownership" }),
639
+ presentation === "catalog" && !provider ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
640
+ /* @__PURE__ */ jsxs5("label", { children: [
468
641
  "Search connections",
469
- /* @__PURE__ */ jsx4(
642
+ /* @__PURE__ */ jsx5(
470
643
  "input",
471
644
  {
472
645
  type: "search",
@@ -475,7 +648,7 @@ function ScopedChooser({
475
648
  }
476
649
  )
477
650
  ] }),
478
- /* @__PURE__ */ jsx4(
651
+ /* @__PURE__ */ jsx5(
479
652
  ConnectionCatalog,
480
653
  {
481
654
  query,
@@ -501,7 +674,7 @@ function ScopedChooser({
501
674
  }
502
675
  )
503
676
  ] }) : null,
504
- presentation === "catalog" && provider ? /* @__PURE__ */ jsx4(
677
+ presentation === "catalog" && provider ? /* @__PURE__ */ jsx5(
505
678
  "button",
506
679
  {
507
680
  type: "button",
@@ -512,9 +685,9 @@ function ScopedChooser({
512
685
  children: "Back to connections"
513
686
  }
514
687
  ) : null,
515
- /* @__PURE__ */ jsxs4("label", { hidden: presentation === "catalog", children: [
688
+ /* @__PURE__ */ jsxs5("label", { hidden: presentation === "catalog", children: [
516
689
  "Provider",
517
- /* @__PURE__ */ jsxs4(
690
+ /* @__PURE__ */ jsxs5(
518
691
  "select",
519
692
  {
520
693
  required: true,
@@ -524,8 +697,8 @@ function ScopedChooser({
524
697
  setOwnership("");
525
698
  },
526
699
  children: [
527
- /* @__PURE__ */ jsx4("option", { value: "", disabled: true, children: "Choose a provider" }),
528
- catalog.map((entry) => /* @__PURE__ */ jsxs4(
700
+ /* @__PURE__ */ jsx5("option", { value: "", disabled: true, children: "Choose a provider" }),
701
+ catalog.map((entry) => /* @__PURE__ */ jsxs5(
529
702
  "option",
530
703
  {
531
704
  value: entry.id,
@@ -545,25 +718,25 @@ function ScopedChooser({
545
718
  }
546
719
  )
547
720
  ] }),
548
- provider && /* @__PURE__ */ jsxs4(Fragment4, { children: [
549
- /* @__PURE__ */ jsx4("strong", { children: presentation === "catalog" ? provider.label : null }),
550
- /* @__PURE__ */ jsxs4("label", { children: [
721
+ provider && /* @__PURE__ */ jsxs5(Fragment3, { children: [
722
+ /* @__PURE__ */ jsx5("strong", { children: presentation === "catalog" ? provider.label : null }),
723
+ /* @__PURE__ */ jsxs5("label", { children: [
551
724
  "Ownership",
552
- /* @__PURE__ */ jsxs4(
725
+ /* @__PURE__ */ jsxs5(
553
726
  "select",
554
727
  {
555
728
  required: true,
556
729
  value: ownership,
557
730
  onChange: (event) => setOwnership(event.target.value),
558
731
  children: [
559
- /* @__PURE__ */ jsx4("option", { value: "", disabled: true, children: "Choose ownership" }),
560
- provider.ownership.map((choice) => /* @__PURE__ */ jsx4("option", { value: choice, children: choice === "personal" ? "Personal \u2014 owned by you" : "Workspace \u2014 shared connection" }, choice))
732
+ /* @__PURE__ */ jsx5("option", { value: "", disabled: true, children: "Choose ownership" }),
733
+ provider.ownership.map((choice) => /* @__PURE__ */ jsx5("option", { value: choice, children: choice === "personal" ? "Personal \u2014 owned by you" : "Workspace \u2014 shared connection" }, choice))
561
734
  ]
562
735
  }
563
736
  )
564
737
  ] })
565
738
  ] }),
566
- /* @__PURE__ */ jsx4(
739
+ /* @__PURE__ */ jsx5(
567
740
  "button",
568
741
  {
569
742
  hidden: presentation === "catalog" && !provider,
@@ -573,7 +746,7 @@ function ScopedChooser({
573
746
  }
574
747
  )
575
748
  ] }) }),
576
- /* @__PURE__ */ jsx4("button", { type: "button", disabled: view.busy, onClick: () => setLoad(load + 1), children: "Reload providers" })
749
+ /* @__PURE__ */ jsx5("button", { type: "button", disabled: view.busy, onClick: () => setLoad(load + 1), children: "Reload providers" })
577
750
  ]
578
751
  }
579
752
  );
@@ -581,7 +754,7 @@ function ScopedChooser({
581
754
 
582
755
  // src/connect-accounts.tsx
583
756
  import { useEffect as useEffect3, useRef, useState as useState4 } from "react";
584
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
757
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
585
758
  function ConnectAccounts(props) {
586
759
  const [scope, setScope] = useState4(props.controller);
587
760
  const [generation, setGeneration] = useState4(0);
@@ -589,7 +762,7 @@ function ConnectAccounts(props) {
589
762
  setScope(props.controller);
590
763
  setGeneration(generation + 1);
591
764
  }
592
- return /* @__PURE__ */ jsx5(ScopedAccounts, { ...props }, generation);
765
+ return /* @__PURE__ */ jsx6(ScopedAccounts, { ...props }, generation);
593
766
  }
594
767
  function ScopedAccounts({ controller, className, returnUrl }) {
595
768
  const view = useConnect(controller);
@@ -657,18 +830,18 @@ function ScopedAccounts({ controller, className, returnUrl }) {
657
830
  setError(true);
658
831
  }
659
832
  };
660
- return /* @__PURE__ */ jsxs5(
833
+ return /* @__PURE__ */ jsxs6(
661
834
  "section",
662
835
  {
663
836
  className,
664
837
  "aria-label": "Connected accounts",
665
838
  "aria-busy": busy || view.busy || !accounts && !error,
666
839
  children: [
667
- error && /* @__PURE__ */ jsx5("p", { role: "alert", children: "Account state could not be confirmed. Reload before trying again." }),
668
- !accounts && !error && /* @__PURE__ */ jsx5("p", { role: "status", children: "Loading accounts\u2026" }),
669
- accounts?.length === 0 && /* @__PURE__ */ jsx5("p", { role: "status", children: "No connected accounts." }),
670
- accounts && accounts.length > 0 && /* @__PURE__ */ jsx5("ul", { children: accounts.map((account) => /* @__PURE__ */ jsxs5("li", { children: [
671
- /* @__PURE__ */ jsxs5("span", { children: [
840
+ error && /* @__PURE__ */ jsx6("p", { role: "alert", children: "Account state could not be confirmed. Reload before trying again." }),
841
+ !accounts && !error && /* @__PURE__ */ jsx6("p", { role: "status", children: "Loading accounts\u2026" }),
842
+ accounts?.length === 0 && /* @__PURE__ */ jsx6("p", { role: "status", children: "No connected accounts." }),
843
+ accounts && accounts.length > 0 && /* @__PURE__ */ jsx6("ul", { children: accounts.map((account) => /* @__PURE__ */ jsxs6("li", { children: [
844
+ /* @__PURE__ */ jsxs6("span", { children: [
672
845
  account.label,
673
846
  " \u2014 ",
674
847
  account.providerId,
@@ -678,7 +851,7 @@ function ScopedAccounts({ controller, className, returnUrl }) {
678
851
  " ",
679
852
  account.status.replaceAll("_", " ")
680
853
  ] }),
681
- returnUrl && /* @__PURE__ */ jsxs5(
854
+ returnUrl && /* @__PURE__ */ jsxs6(
682
855
  "button",
683
856
  {
684
857
  type: "button",
@@ -690,9 +863,9 @@ function ScopedAccounts({ controller, className, returnUrl }) {
690
863
  ]
691
864
  }
692
865
  ),
693
- selected === `${account.providerId}:${account.id}` ? /* @__PURE__ */ jsxs5("div", { role: "group", "aria-label": `Disconnect ${account.label}`, children: [
694
- /* @__PURE__ */ jsx5("p", { children: "This removes local OpenGeni access. It does not revoke consent at the provider." }),
695
- /* @__PURE__ */ jsx5(
866
+ selected === `${account.providerId}:${account.id}` ? /* @__PURE__ */ jsxs6("div", { role: "group", "aria-label": `Disconnect ${account.label}`, children: [
867
+ /* @__PURE__ */ jsx6("p", { children: "This removes local OpenGeni access. It does not revoke consent at the provider." }),
868
+ /* @__PURE__ */ jsx6(
696
869
  "button",
697
870
  {
698
871
  type: "button",
@@ -701,8 +874,8 @@ function ScopedAccounts({ controller, className, returnUrl }) {
701
874
  children: "Confirm disconnect"
702
875
  }
703
876
  ),
704
- /* @__PURE__ */ jsx5("button", { type: "button", disabled: busy, onClick: () => setSelected(null), children: "Keep account" })
705
- ] }) : /* @__PURE__ */ jsxs5(
877
+ /* @__PURE__ */ jsx6("button", { type: "button", disabled: busy, onClick: () => setSelected(null), children: "Keep account" })
878
+ ] }) : /* @__PURE__ */ jsxs6(
706
879
  "button",
707
880
  {
708
881
  type: "button",
@@ -715,14 +888,14 @@ function ScopedAccounts({ controller, className, returnUrl }) {
715
888
  }
716
889
  )
717
890
  ] }, `${account.providerId}:${account.id}`)) }),
718
- /* @__PURE__ */ jsx5("button", { type: "button", disabled: busy, onClick: () => setReload((value) => value + 1), children: "Reload accounts" })
891
+ /* @__PURE__ */ jsx6("button", { type: "button", disabled: busy, onClick: () => setReload((value) => value + 1), children: "Reload accounts" })
719
892
  ]
720
893
  }
721
894
  );
722
895
  }
723
896
 
724
897
  // src/connect-panel.tsx
725
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
898
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
726
899
  function ConnectPanel({
727
900
  returnUrl,
728
901
  title = "Connections",
@@ -731,9 +904,11 @@ function ConnectPanel({
731
904
  className,
732
905
  ...setup
733
906
  }) {
734
- return /* @__PURE__ */ jsxs6("div", { className: ["og-connect", className].filter(Boolean).join(" "), children: [
735
- /* @__PURE__ */ jsx6("h2", { children: title }),
736
- /* @__PURE__ */ jsx6(
907
+ const { attempt } = useConnect(setup.controller);
908
+ const activeSetup = attempt !== null && !["complete", "cancelled", "expired"].includes(attempt.state);
909
+ return /* @__PURE__ */ jsxs7("div", { className: ["og-connect", className].filter(Boolean).join(" "), children: [
910
+ title !== null && /* @__PURE__ */ jsx7("h2", { children: title }),
911
+ !activeSetup && /* @__PURE__ */ jsx7(
737
912
  ConnectChooser,
738
913
  {
739
914
  presentation,
@@ -741,14 +916,14 @@ function ConnectPanel({
741
916
  returnUrl
742
917
  }
743
918
  ),
744
- /* @__PURE__ */ jsx6(ConnectSetup, { ...setup }),
745
- showAccounts && /* @__PURE__ */ jsx6(ConnectAccounts, { controller: setup.controller, returnUrl })
919
+ /* @__PURE__ */ jsx7(ConnectSetup, { ...setup }),
920
+ showAccounts && !activeSetup && /* @__PURE__ */ jsx7(ConnectAccounts, { controller: setup.controller, returnUrl })
746
921
  ] });
747
922
  }
748
923
 
749
924
  // src/device-authorization.tsx
750
925
  import { useEffect as useEffect4, useRef as useRef2, useState as useState5 } from "react";
751
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
926
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
752
927
  function DeviceAuthorization(props) {
753
928
  const [copied, setCopied] = useState5(false);
754
929
  const [copyError, setCopyError] = useState5(false);
@@ -794,11 +969,11 @@ function DeviceAuthorization(props) {
794
969
  } catch {
795
970
  }
796
971
  if (props.render) return props.render({ copied, copyError, copy, verificationHref: href });
797
- return /* @__PURE__ */ jsxs7("section", { className: `og-connect ${props.className ?? ""}`, "aria-label": "Device authorization", children: [
798
- /* @__PURE__ */ jsx7("p", { children: props.description ?? `Enter this code at ${props.providerLabel ?? "the provider"}.` }),
799
- /* @__PURE__ */ jsxs7("div", { style: { display: "flex", flexWrap: "wrap", gap: "0.5rem", alignItems: "center" }, children: [
800
- /* @__PURE__ */ jsx7("code", { ...props.codeAttributes, style: { overflowWrap: "anywhere" }, children: props.userCode }),
801
- /* @__PURE__ */ jsx7(
972
+ return /* @__PURE__ */ jsxs8("section", { className: `og-connect ${props.className ?? ""}`, "aria-label": "Device authorization", children: [
973
+ /* @__PURE__ */ jsx8("p", { children: props.description ?? `Enter this code at ${props.providerLabel ?? "the provider"}.` }),
974
+ /* @__PURE__ */ jsxs8("div", { style: { display: "flex", flexWrap: "wrap", gap: "0.5rem", alignItems: "center" }, children: [
975
+ /* @__PURE__ */ jsx8("code", { ...props.codeAttributes, style: { overflowWrap: "anywhere" }, children: props.userCode }),
976
+ /* @__PURE__ */ jsx8(
802
977
  "button",
803
978
  {
804
979
  type: "button",
@@ -807,19 +982,19 @@ function DeviceAuthorization(props) {
807
982
  children: copied ? "Copied" : "Copy code"
808
983
  }
809
984
  ),
810
- href ? /* @__PURE__ */ jsxs7("a", { href, target: "_blank", rel: "noopener noreferrer", children: [
985
+ href ? /* @__PURE__ */ jsxs8("a", { href, target: "_blank", rel: "noopener noreferrer", children: [
811
986
  "Open ",
812
987
  props.providerLabel ?? "auth page"
813
- ] }) : /* @__PURE__ */ jsx7("span", { role: "alert", children: "Authorization address unavailable." })
988
+ ] }) : /* @__PURE__ */ jsx8("span", { role: "alert", children: "Authorization address unavailable." })
814
989
  ] }),
815
- copyError ? /* @__PURE__ */ jsx7("p", { role: "alert", children: "Couldn't copy the code. Copy it manually instead." }) : null,
816
- /* @__PURE__ */ jsx7("p", { role: "status", children: "Waiting for authorization\u2026" })
990
+ copyError ? /* @__PURE__ */ jsx8("p", { role: "alert", children: "Couldn't copy the code. Copy it manually instead." }) : null,
991
+ /* @__PURE__ */ jsx8("p", { role: "status", children: "Waiting for authorization\u2026" })
817
992
  ] });
818
993
  }
819
994
 
820
995
  // src/identity-link-consent.tsx
821
996
  import { useEffect as useEffect5, useRef as useRef3, useState as useState6 } from "react";
822
- import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
997
+ import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
823
998
  function IdentityLinkConsent({
824
999
  client,
825
1000
  workspaceId,
@@ -879,43 +1054,43 @@ function IdentityLinkConsent({
879
1054
  if (generation.current === current) setBusy(false);
880
1055
  }
881
1056
  }
882
- return /* @__PURE__ */ jsxs8(
1057
+ return /* @__PURE__ */ jsxs9(
883
1058
  "section",
884
1059
  {
885
1060
  className: ["og-connect og-identity-link", className].filter(Boolean).join(" "),
886
1061
  "aria-label": "Link your account",
887
1062
  "aria-busy": busy,
888
1063
  children: [
889
- /* @__PURE__ */ jsx8("h2", { children: "Link your OpenGeni account" }),
890
- /* @__PURE__ */ jsx8("p", { children: "Only continue if you started this request in a product you trust. Linking lets that product act as your account with the permissions you select. It does not merge accounts or move existing work." }),
891
- preview && /* @__PURE__ */ jsxs8("dl", { children: [
892
- /* @__PURE__ */ jsx8("dt", { children: "Organization" }),
893
- /* @__PURE__ */ jsx8("dd", { children: preview.organizationId }),
894
- /* @__PURE__ */ jsx8("dt", { children: "Product user" }),
895
- /* @__PURE__ */ jsxs8("dd", { children: [
1064
+ /* @__PURE__ */ jsx9("h2", { children: "Link your OpenGeni account" }),
1065
+ /* @__PURE__ */ jsx9("p", { children: "Only continue if you started this request in a product you trust. Linking lets that product act as your account with the permissions you select. It does not merge accounts or move existing work." }),
1066
+ preview && /* @__PURE__ */ jsxs9("dl", { children: [
1067
+ /* @__PURE__ */ jsx9("dt", { children: "Organization" }),
1068
+ /* @__PURE__ */ jsx9("dd", { children: preview.organizationId }),
1069
+ /* @__PURE__ */ jsx9("dt", { children: "Product user" }),
1070
+ /* @__PURE__ */ jsxs9("dd", { children: [
896
1071
  preview.externalIdentity.externalId,
897
1072
  " (",
898
1073
  preview.externalIdentity.source,
899
1074
  ")"
900
1075
  ] }),
901
- /* @__PURE__ */ jsx8("dt", { children: "Your OpenGeni identity" }),
902
- /* @__PURE__ */ jsx8("dd", { children: preview.nativeSubjectId })
1076
+ /* @__PURE__ */ jsx9("dt", { children: "Your OpenGeni identity" }),
1077
+ /* @__PURE__ */ jsx9("dd", { children: preview.nativeSubjectId })
903
1078
  ] }),
904
- error && /* @__PURE__ */ jsxs8("div", { role: "alert", children: [
1079
+ error && /* @__PURE__ */ jsxs9("div", { role: "alert", children: [
905
1080
  "This request could not be completed. It may have expired, changed, or require you to sign in to the right organization.",
906
- !link && /* @__PURE__ */ jsx8("button", { type: "button", disabled: busy, onClick: () => setRetry((value) => value + 1), children: "Try again" })
1081
+ !link && /* @__PURE__ */ jsx9("button", { type: "button", disabled: busy, onClick: () => setRetry((value) => value + 1), children: "Try again" })
907
1082
  ] }),
908
- !link && busy && /* @__PURE__ */ jsx8("p", { role: "status", children: "Loading the account-link request\u2026" }),
909
- link?.status === "pending" && /* @__PURE__ */ jsxs8(Fragment5, { children: [
910
- /* @__PURE__ */ jsxs8("p", { children: [
1083
+ !link && busy && /* @__PURE__ */ jsx9("p", { role: "status", children: "Loading the account-link request\u2026" }),
1084
+ link?.status === "pending" && /* @__PURE__ */ jsxs9(Fragment4, { children: [
1085
+ /* @__PURE__ */ jsxs9("p", { children: [
911
1086
  link.expiresAt ? `Access ends ${new Date(link.expiresAt).toLocaleString()}.` : "Access lasts until you or the product revoke this link.",
912
1087
  " ",
913
1088
  "Your current permissions still apply."
914
1089
  ] }),
915
- /* @__PURE__ */ jsxs8("fieldset", { disabled: busy, children: [
916
- /* @__PURE__ */ jsx8("legend", { children: "Allow these permissions" }),
917
- link.permissions.map((permission) => /* @__PURE__ */ jsxs8("label", { children: [
918
- /* @__PURE__ */ jsx8(
1090
+ /* @__PURE__ */ jsxs9("fieldset", { disabled: busy, children: [
1091
+ /* @__PURE__ */ jsx9("legend", { children: "Allow these permissions" }),
1092
+ link.permissions.map((permission) => /* @__PURE__ */ jsxs9("label", { children: [
1093
+ /* @__PURE__ */ jsx9(
919
1094
  "input",
920
1095
  {
921
1096
  type: "checkbox",
@@ -925,10 +1100,10 @@ function IdentityLinkConsent({
925
1100
  )
926
1101
  }
927
1102
  ),
928
- /* @__PURE__ */ jsx8("span", { children: permission.replaceAll(":", " \xB7 ") })
1103
+ /* @__PURE__ */ jsx9("span", { children: permission.replaceAll(":", " \xB7 ") })
929
1104
  ] }, permission))
930
1105
  ] }),
931
- /* @__PURE__ */ jsx8(
1106
+ /* @__PURE__ */ jsx9(
932
1107
  "button",
933
1108
  {
934
1109
  type: "button",
@@ -937,14 +1112,14 @@ function IdentityLinkConsent({
937
1112
  children: busy ? "Saving\u2026" : "Allow selected access"
938
1113
  }
939
1114
  ),
940
- /* @__PURE__ */ jsx8("p", { children: "You can close this page without granting access." })
1115
+ /* @__PURE__ */ jsx9("p", { children: "You can close this page without granting access." })
941
1116
  ] }),
942
- link?.status === "active" && /* @__PURE__ */ jsxs8(Fragment5, { children: [
943
- /* @__PURE__ */ jsx8("p", { role: "status", children: "Account linked. Return to your product to continue." }),
944
- /* @__PURE__ */ jsx8("button", { type: "button", disabled: busy, onClick: () => void mutate(true), children: "Revoke this link" })
1117
+ link?.status === "active" && /* @__PURE__ */ jsxs9(Fragment4, { children: [
1118
+ /* @__PURE__ */ jsx9("p", { role: "status", children: "Account linked. Return to your product to continue." }),
1119
+ /* @__PURE__ */ jsx9("button", { type: "button", disabled: busy, onClick: () => void mutate(true), children: "Revoke this link" })
945
1120
  ] }),
946
- link?.status === "revoked" && /* @__PURE__ */ jsx8("p", { role: "status", children: "Link revoked. Your OpenGeni account and existing work are unchanged." }),
947
- link?.status === "expired" && /* @__PURE__ */ jsx8("p", { role: "status", children: "This request has expired. Start a new request from your product." })
1121
+ link?.status === "revoked" && /* @__PURE__ */ jsx9("p", { role: "status", children: "Link revoked. Your OpenGeni account and existing work are unchanged." }),
1122
+ link?.status === "expired" && /* @__PURE__ */ jsx9("p", { role: "status", children: "This request has expired. Start a new request from your product." })
948
1123
  ]
949
1124
  }
950
1125
  );
@@ -952,7 +1127,7 @@ function IdentityLinkConsent({
952
1127
 
953
1128
  // src/identity-link-accounts.tsx
954
1129
  import { useEffect as useEffect6, useRef as useRef4, useState as useState7 } from "react";
955
- import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
1130
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
956
1131
  function IdentityLinkAccounts({
957
1132
  client,
958
1133
  workspaceId
@@ -1021,68 +1196,69 @@ function IdentityLinkAccounts({
1021
1196
  }
1022
1197
  }
1023
1198
  }
1024
- return /* @__PURE__ */ jsxs9(
1199
+ return /* @__PURE__ */ jsxs10(
1025
1200
  "section",
1026
1201
  {
1027
1202
  className: "og-connect og-identity-link",
1028
1203
  "aria-label": "Linked product access",
1029
1204
  "aria-busy": busy,
1030
1205
  children: [
1031
- /* @__PURE__ */ jsx9("h2", { children: "Linked product access" }),
1032
- /* @__PURE__ */ jsx9("p", { children: "Manage products allowed to act as your account in this organization. Revoking a link stops future linked access; it does not delete your work or undo an operation already started." }),
1033
- error && /* @__PURE__ */ jsxs9("div", { role: "alert", children: [
1206
+ /* @__PURE__ */ jsx10("h2", { children: "Linked product access" }),
1207
+ /* @__PURE__ */ jsx10("p", { children: "Manage products allowed to act as your account in this organization. Revoking a link stops future linked access; it does not delete your work or undo an operation already started." }),
1208
+ error && /* @__PURE__ */ jsxs10("div", { role: "alert", children: [
1034
1209
  "Could not update account links. Reload to see current access.",
1035
- /* @__PURE__ */ jsx9("button", { type: "button", disabled: busy, onClick: () => setRevision((value) => value + 1), children: "Reload links" })
1210
+ /* @__PURE__ */ jsx10("button", { type: "button", disabled: busy, onClick: () => setRevision((value) => value + 1), children: "Reload links" })
1036
1211
  ] }),
1037
- busy && /* @__PURE__ */ jsx9("p", { role: "status", children: "Loading account links\u2026" }),
1038
- !busy && !error && links.length === 0 && /* @__PURE__ */ jsx9("p", { children: "No products have linked access to this account." }),
1039
- /* @__PURE__ */ jsx9("ul", { children: links.map((link) => /* @__PURE__ */ jsxs9("li", { children: [
1040
- /* @__PURE__ */ jsxs9("p", { children: [
1212
+ busy && /* @__PURE__ */ jsx10("p", { role: "status", children: "Loading account links\u2026" }),
1213
+ !busy && !error && links.length === 0 && /* @__PURE__ */ jsx10("p", { children: "No products have linked access to this account." }),
1214
+ /* @__PURE__ */ jsx10("ul", { children: links.map((link) => /* @__PURE__ */ jsxs10("li", { children: [
1215
+ /* @__PURE__ */ jsxs10("p", { children: [
1041
1216
  link.externalIdentity?.source || "Product identity",
1042
1217
  " ",
1043
- /* @__PURE__ */ jsx9("code", { children: link.externalIdentity?.externalId ?? link.externalIdentityId })
1218
+ /* @__PURE__ */ jsx10("code", { children: link.externalIdentity?.externalId ?? link.externalIdentityId })
1044
1219
  ] }),
1045
- /* @__PURE__ */ jsxs9("p", { children: [
1220
+ /* @__PURE__ */ jsxs10("p", { children: [
1046
1221
  "Status: ",
1047
1222
  link.status,
1048
1223
  ".",
1049
1224
  " ",
1050
1225
  link.expiresAt ? `Expires ${new Date(link.expiresAt).toLocaleString()}.` : "No automatic expiry."
1051
1226
  ] }),
1052
- /* @__PURE__ */ jsx9("p", { children: link.permissions.join(", ") }),
1053
- (link.status === "active" || link.status === "pending") && /* @__PURE__ */ jsx9("button", { type: "button", disabled: busy, onClick: () => void act(link), children: "Revoke access" })
1227
+ /* @__PURE__ */ jsx10("p", { children: link.permissions.join(", ") }),
1228
+ (link.status === "active" || link.status === "pending") && /* @__PURE__ */ jsx10("button", { type: "button", disabled: busy, onClick: () => void act(link), children: "Revoke access" })
1054
1229
  ] }, link.id)) }),
1055
- cursor && /* @__PURE__ */ jsx9("button", { type: "button", disabled: busy, onClick: () => void act(), children: "Load more links" })
1230
+ cursor && /* @__PURE__ */ jsx10("button", { type: "button", disabled: busy, onClick: () => void act(), children: "Load more links" })
1056
1231
  ]
1057
1232
  }
1058
1233
  );
1059
1234
  }
1060
1235
 
1061
1236
  // src/connection-installed.tsx
1062
- import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
1237
+ import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
1063
1238
  function ConnectionInstalled({
1064
1239
  items,
1065
1240
  title = "Connected",
1066
1241
  className = ""
1067
1242
  }) {
1068
1243
  if (!items.length) return null;
1069
- return /* @__PURE__ */ jsxs10("section", { "aria-label": title, className: `og-connection-installed ${className}`, children: [
1070
- /* @__PURE__ */ jsxs10("h2", { children: [
1244
+ return /* @__PURE__ */ jsxs11("section", { "aria-label": title, className: `og-connection-installed ${className}`, children: [
1245
+ /* @__PURE__ */ jsxs11("h2", { children: [
1071
1246
  title,
1072
1247
  " ",
1073
- /* @__PURE__ */ jsx10("span", { children: items.length })
1248
+ /* @__PURE__ */ jsx11("span", { children: items.length })
1074
1249
  ] }),
1075
- /* @__PURE__ */ jsx10("div", { children: items.map((item) => /* @__PURE__ */ jsxs10(
1250
+ /* @__PURE__ */ jsx11("div", { children: items.map((item) => /* @__PURE__ */ jsxs11(
1076
1251
  "button",
1077
1252
  {
1078
1253
  type: "button",
1079
1254
  onClick: item.onOpen,
1255
+ disabled: item.disabled,
1080
1256
  title: item.status,
1081
1257
  "aria-label": `${item.name} \xB7 ${item.status}`,
1082
1258
  children: [
1083
1259
  item.icon,
1084
- /* @__PURE__ */ jsx10("span", { children: item.name }),
1085
- item.needsAttention ? /* @__PURE__ */ jsx10("span", { "aria-label": "Needs attention", children: "!" }) : null
1260
+ /* @__PURE__ */ jsx11("span", { children: item.name }),
1261
+ item.needsAttention ? /* @__PURE__ */ jsx11("span", { "aria-label": "Needs attention", children: "!" }) : null
1086
1262
  ]
1087
1263
  },
1088
1264
  item.id
@@ -1092,21 +1268,21 @@ function ConnectionInstalled({
1092
1268
 
1093
1269
  // src/connection-type-picker.tsx
1094
1270
  import { useId } from "react";
1095
- import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
1271
+ import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
1096
1272
  function ConnectionTypePicker({
1097
1273
  value,
1098
1274
  onChange,
1099
1275
  disabled = false
1100
1276
  }) {
1101
1277
  const name = useId();
1102
- return /* @__PURE__ */ jsxs11("fieldset", { className: "og-connection-type-picker", disabled, children: [
1103
- /* @__PURE__ */ jsx11("legend", { children: "Connection type" }),
1278
+ return /* @__PURE__ */ jsxs12("fieldset", { className: "og-connection-type-picker", disabled, children: [
1279
+ /* @__PURE__ */ jsx12("legend", { children: "Connection type" }),
1104
1280
  [
1105
1281
  ["mcp", "MCP server"],
1106
1282
  ["openapi", "OpenAPI"],
1107
1283
  ["graphql", "GraphQL"]
1108
- ].map(([type, label]) => /* @__PURE__ */ jsxs11("label", { "data-selected": value === type, children: [
1109
- /* @__PURE__ */ jsx11(
1284
+ ].map(([type, label]) => /* @__PURE__ */ jsxs12("label", { "data-selected": value === type, children: [
1285
+ /* @__PURE__ */ jsx12(
1110
1286
  "input",
1111
1287
  {
1112
1288
  type: "radio",
@@ -1123,71 +1299,92 @@ function ConnectionTypePicker({
1123
1299
 
1124
1300
  // src/connection-logo.tsx
1125
1301
  import { useState as useState8 } from "react";
1126
- import { jsx as jsx12 } from "react/jsx-runtime";
1302
+ import { jsx as jsx13 } from "react/jsx-runtime";
1127
1303
  function ConnectionLogo({
1128
1304
  src,
1129
1305
  name,
1130
- size = 40
1306
+ size = 40,
1307
+ fallback
1131
1308
  }) {
1132
1309
  const [failedSrc, setFailedSrc] = useState8(null);
1133
- return /* @__PURE__ */ jsx12("span", { className: "og-connection-logo", "aria-hidden": "true", style: { width: size, height: size }, children: src && src !== failedSrc ? /* @__PURE__ */ jsx12("img", { src, alt: "", loading: "lazy", decoding: "async", onError: () => setFailedSrc(src) }) : /* @__PURE__ */ jsx12("span", { children: name.split(/\s+/).map((part) => part[0]).join("").slice(0, 2).toUpperCase() }) });
1310
+ return /* @__PURE__ */ jsx13("span", { className: "og-connection-logo", "aria-hidden": "true", style: { width: size, height: size }, children: src && src !== failedSrc ? /* @__PURE__ */ jsx13("img", { src, alt: "", loading: "lazy", decoding: "async", onError: () => setFailedSrc(src) }) : fallback ?? /* @__PURE__ */ jsx13("span", { children: name.split(/\s+/).map((part) => part[0]).join("").slice(0, 2).toUpperCase() }) });
1134
1311
  }
1135
1312
 
1136
1313
  // src/plugin-discovery.tsx
1137
1314
  import { useEffect as useEffect7, useRef as useRef5, useState as useState9 } from "react";
1138
- import { Fragment as Fragment6, jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
1315
+ import { BoxesIcon } from "lucide-react";
1316
+ import { Fragment as Fragment5, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
1317
+ var discoveryCache2 = createDiscoveryCache();
1318
+ var EMPTY_INSTALLED_IDS = /* @__PURE__ */ new Set();
1139
1319
  function PluginDiscovery(props) {
1140
1320
  const [provider, setProvider] = useState9("");
1141
- return /* @__PURE__ */ jsxs12("section", { className: "og-plugin-discovery", "aria-label": "Discover plugins", children: [
1142
- /* @__PURE__ */ jsxs12("header", { children: [
1143
- /* @__PURE__ */ jsx13("h3", { children: "Browse plugins" }),
1144
- /* @__PURE__ */ jsx13("div", { className: "og-plugin-filters", role: "group", "aria-label": "Plugin registry", children: [
1145
- { value: "", label: "All" },
1146
- { value: "openai", label: "OpenAI plugin registry" },
1147
- { value: "anthropic", label: "Anthropic plugin registry" }
1148
- ].map((option) => /* @__PURE__ */ jsx13(
1149
- "button",
1150
- {
1151
- type: "button",
1152
- "aria-pressed": provider === option.value,
1153
- onClick: () => setProvider(option.value),
1154
- children: option.label
1155
- },
1156
- option.value
1157
- )) })
1158
- ] }),
1159
- /* @__PURE__ */ jsx13(
1160
- Results,
1161
- {
1162
- ...props,
1163
- provider
1164
- },
1165
- `${props.workspaceId}:${props.query}:${provider}`
1166
- )
1167
- ] });
1321
+ return /* @__PURE__ */ jsxs13(
1322
+ "section",
1323
+ {
1324
+ className: `og-plugin-discovery ${props.resultLimit ? "og-catalog-overview" : ""}`,
1325
+ "aria-label": "Discover plugins",
1326
+ children: [
1327
+ /* @__PURE__ */ jsxs13("header", { children: [
1328
+ /* @__PURE__ */ jsx14("h3", { children: props.resultLimit ? "Plugins" : "Browse plugins" }),
1329
+ !props.resultLimit ? /* @__PURE__ */ jsx14("div", { className: "og-plugin-filters", role: "group", "aria-label": "Plugin registry", children: [
1330
+ { value: "", label: "All" },
1331
+ { value: "openai", label: "OpenAI plugin registry" },
1332
+ { value: "anthropic", label: "Anthropic plugin registry" }
1333
+ ].map((option) => /* @__PURE__ */ jsx14(
1334
+ "button",
1335
+ {
1336
+ type: "button",
1337
+ "aria-pressed": provider === option.value,
1338
+ onClick: () => setProvider(option.value),
1339
+ children: option.label
1340
+ },
1341
+ option.value
1342
+ )) }) : null
1343
+ ] }),
1344
+ /* @__PURE__ */ jsx14(
1345
+ Results,
1346
+ {
1347
+ ...props,
1348
+ provider
1349
+ },
1350
+ `${props.workspaceId}:${props.query}:${provider}`
1351
+ )
1352
+ ]
1353
+ }
1354
+ );
1168
1355
  }
1169
1356
  function Results({
1170
1357
  client,
1171
1358
  workspaceId,
1172
1359
  query,
1173
1360
  provider,
1174
- onOpen
1361
+ installedIds = EMPTY_INSTALLED_IDS,
1362
+ onOpen,
1363
+ resultLimit,
1364
+ onShowMore
1175
1365
  }) {
1176
- const [items, setItems] = useState9([]);
1366
+ const initial = discoveryCache2.peek(client, JSON.stringify([workspaceId, query, provider, 0]));
1367
+ const [items, setItems] = useState9(initial?.items ?? []);
1177
1368
  const [offset, setOffset] = useState9(0);
1178
- const [next, setNext] = useState9(null);
1179
- const [total, setTotal] = useState9(0);
1180
- const [loading, setLoading] = useState9(true);
1369
+ const [next, setNext] = useState9(initial?.nextOffset ?? null);
1370
+ const [total, setTotal] = useState9(initial?.total ?? 0);
1371
+ const [loading, setLoading] = useState9(!initial);
1181
1372
  const [error, setError] = useState9(false);
1182
1373
  const [retry, setRetry] = useState9(0);
1183
1374
  const sentinel = useRef5(null);
1184
1375
  useEffect7(() => {
1185
1376
  let active = true;
1186
- setLoading(true);
1377
+ const cacheKey = JSON.stringify([workspaceId, query, provider, offset]);
1378
+ const cached = discoveryCache2.peek(client, cacheKey);
1379
+ setLoading(!cached);
1187
1380
  setError(false);
1188
1381
  const timer = setTimeout(
1189
1382
  () => {
1190
- void client.discoverPlugins(workspaceId, { query, provider, offset }).then(
1383
+ void discoveryCache2.read(
1384
+ client,
1385
+ cacheKey,
1386
+ () => client.discoverPlugins(workspaceId, { query, provider, offset })
1387
+ ).then(
1191
1388
  (page) => {
1192
1389
  if (!active) return;
1193
1390
  setItems((previous) => offset ? [...previous, ...page.items] : page.items);
@@ -1203,7 +1400,7 @@ function Results({
1203
1400
  }
1204
1401
  );
1205
1402
  },
1206
- offset ? 0 : 200
1403
+ cached || offset ? 0 : 200
1207
1404
  );
1208
1405
  return () => {
1209
1406
  active = false;
@@ -1211,7 +1408,7 @@ function Results({
1211
1408
  };
1212
1409
  }, [client, workspaceId, query, provider, offset, retry]);
1213
1410
  useEffect7(() => {
1214
- if (loading || error || next === null || !sentinel.current) return;
1411
+ if (resultLimit || loading || error || next === null || !sentinel.current) return;
1215
1412
  const observer = new IntersectionObserver(
1216
1413
  (entries) => {
1217
1414
  if (entries.some((entry) => entry.isIntersecting)) setOffset(next);
@@ -1220,54 +1417,45 @@ function Results({
1220
1417
  );
1221
1418
  observer.observe(sentinel.current);
1222
1419
  return () => observer.disconnect();
1223
- }, [loading, error, next]);
1224
- return /* @__PURE__ */ jsxs12(Fragment6, { children: [
1225
- !loading && !error ? /* @__PURE__ */ jsx13("p", { role: "status", children: total ? `${total} plugins` : "No matching plugins. Try another search or registry." }) : null,
1226
- /* @__PURE__ */ jsx13("div", { className: "og-plugin-discovery-grid", children: items.map((item) => /* @__PURE__ */ jsxs12(
1227
- "button",
1420
+ }, [loading, error, next, resultLimit]);
1421
+ return /* @__PURE__ */ jsxs13(Fragment5, { children: [
1422
+ !loading && !error ? /* @__PURE__ */ jsx14("p", { role: "status", children: total ? `${total} plugins` : "No matching plugins. Try another search or registry." }) : null,
1423
+ /* @__PURE__ */ jsx14("div", { className: "og-plugin-discovery-grid", children: items.slice(0, resultLimit).map((item) => /* @__PURE__ */ jsx14(
1424
+ CapabilityCatalogRow,
1228
1425
  {
1229
- className: "og-plugin-discovery-row",
1230
- type: "button",
1231
- onClick: () => onOpen(item),
1232
- children: [
1233
- item.logoUrl ? /* @__PURE__ */ jsx13(
1234
- "img",
1235
- {
1236
- src: item.logoUrl,
1237
- alt: "",
1238
- loading: "lazy",
1239
- onError: (event) => {
1240
- event.currentTarget.style.display = "none";
1241
- }
1242
- }
1243
- ) : null,
1244
- /* @__PURE__ */ jsxs12("span", { className: "og-plugin-copy", children: [
1245
- /* @__PURE__ */ jsxs12("span", { className: "og-plugin-title", children: [
1246
- /* @__PURE__ */ jsx13("strong", { children: item.displayName.replace(/-/g, " ") }),
1247
- /* @__PURE__ */ jsx13("small", { children: item.provider === "openai" ? "OpenAI plugin registry" : "Anthropic plugin registry" })
1248
- ] }),
1249
- /* @__PURE__ */ jsx13("span", { className: "og-plugin-description", children: item.description }),
1250
- item.category ? /* @__PURE__ */ jsx13("span", { className: "og-plugin-category", children: item.category }) : null
1251
- ] }),
1252
- /* @__PURE__ */ jsx13("span", { className: "og-plugin-open", "aria-hidden": "true", children: "\u203A" })
1253
- ]
1426
+ "data-plugin-id": item.id,
1427
+ name: item.displayName.replace(/-/g, " "),
1428
+ description: item.description,
1429
+ status: installedIds.has(item.id) ? "added" : "available",
1430
+ statusLabel: installedIds.has(item.id) ? "Installed" : "Available to install",
1431
+ onOpen: () => onOpen(item),
1432
+ icon: /* @__PURE__ */ jsx14(
1433
+ ConnectionLogo,
1434
+ {
1435
+ src: item.logoUrl,
1436
+ name: item.displayName,
1437
+ fallback: /* @__PURE__ */ jsx14(BoxesIcon, { "aria-hidden": "true" })
1438
+ }
1439
+ )
1254
1440
  },
1255
1441
  item.id
1256
1442
  )) }),
1257
- loading ? /* @__PURE__ */ jsx13("p", { role: "status", children: "Loading plugins\u2026" }) : null,
1258
- error ? /* @__PURE__ */ jsxs12("p", { role: "alert", children: [
1443
+ loading ? /* @__PURE__ */ jsx14("p", { role: "status", children: "Loading plugins\u2026" }) : null,
1444
+ error ? /* @__PURE__ */ jsxs13("p", { role: "alert", children: [
1259
1445
  "Couldn\u2019t load plugins.",
1260
1446
  " ",
1261
- /* @__PURE__ */ jsx13("button", { type: "button", onClick: () => setRetry((value) => value + 1), children: "Retry" })
1447
+ /* @__PURE__ */ jsx14("button", { type: "button", onClick: () => setRetry((value) => value + 1), children: "Retry" })
1262
1448
  ] }) : null,
1263
- /* @__PURE__ */ jsx13("div", { ref: sentinel, children: next !== null && !loading && !error ? /* @__PURE__ */ jsx13("button", { className: "og-plugin-more", type: "button", onClick: () => setOffset(next), children: "Show more plugins" }) : null })
1449
+ resultLimit && !loading && !error && total > resultLimit ? /* @__PURE__ */ jsx14("button", { className: "og-catalog-more", type: "button", onClick: onShowMore, children: "View all plugins" }) : null,
1450
+ /* @__PURE__ */ jsx14("div", { ref: sentinel, children: !resultLimit && next !== null && !loading && !error ? /* @__PURE__ */ jsx14("button", { className: "og-plugin-more", type: "button", onClick: () => setOffset(next), children: "Show more plugins" }) : null })
1264
1451
  ] });
1265
1452
  }
1266
1453
 
1267
1454
  // src/plugin-details.tsx
1268
1455
  import { useState as useState10 } from "react";
1269
1456
  import { pluginMcpUnavailableReason } from "@opengeni/sdk";
1270
- import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
1457
+ import { BoxesIcon as BoxesIcon2 } from "lucide-react";
1458
+ import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
1271
1459
  var componentLabels = {
1272
1460
  skills: "Skills",
1273
1461
  mcp: "MCP connections",
@@ -1291,57 +1479,63 @@ function PluginDetails({
1291
1479
  const contentsUnknown = item.skills == null || item.mcpServers == null;
1292
1480
  const installableCount = (item.skills?.length ?? 0) + (item.mcpServers?.filter(supported).length ?? 0);
1293
1481
  const exceedsInstallLimit = installableCount > 64;
1294
- const installable = installableCount > 0 && !exceedsInstallLimit;
1482
+ const installable = !contentsUnknown && installableCount > 0 && !exceedsInstallLimit;
1295
1483
  const [expanded, setExpanded] = useState10(false);
1296
- const [logoFailed, setLogoFailed] = useState10(false);
1297
1484
  const description = item.longDescription || item.description;
1298
1485
  const lengthy = description.length > 700;
1299
1486
  const registryLabel = item.provider === "openai" ? "OpenAI plugin registry" : item.provider === "anthropic" ? "Anthropic plugin registry" : "Custom source";
1300
- return /* @__PURE__ */ jsxs13("article", { className: "og-plugin-details", children: [
1301
- /* @__PURE__ */ jsxs13("header", { className: "og-plugin-details-header", children: [
1302
- item.logoUrl && !logoFailed ? /* @__PURE__ */ jsx14("img", { src: item.logoUrl, alt: "", onError: () => setLogoFailed(true) }) : null,
1303
- /* @__PURE__ */ jsxs13("div", { children: [
1304
- /* @__PURE__ */ jsx14("h2", { children: item.displayName.replace(/-/g, " ") }),
1305
- item.author?.name ? /* @__PURE__ */ jsxs13("p", { children: [
1487
+ return /* @__PURE__ */ jsxs14("article", { className: "og-plugin-details", children: [
1488
+ /* @__PURE__ */ jsxs14("header", { className: "og-plugin-details-header", children: [
1489
+ /* @__PURE__ */ jsx15(
1490
+ ConnectionLogo,
1491
+ {
1492
+ src: item.logoUrl,
1493
+ name: item.displayName,
1494
+ fallback: /* @__PURE__ */ jsx15(BoxesIcon2, { "aria-hidden": "true" })
1495
+ }
1496
+ ),
1497
+ /* @__PURE__ */ jsxs14("div", { children: [
1498
+ /* @__PURE__ */ jsx15("h2", { children: item.displayName.replace(/-/g, " ") }),
1499
+ item.author?.name ? /* @__PURE__ */ jsxs14("p", { children: [
1306
1500
  "By ",
1307
1501
  item.author.name
1308
1502
  ] }) : null
1309
1503
  ] })
1310
1504
  ] }),
1311
- /* @__PURE__ */ jsxs13("div", { className: "og-plugin-details-meta", children: [
1312
- /* @__PURE__ */ jsx14("span", { children: registryLabel }),
1313
- item.category ? /* @__PURE__ */ jsx14("span", { children: item.category }) : null,
1314
- item.version ? /* @__PURE__ */ jsxs13("span", { children: [
1505
+ /* @__PURE__ */ jsxs14("div", { className: "og-plugin-details-meta", children: [
1506
+ /* @__PURE__ */ jsx15("span", { children: registryLabel }),
1507
+ item.category ? /* @__PURE__ */ jsx15("span", { children: item.category }) : null,
1508
+ item.version ? /* @__PURE__ */ jsxs14("span", { children: [
1315
1509
  "v",
1316
1510
  item.version
1317
1511
  ] }) : null
1318
1512
  ] }),
1319
- /* @__PURE__ */ jsxs13("section", { className: "og-plugin-details-members", children: [
1320
- /* @__PURE__ */ jsxs13("h3", { children: [
1513
+ /* @__PURE__ */ jsxs14("section", { className: "og-plugin-details-members", children: [
1514
+ /* @__PURE__ */ jsxs14("h3", { children: [
1321
1515
  "Skills ",
1322
- /* @__PURE__ */ jsx14("span", { children: item.skills?.length ?? "\u2014" })
1516
+ /* @__PURE__ */ jsx15("span", { children: item.skills?.length ?? "\u2014" })
1323
1517
  ] }),
1324
- item.skills?.length ? /* @__PURE__ */ jsx14("ul", { children: item.skills.map((skill) => /* @__PURE__ */ jsx14("li", { children: /* @__PURE__ */ jsxs13("a", { href: skill.sourceUrl, target: "_blank", rel: "noopener noreferrer", children: [
1325
- /* @__PURE__ */ jsx14("strong", { children: skill.name }),
1326
- /* @__PURE__ */ jsx14("span", { "aria-hidden": "true", children: "\u2197" })
1327
- ] }) }, skill.sourceUrl)) }) : /* @__PURE__ */ jsx14("p", { children: item.skills ? "No bundled skills." : "Contents haven\u2019t been indexed for this repository." }),
1328
- /* @__PURE__ */ jsxs13("h3", { children: [
1518
+ item.skills?.length ? /* @__PURE__ */ jsx15("ul", { children: item.skills.map((skill) => /* @__PURE__ */ jsx15("li", { children: /* @__PURE__ */ jsxs14("a", { href: skill.sourceUrl, target: "_blank", rel: "noopener noreferrer", children: [
1519
+ /* @__PURE__ */ jsx15("strong", { children: skill.name }),
1520
+ /* @__PURE__ */ jsx15("span", { "aria-hidden": "true", children: "\u2197" })
1521
+ ] }) }, skill.sourceUrl)) }) : /* @__PURE__ */ jsx15("p", { children: item.skills ? "No bundled skills." : "Contents haven\u2019t been indexed for this repository." }),
1522
+ /* @__PURE__ */ jsxs14("h3", { children: [
1329
1523
  "MCP servers ",
1330
- /* @__PURE__ */ jsx14("span", { children: item.mcpServers?.length ?? "\u2014" })
1524
+ /* @__PURE__ */ jsx15("span", { children: item.mcpServers?.length ?? "\u2014" })
1331
1525
  ] }),
1332
- item.mcpServers?.length ? /* @__PURE__ */ jsx14("ul", { children: item.mcpServers.map((server) => {
1526
+ item.mcpServers?.length ? /* @__PURE__ */ jsx15("ul", { children: item.mcpServers.map((server) => {
1333
1527
  const connected = Boolean(server.endpoint && connections[server.endpoint]);
1334
1528
  const unavailableReason = connected ? null : pluginMcpUnavailableReason(server);
1335
- return /* @__PURE__ */ jsxs13(
1529
+ return /* @__PURE__ */ jsxs14(
1336
1530
  "li",
1337
1531
  {
1338
1532
  className: unavailableReason ? "og-plugin-member-disabled" : void 0,
1339
1533
  children: [
1340
- /* @__PURE__ */ jsxs13("div", { className: "og-plugin-server-heading", children: [
1341
- /* @__PURE__ */ jsx14("strong", { children: server.name }),
1342
- !unavailableReason && onConnect ? /* @__PURE__ */ jsx14("button", { type: "button", disabled: busy, onClick: () => onConnect(server), children: connected ? "Manage" : "Connect" }) : null
1534
+ /* @__PURE__ */ jsxs14("div", { className: "og-plugin-server-heading", children: [
1535
+ /* @__PURE__ */ jsx15("strong", { children: server.name }),
1536
+ !unavailableReason && onConnect ? /* @__PURE__ */ jsx15("button", { type: "button", disabled: busy, onClick: () => onConnect(server), children: connected ? "Manage" : "Connect" }) : null
1343
1537
  ] }),
1344
- /* @__PURE__ */ jsxs13("small", { children: [
1538
+ /* @__PURE__ */ jsxs14("small", { children: [
1345
1539
  connected ? "Connected \xB7 " : "",
1346
1540
  unavailableReason ?? server.endpoint
1347
1541
  ] })
@@ -1349,16 +1543,16 @@ function PluginDetails({
1349
1543
  },
1350
1544
  server.name
1351
1545
  );
1352
- }) }) : /* @__PURE__ */ jsx14("p", { children: item.mcpServers ? "No bundled MCP servers." : "Server details haven\u2019t been indexed." }),
1353
- item.components?.some((component) => !["skills", "mcp"].includes(component)) ? /* @__PURE__ */ jsxs13("div", { className: "og-plugin-details-other", children: [
1546
+ }) }) : /* @__PURE__ */ jsx15("p", { children: item.mcpServers ? "No bundled MCP servers." : "Server details haven\u2019t been indexed." }),
1547
+ item.components?.some((component) => !["skills", "mcp"].includes(component)) ? /* @__PURE__ */ jsxs14("div", { className: "og-plugin-details-other", children: [
1354
1548
  "Not installed here:",
1355
1549
  " ",
1356
1550
  item.components.filter((component) => !["skills", "mcp"].includes(component)).map((component) => componentLabels[component] ?? component).join(", ")
1357
1551
  ] }) : null
1358
1552
  ] }),
1359
- /* @__PURE__ */ jsxs13("section", { className: "og-plugin-details-overview", "aria-label": "Overview", children: [
1360
- /* @__PURE__ */ jsx14("div", { className: lengthy && !expanded ? "og-plugin-details-excerpt" : void 0, children: /* @__PURE__ */ jsx14(Markdown, { children: description }) }),
1361
- lengthy ? /* @__PURE__ */ jsx14(
1553
+ /* @__PURE__ */ jsxs14("section", { className: "og-plugin-details-overview", "aria-label": "Overview", children: [
1554
+ /* @__PURE__ */ jsx15("div", { className: lengthy && !expanded ? "og-plugin-details-excerpt" : void 0, children: /* @__PURE__ */ jsx15(Markdown, { children: description }) }),
1555
+ lengthy ? /* @__PURE__ */ jsx15(
1362
1556
  "button",
1363
1557
  {
1364
1558
  type: "button",
@@ -1369,12 +1563,12 @@ function PluginDetails({
1369
1563
  }
1370
1564
  ) : null
1371
1565
  ] }),
1372
- /* @__PURE__ */ jsxs13("footer", { children: [
1373
- item.sourceUrl ? /* @__PURE__ */ jsxs13("a", { href: item.sourceUrl, target: "_blank", rel: "noopener noreferrer", children: [
1566
+ /* @__PURE__ */ jsxs14("footer", { children: [
1567
+ item.sourceUrl ? /* @__PURE__ */ jsxs14("a", { href: item.sourceUrl, target: "_blank", rel: "noopener noreferrer", children: [
1374
1568
  "View repository ",
1375
- /* @__PURE__ */ jsx14("span", { "aria-hidden": "true", children: "\u2197" })
1569
+ /* @__PURE__ */ jsx15("span", { "aria-hidden": "true", children: "\u2197" })
1376
1570
  ] }) : null,
1377
- onInstall ? /* @__PURE__ */ jsx14(
1571
+ onInstall ? /* @__PURE__ */ jsx15(
1378
1572
  "button",
1379
1573
  {
1380
1574
  className: "og-plugin-install",
@@ -1384,8 +1578,8 @@ function PluginDetails({
1384
1578
  children: installed ? "Installed" : busy ? "Installing\u2026" : "Install plugin"
1385
1579
  }
1386
1580
  ) : null,
1387
- error ? /* @__PURE__ */ jsx14("p", { role: "alert", children: error }) : null,
1388
- exceedsInstallLimit ? /* @__PURE__ */ jsx14("p", { children: "This plugin exceeds the current 64-component installation limit." }) : contentsUnknown ? /* @__PURE__ */ jsx14("p", { children: "Plugin contents are unavailable. Installation is disabled until the repository can be inspected." }) : !installable ? /* @__PURE__ */ jsx14("p", { children: "No installable skills or remote MCP servers." }) : /* @__PURE__ */ jsx14("p", { children: "Installs skills and adds connection references. Connect each server separately." })
1581
+ error ? /* @__PURE__ */ jsx15("p", { role: "alert", children: error }) : null,
1582
+ exceedsInstallLimit ? /* @__PURE__ */ jsx15("p", { children: "This plugin exceeds the current 64-component installation limit." }) : contentsUnknown ? /* @__PURE__ */ jsx15("p", { children: "Plugin contents are unavailable. Installation is disabled until the repository can be inspected." }) : !installable ? /* @__PURE__ */ jsx15("p", { children: "No installable skills or remote MCP servers." }) : /* @__PURE__ */ jsx15("p", { children: "Installs skills and adds connection references. Connect each server separately." })
1389
1583
  ] })
1390
1584
  ] });
1391
1585
  }
@@ -1411,6 +1605,8 @@ function useConnect(controller) {
1411
1605
  return useMemo(() => ({ ...snapshot, ...actions }), [snapshot, actions]);
1412
1606
  }
1413
1607
  export {
1608
+ CapabilityCatalogIndicator,
1609
+ CapabilityCatalogRow,
1414
1610
  ConnectAccounts,
1415
1611
  ConnectChooser,
1416
1612
  ConnectPanel,