Skip to content

Commit

Permalink
feat: remove playground tools + add tool results + misc fixes (#566)
Browse files Browse the repository at this point in the history
* feat: remove tools

* wip tool selection

* feat: remove tool

* fix: add toolkey when sending message

* feat: add tool description + inputs

* feat: add tool results info
  • Loading branch information
paulclindo authored Dec 17, 2024
1 parent 36e88cb commit 3c9e04f
Show file tree
Hide file tree
Showing 18 changed files with 259 additions and 84 deletions.
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

0 comments on commit 3c9e04f

Please sign in to comment.