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

Nico/add tool usage spotlight #646

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
51 changes: 50 additions & 1 deletion apps/shinkai-desktop/src/pages/add-ai.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import {
TextField,
} from '@shinkai_network/shinkai-ui';
import { cn } from '@shinkai_network/shinkai-ui/utils';
import { open } from '@tauri-apps/plugin-shell';
import { HelpCircle } from 'lucide-react';
import { useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';
import { useNavigate } from 'react-router-dom';
Expand Down Expand Up @@ -244,8 +246,55 @@ const AddAIPage = () => {
});
};

const getHelpUrl = () => {
console.log('Current model:', currentModel);

if (!currentModel) {
return 'https://docs.shinkai.com/advanced/models';
}

const urlMap = {
[Models.OpenAI]: 'https://docs.shinkai.com/advanced/models/gpt',
[Models.TogetherComputer]: 'https://docs.shinkai.com/advanced/models/together-ai',
[Models.Ollama]: 'https://docs.shinkai.com/advanced/models/ollama',
[Models.Gemini]: 'https://docs.shinkai.com/advanced/models/gemini',
[Models.Groq]: 'https://docs.shinkai.com/advanced/models/groq',
[Models.OpenRouter]: 'https://docs.shinkai.com/advanced/models/openrouter',
[Models.Exo]: 'https://docs.shinkai.com/advanced/models/exo',
[Models.Claude]: 'https://docs.shinkai.com/advanced/models/claude',
};

return urlMap[currentModel] || 'https://docs.shinkai.com/advanced/models';
};

const handleHelpClick = async (e: React.MouseEvent) => {
e.preventDefault();
const url = getHelpUrl();
console.log('Opening help URL:', url);

try {
await open(url);
} catch (error) {
console.error('Error opening URL in browser:', error);
}
};

