mirror of
https://github.com/eliasstepanik/core.git
synced 2026-01-11 09:08:28 +00:00
feat: add copy
This commit is contained in:
parent
e358dadf5a
commit
7319930048
@ -1,4 +1,4 @@
|
||||
import { EllipsisVertical, Trash } from "lucide-react";
|
||||
import { EllipsisVertical, Trash, Copy } from "lucide-react";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
@ -18,6 +18,7 @@ import {
|
||||
} from "../ui/alert-dialog";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useFetcher, useNavigate } from "@remix-run/react";
|
||||
import { toast } from "~/hooks/use-toast";
|
||||
|
||||
interface LogOptionsProps {
|
||||
id: string;
|
||||
@ -40,6 +41,23 @@ export const LogOptions = ({ id }: LogOptionsProps) => {
|
||||
setDeleteDialogOpen(false);
|
||||
};
|
||||
|
||||
const handleCopy = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(id);
|
||||
toast({
|
||||
title: "Copied",
|
||||
description: "Episode ID copied to clipboard",
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("Failed to copy:", err);
|
||||
toast({
|
||||
title: "Error",
|
||||
description: "Failed to copy ID",
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (deleteFetcher.state === "idle" && deleteFetcher.data?.success) {
|
||||
navigate(`/home/inbox`);
|
||||
@ -48,16 +66,26 @@ export const LogOptions = ({ id }: LogOptionsProps) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
className="gap-2 rounded"
|
||||
onClick={(e) => {
|
||||
setDeleteDialogOpen(true);
|
||||
}}
|
||||
>
|
||||
<Trash size={15} /> Delete
|
||||
</Button>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
className="gap-2 rounded"
|
||||
onClick={handleCopy}
|
||||
>
|
||||
<Copy size={15} /> Copy ID
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
className="gap-2 rounded"
|
||||
onClick={(e) => {
|
||||
setDeleteDialogOpen(true);
|
||||
}}
|
||||
>
|
||||
<Trash size={15} /> Delete
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<AlertDialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}>
|
||||
<AlertDialogContent>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { EllipsisVertical, RefreshCcw, Trash, Edit } from "lucide-react";
|
||||
import { EllipsisVertical, RefreshCcw, Trash, Edit, Copy } from "lucide-react";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
@ -19,6 +19,7 @@ import {
|
||||
import { useEffect, useState } from "react";
|
||||
import { useFetcher, useNavigate } from "@remix-run/react";
|
||||
import { EditSpaceDialog } from "./edit-space-dialog.client";
|
||||
import { toast } from "~/hooks/use-toast";
|
||||
|
||||
interface SpaceOptionsProps {
|
||||
id: string;
|
||||
@ -64,6 +65,23 @@ export const SpaceOptions = ({ id, name, description }: SpaceOptionsProps) => {
|
||||
// revalidator.revalidate();
|
||||
};
|
||||
|
||||
const handleCopy = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(id);
|
||||
toast({
|
||||
title: "Copied",
|
||||
description: "Space ID copied to clipboard",
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("Failed to copy:", err);
|
||||
toast({
|
||||
title: "Error",
|
||||
description: "Failed to copy ID",
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<DropdownMenu>
|
||||
@ -79,6 +97,11 @@ export const SpaceOptions = ({ id, name, description }: SpaceOptionsProps) => {
|
||||
</DropdownMenuTrigger>
|
||||
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuItem onClick={handleCopy}>
|
||||
<Button variant="link" size="sm" className="gap-2 rounded">
|
||||
<Copy size={15} /> Copy ID
|
||||
</Button>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => setEditDialogOpen(true)}>
|
||||
<Button variant="link" size="sm" className="gap-2 rounded">
|
||||
<Edit size={15} /> Edit
|
||||
|
||||
@ -2,3 +2,5 @@ export * from "./button";
|
||||
export * from "./tabs";
|
||||
export * from "./input";
|
||||
export * from "./scrollarea";
|
||||
export * from "./toast";
|
||||
export * from "./toaster";
|
||||
|
||||
133
apps/webapp/app/components/ui/toast.tsx
Normal file
133
apps/webapp/app/components/ui/toast.tsx
Normal file
@ -0,0 +1,133 @@
|
||||
import { Cross2Icon } from "@radix-ui/react-icons";
|
||||
import * as ToastPrimitives from "@radix-ui/react-toast";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import React from "react";
|
||||
|
||||
import { cn } from "../../lib/utils";
|
||||
|
||||
const ToastProvider = ToastPrimitives.Provider;
|
||||
|
||||
const ToastViewport = React.forwardRef<
|
||||
React.ElementRef<typeof ToastPrimitives.Viewport>,
|
||||
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<ToastPrimitives.Viewport
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:top-auto sm:right-0 sm:bottom-0 sm:flex-col md:max-w-[420px]",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
|
||||
|
||||
const toastVariants = cva(
|
||||
"group pointer-events-auto relative flex w-full items-center justify-between space-x-2 overflow-hidden rounded-md border p-3 pr-6 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "border bg-background text-foreground",
|
||||
warning: "warning group border-warning bg-warning text-foreground",
|
||||
success: "success group border-success bg-success text-foreground",
|
||||
destructive:
|
||||
"destructive group border-destructive bg-destructive text-foreground",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const Toast = React.forwardRef<
|
||||
React.ElementRef<typeof ToastPrimitives.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> &
|
||||
VariantProps<typeof toastVariants>
|
||||
>(({ className, variant, ...props }, ref) => {
|
||||
return (
|
||||
<ToastPrimitives.Root
|
||||
ref={ref}
|
||||
className={cn(
|
||||
toastVariants({ variant }),
|
||||
className,
|
||||
"shadow-1 rounded-md border-0 bg-gray-100 font-sans backdrop-blur-md",
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
});
|
||||
Toast.displayName = ToastPrimitives.Root.displayName;
|
||||
|
||||
const ToastAction = React.forwardRef<
|
||||
React.ElementRef<typeof ToastPrimitives.Action>,
|
||||
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<ToastPrimitives.Action
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"hover:bg-secondary focus:ring-ring group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium transition-colors focus:ring-1 focus:outline-none disabled:pointer-events-none disabled:opacity-50",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
ToastAction.displayName = ToastPrimitives.Action.displayName;
|
||||
|
||||
const ToastClose = React.forwardRef<
|
||||
React.ElementRef<typeof ToastPrimitives.Close>,
|
||||
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<ToastPrimitives.Close
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"text-foreground/50 hover:text-foreground absolute top-1 right-1 rounded-md p-1 opacity-0 transition-opacity group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 focus:opacity-100 focus:ring-1 focus:outline-none group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600",
|
||||
className,
|
||||
)}
|
||||
toast-close=""
|
||||
{...props}
|
||||
>
|
||||
<Cross2Icon className="h-4 w-4" />
|
||||
</ToastPrimitives.Close>
|
||||
));
|
||||
ToastClose.displayName = ToastPrimitives.Close.displayName;
|
||||
|
||||
const ToastTitle = React.forwardRef<
|
||||
React.ElementRef<typeof ToastPrimitives.Title>,
|
||||
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<ToastPrimitives.Title
|
||||
ref={ref}
|
||||
className={cn("font-medium [&+div]:text-xs", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
ToastTitle.displayName = ToastPrimitives.Title.displayName;
|
||||
|
||||
const ToastDescription = React.forwardRef<
|
||||
React.ElementRef<typeof ToastPrimitives.Description>,
|
||||
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<ToastPrimitives.Description
|
||||
ref={ref}
|
||||
className={cn("opacity-90", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
ToastDescription.displayName = ToastPrimitives.Description.displayName;
|
||||
|
||||
type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>;
|
||||
|
||||
type ToastActionElement = React.ReactElement<typeof ToastAction>;
|
||||
|
||||
export {
|
||||
type ToastProps,
|
||||
type ToastActionElement,
|
||||
ToastProvider,
|
||||
ToastViewport,
|
||||
Toast,
|
||||
ToastTitle,
|
||||
ToastDescription,
|
||||
ToastClose,
|
||||
ToastAction,
|
||||
};
|
||||
33
apps/webapp/app/components/ui/toaster.tsx
Normal file
33
apps/webapp/app/components/ui/toaster.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
import {
|
||||
Toast,
|
||||
ToastClose,
|
||||
ToastDescription,
|
||||
ToastProvider,
|
||||
ToastTitle,
|
||||
ToastViewport,
|
||||
} from "~/components/ui/toast";
|
||||
import { useToast } from "~/hooks/use-toast";
|
||||
|
||||
export function Toaster() {
|
||||
const { toasts } = useToast();
|
||||
|
||||
return (
|
||||
<ToastProvider>
|
||||
{toasts.map(function ({ id, title, description, action, ...props }) {
|
||||
return (
|
||||
<Toast key={id} {...props}>
|
||||
<div className="grid gap-1">
|
||||
{title && <ToastTitle>{title}</ToastTitle>}
|
||||
{description && (
|
||||
<ToastDescription>{description}</ToastDescription>
|
||||
)}
|
||||
</div>
|
||||
{action}
|
||||
<ToastClose />
|
||||
</Toast>
|
||||
);
|
||||
})}
|
||||
<ToastViewport />
|
||||
</ToastProvider>
|
||||
);
|
||||
}
|
||||
186
apps/webapp/app/hooks/use-toast.ts
Normal file
186
apps/webapp/app/hooks/use-toast.ts
Normal file
@ -0,0 +1,186 @@
|
||||
import * as React from "react";
|
||||
|
||||
import type { ToastActionElement, ToastProps } from "~/components/ui/toast";
|
||||
|
||||
const TOAST_LIMIT = 1;
|
||||
const TOAST_REMOVE_DELAY = 1000000;
|
||||
|
||||
type ToasterToast = ToastProps & {
|
||||
id: string;
|
||||
title?: React.ReactNode;
|
||||
description?: React.ReactNode;
|
||||
action?: ToastActionElement;
|
||||
};
|
||||
|
||||
const actionTypes = {
|
||||
ADD_TOAST: "ADD_TOAST",
|
||||
UPDATE_TOAST: "UPDATE_TOAST",
|
||||
DISMISS_TOAST: "DISMISS_TOAST",
|
||||
REMOVE_TOAST: "REMOVE_TOAST",
|
||||
} as const;
|
||||
|
||||
let count = 0;
|
||||
|
||||
function genId() {
|
||||
count = (count + 1) % Number.MAX_SAFE_INTEGER;
|
||||
return count.toString();
|
||||
}
|
||||
|
||||
type ActionType = typeof actionTypes;
|
||||
|
||||
type Action =
|
||||
| {
|
||||
type: ActionType["ADD_TOAST"];
|
||||
toast: ToasterToast;
|
||||
}
|
||||
| {
|
||||
type: ActionType["UPDATE_TOAST"];
|
||||
toast: Partial<ToasterToast>;
|
||||
}
|
||||
| {
|
||||
type: ActionType["DISMISS_TOAST"];
|
||||
toastId?: ToasterToast["id"];
|
||||
}
|
||||
| {
|
||||
type: ActionType["REMOVE_TOAST"];
|
||||
toastId?: ToasterToast["id"];
|
||||
};
|
||||
|
||||
interface State {
|
||||
toasts: ToasterToast[];
|
||||
}
|
||||
|
||||
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();
|
||||
|
||||
const addToRemoveQueue = (toastId: string) => {
|
||||
if (toastTimeouts.has(toastId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
toastTimeouts.delete(toastId);
|
||||
dispatch({
|
||||
type: "REMOVE_TOAST",
|
||||
toastId: toastId,
|
||||
});
|
||||
}, TOAST_REMOVE_DELAY);
|
||||
|
||||
toastTimeouts.set(toastId, timeout);
|
||||
};
|
||||
|
||||
export const reducer = (state: State, action: Action): State => {
|
||||
switch (action.type) {
|
||||
case "ADD_TOAST":
|
||||
return {
|
||||
...state,
|
||||
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
|
||||
};
|
||||
|
||||
case "UPDATE_TOAST":
|
||||
return {
|
||||
...state,
|
||||
toasts: state.toasts.map((t) =>
|
||||
t.id === action.toast.id ? { ...t, ...action.toast } : t,
|
||||
),
|
||||
};
|
||||
|
||||
case "DISMISS_TOAST": {
|
||||
const { toastId } = action;
|
||||
|
||||
if (toastId) {
|
||||
addToRemoveQueue(toastId);
|
||||
} else {
|
||||
state.toasts.forEach((toast) => {
|
||||
addToRemoveQueue(toast.id);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
toasts: state.toasts.map((t) =>
|
||||
t.id === toastId || toastId === undefined
|
||||
? {
|
||||
...t,
|
||||
open: false,
|
||||
}
|
||||
: t,
|
||||
),
|
||||
};
|
||||
}
|
||||
case "REMOVE_TOAST":
|
||||
if (action.toastId === undefined) {
|
||||
return {
|
||||
...state,
|
||||
toasts: [],
|
||||
};
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
toasts: state.toasts.filter((t) => t.id !== action.toastId),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const listeners: Array<(state: State) => void> = [];
|
||||
|
||||
let memoryState: State = { toasts: [] };
|
||||
|
||||
function dispatch(action: Action) {
|
||||
memoryState = reducer(memoryState, action);
|
||||
listeners.forEach((listener) => {
|
||||
listener(memoryState);
|
||||
});
|
||||
}
|
||||
|
||||
type Toast = Omit<ToasterToast, "id">;
|
||||
|
||||
function toast({ ...props }: Toast) {
|
||||
const id = genId();
|
||||
|
||||
const update = (props: ToasterToast) =>
|
||||
dispatch({
|
||||
type: "UPDATE_TOAST",
|
||||
toast: { ...props, id },
|
||||
});
|
||||
const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id });
|
||||
|
||||
dispatch({
|
||||
type: "ADD_TOAST",
|
||||
toast: {
|
||||
...props,
|
||||
id,
|
||||
open: true,
|
||||
onOpenChange: (open) => {
|
||||
if (!open) dismiss();
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
id: id,
|
||||
dismiss,
|
||||
update,
|
||||
};
|
||||
}
|
||||
|
||||
function useToast() {
|
||||
const [state, setState] = React.useState<State>(memoryState);
|
||||
|
||||
React.useEffect(() => {
|
||||
listeners.push(setState);
|
||||
return () => {
|
||||
const index = listeners.indexOf(setState);
|
||||
if (index > -1) {
|
||||
listeners.splice(index, 1);
|
||||
}
|
||||
};
|
||||
}, [state]);
|
||||
|
||||
return {
|
||||
...state,
|
||||
toast,
|
||||
dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
|
||||
};
|
||||
}
|
||||
|
||||
export { useToast, toast };
|
||||
@ -41,6 +41,7 @@ import {
|
||||
} from "remix-themes";
|
||||
import clsx from "clsx";
|
||||
import { getUsageSummary } from "./services/billing.server";
|
||||
import { Toaster } from "./components/ui/toaster";
|
||||
|
||||
export const links: LinksFunction = () => [{ rel: "stylesheet", href: styles }];
|
||||
|
||||
@ -126,6 +127,7 @@ function App() {
|
||||
</head>
|
||||
<body className="bg-background-2 h-[100vh] h-full w-[100vw] overflow-hidden font-sans">
|
||||
<Outlet />
|
||||
<Toaster />
|
||||
<ScrollRestoration />
|
||||
|
||||
<Scripts />
|
||||
|
||||
@ -72,27 +72,6 @@ async function createMcpServer(
|
||||
);
|
||||
}
|
||||
|
||||
// Handle integration tools (prefixed with integration slug)
|
||||
if (name.includes("_") && !name.startsWith("memory_")) {
|
||||
try {
|
||||
return await IntegrationLoader.callIntegrationTool(
|
||||
sessionId,
|
||||
name,
|
||||
args,
|
||||
);
|
||||
} catch (error) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Error calling integration tool: ${error instanceof Error ? error.message : String(error)}`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(`Unknown tool: ${name}`);
|
||||
});
|
||||
|
||||
|
||||
@ -14,7 +14,8 @@ const SearchParamsSchema = {
|
||||
properties: {
|
||||
query: {
|
||||
type: "string",
|
||||
description: "Search query as a simple statement or question. Write what you want to find, not a command. GOOD: 'user preferences for code style' or 'previous bugs in authentication' or 'GitHub integration setup'. BAD: 'search for' or 'find me' or 'get the'. Just state the topic directly.",
|
||||
description:
|
||||
"Search query as a simple statement or question. Write what you want to find, not a command. GOOD: 'user preferences for code style' or 'previous bugs in authentication' or 'GitHub integration setup'. BAD: 'search for' or 'find me' or 'get the'. Just state the topic directly.",
|
||||
},
|
||||
validAt: {
|
||||
type: "string",
|
||||
@ -36,7 +37,8 @@ const SearchParamsSchema = {
|
||||
items: {
|
||||
type: "string",
|
||||
},
|
||||
description: "Optional: Array of space UUIDs to search within. Leave empty to search all spaces.",
|
||||
description:
|
||||
"Optional: Array of space UUIDs to search within. Leave empty to search all spaces.",
|
||||
},
|
||||
},
|
||||
required: ["query"],
|
||||
@ -47,14 +49,16 @@ const IngestSchema = {
|
||||
properties: {
|
||||
message: {
|
||||
type: "string",
|
||||
description: "The conversation text to store. Include both what the user asked and what you answered. Keep it concise but complete.",
|
||||
description:
|
||||
"The conversation text to store. Include both what the user asked and what you answered. Keep it concise but complete.",
|
||||
},
|
||||
spaceIds: {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "string",
|
||||
},
|
||||
description: "Optional: Array of space UUIDs (from memory_get_spaces). Add this to organize the memory by project. Example: If discussing 'core' project, include the 'core' space ID. Leave empty to store in general memory.",
|
||||
description:
|
||||
"Optional: Array of space UUIDs (from memory_get_spaces). Add this to organize the memory by project. Example: If discussing 'core' project, include the 'core' space ID. Leave empty to store in general memory.",
|
||||
},
|
||||
},
|
||||
required: ["message"],
|
||||
@ -82,7 +86,8 @@ export const memoryTools = [
|
||||
properties: {
|
||||
all: {
|
||||
type: "boolean",
|
||||
description: "Set to true to get all spaces including system spaces. Leave empty for user spaces only.",
|
||||
description:
|
||||
"Set to true to get all spaces including system spaces. Leave empty for user spaces only.",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -96,7 +101,8 @@ export const memoryTools = [
|
||||
properties: {
|
||||
profile: {
|
||||
type: "boolean",
|
||||
description: "Set to true to get full profile. Leave empty for default profile view.",
|
||||
description:
|
||||
"Set to true to get full profile. Leave empty for default profile view.",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -110,11 +116,13 @@ export const memoryTools = [
|
||||
properties: {
|
||||
spaceId: {
|
||||
type: "string",
|
||||
description: "UUID of the space (use this if you have the ID from memory_get_spaces)",
|
||||
description:
|
||||
"UUID of the space (use this if you have the ID from memory_get_spaces)",
|
||||
},
|
||||
spaceName: {
|
||||
type: "string",
|
||||
description: "Name of the space (easier option). Examples: 'core', 'Profile', 'GitHub', 'Health'",
|
||||
description:
|
||||
"Name of the space (easier option). Examples: 'core', 'Profile', 'GitHub', 'Health'",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -137,7 +145,8 @@ export const memoryTools = [
|
||||
properties: {
|
||||
integrationSlug: {
|
||||
type: "string",
|
||||
description: "Slug from get_integrations. Examples: 'github', 'linear', 'slack'",
|
||||
description:
|
||||
"Slug from get_integrations. Examples: 'github', 'linear', 'slack'",
|
||||
},
|
||||
},
|
||||
required: ["integrationSlug"],
|
||||
@ -152,15 +161,18 @@ export const memoryTools = [
|
||||
properties: {
|
||||
integrationSlug: {
|
||||
type: "string",
|
||||
description: "Slug from get_integrations. Examples: 'github', 'linear', 'slack'",
|
||||
description:
|
||||
"Slug from get_integrations. Examples: 'github', 'linear', 'slack'",
|
||||
},
|
||||
action: {
|
||||
type: "string",
|
||||
description: "Action name from get_integration_actions. Examples: 'get_pr', 'get_issues', 'create_issue'",
|
||||
description:
|
||||
"Action name from get_integration_actions. Examples: 'get_pr', 'get_issues', 'create_issue'",
|
||||
},
|
||||
arguments: {
|
||||
type: "object",
|
||||
description: "Parameters for the action. Check the action's inputSchema from get_integration_actions to see what's required.",
|
||||
description:
|
||||
"Parameters for the action. Check the action's inputSchema from get_integration_actions to see what's required.",
|
||||
},
|
||||
},
|
||||
required: ["integrationSlug", "action"],
|
||||
@ -242,7 +254,8 @@ async function handleUserProfile(userId: string) {
|
||||
async function handleMemoryIngest(args: any) {
|
||||
try {
|
||||
// Use spaceIds from args if provided, otherwise use spaceId from query params
|
||||
const spaceIds = args.spaceIds || (args.spaceId ? [args.spaceId] : undefined);
|
||||
const spaceIds =
|
||||
args.spaceIds || (args.spaceId ? [args.spaceId] : undefined);
|
||||
|
||||
const response = await addToQueue(
|
||||
{
|
||||
@ -284,7 +297,8 @@ async function handleMemoryIngest(args: any) {
|
||||
async function handleMemorySearch(args: any) {
|
||||
try {
|
||||
// Use spaceIds from args if provided, otherwise use spaceId from query params
|
||||
const spaceIds = args.spaceIds || (args.spaceId ? [args.spaceId] : undefined);
|
||||
const spaceIds =
|
||||
args.spaceIds || (args.spaceId ? [args.spaceId] : undefined);
|
||||
|
||||
const results = await searchService.search(
|
||||
args.query,
|
||||
@ -328,7 +342,6 @@ async function handleMemoryGetSpaces(userId: string) {
|
||||
const simplifiedSpaces = spaces.map((space) => ({
|
||||
id: space.id,
|
||||
name: space.name,
|
||||
description: space.description,
|
||||
}));
|
||||
|
||||
return {
|
||||
@ -379,7 +392,6 @@ async function handleGetSpace(args: any) {
|
||||
const spaceDetails = {
|
||||
id: space.id,
|
||||
name: space.name,
|
||||
description: space.description,
|
||||
summary: space.summary,
|
||||
};
|
||||
|
||||
@ -426,7 +438,7 @@ async function handleGetIntegrations(args: any) {
|
||||
slug: account.integrationDefinition.slug,
|
||||
name: account.integrationDefinition.name,
|
||||
accountId: account.id,
|
||||
hasMcp: !!(account.integrationDefinition.spec?.mcp),
|
||||
hasMcp: !!account.integrationDefinition.spec?.mcp,
|
||||
}));
|
||||
|
||||
return {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user