Skip to content
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
132 changes: 132 additions & 0 deletions apps/shinkai-desktop/src/components/agent/agent-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ import {
FileTypeIcon,
ScheduledTasksIcon,
SendIcon,
ToolsIcon,
} from '@shinkai_network/shinkai-ui/assets';
import {
formatDateToLocaleStringWithTime,
Expand All @@ -108,6 +109,7 @@ import {
BoltIcon,
ChevronDownIcon,
ChevronRight,
ExternalLinkIcon,
HistoryIcon,
LucideArrowLeft,
MessageSquare,
Expand Down Expand Up @@ -2152,6 +2154,7 @@ function AgentForm({ mode }: AgentFormProps) {
Configure
</Button>
)}

<Switch
checked={form
.watch('tools')
Expand Down Expand Up @@ -2232,6 +2235,14 @@ function AgentForm({ mode }: AgentFormProps) {
</Collapsible>
</div>
)}
{tool.tool_type === 'Agent' && (
<AgentToolToolsList
setSelectedToolConfig={
setSelectedToolConfig
}
toolRouterKey={tool.tool_router_key}
/>
)}
</div>
);
})}
Expand Down Expand Up @@ -2363,6 +2374,14 @@ function AgentForm({ mode }: AgentFormProps) {
</div>
</FormControl>
</div>
{tool.tool_type === 'Agent' && (
<AgentToolToolsList
setSelectedToolConfig={
setSelectedToolConfig
}
toolRouterKey={tool.tool_router_key}
/>
)}
</FormItem>
)}
/>
Expand Down Expand Up @@ -2532,6 +2551,14 @@ function AgentForm({ mode }: AgentFormProps) {
</div>
</FormControl>
</div>
{tool.tool_type === 'Agent' && (
<AgentToolToolsList
setSelectedToolConfig={
setSelectedToolConfig
}
toolRouterKey={tool.tool_router_key}
/>
)}
</FormItem>
)}
/>
Expand Down Expand Up @@ -2954,6 +2981,111 @@ function AgentForm({ mode }: AgentFormProps) {

export default AgentForm;

const AgentToolToolsList = ({
toolRouterKey,
setSelectedToolConfig,
}: {
toolRouterKey: string;
setSelectedToolConfig: (toolKey: string) => void;
}) => {
const { t } = useTranslation();
const auth = useAuth((state) => state.auth);
const { data: toolData } = useGetTool({
nodeAddress: auth?.node_address ?? '',
token: auth?.api_v2_key ?? '',
toolKey: toolRouterKey,
});

const agentTool = toolData?.content?.[0] as ShinkaiTool | undefined;
const agentId =
agentTool && 'agent_id' in agentTool ? agentTool.agent_id : undefined;

const { data: agent, isSuccess } = useGetAgent({
agentId: agentId ?? '',
nodeAddress: auth?.node_address ?? '',
token: auth?.api_v2_key ?? '',
});

const { data: toolsList } = useGetTools({
nodeAddress: auth?.node_address ?? '',
token: auth?.api_v2_key ?? '',
});

const tools = agent?.tools ?? [];

if (!agentId || !isSuccess || !agent || tools.length === 0) {
return null;
}

return (
<div className="flex flex-col">
<Collapsible className="rounded-2xl border">
<CollapsibleTrigger asChild>
<Button
className={cn(
buttonVariants({
variant: 'tertiary',
size: 'sm',
}),
'w-full justify-between [data-state=open]:border-none [&[data-state=open]>svg]:rotate-180',
)}
>
<span className="flex items-center gap-2">
<ToolsIcon className="h-4 w-4" />
Agent Tools ({tools.length})
</span>
<ChevronDownIcon className="h-4 w-4" />
</Button>
</CollapsibleTrigger>
<CollapsibleContent className="space-y-2">
<div className="flex flex-col px-4">
{tools.map((toolKey) => {
const toolName = toolKey.split(':::')?.at(-1) ?? toolKey;
const tool = toolsList?.find(
(t) => t.tool_router_key === toolKey,
);
const hasConfig = (tool?.config ?? []).length > 0;
return (
<div
key={toolKey}
className="flex h-10 items-center justify-between gap-2 py-1"
>
<div className="flex items-center gap-2">
<span className="text-text-secondary text-sm">
{formatText(toolName)}
</span>
</div>
{hasConfig && (
<Button
className={cn(
buttonVariants({
variant: 'tertiary',
size: 'xs',
}),
'text-text-secondary hover:text-text-default shrink-0 border-none',
)}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
setSelectedToolConfig(toolKey);
window.location.hash = '#configuration';
}}
type="button"
>
<BoltIcon className="size-3" />
{t('common.configure')}
</Button>
)}
</div>
);
})}
</div>
</CollapsibleContent>
</Collapsible>
</div>
);
};