return (
<SubpageLayout className="max-w-lg" title={t('llmProviders.add')}>
<SubpageLayout
className="max-w-lg"
rightElement={
<Button
className="gap-2"
onClick={handleHelpClick}
size="sm"
variant="ghost"
>
<HelpCircle className="h-4 w-4" />
Help
</Button>
}
title={t('llmProviders.add')}
>
<Form {...addAgentForm}>
<form
className="space-y-10"
Expand Down
149 changes: 131 additions & 18 deletions apps/shinkai-desktop/src/windows/spotlight/components/quick-ask.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { zodResolver } from '@hookform/resolvers/zod';
import { useTranslation } from '@shinkai_network/shinkai-i18n';
import { ShinkaiToolHeader } from '@shinkai_network/shinkai-message-ts/api/tools/types';
import { buildInboxIdFromJobId } from '@shinkai_network/shinkai-message-ts/utils/inbox_name_handler';
import {
CreateJobFormSchema,
Expand All @@ -8,18 +9,42 @@ import {
import { Models } from '@shinkai_network/shinkai-node-state/lib/utils/models';
import { useCreateJob } from '@shinkai_network/shinkai-node-state/v2/mutations/createJob/useCreateJob';
import { useGetLLMProviders } from '@shinkai_network/shinkai-node-state/v2/queries/getLLMProviders/useGetLLMProviders';
import { useGetTools } from '@shinkai_network/shinkai-node-state/v2/queries/getToolsList/useGetToolsList';
import {
Button,
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CopyToClipboardIcon,
DotsLoader,
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
MarkdownText,
Popover,
PopoverContent,
PopoverTrigger,
ScrollArea,
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
Separator,
Switch,
TextField,
} from '@shinkai_network/shinkai-ui';
import { ShinkaiCombinationMarkIcon } from '@shinkai_network/shinkai-ui/assets';
import { copyToClipboard } from '@shinkai_network/shinkai-ui/helpers';
import { ShinkaiCombinationMarkIcon, ToolsIcon } from '@shinkai_network/shinkai-ui/assets';
import { copyToClipboard, formatText } from '@shinkai_network/shinkai-ui/helpers';
import { cn } from '@shinkai_network/shinkai-ui/utils';
import { invoke } from '@tauri-apps/api/core';
import { listen } from '@tauri-apps/api/event';
Expand Down Expand Up @@ -85,6 +110,16 @@ function QuickAsk() {

const [clipboard, setClipboard] = useState(false);
let timeout: ReturnType<typeof setTimeout>;
const [isCommandOpen, setIsCommandOpen] = useState(false);
const { data: toolsList, isSuccess: isToolsListSuccess } = useGetTools(
{
nodeAddress: auth?.node_address ?? '',
token: auth?.api_v2_key ?? '',
},
{
select: (data: ShinkaiToolHeader[]) => data.filter((tool) => tool.enabled),
},
);

useHotkeys(
['esc'],
Expand Down Expand Up @@ -168,12 +203,15 @@ function QuickAsk() {
setMessageResponse('');

if (!auth) return;
console.log('spotlight tool key: ', data.tool?.key);

await createJob({
nodeAddress: auth.node_address,
token: auth.api_v2_key,
llmProvider: data.agent,
content: data.message,
isHidden: false,
toolKey: data.tool?.key,
});
};

Expand All @@ -196,23 +234,98 @@ function QuickAsk() {
<ChevronLeft className="size-full" />
</button>
)}
<input
autoFocus
className="placeholder:text-gray-80/70 flex-grow bg-transparent text-lg text-white focus:outline-none"
{...chatForm.register('message')}
onKeyDown={(e) => {
if (e.key === 'Enter') {
chatForm.handleSubmit(onSubmit)();
}

if (e.key === 'Backspace' && !chatForm.watch('message')) {
setInboxId(null);
setMessageResponse('');
<div className="relative flex-grow">
<Popover onOpenChange={(open) => {
setIsCommandOpen(open);
if (!open) {
if (chatForm.watch('message') === '/') {
chatForm.setValue('message', '');
}
}
}}
placeholder="Ask a question..."
spellCheck={false}
/>
}} open={isCommandOpen}>
<PopoverTrigger asChild>
<div className="w-full">
<input
autoFocus
className="placeholder:text-gray-80/70 w-full bg-transparent text-lg text-white focus:outline-none"
{...chatForm.register('message')}
onKeyDown={(e) => {
if (e.key === 'Enter') {
chatForm.handleSubmit(onSubmit)();
}

if (e.key === 'Backspace' && !chatForm.watch('message')) {
setInboxId(null);
setMessageResponse('');
}

if (
e.key === '/' &&
!e.shiftKey &&
!e.ctrlKey &&
!e.metaKey &&
!chatForm.watch('message').trim()
) {
e.preventDefault();
setIsCommandOpen(true);
chatForm.setValue('message', '/');
}
}}
placeholder="Ask a question..."
spellCheck={false}
/>
</div>
</PopoverTrigger>
<PopoverContent
align="start"
className="w-[500px] bg-gray-300 p-0"
side="bottom"
sideOffset={5}
>
<Command>
<CommandInput autoFocus={false} placeholder="Search tools..." />
<CommandList>
<CommandEmpty>No tools found.</CommandEmpty>
<CommandGroup heading="Your Active Tools">
{isToolsListSuccess &&
toolsList?.map((tool) => (
<CommandItem
className="data-[selected='true']:bg-gray-200"
key={tool.tool_router_key}
onSelect={() => {
chatForm.setValue('tool', {
key: tool.tool_router_key,
name: tool.name,
description: tool.description,
args: Object.keys(
tool.input_args.properties ?? {},
),
});
chatForm.setValue('message', `/${tool.name} `);
setIsCommandOpen(false);
const input = document.querySelector('input');
if (input) {
input.focus();
}
}}
>
<ToolsIcon className="mr-2 h-4 w-4" />
<div className="flex flex-col">
<span className="line-clamp-1 text-white">
{formatText(tool.name)}
</span>
<span className="text-gray-80 line-clamp-3 text-xs">
{tool.description}
</span>
</div>
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
</div>
<AIModelSelector
onValueChange={(value) => {
chatForm.setValue('agent', value);
Expand Down
20 changes: 20 additions & 0 deletions libs/shinkai-node-state/src/lib/utils/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ export const modelsConfig = {
name: 'GPT 4o',
value: 'gpt-4o',
},
{
name: 'o1',
value: 'o1',
},
{
name: 'o1 Mini',
value: 'o1-mini',
},
{
name: 'o3 Mini',
value: 'o3-mini',
},
],
},
[Models.TogetherComputer]: {
Expand Down Expand Up @@ -64,6 +76,14 @@ export const modelsConfig = {
[Models.Gemini]: {
apiUrl: 'https://generativelanguage.googleapis.com/v1beta/models',
modelTypes: [
{
name: 'Gemini 2.0 Flash',
value: 'gemini-2.0-flash',
},
{
name: 'Gemini 2.0 Flash Lite',
value: 'gemini-2.0-flash-lite-preview-02-05',
},
{
name: 'Gemini 1.5 Flash',
value: 'gemini-1.5-flash',
Expand Down