+
+
Loading…}>
= {
openapi: "openapi",
@@ -72,7 +85,7 @@ export function SourcesPage(props: { sourcePlugins: readonly SourcePlugin[] }) {
Sources
-
+
Tool providers available in this workspace.
@@ -80,55 +93,63 @@ export function SourcesPage(props: { sourcePlugins: readonly SourcePlugin[] }) {
{/* URL detection input */}
-
- {
- setUrl((e.target as HTMLInputElement).value);
- setError(null);
- }}
- onKeyDown={(e) => {
- if (e.key === "Enter") handleDetect();
- }}
- placeholder="Paste a URL to auto-detect source type..."
- disabled={detecting}
- className="flex-1"
- />
-
-
- {error &&
{error}
}
-
- Or add manually:
- {sourcePlugins.map((p) => (
-
+
+
- {p.label}
-
- ))}
-
+
+ {
+ setUrl((e.target as HTMLInputElement).value);
+ setError(null);
+ }}
+ onKeyDown={(e) => {
+ if (e.key === "Enter") handleDetect();
+ }}
+ placeholder="https://..."
+ disabled={detecting}
+ className="flex-1"
+ />
+
+
+
+ Or add manually:{" "}
+ {sourcePlugins.map((p) => (
+
+ {p.label}
+
+ ))}
+
+
+
+
-
-
-
+
+
+
{Result.match(sources, {
onInitial: () =>
Loading…
,
onFailure: () =>
Failed to load sources
,
onSuccess: ({ value }) => {
- const builtInSources = value.filter((source) => source.runtime);
const connectedSources = value.filter((source) => !source.runtime);
return value.length === 0 ? (
-
+
-
No sources yet
-
+
No sources yet
+
Add a source to get started.
) : (
-
- {builtInSources.length > 0 && (
-
-
-
Built-in
-
- Runtime sources exposed by the loaded executor plugins.
-
-
-
-
- )}
-
+
{connectedSources.length > 0 && (
-
-
Connected
-
- User-configured sources available in this workspace.
-
-
)}
@@ -173,6 +176,10 @@ export function SourcesPage(props: { sourcePlugins: readonly SourcePlugin[] }) {
);
},
})}
+
+
+
+
);
@@ -182,47 +189,22 @@ export function SourcesPage(props: { sourcePlugins: readonly SourcePlugin[] }) {
// Preset grid
// ---------------------------------------------------------------------------
-type PresetEntry = { preset: SourcePreset; pluginKey: string; pluginLabel: string };
-
-function PresetCard({ preset, pluginKey, pluginLabel }: PresetEntry) {
- const search: Record
= { preset: preset.id };
- if (preset.url) search.url = preset.url;
-
- return (
-
-
- {preset.icon ? (
-

- ) : (
-
- )}
-
-
-
- {preset.name}
-
- {pluginLabel}
-
-
-
{preset.summary}
-
-
- );
-}
+type PresetEntry = {
+ preset: SourcePreset;
+ pluginKey: string;
+ pluginLabel: string;
+};
function PresetGrid(props: { plugins: readonly SourcePlugin[] }) {
const allPresets = useMemo(() => {
const entries: PresetEntry[] = [];
for (const plugin of props.plugins) {
for (const preset of plugin.presets ?? []) {
- entries.push({ preset, pluginKey: plugin.key, pluginLabel: plugin.label });
+ entries.push({
+ preset,
+ pluginKey: plugin.key,
+ pluginLabel: plugin.label,
+ });
}
}
return entries;
@@ -232,17 +214,46 @@ function PresetGrid(props: { plugins: readonly SourcePlugin[] }) {
return (
-
-
Popular sources
-
- One-click setup for common APIs and services.
-
-
-
- {allPresets.map((entry) => (
-
- ))}
-
+
+ Popular sources
+
+ {allPresets.map(({ preset, pluginKey, pluginLabel }) => {
+ const search: Record = { preset: preset.id };
+ if (preset.url) search.url = preset.url;
+ return (
+
+
+
+ {preset.icon ? (
+
+ ) : (
+
+ )}
+
+
+ {preset.name}
+ {preset.summary}
+
+
+ {pluginLabel}
+
+
+
+ );
+ })}
+
+
);
}
@@ -252,48 +263,43 @@ function PresetGrid(props: { plugins: readonly SourcePlugin[] }) {
// ---------------------------------------------------------------------------
function SourceGrid(props: {
- sources: readonly { id: string; name: string; kind: string; runtime?: boolean }[];
+ sources: readonly {
+ id: string;
+ name: string;
+ kind: string;
+ runtime?: boolean;
+ }[];
}) {
return (
-
- {props.sources.map((s) => (
-
-
-
-
-
-
{s.name}
-
- {s.runtime && (
-
- built-in
-
- )}
-
- {s.kind}
-
-
-
-
{s.id}
-
-
-
- ))}
-
+
+ Connected
+
+ {props.sources.map((s) => (
+
+
+
+
+
+
+ {s.name}
+ {s.id}
+
+
+ {s.runtime && built-in}
+ {s.kind}
+
+
+
+ ))}
+
+
);
}