History

Tighten plugin ownership boundaries

Rhys Sullivan committed 7 months ago

Commit f2a7b111 parent 4f7dbcc38 files · +237 −350Browse files

Unified · Split

38 files
  1. apps/web/src/components/shell.tsx +3 −3
  2. apps/web/src/components/source-favicon.tsx +6 −11
  3. apps/web/src/lib/source-favicon.ts +0 −123
  4. apps/web/src/main.tsx +2 −2
  5. apps/web/src/plugins/index.ts +4 −0
  6. apps/web/src/plugins/pages.tsx +0 −0
  7. apps/web/src/views/home.tsx +1 −1
  8. bun.lock +0 −15
  9. packages/auth/mcp-oauth/package.json +0 −23
  10. packages/auth/mcp-oauth/tsconfig.json +0 −19
  11. packages/clients/react/src/plugins/components/badge.tsx +0 −0
  12. packages/clients/react/src/plugins/components/code-block.tsx +0 −0
  13. packages/clients/react/src/plugins/components/document-panel.tsx +0 −0
  14. packages/clients/react/src/plugins/components/icons.tsx +0 −0
  15. packages/clients/react/src/plugins/components/loadable.tsx +0 −0
  16. packages/clients/react/src/plugins/components/markdown.tsx +0 −0
  17. packages/clients/react/src/plugins/components/source-tool-explorer.tsx +0 −0
  18. packages/clients/react/src/plugins/index.ts +104 −1
  19. packages/clients/react/src/plugins/lib/cn.ts +0 −0
  20. packages/clients/react/src/plugins/lib/shiki.ts +0 −0
  21. packages/clients/react/src/plugins/paths.ts +0 −0
  22. packages/clients/react/src/plugins/plugin-route-context.tsx +0 −0
  23. packages/clients/react/src/plugins/registry.ts +0 −0
  24. packages/clients/react/src/plugins/route-context.tsx +0 −0
  25. packages/clients/react/src/plugins/types.ts +1 −0
  26. packages/clients/react/src/source-plugins/index.ts +1 −104
  27. plugins/google-discovery/http/index.ts +23 −12
  28. plugins/google-discovery/react/index.tsx +55 −12
  29. plugins/google-discovery/sdk/catalog.ts +3 −2
  30. plugins/google-discovery/sdk/index.ts +15 −13
  31. plugins/google-discovery/sdk/tools.ts +3 −2
  32. plugins/google-discovery/sdk/types.ts +2 −1
  33. plugins/google-discovery/shared/index.ts +8 −0
  34. plugins/mcp/sdk/discovery.ts +1 −1
  35. plugins/mcp/sdk/index.ts +1 −1
  36. plugins/mcp/sdk/oauth-effect-errors.ts +0 −0
  37. plugins/mcp/sdk/oauth.ts +4 −3
  38. plugins/mcp/sdk/package.json +0 −1