const ToolConfigModal = ({
toolRouterKey,
isOpen,
Expand Down
77 changes: 56 additions & 21 deletions apps/shinkai-desktop/src/pages/agents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,14 @@ import * as fs from '@tauri-apps/plugin-fs';
import { BaseDirectory } from '@tauri-apps/plugin-fs';
import { open } from '@tauri-apps/plugin-shell';
import cronstrue from 'cronstrue';
import { Edit, Plus, Rocket, TrashIcon } from 'lucide-react';
import {
ChevronDown,
ChevronUp,
Edit,
Plus,
Rocket,
TrashIcon,
} from 'lucide-react';
import React, { useMemo, useState } from 'react';
import { Link, useNavigate } from 'react-router';
import { toast } from 'sonner';
Expand Down Expand Up @@ -133,23 +140,19 @@ function AgentsPage() {
</div>
<p className="text-text-secondary text-sm">
{selectedTab === 'my' ? (
<>
<Trans
i18nKey="agentsPage.description"
components={{
br: <br />,
}}
/>
</>
<Trans
i18nKey="agentsPage.description"
components={{
br: <br />,
}}
/>
) : (
<>
<Trans
i18nKey="agentsPage.exploreDescription"
components={{
br: <br />,
}}
/>
</>
<Trans
i18nKey="agentsPage.exploreDescription"
components={{
br: <br />,
}}
/>
)}
</p>
</div>
Expand Down Expand Up @@ -227,9 +230,14 @@ const AgentCard = ({
const { t } = useTranslation();
const [isDeleteAgentDrawerOpen, setIsDeleteAgentDrawerOpen] =
React.useState(false);
const [isDescriptionExpanded, setIsDescriptionExpanded] =
React.useState(false);
const auth = useAuth((state) => state.auth);
const navigate = useNavigate();

const description = agentDescription ?? 'No description';
const shouldShowExpandButton = description.length > 120;

const { mutateAsync: exportAgent } = useExportAgent({
onSuccess: async (response) => {
const sanitizedAgentName = sanitizeFileName(agentName);
Expand Down Expand Up @@ -305,9 +313,36 @@ const AgentCard = ({
)}
</span>

<span className="text-text-secondary text-sm">
{agentDescription ?? 'No description'}
</span>
<div className="flex flex-col gap-1 pr-3">
<span
className={cn(
'text-text-secondary text-sm whitespace-pre-wrap',
!isDescriptionExpanded &&
shouldShowExpandButton &&
'line-clamp-2',
)}
>
{description}
</span>
{shouldShowExpandButton && (
<button
className="text-text-tertiary hover:text-text-default flex w-fit items-center gap-1 text-xs font-medium underline transition-colors"
onClick={() =>
setIsDescriptionExpanded(!isDescriptionExpanded)
}
type="button"
>
{isDescriptionExpanded
? t('common.showLess')
: t('common.showMore')}
{isDescriptionExpanded ? (
<ChevronUp className="h-3 w-3" />
) : (
<ChevronDown className="h-3 w-3" />
)}
</button>
)}
</div>
{hasScheduledTasks && (
<div className="mt-2 inline-flex gap-2">
{scheduledTasks.map((task) => (
Expand Down Expand Up @@ -340,7 +375,7 @@ const AgentCard = ({
)}
</div>
</div>
<div className="flex items-center gap-4">
<div className="flex items-center gap-2">
<TooltipProvider delayDuration={0}>
<Tooltip>
<TooltipTrigger asChild>
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@shinkai/source",
"version": "1.1.26",
"version": "1.1.27",
"license": "SEE LICENSE IN LICENSE",
"files": [
"LICENSE"
Expand Down