From b380f2657f8f260bb5574d57c4d097665d2df254 Mon Sep 17 00:00:00 2001 From: Harshith Mullapudi Date: Thu, 24 Jul 2025 15:36:24 +0530 Subject: [PATCH] Feat: add mcp oauth2.1 support (#30) * Feat: add mcp oauth2.1 support * Fix: integration mcp is not loading * Feat: add slack integration --------- Co-authored-by: Manoj K --- .env.example | 2 +- apps/webapp/app/components/graph/graph.tsx | 93 +++- .../integrations/mcp-auth-section.tsx | 147 ++++-- .../app/components/integrations/section.tsx | 2 +- apps/webapp/app/components/logo/core.svg | 48 +- apps/webapp/app/components/logo/logo.tsx | 48 +- .../app/components/sidebar/app-sidebar.tsx | 1 - apps/webapp/app/components/ui/button.tsx | 4 +- apps/webapp/app/components/ui/slider.tsx | 25 + apps/webapp/app/lib/usePersistentState.ts | 44 ++ apps/webapp/app/routes/api.v1.mcp.memory.tsx | 18 +- .../app/routes/api.v1.oauth.callback.tsx | 39 +- .../app/routes/home.integration.$slug.tsx | 150 +++--- apps/webapp/app/routes/oauth.authorize.tsx | 171 ++++--- apps/webapp/app/routes/oauth.register.tsx | 59 +++ apps/webapp/app/services/oauth2.server.ts | 44 ++ apps/webapp/app/services/redirectTo.server.ts | 2 +- .../routeBuilders/apiBuilder.server.ts | 19 +- .../app/services/sessionStorage.server.ts | 2 +- apps/webapp/app/trigger/utils/mcp.ts | 27 +- .../webapp/app/trigger/utils/message-utils.ts | 17 +- apps/webapp/package.json | 5 +- apps/webapp/public/logo-dark.svg | 48 +- apps/webapp/server.mjs | 19 +- docker-compose.yaml | 23 +- docs/automation-use-cases.md | 28 -- integrations/slack/package.json | 4 +- integrations/slack/pnpm-lock.yaml | 466 +----------------- integrations/slack/spec.json | 7 +- integrations/slack/src/account-create.ts | 23 +- integrations/slack/src/create-activity.ts | 21 +- integrations/slack/src/index.ts | 10 +- package.json | 2 +- packages/core-cli/package.json | 2 +- packages/core-cli/src/cli/index.ts | 13 +- packages/core-cli/src/cli/version.ts | 1 + packages/core-cli/src/commands/init.ts | 9 + packages/core-cli/src/commands/start.ts | 19 +- packages/core-cli/src/commands/stop.ts | 20 +- packages/core-cli/src/utils/ascii.ts | 7 +- packages/core-cli/src/utils/database-init.ts | 12 +- .../core-cli/src/utils/docker-interactive.ts | 4 +- packages/core-cli/src/utils/env-docker.ts | 11 +- packages/core-cli/src/utils/trigger-deploy.ts | 1 - .../migration.sql | 10 + packages/database/prisma/schema.prisma | 10 +- .../mcp-proxy/src/core/mcp-remote-client.ts | 1 + pnpm-lock.yaml | 35 ++ trigger/.env.example | 1 - 49 files changed, 929 insertions(+), 845 deletions(-) create mode 100644 apps/webapp/app/components/ui/slider.tsx create mode 100644 apps/webapp/app/lib/usePersistentState.ts create mode 100644 apps/webapp/app/routes/oauth.register.tsx delete mode 100644 docs/automation-use-cases.md create mode 100644 packages/core-cli/src/cli/version.ts create mode 100644 packages/database/prisma/migrations/20250723162344_modify_client_for_dymanic_creation/migration.sql diff --git a/.env.example b/.env.example index d354eae..20ae561 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,4 @@ -VERSION=0.1.10 +VERSION=0.1.11 diff --git a/apps/webapp/app/components/graph/graph.tsx b/apps/webapp/app/components/graph/graph.tsx index 3cd16a9..f3063e3 100644 --- a/apps/webapp/app/components/graph/graph.tsx +++ b/apps/webapp/app/components/graph/graph.tsx @@ -5,6 +5,7 @@ import { useCallback, useImperativeHandle, forwardRef, + useState, } from "react"; import Sigma from "sigma"; import GraphologyGraph from "graphology"; @@ -186,10 +187,6 @@ export const Graph = forwardRef( } groups[key].relations.push(triplet.relation.value); groups[key].relationData.push(triplet.relation); - groups[key].label = groups[key].relations - .join(", ") - .replace("HAS_", "") - .toLowerCase(); return groups; }, @@ -216,7 +213,7 @@ export const Graph = forwardRef( }); graph.forEachEdge((edge) => { graph.setEdgeAttribute(edge, "highlighted", false); - graph.setEdgeAttribute(edge, "color", theme.link.stroke); + graph.setEdgeAttribute(edge, "color", "#0000001A"); }); selectedNodeRef.current = null; selectedEdgeRef.current = null; @@ -271,6 +268,71 @@ export const Graph = forwardRef( useImperativeHandle(ref, () => graphRefMethods.current); + // Calculate optimal ForceAtlas2 parameters based on graph properties + const calculateOptimalParameters = useCallback((graph: GraphologyGraph) => { + const nodeCount = graph.order; + const edgeCount = graph.size; + + if (nodeCount === 0) + return { scalingRatio: 30, gravity: 5, iterations: 600 }; + + // Calculate graph density (0 to 1) + const maxPossibleEdges = (nodeCount * (nodeCount - 1)) / 2; + const density = maxPossibleEdges > 0 ? edgeCount / maxPossibleEdges : 0; + + // Calculate optimal scaling ratio based on node count + // More nodes = need more space to prevent overcrowding + let scalingRatio: number; + if (nodeCount < 10) { + scalingRatio = 15; // Tight for small graphs + } else if (nodeCount < 50) { + scalingRatio = 20 + (nodeCount - 10) * 0.5; // Gradual increase + } else if (nodeCount < 200) { + scalingRatio = 40 + (nodeCount - 50) * 0.2; // Slower increase + } else { + scalingRatio = Math.min(80, 70 + (nodeCount - 200) * 0.05); // Cap at 80 + } + + // Calculate optimal gravity based on density and node count + let gravity: number; + if (density > 0.3) { + // Dense graphs need less gravity to prevent overcrowding + gravity = 1 + density * 2; + } else if (density > 0.1) { + // Medium density graphs + gravity = 3 + density * 5; + } else { + // Sparse graphs need more gravity to keep components together + gravity = Math.min(8, 5 + (1 - density) * 3); + } + + // Adjust gravity based on node count + if (nodeCount < 20) { + gravity *= 1.5; // Smaller graphs benefit from stronger gravity + } else if (nodeCount > 100) { + gravity *= 0.8; // Larger graphs need gentler gravity + } + + // Calculate iterations based on complexity + const complexity = nodeCount + edgeCount; + let iterations: number; + if (complexity < 50) { + iterations = 400; + } else if (complexity < 200) { + iterations = 600; + } else if (complexity < 500) { + iterations = 800; + } else { + iterations = Math.min(1200, 1000 + complexity * 0.2); + } + + return { + scalingRatio: Math.round(scalingRatio * 10) / 10, + gravity: Math.round(gravity * 10) / 10, + iterations: Math.round(iterations), + }; + }, []); + useEffect(() => { if (isInitializedRef.current || !containerRef.current) return; isInitializedRef.current = true; @@ -303,25 +365,28 @@ export const Graph = forwardRef( // }); // layout.start(); + // Calculate optimal parameters for this graph + const optimalParams = calculateOptimalParameters(graph); + const settings = forceAtlas2.inferSettings(graph); forceAtlas2.assign(graph, { - iterations: 600, + iterations: optimalParams.iterations, settings: { ...settings, barnesHutOptimize: true, - strongGravityMode: false, - gravity: 1, - scalingRatio: 10, - slowDown: 5, + strongGravityMode: true, + gravity: optimalParams.gravity, + scalingRatio: optimalParams.scalingRatio, + slowDown: 3, }, }); noverlap.assign(graph, { - maxIterations: 150, + maxIterations: 200, settings: { - margin: 5, - expansion: 1.1, - gridSize: 20, + margin: 10, + expansion: 1.5, + gridSize: 30, }, }); } diff --git a/apps/webapp/app/components/integrations/mcp-auth-section.tsx b/apps/webapp/app/components/integrations/mcp-auth-section.tsx index 4c7105e..541df20 100644 --- a/apps/webapp/app/components/integrations/mcp-auth-section.tsx +++ b/apps/webapp/app/components/integrations/mcp-auth-section.tsx @@ -1,12 +1,14 @@ import React, { useCallback, useState } from "react"; import { useFetcher } from "@remix-run/react"; import { Button } from "~/components/ui/button"; -import { Check } from "lucide-react"; +import { Check, Copy } from "lucide-react"; +import { Input } from "../ui/input"; interface MCPAuthSectionProps { integration: { id: string; name: string; + slug: string; }; activeAccount?: { id: string; @@ -17,6 +19,49 @@ interface MCPAuthSectionProps { hasMCPAuth: boolean; } +interface MCPUrlBoxProps { + mcpUrl: string; +} + +function MCPUrlBox({ mcpUrl }: MCPUrlBoxProps) { + const [copied, setCopied] = useState(false); + + const handleCopy = useCallback(() => { + navigator.clipboard.writeText(mcpUrl).then(() => { + setCopied(true); + setTimeout(() => setCopied(false), 2000); + }); + }, [mcpUrl]); + + return ( +
+ e.target.select()} + /> + +
+ ); +} + export function MCPAuthSection({ integration, activeAccount, @@ -26,7 +71,10 @@ export function MCPAuthSection({ const mcpFetcher = useFetcher<{ redirectURL: string }>(); const disconnectMcpFetcher = useFetcher(); - const isMCPConnected = activeAccount?.integrationConfiguration?.mcp; + const isMCPConnected = !!activeAccount?.integrationConfiguration?.mcp; + const isConnected = !!activeAccount; + + const mcpUrl = `https://core.heysol.ai/api/v1/mcp/${integration.slug}`; const handleMCPConnect = useCallback(() => { setIsMCPConnecting(true); @@ -43,7 +91,7 @@ export function MCPAuthSection({ encType: "application/json", }, ); - }, [integration.id, mcpFetcher]); + }, [integration.id, mcpFetcher, activeAccount?.id]); const handleMCPDisconnect = useCallback(() => { if (!activeAccount?.id) return; @@ -77,57 +125,78 @@ export function MCPAuthSection({ } }, [disconnectMcpFetcher.state, disconnectMcpFetcher.data]); - if (!hasMCPAuth || !activeAccount) return null; + // Show nothing if not connected at all + if (!isConnected) return null; + // Show MCP box if: + // - hasMCPAuth is true (always show MCP section) + // - OR hasMCPAuth is false but integration is connected (show MCP URL box only) return (

MCP Authentication

- {isMCPConnected ? ( -
-
-

- MCP Connected -

-

- MCP (Model Context Protocol) authentication is active + {hasMCPAuth ? ( + isMCPConnected ? ( +

+
+

+ MCP Connected +

+

+ MCP (Model Context Protocol) authentication is active +

+ +
+ +
+
+
+ ) : ( +
+

+ MCP (Model Context Protocol) Authentication +

+

+ This integration requires MCP (Model Context Protocol) + authentication. Please provide the required MCP credentials in + addition to any other authentication method.

+
-
- ) : activeAccount ? ( + ) + ) : ( + // hasMCPAuth is false, but integration is connected: show just the MCPUrlBox
-

- MCP (Model Context Protocol) Authentication -

-

- This integration requires MCP (Model Context Protocol) - authentication. Please provide the required MCP credentials in - addition to any other authentication method. -

-
- +
+

+ Integration Connected +

+

+ You can use the MCP endpoint for this integration: +

+
- ) : null} + )}
); } diff --git a/apps/webapp/app/components/integrations/section.tsx b/apps/webapp/app/components/integrations/section.tsx index d0c63fa..e92024d 100644 --- a/apps/webapp/app/components/integrations/section.tsx +++ b/apps/webapp/app/components/integrations/section.tsx @@ -14,7 +14,7 @@ export function Section({ children, }: SectionProps) { return ( -
+
{icon && <>{icon}}

{title}

diff --git a/apps/webapp/app/components/logo/core.svg b/apps/webapp/app/components/logo/core.svg index 6242699..0487725 100644 --- a/apps/webapp/app/components/logo/core.svg +++ b/apps/webapp/app/components/logo/core.svg @@ -1,16 +1,16 @@ - - - - - - - - - - - - + + + + + + + + + + + + @@ -19,18 +19,18 @@ - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/apps/webapp/app/components/logo/logo.tsx b/apps/webapp/app/components/logo/logo.tsx index 955489e..387fb70 100644 --- a/apps/webapp/app/components/logo/logo.tsx +++ b/apps/webapp/app/components/logo/logo.tsx @@ -15,7 +15,7 @@ export default function StaticLogo({ width, height }: LogoProps) { @@ -119,7 +119,7 @@ export default function StaticLogo({ width, height }: LogoProps) { ) { const user = useUser(); - console.log(user); return ( ( {...props} disabled={isLoading ?? disabled} > - {isLoading ? : <>} + {isLoading ? : <>} {children} ); diff --git a/apps/webapp/app/components/ui/slider.tsx b/apps/webapp/app/components/ui/slider.tsx new file mode 100644 index 0000000..e254007 --- /dev/null +++ b/apps/webapp/app/components/ui/slider.tsx @@ -0,0 +1,25 @@ +import * as SliderPrimitive from "@radix-ui/react-slider"; +import * as React from "react"; +import { cn } from "~/lib/utils"; + +const Slider = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + + + +)); +Slider.displayName = SliderPrimitive.Root.displayName; + +export { Slider }; diff --git a/apps/webapp/app/lib/usePersistentState.ts b/apps/webapp/app/lib/usePersistentState.ts new file mode 100644 index 0000000..0c92115 --- /dev/null +++ b/apps/webapp/app/lib/usePersistentState.ts @@ -0,0 +1,44 @@ +import { useState, useEffect } from "react"; + +/** + * A hook that persists state to localStorage + * @param key - The localStorage key to store the value under + * @param defaultValue - The default value to use if nothing is stored + * @returns A tuple of [value, setValue] similar to useState + */ +export function usePersistentState( + key: string, + defaultValue: T +): [T, (value: T | ((prevValue: T) => T)) => void] { + const [state, setState] = useState(() => { + // Only access localStorage on the client side + if (typeof window === "undefined") { + return defaultValue; + } + + try { + const item = window.localStorage.getItem(key); + return item ? JSON.parse(item) : defaultValue; + } catch (error) { + console.warn(`Error reading localStorage key "${key}":`, error); + return defaultValue; + } + }); + + const setValue = (value: T | ((prevValue: T) => T)) => { + try { + // Allow value to be a function so we have the same API as useState + const valueToStore = value instanceof Function ? value(state) : value; + setState(valueToStore); + + // Save to localStorage on the client side + if (typeof window !== "undefined") { + window.localStorage.setItem(key, JSON.stringify(valueToStore)); + } + } catch (error) { + console.warn(`Error setting localStorage key "${key}":`, error); + } + }; + + return [state, setValue]; +} \ No newline at end of file diff --git a/apps/webapp/app/routes/api.v1.mcp.memory.tsx b/apps/webapp/app/routes/api.v1.mcp.memory.tsx index 83ebb70..3a26fc7 100644 --- a/apps/webapp/app/routes/api.v1.mcp.memory.tsx +++ b/apps/webapp/app/routes/api.v1.mcp.memory.tsx @@ -35,6 +35,9 @@ setInterval( // MCP request body schema const MCPRequestSchema = z.object({}).passthrough(); +const SourceParams = z.object({ + source: z.string().optional(), +}); // Search parameters schema for MCP tool const SearchParamsSchema = z.object({ @@ -55,9 +58,12 @@ const handleMCPRequest = async ( request: Request, body: any, authentication: any, + params: z.infer, ) => { const sessionId = request.headers.get("mcp-session-id") as string | undefined; - const source = request.headers.get("source") as string | undefined; + const source = + (request.headers.get("source") as string | undefined) ?? + (params.source as string | undefined); if (!source) { return json( @@ -241,17 +247,23 @@ const handleDelete = async (request: Request, authentication: any) => { const { action, loader } = createHybridActionApiRoute( { body: MCPRequestSchema, + searchParams: SourceParams, allowJWT: true, authorization: { action: "mcp", }, corsStrategy: "all", }, - async ({ body, authentication, request }) => { + async ({ body, authentication, request, searchParams }) => { const method = request.method; if (method === "POST") { - return await handleMCPRequest(request, body, authentication); + return await handleMCPRequest( + request, + body, + authentication, + searchParams, + ); } else if (method === "DELETE") { return await handleDelete(request, authentication); } else { diff --git a/apps/webapp/app/routes/api.v1.oauth.callback.tsx b/apps/webapp/app/routes/api.v1.oauth.callback.tsx index 1e361a8..4001294 100644 --- a/apps/webapp/app/routes/api.v1.oauth.callback.tsx +++ b/apps/webapp/app/routes/api.v1.oauth.callback.tsx @@ -1,21 +1,38 @@ -import { createActionApiRoute } from "~/services/routeBuilders/apiBuilder.server"; import { callbackHandler } from "~/services/oauth/oauth.server"; import type { CallbackParams } from "~/services/oauth/oauth-utils.server"; +import { type LoaderFunctionArgs } from "@remix-run/node"; // This route handles the OAuth callback, similar to the NestJS controller -const { loader } = createActionApiRoute( - { - allowJWT: false, - corsStrategy: "all", - }, - async ({ request }) => { +export async function loader({ request }: LoaderFunctionArgs) { + // Handle CORS preflight + if (request.method.toUpperCase() === "OPTIONS") { + return new Response(null, { + status: 200, + headers: { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "GET, OPTIONS", + "Access-Control-Allow-Headers": "Content-Type", + }, + }); + } + + // Only allow GET requests + if (request.method.toUpperCase() !== "GET") { + return new Response("Method Not Allowed", { + status: 405, + headers: { Allow: "GET" } + }); + } + + try { const url = new URL(request.url); const params: CallbackParams = {}; for (const [key, value] of url.searchParams.entries()) { params[key] = value; } return await callbackHandler(params); - }, -); - -export { loader }; + } catch (error) { + console.error("OAuth callback error:", error); + return new Response("Internal Server Error", { status: 500 }); + } +} \ No newline at end of file diff --git a/apps/webapp/app/routes/home.integration.$slug.tsx b/apps/webapp/app/routes/home.integration.$slug.tsx index fc1e453..1e422e4 100644 --- a/apps/webapp/app/routes/home.integration.$slug.tsx +++ b/apps/webapp/app/routes/home.integration.$slug.tsx @@ -138,7 +138,7 @@ export default function IntegrationDetail() { const hasApiKey = !!specData?.auth?.api_key; const hasOAuth2 = !!specData?.auth?.OAuth2; const hasMCPAuth = !!( - specData?.mcp.type === "url" && specData?.mcp.needsAuth + specData?.mcp.type === "http" && specData?.mcp.needsAuth ); const Component = getIcon(integration.icon as IconType); @@ -163,84 +163,86 @@ export default function IntegrationDetail() { }, ]} /> -
-
- -
- } - > -
- {/* Authentication Methods */} -
-

Authentication Methods

-
- {hasApiKey && ( -
- - API Key authentication - -
- )} - {hasOAuth2 && ( -
- - - OAuth 2.0 authentication - -
- )} - {!hasApiKey && !hasOAuth2 && !hasMCPAuth && ( -
- No authentication method specified -
- )} +
+
+
+
-
- - {/* Connect Section */} - {!activeAccount && (hasApiKey || hasOAuth2) && ( -
-

- Connect to {integration.name} -

- - {/* API Key Authentication */} - - - {/* OAuth Authentication */} - + } + > +
+ {/* Authentication Methods */} +
+

Authentication Methods

+
+ {hasApiKey && ( +
+ + API Key authentication + +
+ )} + {hasOAuth2 && ( +
+ + + OAuth 2.0 authentication + +
+ )} + {!hasApiKey && !hasOAuth2 && !hasMCPAuth && ( +
+ No authentication method specified +
+ )} +
- )} - {/* Connected Account Info */} - + {/* Connect Section */} + {!activeAccount && (hasApiKey || hasOAuth2) && ( +
+

+ Connect to {integration.name} +

- {/* MCP Authentication Section */} - + {/* API Key Authentication */} + - {/* Ingestion Rule Section */} - -
- + {/* OAuth Authentication */} + +
+ )} + + {/* Connected Account Info */} + + + {/* MCP Authentication Section */} + + + {/* Ingestion Rule Section */} + +
+ +
); diff --git a/apps/webapp/app/routes/oauth.authorize.tsx b/apps/webapp/app/routes/oauth.authorize.tsx index 531e98d..8e2944a 100644 --- a/apps/webapp/app/routes/oauth.authorize.tsx +++ b/apps/webapp/app/routes/oauth.authorize.tsx @@ -14,8 +14,17 @@ import { Button } from "~/components/ui/button"; import { Card, CardContent } from "~/components/ui/card"; import { Arrows } from "~/components/icons"; import Logo from "~/components/logo/logo"; -import { AlignLeft, LayoutGrid, Pen, User, Mail, Shield, Database } from "lucide-react"; - +import { + AlignLeft, + LayoutGrid, + Pen, + User, + Mail, + Shield, + Database, + LoaderCircle, +} from "lucide-react"; +import { useState } from "react"; export const loader = async ({ request }: LoaderFunctionArgs) => { // Check if user is authenticated @@ -30,19 +39,22 @@ export const loader = async ({ request }: LoaderFunctionArgs) => { } const url = new URL(request.url); - let scopeParam = url.searchParams.get("scope") || undefined; + let scopeParam = url.searchParams.get("scope") || "mcp"; // If scope is present, normalize it to comma-separated format // Handle both space-separated (from URL encoding) and comma-separated scopes if (scopeParam) { // First, try splitting by spaces (common in OAuth2 URLs) - let scopes = scopeParam.split(/\s+/).filter(s => s.length > 0); - + let scopes = scopeParam.split(/\s+/).filter((s) => s.length > 0); + // If no spaces found, try splitting by commas if (scopes.length === 1) { - scopes = scopeParam.split(",").map(s => s.trim()).filter(s => s.length > 0); + scopes = scopeParam + .split(",") + .map((s) => s.trim()) + .filter((s) => s.length > 0); } - + scopeParam = scopes.join(","); } else { throw new Error("Scope is not found"); @@ -85,7 +97,7 @@ export const loader = async ({ request }: LoaderFunctionArgs) => { } // Validate scopes - if (!oauth2Service.validateScopes(client, params.scope || '')) { + if (!oauth2Service.validateScopes(client, params.scope || "")) { return redirect( `${params.redirect_uri}?error=${OAuth2Errors.INVALID_SCOPE}&error_description=Invalid scope${params.state ? `&state=${params.state}` : ""}`, ); @@ -151,7 +163,7 @@ export const action = async ({ request }: ActionFunctionArgs) => { codeChallenge: params.code_challenge, codeChallengeMethod: params.code_challenge_method, workspaceId: workspace.id, - }); + }); // Redirect back to client with authorization code const redirectUrl = new URL(params.redirect_uri); redirectUrl.searchParams.set("code", authCode); @@ -173,8 +185,8 @@ export const action = async ({ request }: ActionFunctionArgs) => { }; export default function OAuthAuthorize() { - const { user, client, params } = useLoaderData(); - + const { user, client, params } = useLoaderData(); + const [isRedirecting, setIsRedirecting] = useState(false); const getScopeIcon = (scope: string) => { switch (scope) { @@ -255,68 +267,93 @@ export default function OAuthAuthorize() { className={`flex items-center gap-2 border-x border-t border-gray-300 p-2 ${isLast ? "border-b" : ""} ${isFirst ? "rounded-tl-md rounded-tr-md" : ""} ${isLast ? "rounded-br-md rounded-bl-md" : ""} `} >
{getScopeIcon(trimmedScope)}
-
- {getScopeDescription(trimmedScope)} -
+
{getScopeDescription(trimmedScope)}
); })} -
- - - - {params.scope && ( - - )} - {params.state && ( - - )} - {params.code_challenge && ( - - )} - {params.code_challenge_method && ( - - )} - -
- - + {isRedirecting ? ( +
+ + + Redirecting to the page... (Close this page if it doesn't + redirect in 5 seconds) +
- + ) : ( +
{ + // Only show loading if allow is clicked + const form = e.target as HTMLFormElement; + const allowBtn = form.querySelector( + 'button[name="action"][value="allow"]', + ); + if ((e.nativeEvent as SubmitEvent).submitter === allowBtn) { + setIsRedirecting(true); + } + }} + > + + + + {params.scope && ( + + )} + {params.state && ( + + )} + {params.code_challenge && ( + + )} + {params.code_challenge_method && ( + + )} + +
+ + +
+
+ )}
diff --git a/apps/webapp/app/routes/oauth.register.tsx b/apps/webapp/app/routes/oauth.register.tsx new file mode 100644 index 0000000..d9e2b43 --- /dev/null +++ b/apps/webapp/app/routes/oauth.register.tsx @@ -0,0 +1,59 @@ +import { json } from "@remix-run/node"; +import { type ActionFunctionArgs } from "@remix-run/server-runtime"; +import { oauth2Service } from "~/services/oauth2.server"; + +// Dynamic Client Registration for MCP clients (Claude, etc.) +export async function action({ request }: ActionFunctionArgs) { + if (request.method !== "POST") { + throw new Response("Method Not Allowed", { status: 405 }); + } + + try { + const body = await request.json(); + const { client_name, redirect_uris, grant_types, response_types } = body; + + // Validate required fields + if (!redirect_uris || !Array.isArray(redirect_uris) || redirect_uris.length === 0) { + return json( + { error: "invalid_request", error_description: "redirect_uris is required" }, + { status: 400 } + ); + } + + // Create MCP client with special handling + const client = await oauth2Service.createDynamicClient({ + name: client_name || "MCP Client", + redirectUris: redirect_uris, + grantTypes: grant_types || ["authorization_code"], + responseTypes: response_types || ["code"], + clientType: "mcp", // Special flag for MCP clients + requirePkce: true, + allowedScopes: "mcp", + }); + + return json ({ + client_id: client.clientId, + client_secret: client.clientSecret, // Include if confidential client + client_id_issued_at: Math.floor(Date.now() / 1000), + grant_types: client.grantTypes.split(","), + response_types: ["code"], + redirect_uris: client.redirectUris.split(","), + scope: client.allowedScopes, + token_endpoint_auth_method: "client_secret_post", + }); + } catch (error) { + console.error("Dynamic client registration error:", error); + return json( + { + error: "invalid_request", + error_description: "Failed to register client" + }, + { status: 400 } + ); + } +} + +// Prevent GET requests +export async function loader() { + throw new Response("Method Not Allowed", { status: 405 }); +} \ No newline at end of file diff --git a/apps/webapp/app/services/oauth2.server.ts b/apps/webapp/app/services/oauth2.server.ts index 365ad8b..494749c 100644 --- a/apps/webapp/app/services/oauth2.server.ts +++ b/apps/webapp/app/services/oauth2.server.ts @@ -691,6 +691,50 @@ export class OAuth2Service { scope: storedRefreshToken.scope || undefined, }; } + + async createDynamicClient(params: { + name: string; + redirectUris: string[]; + grantTypes?: string[]; + clientType?: string; + responseTypes?: string[]; + requirePkce?: boolean; + allowedScopes?: string; + description?: string; + workspaceId?: string; + createdById?: string; + }) { + // Generate secure client credentials + const clientId = crypto.randomBytes(16).toString("hex"); + const clientSecret = crypto.randomBytes(32).toString("hex"); + + // Default values for MCP clients + const grantTypes = params.grantTypes || [ + "authorization_code", + "refresh_token", + ]; + const allowedScopes = params.allowedScopes || "mcp"; + const requirePkce = params.requirePkce ?? true; // Default to true for security + + const client = await prisma.oAuthClient.create({ + data: { + clientId, + clientSecret, + name: params.name, + description: + params.description || + `Dynamically registered ${params.clientType || "client"}`, + redirectUris: params.redirectUris.join(","), + grantTypes: grantTypes.join(","), + allowedScopes, + requirePkce, + clientType: "mcp", + isActive: true, + }, + }); + + return client; + } } export const oauth2Service = new OAuth2Service(); diff --git a/apps/webapp/app/services/redirectTo.server.ts b/apps/webapp/app/services/redirectTo.server.ts index 53828e0..94eb169 100644 --- a/apps/webapp/app/services/redirectTo.server.ts +++ b/apps/webapp/app/services/redirectTo.server.ts @@ -6,7 +6,7 @@ const ONE_DAY = 60 * 60 * 24; export const { commitSession, getSession } = createCookieSessionStorage({ cookie: { - name: "__redirectTo", + name: "__redirectTo__core", path: "/", httpOnly: true, sameSite: "lax", diff --git a/apps/webapp/app/services/routeBuilders/apiBuilder.server.ts b/apps/webapp/app/services/routeBuilders/apiBuilder.server.ts index c686cf0..bce2d42 100644 --- a/apps/webapp/app/services/routeBuilders/apiBuilder.server.ts +++ b/apps/webapp/app/services/routeBuilders/apiBuilder.server.ts @@ -635,11 +635,13 @@ async function wrapResponse( } // New hybrid authentication types and functions -export type HybridAuthenticationResult = ApiAuthenticationResultSuccess | { - ok: true; - type: "COOKIE"; - userId: string; -}; +export type HybridAuthenticationResult = + | ApiAuthenticationResultSuccess + | { + ok: true; + type: "COOKIE"; + userId: string; + }; async function authenticateHybridRequest( request: Request, @@ -766,10 +768,9 @@ export function createHybridActionApiRoute< } try { - const authenticationResult = await authenticateHybridRequest( - request, - { allowJWT }, - ); + const authenticationResult = await authenticateHybridRequest(request, { + allowJWT, + }); if (!authenticationResult) { return await wrapResponse( diff --git a/apps/webapp/app/services/sessionStorage.server.ts b/apps/webapp/app/services/sessionStorage.server.ts index 4d26749..ff92c4e 100644 --- a/apps/webapp/app/services/sessionStorage.server.ts +++ b/apps/webapp/app/services/sessionStorage.server.ts @@ -9,7 +9,7 @@ export const sessionStorage = createCookieSessionStorage<{ [SESSION_KEY]: AuthUser; }>({ cookie: { - name: "__session", // use any name you want here + name: "__session__core", // use any name you want here sameSite: "lax", // this helps with CSRF path: "/", // remember to add this so the cookie will work in all routes httpOnly: true, // for security reasons, make this cookie http only diff --git a/apps/webapp/app/trigger/utils/mcp.ts b/apps/webapp/app/trigger/utils/mcp.ts index 14edca8..8008dae 100644 --- a/apps/webapp/app/trigger/utils/mcp.ts +++ b/apps/webapp/app/trigger/utils/mcp.ts @@ -271,10 +271,33 @@ export const fetchAndSaveStdioIntegrations = async () => { continue; } - const content = await response.text(); + // Check if the response is binary (executable) or text + const contentType = response.headers.get("content-type"); + const isBinary = + contentType && + (contentType.includes("application/octet-stream") || + contentType.includes("application/executable") || + contentType.includes("application/x-executable") || + contentType.includes("binary") || + !contentType.includes("text/")); + + let content: string | Buffer; + + if (isBinary) { + // Handle binary files + const arrayBuffer = await response.arrayBuffer(); + content = Buffer.from(arrayBuffer); + } else { + // Handle text files + content = await response.text(); + } // Save the content to the target file - fs.writeFileSync(targetFile, content); + if (typeof content === "string") { + fs.writeFileSync(targetFile, content); + } else { + fs.writeFileSync(targetFile, content); + } // Make the file executable if it's a script if (process.platform !== "win32") { diff --git a/apps/webapp/app/trigger/utils/message-utils.ts b/apps/webapp/app/trigger/utils/message-utils.ts index 2972f3f..5ffc559 100644 --- a/apps/webapp/app/trigger/utils/message-utils.ts +++ b/apps/webapp/app/trigger/utils/message-utils.ts @@ -19,8 +19,21 @@ export const createIntegrationAccount = async ({ config?: Record; settings?: Record; }) => { - return prisma.integrationAccount.create({ - data: { + return prisma.integrationAccount.upsert({ + where: { + accountId_integrationDefinitionId_workspaceId: { + accountId, + integrationDefinitionId, + workspaceId, + }, + }, + update: { + integrationConfiguration: config || {}, + settings: settings || {}, + isActive: true, + deleted: null, + }, + create: { accountId, integrationDefinitionId, integratedById: userId, diff --git a/apps/webapp/package.json b/apps/webapp/package.json index 2a74d5e..99b1220 100644 --- a/apps/webapp/package.json +++ b/apps/webapp/package.json @@ -6,8 +6,8 @@ "scripts": { "build": "remix vite:build", "dev": "node ./server.mjs", - "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", - "lint:fix": "eslint --fix --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", + "lint": "eslint --fix --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", + "lint:fix": "eslint 'app/**/*.{ts,tsx,js,jsx}' --rule 'turbo/no-undeclared-env-vars:error' -f table", "start": "remix-serve ./build/server/index.js", "typecheck": "tsc", "trigger:dev": "pnpm dlx trigger.dev@4.0.0-v4-beta.22 dev", @@ -38,6 +38,7 @@ "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-popover": "^1.0.7", + "@radix-ui/react-slider": "^1.3.5", "@radix-ui/react-scroll-area": "^1.0.5", "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-separator": "^1.1.7", diff --git a/apps/webapp/public/logo-dark.svg b/apps/webapp/public/logo-dark.svg index 6242699..0487725 100644 --- a/apps/webapp/public/logo-dark.svg +++ b/apps/webapp/public/logo-dark.svg @@ -1,16 +1,16 @@ - - - - - - - - - - - - + + + + + + + + + + + + @@ -19,18 +19,18 @@ - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/apps/webapp/server.mjs b/apps/webapp/server.mjs index 2a62d17..ca490a4 100644 --- a/apps/webapp/server.mjs +++ b/apps/webapp/server.mjs @@ -44,10 +44,27 @@ async function init() { app.use(morgan("tiny")); + app.get("/.well-known/oauth-authorization-server", (req, res) => { + res.json({ + issuer: process.env.APP_ORIGIN, + authorization_endpoint: `${process.env.APP_ORIGIN}/oauth/authorize`, + token_endpoint: `${process.env.APP_ORIGIN}/oauth/token`, + registration_endpoint: `${process.env.APP_ORIGIN}/oauth/register`, + scopes_supported: ["mcp"], + response_types_supported: ["code"], + grant_types_supported: [ + "authorization_code", + "refresh_token", + "client_credentials", + ], + code_challenge_methods_supported: ["S256"], + token_endpoint_auth_methods_supported: ["client_secret_basic", "none"], + }); + }); + // handle SSR requests app.all("*", remixHandler); - const port = process.env.REMIX_APP_PORT || 3000; app.listen(port, () => console.log(`Express server listening at http://localhost:${port}`), diff --git a/docker-compose.yaml b/docker-compose.yaml index 7c95ce2..d715af6 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -32,15 +32,18 @@ services: ports: - "3033:3000" depends_on: - - postgres - - redis - - neo4j + postgres: + condition: service_healthy + redis: + condition: service_started + neo4j: + condition: service_healthy networks: - core postgres: container_name: core-postgres - image: postgres:15 + image: redplanethq/postgres:0.1.0 environment: - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} @@ -51,6 +54,12 @@ services: - postgres_data:/var/lib/postgresql/data networks: - core + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $POSTGRES_USER"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 10s redis: container_name: core-redis @@ -72,6 +81,12 @@ services: - neo4j_data:/data networks: - core + healthcheck: + test: ["CMD-SHELL", "cypher-shell -u $NEO4J_USERNAME -p $NEO4J_PASSWORD 'RETURN 1'"] + interval: 10s + timeout: 5s + retries: 10 + start_period: 20s networks: core: diff --git a/docs/automation-use-cases.md b/docs/automation-use-cases.md deleted file mode 100644 index a9c050f..0000000 --- a/docs/automation-use-cases.md +++ /dev/null @@ -1,28 +0,0 @@ -# Automation Workflow Use Cases - -## Persona-Based Automation Workflows - -This document outlines high-impact automation workflows for different personas using our supported integrations: Slack, Github, Google Drive, Linear, Calendar, Claude Code, and Gmail. - -| Rule Name | Description | Persona | Integrations | Importance | -|-----------|-------------|---------|-------------|------------| -| **Code Review Prioritizer** | Automatically prioritize and assign code reviews based on PR size, dependencies, and team availability | Developer | Github, Slack, Calendar | 9.7 | -| **PR to Deployment Tracker** | Track PRs from submission to deployment, notifying stakeholders at each stage with estimated completion times | Developer | Github, Slack, Linear | 9.5 | -| **Standup Automator** | Collect daily updates from commit messages and Linear tasks, post summaries to team Slack channel before standups | Developer | Github, Linear, Slack | 9.3 | -| **Technical Debt Tracker** | Auto-identify technical debt from code comments and Linear tickets, creating weekly summaries with prioritization suggestions | Developer | Github, Linear, Slack | 9.2 | -| **Code Documentation Generator** | Use Claude Code to auto-generate documentation from code changes, adding to Google Drive knowledge base | Developer | Github, Claude Code, Google Drive | 9.1 | -| **Sprint Planning Assistant** | Collect Linear backlog items, analyze GitHub PRs, and create pre-populated sprint planning documents | Product Manager | Linear, Github, Google Drive | 9.8 | -| **Feature Impact Dashboard** | Track feature usage metrics from analytics, connect to Linear tickets, and generate impact reports | Product Manager | Linear, Gmail, Google Drive | 9.6 | -| **Customer Feedback Connector** | Route customer feedback from Gmail to appropriate Linear tickets and notify product team in Slack | Product Manager | Gmail, Linear, Slack | 9.5 | -| **Release Notes Automator** | Generate release notes from Linear tickets and GitHub PRs, distribute via Slack and email | Product Manager | Linear, Github, Slack, Gmail | 9.4 | -| **Meeting Effectiveness Tracker** | Monitor calendar events, auto-document action items in Linear, and track follow-through | Product Manager | Calendar, Linear, Slack | 9.2 | -| **Investor Update Compiler** | Aggregate key metrics from various sources into monthly investor update templates | Founder | Google Drive, Linear, Gmail | 9.9 | -| **Competitive Intelligence Monitor** | Monitor competitor activities from various sources, creating summaries with Claude Code | Founder | Gmail, Claude Code, Google Drive | 9.7 | -| **Strategic Alignment Tracker** | Connect company OKRs to actual work items in Linear, creating executive dashboards | Founder | Linear, Google Drive, Slack | 9.6 | -| **Board Meeting Automator** | Collect data for board meetings, pre-populate slides, and send reminders with preparation materials | Founder | Calendar, Google Drive, Gmail | 9.5 | -| **Team Pulse Monitor** | Analyze communication patterns and work distribution to identify burnout risks | Founder | Slack, Github, Linear | 9.3 | -| **Deal Stage Progression** | Move deals through pipeline stages based on email interactions and scheduled meetings | Sales | Gmail, Calendar, Slack | 9.8 | -| **Proposal Generator** | Auto-generate customized proposals using templates and client-specific data | Sales | Google Drive, Gmail, Claude Code | 9.7 | -| **Meeting Follow-up Orchestrator** | Schedule and personalize follow-ups based on meeting notes and conversation topics | Sales | Calendar, Gmail, Slack | 9.6 | -| **Competitive Deal Intelligence** | Alert sales team when competitors are mentioned in prospect communications | Sales | Gmail, Slack, Claude Code | 9.4 | -| **Customer Success Handoff** | Automate post-sale transition with documentation, training materials, and onboarding schedules | Sales | Gmail, Google Drive, Calendar | 9.3 | \ No newline at end of file diff --git a/integrations/slack/package.json b/integrations/slack/package.json index 99bed03..ed10e0e 100644 --- a/integrations/slack/package.json +++ b/integrations/slack/package.json @@ -58,6 +58,6 @@ "commander": "^12.0.0", "openai": "^4.0.0", "react-query": "^3.39.3", - "@redplanethq/sdk": "0.1.0" + "@redplanethq/sdk": "0.1.1" } -} \ No newline at end of file +} diff --git a/integrations/slack/pnpm-lock.yaml b/integrations/slack/pnpm-lock.yaml index e0bca70..0e1b352 100644 --- a/integrations/slack/pnpm-lock.yaml +++ b/integrations/slack/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@redplanethq/sdk': - specifier: 0.1.0 - version: 0.1.0 + specifier: 0.1.1 + version: 0.1.1 axios: specifier: ^1.7.9 version: 1.9.0 @@ -33,18 +33,6 @@ importers: '@babel/preset-typescript': specifier: ^7.26.0 version: 7.27.1(@babel/core@7.27.1) - '@rollup/plugin-commonjs': - specifier: ^28.0.1 - version: 28.0.3(rollup@4.40.2) - '@rollup/plugin-json': - specifier: ^6.1.0 - version: 6.1.0(rollup@4.40.2) - '@rollup/plugin-node-resolve': - specifier: ^15.3.0 - version: 15.3.1(rollup@4.40.2) - '@rollup/plugin-replace': - specifier: ^5.0.7 - version: 5.0.7(rollup@4.40.2) '@types/node': specifier: ^18.0.20 version: 18.19.100 @@ -56,19 +44,19 @@ importers: version: 10.1.3(eslint@9.26.0) eslint-import-resolver-alias: specifier: ^1.1.2 - version: 1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@9.26.0)(typescript@4.9.5))(eslint@9.26.0)) + version: 1.1.2(eslint-plugin-import@2.31.0(eslint@9.26.0)) eslint-plugin-import: specifier: ^2.31.0 - version: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@9.26.0)(typescript@4.9.5))(eslint@9.26.0) + version: 2.31.0(eslint@9.26.0) eslint-plugin-jest: specifier: ^27.9.0 - version: 27.9.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.26.0)(typescript@4.9.5))(eslint@9.26.0)(typescript@4.9.5))(eslint@9.26.0)(typescript@4.9.5) + version: 27.9.0(@typescript-eslint/eslint-plugin@5.62.0(eslint@9.26.0)(typescript@4.9.5))(eslint@9.26.0)(typescript@4.9.5) eslint-plugin-prettier: specifier: ^5.2.1 version: 5.4.0(eslint-config-prettier@10.1.3(eslint@9.26.0))(eslint@9.26.0)(prettier@3.5.3) eslint-plugin-unused-imports: specifier: ^2.0.0 - version: 2.0.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.26.0)(typescript@4.9.5))(eslint@9.26.0)(typescript@4.9.5))(eslint@9.26.0) + version: 2.0.0(@typescript-eslint/eslint-plugin@5.62.0(eslint@9.26.0)(typescript@4.9.5))(eslint@9.26.0) ncc: specifier: 0.3.6 version: 0.3.6 @@ -78,18 +66,6 @@ importers: rimraf: specifier: ^3.0.2 version: 3.0.2 - rollup: - specifier: ^4.28.1 - version: 4.40.2 - rollup-plugin-node-polyfills: - specifier: ^0.2.1 - version: 0.2.1 - rollup-plugin-terser: - specifier: ^7.0.2 - version: 7.0.2(rollup@4.40.2) - rollup-plugin-typescript2: - specifier: ^0.34.1 - version: 0.34.1(rollup@4.40.2)(typescript@4.9.5) tslib: specifier: ^2.8.1 version: 2.8.1 @@ -459,9 +435,6 @@ packages: resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} engines: {node: '>=6.0.0'} - '@jridgewell/source-map@0.3.6': - resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} - '@jridgewell/sourcemap-codec@1.5.0': resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} @@ -492,59 +465,10 @@ packages: resolution: {integrity: sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@redplanethq/sdk@0.1.0': - resolution: {integrity: sha512-RmPfT9XESjTSMLlAMkolZEF28PvGo5hlwrG75JQy1tAZkvaTHzC7A2mEAMbsBvOMrJuUztL3NtCmVF//C/C/+A==} + '@redplanethq/sdk@0.1.1': + resolution: {integrity: sha512-tfR1c9p7vNeCL5jsF9QlEZcRFLsihaHe/ZQWVKZYXzAZ6GugoIFBaayGfVvjNjyEnN3nlrl3usKBX+hhaKzg0g==} engines: {node: '>=18.0.0'} - '@rollup/plugin-commonjs@28.0.3': - resolution: {integrity: sha512-pyltgilam1QPdn+Zd9gaCfOLcnjMEJ9gV+bTw6/r73INdvzf1ah9zLIJBm+kW7R6IUFIQ1YO+VqZtYxZNWFPEQ==} - engines: {node: '>=16.0.0 || 14 >= 14.17'} - peerDependencies: - rollup: ^2.68.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-json@6.1.0': - resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-node-resolve@15.3.1': - resolution: {integrity: sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.78.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-replace@5.0.7': - resolution: {integrity: sha512-PqxSfuorkHz/SPpyngLyg5GCEkOcee9M1bkxiVDr41Pd61mqP1PLOoDPbpl44SB2mQGKwV/In74gqQmGITOhEQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/pluginutils@4.2.1': - resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} - engines: {node: '>= 8.0.0'} - - '@rollup/pluginutils@5.1.4': - resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - '@rollup/rollup-android-arm-eabi@4.40.2': resolution: {integrity: sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg==} cpu: [arm] @@ -663,9 +587,6 @@ packages: '@types/node@18.19.100': resolution: {integrity: sha512-ojmMP8SZBKprc3qGrGk8Ujpo80AXkrP7G2tOT4VWr5jlr5DHjsJF+emXJz+Wm0glmy4Js62oKMdZZ6B9Y+tEcA==} - '@types/resolve@1.20.2': - resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} - '@types/semver@7.7.0': resolution: {integrity: sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==} @@ -680,16 +601,6 @@ packages: typescript: optional: true - '@typescript-eslint/parser@5.62.0': - resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - '@typescript-eslint/scope-manager@5.62.0': resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -845,9 +756,6 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true - buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - bundle-require@5.1.0: resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -912,16 +820,10 @@ packages: resolution: {integrity: sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==} engines: {node: '>=20'} - commander@2.20.3: - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} - commondir@1.0.1: - resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -991,10 +893,6 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} @@ -1222,12 +1120,6 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} - estree-walker@0.6.1: - resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==} - - estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -1297,14 +1189,6 @@ packages: resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==} engines: {node: '>= 0.8'} - find-cache-dir@3.3.2: - resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} - engines: {node: '>=8'} - - find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} @@ -1352,10 +1236,6 @@ packages: resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} engines: {node: '>= 0.8'} - fs-extra@10.1.0: - resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} - engines: {node: '>=12'} - fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -1426,9 +1306,6 @@ packages: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} @@ -1553,9 +1430,6 @@ packages: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} - is-module@1.0.0: - resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} - is-number-object@1.1.1: resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} engines: {node: '>= 0.4'} @@ -1567,9 +1441,6 @@ packages: is-promise@4.0.0: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} - is-reference@1.2.1: - resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} - is-regex@1.2.1: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} @@ -1615,10 +1486,6 @@ packages: jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - jest-worker@26.6.2: - resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} - engines: {node: '>= 10.13.0'} - joycon@3.1.1: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} @@ -1656,9 +1523,6 @@ packages: engines: {node: '>=6'} hasBin: true - jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -1677,10 +1541,6 @@ packages: resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -1701,16 +1561,6 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - magic-string@0.25.9: - resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} - - magic-string@0.30.17: - resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} - - make-dir@3.1.0: - resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} - engines: {node: '>=8'} - match-sorter@6.3.4: resolution: {integrity: sha512-jfZW7cWS5y/1xswZo8VBOdudUiSd9nifYRWphc9M5D/ee4w4AoXLgBEdRbgVaxbMuagBPeUC5y2Hi8DO6o9aDg==} @@ -1726,9 +1576,6 @@ packages: resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} engines: {node: '>=18'} - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -1876,26 +1723,14 @@ packages: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} - p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} - p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} - p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} @@ -1953,10 +1788,6 @@ packages: resolution: {integrity: sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==} engines: {node: '>=16.20.0'} - pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - possible-typed-array-names@1.1.0: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} @@ -2014,9 +1845,6 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} @@ -2088,28 +1916,6 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true - rollup-plugin-inject@3.0.2: - resolution: {integrity: sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==} - deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject. - - rollup-plugin-node-polyfills@0.2.1: - resolution: {integrity: sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==} - - rollup-plugin-terser@7.0.2: - resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==} - deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser - peerDependencies: - rollup: ^2.0.0 - - rollup-plugin-typescript2@0.34.1: - resolution: {integrity: sha512-P4cHLtGikESmqi1CA+tdMDUv8WbQV48mzPYt77TSTOPJpERyZ9TXdDgjSDix8Fkqce6soYz3+fa4lrC93IEkcw==} - peerDependencies: - rollup: '>=1.26.3' - typescript: '>=2.4.0' - - rollup-pluginutils@2.8.2: - resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} - rollup@4.40.2: resolution: {integrity: sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -2159,9 +1965,6 @@ packages: resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==} engines: {node: '>= 18'} - serialize-javascript@4.0.0: - resolution: {integrity: sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==} - serve-static@2.2.0: resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==} engines: {node: '>= 18'} @@ -2217,21 +2020,10 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - - source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - source-map@0.8.0-beta.0: resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} engines: {node: '>= 8'} - sourcemap-codec@1.4.8: - resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} - deprecated: Please use @jridgewell/sourcemap-codec instead - statuses@2.0.1: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} @@ -2289,11 +2081,6 @@ packages: resolution: {integrity: sha512-Q/XQKRaJiLiFIBNN+mndW7S/RHxvwzuZS6ZwmRzUBqJBv/5QIKCEwkBC8GBf8EQJKYnaFs0wOZbKTXBPj8L9oQ==} engines: {node: ^14.18.0 || >=16.0.0} - terser@5.39.0: - resolution: {integrity: sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==} - engines: {node: '>=10'} - hasBin: true - thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -2410,10 +2197,6 @@ packages: undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - unload@2.2.0: resolution: {integrity: sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==} @@ -2861,11 +2644,6 @@ snapshots: '@jridgewell/set-array@1.2.1': {} - '@jridgewell/source-map@0.3.6': - dependencies: - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 - '@jridgewell/sourcemap-codec@1.5.0': {} '@jridgewell/trace-mapping@0.3.25': @@ -2905,58 +2683,10 @@ snapshots: '@pkgr/core@0.2.4': {} - '@redplanethq/sdk@0.1.0': + '@redplanethq/sdk@0.1.1': dependencies: commander: 14.0.0 - '@rollup/plugin-commonjs@28.0.3(rollup@4.40.2)': - dependencies: - '@rollup/pluginutils': 5.1.4(rollup@4.40.2) - commondir: 1.0.1 - estree-walker: 2.0.2 - fdir: 6.4.4(picomatch@4.0.2) - is-reference: 1.2.1 - magic-string: 0.30.17 - picomatch: 4.0.2 - optionalDependencies: - rollup: 4.40.2 - - '@rollup/plugin-json@6.1.0(rollup@4.40.2)': - dependencies: - '@rollup/pluginutils': 5.1.4(rollup@4.40.2) - optionalDependencies: - rollup: 4.40.2 - - '@rollup/plugin-node-resolve@15.3.1(rollup@4.40.2)': - dependencies: - '@rollup/pluginutils': 5.1.4(rollup@4.40.2) - '@types/resolve': 1.20.2 - deepmerge: 4.3.1 - is-module: 1.0.0 - resolve: 1.22.10 - optionalDependencies: - rollup: 4.40.2 - - '@rollup/plugin-replace@5.0.7(rollup@4.40.2)': - dependencies: - '@rollup/pluginutils': 5.1.4(rollup@4.40.2) - magic-string: 0.30.17 - optionalDependencies: - rollup: 4.40.2 - - '@rollup/pluginutils@4.2.1': - dependencies: - estree-walker: 2.0.2 - picomatch: 2.3.1 - - '@rollup/pluginutils@5.1.4(rollup@4.40.2)': - dependencies: - '@types/estree': 1.0.7 - estree-walker: 2.0.2 - picomatch: 4.0.2 - optionalDependencies: - rollup: 4.40.2 - '@rollup/rollup-android-arm-eabi@4.40.2': optional: true @@ -3034,14 +2764,11 @@ snapshots: dependencies: undici-types: 5.26.5 - '@types/resolve@1.20.2': {} - '@types/semver@7.7.0': {} - '@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.26.0)(typescript@4.9.5))(eslint@9.26.0)(typescript@4.9.5)': + '@typescript-eslint/eslint-plugin@5.62.0(eslint@9.26.0)(typescript@4.9.5)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 5.62.0(eslint@9.26.0)(typescript@4.9.5) '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/type-utils': 5.62.0(eslint@9.26.0)(typescript@4.9.5) '@typescript-eslint/utils': 5.62.0(eslint@9.26.0)(typescript@4.9.5) @@ -3058,19 +2785,6 @@ snapshots: - supports-color optional: true - '@typescript-eslint/parser@5.62.0(eslint@9.26.0)(typescript@4.9.5)': - dependencies: - '@typescript-eslint/scope-manager': 5.62.0 - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/typescript-estree': 5.62.0(typescript@4.9.5) - debug: 4.4.0 - eslint: 9.26.0 - optionalDependencies: - typescript: 4.9.5 - transitivePeerDependencies: - - supports-color - optional: true - '@typescript-eslint/scope-manager@5.62.0': dependencies: '@typescript-eslint/types': 5.62.0 @@ -3280,8 +2994,6 @@ snapshots: node-releases: 2.0.19 update-browserslist-db: 1.1.3(browserslist@4.24.5) - buffer-from@1.1.2: {} - bundle-require@5.1.0(esbuild@0.25.4): dependencies: esbuild: 0.25.4 @@ -3337,12 +3049,8 @@ snapshots: commander@14.0.0: {} - commander@2.20.3: {} - commander@4.1.1: {} - commondir@1.0.1: {} - concat-map@0.0.1: {} consola@3.4.2: {} @@ -3400,8 +3108,6 @@ snapshots: deep-is@0.1.4: {} - deepmerge@4.3.1: {} - define-data-property@1.1.4: dependencies: es-define-property: 1.0.1 @@ -3563,9 +3269,9 @@ snapshots: dependencies: eslint: 9.26.0 - eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@9.26.0)(typescript@4.9.5))(eslint@9.26.0)): + eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.31.0(eslint@9.26.0)): dependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@9.26.0)(typescript@4.9.5))(eslint@9.26.0) + eslint-plugin-import: 2.31.0(eslint@9.26.0) eslint-import-resolver-node@0.3.9: dependencies: @@ -3575,17 +3281,16 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@5.62.0(eslint@9.26.0)(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint@9.26.0): + eslint-module-utils@2.12.0(eslint-import-resolver-node@0.3.9)(eslint@9.26.0): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 5.62.0(eslint@9.26.0)(typescript@4.9.5) eslint: 9.26.0 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@9.26.0)(typescript@4.9.5))(eslint@9.26.0): + eslint-plugin-import@2.31.0(eslint@9.26.0): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -3596,7 +3301,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.26.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.62.0(eslint@9.26.0)(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint@9.26.0) + eslint-module-utils: 2.12.0(eslint-import-resolver-node@0.3.9)(eslint@9.26.0) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -3607,19 +3312,17 @@ snapshots: semver: 6.3.1 string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 - optionalDependencies: - '@typescript-eslint/parser': 5.62.0(eslint@9.26.0)(typescript@4.9.5) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.26.0)(typescript@4.9.5))(eslint@9.26.0)(typescript@4.9.5))(eslint@9.26.0)(typescript@4.9.5): + eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@5.62.0(eslint@9.26.0)(typescript@4.9.5))(eslint@9.26.0)(typescript@4.9.5): dependencies: '@typescript-eslint/utils': 5.62.0(eslint@9.26.0)(typescript@4.9.5) eslint: 9.26.0 optionalDependencies: - '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.26.0)(typescript@4.9.5))(eslint@9.26.0)(typescript@4.9.5) + '@typescript-eslint/eslint-plugin': 5.62.0(eslint@9.26.0)(typescript@4.9.5) transitivePeerDependencies: - supports-color - typescript @@ -3633,12 +3336,12 @@ snapshots: optionalDependencies: eslint-config-prettier: 10.1.3(eslint@9.26.0) - eslint-plugin-unused-imports@2.0.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.26.0)(typescript@4.9.5))(eslint@9.26.0)(typescript@4.9.5))(eslint@9.26.0): + eslint-plugin-unused-imports@2.0.0(@typescript-eslint/eslint-plugin@5.62.0(eslint@9.26.0)(typescript@4.9.5))(eslint@9.26.0): dependencies: eslint: 9.26.0 eslint-rule-composer: 0.3.0 optionalDependencies: - '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.26.0)(typescript@4.9.5))(eslint@9.26.0)(typescript@4.9.5) + '@typescript-eslint/eslint-plugin': 5.62.0(eslint@9.26.0)(typescript@4.9.5) eslint-rule-composer@0.3.0: {} @@ -3716,10 +3419,6 @@ snapshots: estraverse@5.3.0: {} - estree-walker@0.6.1: {} - - estree-walker@2.0.2: {} - esutils@2.0.3: {} etag@1.8.1: {} @@ -3811,17 +3510,6 @@ snapshots: transitivePeerDependencies: - supports-color - find-cache-dir@3.3.2: - dependencies: - commondir: 1.0.1 - make-dir: 3.1.0 - pkg-dir: 4.2.0 - - find-up@4.1.0: - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - find-up@5.0.0: dependencies: locate-path: 6.0.0 @@ -3863,12 +3551,6 @@ snapshots: fresh@2.0.0: {} - fs-extra@10.1.0: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - fs.realpath@1.0.0: {} fsevents@2.3.3: @@ -3959,8 +3641,6 @@ snapshots: gopd@1.2.0: {} - graceful-fs@4.2.11: {} - graphemer@1.4.0: optional: true @@ -4087,8 +3767,6 @@ snapshots: is-map@2.0.3: {} - is-module@1.0.0: {} - is-number-object@1.1.1: dependencies: call-bound: 1.0.4 @@ -4098,10 +3776,6 @@ snapshots: is-promise@4.0.0: {} - is-reference@1.2.1: - dependencies: - '@types/estree': 1.0.7 - is-regex@1.2.1: dependencies: call-bound: 1.0.4 @@ -4151,12 +3825,6 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 - jest-worker@26.6.2: - dependencies: - '@types/node': 18.19.100 - merge-stream: 2.0.0 - supports-color: 7.2.0 - joycon@3.1.1: {} js-sha3@0.8.0: {} @@ -4181,12 +3849,6 @@ snapshots: json5@2.2.3: {} - jsonfile@6.1.0: - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -4202,10 +3864,6 @@ snapshots: load-tsconfig@0.2.5: {} - locate-path@5.0.0: - dependencies: - p-locate: 4.1.0 - locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -4224,18 +3882,6 @@ snapshots: dependencies: yallist: 3.1.1 - magic-string@0.25.9: - dependencies: - sourcemap-codec: 1.4.8 - - magic-string@0.30.17: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 - - make-dir@3.1.0: - dependencies: - semver: 6.3.1 - match-sorter@6.3.4: dependencies: '@babel/runtime': 7.27.1 @@ -4247,8 +3893,6 @@ snapshots: merge-descriptors@2.0.0: {} - merge-stream@2.0.0: {} - merge2@1.4.1: {} micromatch@4.0.8: @@ -4400,24 +4044,14 @@ snapshots: object-keys: 1.1.1 safe-push-apply: 1.0.0 - p-limit@2.3.0: - dependencies: - p-try: 2.2.0 - p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 - p-locate@4.1.0: - dependencies: - p-limit: 2.3.0 - p-locate@5.0.0: dependencies: p-limit: 3.1.0 - p-try@2.2.0: {} - package-json-from-dist@1.0.1: {} parent-module@1.0.1: @@ -4453,10 +4087,6 @@ snapshots: pkce-challenge@5.0.0: {} - pkg-dir@4.2.0: - dependencies: - find-up: 4.1.0 - possible-typed-array-names@1.1.0: {} postcss-load-config@6.0.1(postcss@8.5.3)(yaml@2.7.1): @@ -4496,10 +4126,6 @@ snapshots: queue-microtask@1.2.3: {} - randombytes@2.1.0: - dependencies: - safe-buffer: 5.2.1 - range-parser@1.2.1: {} raw-body@3.0.0: @@ -4572,38 +4198,6 @@ snapshots: dependencies: glob: 7.2.3 - rollup-plugin-inject@3.0.2: - dependencies: - estree-walker: 0.6.1 - magic-string: 0.25.9 - rollup-pluginutils: 2.8.2 - - rollup-plugin-node-polyfills@0.2.1: - dependencies: - rollup-plugin-inject: 3.0.2 - - rollup-plugin-terser@7.0.2(rollup@4.40.2): - dependencies: - '@babel/code-frame': 7.27.1 - jest-worker: 26.6.2 - rollup: 4.40.2 - serialize-javascript: 4.0.0 - terser: 5.39.0 - - rollup-plugin-typescript2@0.34.1(rollup@4.40.2)(typescript@4.9.5): - dependencies: - '@rollup/pluginutils': 4.2.1 - find-cache-dir: 3.3.2 - fs-extra: 10.1.0 - rollup: 4.40.2 - semver: 7.7.1 - tslib: 2.8.1 - typescript: 4.9.5 - - rollup-pluginutils@2.8.2: - dependencies: - estree-walker: 0.6.1 - rollup@4.40.2: dependencies: '@types/estree': 1.0.7 @@ -4693,10 +4287,6 @@ snapshots: transitivePeerDependencies: - supports-color - serialize-javascript@4.0.0: - dependencies: - randombytes: 2.1.0 - serve-static@2.2.0: dependencies: encodeurl: 2.0.0 @@ -4771,19 +4361,10 @@ snapshots: source-map-js@1.2.1: optional: true - source-map-support@0.5.21: - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - - source-map@0.6.1: {} - source-map@0.8.0-beta.0: dependencies: whatwg-url: 7.1.0 - sourcemap-codec@1.4.8: {} - statuses@2.0.1: {} string-width@4.2.3: @@ -4854,13 +4435,6 @@ snapshots: '@pkgr/core': 0.2.4 tslib: 2.8.1 - terser@5.39.0: - dependencies: - '@jridgewell/source-map': 0.3.6 - acorn: 8.14.1 - commander: 2.20.3 - source-map-support: 0.5.21 - thenify-all@1.6.0: dependencies: thenify: 3.3.1 @@ -5000,8 +4574,6 @@ snapshots: undici-types@5.26.5: {} - universalify@2.0.1: {} - unload@2.2.0: dependencies: '@babel/runtime': 7.27.1 diff --git a/integrations/slack/spec.json b/integrations/slack/spec.json index ccf64b5..45a752d 100644 --- a/integrations/slack/spec.json +++ b/integrations/slack/spec.json @@ -5,10 +5,11 @@ "icon": "slack", "mcp": { "type": "stdio", - "url": "", - "args": [ ], + "url": "https://integrations.heysol.ai/slack/mcp/slack-mcp-server", + "args": [], "env": { - "SLACK_MCP_XOXP_TOKEN": "${config:access_token}" + "SLACK_MCP_XOXP_TOKEN": "${config:access_token}", + "SLACK_MCP_ADD_MESSAGE_TOOL": true } }, "auth": { diff --git a/integrations/slack/src/account-create.ts b/integrations/slack/src/account-create.ts index 4b59add..56d9f59 100644 --- a/integrations/slack/src/account-create.ts +++ b/integrations/slack/src/account-create.ts @@ -1,9 +1,6 @@ -import axios from 'axios'; - export async function integrationCreate( // eslint-disable-next-line @typescript-eslint/no-explicit-any data: any, - integrationDefinition: any, ) { const { oauthResponse } = data; const integrationConfiguration = { @@ -14,14 +11,14 @@ export async function integrationCreate( scope: oauthResponse.authed_user.scope, }; - const payload = { - settings: {}, - accountId: integrationConfiguration.userId, - config: integrationConfiguration, - integrationDefinitionId: integrationDefinition.id, - }; - - const integrationAccount = (await axios.post(`/api/v1/integration_account`, payload)).data; - - return integrationAccount; + return [ + { + type: 'account', + data: { + settings: {}, + accountId: integrationConfiguration.userId, + config: integrationConfiguration, + }, + }, + ]; } diff --git a/integrations/slack/src/create-activity.ts b/integrations/slack/src/create-activity.ts index 2aa57d4..d6d2698 100644 --- a/integrations/slack/src/create-activity.ts +++ b/integrations/slack/src/create-activity.ts @@ -3,6 +3,23 @@ import axios from 'axios'; import { getUserDetails } from './utils'; +interface SlackActivityCreateParams { + text: string; + sourceURL: string; +} +/** + * Creates an activity message based on Linear data + */ +function createActivityMessage(params: SlackActivityCreateParams) { + return { + type: 'activity', + data: { + text: params.text, + sourceURL: params.sourceURL, + }, + }; +} + async function getMessage(accessToken: string, channel: string, ts: string) { const result = await axios.get('https://slack.com/api/conversations.history', { headers: { @@ -64,7 +81,7 @@ export const createActivityEvent = async ( taskId: null, }; - await axios.post('/api/v1/activity', activity); + return createActivityMessage(activity); } if (eventData.event.type === 'reaction_added' && eventData.event.reaction === 'eyes') { @@ -120,7 +137,7 @@ export const createActivityEvent = async ( integrationAccountId: config.integrationAccountId, }; - await axios.post('/api/v1/activity', activity); + return createActivityMessage(activity); } return { message: `Processed activity from slack` }; }; diff --git a/integrations/slack/src/index.ts b/integrations/slack/src/index.ts index 4cb4537..3f421fc 100644 --- a/integrations/slack/src/index.ts +++ b/integrations/slack/src/index.ts @@ -10,7 +10,7 @@ import { export async function run(eventPayload: IntegrationEventPayload) { switch (eventPayload.event) { case IntegrationEventType.SETUP: - return await integrationCreate(eventPayload.eventBody, eventPayload.integrationDefinition); + return await integrationCreate(eventPayload.eventBody); case IntegrationEventType.IDENTIFY: return eventPayload.eventBody.event.user; @@ -40,12 +40,10 @@ class SlackCLI extends IntegrationCLI { description: 'Connect your workspace to Slack. Run your workflows from slack bookmarks', icon: 'slack', mcp: { - command: 'npx', - args: ['-y', '@modelcontextprotocol/server-slack'], + command: 'slack-mcp-server', + args: [], env: { - SLACK_BOT_TOKEN: '${config:access_token}', - SLACK_TEAM_ID: '${config:team_id}', - SLACK_CHANNEL_IDS: '${config:channel_ids}', + SLACK_MCP_XOXP_TOKEN: '${config:access_token}', }, }, auth: { diff --git a/package.json b/package.json index 0d4e7d7..36023bb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "core", "private": true, - "version": "0.1.10", + "version": "0.1.11", "workspaces": [ "apps/*", "packages/*" diff --git a/packages/core-cli/package.json b/packages/core-cli/package.json index 31c3cd1..d76c865 100644 --- a/packages/core-cli/package.json +++ b/packages/core-cli/package.json @@ -1,6 +1,6 @@ { "name": "@redplanethq/core", - "version": "0.1.6", + "version": "0.1.8", "description": "A Command-Line Interface for Core", "type": "module", "license": "MIT", diff --git a/packages/core-cli/src/cli/index.ts b/packages/core-cli/src/cli/index.ts index 5b145cf..8157f4b 100644 --- a/packages/core-cli/src/cli/index.ts +++ b/packages/core-cli/src/cli/index.ts @@ -2,24 +2,19 @@ import { Command } from "commander"; import { initCommand } from "../commands/init.js"; import { startCommand } from "../commands/start.js"; import { stopCommand } from "../commands/stop.js"; +import { VERSION } from "./version.js"; const program = new Command(); -program.name("core").description("Core CLI - A Command-Line Interface for Core").version("0.1.0"); +program.name("core").description("Core CLI - A Command-Line Interface for Core").version(VERSION); program .command("init") .description("Initialize Core development environment (run once)") .action(initCommand); -program - .command("start") - .description("Start Core development environment") - .action(startCommand); +program.command("start").description("Start Core development environment").action(startCommand); -program - .command("stop") - .description("Stop Core development environment") - .action(stopCommand); +program.command("stop").description("Stop Core development environment").action(stopCommand); program.parse(process.argv); diff --git a/packages/core-cli/src/cli/version.ts b/packages/core-cli/src/cli/version.ts new file mode 100644 index 0000000..a0fb2e7 --- /dev/null +++ b/packages/core-cli/src/cli/version.ts @@ -0,0 +1 @@ +export const VERSION = "0.1.7"; diff --git a/packages/core-cli/src/commands/init.ts b/packages/core-cli/src/commands/init.ts index 5820195..a8d543f 100644 --- a/packages/core-cli/src/commands/init.ts +++ b/packages/core-cli/src/commands/init.ts @@ -10,6 +10,8 @@ import { deployTriggerTasks } from "../utils/trigger-deploy.js"; import path from "path"; import * as fs from "fs"; import { createTriggerConfigJson, initTriggerDatabase } from "../utils/database-init.js"; +import { parse } from "dotenv"; +import { expand } from "dotenv-expand"; export async function initCommand() { // Display the CORE brain logo @@ -179,10 +181,17 @@ export async function initCommand() { // Step 12: Restart root docker-compose with new configuration try { + const file = fs.readFileSync(envPath); + + const parsed = parse(file); + const envVarsExpand = expand({ parsed, processEnv: {} }).parsed || {}; + + console.log(envVarsExpand); await executeCommandInteractive("docker compose up -d", { cwd: rootDir, message: "Starting Core services with new Trigger.dev configuration...", showOutput: true, + env: envVarsExpand, }); } catch (error: any) { outro("❌ Setup failed: " + error.message); diff --git a/packages/core-cli/src/commands/start.ts b/packages/core-cli/src/commands/start.ts index 00cbbef..eba14c3 100644 --- a/packages/core-cli/src/commands/start.ts +++ b/packages/core-cli/src/commands/start.ts @@ -1,7 +1,8 @@ -import { intro, outro, note, log, confirm } from "@clack/prompts"; +import { intro, outro, note, log } from "@clack/prompts"; import { executeCommandInteractive } from "../utils/docker-interactive.js"; import { printCoreBrainLogo } from "../utils/ascii.js"; import path from "path"; +import * as fs from "fs"; export async function startCommand() { // Display the CORE brain logo @@ -10,9 +11,19 @@ export async function startCommand() { intro("🚀 Starting Core Development Environment"); // Step 1: Confirm this is the Core repository - const isCoreRepo = await confirm({ - message: "Are you currently in the Core repository directory?", - }); + // Check if package.json name has "core" in it, else exit + const pkgPath = path.join(process.cwd(), "package.json"); + let isCoreRepo = false; + try { + if (fs.existsSync(pkgPath)) { + const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8")); + if (typeof pkg.name === "string" && pkg.name.includes("core")) { + isCoreRepo = true; + } + } + } catch (err) { + // ignore, will prompt below + } if (!isCoreRepo) { note( diff --git a/packages/core-cli/src/commands/stop.ts b/packages/core-cli/src/commands/stop.ts index 111222b..e384cb3 100644 --- a/packages/core-cli/src/commands/stop.ts +++ b/packages/core-cli/src/commands/stop.ts @@ -1,7 +1,8 @@ -import { intro, outro, log, confirm, note } from "@clack/prompts"; +import { intro, outro, log, note } from "@clack/prompts"; import { executeCommandInteractive } from "../utils/docker-interactive.js"; import { printCoreBrainLogo } from "../utils/ascii.js"; import path from "path"; +import * as fs from "fs"; export async function stopCommand() { // Display the CORE brain logo @@ -10,10 +11,19 @@ export async function stopCommand() { intro("🛑 Stopping Core Development Environment"); // Step 1: Confirm this is the Core repository - const isCoreRepo = await confirm({ - message: "Are you currently in the Core repository directory?", - }); - + // Check if package.json name has "core" in it, else exit + const pkgPath = path.join(process.cwd(), "package.json"); + let isCoreRepo = false; + try { + if (fs.existsSync(pkgPath)) { + const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8")); + if (typeof pkg.name === "string" && pkg.name.includes("core")) { + isCoreRepo = true; + } + } + } catch (err) { + // ignore, will prompt below + } if (!isCoreRepo) { note( 'Please navigate to the Core repository first:\n\ngit clone https://github.com/redplanethq/core.git\ncd core\n\nThen run "core stop" again.', diff --git a/packages/core-cli/src/utils/ascii.ts b/packages/core-cli/src/utils/ascii.ts index 6b5dbfb..5df2765 100644 --- a/packages/core-cli/src/utils/ascii.ts +++ b/packages/core-cli/src/utils/ascii.ts @@ -1,4 +1,5 @@ import chalk from "chalk"; +import { VERSION } from "../cli/version.js"; export function printCoreBrainLogo(): void { const brain = ` @@ -20,5 +21,9 @@ export function printCoreBrainLogo(): void { `; console.log(chalk.cyan(brain)); - console.log(chalk.bold.white(" 🧠 CORE - Contextual Observation & Recall Engine \n")); + console.log( + chalk.bold.white( + ` 🧠 CORE - Contextual Observation & Recall Engine ${VERSION ? chalk.gray(`(${VERSION})`) : ""}\n` + ) + ); } diff --git a/packages/core-cli/src/utils/database-init.ts b/packages/core-cli/src/utils/database-init.ts index 3e7ddc0..3a5c460 100644 --- a/packages/core-cli/src/utils/database-init.ts +++ b/packages/core-cli/src/utils/database-init.ts @@ -2,14 +2,14 @@ import Knex, { Knex as KnexT } from "knex"; import { v4 as uuidv4 } from "uuid"; import nodeCrypto from "node:crypto"; -import dotenv from "dotenv"; -import dotenvExpand from "dotenv-expand"; +import { parse } from "dotenv"; +import { expand } from "dotenv-expand"; import path from "node:path"; import { log } from "@clack/prompts"; import { customAlphabet } from "nanoid"; import $xdgAppPaths from "xdg-app-paths"; -import { mkdirSync, writeFileSync } from "node:fs"; +import { mkdirSync, readFileSync, writeFileSync } from "node:fs"; export const xdgAppPaths = $xdgAppPaths as unknown as typeof $xdgAppPaths.default; @@ -241,8 +241,10 @@ export async function initTriggerDatabase(triggerDir: string) { const envPath = path.join(triggerDir, ".env"); log.step(`Loading environment variables from ${envPath}...`); - const envVarsExpand = - dotenvExpand.expand(dotenv.config({ path: envPath, processEnv: {} })).parsed || {}; + const file = readFileSync(envPath); + + const parsed = parse(file); + const envVarsExpand = expand({ parsed, processEnv: {} }).parsed || {}; // Set the encryption key from the .env file ENCRYPTION_KEY = envVarsExpand.ENCRYPTION_KEY as string; diff --git a/packages/core-cli/src/utils/docker-interactive.ts b/packages/core-cli/src/utils/docker-interactive.ts index 1cd59d4..46eb5f3 100644 --- a/packages/core-cli/src/utils/docker-interactive.ts +++ b/packages/core-cli/src/utils/docker-interactive.ts @@ -10,6 +10,8 @@ export interface CommandOptions { export function executeCommandInteractive(command: string, options: CommandOptions): Promise { return new Promise((resolve, reject) => { + console.log(process.env); + const s = spinner(); s.start(options.message); @@ -27,7 +29,7 @@ export function executeCommandInteractive(command: string, options: CommandOptio cwd: options.cwd, stdio: options.showOutput ? ["ignore", "pipe", "pipe"] : "ignore", detached: false, - env: options.env ? { ...process.env, ...options.env } : {}, + env: options.env ? { ...process.env, ...options.env } : { ...process.env }, }); let output = ""; diff --git a/packages/core-cli/src/utils/env-docker.ts b/packages/core-cli/src/utils/env-docker.ts index 9fe37e9..88db0c0 100644 --- a/packages/core-cli/src/utils/env-docker.ts +++ b/packages/core-cli/src/utils/env-docker.ts @@ -1,7 +1,8 @@ import path from "path"; -import dotenv from "dotenv"; -import dotenvExpand from "dotenv-expand"; +import { parse } from "dotenv"; +import { expand } from "dotenv-expand"; +import * as fs from "fs"; /** * Reads environment variables from .env file and replaces localhost URLs with host.docker.internal @@ -12,8 +13,10 @@ export async function getDockerCompatibleEnvVars(rootDir: string): Promise { return envVarsExpand[key] || ""; diff --git a/packages/core-cli/src/utils/trigger-deploy.ts b/packages/core-cli/src/utils/trigger-deploy.ts index e679f41..50a3c7a 100644 --- a/packages/core-cli/src/utils/trigger-deploy.ts +++ b/packages/core-cli/src/utils/trigger-deploy.ts @@ -2,7 +2,6 @@ import { note, log } from "@clack/prompts"; import { executeCommandInteractive } from "./docker-interactive.js"; import { getDockerCompatibleEnvVars } from "./env-docker.js"; import path from "path"; -import { createTriggerConfigJson } from "./database-init.js"; export async function deployTriggerTasks(rootDir: string): Promise { const webappDir = path.join(rootDir, "apps", "webapp"); diff --git a/packages/database/prisma/migrations/20250723162344_modify_client_for_dymanic_creation/migration.sql b/packages/database/prisma/migrations/20250723162344_modify_client_for_dymanic_creation/migration.sql new file mode 100644 index 0000000..251c030 --- /dev/null +++ b/packages/database/prisma/migrations/20250723162344_modify_client_for_dymanic_creation/migration.sql @@ -0,0 +1,10 @@ +-- DropForeignKey +ALTER TABLE "OAuthClient" DROP CONSTRAINT "OAuthClient_createdById_fkey"; + +-- AlterTable +ALTER TABLE "OAuthClient" ADD COLUMN "clientType" TEXT NOT NULL DEFAULT 'regular', +ALTER COLUMN "workspaceId" DROP NOT NULL, +ALTER COLUMN "createdById" DROP NOT NULL; + +-- AddForeignKey +ALTER TABLE "OAuthClient" ADD CONSTRAINT "OAuthClient_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/packages/database/prisma/schema.prisma b/packages/database/prisma/schema.prisma index 9d6187f..476b6cb 100644 --- a/packages/database/prisma/schema.prisma +++ b/packages/database/prisma/schema.prisma @@ -287,6 +287,8 @@ model OAuthClient { // PKCE support requirePkce Boolean @default(false) + clientType String @default("regular") + // Client metadata logoUrl String? homepageUrl String? @@ -299,12 +301,12 @@ model OAuthClient { isActive Boolean @default(true) // Workspace relationship (like GitHub orgs) - workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade) - workspaceId String + workspace Workspace? @relation(fields: [workspaceId], references: [id], onDelete: Cascade) + workspaceId String? // Created by user (for audit trail) - createdBy User @relation(fields: [createdById], references: [id]) - createdById String + createdBy User? @relation(fields: [createdById], references: [id]) + createdById String? // Relations oauthAuthorizationCodes OAuthAuthorizationCode[] diff --git a/packages/mcp-proxy/src/core/mcp-remote-client.ts b/packages/mcp-proxy/src/core/mcp-remote-client.ts index ec093f6..4d17d2b 100644 --- a/packages/mcp-proxy/src/core/mcp-remote-client.ts +++ b/packages/mcp-proxy/src/core/mcp-remote-client.ts @@ -569,6 +569,7 @@ export class MCPAuthenticationClient { // } // } + console.log("completeOAuthFlow", options); // Use the NodeOAuthClientProvider's completeAuth method await authProvider.completeAuth({ authorizationCode: options.authorizationCode, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 49a478d..d0a062b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -114,6 +114,9 @@ importers: '@radix-ui/react-separator': specifier: ^1.1.7 version: 1.1.7(@types/react-dom@18.3.7(@types/react@18.2.69))(@types/react@18.2.69)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slider': + specifier: ^1.3.5 + version: 1.3.5(@types/react-dom@18.3.7(@types/react@18.2.69))(@types/react@18.2.69)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slot': specifier: ^1.2.3 version: 1.2.3(@types/react@18.2.69)(react@18.3.1) @@ -3330,6 +3333,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-slider@1.3.5': + resolution: {integrity: sha512-rkfe2pU2NBAYfGaxa3Mqosi7VZEWX5CxKaanRv0vZd4Zhl9fvQrg0VM93dv3xGLGfrHuoTRF3JXH8nb9g+B3fw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-slot@1.0.0': resolution: {integrity: sha512-3mrKauI/tWXo1Ll+gN5dHcxDPdm/Df1ufcDLCecn+pnCIVcdWE7CujXo8QaXOWRJyZyQWWbpB8eFwHzWXlv5mQ==} peerDependencies: @@ -14014,6 +14030,25 @@ snapshots: '@types/react': 18.2.69 '@types/react-dom': 18.3.7(@types/react@18.2.69) + '@radix-ui/react-slider@1.3.5(@types/react-dom@18.3.7(@types/react@18.2.69))(@types/react@18.2.69)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/number': 1.1.1 + '@radix-ui/primitive': 1.1.2 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.7(@types/react@18.2.69))(@types/react@18.2.69)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.2.69)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.2.69)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@18.2.69)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.2.69))(@types/react@18.2.69)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.2.69)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.2.69)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.1(@types/react@18.2.69)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.1(@types/react@18.2.69)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.2.69 + '@types/react-dom': 18.3.7(@types/react@18.2.69) + '@radix-ui/react-slot@1.0.0(react@18.3.1)': dependencies: '@babel/runtime': 7.27.6 diff --git a/trigger/.env.example b/trigger/.env.example index 78902ca..8492b68 100644 --- a/trigger/.env.example +++ b/trigger/.env.example @@ -33,7 +33,6 @@ TRIGGER_DB=trigger DB_HOST=host.docker.internal DB_PORT=5432 -DB_SCHEMA=sigma # POSTGRES_DB=postgres