apps/web/src/components/shell.tsx+3−3
@@ -6,7 +6,7 @@ import { cn } from "../lib/utils"; · 5 unmodified lines
66 import { IconPlus, IconCopy, IconCheck } from "./icons";
77 import { LoadableBlock } from "./loadable";
88 import { SourceFavicon } from "./source-favicon";
9−import { getSourceFrontendPaths } from "../source-plugins";
9+import { getSourceFrontendPaths } from "../plugins";
1010
1111 // ── Status dot color ─────────────────────────────────────────────────────
1212
@@ -324,7 +324,7 @@ function SourceItem(props: { · 311 unmodified lines
324324 return (
325325 <div className="group flex items-center gap-2 rounded-md px-2.5 py-1.5 text-[13px] text-sidebar-foreground/60">
326326 <div className="flex size-3 shrink-0 items-center justify-center text-muted-foreground/50">
327− <SourceFavicon kind={props.source.kind} className="size-3" />
327+ <SourceFavicon source={props.source} className="size-3" />
328328 </div>
329329 <span className="flex-1 truncate">{props.source.name}</span>
330330 <span
@@ -352,7 +352,7 @@ function SourceItem(props: { · 21 unmodified lines
352352 )}
353353 >
354354 <div className="flex size-3 shrink-0 items-center justify-center text-muted-foreground/50">
355− <SourceFavicon kind={props.source.kind} className="size-3" />
355+ <SourceFavicon source={props.source} className="size-3" />
356356 </div>
357357 <span className="flex-1 truncate">{props.source.name}</span>
358358 <span
apps/web/src/components/source-favicon.tsx+6−11
@@ -1,30 +1,25 @@
1−import { useMemo, useState } from "react";
1+import { useState } from "react";
22 import type { Source } from "@executor/react";
3−import { getGoogleProductIconUrl, getSourceFaviconUrl } from "../lib/source-favicon";
3+import { getSourceFrontendIconUrl } from "../plugins";
44 import { cn } from "../lib/utils";
55
66 type SourceKind = Source["kind"] | string;
77
88 export function SourceFavicon({
9− endpoint,
10− kind: _kind,
9+ source,
1110 className,
1211 size = 16,
1312 }: {
14− endpoint?: string | null;
15− kind: SourceKind;
13+ source: Source;
1614 className?: string;
1715 size?: number;
1816 }) {
19− const faviconUrl = useMemo(() => {
20− return getGoogleProductIconUrl(endpoint) ?? getSourceFaviconUrl(endpoint);
21− }, [endpoint]);
22−
17+ const faviconUrl = getSourceFrontendIconUrl(source);
2318 const [failedUrl, setFailedUrl] = useState<string | null>(null);
2419 const isFailed = Boolean(faviconUrl && failedUrl === faviconUrl);
2520
2621 if (!faviconUrl || isFailed) {
27− return <DefaultSourceIcon kind={_kind} className={className} />;
22+ return <DefaultSourceIcon kind={source.kind} className={className} />;
2823 }
2924
3025 return (
apps/web/src/lib/source-favicon.ts+0−123
@@ -1,123 +0,0 @@
1−import { parse as parseDomain } from "tldts";
2−
3−const RAW_HOSTS = new Set([
4− "raw.githubusercontent.com",
5− "cdn.jsdelivr.net",
6− "unpkg.com",
7− "raw.github.com",
8−]);
9−
10−// ---------------------------------------------------------------------------
11−// Google product icon URLs (official CDN assets)
12−// ---------------------------------------------------------------------------
13−
14−const GOOGLE_SERVICE_ICONS: Record<string, string> = {
15− calendar: "https://ssl.gstatic.com/calendar/images/dynamiclogo_2020q4/calendar_31_2x.png",
16− drive: "https://ssl.gstatic.com/images/branding/product/2x/drive_2020q4_48dp.png",
17− gmail: "https://ssl.gstatic.com/ui/v1/icons/mail/rfr/gmail.ico",
18− docs: "https://ssl.gstatic.com/docs/documents/images/kix-favicon7.ico",
19− sheets: "https://ssl.gstatic.com/docs/spreadsheets/favicon3.ico",
20− slides: "https://ssl.gstatic.com/docs/presentations/images/favicon5.ico",
21− forms: "https://ssl.gstatic.com/docs/forms/device_home/android_192.png",
22− searchconsole: "https://ssl.gstatic.com/search-console/scfe/search_console-64.png",
23− people: "https://ssl.gstatic.com/images/branding/product/2x/contacts_2022_48dp.png",
24− tasks: "https://ssl.gstatic.com/tasks/images/favicon.ico",
25− chat: "https://ssl.gstatic.com/chat/favicon/favicon_v2.ico",
26− keep: "https://ssl.gstatic.com/keep/icon_2020q4v2_128.png",
27− classroom: "https://ssl.gstatic.com/classroom/favicon.png",
28− admin: "https://ssl.gstatic.com/images/branding/product/2x/admin_2020q4_48dp.png",
29− script: "https://ssl.gstatic.com/script/images/favicon.ico",
30− bigquery: "https://ssl.gstatic.com/bqui1/favicon.ico",
31− cloudresourcemanager: "https://www.gstatic.com/devrel-devsite/prod/v0e0f589edd85502a40d78d7d0825db8ea5ef3b99b1571571945f0f3f764ff61b/cloud/images/favicons/onecloud/favicon.ico",
32− youtube: "https://www.youtube.com/s/desktop/a94e1818/img/favicon_32x32.png",
33−};
34−
35−/**
36− * For google_discovery endpoints, extract the service name and return
37− * the official product icon URL if we have one.
38− */
39−const getGoogleServiceIconUrl = (endpoint: string | null | undefined): string | null => {
40− if (!endpoint) return null;
41− try {
42− const url = new URL(endpoint);
43− const host = url.hostname;
44−
45− // Direct service subdomain: "calendar-json.googleapis.com", "gmail.googleapis.com"
46− if (host.endsWith(".googleapis.com")) {
47− const sub = host.replace(/\.googleapis\.com$/, "").replace(/-json$/, "");
48− if (GOOGLE_SERVICE_ICONS[sub]) return GOOGLE_SERVICE_ICONS[sub];
49− }
50−
51− // Discovery URL pattern: /discovery/v1/apis/{service}/{version}/rest
52− const discoveryMatch = url.pathname.match(/\/apis\/([^/]+)\//);
53− if (discoveryMatch?.[1] && GOOGLE_SERVICE_ICONS[discoveryMatch[1]]) {
54− return GOOGLE_SERVICE_ICONS[discoveryMatch[1]];
55− }
56−
57− // $discovery/rest pattern on service subdomains is already handled above
58− } catch {
59− // fall through
60− }
61− return null;
62−};
63−
64−// ---------------------------------------------------------------------------
65−// General favicon resolution
66−// ---------------------------------------------------------------------------
67−
68−const parseUrl = (value: string | null | undefined): URL | null => {
69− if (!value) {
70− return null;
71− }
72−
73− try {
74− return new URL(value);
75− } catch {
76− return null;
77− }
78−};
79−
80−const normalizeSeedUrl = (value: string | null | undefined): string | null => {
81− const parsed = parseUrl(value);
82− if (!parsed) {
83− return null;
84− }
85−
86− if (!RAW_HOSTS.has(parsed.hostname)) {
87− return parsed.origin;
88− }
89−
90− const segments = parsed.pathname
91− .split("/")
92− .map((segment) => segment.trim())
93− .filter((segment) => segment.length > 0);
94−
95− for (const segment of segments) {
96− const withoutExtension = segment.replace(/\.(ya?ml|json)$/i, "");
97− if (/^[a-z0-9-]+(\.[a-z0-9-]+)+$/i.test(withoutExtension)) {
98− return `https://${withoutExtension}`;
99− }
100− }
101−
102− return parsed.origin;
103−};
104−
105−export const getGoogleProductIconUrl = getGoogleServiceIconUrl;
106−
107−export const getSourceFaviconUrl = (
108− value: string | null | undefined,
109−): string | null => {
110− const seedUrl = normalizeSeedUrl(value);
111− if (!seedUrl) {
112− return null;
113− }
114−
115− try {
116− const hostname = new URL(seedUrl).hostname;
117− const parsed = parseDomain(hostname);
118− const domain = parsed.domain ?? hostname;
119− return `https://www.google.com/s2/favicons?domain=${encodeURIComponent(domain)}&sz=32`;
120− } catch {
121− return null;
122− }
123−};
apps/web/src/main.tsx+2−2
@@ -24,7 +24,7 @@ import { AppShell } from "./components/shell"; · 23 unmodified lines
2424 import {
2525 registeredFrontendPluginRoutes,
2626 registeredSourceFrontendTypes,
27−} from "./source-plugins";
27+} from "./plugins";
2828 import {
2929 ExecutorPluginRoutePage,
3030 SourcePluginAddPage,
@@ -32,7 +32,7 @@ import { · 1 unmodified line
3232 SourcePluginDetailPage,
3333 SourcePluginEditPage,
3434 SourcePluginsIndexPage,
35−} from "./source-plugins/pages";
35+} from "./plugins/pages";
3636 import { HomePage } from "./views/home";
3737 import { SecretsPage } from "./views/secrets";
3838
apps/web/src/plugins/index.tsrenamed from apps/web/src/source-plugins/index.ts+4−0
@@ -1,3 +1,4 @@
1+import type { Source } from "@executor/react";
12 import {
23 GoogleDiscoveryReactPlugin,
34 } from "@executor/plugin-google-discovery-react";
@@ -59,3 +60,6 @@ export const getSourceFrontendPaths = (kind: string) => { · 55 unmodified lines
5960 const definition = getSourceFrontendType(kind);
6061 return definition ? createSourcePluginPaths(definition.key) : null;
6162 };
63+
64+export const getSourceFrontendIconUrl = (source: Source) =>
65+ getSourceFrontendTypeEntry(source.kind)?.definition.getIconUrl?.(source) ?? null;
apps/web/src/plugins/pages.tsxrenamed from apps/web/src/source-plugins/pages.tsx+0−0

File renamed without changes.

apps/web/src/views/home.tsx+1−1
@@ -8,7 +8,7 @@ import { SourcePluginsResetState } from "../components/source-plugins-reset-stat · 7 unmodified lines
88 import {
99 getSourceFrontendPaths,
1010 registeredSourceFrontendTypes,
11−} from "../source-plugins";
11+} from "../plugins";
1212
1313 export function HomePage() {
1414 const sources = useSources();
bun.lock+0−15
@@ -123,18 +123,6 @@ · 122 unmodified lines
123123 "bun-types": "catalog:",
124124 },
125125 },
126− "packages/auth/mcp-oauth": {
127− "name": "@executor/auth-mcp-oauth",
128− "version": "0.0.0",
129− "dependencies": {
130− "@modelcontextprotocol/sdk": "^1.26.0",
131− "effect": "catalog:",
132− },
133− "devDependencies": {
134− "@types/node": "catalog:",
135− "bun-types": "catalog:",
136− },
137− },
138126 "packages/clients/react": {
139127 "name": "@executor/react",
140128 "version": "0.0.0",
@@ -587,7 +575,6 @@ · 446 unmodified lines
587575 "name": "@executor/plugin-mcp-sdk",
588576 "version": "0.0.0",
589577 "dependencies": {
590− "@executor/auth-mcp-oauth": "workspace:*",
591578 "@executor/codemode-core": "workspace:*",
592579 "@executor/ir": "workspace:*",
593580 "@executor/platform-sdk": "workspace:*",
@@ -883,8 +870,6 @@ · 289 unmodified lines
883870
884871 "@executor/ai-sdk-adapter": ["@executor/ai-sdk-adapter@workspace:packages/hosts/ai-sdk"],
885872
886− "@executor/auth-mcp-oauth": ["@executor/auth-mcp-oauth@workspace:packages/auth/mcp-oauth"],
887−
888873 "@executor/codemode-core": ["@executor/codemode-core@workspace:packages/kernel/core"],
889874
890875 "@executor/docs": ["@executor/docs@workspace:apps/docs"],
packages/auth/mcp-oauth/package.json+0−23
@@ -1,23 +0,0 @@
1−{
2− "name": "@executor/auth-mcp-oauth",
3− "private": true,
4− "type": "module",
5− "exports": {
6− ".": "./src/index.ts"
7− },
8− "files": [
9− "src"
10− ],
11− "scripts": {
12− "typecheck": "bunx tsc --noEmit -p tsconfig.json"
13− },
14− "dependencies": {
15− "@modelcontextprotocol/sdk": "^1.26.0",
16− "effect": "catalog:"
17− },
18− "devDependencies": {
19− "@types/node": "catalog:",
20− "bun-types": "catalog:"
21− },
22− "version": "0.0.0"
23−}
packages/auth/mcp-oauth/tsconfig.json+0−19
@@ -1,19 +0,0 @@
1−{
2− "compilerOptions": {
3− "target": "ES2022",
4− "module": "ESNext",
5− "moduleResolution": "Bundler",
6− "strict": true,
7− "skipLibCheck": true,
8− "noEmit": true,
9− "lib": ["ES2022"],
10− "types": ["bun-types", "node"]
11− },
12− "include": [
13− "src/**/*.ts",
14− "src/**/*.d.ts"
15− ],
16− "exclude": [
17− "src/**/*.test.ts"
18− ]
19−}
packages/clients/react/src/plugins/components/badge.tsxrenamed from packages/clients/react/src/source-plugins/components/badge.tsx+0−0

File renamed without changes.

packages/clients/react/src/plugins/components/code-block.tsxrenamed from packages/clients/react/src/source-plugins/components/code-block.tsx+0−0

File renamed without changes.

packages/clients/react/src/plugins/components/document-panel.tsxrenamed from packages/clients/react/src/source-plugins/components/document-panel.tsx+0−0

File renamed without changes.

packages/clients/react/src/plugins/components/icons.tsxrenamed from packages/clients/react/src/source-plugins/components/icons.tsx+0−0

File renamed without changes.

packages/clients/react/src/plugins/components/loadable.tsxrenamed from packages/clients/react/src/source-plugins/components/loadable.tsx+0−0

File renamed without changes.

packages/clients/react/src/plugins/components/markdown.tsxrenamed from packages/clients/react/src/source-plugins/components/markdown.tsx+0−0

File renamed without changes.

packages/clients/react/src/plugins/components/source-tool-explorer.tsxrenamed from packages/clients/react/src/source-plugins/components/source-tool-explorer.tsx+0−0

File renamed without changes.

packages/clients/react/src/plugins/index.ts+104−1
@@ -1 +1,104 @@
1−export * from "../source-plugins/index";
1+export type {
2+ ExecutorFrontendPlugin,
3+ ExecutorPluginNavigation,
4+ ExecutorPluginRouteContextValue,
5+ FrontendPluginRouteDefinition,
6+ FrontendPluginRouteParams,
7+ FrontendPluginRouteSearch,
8+ FrontendSourceDetailRouteDefinition,
9+ FrontendSourceTypeDefinition,
10+ SourcePluginNavigation,
11+ SourcePluginRouteContextValue,
12+ SourcePluginRouteParams,
13+ SourcePluginRouteSearch,
14+} from "./types";
15+
16+export {
17+ createExecutorPluginPaths,
18+ createSourcePluginPaths,
19+ executorPluginBasePath,
20+ executorPluginRoutePath,
21+ executorPluginRoutePattern,
22+ normalizeExecutorPluginPath,
23+ normalizeSourcePluginPath,
24+ sourcePluginAddPath,
25+ sourcePluginChildPath,
26+ sourcePluginChildPattern,
27+ sourcePluginDetailPath,
28+ sourcePluginDetailPattern,
29+ sourcePluginEditPath,
30+ sourcePluginEditPattern,
31+ sourcePluginsIndexPath,
32+ type ExecutorPluginPaths,
33+ type SourcePluginPaths,
34+} from "./paths";
35+
36+export {
37+ defineExecutorFrontendPlugin,
38+ defineFrontendPluginRoute,
39+ defineFrontendSourceType,
40+ registerExecutorFrontendPlugins,
41+ type RegisteredFrontendPluginRoute,
42+ type RegisteredFrontendSourceType,
43+} from "./registry";
44+
45+export {
46+ ExecutorPluginRouteProvider,
47+ useExecutorPlugin,
48+ useExecutorPluginNavigation,
49+ useExecutorPluginPaths,
50+ useExecutorPluginRoute,
51+ useExecutorPluginRouteDefinition,
52+ useExecutorPluginRouteParams,
53+ useExecutorPluginSearch,
54+} from "./plugin-route-context";
55+
56+export {
57+ SourcePluginRouteProvider,
58+ useSourcePlugin,
59+ useSourcePluginDefinition,
60+ useSourcePluginNavigation,
61+ useSourcePluginPaths,
62+ useSourcePluginRoute,
63+ useSourcePluginRouteParams,
64+ useSourcePluginSearch,
65+} from "./route-context";
66+
67+export {
68+ cn,
69+} from "./lib/cn";
70+
71+export {
72+ Badge,
73+ MethodBadge,
74+} from "./components/badge";
75+export {
76+ CodeBlock,
77+} from "./components/code-block";
78+export {
79+ DocumentPanel,
80+} from "./components/document-panel";
81+export {
82+ IconCheck,
83+ IconChevron,
84+ IconClose,
85+ IconCopy,
86+ IconEmpty,
87+ IconFolder,
88+ IconPencil,
89+ IconSearch,
90+ IconSpinner,
91+ IconTool,
92+} from "./components/icons";
93+export {
94+ EmptyState,
95+ LoadableBlock,
96+} from "./components/loadable";
97+export {
98+ Markdown,
99+} from "./components/markdown";
100+export {
101+ SourceToolExplorer,
102+ type SourceToolExplorerSearch,
103+ parseSourceToolExplorerSearch,
104+} from "./components/source-tool-explorer";
packages/clients/react/src/plugins/lib/cn.tsrenamed from packages/clients/react/src/source-plugins/lib/cn.ts+0−0

File renamed without changes.

packages/clients/react/src/plugins/lib/shiki.tsrenamed from packages/clients/react/src/source-plugins/lib/shiki.ts+0−0

File renamed without changes.

packages/clients/react/src/plugins/paths.tsrenamed from packages/clients/react/src/source-plugins/paths.ts+0−0

File renamed without changes.

packages/clients/react/src/plugins/plugin-route-context.tsxrenamed from packages/clients/react/src/source-plugins/plugin-route-context.tsx+0−0

File renamed without changes.

packages/clients/react/src/plugins/registry.tsrenamed from packages/clients/react/src/source-plugins/registry.ts+0−0

File renamed without changes.

packages/clients/react/src/plugins/route-context.tsxrenamed from packages/clients/react/src/source-plugins/route-context.tsx+0−0

File renamed without changes.

packages/clients/react/src/plugins/types.tsrenamed from packages/clients/react/src/source-plugins/types.ts+1−0
@@ -59,6 +59,7 @@ export type FrontendSourceTypeDefinition = { · 58 unmodified lines
5959 kind: string;
6060 displayName: string;
6161 description?: string;
62+ getIconUrl?: (source: Source) => string | null;
6263 renderAddPage: ComponentType;
6364 renderEditPage?: ComponentType<{ source: Source }>;
6465 renderDetailPage?: ComponentType<{ source: Source }>;
packages/clients/react/src/source-plugins/index.ts+1−104
@@ -1,104 +1 @@
1−export type {
2− ExecutorFrontendPlugin,
3− ExecutorPluginNavigation,
4− ExecutorPluginRouteContextValue,
5− FrontendPluginRouteDefinition,
6− FrontendPluginRouteParams,
7− FrontendPluginRouteSearch,
8− FrontendSourceDetailRouteDefinition,
9− FrontendSourceTypeDefinition,
10− SourcePluginNavigation,
11− SourcePluginRouteContextValue,
12− SourcePluginRouteParams,
13− SourcePluginRouteSearch,
14−} from "./types";
15−
16−export {
17− createExecutorPluginPaths,
18− createSourcePluginPaths,
19− executorPluginBasePath,
20− executorPluginRoutePath,
21− executorPluginRoutePattern,
22− normalizeExecutorPluginPath,
23− normalizeSourcePluginPath,
24− sourcePluginAddPath,
25− sourcePluginChildPath,
26− sourcePluginChildPattern,
27− sourcePluginDetailPath,
28− sourcePluginDetailPattern,
29− sourcePluginEditPath,
30− sourcePluginEditPattern,
31− sourcePluginsIndexPath,
32− type ExecutorPluginPaths,
33− type SourcePluginPaths,
34−} from "./paths";
35−
36−export {
37− defineExecutorFrontendPlugin,
38− defineFrontendPluginRoute,
39− defineFrontendSourceType,
40− registerExecutorFrontendPlugins,
41− type RegisteredFrontendPluginRoute,
42− type RegisteredFrontendSourceType,
43−} from "./registry";
44−
45−export {
46− ExecutorPluginRouteProvider,
47− useExecutorPlugin,
48− useExecutorPluginNavigation,
49− useExecutorPluginPaths,
50− useExecutorPluginRoute,
51− useExecutorPluginRouteDefinition,
52− useExecutorPluginRouteParams,
53− useExecutorPluginSearch,
54−} from "./plugin-route-context";
55−
56−export {
57− SourcePluginRouteProvider,
58− useSourcePlugin,
59− useSourcePluginDefinition,
60− useSourcePluginNavigation,
61− useSourcePluginPaths,
62− useSourcePluginRoute,
63− useSourcePluginRouteParams,
64− useSourcePluginSearch,
65−} from "./route-context";
66−
67−export {
68− cn,
69−} from "./lib/cn";
70−
71−export {
72− Badge,
73− MethodBadge,
74−} from "./components/badge";
75−export {
76− CodeBlock,
77−} from "./components/code-block";
78−export {
79− DocumentPanel,
80−} from "./components/document-panel";
81−export {
82− IconCheck,
83− IconChevron,
84− IconClose,
85− IconCopy,
86− IconEmpty,
87− IconFolder,
88− IconPencil,
89− IconSearch,
90− IconSpinner,
91− IconTool,
92−} from "./components/icons";
93−export {
94− EmptyState,
95− LoadableBlock,
96−} from "./components/loadable";
97−export {
98− Markdown,
99−} from "./components/markdown";
100−export {
101− SourceToolExplorer,
102− type SourceToolExplorerSearch,
103− parseSourceToolExplorerSearch,
104−} from "./components/source-tool-explorer";
1+export * from "../plugins/index";
plugins/google-discovery/http/index.ts+23−12
@@ -25,6 +25,9 @@ import * as Effect from "effect/Effect"; · 24 unmodified lines
2525 import * as Schema from "effect/Schema";
2626
2727 import {
28+ GOOGLE_DISCOVERY_EXECUTOR_KEY,
29+ GOOGLE_DISCOVERY_OAUTH_STORAGE_PREFIX,
30+ GOOGLE_DISCOVERY_PLUGIN_KEY,
2831 GoogleDiscoveryConnectInputSchema,
2932 GoogleDiscoveryOAuthPopupResultSchema,
3033 GoogleDiscoverySourceConfigPayloadSchema,
@@ -39,7 +42,7 @@ import { · 8 unmodified lines
3942 } from "@executor/plugin-google-discovery-shared";
4043
4144 type GoogleDiscoveryExecutorExtension = {
42− googleDiscovery: {
45+ [GOOGLE_DISCOVERY_EXECUTOR_KEY]: {
4346 createSource: (
4447 input: GoogleDiscoveryConnectInput,
4548 ) => Effect.Effect<Source, Error>;
@@ -77,7 +80,7 @@ const callbackParamsSchema = Schema.Struct({ · 31 unmodified lines
7780 error_description: Schema.optional(Schema.String),
7881 });
7982
80−export const GoogleDiscoveryHttpGroup = HttpApiGroup.make("googleDiscovery")
83+export const GoogleDiscoveryHttpGroup = HttpApiGroup.make(GOOGLE_DISCOVERY_PLUGIN_KEY)
8184 .add(
8285 HttpApiEndpoint.post("createSource")`/workspaces/${workspaceIdParam}/plugins/google-discovery/sources`
8386 .setPayload(GoogleDiscoveryConnectInputSchema)
@@ -129,7 +132,7 @@ export const GoogleDiscoveryHttpGroup = HttpApiGroup.make("googleDiscovery") · 45 unmodified lines
129132 .prefix("/v1");
130133
131134 export const googleDiscoveryHttpApiExtension = {
132− key: "googleDiscovery",
135+ key: GOOGLE_DISCOVERY_PLUGIN_KEY,
133136 group: GoogleDiscoveryHttpGroup,
134137 } satisfies ExecutorHttpApiExtension<typeof GoogleDiscoveryHttpGroup>;
135138
@@ -199,7 +202,7 @@ const popupDocument = (payload: GoogleDiscoveryOAuthPopupResult): string => { · 63 unmodified lines
199202 (() => {
200203 const payload = ${serialized};
201204 try {
202− window.localStorage.setItem("executor:google-discovery-oauth:" + (payload.ok ? payload.sessionId : "failed"), JSON.stringify(payload));
205+ window.localStorage.setItem("${GOOGLE_DISCOVERY_OAUTH_STORAGE_PREFIX}" + (payload.ok ? payload.sessionId : "failed"), JSON.stringify(payload));
203206 } catch {}
204207 try {
205208 if (window.opener) {
@@ -218,17 +221,19 @@ export const googleDiscoveryHttpPlugin = (): ExecutorHttpPlugin< · 12 unmodified lines
218221 typeof GoogleDiscoveryHttpGroup,
219222 GoogleDiscoveryExecutorExtension
220223 > => ({
221− key: "googleDiscovery",
224+ key: GOOGLE_DISCOVERY_PLUGIN_KEY,
222225 group: GoogleDiscoveryHttpGroup,
223226 build: ({ executor }) =>
224− HttpApiBuilder.group(GoogleDiscoveryHttpApi, "googleDiscovery", (handlers) =>
227+ HttpApiBuilder.group(GoogleDiscoveryHttpApi, GOOGLE_DISCOVERY_PLUGIN_KEY, (handlers) =>
225228 handlers
226229 .handle("createSource", ({ path, payload }) =>
227230 resolveRequestedLocalWorkspace(
228231 "googleDiscovery.createSource",
229232 path.workspaceId,
230233 ).pipe(
231− Effect.flatMap(() => executor.googleDiscovery.createSource(payload)),
234+ Effect.flatMap(() =>
235+ executor[GOOGLE_DISCOVERY_EXECUTOR_KEY].createSource(payload)
236+ ),
232237 Effect.mapError((cause) =>
233238 toStorageError("googleDiscovery.createSource", cause)
234239 ),
@@ -240,7 +245,9 @@ export const googleDiscoveryHttpPlugin = (): ExecutorHttpPlugin< · 5 unmodified lines
240245 path.workspaceId,
241246 ).pipe(
242247 Effect.flatMap(() =>
243− executor.googleDiscovery.getSourceConfig(path.sourceId)
248+ executor[GOOGLE_DISCOVERY_EXECUTOR_KEY].getSourceConfig(
249+ path.sourceId,
250+ )
244251 ),
245252 Effect.mapError((cause) =>
246253 mapPluginStorageError("googleDiscovery.getSourceConfig", cause)
@@ -253,7 +260,7 @@ export const googleDiscoveryHttpPlugin = (): ExecutorHttpPlugin< · 6 unmodified lines
253260 path.workspaceId,
254261 ).pipe(
255262 Effect.flatMap(() =>
256− executor.googleDiscovery.updateSource({
263+ executor[GOOGLE_DISCOVERY_EXECUTOR_KEY].updateSource({
257264 sourceId: path.sourceId,
258265 config: payload,
259266 })
@@ -269,7 +276,9 @@ export const googleDiscoveryHttpPlugin = (): ExecutorHttpPlugin< · 9 unmodified lines
269276 path.workspaceId,
270277 ).pipe(
271278 Effect.flatMap(() =>
272− executor.googleDiscovery.removeSource(path.sourceId)
279+ executor[GOOGLE_DISCOVERY_EXECUTOR_KEY].removeSource(
280+ path.sourceId,
281+ )
273282 ),
274283 Effect.map((removed) => ({ removed })),
275284 Effect.mapError((cause) =>
@@ -282,14 +291,16 @@ export const googleDiscoveryHttpPlugin = (): ExecutorHttpPlugin< · 6 unmodified lines
282291 "googleDiscovery.startOAuth",
283292 path.workspaceId,
284293 ).pipe(
285− Effect.flatMap(() => executor.googleDiscovery.startOAuth(payload)),
294+ Effect.flatMap(() =>
295+ executor[GOOGLE_DISCOVERY_EXECUTOR_KEY].startOAuth(payload)
296+ ),
286297 Effect.mapError((cause) =>
287298 toStorageError("googleDiscovery.startOAuth", cause)
288299 ),
289300 )
290301 )
291302 .handle("oauthCallback", ({ urlParams }) =>
292− executor.googleDiscovery.completeOAuth({
303+ executor[GOOGLE_DISCOVERY_EXECUTOR_KEY].completeOAuth({
293304 state: urlParams.state,
294305 code: urlParams.code,
295306 error: urlParams.error,
plugins/google-discovery/react/index.tsx+55−12
@@ -24,6 +24,10 @@ import { · 23 unmodified lines
2424 googleDiscoveryHttpApiExtension,
2525 } from "@executor/plugin-google-discovery-http";
2626 import {
27+ GOOGLE_DISCOVERY_OAUTH_CALLBACK_PATH,
28+ GOOGLE_DISCOVERY_OAUTH_STORAGE_PREFIX,
29+ GOOGLE_DISCOVERY_PLUGIN_KEY,
30+ GOOGLE_DISCOVERY_SOURCE_KIND,
2731 defaultGoogleDiscoveryUrl,
2832 type GoogleDiscoveryConnectInput,
2933 type GoogleDiscoveryConnectionAuth,
@@ -31,9 +35,47 @@ import { · 1 unmodified line
3135 type GoogleDiscoveryStartOAuthInput,
3236 } from "@executor/plugin-google-discovery-shared";
3337
34−const OAUTH_STORAGE_PREFIX = "executor:google-discovery-oauth:";
3538 const OAUTH_TIMEOUT_MS = 2 * 60_000;
3639
40+const GOOGLE_DISCOVERY_SERVICE_ICONS: Record<string, string> = {
41+ admin: "https://ssl.gstatic.com/images/branding/product/2x/admin_2020q4_48dp.png",
42+ bigquery: "https://ssl.gstatic.com/bqui1/favicon.ico",
43+ calendar: "https://ssl.gstatic.com/calendar/images/dynamiclogo_2020q4/calendar_31_2x.png",
44+ chat: "https://ssl.gstatic.com/chat/favicon/favicon_v2.ico",
45+ classroom: "https://ssl.gstatic.com/classroom/favicon.png",
46+ cloudresourcemanager: "https://www.gstatic.com/devrel-devsite/prod/v0e0f589edd85502a40d78d7d0825db8ea5ef3b99b1571571945f0f3f764ff61b/cloud/images/favicons/onecloud/favicon.ico",
47+ docs: "https://ssl.gstatic.com/docs/documents/images/kix-favicon7.ico",
48+ drive: "https://ssl.gstatic.com/images/branding/product/2x/drive_2020q4_48dp.png",
49+ forms: "https://ssl.gstatic.com/docs/forms/device_home/android_192.png",
50+ gmail: "https://ssl.gstatic.com/ui/v1/icons/mail/rfr/gmail.ico",
51+ keep: "https://ssl.gstatic.com/keep/icon_2020q4v2_128.png",
52+ people: "https://ssl.gstatic.com/images/branding/product/2x/contacts_2022_48dp.png",
53+ script: "https://ssl.gstatic.com/script/images/favicon.ico",
54+ searchconsole: "https://ssl.gstatic.com/search-console/scfe/search_console-64.png",
55+ sheets: "https://ssl.gstatic.com/docs/spreadsheets/favicon3.ico",
56+ slides: "https://ssl.gstatic.com/docs/presentations/images/favicon5.ico",
57+ tasks: "https://ssl.gstatic.com/tasks/images/favicon.ico",
58+ youtube: "https://www.youtube.com/s/desktop/a94e1818/img/favicon_32x32.png",
59+};
60+
61+const getGoogleDiscoveryServiceKey = (
62+ source: Pick<Source, "namespace">,
63+): string | null => {
64+ const namespace = source.namespace?.trim();
65+ if (!namespace || !namespace.startsWith("google.")) {
66+ return null;
67+ }
68+
69+ return namespace.slice("google.".length).replaceAll(".", "");
70+};
71+
72+const getGoogleDiscoveryIconUrl = (
73+ source: Pick<Source, "namespace">,
74+): string | null => {
75+ const serviceKey = getGoogleDiscoveryServiceKey(source);
76+ return serviceKey ? GOOGLE_DISCOVERY_SERVICE_ICONS[serviceKey] ?? null : null;
77+};
78+
3779 const getGoogleDiscoveryHttpClient =
3880 defineExecutorPluginHttpApiClient<"GoogleDiscoveryReactHttpClient">()(
3981 "GoogleDiscoveryReactHttpClient",
@@ -105,7 +147,7 @@ const waitForOauthPopupResult = async ( · 65 unmodified lines
105147 sessionId: string,
106148 ): Promise<GoogleDiscoveryOAuthPopupResult> =>
107149 new Promise((resolve, reject) => {
108− const storageKey = `${OAUTH_STORAGE_PREFIX}${sessionId}`;
150+ const storageKey = `${GOOGLE_DISCOVERY_OAUTH_STORAGE_PREFIX}${sessionId}`;
109151 const startedAt = Date.now();
110152
111153 const cleanup = () => {
@@ -168,7 +210,7 @@ function GoogleDiscoverySourceForm(props: { · 56 unmodified lines
168210 const client = getGoogleDiscoveryHttpClient();
169211 const secrets = useSecrets();
170212 const startOAuth = useAtomSet(
171− client.mutation("googleDiscovery", "startOAuth"),
213+ client.mutation(GOOGLE_DISCOVERY_PLUGIN_KEY, "startOAuth"),
172214 { mode: "promise" },
173215 );
174216 const submitMutation = useExecutorMutation<GoogleDiscoveryConnectInput, void>(props.onSubmit);
@@ -219,7 +261,7 @@ function GoogleDiscoverySourceForm(props: { · 44 unmodified lines
219261 : null,
220262 clientAuthentication: clientSecretRef ? "client_secret_post" : "none",
221263 redirectUrl: new URL(
222− "/v1/plugins/google-discovery/oauth/callback",
264+ GOOGLE_DISCOVERY_OAUTH_CALLBACK_PATH,
223265 window.location.origin,
224266 ).toString(),
225267 };
@@ -492,7 +534,7 @@ function GoogleDiscoveryAddPage() { · 266 unmodified lines
492534 const installation = useLocalInstallation();
493535 const client = getGoogleDiscoveryHttpClient();
494536 const createSource = useAtomSet(
495− client.mutation("googleDiscovery", "createSource"),
537+ client.mutation(GOOGLE_DISCOVERY_PLUGIN_KEY, "createSource"),
496538 { mode: "promise" },
497539 );
498540
@@ -533,7 +575,7 @@ function GoogleDiscoveryEditPage(props: { · 34 unmodified lines
533575 const client = getGoogleDiscoveryHttpClient();
534576 const configResult = useAtomValue(
535577 installation.status === "ready"
536− ? client.query("googleDiscovery", "getSourceConfig", {
578+ ? client.query(GOOGLE_DISCOVERY_PLUGIN_KEY, "getSourceConfig", {
537579 path: {
538580 workspaceId: installation.data.scopeId,
539581 sourceId: props.source.id,
@@ -548,7 +590,7 @@ function GoogleDiscoveryEditPage(props: { · 8 unmodified lines
548590 }) as never,
549591 );
550592 const updateSource = useAtomSet(
551− client.mutation("googleDiscovery", "updateSource"),
593+ client.mutation(GOOGLE_DISCOVERY_PLUGIN_KEY, "updateSource"),
552594 { mode: "promise" },
553595 );
554596
@@ -608,12 +650,12 @@ function GoogleDiscoveryDetailPage(props: { · 53 unmodified lines
608650 const installation = useLocalInstallation();
609651 const client = getGoogleDiscoveryHttpClient();
610652 const removeSource = useAtomSet(
611− client.mutation("googleDiscovery", "removeSource"),
653+ client.mutation(GOOGLE_DISCOVERY_PLUGIN_KEY, "removeSource"),
612654 { mode: "promise" },
613655 );
614656 const configResult = useAtomValue(
615657 installation.status === "ready"
616− ? client.query("googleDiscovery", "getSourceConfig", {
658+ ? client.query(GOOGLE_DISCOVERY_PLUGIN_KEY, "getSourceConfig", {
617659 path: {
618660 workspaceId: installation.data.scopeId,
619661 sourceId: props.source.id,
@@ -710,16 +752,17 @@ function GoogleDiscoveryDetailPage(props: { · 90 unmodified lines
710752 }
711753
712754 const googleDiscoverySourceType = defineFrontendSourceType({
713− key: "google-discovery",
714− kind: "google_discovery",
755+ key: GOOGLE_DISCOVERY_PLUGIN_KEY,
756+ kind: GOOGLE_DISCOVERY_SOURCE_KIND,
715757 displayName: "Google Discovery",
716758 description: "Import Google APIs from discovery documents with plugin-owned OAuth.",
759+ getIconUrl: getGoogleDiscoveryIconUrl,
717760 renderAddPage: GoogleDiscoveryAddPage,
718761 renderEditPage: GoogleDiscoveryEditPage,
719762 renderDetailPage: GoogleDiscoveryDetailPage,
720763 });
721764
722765 export const GoogleDiscoveryReactPlugin = defineExecutorFrontendPlugin({
723− key: "google-discovery",
766+ key: GOOGLE_DISCOVERY_PLUGIN_KEY,
724767 sourceTypes: [googleDiscoverySourceType],
725768 });
plugins/google-discovery/sdk/catalog.ts+3−2
@@ -38,6 +38,7 @@ import { · 37 unmodified lines
3838 stableHash,
3939 toolPathSegments,
4040 } from "@executor/source-core";
41+import { GOOGLE_DISCOVERY_SOURCE_KIND } from "@executor/plugin-google-discovery-shared";
4142
4243 import type { GoogleDiscoveryToolProviderData } from "./types";
4344
@@ -284,7 +285,7 @@ const createHttpCapabilityFromGoogleDiscovery = (input: { · 240 unmodified lines
284285 id: executableId,
285286 capabilityId,
286287 scopeId: input.serviceScopeId,
287− pluginKey: "google_discovery",
288+ pluginKey: GOOGLE_DISCOVERY_SOURCE_KIND,
288289 bindingVersion: EXECUTABLE_BINDING_VERSION,
289290 binding: input.operation.providerData,
290291 projection: {
@@ -384,7 +385,7 @@ export const createGoogleDiscoveryCatalogSnapshot = (input: { · 93 unmodified lines
384385 createCatalogSnapshotV1FromFragments({
385386 import: createCatalogImportMetadata({
386387 source: input.source,
387− pluginKey: "google_discovery",
388+ pluginKey: GOOGLE_DISCOVERY_SOURCE_KIND,
388389 }),
389390 fragments: [createGoogleDiscoveryCatalogFragment(input)],
390391 });
plugins/google-discovery/sdk/index.ts+15−13
@@ -20,6 +20,8 @@ import { · 19 unmodified lines
2020 provideExecutorRuntime,
2121 } from "@executor/platform-sdk/runtime";
2222 import {
23+ GOOGLE_DISCOVERY_EXECUTOR_KEY,
24+ GOOGLE_DISCOVERY_SOURCE_KIND,
2325 GoogleDiscoveryConnectionAuthSchema,
2426 GoogleDiscoveryOAuthSessionSchema,
2527 defaultGoogleDiscoveryUrl,
@@ -115,7 +117,7 @@ export type GoogleDiscoverySdk = { · 89 unmodified lines
115117 };
116118
117119 const GoogleDiscoveryExecutorAddInputSchema = Schema.Struct({
118− kind: Schema.Literal("google_discovery"),
120+ kind: Schema.Literal(GOOGLE_DISCOVERY_SOURCE_KIND),
119121 name: Schema.String,
120122 service: Schema.String,
121123 version: Schema.String,
@@ -476,7 +478,7 @@ const createGoogleDiscoverySourceSdk = ( · 354 unmodified lines
476478 getSourceConfig: (sourceId: Source["id"]) =>
477479 Effect.gen(function* () {
478480 const source = yield* host.sources.get(sourceId);
479− if (source.kind !== "google_discovery") {
481+ if (source.kind !== GOOGLE_DISCOVERY_SOURCE_KIND) {
480482 return yield* Effect.fail(
481483 new Error(`Source ${sourceId} is not a Google Discovery source.`),
482484 );
@@ -500,7 +502,7 @@ const createGoogleDiscoverySourceSdk = ( · 17 unmodified lines
500502 const createdSource = yield* host.sources.create({
501503 source: {
502504 name: input.name.trim(),
503− kind: "google_discovery",
505+ kind: GOOGLE_DISCOVERY_SOURCE_KIND,
504506 status: "connected",
505507 enabled: true,
506508 namespace: deriveGoogleDiscoveryNamespace(input.service),
@@ -518,7 +520,7 @@ const createGoogleDiscoverySourceSdk = ( · 11 unmodified lines
518520 updateSource: (input: GoogleDiscoveryUpdateSourceInput) =>
519521 Effect.gen(function* () {
520522 const source = yield* host.sources.get(input.sourceId as Source["id"]);
521− if (source.kind !== "google_discovery") {
523+ if (source.kind !== GOOGLE_DISCOVERY_SOURCE_KIND) {
522524 return yield* Effect.fail(
523525 new Error(`Source ${input.sourceId} is not a Google Discovery source.`),
524526 );
@@ -542,7 +544,7 @@ const createGoogleDiscoverySourceSdk = ( · 17 unmodified lines
542544 removeSource: (sourceId: Source["id"]) =>
543545 Effect.gen(function* () {
544546 const source = yield* host.sources.get(sourceId);
545− if (source.kind !== "google_discovery") {
547+ if (source.kind !== GOOGLE_DISCOVERY_SOURCE_KIND) {
546548 return yield* Effect.fail(
547549 new Error(`Source ${sourceId} is not a Google Discovery source.`),
548550 );
@@ -577,7 +579,7 @@ const googleDiscoverySourceConnector = ( · 28 unmodified lines
577579 oauthSessions: GoogleDiscoveryOAuthSessionStorage;
578580 },
579581 ): ExecutorSourceConnector<GoogleDiscoveryExecutorAddInput> => ({
580− kind: "google_discovery",
582+ kind: GOOGLE_DISCOVERY_SOURCE_KIND,
581583 displayName: "Google Discovery",
582584 inputSchema: GoogleDiscoveryExecutorAddInputSchema,
583585 inputSignatureWidth: 320,
@@ -592,11 +594,11 @@ const googleDiscoverySourceConnector = ( · 8 unmodified lines
592594 const createGoogleDiscoverySourceRuntime = (options: {
593595 storage: GoogleDiscoverySourceStorage;
594596 }): SourcePluginRuntime => ({
595− kind: "google_discovery",
597+ kind: GOOGLE_DISCOVERY_SOURCE_KIND,
596598 displayName: "Google Discovery",
597599 catalogKind: "imported",
598600 catalogIdentity: ({ source }) => ({
599− kind: "google_discovery",
601+ kind: GOOGLE_DISCOVERY_SOURCE_KIND,
600602 sourceId: source.id,
601603 }),
602604 getIrModel: ({ source }) =>
@@ -613,7 +615,7 @@ const createGoogleDiscoverySourceRuntime = (options: { · 10 unmodified lines
613615 importMetadata: {
614616 ...createCatalogImportMetadata({
615617 source,
616− pluginKey: "google_discovery",
618+ pluginKey: GOOGLE_DISCOVERY_SOURCE_KIND,
617619 }),
618620 importerVersion: "ir.v1.google_discovery",
619621 sourceConfigHash: "missing",
@@ -647,7 +649,7 @@ const createGoogleDiscoverySourceRuntime = (options: { · 27 unmodified lines
647649 source,
648650 documents: [
649651 {
650− documentKind: "google_discovery",
652+ documentKind: GOOGLE_DISCOVERY_SOURCE_KIND,
651653 documentKey: stored.discoveryUrl,
652654 contentText: document,
653655 fetchedAt: now,
@@ -658,7 +660,7 @@ const createGoogleDiscoverySourceRuntime = (options: { · 4 unmodified lines
658660 importMetadata: {
659661 ...createCatalogImportMetadata({
660662 source,
661− pluginKey: "google_discovery",
663+ pluginKey: GOOGLE_DISCOVERY_SOURCE_KIND,
662664 }),
663665 importerVersion: "ir.v1.google_discovery",
664666 },
@@ -753,8 +755,8 @@ const createGoogleDiscoverySourceRuntime = (options: { · 88 unmodified lines
753755 export const googleDiscoverySdkPlugin = (options: {
754756 storage: GoogleDiscoverySourceStorage;
755757 oauthSessions: GoogleDiscoveryOAuthSessionStorage;
756−}): ExecutorSdkPlugin<"googleDiscovery", GoogleDiscoverySdk> => ({
757− key: "googleDiscovery",
758+}): ExecutorSdkPlugin<typeof GOOGLE_DISCOVERY_EXECUTOR_KEY, GoogleDiscoverySdk> => ({
759+ key: GOOGLE_DISCOVERY_EXECUTOR_KEY,
758760 sources: [createGoogleDiscoverySourceRuntime(options)],
759761 sourceConnectors: [googleDiscoverySourceConnector(options)],
760762 extendExecutor: ({ host, executor }) => {
plugins/google-discovery/sdk/tools.ts+3−2
@@ -18,6 +18,7 @@ import { sourceCoreEffectError } from "@executor/source-core"; · 17 unmodified lines
1818 import * as Effect from "effect/Effect";
1919 import * as Layer from "effect/Layer";
2020 import * as Schema from "effect/Schema";
21+import { GOOGLE_DISCOVERY_SOURCE_KIND } from "@executor/plugin-google-discovery-shared";
2122
2223 import type {
2324 GoogleDiscoveryManifestMethod,
@@ -43,7 +44,7 @@ export const googleDiscoveryProviderDataFromDefinition = ( · 19 unmodified lines
4344 definition: GoogleDiscoveryManifestMethod;
4445 },
4546 ): typeof GoogleDiscoveryToolProviderDataSchema.Type => ({
46− kind: "google_discovery",
47+ kind: GOOGLE_DISCOVERY_SOURCE_KIND,
4748 service: input.service,
4849 version: input.version,
4950 toolId: input.definition.toolId,
@@ -467,7 +468,7 @@ export const createGoogleDiscoveryToolFromDefinition = ( · 417 unmodified lines
467468 : {}),
468469 },
469470 sourceKey: input.sourceKey,
470− pluginKind: "google_discovery",
471+ pluginKind: GOOGLE_DISCOVERY_SOURCE_KIND,
471472 pluginData: providerData,
472473 };
473474
plugins/google-discovery/sdk/types.ts+2−1
@@ -1,4 +1,5 @@
11 import { Schema } from "effect";
2+import { GOOGLE_DISCOVERY_SOURCE_KIND } from "@executor/plugin-google-discovery-shared";
23
34 export const GOOGLE_DISCOVERY_HTTP_METHODS = [
45 "get",
@@ -52,7 +53,7 @@ export const GoogleDiscoveryInvocationPayloadSchema = Schema.Struct({ · 47 unmodified lines
5253 });
5354
5455 export const GoogleDiscoveryToolProviderDataSchema = Schema.Struct({
55− kind: Schema.Literal("google_discovery"),
56+ kind: Schema.Literal(GOOGLE_DISCOVERY_SOURCE_KIND),
5657 service: Schema.String,
5758 version: Schema.String,
5859 toolId: Schema.String,
plugins/google-discovery/shared/index.ts+8−0
@@ -5,6 +5,14 @@ import { · 4 unmodified lines
55 StringMapSchema,
66 } from "@executor/platform-sdk/schema";
77
8+export const GOOGLE_DISCOVERY_SOURCE_KIND = "google_discovery" as const;
9+export const GOOGLE_DISCOVERY_PLUGIN_KEY = "google-discovery" as const;
10+export const GOOGLE_DISCOVERY_EXECUTOR_KEY = "googleDiscovery" as const;
11+export const GOOGLE_DISCOVERY_OAUTH_STORAGE_PREFIX =
12+ "executor:google-discovery-oauth:" as const;
13+export const GOOGLE_DISCOVERY_OAUTH_CALLBACK_PATH =
14+ `/v1/plugins/${GOOGLE_DISCOVERY_PLUGIN_KEY}/oauth/callback` as const;
15+
816 export const GoogleDiscoveryOAuthClientAuthenticationSchema = Schema.Literal(
917 "none",
1018 "client_secret_post",
plugins/mcp/sdk/discovery.ts+1−1
@@ -6,11 +6,11 @@ import { · 5 unmodified lines
66 type SourceDiscoveryProbeInput,
77 type SourceDiscoveryResult,
88 } from "@executor/source-core";
9−import { startMcpOAuthAuthorization } from "@executor/auth-mcp-oauth";
109 import * as Either from "effect/Either";
1110 import * as Effect from "effect/Effect";
1211
1312 import { createSdkMcpConnector } from "./connection";
13+import { startMcpOAuthAuthorization } from "./oauth";
1414 import { discoverMcpToolsFromConnector } from "./tools";
1515
1616 export const detectMcpSource = (
plugins/mcp/sdk/index.ts+1−1
@@ -14,7 +14,7 @@ import type { · 13 unmodified lines
1414 import {
1515 exchangeMcpOAuthAuthorizationCode,
1616 startMcpOAuthAuthorization,
17−} from "@executor/auth-mcp-oauth";
17+} from "./oauth";
1818 import {
1919 contentHash,
2020 createCatalogImportMetadata,
plugins/mcp/sdk/oauth-effect-errors.tsrenamed from packages/auth/mcp-oauth/src/effect-errors.ts+0−0

File renamed without changes.

plugins/mcp/sdk/oauth.tsrenamed from packages/auth/mcp-oauth/src/index.ts+4−3
@@ -8,7 +8,8 @@ import type { · 7 unmodified lines
88 OAuthTokens,
99 } from "@modelcontextprotocol/sdk/shared/auth.js";
1010 import * as Effect from "effect/Effect";
11−import { mcpOAuthEffectError } from "./effect-errors";
11+
12+import { mcpOAuthEffectError } from "./oauth-effect-errors";
1213
1314 type JsonValue =
1415 | string
@@ -123,7 +124,7 @@ export const startMcpOAuthAuthorization = (input: { · 108 unmodified lines
123124 });
124125
125126 if (result !== "REDIRECT" || !captured.authorizationUrl || !captured.codeVerifier) {
126− return yield* mcpOAuthEffectError("index", "OAuth flow did not produce an authorization redirect");
127+ return yield* mcpOAuthEffectError("oauth", "OAuth flow did not produce an authorization redirect");
127128 }
128129
129130 return {
@@ -196,7 +197,7 @@ export const exchangeMcpOAuthAuthorizationCode = (input: { · 66 unmodified lines
196197 });
197198
198199 if (result !== "AUTHORIZED" || !captured.tokens) {
199− return yield* mcpOAuthEffectError("index", "OAuth redirect did not complete MCP OAuth setup");
200+ return yield* mcpOAuthEffectError("oauth", "OAuth redirect did not complete MCP OAuth setup");
200201 }
201202
202203 return {
plugins/mcp/sdk/package.json+0−1
@@ -12,7 +12,6 @@ · 11 unmodified lines
1212 "typecheck": "bunx tsc --noEmit -p tsconfig.json"
1313 },
1414 "dependencies": {
15− "@executor/auth-mcp-oauth": "workspace:*",
1615 "@executor/codemode-core": "workspace:*",
1716 "@executor/ir": "workspace:*",
1817 "@executor/platform-sdk": "workspace:*",