Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: remove playground tools + add tool results + misc fixes #566

Merged
merged 6 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions apps/shinkai-desktop/src/components/chat/components/message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,9 @@ export const MessageBase = ({
<AccordionTrigger
className={cn(
'min-w-[10rem] py-0 pr-2 no-underline hover:no-underline',
'transition-colors hover:bg-gray-500 [&>svg]:hidden [&[data-state=open]]:bg-gray-500',
'transition-colors hover:bg-gray-500 [&[data-state=open]]:bg-gray-500',
tool.status !== ToolStatusType.Complete &&
'[&>svg]:hidden',
)}
>
<ToolCard
Expand All @@ -320,18 +322,26 @@ export const MessageBase = ({
toolRouterKey={tool.toolRouterKey}
/>
</AccordionTrigger>
<AccordionContent className="bg-gray-450 rounded-b-lg px-3 pb-3 pt-2 text-xs">
<AccordionContent className="bg-gray-450 flex flex-col gap-1 rounded-b-lg px-3 pb-3 pt-2 text-xs">
{Object.keys(tool.args).length > 0 && (
<span className="font-medium text-white">
{tool.name}(
{Object.keys(tool.args).length > 0 && (
<span className="text-gray-80 font-medium">
<span className="text-gray-80 font-mono font-medium">
{JSON.stringify(tool.args)}
</span>
)}
)
</span>
)}
{tool.result && (
<div>
<span>Response:</span>
<span className="text-gray-80 break-all font-mono">
{JSON.stringify(tool.result, null, 2)}
</span>
</div>
)}
</AccordionContent>
</AccordionItem>
);
Expand Down
162 changes: 87 additions & 75 deletions apps/shinkai-desktop/src/components/chat/conversation-footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ import { cn } from '@shinkai_network/shinkai-ui/utils';
import { partial } from 'filesize';
import { AnimatePresence, motion } from 'framer-motion';
import { Paperclip, X, XIcon } from 'lucide-react';
import { InfoCircleIcon } from 'primereact/icons/infocircle';
import { useEffect, useMemo, useRef } from 'react';
import { useDropzone } from 'react-dropzone';
import { useForm, useWatch } from 'react-hook-form';
Expand Down Expand Up @@ -421,42 +420,14 @@ function ConversationEmptyFooter() {
<>
{isDragActive && <DropFileActive />}
{selectedTool && (
<div className="bg-gray-375 relative max-w-full rounded-lg p-1.5 px-2">
<Tooltip>
<TooltipTrigger asChild>
<div className="flex items-center gap-2 pr-6">
<ToolsIcon className="h-3.5 w-3.5" />
<div className="line-clamp-1 inline-flex items-center gap-2 text-xs text-gray-100">
<span className="text-white">
{formatText(selectedTool.name)}{' '}
</span>
<InfoCircleIcon className="h-3 w-3 shrink-0" />
</div>
</div>
</TooltipTrigger>
<TooltipPortal>
<TooltipContent
align="start"
alignOffset={-10}
className="max-w-[400px]"
side="top"
sideOffset={10}
>
{selectedTool.description}
</TooltipContent>
</TooltipPortal>
</Tooltip>

<button
className="absolute right-2 top-1.5 text-gray-100 hover:text-white"
onClick={() => {
chatForm.setValue('tool', undefined);
}}
type="button"
>
<XIcon className="h-4 w-4" />
</button>
</div>
<SelectedToolChat
args={selectedTool.args ?? []}
description={selectedTool.description}
name={formatText(selectedTool.name)}
remove={() => {
chatForm.setValue('tool', undefined);
}}
/>
)}
{!isDragActive &&
currentFiles &&
Expand Down Expand Up @@ -504,6 +475,9 @@ function ConversationEmptyFooter() {
key: tool.tool_router_key,
name: tool.name,
description: tool.description,
args: Object.keys(
tool.input_args.properties ?? {},
),
});
}}
type="button"
Expand All @@ -513,7 +487,11 @@ function ConversationEmptyFooter() {
</motion.button>
</TooltipTrigger>
<TooltipPortal>
<TooltipContent align="start" side="top">
<TooltipContent
align="start"
className="max-w-[500px]"
side="top"
>
{tool.description}
</TooltipContent>
</TooltipPortal>
Expand All @@ -538,7 +516,6 @@ function ConversationEmptyFooter() {
</div>
);
}

function ConversationChatFooter({ inboxId }: { inboxId: string }) {
const { t } = useTranslation();

Expand Down Expand Up @@ -665,6 +642,7 @@ function ConversationChatFooter({ inboxId }: { inboxId: string }) {
message: data.message,
parent: '', // Note: we should set the parent if we want to retry or branch out
files: currentFiles,
toolKey: selectedTool?.key,
});
} else {
const sender = `${auth.shinkai_identity}/${auth.profile}/device/${auth.registration_name}`;
Expand Down Expand Up @@ -778,42 +756,14 @@ function ConversationChatFooter({ inboxId }: { inboxId: string }) {
<>
{isDragActive && <DropFileActive />}
{selectedTool && (
<div className="bg-gray-375 relative max-w-full rounded-lg p-1.5 px-2">
<Tooltip>
<TooltipTrigger asChild>
<div className="flex items-center gap-2 pr-6">
<ToolsIcon className="h-3.5 w-3.5" />
<div className="line-clamp-1 inline-flex items-center gap-2 text-xs text-gray-100">
<span className="text-white">
{formatText(selectedTool.name)}{' '}
</span>
<InfoCircleIcon className="h-3 w-3 shrink-0" />
</div>
</div>
</TooltipTrigger>
<TooltipPortal>
<TooltipContent
align="start"
alignOffset={-10}
className="max-w-[400px]"
side="top"
sideOffset={10}
>
{selectedTool.description}
</TooltipContent>
</TooltipPortal>
</Tooltip>

<button
className="absolute right-2 top-1.5 text-gray-100 hover:text-white"
onClick={() => {
chatForm.setValue('tool', undefined);
}}
type="button"
>
<XIcon className="h-4 w-4" />
</button>
</div>
<SelectedToolChat
args={selectedTool.args ?? []}
description={selectedTool.description}
name={formatText(selectedTool.name)}
remove={() => {
chatForm.setValue('tool', undefined);
}}
/>
)}
{!isDragActive &&
currentFiles &&
Expand Down Expand Up @@ -861,6 +811,9 @@ function ConversationChatFooter({ inboxId }: { inboxId: string }) {
key: tool.tool_router_key,
name: tool.name,
description: tool.description,
args: Object.keys(
tool.input_args.properties ?? {},
),
});
}}
type="button"
Expand Down Expand Up @@ -1013,3 +966,62 @@ const DropFileActive = () => (
</div>
</motion.div>
);

const SelectedToolChat = ({
name,
description,
args,
remove,
}: {
name: string;
description: string;
args: string[];
remove: () => void;
}) => {
return (
<div className="bg-gray-375 relative max-w-full rounded-lg p-1.5 px-2">
<Tooltip>
<TooltipTrigger asChild>
<div className="flex items-start gap-2 pr-6">
<ToolsIcon className="mt-1 aspect-square size-3.5" />
<div className="flex flex-1 flex-col items-start text-xs text-gray-100">
<span className="line-clamp-1 font-medium text-white">
{name} -{' '}
<span className="text-gray-80 font-light">{description}</span>
</span>
{args.length > 0 && (
<span className="text-gray-80">
<div className="inline-flex gap-1">
<span className="capitalize">Inputs: </span>
<div className="inline-flex font-mono">
{args.join(', ')}
</div>
</div>
</span>
)}
</div>
</div>
</TooltipTrigger>
<TooltipPortal>
<TooltipContent
align="start"
alignOffset={-10}
className="max-w-[400px]"
side="top"
sideOffset={10}
>
wellelele
</TooltipContent>
</TooltipPortal>
</Tooltip>

<button
className="absolute right-2 top-1.5 text-gray-100 hover:text-white"
onClick={remove}
type="button"
>
<XIcon className="h-4 w-4" />
</button>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useRemoveTool } from '@shinkai_network/shinkai-node-state/v2/mutations/removeTool/useRemoveTool';
import { Button } from '@shinkai_network/shinkai-ui';
import { useNavigate } from 'react-router-dom';
import { toast } from 'sonner';

import { useAuth } from '../../../store/auth';

export default function RemoveToolButton({ toolKey }: { toolKey: string }) {
const auth = useAuth((state) => state.auth);
const navigate = useNavigate();

const { mutateAsync: removeTool, isPending: isRemoveToolPending } =
useRemoveTool({
onSuccess: () => {
toast.success('Tool has been removed successfully');
navigate('/tools');
},
onError: (error) => {
toast.error('Failed to remove tool', {
description: error.response?.data?.message ?? error.message,
});
},
});

return (
<Button
className="border-red-800 bg-red-700/50 text-red-50 hover:bg-red-900"
disabled={isRemoveToolPending}
isLoading={isRemoveToolPending}
onClick={async () => {
await removeTool({
toolKey: toolKey ?? '',
nodeAddress: auth?.node_address ?? '',
token: auth?.api_v2_key ?? '',
});
}}
size="sm"
variant={'outline'}
>
Delete Tool
</Button>
);
}
4 changes: 3 additions & 1 deletion apps/shinkai-desktop/src/components/tools/deno-tool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { z } from 'zod';

import { SubpageLayout } from '../../pages/layout/simple-layout';
import { useAuth } from '../../store/auth';
import RemoveToolButton from '../playground-tool/components/remove-tool-button';
const jsToolSchema = z.object({
config: z.array(
z.object({
Expand Down Expand Up @@ -241,7 +242,7 @@ export default function DenoTool({
</Form>
</div>
)}
<div className="space-y-4 py-4">
<div className="flex flex-col gap-4 py-4">
{isPlaygroundTool && (
<Link
className={cn(
Expand All @@ -255,6 +256,7 @@ export default function DenoTool({
Go Playground
</Link>
)}
<RemoveToolButton toolKey={toolKey as string} />
</div>
</div>
</SubpageLayout>
Expand Down
4 changes: 4 additions & 0 deletions apps/shinkai-desktop/src/components/tools/network-tool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { toast } from 'sonner';
// import { z } from 'zod';
import { SubpageLayout } from '../../pages/layout/simple-layout';
import { useAuth } from '../../store/auth';
import RemoveToolButton from '../playground-tool/components/remove-tool-button';

// const jsToolSchema = z.object({
// config: z.array(
Expand Down Expand Up @@ -247,6 +248,9 @@ export default function NetworkTool({
{/* Go Playground*/}
{/* </Link>*/}
{/*)}*/}
<div className="flex flex-col gap-4 py-4">
<RemoveToolButton toolKey={toolKey as string} />
</div>
</div>
</SubpageLayout>
);
Expand Down
4 changes: 3 additions & 1 deletion apps/shinkai-desktop/src/components/tools/python-tool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { z } from 'zod';

import { SubpageLayout } from '../../pages/layout/simple-layout';
import { useAuth } from '../../store/auth';
import RemoveToolButton from '../playground-tool/components/remove-tool-button';
const jsToolSchema = z.object({
config: z.array(
z.object({
Expand Down Expand Up @@ -241,7 +242,7 @@ export default function PythonTool({
</Form>
</div>
)}
<div className="space-y-4 py-4">
<div className="flex flex-col gap-4 py-4">
{isPlaygroundTool && (
<Link
className={cn(
Expand All @@ -255,6 +256,7 @@ export default function PythonTool({
Go Playground
</Link>
)}
<RemoveToolButton toolKey={toolKey as string} />
</div>
</div>
</SubpageLayout>
Expand Down
4 changes: 4 additions & 0 deletions apps/shinkai-desktop/src/components/tools/rust-tool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { toast } from 'sonner';
// import { z } from 'zod';
import { SubpageLayout } from '../../pages/layout/simple-layout';
import { useAuth } from '../../store/auth';
import RemoveToolButton from '../playground-tool/components/remove-tool-button';

// const jsToolSchema = z.object({
// config: z.array(
Expand Down Expand Up @@ -188,6 +189,9 @@ export default function RustTool({
{/* Go Playground*/}
{/* </Link>*/}
{/*)}*/}
<div className="flex flex-col gap-4 py-4">
<RemoveToolButton toolKey={toolKey as string} />
</div>
</div>
</SubpageLayout>
);
Expand Down
1 change: 1 addition & 0 deletions libs/shinkai-message-ts/src/api/jobs/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ export type JobMessage = {
message: string;
};
tool_router_key: string;
response?: string;
}[];
};
};
Expand Down
Loading