History

merge @executor/ui + @executor/react into packages/react (#88)

- Merge UI components, hooks, lib, styles from packages/ui - Merge API client, atoms, provider from packages/clients/react - Move shared pages and components from apps/local/src/web - Direct subpath exports: @executor/react/{api,plugins,pages,components,hooks,lib}/* - No barrel files, no backwards compat shims - Each app owns its own shell/router, imports pages from package - Delete packages/ui and packages/clients/react

Rhys Sullivan committed 7 months ago

Commit 4153df42 parents c3f0b23 7cb48ec133 files · +877 −498Browse files

Unified · Split

133 files
  1. .changeset/config.json +1 −3
  2. apps/cloud/package.json +0 −1
  3. apps/cloud/src/api.ts +25 −4
  4. apps/cloud/src/auth/api.ts +25 −0
  5. apps/cloud/src/auth/context.ts +8 −0
  6. apps/cloud/src/auth/handlers.ts +34 −0
  7. apps/cloud/src/auth/workos.ts +34 −31
  8. apps/cloud/src/web/auth.tsx +32 −26
  9. apps/cloud/src/web/client.tsx +22 −0
  10. apps/cloud/src/web/main.tsx +1 −1
  11. apps/cloud/src/web/router.tsx +7 −7
  12. apps/cloud/src/web/shell.tsx +483 −0
  13. apps/cloud/tsconfig.json +0 −3
  14. apps/cloud/vite.config.ts +0 −6
  15. apps/local/package.json +0 −1
  16. apps/local/src/web/lib/use-scope.ts +0 −1
  17. apps/local/src/web/main.tsx +1 −1
  18. apps/local/src/web/router.tsx +6 −6
  19. apps/local/src/web/shell.tsx +4 −10
  20. bun.lock +10 −40
  21. package.json +1 −1
  22. packages/clients/react/CHANGELOG.md +0 −4
  23. packages/clients/react/package.json +0 −27
  24. packages/clients/react/src/index.ts +0 −54
  25. packages/clients/react/src/use-scope.ts +0 −2
  26. packages/plugins/google-discovery/package.json +1 −6
  27. packages/plugins/google-discovery/src/react/AddGoogleDiscoverySource.tsx +10 −14
  28. packages/plugins/google-discovery/src/react/EditGoogleDiscoverySource.tsx +2 −2
  29. packages/plugins/google-discovery/src/react/GoogleDiscoverySourceSummary.tsx +1 −1
  30. packages/plugins/google-discovery/src/react/client.ts +1 −1
  31. packages/plugins/google-discovery/src/react/source-plugin.ts +1 −1
  32. packages/plugins/graphql/package.json +1 −6
  33. packages/plugins/graphql/src/react/AddGraphqlSource.tsx +7 −11
  34. packages/plugins/graphql/src/react/client.ts +1 −1
  35. packages/plugins/graphql/src/react/source-plugin.ts +1 −1
  36. packages/plugins/mcp/package.json +1 −6
  37. packages/plugins/mcp/src/react/AddMcpSource.tsx +6 −6
  38. packages/plugins/mcp/src/react/EditMcpSource.tsx +2 −2
  39. packages/plugins/mcp/src/react/McpSourceSummary.tsx +1 −1
  40. packages/plugins/mcp/src/react/client.ts +1 −1
  41. packages/plugins/mcp/src/react/source-plugin.ts +1 −1
  42. packages/plugins/onepassword/package.json +1 −5
  43. packages/plugins/onepassword/src/react/OnePasswordSettings.tsx +6 −6
  44. packages/plugins/onepassword/src/react/client.ts +1 −1
  45. packages/plugins/onepassword/src/react/secret-provider-plugin.ts +1 −1
  46. packages/plugins/openapi/package.json +1 −6
  47. packages/plugins/openapi/src/react/AddOpenApiSource.tsx +10 −15
  48. packages/plugins/openapi/src/react/client.ts +1 −1
  49. packages/plugins/openapi/src/react/source-plugin.ts +1 −1
  50. packages/react/package.json +11 −1
  51. packages/react/src/api/atoms.tsx +0 −0
  52. packages/react/src/api/base-url.tsx +0 −0
  53. packages/react/src/api/client.tsx +0 −0
  54. packages/react/src/api/provider.tsx +0 −0
  55. packages/react/src/api/scope-context.tsx +0 −0
  56. packages/react/src/components/accordion.tsx +1 −1
  57. packages/react/src/components/alert-dialog.tsx +2 −2
  58. packages/react/src/components/alert.tsx +1 −1
  59. packages/react/src/components/aspect-ratio.tsx +0 −0
  60. packages/react/src/components/avatar.tsx +1 −1
  61. packages/react/src/components/badge.tsx +1 −1
  62. packages/react/src/components/breadcrumb.tsx +1 −1
  63. packages/react/src/components/button-group.tsx +2 −2
  64. packages/react/src/components/button.tsx +1 −1
  65. packages/react/src/components/calendar.tsx +2 −2
  66. packages/react/src/components/card.tsx +1 −1
  67. packages/react/src/components/carousel.tsx +2 −2
  68. packages/react/src/components/chart.tsx +1 −1
  69. packages/react/src/components/checkbox.tsx +1 −1
  70. packages/react/src/components/code-block.tsx +0 −0
  71. packages/react/src/components/collapsible.tsx +0 −0
  72. packages/react/src/components/combobox.tsx +3 −3
  73. packages/react/src/components/command.tsx +2 −2
  74. packages/react/src/components/context-menu.tsx +1 −1
  75. packages/react/src/components/dialog.tsx +2 −2
  76. packages/react/src/components/direction.tsx +0 −0
  77. packages/react/src/components/drawer.tsx +1 −1
  78. packages/react/src/components/dropdown-menu.tsx +1 −1
  79. packages/react/src/components/empty.tsx +1 −1
  80. packages/react/src/components/field.tsx +3 −3
  81. packages/react/src/components/form.tsx +2 −2
  82. packages/react/src/components/hover-card.tsx +1 −1
  83. packages/react/src/components/input-group.tsx +4 −4
  84. packages/react/src/components/input-otp.tsx +1 −1
  85. packages/react/src/components/input.tsx +1 −1
  86. packages/react/src/components/item.tsx +2 −2
  87. packages/react/src/components/kbd.tsx +1 −1
  88. packages/react/src/components/label.tsx +1 −1
  89. packages/react/src/components/markdown.tsx +0 −0
  90. packages/react/src/components/mcp-install-card.tsx +0 −0
  91. packages/react/src/components/menubar.tsx +1 −1
  92. packages/react/src/components/native-select.tsx +1 −1
  93. packages/react/src/components/navigation-menu.tsx +1 −1
  94. packages/react/src/components/pagination.tsx +2 −2
  95. packages/react/src/components/popover.tsx +1 −1
  96. packages/react/src/components/progress.tsx +1 −1
  97. packages/react/src/components/radio-group.tsx +1 −1
  98. packages/react/src/components/resizable.tsx +1 −1
  99. packages/react/src/components/scroll-area.tsx +1 −1
  100. packages/react/src/components/select.tsx +1 −1
  101. packages/react/src/components/separator.tsx +1 −1
  102. packages/react/src/components/sheet.tsx +1 −1
  103. packages/react/src/components/sidebar.tsx +8 −8
  104. packages/react/src/components/skeleton.tsx +1 −1
  105. packages/react/src/components/slider.tsx +1 −1
  106. packages/react/src/components/sonner.tsx +0 −0
  107. packages/react/src/components/spinner.tsx +1 −1
  108. packages/react/src/components/switch.tsx +1 −1
  109. packages/react/src/components/table.tsx +1 −1
  110. packages/react/src/components/tabs.tsx +1 −1
  111. packages/react/src/components/textarea.tsx +1 −1
  112. packages/react/src/components/toggle-group.tsx +2 −2
  113. packages/react/src/components/toggle.tsx +1 −1
  114. packages/react/src/components/tool-detail.tsx +7 −5
  115. packages/react/src/components/tool-tree.tsx +0 −0
  116. packages/react/src/components/tooltip.tsx +1 −1
  117. packages/react/src/hooks/use-mobile.ts +0 −0
  118. packages/react/src/hooks/use-scope.ts +1 −0
  119. packages/react/src/lib/shiki.ts +0 −0
  120. packages/react/src/lib/utils.ts +0 −0
  121. packages/react/src/pages/secrets.tsx +11 −18
  122. packages/react/src/pages/source-detail.tsx +3 −12
  123. packages/react/src/pages/sources-add.tsx +4 −3
  124. packages/react/src/pages/sources.tsx +4 −3
  125. packages/react/src/pages/tools.tsx +3 −2
  126. packages/react/src/plugins/secret-picker.tsx +3 −3
  127. packages/react/src/plugins/secret-provider-plugin.tsx +0 −0
  128. packages/react/src/plugins/source-plugin.tsx +0 −0
  129. packages/react/src/styles/globals.css +0 −0
  130. packages/react/tsconfig.json +0 −0
  131. packages/ui/CHANGELOG.md +0 −4
  132. packages/ui/components.json +0 −20
  133. packages/ui/tsconfig.json +0 −25
.changeset/config.json+1−3
@@ -26,8 +26,6 @@ · 25 unmodified lines
26 "@executor/plugin-keychain",26 "@executor/plugin-keychain",
27 "@executor/plugin-mcp",27 "@executor/plugin-mcp",
28 "@executor/plugin-onepassword",28 "@executor/plugin-onepassword",
29 "@executor/plugin-openapi",29 "@executor/plugin-openapi"
30 "@executor/ui",
31 "@executor/marketing"
32 ]30 ]
33}31}
apps/cloud/package.json+0−1
@@ -15,7 +15,6 @@ · 14 unmodified lines
15 "@executor/react": "workspace:*",15 "@executor/react": "workspace:*",
16 "@executor/sdk": "workspace:*",16 "@executor/sdk": "workspace:*",
17 "@executor/storage-postgres": "workspace:*",17 "@executor/storage-postgres": "workspace:*",
18 "@executor/ui": "workspace:*",
19 "@tanstack/react-router": "^1.168.10",18 "@tanstack/react-router": "^1.168.10",
20 "@workos-inc/node": "^7.0.0",19 "@workos-inc/node": "^7.0.0",
21 "drizzle-orm": "catalog:",20 "drizzle-orm": "catalog:",
apps/cloud/src/api.ts+25−4
@@ -1,5 +1,5 @@
1// ---------------------------------------------------------------------------1// ---------------------------------------------------------------------------
2// Cloud API — core handlers from @executor/api + cloud-specific plugins2// Cloud API — core handlers from @executor/api + cloud-specific plugins + auth
3// ---------------------------------------------------------------------------3// ---------------------------------------------------------------------------
4 4
5import {5import {
@@ -20,16 +20,20 @@ import { GraphqlGroup, GraphqlExtensionService, GraphqlHandlers } from "@executo · 14 unmodified lines
20 20
21import { createTeamExecutor } from "./services/executor";21import { createTeamExecutor } from "./services/executor";
22import { authenticateRequest } from "./auth/workos";22import { authenticateRequest } from "./auth/workos";
23import { CloudAuthApi } from "./auth/api";
24import { CloudAuthHandlers } from "./auth/handlers";
25import { AuthContext, UserStoreService } from "./auth/context";
23import type { DrizzleDb } from "./services/db";26import type { DrizzleDb } from "./services/db";
24 27
25// ---------------------------------------------------------------------------28// ---------------------------------------------------------------------------
26// Cloud API — core + cloud plugins (no onepassword)29// Cloud API — core + cloud plugins + cloud auth (no onepassword)
27// ---------------------------------------------------------------------------30// ---------------------------------------------------------------------------
28 31
29const CloudApi = addGroup(OpenApiGroup)32const CloudApi = addGroup(OpenApiGroup)
30 .add(McpGroup)33 .add(McpGroup)
31 .add(GoogleDiscoveryGroup)34 .add(GoogleDiscoveryGroup)
32 .add(GraphqlGroup);35 .add(GraphqlGroup)
36 .add(CloudAuthApi);
33 37
34const CloudApiBase = HttpApiBuilder.api(CloudApi).pipe(38const CloudApiBase = HttpApiBuilder.api(CloudApi).pipe(
35 Layer.provide(CoreHandlers),39 Layer.provide(CoreHandlers),
@@ -38,6 +42,7 @@ const CloudApiBase = HttpApiBuilder.api(CloudApi).pipe( · 2 unmodified lines
38 McpHandlers,42 McpHandlers,
39 GoogleDiscoveryHandlers,43 GoogleDiscoveryHandlers,
40 GraphqlHandlers,44 GraphqlHandlers,
45 CloudAuthHandlers,
41 )),46 )),
42);47);
43 48
@@ -96,13 +101,29 @@ export const createCloudApiHandler = (db: DrizzleDb, encryptionKey: string) => { · 52 unmodified lines
96 Layer.provideMerge(pluginExtensions),101 Layer.provideMerge(pluginExtensions),
97 Layer.provideMerge(Layer.succeed(ExecutorService, executor)),102 Layer.provideMerge(Layer.succeed(ExecutorService, executor)),
98 Layer.provideMerge(Layer.succeed(ExecutionEngineService, engine)),103 Layer.provideMerge(Layer.succeed(ExecutionEngineService, engine)),
104 Layer.provideMerge(Layer.succeed(AuthContext, {
105 userId: auth.userId,
106 email: auth.email,
107 teamId,
108 name: `${auth.firstName ?? ""} ${auth.lastName ?? ""}`.trim() || null,
109 avatarUrl: auth.avatarUrl,
110 })),
111 Layer.provideMerge(Layer.succeed(UserStoreService, userStore)),
99 Layer.provideMerge(HttpServer.layerContext),112 Layer.provideMerge(HttpServer.layerContext),
100 ),113 ),
101 { middleware: HttpMiddleware.logger },114 { middleware: HttpMiddleware.logger },
102 );115 );
103 116
104 try {117 try {
105 return await handler.handler(request);118 const response = await handler.handler(request);
119
120 if (auth.refreshedCookie) {
121 const newResponse = new Response(response.body, response);
122 newResponse.headers.append("Set-Cookie", auth.refreshedCookie);
123 return newResponse;
124 }
125
126 return response;
106 } finally {127 } finally {
107 await Effect.runPromise(executor.close()).catch(() => undefined);128 await Effect.runPromise(executor.close()).catch(() => undefined);
108 handler.dispose();129 handler.dispose();
apps/cloud/src/auth/api.ts+25−0
@@ -0,0 +1,25 @@
1import { HttpApiEndpoint, HttpApiGroup } from "@effect/platform";
2import { Schema } from "effect";
3
4const AuthUser = Schema.Struct({
5 id: Schema.String,
6 email: Schema.String,
7 name: Schema.NullOr(Schema.String),
8 avatarUrl: Schema.NullOr(Schema.String),
9});
10
11const AuthTeam = Schema.Struct({
12 id: Schema.String,
13 name: Schema.String,
14});
15
16const AuthMeResponse = Schema.Struct({
17 user: AuthUser,
18 team: Schema.NullOr(AuthTeam),
19});
20
21export class CloudAuthApi extends HttpApiGroup.make("cloudAuth")
22 .add(
23 HttpApiEndpoint.get("me")`/auth/me`
24 .addSuccess(AuthMeResponse),
25 ) {}
apps/cloud/src/auth/context.ts+8−0
@@ -1,4 +1,5 @@
1import { Context } from "effect";1import { Context } from "effect";
2import type { makeUserStore } from "@executor/storage-postgres";
2 3
3export class AuthContext extends Context.Tag("@executor/cloud/AuthContext")<4export class AuthContext extends Context.Tag("@executor/cloud/AuthContext")<
4 AuthContext,5 AuthContext,
@@ -6,5 +7,12 @@ export class AuthContext extends Context.Tag("@executor/cloud/AuthContext")< · 1 unmodified line
6 readonly userId: string;7 readonly userId: string;
7 readonly teamId: string;8 readonly teamId: string;
8 readonly email: string;9 readonly email: string;
10 readonly name: string | null;
11 readonly avatarUrl: string | null;
9 }12 }
10>() {}13>() {}
14
15export class UserStoreService extends Context.Tag("@executor/cloud/UserStoreService")<
16 UserStoreService,
17 ReturnType<typeof makeUserStore>
18>() {}
apps/cloud/src/auth/handlers.ts+34−0
@@ -0,0 +1,34 @@
1import { HttpApiBuilder } from "@effect/platform";
2import { Effect } from "effect";
3
4import { addGroup } from "@executor/api";
5import { CloudAuthApi } from "./api";
6import { AuthContext, UserStoreService } from "./context";
7
8const ApiWithCloudAuth = addGroup(CloudAuthApi);
9
10export const CloudAuthHandlers = HttpApiBuilder.group(
11 ApiWithCloudAuth,
12 "cloudAuth",
13 (handlers) =>
14 handlers.handle("me", () =>
15 Effect.gen(function* () {
16 const auth = yield* AuthContext;
17 const userStore = yield* UserStoreService;
18
19 const team = yield* Effect.tryPromise(() =>
20 userStore.getTeam(auth.teamId),
21 ).pipe(Effect.orDie);
22
23 return {
24 user: {
25 id: auth.userId,
26 email: auth.email,
27 name: auth.name,
28 avatarUrl: auth.avatarUrl,
29 },
30 team: team ? { id: team.id, name: team.name } : null,
31 };
32 }),
33 ),
34);
apps/cloud/src/auth/workos.ts+34−31
@@ -48,6 +48,10 @@ export const authenticateWithCode = async (code: string) => { · 47 unmodified lines
48 * Authenticate a request using the sealed session cookie.48 * Authenticate a request using the sealed session cookie.
49 * Returns user info or null if not authenticated.49 * Returns user info or null if not authenticated.
50 */50 */
51/**
52 * Authenticate a request using the sealed session cookie.
53 * Automatically refreshes expired tokens and returns a new cookie if needed.
54 */
51export const authenticateRequest = async (request: Request) => {55export const authenticateRequest = async (request: Request) => {
52 const cookieHeader = request.headers.get("cookie");56 const cookieHeader = request.headers.get("cookie");
53 const sessionData = parseCookie(cookieHeader, COOKIE_NAME);57 const sessionData = parseCookie(cookieHeader, COOKIE_NAME);
@@ -60,39 +64,38 @@ export const authenticateRequest = async (request: Request) => { · 6 unmodified lines
60 });64 });
61 65
62 const result = await session.authenticate();66 const result = await session.authenticate();
63 if (!result.authenticated) return null;
64
65 return {
66 userId: result.user.id,
67 email: result.user.email,
68 firstName: result.user.firstName,
69 lastName: result.user.lastName,
70 avatarUrl: result.user.profilePictureUrl,
71 sessionId: result.sessionId,
72 };
73};
74
75/**
76 * Refresh the sealed session cookie. Returns new cookie value or null.
77 */
78export const refreshSession = async (request: Request) => {
79 const cookieHeader = request.headers.get("cookie");
80 const sessionData = parseCookie(cookieHeader, COOKIE_NAME);
81 if (!sessionData) return null;
82 67
83 const wos = getWorkOS();68 if (result.authenticated) {
84 const session = wos.userManagement.loadSealedSession({69 return {
85 sessionData,70 userId: result.user.id,
86 cookiePassword: getCookiePassword(),71 email: result.user.email,
87 });72 firstName: result.user.firstName,
88 73 lastName: result.user.lastName,
89 const result = await session.refresh();74 avatarUrl: result.user.profilePictureUrl,
90 if (!result.authenticated || !result.sealedSession) return null;75 sessionId: result.sessionId,
76 refreshedCookie: undefined as string | undefined,
77 };
78 }
91 79
92 return {80 // Token expired — try refreshing
93 sealedSession: result.sealedSession,81 if (result.reason === "no_session_cookie_provided") return null;
94 cookie: makeSessionCookie(result.sealedSession),82
95 };83 try {
84 const refreshed = await session.refresh();
85 if (!refreshed.authenticated || !refreshed.sealedSession) return null;
86
87 return {
88 userId: refreshed.user.id,
89 email: refreshed.user.email,
90 firstName: refreshed.user.firstName,
91 lastName: refreshed.user.lastName,
92 avatarUrl: refreshed.user.profilePictureUrl,
93 sessionId: refreshed.sessionId,
94 refreshedCookie: makeSessionCookie(refreshed.sealedSession),
95 };
96 } catch {
97 return null;
98 }
96};99};
97 100
98/**101/**
apps/cloud/src/web/auth.tsx+32−26
@@ -1,4 +1,11 @@
1import React, { createContext, useContext, useEffect, useState } from "react";1import React, { createContext, useContext } from "react";
2import { useAtomValue, Result } from "@effect-atom/atom-react";
3
4import { CloudApiClient } from "./client";
5
6// ---------------------------------------------------------------------------
7// Types (from CloudAuthApi response schema)
8// ---------------------------------------------------------------------------
2 9
3type AuthUser = {10type AuthUser = {
4 id: string;11 id: string;
@@ -12,40 +19,39 @@ type AuthTeam = { · 7 unmodified lines
12 name: string;19 name: string;
13};20};
14 21
22// ---------------------------------------------------------------------------
23// Auth atom — typed query against CloudAuthApi
24// ---------------------------------------------------------------------------
25
26export const authAtom = CloudApiClient.query("cloudAuth", "me", {
27 timeToLive: "5 minutes",
28});
29
30// ---------------------------------------------------------------------------
31// Provider + hook
32// ---------------------------------------------------------------------------
33
15type AuthState =34type AuthState =
16 | { status: "loading" }35 | { status: "loading" }
17 | { status: "unauthenticated" }36 | { status: "unauthenticated" }
18 | { status: "authenticated"; user: AuthUser; team: AuthTeam };37 | { status: "authenticated"; user: AuthUser; team: AuthTeam | null };
19 38
20const AuthContext = createContext<AuthState>({ status: "loading" });39const AuthContext = createContext<AuthState>({ status: "loading" });
21 40
22export const useAuth = () => useContext(AuthContext);41export const useAuth = () => useContext(AuthContext);
23 42
24export const AuthProvider = ({ children }: { children: React.ReactNode }) => {43export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
25 const [state, setState] = useState<AuthState>({ status: "loading" });44 const result = useAtomValue(authAtom);
26 45
27 useEffect(() => {46 const state: AuthState = Result.match(result, {
28 fetch("/auth/me")47 onInitial: () => ({ status: "loading" as const }),
29 .then((res) => {48 onSuccess: ({ value }) => ({
30 if (!res.ok) {49 status: "authenticated" as const,
31 setState({ status: "unauthenticated" });50 user: value.user,
32 return;51 team: value.team,
33 }52 }),
34 return res.json();53 onFailure: () => ({ status: "unauthenticated" as const }),
35 })54 });
36 .then((data) => {
37 if (data?.user) {
38 setState({
39 status: "authenticated",
40 user: data.user,
41 team: data.team,
42 });
43 }
44 })
45 .catch(() => {
46 setState({ status: "unauthenticated" });
47 });
48 }, []);
49 55
50 return <AuthContext.Provider value={state}>{children}</AuthContext.Provider>;56 return <AuthContext.Provider value={state}>{children}</AuthContext.Provider>;
51};57};
apps/cloud/src/web/client.tsx+22−0
@@ -0,0 +1,22 @@
1import { AtomHttpApi } from "@effect-atom/atom-react";
2import { FetchHttpClient } from "@effect/platform";
3import { addGroup } from "@executor/api";
4import { getBaseUrl } from "@executor/react/api/base-url";
5import { CloudAuthApi } from "../auth/api";
6
7// ---------------------------------------------------------------------------
8// Cloud API client — core API + cloud auth
9// ---------------------------------------------------------------------------
10
11const CloudApi = addGroup(CloudAuthApi);
12
13class CloudApiClient extends AtomHttpApi.Tag<CloudApiClient>()(
14 "CloudApiClient",
15 {
16 api: CloudApi,
17 httpClient: FetchHttpClient.layer,
18 baseUrl: getBaseUrl(),
19 },
20) {}
21
22export { CloudApiClient };
apps/cloud/src/web/main.tsx+1−1
@@ -1,6 +1,6 @@
1import React from "react";1import React from "react";
2import { createRoot } from "react-dom/client";2import { createRoot } from "react-dom/client";
3import "@executor/ui/globals.css";3import "@executor/react/globals.css";
4import { App } from "./App";4import { App } from "./App";
5 5
6const root = createRoot(document.getElementById("root")!);6const root = createRoot(document.getElementById("root")!);
apps/cloud/src/web/router.tsx+7−7
@@ -3,13 +3,13 @@ import { · 2 unmodified lines
3 createRootRoute,3 createRootRoute,
4 createRoute,4 createRoute,
5} from "@tanstack/react-router";5} from "@tanstack/react-router";
6import { ExecutorProvider } from "@executor/react";6import { ExecutorProvider } from "@executor/react/api/provider";
7import { ToolsPage } from "@web/pages/tools";7import { ToolsPage } from "@executor/react/pages/tools";
8import { SourcesPage } from "@web/pages/sources";8import { SourcesPage } from "@executor/react/pages/sources";
9import { SourcesAddPage } from "@web/pages/sources-add";9import { SourcesAddPage } from "@executor/react/pages/sources-add";
10import { SourceDetailPage } from "@web/pages/source-detail";10import { SourceDetailPage } from "@executor/react/pages/source-detail";
11import { SecretsPage } from "@web/pages/secrets";11import { SecretsPage } from "@executor/react/pages/secrets";
12import { Shell } from "@web/shell";12import { Shell } from "./shell";
13 13
14// ---------------------------------------------------------------------------14// ---------------------------------------------------------------------------
15// Root layout — Shell renders <Outlet /> directly15// Root layout — Shell renders <Outlet /> directly
apps/cloud/src/web/shell.tsx+483−0
@@ -0,0 +1,483 @@
1import { Link, Outlet, useLocation } from "@tanstack/react-router";
2import { useCallback, useEffect, useRef, useState } from "react";
3import { useAtomRefresh, useAtomValue, Result } from "@effect-atom/atom-react";
4import { sourcesAtom, toolsAtom } from "@executor/react/api/atoms";
5import { useScope, useScopeInfo } from "@executor/react/api/scope-context";
6import { Button } from "@executor/react/components/button";
7import { useAuth } from "./auth";
8
9// ── Env ─────────────────────────────────────────────────────────────────
10
11type AppMetaEnv = {
12 readonly VITE_APP_VERSION: string;
13 readonly VITE_GITHUB_URL: string;
14};
15
16const { VITE_APP_VERSION, VITE_GITHUB_URL } = (import.meta as ImportMeta & {
17 readonly env: AppMetaEnv;
18}).env;
19
20// ── Version helpers ─────────────────────────────────────────────────────
21
22type UpdateChannel = "latest" | "beta";
23
24const EXECUTOR_DIST_TAGS_PATH = "/v1/app/npm/dist-tags";
25
26type ParsedVersion = {
27 readonly major: number;
28 readonly minor: number;
29 readonly patch: number;
30 readonly prerelease: ReadonlyArray<string | number> | null;
31};
32
33const semverPattern =
34 /^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(?:-(?<prerelease>[0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
35
36const resolveUpdateChannel = (version: string): UpdateChannel =>
37 version.includes("-beta.") ? "beta" : "latest";
38
39const parseVersion = (version: string): ParsedVersion | null => {
40 const match = version.trim().match(semverPattern);
41 if (!match?.groups) return null;
42 return {
43 major: Number(match.groups.major),
44 minor: Number(match.groups.minor),
45 patch: Number(match.groups.patch),
46 prerelease: match.groups.prerelease
47 ? match.groups.prerelease.split(".").map((id) =>
48 /^\d+$/.test(id) ? Number(id) : id,
49 )
50 : null,
51 };
52};
53
54const comparePrereleaseIdentifiers = (
55 left: ReadonlyArray<string | number> | null,
56 right: ReadonlyArray<string | number> | null,
57): number => {
58 if (left === null && right === null) return 0;
59 if (left === null) return 1;
60 if (right === null) return -1;
61 const max = Math.max(left.length, right.length);
62 for (let i = 0; i < max; i++) {
63 const l = left[i];
64 const r = right[i];
65 if (l === undefined) return -1;
66 if (r === undefined) return 1;
67 if (l === r) continue;
68 if (typeof l === "number" && typeof r === "number") return l < r ? -1 : 1;
69 if (typeof l === "number") return -1;
70 if (typeof r === "number") return 1;
71 return l < r ? -1 : 1;
72 }
73 return 0;
74};
75
76const compareVersions = (left: string, right: string): number | null => {
77 const lv = parseVersion(left);
78 const rv = parseVersion(right);
79 if (!lv || !rv) return null;
80 if (lv.major !== rv.major) return lv.major < rv.major ? -1 : 1;
81 if (lv.minor !== rv.minor) return lv.minor < rv.minor ? -1 : 1;
82 if (lv.patch !== rv.patch) return lv.patch < rv.patch ? -1 : 1;
83 return comparePrereleaseIdentifiers(lv.prerelease, rv.prerelease);
84};
85
86// ── useLatestVersion ────────────────────────────────────────────────────
87
88function useLatestVersion(currentVersion: string) {
89 const channel = resolveUpdateChannel(currentVersion);
90 const [latestVersion, setLatestVersion] = useState<string | null>(null);
91
92 useEffect(() => {
93 let cancelled = false;
94 fetch(EXECUTOR_DIST_TAGS_PATH)
95 .then(async (res) => {
96 if (!res.ok) throw new Error(`Failed to load dist tags: ${res.status}`);
97 return res.json() as Promise<Partial<Record<UpdateChannel, string>>>;
98 })
99 .then((data) => {
100 if (!cancelled) setLatestVersion(data[channel] ?? null);
101 })
102 .catch(() => {});
103 return () => { cancelled = true; };
104 }, [channel]);
105
106 const updateAvailable =
107 latestVersion !== null && compareVersions(currentVersion, latestVersion) === -1;
108
109 return { latestVersion, updateAvailable, channel };
110}
111
112// ── UpdateCard ──────────────────────────────────────────────────────────
113
114function UpdateCard(props: { latestVersion: string; channel: UpdateChannel }) {
115 const command = `npm i -g executor@${props.channel}`;
116 const [copied, setCopied] = useState(false);
117
118 const handleCopy = useCallback(() => {
119 void navigator.clipboard.writeText(command).then(() => {
120 setCopied(true);
121 setTimeout(() => setCopied(false), 1500);
122 });
123 }, [command]);
124
125 return (
126 <div className="mx-2 mb-2 rounded-xl border border-primary/25 bg-primary/[0.06] p-3">
127 <div className="flex items-center gap-2">
128 <div className="flex size-5 shrink-0 items-center justify-center rounded-full bg-primary/15">
129 <svg viewBox="0 0 16 16" fill="none" className="size-3 text-primary">
130 <path d="M8 3v7M5 7l3 3 3-3" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />
131 <path d="M3 12h10" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" />
132 </svg>
133 </div>
134 <div className="min-w-0">
135 <p className="text-[11px] font-semibold text-foreground">Update available</p>
136 <p className="text-[10px] text-muted-foreground">
137 v{props.latestVersion}
138 </p>
139 </div>
140 </div>
141 <Button
142 type="button"
143 variant="outline"
144 onClick={handleCopy}
145 className="mt-2.5 flex w-full items-center justify-between gap-2 rounded-lg border-border/60 bg-background/50 px-2.5 py-1.5 text-left hover:bg-background/80"
146 >
147 <code className="truncate font-mono text-[10px] text-sidebar-foreground">
148 {command}
149 </code>
150 <span className="shrink-0 text-muted-foreground transition-colors group-hover:text-foreground">
151 {copied ? (
152 <svg viewBox="0 0 16 16" fill="none" className="size-3 text-primary">
153 <path d="M3 8.5l3.5 3.5L13 4" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />
154 </svg>
155 ) : (
156 <svg viewBox="0 0 16 16" fill="none" className="size-3">
157 <rect x="5" y="5" width="8" height="8" rx="1.5" stroke="currentColor" strokeWidth="1.2" />
158 <path d="M3 11V3.5A.5.5 0 013.5 3H11" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" />
159 </svg>
160 )}
161 </span>
162 </Button>
163 </div>
164 );
165}
166
167// ── NavItem ──────────────────────────────────────────────────────────────
168
169function NavItem(props: { to: string; label: string; active: boolean; onNavigate?: () => void }) {
170 return (
171 <Link
172 to={props.to}
173 onClick={props.onNavigate}
174 className={[
175 "flex items-center gap-2.5 rounded-md px-2.5 py-1.5 text-[13px] transition-colors",
176 props.active
177 ? "bg-sidebar-active text-foreground font-medium"
178 : "text-sidebar-foreground hover:bg-sidebar-active/60 hover:text-foreground",
179 ].join(" ")}
180 >
181 {props.label}
182 </Link>
183 );
184}
185
186// ── SourceList ───────────────────────────────────────────────────────────
187
188function SourceList(props: { pathname: string; onNavigate?: () => void }) {
189 const scopeId = useScope();
190 const sources = useAtomValue(sourcesAtom(scopeId));
191
192 return Result.match(sources, {
193 onInitial: () => (
194 <div className="px-2.5 py-2 text-[11px] text-muted-foreground/40">Loading…</div>
195 ),
196 onFailure: () => (
197 <div className="px-2.5 py-2 text-[11px] text-muted-foreground/40">No sources yet</div>
198 ),
199 onSuccess: ({ value }) =>
200 value.length === 0 ? (
201 <div className="px-2.5 py-2 text-[11px] leading-relaxed text-muted-foreground/40">
202 No sources yet
203 </div>
204 ) : (
205 <div className="flex flex-col gap-px">
206 {value.map((s) => {
207 const detailPath = `/sources/${s.id}`;
208 const active =
209 props.pathname === detailPath ||
210 props.pathname.startsWith(`${detailPath}/`);
211 return (
212 <Link
213 key={s.id}
214 to="/sources/$namespace"
215 params={{ namespace: s.id }}
216 onClick={props.onNavigate}
217 className={[
218 "group flex items-center gap-2 rounded-md px-2.5 py-1.5 text-[13px] transition-colors",
219 active
220 ? "bg-sidebar-active text-foreground font-medium"
221 : "text-sidebar-foreground hover:bg-sidebar-active/60 hover:text-foreground",
222 ].join(" ")}
223 >
224 <span className="flex-1 truncate">{s.name}</span>
225 <span className="rounded bg-secondary/50 px-1 py-px text-[9px] font-medium text-muted-foreground/50">
226 {s.kind}
227 </span>
228 </Link>
229 );
230 })}
231 </div>
232 ),
233 });
234}
235
236// ── ScopeLabel ───────────────────────────────────────────────────────────
237
238function ScopeLabel() {
239 const { name } = useScopeInfo();
240 // Show just the last folder name, with full path as tooltip
241 const parts = name.replace(/\/+$/, "").split("/");
242 const folder = parts[parts.length - 1] || name;
243
244 return (
245 <div className="mb-1.5 flex items-center gap-1.5 rounded-md px-2.5 py-1.5" title={name}>
246 <svg viewBox="0 0 16 16" fill="none" className="size-3.5 shrink-0 text-muted-foreground/50">
247 <path
248 d="M2 4.5C2 3.67 2.67 3 3.5 3h3.09a1 1 0 0 1 .7.29l1.42 1.42a1 1 0 0 0 .7.29H12.5c.83 0 1.5.67 1.5 1.5v5.5c0 .83-.67 1.5-1.5 1.5h-9A1.5 1.5 0 0 1 2 12V4.5z"
249 stroke="currentColor"
250 strokeWidth="1.2"
251 />
252 </svg>
253 <span className="truncate text-[12px] font-medium text-foreground/80">
254 {folder}
255 </span>
256 </div>
257 );
258}
259
260// ── UserFooter ──────────────────────────────────────────────────────────
261
262function UserFooter() {
263 const auth = useAuth();
264 if (auth.status !== "authenticated") return null;
265
266 const initials = auth.user.name
267 ? auth.user.name.split(" ").map((n) => n[0]).join("").slice(0, 2).toUpperCase()
268 : auth.user.email[0]!.toUpperCase();
269
270 return (
271 <div className="shrink-0 border-t border-sidebar-border px-3 py-2.5">
272 <div className="flex items-center gap-2.5">
273 {auth.user.avatarUrl ? (
274 <img
275 src={auth.user.avatarUrl}
276 alt=""
277 className="size-7 shrink-0 rounded-full"
278 />
279 ) : (
280 <div className="flex size-7 shrink-0 items-center justify-center rounded-full bg-primary/10 text-[10px] font-semibold text-primary">
281 {initials}
282 </div>
283 )}
284 <div className="min-w-0 flex-1">
285 <p className="truncate text-[12px] font-medium text-foreground">
286 {auth.user.name ?? auth.user.email}
287 </p>
288 {auth.team && (
289 <p className="truncate text-[10px] text-muted-foreground">
290 {auth.team.name}
291 </p>
292 )}
293 </div>
294 <a
295 href="/auth/logout"
296 className="shrink-0 rounded-md p-1 text-muted-foreground/50 transition-colors hover:bg-sidebar-active hover:text-foreground"
297 title="Sign out"
298 >
299 <svg viewBox="0 0 16 16" fill="none" className="size-3.5">
300 <path d="M6 2H3.5A1.5 1.5 0 002 3.5v9A1.5 1.5 0 003.5 14H6M10.5 11.5L14 8l-3.5-3.5M14 8H6" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" />
301 </svg>
302 </a>
303 </div>
304 </div>
305 );
306}
307
308// ── SidebarContent ───────────────────────────────────────────────────────
309
310function SidebarContent(props: {
311 pathname: string;
312 onNavigate?: () => void;
313 showBrand?: boolean;
314 updateAvailable: boolean;
315 latestVersion: string | null;
316 channel: UpdateChannel;
317}) {
318 const isHome = props.pathname === "/";
319 const isSecrets = props.pathname === "/secrets";
320
321 return (
322 <>
323 {props.showBrand !== false && (
324 <div className="flex h-12 shrink-0 items-center border-b border-sidebar-border px-4">
325 <Link to="/" className="flex items-center gap-1.5">
326 <span className="font-display text-base tracking-tight text-foreground">
327 executor
328 </span>
329 </Link>
330 </div>
331 )}
332
333 <nav className="flex flex-1 flex-col overflow-y-auto p-2">
334 <ScopeLabel />
335 <NavItem
336 to="/"
337 label="Sources"
338 active={isHome}
339 onNavigate={props.onNavigate}
340 />
341 <NavItem
342 to="/secrets"
343 label="Secrets"
344 active={isSecrets}
345 onNavigate={props.onNavigate}
346 />
347
348 {/* Sources list */}
349 <div className="mt-5 mb-1 px-2.5 text-[10px] font-medium uppercase tracking-widest text-muted-foreground/50">
350 <span>Configured</span>
351 </div>
352
353 <SourceList pathname={props.pathname} onNavigate={props.onNavigate} />
354 </nav>
355
356 {/* User */}
357 <UserFooter />
358 </>
359 );
360}
361
362// ── Shell ─────────────────────────────────────────────────────────────────
363
364export function Shell() {
365 const location = useLocation();
366 const pathname = location.pathname;
367 const scopeId = useScope();
368 const refreshSources = useAtomRefresh(sourcesAtom(scopeId));
369 const refreshTools = useAtomRefresh(toolsAtom(scopeId));
370 const { latestVersion, updateAvailable, channel } = useLatestVersion(VITE_APP_VERSION);
371 const lastPathname = useRef(pathname);
372 const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
373 if (lastPathname.current !== pathname) {
374 lastPathname.current = pathname;
375 if (mobileSidebarOpen) setMobileSidebarOpen(false);
376 }
377
378 // Lock scroll when mobile sidebar open
379 useEffect(() => {
380 if (!mobileSidebarOpen) return;
381 const prev = document.body.style.overflow;
382 document.body.style.overflow = "hidden";
383 return () => {
384 document.body.style.overflow = prev;
385 };
386 }, [mobileSidebarOpen]);
387
388 useEffect(() => {
389 if (!import.meta.hot) {
390 return;
391 }
392
393 const refreshBackendData = () => {
394 refreshSources();
395 refreshTools();
396 };
397
398 import.meta.hot.on("executor:backend-updated", refreshBackendData);
399
400 return () => {
401 import.meta.hot?.off("executor:backend-updated", refreshBackendData);
402 };
403 }, [refreshSources, refreshTools]);
404
405 return (
406 <div className="flex h-screen overflow-hidden">
407 {/* Desktop sidebar */}
408 <aside className="hidden w-52 shrink-0 border-r border-sidebar-border bg-sidebar md:flex md:flex-col lg:w-56">
409 <SidebarContent
410 pathname={pathname}
411 updateAvailable={updateAvailable}
412 latestVersion={latestVersion}
413 channel={channel}
414 />
415 </aside>
416
417 {/* Mobile sidebar overlay */}
418 {mobileSidebarOpen && (
419 <div className="fixed inset-0 z-50 flex md:hidden">
420 <button
421 type="button"
422 aria-label="Close navigation"
423 className="absolute inset-0 bg-black/45 backdrop-blur-[1px]"
424 onClick={() => setMobileSidebarOpen(false)}
425 />
426 <div className="relative flex h-full w-[84vw] max-w-xs flex-col border-r border-sidebar-border bg-sidebar shadow-2xl">
427 <div className="flex h-12 shrink-0 items-center justify-between border-b border-sidebar-border px-4">
428 <Link to="/" className="flex items-center gap-1.5">
429 <span className="font-display text-base tracking-tight text-foreground">
430 executor
431 </span>
432 </Link>
433 <button
434 type="button"
435 aria-label="Close navigation"
436 onClick={() => setMobileSidebarOpen(false)}
437 className="size-8 flex items-center justify-center rounded-md text-sidebar-foreground hover:bg-sidebar-active hover:text-foreground"
438 >
439 <svg viewBox="0 0 16 16" className="size-3.5">
440 <path d="M3 3l10 10M13 3L3 13" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" />
441 </svg>
442 </button>
443 </div>
444 <SidebarContent
445 pathname={pathname}
446 onNavigate={() => setMobileSidebarOpen(false)}
447 showBrand={false}
448 updateAvailable={updateAvailable}
449 latestVersion={latestVersion}
450 channel={channel}
451 />
452 </div>
453 </div>
454 )}
455
456 {/* Main content */}
457 <main className="flex min-h-0 flex-1 flex-col min-w-0 overflow-hidden">
458 {/* Mobile top bar */}
459 <div className="flex h-12 shrink-0 items-center justify-between border-b border-border bg-background px-4 md:hidden">
460 <button
461 type="button"
462 aria-label="Open navigation"
463 onClick={() => setMobileSidebarOpen(true)}
464 className="size-8 flex items-center justify-center rounded-md border border-border bg-card hover:bg-accent/50"
465 >
466 <svg viewBox="0 0 16 16" className="size-4">
467 <path d="M2 4h12M2 8h12M2 12h12" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" />
468 </svg>
469 </button>
470 <Link to="/" className="flex items-center gap-1.5">
471 <span className="font-display text-base tracking-tight text-foreground">
472 executor
473 </span>
474 </Link>
475 <div className="w-8 shrink-0" />
476 </div>
477
478 {/* Outlet — pages control their own padding/scroll */}
479 <Outlet />
480 </main>
481 </div>
482 );
483}
apps/cloud/tsconfig.json+0−3
@@ -12,9 +12,6 @@ · 11 unmodified lines
12 "declarationMap": true,12 "declarationMap": true,
13 "sourceMap": true,13 "sourceMap": true,
14 "jsx": "react-jsx",14 "jsx": "react-jsx",
15 "paths": {
16 "@web/*": ["../local/src/web/*"]
17 },
18 "plugins": [15 "plugins": [
19 {16 {
20 "name": "@effect/language-service",17 "name": "@effect/language-service",
apps/cloud/vite.config.ts+0−6
@@ -1,4 +1,3 @@
1import { resolve } from "node:path";
2import { defineConfig } from "vite";1import { defineConfig } from "vite";
3import react from "@vitejs/plugin-react";2import react from "@vitejs/plugin-react";
4import tailwindcss from "@tailwindcss/vite";3import tailwindcss from "@tailwindcss/vite";
@@ -11,11 +10,6 @@ export default defineConfig({ · 6 unmodified lines
11 "import.meta.env.VITE_APP_VERSION": JSON.stringify("0.0.0"),10 "import.meta.env.VITE_APP_VERSION": JSON.stringify("0.0.0"),
12 "import.meta.env.VITE_GITHUB_URL": JSON.stringify("https://github.com/RhysSullivan/executor"),11 "import.meta.env.VITE_GITHUB_URL": JSON.stringify("https://github.com/RhysSullivan/executor"),
13 },12 },
14 resolve: {
15 alias: {
16 "@web": resolve(__dirname, "../local/src/web"),
17 },
18 },
19 server: {13 server: {
20 proxy: {14 proxy: {
21 "/v1": `http://localhost:${API_PORT}`,15 "/v1": `http://localhost:${API_PORT}`,
apps/local/package.json+0−1
@@ -25,7 +25,6 @@ · 24 unmodified lines
25 "@executor/react": "workspace:*",25 "@executor/react": "workspace:*",
26 "@executor/sdk": "workspace:*",26 "@executor/sdk": "workspace:*",
27 "@executor/storage-file": "workspace:*",27 "@executor/storage-file": "workspace:*",
28 "@executor/ui": "workspace:*",
29 "@modelcontextprotocol/sdk": "^1.12.1",28 "@modelcontextprotocol/sdk": "^1.12.1",
30 "@shikijs/langs": "^4.0.2",29 "@shikijs/langs": "^4.0.2",
31 "@shikijs/themes": "^4.0.2",30 "@shikijs/themes": "^4.0.2",
apps/local/src/web/lib/use-scope.ts+0−1
@@ -1 +0,0 @@
1export { useScope } from "@executor/react";
apps/local/src/web/main.tsx+1−1
@@ -1,6 +1,6 @@
1import React from "react";1import React from "react";
2import { createRoot } from "react-dom/client";2import { createRoot } from "react-dom/client";
3import "@executor/ui/globals.css";3import "@executor/react/globals.css";
4import { App } from "./App";4import { App } from "./App";
5 5
6const root = createRoot(document.getElementById("root")!);6const root = createRoot(document.getElementById("root")!);
apps/local/src/web/router.tsx+6−6
@@ -3,12 +3,12 @@ import { · 2 unmodified lines
3 createRootRoute,3 createRootRoute,
4 createRoute,4 createRoute,
5} from "@tanstack/react-router";5} from "@tanstack/react-router";
6import { ExecutorProvider } from "@executor/react";6import { ExecutorProvider } from "@executor/react/api/provider";
7import { ToolsPage } from "./pages/tools";7import { ToolsPage } from "@executor/react/pages/tools";
8import { SourcesPage } from "./pages/sources";8import { SourcesPage } from "@executor/react/pages/sources";
9import { SourcesAddPage } from "./pages/sources-add";9import { SourcesAddPage } from "@executor/react/pages/sources-add";
10import { SourceDetailPage } from "./pages/source-detail";10import { SourceDetailPage } from "@executor/react/pages/source-detail";
11import { SecretsPage } from "./pages/secrets";11import { SecretsPage } from "@executor/react/pages/secrets";
12import { Shell } from "./shell";12import { Shell } from "./shell";
13 13
14// ---------------------------------------------------------------------------14// ---------------------------------------------------------------------------
apps/local/src/web/shell.tsx+4−10
@@ -1,15 +1,9 @@
1import { Link, Outlet, useLocation } from "@tanstack/react-router";1import { Link, Outlet, useLocation } from "@tanstack/react-router";
2import { useCallback, useEffect, useRef, useState } from "react";2import { useCallback, useEffect, useRef, useState } from "react";
3import {3import { useAtomRefresh, useAtomValue, Result } from "@effect-atom/atom-react";
4 useAtomRefresh,4import { sourcesAtom, toolsAtom } from "@executor/react/api/atoms";
5 useAtomValue,5import { useScope, useScopeInfo } from "@executor/react/api/scope-context";
6 Result,6import { Button } from "@executor/react/components/button";
7 sourcesAtom,
8 toolsAtom,
9 useScope,
10 useScopeInfo,
11} from "@executor/react";
12import { Button } from "@executor/ui/components/button";
13 7
14// ── Env ─────────────────────────────────────────────────────────────────8// ── Env ─────────────────────────────────────────────────────────────────
15 9
bun.lock+10−40
@@ -53,7 +53,6 @@ · 52 unmodified lines
53 "@executor/react": "workspace:*",53 "@executor/react": "workspace:*",
54 "@executor/sdk": "workspace:*",54 "@executor/sdk": "workspace:*",
55 "@executor/storage-postgres": "workspace:*",55 "@executor/storage-postgres": "workspace:*",
56 "@executor/ui": "workspace:*",
57 "@tanstack/react-router": "^1.168.10",56 "@tanstack/react-router": "^1.168.10",
58 "@workos-inc/node": "^7.0.0",57 "@workos-inc/node": "^7.0.0",
59 "drizzle-orm": "catalog:",58 "drizzle-orm": "catalog:",
@@ -106,7 +105,6 @@ · 46 unmodified lines
106 "@executor/react": "workspace:*",105 "@executor/react": "workspace:*",
107 "@executor/sdk": "workspace:*",106 "@executor/sdk": "workspace:*",
108 "@executor/storage-file": "workspace:*",107 "@executor/storage-file": "workspace:*",
109 "@executor/ui": "workspace:*",
110 "@modelcontextprotocol/sdk": "^1.12.1",108 "@modelcontextprotocol/sdk": "^1.12.1",
111 "@shikijs/langs": "^4.0.2",109 "@shikijs/langs": "^4.0.2",
112 "@shikijs/themes": "^4.0.2",110 "@shikijs/themes": "^4.0.2",
@@ -140,25 +138,6 @@ · 27 unmodified lines
140 "tailwindcss": "^4.2.2",138 "tailwindcss": "^4.2.2",
141 },139 },
142 },140 },
143 "packages/clients/react": {
144 "name": "@executor/react",
145 "version": "1.4.0",
146 "dependencies": {
147 "@effect-atom/atom": "^0.5.3",
148 "@effect-atom/atom-react": "^0.5.0",
149 "@effect/platform": "catalog:",
150 "@executor/api": "workspace:*",
151 "@executor/sdk": "workspace:*",
152 "@executor/ui": "workspace:*",
153 "effect": "catalog:",
154 "react": "^19.1.0",
155 },
156 "devDependencies": {
157 "@types/node": "catalog:",
158 "@types/react": "^19.1.0",
159 "typescript": "^5.9.3",
160 },
161 },
162 "packages/core/api": {141 "packages/core/api": {
163 "name": "@executor/api",142 "name": "@executor/api",
164 "version": "1.4.0",143 "version": "1.4.0",
@@ -357,7 +336,6 @@ · 192 unmodified lines
357 "@effect-atom/atom-react": "^0.5.0",336 "@effect-atom/atom-react": "^0.5.0",
358 "@effect/vitest": "catalog:",337 "@effect/vitest": "catalog:",
359 "@executor/react": "workspace:*",338 "@executor/react": "workspace:*",
360 "@executor/ui": "workspace:*",
361 "@types/node": "catalog:",339 "@types/node": "catalog:",
362 "@types/react": "^19.1.0",340 "@types/react": "^19.1.0",
363 "bun-types": "catalog:",341 "bun-types": "catalog:",
@@ -367,14 +345,12 @@ · 3 unmodified lines
367 "peerDependencies": {345 "peerDependencies": {
368 "@effect-atom/atom-react": "^0.5.0",346 "@effect-atom/atom-react": "^0.5.0",
369 "@executor/react": "workspace:*",347 "@executor/react": "workspace:*",
370 "@executor/ui": "workspace:*",
371 "@tanstack/react-router": "^1.168.10",348 "@tanstack/react-router": "^1.168.10",
372 "react": "^19.1.0",349 "react": "^19.1.0",
373 },350 },
374 "optionalPeers": [351 "optionalPeers": [
375 "@effect-atom/atom-react",352 "@effect-atom/atom-react",
376 "@executor/react",353 "@executor/react",
377 "@executor/ui",
378 "@tanstack/react-router",354 "@tanstack/react-router",
379 "react",355 "react",
380 ],356 ],
@@ -393,7 +369,6 @@ · 12 unmodified lines
393 "@effect/vitest": "catalog:",369 "@effect/vitest": "catalog:",
394 "@executor/api": "workspace:*",370 "@executor/api": "workspace:*",
395 "@executor/react": "workspace:*",371 "@executor/react": "workspace:*",
396 "@executor/ui": "workspace:*",
397 "@types/node": "catalog:",372 "@types/node": "catalog:",
398 "@types/react": "^19.1.0",373 "@types/react": "^19.1.0",
399 "bun-types": "catalog:",374 "bun-types": "catalog:",
@@ -404,7 +379,6 @@ · 4 unmodified lines
404 "@effect-atom/atom-react": "^0.5.0",379 "@effect-atom/atom-react": "^0.5.0",
405 "@executor/api": "workspace:*",380 "@executor/api": "workspace:*",
406 "@executor/react": "workspace:*",381 "@executor/react": "workspace:*",
407 "@executor/ui": "workspace:*",
408 "@tanstack/react-router": "^1.168.10",382 "@tanstack/react-router": "^1.168.10",
409 "react": "^19.1.0",383 "react": "^19.1.0",
410 },384 },
@@ -412,7 +386,6 @@ · 1 unmodified line
412 "@effect-atom/atom-react",386 "@effect-atom/atom-react",
413 "@executor/api",387 "@executor/api",
414 "@executor/react",388 "@executor/react",
415 "@executor/ui",
416 "@tanstack/react-router",389 "@tanstack/react-router",
417 "react",390 "react",
418 ],391 ],
@@ -447,7 +420,6 @@ · 28 unmodified lines
447 "@effect/vitest": "catalog:",420 "@effect/vitest": "catalog:",
448 "@executor/api": "workspace:*",421 "@executor/api": "workspace:*",
449 "@executor/react": "workspace:*",422 "@executor/react": "workspace:*",
450 "@executor/ui": "workspace:*",
451 "@types/node": "catalog:",423 "@types/node": "catalog:",
452 "@types/react": "^19.1.0",424 "@types/react": "^19.1.0",
453 "bun-types": "catalog:",425 "bun-types": "catalog:",
@@ -459,7 +431,6 @@ · 5 unmodified lines
459 "@effect-atom/atom-react": "^0.5.0",431 "@effect-atom/atom-react": "^0.5.0",
460 "@executor/api": "workspace:*",432 "@executor/api": "workspace:*",
461 "@executor/react": "workspace:*",433 "@executor/react": "workspace:*",
462 "@executor/ui": "workspace:*",
463 "@tanstack/react-router": "^1.168.10",434 "@tanstack/react-router": "^1.168.10",
464 "react": "^19.1.0",435 "react": "^19.1.0",
465 },436 },
@@ -467,7 +438,6 @@ · 1 unmodified line
467 "@effect-atom/atom-react",438 "@effect-atom/atom-react",
468 "@executor/api",439 "@executor/api",
469 "@executor/react",440 "@executor/react",
470 "@executor/ui",
471 "@tanstack/react-router",441 "@tanstack/react-router",
472 "react",442 "react",
473 ],443 ],
@@ -495,13 +465,11 @@ · 21 unmodified lines
495 "peerDependencies": {465 "peerDependencies": {
496 "@effect-atom/atom-react": "^0.5.0",466 "@effect-atom/atom-react": "^0.5.0",
497 "@executor/react": "workspace:*",467 "@executor/react": "workspace:*",
498 "@executor/ui": "workspace:*",
499 "react": ">=18",468 "react": ">=18",
500 },469 },
501 "optionalPeers": [470 "optionalPeers": [
502 "@effect-atom/atom-react",471 "@effect-atom/atom-react",
503 "@executor/react",472 "@executor/react",
504 "@executor/ui",
505 "react",473 "react",
506 ],474 ],
507 },475 },
@@ -522,7 +490,6 @@ · 14 unmodified lines
522 "@effect/vitest": "catalog:",490 "@effect/vitest": "catalog:",
523 "@executor/api": "workspace:*",491 "@executor/api": "workspace:*",
524 "@executor/react": "workspace:*",492 "@executor/react": "workspace:*",
525 "@executor/ui": "workspace:*",
526 "@types/node": "catalog:",493 "@types/node": "catalog:",
527 "@types/react": "^19.1.0",494 "@types/react": "^19.1.0",
528 "bun-types": "catalog:",495 "bun-types": "catalog:",
@@ -533,7 +500,6 @@ · 4 unmodified lines
533 "@effect-atom/atom-react": "^0.5.0",500 "@effect-atom/atom-react": "^0.5.0",
534 "@executor/api": "workspace:*",501 "@executor/api": "workspace:*",
535 "@executor/react": "workspace:*",502 "@executor/react": "workspace:*",
536 "@executor/ui": "workspace:*",
537 "@tanstack/react-router": "^1.168.10",503 "@tanstack/react-router": "^1.168.10",
538 "react": "^19.1.0",504 "react": "^19.1.0",
539 },505 },
@@ -541,16 +507,20 @@ · 1 unmodified line
541 "@effect-atom/atom-react",507 "@effect-atom/atom-react",
542 "@executor/api",508 "@executor/api",
543 "@executor/react",509 "@executor/react",
544 "@executor/ui",
545 "@tanstack/react-router",510 "@tanstack/react-router",
546 "react",511 "react",
547 ],512 ],
548 },513 },
549 "packages/ui": {514 "packages/react": {
550 "name": "@executor/ui",515 "name": "@executor/react",
551 "version": "1.4.0",516 "version": "1.4.0",
552 "dependencies": {517 "dependencies": {
553 "@base-ui/react": "^1.3.0",518 "@base-ui/react": "^1.3.0",
519 "@effect-atom/atom": "^0.5.3",
520 "@effect-atom/atom-react": "^0.5.0",
521 "@effect/platform": "catalog:",
522 "@executor/api": "workspace:*",
523 "@executor/sdk": "workspace:*",
554 "@hookform/resolvers": "^5.2.2",524 "@hookform/resolvers": "^5.2.2",
555 "@shikijs/langs": "^4.0.2",525 "@shikijs/langs": "^4.0.2",
556 "@shikijs/themes": "^4.0.2",526 "@shikijs/themes": "^4.0.2",
@@ -558,6 +528,7 @@ · 1 unmodified line
558 "clsx": "^2.1.1",528 "clsx": "^2.1.1",
559 "cmdk": "^1.1.1",529 "cmdk": "^1.1.1",
560 "date-fns": "^4.1.0",530 "date-fns": "^4.1.0",
531 "effect": "catalog:",
561 "embla-carousel-react": "^8.6.0",532 "embla-carousel-react": "^8.6.0",
562 "input-otp": "^1.4.2",533 "input-otp": "^1.4.2",
563 "lucide-react": "^1.7.0",534 "lucide-react": "^1.7.0",
@@ -576,6 +547,7 @@ · 12 unmodified lines
576 "zod": "^4.3.6",547 "zod": "^4.3.6",
577 },548 },
578 "devDependencies": {549 "devDependencies": {
550 "@types/node": "catalog:",
579 "@types/react": "^19.1.0",551 "@types/react": "^19.1.0",
580 "hast-util-to-jsx-runtime": "^2.3.6",552 "hast-util-to-jsx-runtime": "^2.3.6",
581 "tailwindcss": "^4.1.10",553 "tailwindcss": "^4.1.10",
@@ -885,7 +857,7 @@ · 303 unmodified lines
885 857
886 "@executor/plugin-openapi": ["@executor/plugin-openapi@workspace:packages/plugins/openapi"],858 "@executor/plugin-openapi": ["@executor/plugin-openapi@workspace:packages/plugins/openapi"],
887 859
888 "@executor/react": ["@executor/react@workspace:packages/clients/react"],860 "@executor/react": ["@executor/react@workspace:packages/react"],
889 861
890 "@executor/runtime-deno-subprocess": ["@executor/runtime-deno-subprocess@workspace:packages/kernel/runtime-deno-subprocess"],862 "@executor/runtime-deno-subprocess": ["@executor/runtime-deno-subprocess@workspace:packages/kernel/runtime-deno-subprocess"],
891 863
@@ -897,8 +869,6 @@ · 5 unmodified lines
897 869
898 "@executor/storage-postgres": ["@executor/storage-postgres@workspace:packages/core/storage-postgres"],870 "@executor/storage-postgres": ["@executor/storage-postgres@workspace:packages/core/storage-postgres"],
899 871
900 "@executor/ui": ["@executor/ui@workspace:packages/ui"],
901
902 "@floating-ui/core": ["@floating-ui/core@1.7.5", "", { "dependencies": { "@floating-ui/utils": "^0.2.11" } }, "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ=="],872 "@floating-ui/core": ["@floating-ui/core@1.7.5", "", { "dependencies": { "@floating-ui/utils": "^0.2.11" } }, "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ=="],
903 873
904 "@floating-ui/dom": ["@floating-ui/dom@1.7.6", "", { "dependencies": { "@floating-ui/core": "^1.7.5", "@floating-ui/utils": "^0.2.11" } }, "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ=="],874 "@floating-ui/dom": ["@floating-ui/dom@1.7.6", "", { "dependencies": { "@floating-ui/core": "^1.7.5", "@floating-ui/utils": "^0.2.11" } }, "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ=="],
package.json+1−1
@@ -24,7 +24,7 @@ · 23 unmodified lines
24 "packageManager": "bun@1.3.11",24 "packageManager": "bun@1.3.11",
25 "workspaces": [25 "workspaces": [
26 "packages/*/*",26 "packages/*/*",
27 "packages/ui",27 "packages/react",
28 "apps/*"28 "apps/*"
29 ],29 ],
30 "catalog": {30 "catalog": {
packages/clients/react/CHANGELOG.md+0−4
@@ -1,4 +0,0 @@
1# @executor/react changelog
2
3This file exists for Changesets release workflow compatibility.
4Canonical user-facing release notes are published on GitHub Releases.
packages/clients/react/package.json+0−27
@@ -1,27 +0,0 @@
1{
2 "name": "@executor/react",
3 "version": "1.4.0",
4 "private": true,
5 "type": "module",
6 "exports": {
7 ".": "./src/index.ts"
8 },
9 "dependencies": {
10 "@effect/platform": "catalog:",
11 "@effect-atom/atom": "^0.5.3",
12 "@effect-atom/atom-react": "^0.5.0",
13 "@executor/api": "workspace:*",
14 "@executor/ui": "workspace:*",
15 "@executor/sdk": "workspace:*",
16 "effect": "catalog:",
17 "react": "^19.1.0"
18 },
19 "devDependencies": {
20 "@types/react": "^19.1.0",
21 "@types/node": "catalog:",
22 "typescript": "^5.9.3"
23 },
24 "scripts": {
25 "typecheck": "tsc --noEmit"
26 }
27}
packages/clients/react/src/index.ts+0−54
@@ -1,54 +0,0 @@
1// Re-export effect-atom essentials so consumers don't need direct deps
2export {
3 Atom,
4 AtomHttpApi,
5 Result,
6 RegistryContext,
7 RegistryProvider,
8 useAtom,
9 useAtomMount,
10 useAtomRefresh,
11 useAtomSet,
12 useAtomSuspense,
13 useAtomValue,
14} from "@effect-atom/atom-react";
15
16// Base URL management
17export { getBaseUrl, setBaseUrl } from "./base-url";
18
19// Typed API client
20export { ExecutorApiClient } from "./client";
21
22// Query & mutation atoms
23export {
24 toolsAtom,
25 sourceToolsAtom,
26 toolSchemaAtom,
27 sourcesAtom,
28 sourceAtom,
29 secretsAtom,
30 secretStatusAtom,
31 setSecret,
32 resolveSecret,
33 removeSecret,
34 removeSource,
35 refreshSource,
36 detectSource,
37} from "./atoms";
38
39// Scope hook
40export { useScope, useScopeInfo } from "./use-scope";
41export type { ScopeInfo } from "./use-scope";
42
43// Provider
44export { ExecutorProvider } from "./provider";
45export { SecretPicker } from "./secret-picker";
46export type { SecretPickerSecret } from "./secret-picker";
47
48// Re-export commonly needed SDK types
49export { ScopeId, ToolId } from "@executor/sdk";
50export type { ScopeId as ScopeIdType, ToolId as ToolIdType } from "@executor/sdk";
51
52// Plugin contracts
53export type { SourcePlugin, SourcePreset } from "./source-plugin";
54export type { SecretProviderPlugin } from "./secret-provider-plugin";
packages/clients/react/src/use-scope.ts+0−2
@@ -1,2 +0,0 @@
1export { useScope, useScopeInfo } from "./scope-context";
2export type { ScopeInfo } from "./scope-context";
packages/plugins/google-discovery/package.json+1−6
@@ -24,8 +24,7 @@ · 23 unmodified lines
24 "react": "^19.1.0",24 "react": "^19.1.0",
25 "@effect-atom/atom-react": "^0.5.0",25 "@effect-atom/atom-react": "^0.5.0",
26 "@tanstack/react-router": "^1.168.10",26 "@tanstack/react-router": "^1.168.10",
27 "@executor/react": "workspace:*",27 "@executor/react": "workspace:*"
28 "@executor/ui": "workspace:*"
29 },28 },
30 "peerDependenciesMeta": {29 "peerDependenciesMeta": {
31 "react": {30 "react": {
@@ -39,16 +38,12 @@ · 7 unmodified lines
39 },38 },
40 "@executor/react": {39 "@executor/react": {
41 "optional": true40 "optional": true
42 },
43 "@executor/ui": {
44 "optional": true
45 }41 }
46 },42 },
47 "devDependencies": {43 "devDependencies": {
48 "@effect-atom/atom-react": "^0.5.0",44 "@effect-atom/atom-react": "^0.5.0",
49 "@effect/vitest": "catalog:",45 "@effect/vitest": "catalog:",
50 "@executor/react": "workspace:*",46 "@executor/react": "workspace:*",
51 "@executor/ui": "workspace:*",
52 "@types/node": "catalog:",47 "@types/node": "catalog:",
53 "@types/react": "^19.1.0",48 "@types/react": "^19.1.0",
54 "bun-types": "catalog:",49 "bun-types": "catalog:",
packages/plugins/google-discovery/src/react/AddGoogleDiscoverySource.tsx+10−14
@@ -1,25 +1,21 @@
1import { useCallback, useEffect, useMemo, useRef, useState } from "react";1import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2import { useAtomSet, useAtomValue, useAtomRefresh, Result } from "@effect-atom/atom-react";2import { useAtomSet, useAtomValue, useAtomRefresh, Result } from "@effect-atom/atom-react";
3 3
4import {4import { secretsAtom, setSecret } from "@executor/react/api/atoms";
5 useScope,5import { useScope } from "@executor/react/api/scope-context";
6 SecretPicker,6import { SecretPicker, type SecretPickerSecret } from "@executor/react/plugins/secret-picker";
7 secretsAtom,
8 setSecret,
9 type SecretPickerSecret,
10} from "@executor/react";
11import { SecretId } from "@executor/sdk";7import { SecretId } from "@executor/sdk";
12import { Badge } from "@executor/ui/components/badge";8import { Badge } from "@executor/react/components/badge";
13import { Button } from "@executor/ui/components/button";9import { Button } from "@executor/react/components/button";
14import {10import {
15 Collapsible,11 Collapsible,
16 CollapsibleContent,12 CollapsibleContent,
17 CollapsibleTrigger,13 CollapsibleTrigger,
18} from "@executor/ui/components/collapsible";14} from "@executor/react/components/collapsible";
19import { Input } from "@executor/ui/components/input";15import { Input } from "@executor/react/components/input";
20import { Label } from "@executor/ui/components/label";16import { Label } from "@executor/react/components/label";
21import { RadioGroup, RadioGroupItem } from "@executor/ui/components/radio-group";17import { RadioGroup, RadioGroupItem } from "@executor/react/components/radio-group";
22import { Spinner } from "@executor/ui/components/spinner";18import { Spinner } from "@executor/react/components/spinner";
23import {19import {
24 addGoogleDiscoverySource,20 addGoogleDiscoverySource,
25 probeGoogleDiscovery,21 probeGoogleDiscovery,
packages/plugins/google-discovery/src/react/EditGoogleDiscoverySource.tsx+2−2
@@ -1,5 +1,5 @@
1import { Badge } from "@executor/ui/components/badge";1import { Badge } from "@executor/react/components/badge";
2import { Button } from "@executor/ui/components/button";2import { Button } from "@executor/react/components/button";
3 3
4export default function EditGoogleDiscoverySource({4export default function EditGoogleDiscoverySource({
5 sourceId,5 sourceId,
packages/plugins/google-discovery/src/react/GoogleDiscoverySourceSummary.tsx+1−1
@@ -1,4 +1,4 @@
1import { Badge } from "@executor/ui/components/badge";1import { Badge } from "@executor/react/components/badge";
2 2
3export default function GoogleDiscoverySourceSummary({3export default function GoogleDiscoverySourceSummary({
4 sourceId,4 sourceId,
packages/plugins/google-discovery/src/react/client.ts+1−1
@@ -1,7 +1,7 @@
1import { AtomHttpApi } from "@effect-atom/atom-react";1import { AtomHttpApi } from "@effect-atom/atom-react";
2import { FetchHttpClient } from "@effect/platform";2import { FetchHttpClient } from "@effect/platform";
3import { addGroup } from "@executor/api";3import { addGroup } from "@executor/api";
4import { getBaseUrl } from "@executor/react";4import { getBaseUrl } from "@executor/react/api/base-url";
5import { GoogleDiscoveryGroup } from "../api/group";5import { GoogleDiscoveryGroup } from "../api/group";
6 6
7const GoogleDiscoveryApi = addGroup(GoogleDiscoveryGroup);7const GoogleDiscoveryApi = addGroup(GoogleDiscoveryGroup);
packages/plugins/google-discovery/src/react/source-plugin.ts+1−1
@@ -1,5 +1,5 @@
1import { lazy } from "react";1import { lazy } from "react";
2import type { SourcePlugin } from "@executor/react";2import type { SourcePlugin } from "@executor/react/plugins/source-plugin";
3import { googleDiscoveryPresets } from "../sdk/presets";3import { googleDiscoveryPresets } from "../sdk/presets";
4 4
5export const googleDiscoverySourcePlugin: SourcePlugin = {5export const googleDiscoverySourcePlugin: SourcePlugin = {
packages/plugins/graphql/package.json+1−6
@@ -25,8 +25,7 @@ · 24 unmodified lines
25 "@effect-atom/atom-react": "^0.5.0",25 "@effect-atom/atom-react": "^0.5.0",
26 "@tanstack/react-router": "^1.168.10",26 "@tanstack/react-router": "^1.168.10",
27 "@executor/api": "workspace:*",27 "@executor/api": "workspace:*",
28 "@executor/react": "workspace:*",28 "@executor/react": "workspace:*"
29 "@executor/ui": "workspace:*"
30 },29 },
31 "peerDependenciesMeta": {30 "peerDependenciesMeta": {
32 "react": {31 "react": {
@@ -43,9 +42,6 @@ · 10 unmodified lines
43 },42 },
44 "@executor/react": {43 "@executor/react": {
45 "optional": true44 "optional": true
46 },
47 "@executor/ui": {
48 "optional": true
49 }45 }
50 },46 },
51 "devDependencies": {47 "devDependencies": {
@@ -53,7 +49,6 @@ · 1 unmodified line
53 "@effect-atom/atom-react": "^0.5.0",49 "@effect-atom/atom-react": "^0.5.0",
54 "@executor/api": "workspace:*",50 "@executor/api": "workspace:*",
55 "@executor/react": "workspace:*",51 "@executor/react": "workspace:*",
56 "@executor/ui": "workspace:*",
57 "@types/react": "^19.1.0",52 "@types/react": "^19.1.0",
58 "@effect/vitest": "catalog:",53 "@effect/vitest": "catalog:",
59 "@types/node": "catalog:",54 "@types/node": "catalog:",
packages/plugins/graphql/src/react/AddGraphqlSource.tsx+7−11
@@ -1,18 +1,14 @@
1import { useState } from "react";1import { useState } from "react";
2import { useAtomSet, useAtomValue, useAtomRefresh, Result } from "@effect-atom/atom-react";2import { useAtomSet, useAtomValue, useAtomRefresh, Result } from "@effect-atom/atom-react";
3 3
4import {4import { secretsAtom, setSecret } from "@executor/react/api/atoms";
5 secretsAtom,5import { useScope } from "@executor/react/api/scope-context";
6 setSecret,6import { SecretPicker, type SecretPickerSecret } from "@executor/react/plugins/secret-picker";
7 useScope,
8 SecretPicker,
9 type SecretPickerSecret,
10} from "@executor/react";
11import { SecretId } from "@executor/sdk";7import { SecretId } from "@executor/sdk";
12import { Button } from "@executor/ui/components/button";8import { Button } from "@executor/react/components/button";
13import { Input } from "@executor/ui/components/input";9import { Input } from "@executor/react/components/input";
14import { Label } from "@executor/ui/components/label";10import { Label } from "@executor/react/components/label";
15import { Spinner } from "@executor/ui/components/spinner";11import { Spinner } from "@executor/react/components/spinner";
16import { addGraphqlSource } from "./atoms";12import { addGraphqlSource } from "./atoms";
17import type { HeaderValue } from "../sdk/types";13import type { HeaderValue } from "../sdk/types";
18 14
packages/plugins/graphql/src/react/client.ts+1−1
@@ -1,7 +1,7 @@
1import { AtomHttpApi } from "@effect-atom/atom-react";1import { AtomHttpApi } from "@effect-atom/atom-react";
2import { FetchHttpClient } from "@effect/platform";2import { FetchHttpClient } from "@effect/platform";
3import { addGroup } from "@executor/api";3import { addGroup } from "@executor/api";
4import { getBaseUrl } from "@executor/react";4import { getBaseUrl } from "@executor/react/api/base-url";
5import { GraphqlGroup } from "../api/group";5import { GraphqlGroup } from "../api/group";
6 6
7// ---------------------------------------------------------------------------7// ---------------------------------------------------------------------------
packages/plugins/graphql/src/react/source-plugin.ts+1−1
@@ -1,5 +1,5 @@
1import { lazy } from "react";1import { lazy } from "react";
2import type { SourcePlugin } from "@executor/react";2import type { SourcePlugin } from "@executor/react/plugins/source-plugin";
3import { graphqlPresets } from "../sdk/presets";3import { graphqlPresets } from "../sdk/presets";
4 4
5export const graphqlSourcePlugin: SourcePlugin = {5export const graphqlSourcePlugin: SourcePlugin = {
packages/plugins/mcp/package.json+1−6
@@ -26,8 +26,7 @@ · 25 unmodified lines
26 "@effect-atom/atom-react": "^0.5.0",26 "@effect-atom/atom-react": "^0.5.0",
27 "@tanstack/react-router": "^1.168.10",27 "@tanstack/react-router": "^1.168.10",
28 "@executor/api": "workspace:*",28 "@executor/api": "workspace:*",
29 "@executor/react": "workspace:*",29 "@executor/react": "workspace:*"
30 "@executor/ui": "workspace:*"
31 },30 },
32 "peerDependenciesMeta": {31 "peerDependenciesMeta": {
33 "react": {32 "react": {
@@ -44,9 +43,6 @@ · 10 unmodified lines
44 },43 },
45 "@executor/react": {44 "@executor/react": {
46 "optional": true45 "optional": true
47 },
48 "@executor/ui": {
49 "optional": true
50 }46 }
51 },47 },
52 "devDependencies": {48 "devDependencies": {
@@ -54,7 +50,6 @@ · 1 unmodified line
54 "@effect-atom/atom-react": "^0.5.0",50 "@effect-atom/atom-react": "^0.5.0",
55 "@executor/api": "workspace:*",51 "@executor/api": "workspace:*",
56 "@executor/react": "workspace:*",52 "@executor/react": "workspace:*",
57 "@executor/ui": "workspace:*",
58 "@types/react": "^19.1.0",53 "@types/react": "^19.1.0",
59 "@effect/vitest": "catalog:",54 "@effect/vitest": "catalog:",
60 "@types/node": "catalog:",55 "@types/node": "catalog:",
packages/plugins/mcp/src/react/AddMcpSource.tsx+6−6
@@ -1,12 +1,12 @@
1import { useReducer, useCallback, useEffect, useRef, useState } from "react";1import { useReducer, useCallback, useEffect, useRef, useState } from "react";
2import { useAtomSet } from "@effect-atom/atom-react";2import { useAtomSet } from "@effect-atom/atom-react";
3 3
4import { useScope } from "@executor/react";4import { useScope } from "@executor/react/api/scope-context";
5import { Button } from "@executor/ui/components/button";5import { Button } from "@executor/react/components/button";
6import { Input } from "@executor/ui/components/input";6import { Input } from "@executor/react/components/input";
7import { Label } from "@executor/ui/components/label";7import { Label } from "@executor/react/components/label";
8import { Badge } from "@executor/ui/components/badge";8import { Badge } from "@executor/react/components/badge";
9import { Spinner } from "@executor/ui/components/spinner";9import { Spinner } from "@executor/react/components/spinner";
10import { probeMcpEndpoint, addMcpSource, startMcpOAuth } from "./atoms";10import { probeMcpEndpoint, addMcpSource, startMcpOAuth } from "./atoms";
11import { mcpPresets, type McpPreset } from "../sdk/presets";11import { mcpPresets, type McpPreset } from "../sdk/presets";
12 12
packages/plugins/mcp/src/react/EditMcpSource.tsx+2−2
@@ -1,5 +1,5 @@
1import { Button } from "@executor/ui/components/button";1import { Button } from "@executor/react/components/button";
2import { Badge } from "@executor/ui/components/badge";2import { Badge } from "@executor/react/components/badge";
3 3
4// ---------------------------------------------------------------------------4// ---------------------------------------------------------------------------
5// Edit MCP Source — config view for an existing MCP source5// Edit MCP Source — config view for an existing MCP source
packages/plugins/mcp/src/react/McpSourceSummary.tsx+1−1
@@ -1,4 +1,4 @@
1import { Badge } from "@executor/ui/components/badge";1import { Badge } from "@executor/react/components/badge";
2 2
3// ---------------------------------------------------------------------------3// ---------------------------------------------------------------------------
4// MCP Source Summary — shown in the source list4// MCP Source Summary — shown in the source list
packages/plugins/mcp/src/react/client.ts+1−1
@@ -1,7 +1,7 @@
1import { AtomHttpApi } from "@effect-atom/atom-react";1import { AtomHttpApi } from "@effect-atom/atom-react";
2import { FetchHttpClient } from "@effect/platform";2import { FetchHttpClient } from "@effect/platform";
3import { addGroup } from "@executor/api";3import { addGroup } from "@executor/api";
4import { getBaseUrl } from "@executor/react";4import { getBaseUrl } from "@executor/react/api/base-url";
5import { McpGroup } from "../api/group";5import { McpGroup } from "../api/group";
6 6
7// ---------------------------------------------------------------------------7// ---------------------------------------------------------------------------
packages/plugins/mcp/src/react/source-plugin.ts+1−1
@@ -1,5 +1,5 @@
1import { lazy } from "react";1import { lazy } from "react";
2import type { SourcePlugin } from "@executor/react";2import type { SourcePlugin } from "@executor/react/plugins/source-plugin";
3import { mcpPresets } from "../sdk/presets";3import { mcpPresets } from "../sdk/presets";
4 4
5export const mcpSourcePlugin: SourcePlugin = {5export const mcpSourcePlugin: SourcePlugin = {
packages/plugins/onepassword/package.json+1−5
@@ -33,8 +33,7 @@ · 32 unmodified lines
33 "peerDependencies": {33 "peerDependencies": {
34 "react": ">=18",34 "react": ">=18",
35 "@effect-atom/atom-react": "^0.5.0",35 "@effect-atom/atom-react": "^0.5.0",
36 "@executor/react": "workspace:*",36 "@executor/react": "workspace:*"
37 "@executor/ui": "workspace:*"
38 },37 },
39 "peerDependenciesMeta": {38 "peerDependenciesMeta": {
40 "react": {39 "react": {
@@ -45,9 +44,6 @@ · 4 unmodified lines
45 },44 },
46 "@executor/react": {45 "@executor/react": {
47 "optional": true46 "optional": true
48 },
49 "@executor/ui": {
50 "optional": true
51 }47 }
52 }48 }
53}49}
packages/plugins/onepassword/src/react/OnePasswordSettings.tsx+6−6
@@ -1,17 +1,17 @@
1import { useState } from "react";1import { useState } from "react";
2import { useAtomSet, useAtomValue, useAtomRefresh } from "@effect-atom/atom-react";2import { useAtomSet, useAtomValue, useAtomRefresh } from "@effect-atom/atom-react";
3import { Result } from "@effect-atom/atom-react";3import { Result } from "@effect-atom/atom-react";
4import { useScope } from "@executor/react";4import { useScope } from "@executor/react/api/scope-context";
5import { Button } from "@executor/ui/components/button";5import { Button } from "@executor/react/components/button";
6import { Input } from "@executor/ui/components/input";6import { Input } from "@executor/react/components/input";
7import { Label } from "@executor/ui/components/label";7import { Label } from "@executor/react/components/label";
8import {8import {
9 Select,9 Select,
10 SelectContent,10 SelectContent,
11 SelectItem,11 SelectItem,
12 SelectTrigger,12 SelectTrigger,
13 SelectValue,13 SelectValue,
14} from "@executor/ui/components/select";14} from "@executor/react/components/select";
15import {15import {
16 Dialog,16 Dialog,
17 DialogContent,17 DialogContent,
@@ -20,7 +20,7 @@ import { · 2 unmodified lines
20 DialogDescription,20 DialogDescription,
21 DialogFooter,21 DialogFooter,
22 DialogClose,22 DialogClose,
23} from "@executor/ui/components/dialog";23} from "@executor/react/components/dialog";
24 24
25import {25import {
26 onepasswordConfigAtom,26 onepasswordConfigAtom,
packages/plugins/onepassword/src/react/client.ts+1−1
@@ -1,7 +1,7 @@
1import { AtomHttpApi } from "@effect-atom/atom-react";1import { AtomHttpApi } from "@effect-atom/atom-react";
2import { FetchHttpClient } from "@effect/platform";2import { FetchHttpClient } from "@effect/platform";
3import { addGroup } from "@executor/api";3import { addGroup } from "@executor/api";
4import { getBaseUrl } from "@executor/react";4import { getBaseUrl } from "@executor/react/api/base-url";
5import { OnePasswordGroup } from "../api/group";5import { OnePasswordGroup } from "../api/group";
6 6
7// ---------------------------------------------------------------------------7// ---------------------------------------------------------------------------
packages/plugins/onepassword/src/react/secret-provider-plugin.ts+1−1
@@ -1,5 +1,5 @@
1import { lazy } from "react";1import { lazy } from "react";
2import type { SecretProviderPlugin } from "@executor/react";2import type { SecretProviderPlugin } from "@executor/react/plugins/secret-provider-plugin";
3 3
4export const onePasswordSecretProviderPlugin: SecretProviderPlugin = {4export const onePasswordSecretProviderPlugin: SecretProviderPlugin = {
5 key: "onepassword",5 key: "onepassword",
packages/plugins/openapi/package.json+1−6
@@ -28,8 +28,7 @@ · 27 unmodified lines
28 "@effect-atom/atom-react": "^0.5.0",28 "@effect-atom/atom-react": "^0.5.0",
29 "@tanstack/react-router": "^1.168.10",29 "@tanstack/react-router": "^1.168.10",
30 "@executor/api": "workspace:*",30 "@executor/api": "workspace:*",
31 "@executor/react": "workspace:*",31 "@executor/react": "workspace:*"
32 "@executor/ui": "workspace:*"
33 },32 },
34 "peerDependenciesMeta": {33 "peerDependenciesMeta": {
35 "react": {34 "react": {
@@ -46,9 +45,6 @@ · 10 unmodified lines
46 },45 },
47 "@executor/react": {46 "@executor/react": {
48 "optional": true47 "optional": true
49 },
50 "@executor/ui": {
51 "optional": true
52 }48 }
53 },49 },
54 "devDependencies": {50 "devDependencies": {
@@ -56,7 +52,6 @@ · 1 unmodified line
56 "@effect-atom/atom-react": "^0.5.0",52 "@effect-atom/atom-react": "^0.5.0",
57 "@executor/api": "workspace:*",53 "@executor/api": "workspace:*",
58 "@executor/react": "workspace:*",54 "@executor/react": "workspace:*",
59 "@executor/ui": "workspace:*",
60 "@types/react": "^19.1.0",55 "@types/react": "^19.1.0",
61 "@effect/vitest": "catalog:",56 "@effect/vitest": "catalog:",
62 "@types/node": "catalog:",57 "@types/node": "catalog:",
packages/plugins/openapi/src/react/AddOpenApiSource.tsx+10−15
@@ -2,22 +2,17 @@ import { useState, useEffect, useRef } from "react"; · 1 unmodified line
2import { useAtomSet, useAtomValue, useAtomRefresh, Result } from "@effect-atom/atom-react";2import { useAtomSet, useAtomValue, useAtomRefresh, Result } from "@effect-atom/atom-react";
3import { Option } from "effect";3import { Option } from "effect";
4 4
5import {5import { secretsAtom, setSecret, resolveSecret } from "@executor/react/api/atoms";
6 secretsAtom,6import { useScope } from "@executor/react/api/scope-context";
7 setSecret,7import { SecretPicker, type SecretPickerSecret } from "@executor/react/plugins/secret-picker";
8 resolveSecret,
9 useScope,
10 SecretPicker,
11 type SecretPickerSecret,
12} from "@executor/react";
13import { SecretId } from "@executor/sdk";8import { SecretId } from "@executor/sdk";
14import { Button } from "@executor/ui/components/button";9import { Button } from "@executor/react/components/button";
15import { Input } from "@executor/ui/components/input";10import { Input } from "@executor/react/components/input";
16import { Label } from "@executor/ui/components/label";11import { Label } from "@executor/react/components/label";
17import { Textarea } from "@executor/ui/components/textarea";12import { Textarea } from "@executor/react/components/textarea";
18import { Badge } from "@executor/ui/components/badge";13import { Badge } from "@executor/react/components/badge";
19import { RadioGroup, RadioGroupItem } from "@executor/ui/components/radio-group";14import { RadioGroup, RadioGroupItem } from "@executor/react/components/radio-group";
20import { Spinner } from "@executor/ui/components/spinner";15import { Spinner } from "@executor/react/components/spinner";
21import { previewOpenApiSpec, addOpenApiSpec } from "./atoms";16import { previewOpenApiSpec, addOpenApiSpec } from "./atoms";
22import type { SpecPreview, HeaderPreset } from "../sdk/preview";17import type { SpecPreview, HeaderPreset } from "../sdk/preview";
23import type { HeaderValue } from "../sdk/types";18import type { HeaderValue } from "../sdk/types";
packages/plugins/openapi/src/react/client.ts+1−1
@@ -1,7 +1,7 @@
1import { AtomHttpApi } from "@effect-atom/atom-react";1import { AtomHttpApi } from "@effect-atom/atom-react";
2import { FetchHttpClient } from "@effect/platform";2import { FetchHttpClient } from "@effect/platform";
3import { addGroup } from "@executor/api";3import { addGroup } from "@executor/api";
4import { getBaseUrl } from "@executor/react";4import { getBaseUrl } from "@executor/react/api/base-url";
5import { OpenApiGroup } from "../api/group";5import { OpenApiGroup } from "../api/group";
6 6
7// ---------------------------------------------------------------------------7// ---------------------------------------------------------------------------
packages/plugins/openapi/src/react/source-plugin.ts+1−1
@@ -1,5 +1,5 @@
1import { lazy } from "react";1import { lazy } from "react";
2import type { SourcePlugin } from "@executor/react";2import type { SourcePlugin } from "@executor/react/plugins/source-plugin";
3import { openApiPresets } from "../sdk/presets";3import { openApiPresets } from "../sdk/presets";
4 4
5export const openApiSourcePlugin: SourcePlugin = {5export const openApiSourcePlugin: SourcePlugin = {
packages/react/package.jsonrenamed from packages/ui/package.json+11−1
@@ -1,9 +1,12 @@
1{1{
2 "name": "@executor/ui",2 "name": "@executor/react",
3 "version": "1.4.0",3 "version": "1.4.0",
4 "private": true,4 "private": true,
5 "type": "module",5 "type": "module",
6 "exports": {6 "exports": {
7 "./api/*": "./src/api/*.tsx",
8 "./plugins/*": "./src/plugins/*.tsx",
9 "./pages/*": "./src/pages/*.tsx",
7 "./components/*": "./src/components/*.tsx",10 "./components/*": "./src/components/*.tsx",
8 "./hooks/*": "./src/hooks/*.ts",11 "./hooks/*": "./src/hooks/*.ts",
9 "./lib/*": "./src/lib/*.ts",12 "./lib/*": "./src/lib/*.ts",
@@ -11,6 +14,11 @@ · 1 unmodified line
11 },14 },
12 "dependencies": {15 "dependencies": {
13 "@base-ui/react": "^1.3.0",16 "@base-ui/react": "^1.3.0",
17 "@effect/platform": "catalog:",
18 "@effect-atom/atom": "^0.5.3",
19 "@effect-atom/atom-react": "^0.5.0",
20 "@executor/api": "workspace:*",
21 "@executor/sdk": "workspace:*",
14 "@hookform/resolvers": "^5.2.2",22 "@hookform/resolvers": "^5.2.2",
15 "@shikijs/langs": "^4.0.2",23 "@shikijs/langs": "^4.0.2",
16 "@shikijs/themes": "^4.0.2",24 "@shikijs/themes": "^4.0.2",
@@ -18,6 +26,7 @@ · 1 unmodified line
18 "clsx": "^2.1.1",26 "clsx": "^2.1.1",
19 "cmdk": "^1.1.1",27 "cmdk": "^1.1.1",
20 "date-fns": "^4.1.0",28 "date-fns": "^4.1.0",
29 "effect": "catalog:",
21 "embla-carousel-react": "^8.6.0",30 "embla-carousel-react": "^8.6.0",
22 "input-otp": "^1.4.2",31 "input-otp": "^1.4.2",
23 "lucide-react": "^1.7.0",32 "lucide-react": "^1.7.0",
@@ -37,6 +46,7 @@ · 13 unmodified lines
37 },46 },
38 "devDependencies": {47 "devDependencies": {
39 "@types/react": "^19.1.0",48 "@types/react": "^19.1.0",
49 "@types/node": "catalog:",
40 "hast-util-to-jsx-runtime": "^2.3.6",50 "hast-util-to-jsx-runtime": "^2.3.6",
41 "tailwindcss": "^4.1.10",51 "tailwindcss": "^4.1.10",
42 "typescript": "^5.9.3"52 "typescript": "^5.9.3"
packages/react/src/api/atoms.tsxrenamed from packages/clients/react/src/atoms.ts+0−0

File renamed without changes.

packages/react/src/api/base-url.tsxrenamed from packages/clients/react/src/base-url.ts+0−0

File renamed without changes.

packages/react/src/api/client.tsxrenamed from packages/clients/react/src/client.ts+0−0

File renamed without changes.

packages/react/src/api/provider.tsxrenamed from packages/clients/react/src/provider.tsx+0−0

File renamed without changes.

packages/react/src/api/scope-context.tsxrenamed from packages/clients/react/src/scope-context.tsx+0−0

File renamed without changes.

packages/react/src/components/accordion.tsxrenamed from packages/ui/src/components/accordion.tsx+1−1
@@ -2,7 +2,7 @@ import * as React from "react" · 1 unmodified line
2import { ChevronDownIcon } from "lucide-react"2import { ChevronDownIcon } from "lucide-react"
3import { Accordion as AccordionPrimitive } from "radix-ui"3import { Accordion as AccordionPrimitive } from "radix-ui"
4 4
5import { cn } from "@executor/ui/lib/utils"5import { cn } from "../lib/utils"
6 6
7function Accordion({7function Accordion({
8 ...props8 ...props
packages/react/src/components/alert-dialog.tsxrenamed from packages/ui/src/components/alert-dialog.tsx+2−2
@@ -3,8 +3,8 @@ · 2 unmodified lines
3import * as React from "react"3import * as React from "react"
4import { AlertDialog as AlertDialogPrimitive } from "radix-ui"4import { AlertDialog as AlertDialogPrimitive } from "radix-ui"
5 5
6import { cn } from "@executor/ui/lib/utils"6import { cn } from "../lib/utils"
7import { Button } from "@executor/ui/components/button"7import { Button } from "./button"
8 8
9function AlertDialog({9function AlertDialog({
10 ...props10 ...props
packages/react/src/components/alert.tsxrenamed from packages/ui/src/components/alert.tsx+1−1
@@ -1,7 +1,7 @@
1import * as React from "react"1import * as React from "react"
2import { cva, type VariantProps } from "class-variance-authority"2import { cva, type VariantProps } from "class-variance-authority"
3 3
4import { cn } from "@executor/ui/lib/utils"4import { cn } from "../lib/utils"
5 5
6const alertVariants = cva(6const alertVariants = cva(
7 "relative grid w-full grid-cols-[0_1fr] items-start gap-y-0.5 rounded-lg border px-4 py-3 text-sm has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] has-[>svg]:gap-x-3 [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",7 "relative grid w-full grid-cols-[0_1fr] items-start gap-y-0.5 rounded-lg border px-4 py-3 text-sm has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] has-[>svg]:gap-x-3 [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
packages/react/src/components/aspect-ratio.tsxrenamed from packages/ui/src/components/aspect-ratio.tsx+0−0

File renamed without changes.

packages/react/src/components/avatar.tsxrenamed from packages/ui/src/components/avatar.tsx+1−1
@@ -1,7 +1,7 @@
1import * as React from "react"1import * as React from "react"
2import { Avatar as AvatarPrimitive } from "radix-ui"2import { Avatar as AvatarPrimitive } from "radix-ui"
3 3
4import { cn } from "@executor/ui/lib/utils"4import { cn } from "../lib/utils"
5 5
6function Avatar({6function Avatar({
7 className,7 className,
packages/react/src/components/badge.tsxrenamed from packages/ui/src/components/badge.tsx+1−1
@@ -2,7 +2,7 @@ import * as React from "react" · 1 unmodified line
2import { cva, type VariantProps } from "class-variance-authority"2import { cva, type VariantProps } from "class-variance-authority"
3import { Slot } from "radix-ui"3import { Slot } from "radix-ui"
4 4
5import { cn } from "@executor/ui/lib/utils"5import { cn } from "../lib/utils"
6 6
7const badgeVariants = cva(7const badgeVariants = cva(
8 "inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3",8 "inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3",
packages/react/src/components/breadcrumb.tsxrenamed from packages/ui/src/components/breadcrumb.tsx+1−1
@@ -2,7 +2,7 @@ import * as React from "react" · 1 unmodified line
2import { ChevronRight, MoreHorizontal } from "lucide-react"2import { ChevronRight, MoreHorizontal } from "lucide-react"
3import { Slot } from "radix-ui"3import { Slot } from "radix-ui"
4 4
5import { cn } from "@executor/ui/lib/utils"5import { cn } from "../lib/utils"
6 6
7function Breadcrumb({ ...props }: React.ComponentProps<"nav">) {7function Breadcrumb({ ...props }: React.ComponentProps<"nav">) {
8 return <nav aria-label="breadcrumb" data-slot="breadcrumb" {...props} />8 return <nav aria-label="breadcrumb" data-slot="breadcrumb" {...props} />
packages/react/src/components/button-group.tsxrenamed from packages/ui/src/components/button-group.tsx+2−2
@@ -1,8 +1,8 @@
1import { cva, type VariantProps } from "class-variance-authority"1import { cva, type VariantProps } from "class-variance-authority"
2import { Slot } from "radix-ui"2import { Slot } from "radix-ui"
3 3
4import { cn } from "@executor/ui/lib/utils"4import { cn } from "../lib/utils"
5import { Separator } from "@executor/ui/components/separator"5import { Separator } from "./separator"
6 6
7const buttonGroupVariants = cva(7const buttonGroupVariants = cva(
8 "flex w-fit items-stretch has-[>[data-slot=button-group]]:gap-2 [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",8 "flex w-fit items-stretch has-[>[data-slot=button-group]]:gap-2 [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
packages/react/src/components/button.tsxrenamed from packages/ui/src/components/button.tsx+1−1
@@ -2,7 +2,7 @@ import * as React from "react" · 1 unmodified line
2import { cva, type VariantProps } from "class-variance-authority"2import { cva, type VariantProps } from "class-variance-authority"
3import { Slot } from "radix-ui"3import { Slot } from "radix-ui"
4 4
5import { cn } from "@executor/ui/lib/utils"5import { cn } from "../lib/utils"
6 6
7const buttonVariants = cva(7const buttonVariants = cva(
8 "inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",8 "inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
packages/react/src/components/calendar.tsxrenamed from packages/ui/src/components/calendar.tsx+2−2
@@ -10,8 +10,8 @@ import { · 9 unmodified lines
10 type DayButton,10 type DayButton,
11} from "react-day-picker"11} from "react-day-picker"
12 12
13import { cn } from "@executor/ui/lib/utils"13import { cn } from "../lib/utils"
14import { Button, buttonVariants } from "@executor/ui/components/button"14import { Button, buttonVariants } from "./button"
15 15
16function Calendar({16function Calendar({
17 className,17 className,
packages/react/src/components/card.tsxrenamed from packages/ui/src/components/card.tsx+1−1
@@ -1,6 +1,6 @@
1import * as React from "react"1import * as React from "react"
2 2
3import { cn } from "@executor/ui/lib/utils"3import { cn } from "../lib/utils"
4 4
5function Card({ className, ...props }: React.ComponentProps<"div">) {5function Card({ className, ...props }: React.ComponentProps<"div">) {
6 return (6 return (
packages/react/src/components/carousel.tsxrenamed from packages/ui/src/components/carousel.tsx+2−2
@@ -6,8 +6,8 @@ import useEmblaCarousel, { · 5 unmodified lines
6} from "embla-carousel-react"6} from "embla-carousel-react"
7import { ArrowLeft, ArrowRight } from "lucide-react"7import { ArrowLeft, ArrowRight } from "lucide-react"
8 8
9import { cn } from "@executor/ui/lib/utils"9import { cn } from "../lib/utils"
10import { Button } from "@executor/ui/components/button"10import { Button } from "./button"
11 11
12type CarouselApi = UseEmblaCarouselType[1]12type CarouselApi = UseEmblaCarouselType[1]
13type UseCarouselParameters = Parameters<typeof useEmblaCarousel>13type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
packages/react/src/components/chart.tsxrenamed from packages/ui/src/components/chart.tsx+1−1
@@ -2,7 +2,7 @@ import * as React from "react" · 1 unmodified line
2import * as RechartsPrimitive from "recharts"2import * as RechartsPrimitive from "recharts"
3import type { TooltipValueType } from "recharts"3import type { TooltipValueType } from "recharts"
4 4
5import { cn } from "@executor/ui/lib/utils"5import { cn } from "../lib/utils"
6 6
7// Format: { THEME_NAME: CSS_SELECTOR }7// Format: { THEME_NAME: CSS_SELECTOR }
8const THEMES = { light: "", dark: ".dark" } as const8const THEMES = { light: "", dark: ".dark" } as const
packages/react/src/components/checkbox.tsxrenamed from packages/ui/src/components/checkbox.tsx+1−1
@@ -4,7 +4,7 @@ import * as React from "react" · 3 unmodified lines
4import { CheckIcon } from "lucide-react"4import { CheckIcon } from "lucide-react"
5import { Checkbox as CheckboxPrimitive } from "radix-ui"5import { Checkbox as CheckboxPrimitive } from "radix-ui"
6 6
7import { cn } from "@executor/ui/lib/utils"7import { cn } from "../lib/utils"
8 8
9function Checkbox({9function Checkbox({
10 className,10 className,
packages/react/src/components/code-block.tsxrenamed from packages/ui/src/components/code-block.tsx+0−0

File renamed without changes.

packages/react/src/components/collapsible.tsxrenamed from packages/ui/src/components/collapsible.tsx+0−0

File renamed without changes.

packages/react/src/components/combobox.tsxrenamed from packages/ui/src/components/combobox.tsx+3−3
@@ -4,14 +4,14 @@ import * as React from "react" · 3 unmodified lines
4import { Combobox as ComboboxPrimitive } from "@base-ui/react"4import { Combobox as ComboboxPrimitive } from "@base-ui/react"
5import { CheckIcon, ChevronDownIcon, XIcon } from "lucide-react"5import { CheckIcon, ChevronDownIcon, XIcon } from "lucide-react"
6 6
7import { cn } from "@executor/ui/lib/utils"7import { cn } from "../lib/utils"
8import { Button } from "@executor/ui/components/button"8import { Button } from "./button"
9import {9import {
10 InputGroup,10 InputGroup,
11 InputGroupAddon,11 InputGroupAddon,
12 InputGroupButton,12 InputGroupButton,
13 InputGroupInput,13 InputGroupInput,
14} from "@executor/ui/components/input-group"14} from "./input-group"
15 15
16const Combobox = ComboboxPrimitive.Root16const Combobox = ComboboxPrimitive.Root
17 17
packages/react/src/components/command.tsxrenamed from packages/ui/src/components/command.tsx+2−2
@@ -4,14 +4,14 @@ import * as React from "react" · 3 unmodified lines
4import { Command as CommandPrimitive } from "cmdk"4import { Command as CommandPrimitive } from "cmdk"
5import { SearchIcon } from "lucide-react"5import { SearchIcon } from "lucide-react"
6 6
7import { cn } from "@executor/ui/lib/utils"7import { cn } from "../lib/utils"
8import {8import {
9 Dialog,9 Dialog,
10 DialogContent,10 DialogContent,
11 DialogDescription,11 DialogDescription,
12 DialogHeader,12 DialogHeader,
13 DialogTitle,13 DialogTitle,
14} from "@executor/ui/components/dialog"14} from "./dialog"
15 15
16function Command({16function Command({
17 className,17 className,
packages/react/src/components/context-menu.tsxrenamed from packages/ui/src/components/context-menu.tsx+1−1
@@ -4,7 +4,7 @@ import * as React from "react" · 3 unmodified lines
4import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"4import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
5import { ContextMenu as ContextMenuPrimitive } from "radix-ui"5import { ContextMenu as ContextMenuPrimitive } from "radix-ui"
6 6
7import { cn } from "@executor/ui/lib/utils"7import { cn } from "../lib/utils"
8 8
9function ContextMenu({9function ContextMenu({
10 ...props10 ...props
packages/react/src/components/dialog.tsxrenamed from packages/ui/src/components/dialog.tsx+2−2
@@ -2,8 +2,8 @@ import * as React from "react" · 1 unmodified line
2import { XIcon } from "lucide-react"2import { XIcon } from "lucide-react"
3import { Dialog as DialogPrimitive } from "radix-ui"3import { Dialog as DialogPrimitive } from "radix-ui"
4 4
5import { cn } from "@executor/ui/lib/utils"5import { cn } from "../lib/utils"
6import { Button } from "@executor/ui/components/button"6import { Button } from "./button"
7 7
8function Dialog({8function Dialog({
9 ...props9 ...props
packages/react/src/components/direction.tsxrenamed from packages/ui/src/components/direction.tsx+0−0

File renamed without changes.

packages/react/src/components/drawer.tsxrenamed from packages/ui/src/components/drawer.tsx+1−1
@@ -1,7 +1,7 @@
1import * as React from "react"1import * as React from "react"
2import { Drawer as DrawerPrimitive } from "vaul"2import { Drawer as DrawerPrimitive } from "vaul"
3 3
4import { cn } from "@executor/ui/lib/utils"4import { cn } from "../lib/utils"
5 5
6function Drawer({6function Drawer({
7 ...props7 ...props
packages/react/src/components/dropdown-menu.tsxrenamed from packages/ui/src/components/dropdown-menu.tsx+1−1
@@ -4,7 +4,7 @@ import * as React from "react" · 3 unmodified lines
4import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"4import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
5import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui"5import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui"
6 6
7import { cn } from "@executor/ui/lib/utils"7import { cn } from "../lib/utils"
8 8
9function DropdownMenu({9function DropdownMenu({
10 ...props10 ...props
packages/react/src/components/empty.tsxrenamed from packages/ui/src/components/empty.tsx+1−1
@@ -1,6 +1,6 @@
1import { cva, type VariantProps } from "class-variance-authority"1import { cva, type VariantProps } from "class-variance-authority"
2 2
3import { cn } from "@executor/ui/lib/utils"3import { cn } from "../lib/utils"
4 4
5function Empty({ className, ...props }: React.ComponentProps<"div">) {5function Empty({ className, ...props }: React.ComponentProps<"div">) {
6 return (6 return (
packages/react/src/components/field.tsxrenamed from packages/ui/src/components/field.tsx+3−3
@@ -3,9 +3,9 @@ · 2 unmodified lines
3import { useMemo } from "react"3import { useMemo } from "react"
4import { cva, type VariantProps } from "class-variance-authority"4import { cva, type VariantProps } from "class-variance-authority"
5 5
6import { cn } from "@executor/ui/lib/utils"6import { cn } from "../lib/utils"
7import { Label } from "@executor/ui/components/label"7import { Label } from "./label"
8import { Separator } from "@executor/ui/components/separator"8import { Separator } from "./separator"
9 9
10function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) {10function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) {
11 return (11 return (
packages/react/src/components/form.tsxrenamed from packages/ui/src/components/form.tsx+2−2
@@ -11,8 +11,8 @@ import { · 10 unmodified lines
11 type FieldValues,11 type FieldValues,
12} from "react-hook-form"12} from "react-hook-form"
13 13
14import { cn } from "@executor/ui/lib/utils"14import { cn } from "../lib/utils"
15import { Label } from "@executor/ui/components/label"15import { Label } from "./label"
16 16
17const Form = FormProvider17const Form = FormProvider
18 18
packages/react/src/components/hover-card.tsxrenamed from packages/ui/src/components/hover-card.tsx+1−1
@@ -1,7 +1,7 @@
1import * as React from "react"1import * as React from "react"
2import { HoverCard as HoverCardPrimitive } from "radix-ui"2import { HoverCard as HoverCardPrimitive } from "radix-ui"
3 3
4import { cn } from "@executor/ui/lib/utils"4import { cn } from "../lib/utils"
5 5
6function HoverCard({6function HoverCard({
7 ...props7 ...props
packages/react/src/components/input-group.tsxrenamed from packages/ui/src/components/input-group.tsx+4−4
@@ -1,10 +1,10 @@
1import * as React from "react"1import * as React from "react"
2import { cva, type VariantProps } from "class-variance-authority"2import { cva, type VariantProps } from "class-variance-authority"
3 3
4import { cn } from "@executor/ui/lib/utils"4import { cn } from "../lib/utils"
5import { Button } from "@executor/ui/components/button"5import { Button } from "./button"
6import { Input } from "@executor/ui/components/input"6import { Input } from "./input"
7import { Textarea } from "@executor/ui/components/textarea"7import { Textarea } from "./textarea"
8 8
9function InputGroup({ className, ...props }: React.ComponentProps<"div">) {9function InputGroup({ className, ...props }: React.ComponentProps<"div">) {
10 return (10 return (
packages/react/src/components/input-otp.tsxrenamed from packages/ui/src/components/input-otp.tsx+1−1
@@ -4,7 +4,7 @@ import * as React from "react" · 3 unmodified lines
4import { OTPInput, OTPInputContext } from "input-otp"4import { OTPInput, OTPInputContext } from "input-otp"
5import { MinusIcon } from "lucide-react"5import { MinusIcon } from "lucide-react"
6 6
7import { cn } from "@executor/ui/lib/utils"7import { cn } from "../lib/utils"
8 8
9function InputOTP({9function InputOTP({
10 className,10 className,
packages/react/src/components/input.tsxrenamed from packages/ui/src/components/input.tsx+1−1
@@ -1,6 +1,6 @@
1import * as React from "react"1import * as React from "react"
2 2
3import { cn } from "@executor/ui/lib/utils"3import { cn } from "../lib/utils"
4 4
5function Input({ className, type, ...props }: React.ComponentProps<"input">) {5function Input({ className, type, ...props }: React.ComponentProps<"input">) {
6 return (6 return (
packages/react/src/components/item.tsxrenamed from packages/ui/src/components/item.tsx+2−2
@@ -2,8 +2,8 @@ import * as React from "react" · 1 unmodified line
2import { cva, type VariantProps } from "class-variance-authority"2import { cva, type VariantProps } from "class-variance-authority"
3import { Slot } from "radix-ui"3import { Slot } from "radix-ui"
4 4
5import { cn } from "@executor/ui/lib/utils"5import { cn } from "../lib/utils"
6import { Separator } from "@executor/ui/components/separator"6import { Separator } from "./separator"
7 7
8function ItemGroup({ className, ...props }: React.ComponentProps<"div">) {8function ItemGroup({ className, ...props }: React.ComponentProps<"div">) {
9 return (9 return (
packages/react/src/components/kbd.tsxrenamed from packages/ui/src/components/kbd.tsx+1−1
@@ -1,4 +1,4 @@
1import { cn } from "@executor/ui/lib/utils"1import { cn } from "../lib/utils"
2 2
3function Kbd({ className, ...props }: React.ComponentProps<"kbd">) {3function Kbd({ className, ...props }: React.ComponentProps<"kbd">) {
4 return (4 return (
packages/react/src/components/label.tsxrenamed from packages/ui/src/components/label.tsx+1−1
@@ -1,7 +1,7 @@
1import * as React from "react"1import * as React from "react"
2import { Label as LabelPrimitive } from "radix-ui"2import { Label as LabelPrimitive } from "radix-ui"
3 3
4import { cn } from "@executor/ui/lib/utils"4import { cn } from "../lib/utils"
5 5
6function Label({6function Label({
7 className,7 className,
packages/react/src/components/markdown.tsxrenamed from packages/ui/src/components/markdown.tsx+0−0

File renamed without changes.

packages/react/src/components/mcp-install-card.tsxrenamed from apps/local/src/web/components/mcp-install-card.tsx+0−0

File renamed without changes.

packages/react/src/components/menubar.tsxrenamed from packages/ui/src/components/menubar.tsx+1−1
@@ -4,7 +4,7 @@ import * as React from "react" · 3 unmodified lines
4import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"4import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
5import { Menubar as MenubarPrimitive } from "radix-ui"5import { Menubar as MenubarPrimitive } from "radix-ui"
6 6
7import { cn } from "@executor/ui/lib/utils"7import { cn } from "../lib/utils"
8 8
9function Menubar({9function Menubar({
10 className,10 className,
packages/react/src/components/native-select.tsxrenamed from packages/ui/src/components/native-select.tsx+1−1
@@ -1,7 +1,7 @@
1import * as React from "react"1import * as React from "react"
2import { ChevronDownIcon } from "lucide-react"2import { ChevronDownIcon } from "lucide-react"
3 3
4import { cn } from "@executor/ui/lib/utils"4import { cn } from "../lib/utils"
5 5
6function NativeSelect({6function NativeSelect({
7 className,7 className,
packages/react/src/components/navigation-menu.tsxrenamed from packages/ui/src/components/navigation-menu.tsx+1−1
@@ -3,7 +3,7 @@ import { cva } from "class-variance-authority" · 2 unmodified lines
3import { ChevronDownIcon } from "lucide-react"3import { ChevronDownIcon } from "lucide-react"
4import { NavigationMenu as NavigationMenuPrimitive } from "radix-ui"4import { NavigationMenu as NavigationMenuPrimitive } from "radix-ui"
5 5
6import { cn } from "@executor/ui/lib/utils"6import { cn } from "../lib/utils"
7 7
8function NavigationMenu({8function NavigationMenu({
9 className,9 className,
packages/react/src/components/pagination.tsxrenamed from packages/ui/src/components/pagination.tsx+2−2
@@ -5,8 +5,8 @@ import { · 4 unmodified lines
5 MoreHorizontalIcon,5 MoreHorizontalIcon,
6} from "lucide-react"6} from "lucide-react"
7 7
8import { cn } from "@executor/ui/lib/utils"8import { cn } from "../lib/utils"
9import { buttonVariants, type Button } from "@executor/ui/components/button"9import { buttonVariants, type Button } from "./button"
10 10
11function Pagination({ className, ...props }: React.ComponentProps<"nav">) {11function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
12 return (12 return (
packages/react/src/components/popover.tsxrenamed from packages/ui/src/components/popover.tsx+1−1
@@ -1,7 +1,7 @@
1import * as React from "react"1import * as React from "react"
2import { Popover as PopoverPrimitive } from "radix-ui"2import { Popover as PopoverPrimitive } from "radix-ui"
3 3
4import { cn } from "@executor/ui/lib/utils"4import { cn } from "../lib/utils"
5 5
6function Popover({6function Popover({
7 ...props7 ...props
packages/react/src/components/progress.tsxrenamed from packages/ui/src/components/progress.tsx+1−1
@@ -3,7 +3,7 @@ · 2 unmodified lines
3import * as React from "react"3import * as React from "react"
4import { Progress as ProgressPrimitive } from "radix-ui"4import { Progress as ProgressPrimitive } from "radix-ui"
5 5
6import { cn } from "@executor/ui/lib/utils"6import { cn } from "../lib/utils"
7 7
8function Progress({8function Progress({
9 className,9 className,
packages/react/src/components/radio-group.tsxrenamed from packages/ui/src/components/radio-group.tsx+1−1
@@ -2,7 +2,7 @@ import * as React from "react" · 1 unmodified line
2import { CircleIcon } from "lucide-react"2import { CircleIcon } from "lucide-react"
3import { RadioGroup as RadioGroupPrimitive } from "radix-ui"3import { RadioGroup as RadioGroupPrimitive } from "radix-ui"
4 4
5import { cn } from "@executor/ui/lib/utils"5import { cn } from "../lib/utils"
6 6
7function RadioGroup({7function RadioGroup({
8 className,8 className,
packages/react/src/components/resizable.tsxrenamed from packages/ui/src/components/resizable.tsx+1−1
@@ -3,7 +3,7 @@ · 2 unmodified lines
3import { GripVerticalIcon } from "lucide-react"3import { GripVerticalIcon } from "lucide-react"
4import * as ResizablePrimitive from "react-resizable-panels"4import * as ResizablePrimitive from "react-resizable-panels"
5 5
6import { cn } from "@executor/ui/lib/utils"6import { cn } from "../lib/utils"
7 7
8function ResizablePanelGroup({8function ResizablePanelGroup({
9 className,9 className,
packages/react/src/components/scroll-area.tsxrenamed from packages/ui/src/components/scroll-area.tsx+1−1
@@ -1,7 +1,7 @@
1import * as React from "react"1import * as React from "react"
2import { ScrollArea as ScrollAreaPrimitive } from "radix-ui"2import { ScrollArea as ScrollAreaPrimitive } from "radix-ui"
3 3
4import { cn } from "@executor/ui/lib/utils"4import { cn } from "../lib/utils"
5 5
6function ScrollArea({6function ScrollArea({
7 className,7 className,
packages/react/src/components/select.tsxrenamed from packages/ui/src/components/select.tsx+1−1
@@ -4,7 +4,7 @@ import * as React from "react" · 3 unmodified lines
4import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react"4import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react"
5import { Select as SelectPrimitive } from "radix-ui"5import { Select as SelectPrimitive } from "radix-ui"
6 6
7import { cn } from "@executor/ui/lib/utils"7import { cn } from "../lib/utils"
8 8
9function Select({9function Select({
10 ...props10 ...props
packages/react/src/components/separator.tsxrenamed from packages/ui/src/components/separator.tsx+1−1
@@ -1,7 +1,7 @@
1import * as React from "react"1import * as React from "react"
2import { Separator as SeparatorPrimitive } from "radix-ui"2import { Separator as SeparatorPrimitive } from "radix-ui"
3 3
4import { cn } from "@executor/ui/lib/utils"4import { cn } from "../lib/utils"
5 5
6function Separator({6function Separator({
7 className,7 className,
packages/react/src/components/sheet.tsxrenamed from packages/ui/src/components/sheet.tsx+1−1
@@ -4,7 +4,7 @@ import * as React from "react" · 3 unmodified lines
4import { XIcon } from "lucide-react"4import { XIcon } from "lucide-react"
5import { Dialog as SheetPrimitive } from "radix-ui"5import { Dialog as SheetPrimitive } from "radix-ui"
6 6
7import { cn } from "@executor/ui/lib/utils"7import { cn } from "../lib/utils"
8 8
9function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {9function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
10 return <SheetPrimitive.Root data-slot="sheet" {...props} />10 return <SheetPrimitive.Root data-slot="sheet" {...props} />
packages/react/src/components/sidebar.tsxrenamed from packages/ui/src/components/sidebar.tsx+8−8
@@ -3,25 +3,25 @@ import { cva, type VariantProps } from "class-variance-authority" · 2 unmodified lines
3import { PanelLeftIcon } from "lucide-react"3import { PanelLeftIcon } from "lucide-react"
4import { Slot } from "radix-ui"4import { Slot } from "radix-ui"
5 5
6import { useIsMobile } from "@executor/ui/hooks/use-mobile"6import { useIsMobile } from "../hooks/use-mobile"
7import { cn } from "@executor/ui/lib/utils"7import { cn } from "../lib/utils"
8import { Button } from "@executor/ui/components/button"8import { Button } from "./button"
9import { Input } from "@executor/ui/components/input"9import { Input } from "./input"
10import { Separator } from "@executor/ui/components/separator"10import { Separator } from "./separator"
11import {11import {
12 Sheet,12 Sheet,
13 SheetContent,13 SheetContent,
14 SheetDescription,14 SheetDescription,
15 SheetHeader,15 SheetHeader,
16 SheetTitle,16 SheetTitle,
17} from "@executor/ui/components/sheet"17} from "./sheet"
18import { Skeleton } from "@executor/ui/components/skeleton"18import { Skeleton } from "./skeleton"
19import {19import {
20 Tooltip,20 Tooltip,
21 TooltipContent,21 TooltipContent,
22 TooltipProvider,22 TooltipProvider,
23 TooltipTrigger,23 TooltipTrigger,
24} from "@executor/ui/components/tooltip"24} from "./tooltip"
25 25
26const SIDEBAR_COOKIE_NAME = "sidebar_state"26const SIDEBAR_COOKIE_NAME = "sidebar_state"
27const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 727const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
packages/react/src/components/skeleton.tsxrenamed from packages/ui/src/components/skeleton.tsx+1−1
@@ -1,4 +1,4 @@
1import { cn } from "@executor/ui/lib/utils"1import { cn } from "../lib/utils"
2 2
3function Skeleton({ className, ...props }: React.ComponentProps<"div">) {3function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
4 return (4 return (
packages/react/src/components/slider.tsxrenamed from packages/ui/src/components/slider.tsx+1−1
@@ -1,7 +1,7 @@
1import * as React from "react"1import * as React from "react"
2import { Slider as SliderPrimitive } from "radix-ui"2import { Slider as SliderPrimitive } from "radix-ui"
3 3
4import { cn } from "@executor/ui/lib/utils"4import { cn } from "../lib/utils"
5 5
6function Slider({6function Slider({
7 className,7 className,
packages/react/src/components/sonner.tsxrenamed from packages/ui/src/components/sonner.tsx+0−0

File renamed without changes.

packages/react/src/components/spinner.tsxrenamed from packages/ui/src/components/spinner.tsx+1−1
@@ -1,6 +1,6 @@
1import { Loader2Icon } from "lucide-react"1import { Loader2Icon } from "lucide-react"
2 2
3import { cn } from "@executor/ui/lib/utils"3import { cn } from "../lib/utils"
4 4
5function Spinner({ className, ...props }: React.ComponentProps<"svg">) {5function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
6 return (6 return (
packages/react/src/components/switch.tsxrenamed from packages/ui/src/components/switch.tsx+1−1
@@ -1,7 +1,7 @@
1import * as React from "react"1import * as React from "react"
2import { Switch as SwitchPrimitive } from "radix-ui"2import { Switch as SwitchPrimitive } from "radix-ui"
3 3
4import { cn } from "@executor/ui/lib/utils"4import { cn } from "../lib/utils"
5 5
6function Switch({6function Switch({
7 className,7 className,
packages/react/src/components/table.tsxrenamed from packages/ui/src/components/table.tsx+1−1
@@ -2,7 +2,7 @@ · 1 unmodified line
2 2
3import * as React from "react"3import * as React from "react"
4 4
5import { cn } from "@executor/ui/lib/utils"5import { cn } from "../lib/utils"
6 6
7function Table({ className, ...props }: React.ComponentProps<"table">) {7function Table({ className, ...props }: React.ComponentProps<"table">) {
8 return (8 return (
packages/react/src/components/tabs.tsxrenamed from packages/ui/src/components/tabs.tsx+1−1
@@ -2,7 +2,7 @@ import * as React from "react" · 1 unmodified line
2import { cva, type VariantProps } from "class-variance-authority"2import { cva, type VariantProps } from "class-variance-authority"
3import { Tabs as TabsPrimitive } from "radix-ui"3import { Tabs as TabsPrimitive } from "radix-ui"
4 4
5import { cn } from "@executor/ui/lib/utils"5import { cn } from "../lib/utils"
6 6
7function Tabs({7function Tabs({
8 className,8 className,
packages/react/src/components/textarea.tsxrenamed from packages/ui/src/components/textarea.tsx+1−1
@@ -1,6 +1,6 @@
1import * as React from "react"1import * as React from "react"
2 2
3import { cn } from "@executor/ui/lib/utils"3import { cn } from "../lib/utils"
4 4
5function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {5function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
6 return (6 return (
packages/react/src/components/toggle-group.tsxrenamed from packages/ui/src/components/toggle-group.tsx+2−2
@@ -4,8 +4,8 @@ import * as React from "react" · 3 unmodified lines
4import { type VariantProps } from "class-variance-authority"4import { type VariantProps } from "class-variance-authority"
5import { ToggleGroup as ToggleGroupPrimitive } from "radix-ui"5import { ToggleGroup as ToggleGroupPrimitive } from "radix-ui"
6 6
7import { cn } from "@executor/ui/lib/utils"7import { cn } from "../lib/utils"
8import { toggleVariants } from "@executor/ui/components/toggle"8import { toggleVariants } from "./toggle"
9 9
10const ToggleGroupContext = React.createContext<10const ToggleGroupContext = React.createContext<
11 VariantProps<typeof toggleVariants> & {11 VariantProps<typeof toggleVariants> & {
packages/react/src/components/toggle.tsxrenamed from packages/ui/src/components/toggle.tsx+1−1
@@ -4,7 +4,7 @@ import * as React from "react" · 3 unmodified lines
4import { cva, type VariantProps } from "class-variance-authority"4import { cva, type VariantProps } from "class-variance-authority"
5import { Toggle as TogglePrimitive } from "radix-ui"5import { Toggle as TogglePrimitive } from "radix-ui"
6 6
7import { cn } from "@executor/ui/lib/utils"7import { cn } from "../lib/utils"
8 8
9const toggleVariants = cva(9const toggleVariants = cva(
10 "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none hover:bg-muted hover:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",10 "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none hover:bg-muted hover:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
packages/react/src/components/tool-detail.tsxrenamed from apps/local/src/web/components/tool-detail.tsx+7−5
@@ -1,9 +1,11 @@
1import { useMemo, useState } from "react";1import { useMemo, useState } from "react";
2import { useAtomValue, toolSchemaAtom, Result, ScopeId, ToolId } from "@executor/react";2import { useAtomValue, Result } from "@effect-atom/atom-react";
3import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@executor/ui/components/accordion";3import { toolSchemaAtom } from "../api/atoms";
4import { Badge } from "@executor/ui/components/badge";4import { ScopeId, ToolId } from "@executor/sdk";
5import { CodeBlock } from "@executor/ui/components/code-block";5import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "./accordion";
6import { Markdown } from "@executor/ui/components/markdown";6import { Badge } from "./badge";
7import { CodeBlock } from "./code-block";
8import { Markdown } from "./markdown";
7 9
8// ---------------------------------------------------------------------------10// ---------------------------------------------------------------------------
9// Copy button11// Copy button
packages/react/src/components/tool-tree.tsxrenamed from apps/local/src/web/components/tool-tree.tsx+0−0

File renamed without changes.

packages/react/src/components/tooltip.tsxrenamed from packages/ui/src/components/tooltip.tsx+1−1
@@ -1,7 +1,7 @@
1import * as React from "react"1import * as React from "react"
2import { Tooltip as TooltipPrimitive } from "radix-ui"2import { Tooltip as TooltipPrimitive } from "radix-ui"
3 3
4import { cn } from "@executor/ui/lib/utils"4import { cn } from "../lib/utils"
5 5
6function TooltipProvider({6function TooltipProvider({
7 delayDuration = 0,7 delayDuration = 0,
packages/react/src/hooks/use-mobile.tsrenamed from packages/ui/src/hooks/use-mobile.ts+0−0

File renamed without changes.

packages/react/src/hooks/use-scope.ts+1−0
@@ -0,0 +1 @@
1export { useScope } from "../api/scope-context";
packages/react/src/lib/shiki.tsrenamed from packages/ui/src/lib/shiki.ts+0−0

File renamed without changes.

packages/react/src/lib/utils.tsrenamed from packages/ui/src/lib/utils.ts+0−0

File renamed without changes.

packages/react/src/pages/secrets.tsxrenamed from apps/local/src/web/pages/secrets.tsx+11−18
@@ -1,16 +1,9 @@
1import { useState, Suspense } from "react";1import { useState, Suspense } from "react";
2import {2import { useAtomValue, useAtomSet, useAtomRefresh, Result } from "@effect-atom/atom-react";
3 useAtomValue,3import { secretsAtom, setSecret, removeSecret } from "../api/atoms";
4 useAtomSet,4import type { SecretProviderPlugin } from "../plugins/secret-provider-plugin";
5 useAtomRefresh,
6 Result,
7 secretsAtom,
8 setSecret,
9 removeSecret,
10} from "@executor/react";
11import type { SecretProviderPlugin } from "@executor/react";
12import { SecretId } from "@executor/sdk";5import { SecretId } from "@executor/sdk";
13import { useScope } from "../lib/use-scope";6import { useScope } from "../hooks/use-scope";
14import { onePasswordSecretProviderPlugin } from "@executor/plugin-onepassword/react";7import { onePasswordSecretProviderPlugin } from "@executor/plugin-onepassword/react";
15import {8import {
16 Dialog,9 Dialog,
@@ -20,24 +13,24 @@ import { · 3 unmodified lines
20 DialogDescription,13 DialogDescription,
21 DialogFooter,14 DialogFooter,
22 DialogClose,15 DialogClose,
23} from "@executor/ui/components/dialog";16} from "../components/dialog";
24import { Button } from "@executor/ui/components/button";17import { Button } from "../components/button";
25import { Input } from "@executor/ui/components/input";18import { Input } from "../components/input";
26import { Label } from "@executor/ui/components/label";19import { Label } from "../components/label";
27import { Badge } from "@executor/ui/components/badge";20import { Badge } from "../components/badge";
28import {21import {
29 DropdownMenu,22 DropdownMenu,
30 DropdownMenuContent,23 DropdownMenuContent,
31 DropdownMenuItem,24 DropdownMenuItem,
32 DropdownMenuTrigger,25 DropdownMenuTrigger,
33} from "@executor/ui/components/dropdown-menu";26} from "../components/dropdown-menu";
34import {27import {
35 Select,28 Select,
36 SelectContent,29 SelectContent,
37 SelectItem,30 SelectItem,
38 SelectTrigger,31 SelectTrigger,
39 SelectValue,32 SelectValue,
40} from "@executor/ui/components/select";33} from "../components/select";
41 34
42// ---------------------------------------------------------------------------35// ---------------------------------------------------------------------------
43// Add secret dialog36// Add secret dialog
packages/react/src/pages/source-detail.tsxrenamed from apps/local/src/web/pages/source-detail.tsx+3−12
@@ -1,20 +1,11 @@
1import { useEffect, useMemo, useState } from "react";1import { useEffect, useMemo, useState } from "react";
2import { useNavigate } from "@tanstack/react-router";2import { useNavigate } from "@tanstack/react-router";
3import {3import { useAtomValue, useAtomSet, useAtomRefresh, Result } from "@effect-atom/atom-react";
4 useAtomValue,4import { sourceToolsAtom, sourcesAtom, sourceAtom, removeSource, refreshSource } from "../api/atoms";
5 useAtomSet,
6 useAtomRefresh,
7 sourceToolsAtom,
8 sourcesAtom,
9 sourceAtom,
10 removeSource,
11 refreshSource,
12 Result,
13} from "@executor/react";
14import { ToolTree } from "../components/tool-tree";5import { ToolTree } from "../components/tool-tree";
15import { ToolDetail, ToolDetailEmpty } from "../components/tool-detail";6import { ToolDetail, ToolDetailEmpty } from "../components/tool-detail";
16import type { ToolSummary } from "../components/tool-tree";7import type { ToolSummary } from "../components/tool-tree";
17import { useScope } from "../lib/use-scope";8import { useScope } from "../hooks/use-scope";
18 9
19export function SourceDetailPage(props: { namespace: string }) {10export function SourceDetailPage(props: { namespace: string }) {
20 const { namespace } = props;11 const { namespace } = props;
packages/react/src/pages/sources-add.tsxrenamed from apps/local/src/web/pages/sources-add.tsx+4−3
@@ -1,8 +1,9 @@
1import { Suspense } from "react";1import { Suspense } from "react";
2import { Link, useNavigate } from "@tanstack/react-router";2import { Link, useNavigate } from "@tanstack/react-router";
3import type { SourcePlugin } from "@executor/react";3import type { SourcePlugin } from "../plugins/source-plugin";
4import { useAtomRefresh, sourcesAtom } from "@executor/react";4import { useAtomRefresh } from "@effect-atom/atom-react";
5import { useScope } from "../lib/use-scope";5import { sourcesAtom } from "../api/atoms";
6import { useScope } from "../hooks/use-scope";
6import { openApiSourcePlugin } from "@executor/plugin-openapi/react";7import { openApiSourcePlugin } from "@executor/plugin-openapi/react";
7import { mcpSourcePlugin } from "@executor/plugin-mcp/react";8import { mcpSourcePlugin } from "@executor/plugin-mcp/react";
8import { googleDiscoverySourcePlugin } from "@executor/plugin-google-discovery/react";9import { googleDiscoverySourcePlugin } from "@executor/plugin-google-discovery/react";
packages/react/src/pages/sources.tsxrenamed from apps/local/src/web/pages/sources.tsx+4−3
@@ -1,8 +1,9 @@
1import { useState, useCallback, useMemo } from "react";1import { useState, useCallback, useMemo } from "react";
2import { Link, useNavigate } from "@tanstack/react-router";2import { Link, useNavigate } from "@tanstack/react-router";
3import { Result, useAtomValue, useAtomSet, sourcesAtom, detectSource } from "@executor/react";3import { Result, useAtomValue, useAtomSet } from "@effect-atom/atom-react";
4import { useScope } from "../lib/use-scope";4import { sourcesAtom, detectSource } from "../api/atoms";
5import type { SourcePlugin, SourcePreset } from "@executor/react";5import { useScope } from "../hooks/use-scope";
6import type { SourcePlugin, SourcePreset } from "../plugins/source-plugin";
6import { openApiSourcePlugin } from "@executor/plugin-openapi/react";7import { openApiSourcePlugin } from "@executor/plugin-openapi/react";
7import { mcpSourcePlugin } from "@executor/plugin-mcp/react";8import { mcpSourcePlugin } from "@executor/plugin-mcp/react";
8import { googleDiscoverySourcePlugin } from "@executor/plugin-google-discovery/react";9import { googleDiscoverySourcePlugin } from "@executor/plugin-google-discovery/react";
packages/react/src/pages/tools.tsxrenamed from apps/local/src/web/pages/tools.tsx+3−2
@@ -1,5 +1,6 @@
1import { useAtomValue, Result, toolsAtom } from "@executor/react";1import { useAtomValue, Result } from "@effect-atom/atom-react";
2import { useScope } from "../lib/use-scope";2import { toolsAtom } from "../api/atoms";
3import { useScope } from "../hooks/use-scope";
3 4
4export function ToolsPage() {5export function ToolsPage() {
5 const scopeId = useScope();6 const scopeId = useScope();
packages/react/src/plugins/secret-picker.tsxrenamed from packages/clients/react/src/secret-picker.tsx+3−3
@@ -1,18 +1,18 @@
1import { useState, type ChangeEvent, type FocusEvent } from "react";1import { useState, type ChangeEvent, type FocusEvent } from "react";
2 2
3import { Input } from "@executor/ui/components/input";3import { Input } from "../components/input";
4import {4import {
5 Command,5 Command,
6 CommandEmpty,6 CommandEmpty,
7 CommandGroup,7 CommandGroup,
8 CommandItem,8 CommandItem,
9 CommandList,9 CommandList,
10} from "@executor/ui/components/command";10} from "../components/command";
11import {11import {
12 Popover,12 Popover,
13 PopoverAnchor,13 PopoverAnchor,
14 PopoverContent,14 PopoverContent,
15} from "@executor/ui/components/popover";15} from "../components/popover";
16 16
17export interface SecretPickerSecret {17export interface SecretPickerSecret {
18 readonly id: string;18 readonly id: string;
packages/react/src/plugins/secret-provider-plugin.tsxrenamed from packages/clients/react/src/secret-provider-plugin.ts+0−0

File renamed without changes.

packages/react/src/plugins/source-plugin.tsxrenamed from packages/clients/react/src/source-plugin.ts+0−0

File renamed without changes.

packages/react/src/styles/globals.cssrenamed from packages/ui/src/styles/globals.css+0−0

File renamed without changes.

packages/react/tsconfig.jsonrenamed from packages/clients/react/tsconfig.json+0−0

File renamed without changes.

packages/ui/CHANGELOG.md+0−4
@@ -1,4 +0,0 @@
1# @executor/ui changelog
2
3This file exists for Changesets release workflow compatibility.
4Canonical user-facing release notes are published on GitHub Releases.
packages/ui/components.json+0−20
@@ -1,20 +0,0 @@
1{
2 "$schema": "https://ui.shadcn.com/schema.json",
3 "style": "new-york",
4 "rsc": false,
5 "tsx": true,
6 "tailwind": {
7 "config": "",
8 "css": "src/styles/globals.css",
9 "baseColor": "neutral",
10 "cssVariables": true
11 },
12 "iconLibrary": "lucide",
13 "aliases": {
14 "components": "@executor/ui/components",
15 "utils": "@executor/ui/lib/utils",
16 "hooks": "@executor/ui/hooks",
17 "lib": "@executor/ui/lib",
18 "ui": "@executor/ui/components"
19 }
20}
packages/ui/tsconfig.json+0−25
@@ -1,25 +0,0 @@
1{
2 "compilerOptions": {
3 "target": "ESNext",
4 "module": "ESNext",
5 "moduleResolution": "bundler",
6 "strict": true,
7 "esModuleInterop": true,
8 "skipLibCheck": true,
9 "outDir": "dist",
10 "rootDir": "src",
11 "declaration": true,
12 "declarationMap": true,
13 "sourceMap": true,
14 "jsx": "react-jsx",
15 "paths": {
16 "@executor/ui/*": ["./src/*"]
17 },
18 "plugins": [
19 {
20 "name": "@effect/language-service"
21 }
22 ]
23 },
24 "include": ["src"]
25}