mirror of
https://github.com/ItzCrazyKns/Perplexica.git
synced 2025-12-25 04:58:15 +00:00
Compare commits
16 Commits
cf95ea0af7
...
60dd7a8108
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
60dd7a8108 | ||
|
|
f5e054f6ea | ||
|
|
452180356d | ||
|
|
0a9641a110 | ||
|
|
a2f2e17bbb | ||
|
|
e1afcbb787 | ||
|
|
fe2c1b8210 | ||
|
|
d40fcd57d9 | ||
|
|
86a43086cc | ||
|
|
9ce17edd4a | ||
|
|
c4349f3d5c | ||
|
|
d4c276ab93 | ||
|
|
6ae885e0ed | ||
|
|
dc74e7174f | ||
|
|
53697bb42e | ||
|
|
eca66f0b5f |
@@ -11,9 +11,10 @@
|
||||
"format:write": "prettier . --write"
|
||||
},
|
||||
"dependencies": {
|
||||
"@google/genai": "^1.34.0",
|
||||
"@headlessui/react": "^2.2.0",
|
||||
"@headlessui/tailwindcss": "^0.2.2",
|
||||
"@huggingface/transformers": "^3.7.5",
|
||||
"@huggingface/transformers": "^3.8.1",
|
||||
"@icons-pack/react-simple-icons": "^12.3.0",
|
||||
"@phosphor-icons/react": "^2.1.10",
|
||||
"@radix-ui/react-tooltip": "^1.2.8",
|
||||
|
||||
@@ -221,6 +221,7 @@ export const POST = async (req: Request) => {
|
||||
sources: body.sources as SearchSources[],
|
||||
mode: body.optimizationMode,
|
||||
fileIds: body.files,
|
||||
systemInstructions: body.systemInstructions || 'None',
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use client';
|
||||
|
||||
import DeleteChat from '@/components/DeleteChat';
|
||||
import { cn, formatTimeDifference } from '@/lib/utils';
|
||||
import { BookOpenText, ClockIcon, Delete, ScanEye } from 'lucide-react';
|
||||
import { formatTimeDifference } from '@/lib/utils';
|
||||
import { BookOpenText, ClockIcon, FileText, Globe2Icon } from 'lucide-react';
|
||||
import Link from 'next/link';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
@@ -10,7 +10,8 @@ export interface Chat {
|
||||
id: string;
|
||||
title: string;
|
||||
createdAt: string;
|
||||
focusMode: string;
|
||||
sources: string[];
|
||||
files: { fileId: string; name: string }[];
|
||||
}
|
||||
|
||||
const Page = () => {
|
||||
@@ -37,74 +38,137 @@ const Page = () => {
|
||||
fetchChats();
|
||||
}, []);
|
||||
|
||||
return loading ? (
|
||||
<div className="flex flex-row items-center justify-center min-h-screen">
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="w-8 h-8 text-light-200 fill-light-secondary dark:text-[#202020] animate-spin dark:fill-[#ffffff3b]"
|
||||
viewBox="0 0 100 101"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M100 50.5908C100.003 78.2051 78.1951 100.003 50.5908 100C22.9765 99.9972 0.997224 78.018 1 50.4037C1.00281 22.7993 22.8108 0.997224 50.4251 1C78.0395 1.00281 100.018 22.8108 100 50.4251ZM9.08164 50.594C9.06312 73.3997 27.7909 92.1272 50.5966 92.1457C73.4023 92.1642 92.1298 73.4365 92.1483 50.6308C92.1669 27.8251 73.4392 9.0973 50.6335 9.07878C27.8278 9.06026 9.10003 27.787 9.08164 50.594Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M93.9676 39.0409C96.393 38.4037 97.8624 35.9116 96.9801 33.5533C95.1945 28.8227 92.871 24.3692 90.0681 20.348C85.6237 14.1775 79.4473 9.36872 72.0454 6.45794C64.6435 3.54717 56.3134 2.65431 48.3133 3.89319C45.869 4.27179 44.3768 6.77534 45.014 9.20079C45.6512 11.6262 48.1343 13.0956 50.5786 12.717C56.5073 11.8281 62.5542 12.5399 68.0406 14.7911C73.527 17.0422 78.2187 20.7487 81.5841 25.4923C83.7976 28.5886 85.4467 32.059 86.4416 35.7474C87.1273 38.1189 89.5423 39.6781 91.9676 39.0409Z"
|
||||
fill="currentFill"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
) : (
|
||||
return (
|
||||
<div>
|
||||
<div className="flex flex-col pt-4">
|
||||
<div className="flex items-center">
|
||||
<BookOpenText />
|
||||
<h1 className="text-3xl font-medium p-2">Library</h1>
|
||||
</div>
|
||||
<hr className="border-t border-[#2B2C2C] my-4 w-full" />
|
||||
</div>
|
||||
{chats.length === 0 && (
|
||||
<div className="flex flex-row items-center justify-center min-h-screen">
|
||||
<p className="text-black/70 dark:text-white/70 text-sm">
|
||||
No chats found.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
{chats.length > 0 && (
|
||||
<div className="flex flex-col pb-20 lg:pb-2">
|
||||
{chats.map((chat, i) => (
|
||||
<div
|
||||
className={cn(
|
||||
'flex flex-col space-y-4 py-6',
|
||||
i !== chats.length - 1
|
||||
? 'border-b border-white-200 dark:border-dark-200'
|
||||
: '',
|
||||
)}
|
||||
key={i}
|
||||
>
|
||||
<Link
|
||||
href={`/c/${chat.id}`}
|
||||
className="text-black dark:text-white lg:text-xl font-medium truncate transition duration-200 hover:text-[#24A0ED] dark:hover:text-[#24A0ED] cursor-pointer"
|
||||
<div className="flex flex-col pt-10 border-b border-light-200/20 dark:border-dark-200/20 pb-6 px-2">
|
||||
<div className="flex flex-col lg:flex-row lg:items-end lg:justify-between gap-3">
|
||||
<div className="flex items-center justify-center">
|
||||
<BookOpenText size={45} className="mb-2.5" />
|
||||
<div className="flex flex-col">
|
||||
<h1
|
||||
className="text-5xl font-normal p-2 pb-0"
|
||||
style={{ fontFamily: 'PP Editorial, serif' }}
|
||||
>
|
||||
{chat.title}
|
||||
</Link>
|
||||
<div className="flex flex-row items-center justify-between w-full">
|
||||
<div className="flex flex-row items-center space-x-1 lg:space-x-1.5 text-black/70 dark:text-white/70">
|
||||
<ClockIcon size={15} />
|
||||
<p className="text-xs">
|
||||
{formatTimeDifference(new Date(), chat.createdAt)} Ago
|
||||
</p>
|
||||
</div>
|
||||
<DeleteChat
|
||||
chatId={chat.id}
|
||||
chats={chats}
|
||||
setChats={setChats}
|
||||
/>
|
||||
Library
|
||||
</h1>
|
||||
<div className="px-2 text-sm text-black/60 dark:text-white/60 text-center lg:text-left">
|
||||
Past chats, sources, and uploads.
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-center lg:justify-end gap-2 text-xs text-black/60 dark:text-white/60">
|
||||
<span className="inline-flex items-center gap-1 rounded-full border border-black/20 dark:border-white/20 px-2 py-0.5">
|
||||
<BookOpenText size={14} />
|
||||
{loading
|
||||
? 'Loading…'
|
||||
: `${chats.length} ${chats.length === 1 ? 'chat' : 'chats'}`}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{loading ? (
|
||||
<div className="flex flex-row items-center justify-center min-h-[60vh]">
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="w-8 h-8 text-light-200 fill-light-secondary dark:text-[#202020] animate-spin dark:fill-[#ffffff3b]"
|
||||
viewBox="0 0 100 101"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M100 50.5908C100.003 78.2051 78.1951 100.003 50.5908 100C22.9765 99.9972 0.997224 78.018 1 50.4037C1.00281 22.7993 22.8108 0.997224 50.4251 1C78.0395 1.00281 100.018 22.8108 100 50.4251ZM9.08164 50.594C9.06312 73.3997 27.7909 92.1272 50.5966 92.1457C73.4023 92.1642 92.1298 73.4365 92.1483 50.6308C92.1669 27.8251 73.4392 9.0973 50.6335 9.07878C27.8278 9.06026 9.10003 27.787 9.08164 50.594Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M93.9676 39.0409C96.393 38.4037 97.8624 35.9116 96.9801 33.5533C95.1945 28.8227 92.871 24.3692 90.0681 20.348C85.6237 14.1775 79.4473 9.36872 72.0454 6.45794C64.6435 3.54717 56.3134 2.65431 48.3133 3.89319C45.869 4.27179 44.3768 6.77534 45.014 9.20079C45.6512 11.6262 48.1343 13.0956 50.5786 12.717C56.5073 11.8281 62.5542 12.5399 68.0406 14.7911C73.527 17.0422 78.2187 20.7487 81.5841 25.4923C83.7976 28.5886 85.4467 32.059 86.4416 35.7474C87.1273 38.1189 89.5423 39.6781 91.9676 39.0409Z"
|
||||
fill="currentFill"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
) : chats.length === 0 ? (
|
||||
<div className="flex flex-col items-center justify-center min-h-[70vh] px-2 text-center">
|
||||
<div className="flex items-center justify-center w-12 h-12 rounded-2xl border border-light-200 dark:border-dark-200 bg-light-secondary dark:bg-dark-secondary">
|
||||
<BookOpenText className="text-black/70 dark:text-white/70" />
|
||||
</div>
|
||||
<p className="mt-2 text-black/70 dark:text-white/70 text-sm">
|
||||
No chats found.
|
||||
</p>
|
||||
<p className="mt-1 text-black/70 dark:text-white/70 text-sm">
|
||||
<Link href="/" className="text-sky-400">
|
||||
Start a new chat
|
||||
</Link>{' '}
|
||||
to see it listed here.
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="pt-6 pb-28 px-2">
|
||||
<div className="rounded-2xl border border-light-200 dark:border-dark-200 overflow-hidden bg-light-primary dark:bg-dark-primary">
|
||||
{chats.map((chat, index) => {
|
||||
const sourcesLabel =
|
||||
chat.sources.length === 0
|
||||
? null
|
||||
: chat.sources.length <= 2
|
||||
? chat.sources
|
||||
.map((s) => s.charAt(0).toUpperCase() + s.slice(1))
|
||||
.join(', ')
|
||||
: `${chat.sources
|
||||
.slice(0, 2)
|
||||
.map((s) => s.charAt(0).toUpperCase() + s.slice(1))
|
||||
.join(', ')} + ${chat.sources.length - 2}`;
|
||||
|
||||
return (
|
||||
<div
|
||||
key={chat.id}
|
||||
className={
|
||||
'group flex flex-col gap-2 p-4 hover:bg-light-secondary dark:hover:bg-dark-secondary transition-colors duration-200 ' +
|
||||
(index !== chats.length - 1
|
||||
? 'border-b border-light-200 dark:border-dark-200'
|
||||
: '')
|
||||
}
|
||||
>
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<Link
|
||||
href={`/c/${chat.id}`}
|
||||
className="flex-1 text-black dark:text-white text-base lg:text-lg font-medium leading-snug line-clamp-2 group-hover:text-[#24A0ED] transition duration-200"
|
||||
title={chat.title}
|
||||
>
|
||||
{chat.title}
|
||||
</Link>
|
||||
<div className="pt-0.5 shrink-0">
|
||||
<DeleteChat
|
||||
chatId={chat.id}
|
||||
chats={chats}
|
||||
setChats={setChats}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap items-center gap-2 text-black/70 dark:text-white/70">
|
||||
<span className="inline-flex items-center gap-1 text-xs">
|
||||
<ClockIcon size={14} />
|
||||
{formatTimeDifference(new Date(), chat.createdAt)} Ago
|
||||
</span>
|
||||
|
||||
{sourcesLabel && (
|
||||
<span className="inline-flex items-center gap-1 text-xs border border-black/20 dark:border-white/20 rounded-full px-2 py-0.5">
|
||||
<Globe2Icon size={14} />
|
||||
{sourcesLabel}
|
||||
</span>
|
||||
)}
|
||||
{chat.files.length > 0 && (
|
||||
<span className="inline-flex items-center gap-1 text-xs border border-black/20 dark:border-white/20 rounded-full px-2 py-0.5">
|
||||
<FileText size={14} />
|
||||
{chat.files.length}{' '}
|
||||
{chat.files.length === 1 ? 'file' : 'files'}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -59,7 +59,7 @@ const Chat = () => {
|
||||
}, [messages]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col space-y-6 pt-8 pb-28 sm:mx-4 md:mx-8">
|
||||
<div className="flex flex-col space-y-6 pt-8 pb-44 lg:pb-28 sm:mx-4 md:mx-8">
|
||||
{sections.map((section, i) => {
|
||||
const isLast = i === sections.length - 1;
|
||||
|
||||
@@ -80,7 +80,7 @@ const Chat = () => {
|
||||
{loading && !messageAppeared && <MessageBoxLoading />}
|
||||
<div ref={messageEnd} className="h-0" />
|
||||
{dividerWidth > 0 && (
|
||||
<div className="bottom-6 fixed z-40" style={{ width: dividerWidth }}>
|
||||
<div className="fixed z-40 bottom-24 lg:bottom-6" style={{ width: dividerWidth }}>
|
||||
<div
|
||||
className="pointer-events-none absolute -bottom-6 left-0 right-0 h-[calc(100%+24px+24px)] dark:hidden"
|
||||
style={{
|
||||
|
||||
@@ -136,8 +136,6 @@ const MessageBox = ({
|
||||
</div>
|
||||
))}
|
||||
|
||||
{section.widgets.length > 0 && <Renderer widgets={section.widgets} />}
|
||||
|
||||
{isLast &&
|
||||
loading &&
|
||||
!researchEnded &&
|
||||
@@ -152,6 +150,8 @@ const MessageBox = ({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{section.widgets.length > 0 && <Renderer widgets={section.widgets} />}
|
||||
|
||||
<div className="flex flex-col space-y-2">
|
||||
{sources.length > 0 && (
|
||||
<div className="flex flex-row items-center space-x-2">
|
||||
|
||||
@@ -51,12 +51,12 @@ const Sources = () => {
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
exit={{ opacity: 0, scale: 0.9 }}
|
||||
transition={{ duration: 0.1, ease: 'easeOut' }}
|
||||
className="origin-top-right flex flex-col bg-light-primary dark:bg-dark-primary border rounded-lg border-light-200 dark:border-dark-200 w-full p-1 max-h-[200px] md:max-h-none overflow-y-auto shadow-md shadow-dark-50"
|
||||
className="origin-top-right flex flex-col bg-light-primary dark:bg-dark-primary border rounded-lg border-light-200 dark:border-dark-200 w-full p-1 max-h-[200px] md:max-h-none overflow-y-auto shadow-lg"
|
||||
>
|
||||
{sourcesList.map((source, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="flex flex-row justify-between hover:bg-white-100 hover:dark:bg-dark-100 rounded-md py-3 px-2 cursor-pointer"
|
||||
className="flex flex-row justify-between hover:bg-light-100 hover:dark:bg-dark-100 rounded-md py-3 px-2 cursor-pointer"
|
||||
onClick={() => {
|
||||
if (!sources.includes(source.key)) {
|
||||
setSources([...sources, source.key]);
|
||||
@@ -65,13 +65,13 @@ const Sources = () => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="flex flex-row space-x-1.5 text-white/80">
|
||||
<div className="flex flex-row space-x-1.5 text-black/80 dark:text-white/80">
|
||||
{source.icon}
|
||||
<p className="text-xs">{source.name}</p>
|
||||
</div>
|
||||
<Switch
|
||||
checked={sources.includes(source.key)}
|
||||
className="group relative flex h-4 w-7 shrink-0 cursor-pointer rounded-full bg-white/10 p-0.5 duration-200 ease-in-out focus:outline-none transition-colors disabled:opacity-60 disabled:cursor-not-allowed data-[checked]:bg-sky-500"
|
||||
className="group relative flex h-4 w-7 shrink-0 cursor-pointer rounded-full bg-light-200 dark:bg-white/10 p-0.5 duration-200 ease-in-out focus:outline-none transition-colors disabled:opacity-60 disabled:cursor-not-allowed data-[checked]:bg-sky-500 dark:data-[checked]:bg-sky-500"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
|
||||
@@ -310,7 +310,7 @@ const SettingsSwitch = ({
|
||||
checked={isChecked}
|
||||
onChange={handleSave}
|
||||
disabled={loading}
|
||||
className="group relative flex h-6 w-12 shrink-0 cursor-pointer rounded-full bg-white/10 p-1 duration-200 ease-in-out focus:outline-none transition-colors disabled:opacity-60 disabled:cursor-not-allowed data-[checked]:bg-sky-500"
|
||||
className="group relative flex h-6 w-12 shrink-0 cursor-pointer rounded-full bg-light-200 dark:bg-white/10 p-1 duration-200 ease-in-out focus:outline-none transition-colors disabled:opacity-60 disabled:cursor-not-allowed data-[checked]:bg-sky-500 dark:data-[checked]:bg-sky-500"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
|
||||
@@ -114,7 +114,11 @@ class SearchAgent {
|
||||
|
||||
const finalContextWithWidgets = `<search_results note="These are the search results and assistant can cite these">\n${finalContext}\n</search_results>\n<widgets_result noteForAssistant="Its output is already showed to the user, assistant can use this information to answer the query but do not CITE this as a souce">\n${widgetContext}\n</widgets_result>`;
|
||||
|
||||
const writerPrompt = getWriterPrompt(finalContextWithWidgets);
|
||||
const writerPrompt = getWriterPrompt(
|
||||
finalContextWithWidgets,
|
||||
input.config.systemInstructions,
|
||||
input.config.mode,
|
||||
);
|
||||
const answerStream = input.config.llm.streamText({
|
||||
messages: [
|
||||
{
|
||||
@@ -129,24 +133,36 @@ class SearchAgent {
|
||||
],
|
||||
});
|
||||
|
||||
const block: TextBlock = {
|
||||
id: crypto.randomUUID(),
|
||||
type: 'text',
|
||||
data: '',
|
||||
};
|
||||
|
||||
session.emitBlock(block);
|
||||
let responseBlockId = '';
|
||||
|
||||
for await (const chunk of answerStream) {
|
||||
block.data += chunk.contentChunk;
|
||||
if (!responseBlockId) {
|
||||
const block: TextBlock = {
|
||||
id: crypto.randomUUID(),
|
||||
type: 'text',
|
||||
data: chunk.contentChunk,
|
||||
};
|
||||
|
||||
session.updateBlock(block.id, [
|
||||
{
|
||||
op: 'replace',
|
||||
path: '/data',
|
||||
value: block.data,
|
||||
},
|
||||
]);
|
||||
session.emitBlock(block);
|
||||
|
||||
responseBlockId = block.id;
|
||||
} else {
|
||||
const block = session.getBlock(responseBlockId) as TextBlock | null;
|
||||
|
||||
if (!block) {
|
||||
continue;
|
||||
}
|
||||
|
||||
block.data += chunk.contentChunk;
|
||||
|
||||
session.updateBlock(block.id, [
|
||||
{
|
||||
op: 'replace',
|
||||
path: '/data',
|
||||
value: block.data,
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
session.emit('end', {});
|
||||
|
||||
@@ -11,7 +11,7 @@ const doneAction: ResearchAction<any> = {
|
||||
name: 'done',
|
||||
schema: z.object({}),
|
||||
getToolDescription: () =>
|
||||
'Only call this after 0_reasoning AND after any other needed tool calls when you truly have enough to answer. Do not call if information is still missing.',
|
||||
'Only call this after __reasoning_preamble AND after any other needed tool calls when you truly have enough to answer. Do not call if information is still missing.',
|
||||
getDescription: () => actionDescription,
|
||||
enabled: (_) => true,
|
||||
execute: async (params, additionalConfig) => {
|
||||
|
||||
@@ -23,7 +23,7 @@ YOU CAN NEVER CALL ANY OTHER TOOL BEFORE CALLING THIS ONE FIRST, IF YOU DO, THAT
|
||||
`;
|
||||
|
||||
const planAction: ResearchAction<typeof schema> = {
|
||||
name: '0_reasoning',
|
||||
name: '__reasoning_preamble',
|
||||
schema: schema,
|
||||
getToolDescription: () =>
|
||||
'Use this FIRST on every turn to state your plan in natural language before any other action. Keep it short, action-focused, and tailored to the current query.',
|
||||
|
||||
@@ -32,11 +32,11 @@ Start initially with broader queries to get an overview, then narrow down with m
|
||||
Your queries shouldn't be sentences but rather keywords that are SEO friendly and can be used to search the web for information.
|
||||
|
||||
For example if the user is asking about Tesla, your actions should be like:
|
||||
1. 0_reasoning "The user is asking about Tesla. I will start with broader queries to get an overview of Tesla, then narrow down with more specific queries based on the results I receive." then
|
||||
1. __reasoning_preamble "The user is asking about Tesla. I will start with broader queries to get an overview of Tesla, then narrow down with more specific queries based on the results I receive." then
|
||||
2. web_search ["Tesla", "Tesla latest news", "Tesla stock price"] then
|
||||
3. 0_reasoning "Based on the previous search results, I will now narrow down my queries to focus on Tesla's recent developments and stock performance." then
|
||||
3. __reasoning_preamble "Based on the previous search results, I will now narrow down my queries to focus on Tesla's recent developments and stock performance." then
|
||||
4. web_search ["Tesla Q2 2025 earnings", "Tesla new model 2025", "Tesla stock analysis"] then done.
|
||||
5. 0_reasoning "I have gathered enough information to provide a comprehensive answer."
|
||||
5. __reasoning_preamble "I have gathered enough information to provide a comprehensive answer."
|
||||
6. done.
|
||||
|
||||
You can search for 3 queries in one go, make sure to utilize all 3 queries to maximize the information you can gather. If a question is simple, then split your queries to cover different aspects or related topics to get a comprehensive understanding.
|
||||
|
||||
@@ -87,7 +87,7 @@ class Researcher {
|
||||
if (partialRes.toolCallChunk.length > 0) {
|
||||
partialRes.toolCallChunk.forEach((tc) => {
|
||||
if (
|
||||
tc.name === '0_reasoning' &&
|
||||
tc.name === '__reasoning_preamble' &&
|
||||
tc.arguments['plan'] &&
|
||||
!reasoningEmitted &&
|
||||
block &&
|
||||
@@ -109,7 +109,7 @@ class Researcher {
|
||||
},
|
||||
]);
|
||||
} else if (
|
||||
tc.name === '0_reasoning' &&
|
||||
tc.name === '__reasoning_preamble' &&
|
||||
tc.arguments['plan'] &&
|
||||
reasoningEmitted &&
|
||||
block &&
|
||||
|
||||
@@ -12,6 +12,7 @@ export type SearchAgentConfig = {
|
||||
llm: BaseLLM<any>;
|
||||
embedding: BaseEmbedding<any>;
|
||||
mode: 'speed' | 'balanced' | 'quality';
|
||||
systemInstructions: string;
|
||||
};
|
||||
|
||||
export type SearchAgentInput = {
|
||||
|
||||
5
src/lib/models/providers/anthropic/anthropicLLM.ts
Normal file
5
src/lib/models/providers/anthropic/anthropicLLM.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import OpenAILLM from "../openai/openaiLLM";
|
||||
|
||||
class AnthropicLLM extends OpenAILLM {}
|
||||
|
||||
export default AnthropicLLM;
|
||||
115
src/lib/models/providers/anthropic/index.ts
Normal file
115
src/lib/models/providers/anthropic/index.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import { UIConfigField } from '@/lib/config/types';
|
||||
import { getConfiguredModelProviderById } from '@/lib/config/serverRegistry';
|
||||
import { Model, ModelList, ProviderMetadata } from '../../types';
|
||||
import BaseEmbedding from '../../base/embedding';
|
||||
import BaseModelProvider from '../../base/provider';
|
||||
import BaseLLM from '../../base/llm';
|
||||
import AnthropicLLM from './anthropicLLM';
|
||||
|
||||
interface AnthropicConfig {
|
||||
apiKey: string;
|
||||
}
|
||||
|
||||
const providerConfigFields: UIConfigField[] = [
|
||||
{
|
||||
type: 'password',
|
||||
name: 'API Key',
|
||||
key: 'apiKey',
|
||||
description: 'Your Anthropic API key',
|
||||
required: true,
|
||||
placeholder: 'Anthropic API Key',
|
||||
env: 'ANTHROPIC_API_KEY',
|
||||
scope: 'server',
|
||||
},
|
||||
];
|
||||
|
||||
class AnthropicProvider extends BaseModelProvider<AnthropicConfig> {
|
||||
constructor(id: string, name: string, config: AnthropicConfig) {
|
||||
super(id, name, config);
|
||||
}
|
||||
|
||||
async getDefaultModels(): Promise<ModelList> {
|
||||
const res = await fetch('https://api.anthropic.com/v1/models?limit=999', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'x-api-key': this.config.apiKey,
|
||||
'anthropic-version': '2023-06-01',
|
||||
'Content-type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error(`Failed to fetch Anthropic models: ${res.statusText}`);
|
||||
}
|
||||
|
||||
const data = (await res.json()).data;
|
||||
|
||||
const models: Model[] = data.map((m: any) => {
|
||||
return {
|
||||
key: m.id,
|
||||
name: m.display_name,
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
embedding: [],
|
||||
chat: models,
|
||||
};
|
||||
}
|
||||
|
||||
async getModelList(): Promise<ModelList> {
|
||||
const defaultModels = await this.getDefaultModels();
|
||||
const configProvider = getConfiguredModelProviderById(this.id)!;
|
||||
|
||||
return {
|
||||
embedding: [],
|
||||
chat: [...defaultModels.chat, ...configProvider.chatModels],
|
||||
};
|
||||
}
|
||||
|
||||
async loadChatModel(key: string): Promise<BaseLLM<any>> {
|
||||
const modelList = await this.getModelList();
|
||||
|
||||
const exists = modelList.chat.find((m) => m.key === key);
|
||||
|
||||
if (!exists) {
|
||||
throw new Error(
|
||||
'Error Loading Anthropic Chat Model. Invalid Model Selected',
|
||||
);
|
||||
}
|
||||
|
||||
return new AnthropicLLM({
|
||||
apiKey: this.config.apiKey,
|
||||
model: key,
|
||||
baseURL: 'https://api.anthropic.com/v1'
|
||||
});
|
||||
}
|
||||
|
||||
async loadEmbeddingModel(key: string): Promise<BaseEmbedding<any>> {
|
||||
throw new Error('Anthropic provider does not support embedding models.');
|
||||
}
|
||||
|
||||
static parseAndValidate(raw: any): AnthropicConfig {
|
||||
if (!raw || typeof raw !== 'object')
|
||||
throw new Error('Invalid config provided. Expected object');
|
||||
if (!raw.apiKey)
|
||||
throw new Error('Invalid config provided. API key must be provided');
|
||||
|
||||
return {
|
||||
apiKey: String(raw.apiKey),
|
||||
};
|
||||
}
|
||||
|
||||
static getProviderConfigFields(): UIConfigField[] {
|
||||
return providerConfigFields;
|
||||
}
|
||||
|
||||
static getProviderMetadata(): ProviderMetadata {
|
||||
return {
|
||||
key: 'anthropic',
|
||||
name: 'Anthropic',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default AnthropicProvider;
|
||||
5
src/lib/models/providers/gemini/geminiEmbedding.ts
Normal file
5
src/lib/models/providers/gemini/geminiEmbedding.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import OpenAIEmbedding from '../openai/openaiEmbedding';
|
||||
|
||||
class GeminiEmbedding extends OpenAIEmbedding {}
|
||||
|
||||
export default GeminiEmbedding;
|
||||
5
src/lib/models/providers/gemini/geminiLLM.ts
Normal file
5
src/lib/models/providers/gemini/geminiLLM.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import OpenAILLM from '../openai/openaiLLM';
|
||||
|
||||
class GeminiLLM extends OpenAILLM {}
|
||||
|
||||
export default GeminiLLM;
|
||||
144
src/lib/models/providers/gemini/index.ts
Normal file
144
src/lib/models/providers/gemini/index.ts
Normal file
@@ -0,0 +1,144 @@
|
||||
import { UIConfigField } from '@/lib/config/types';
|
||||
import { getConfiguredModelProviderById } from '@/lib/config/serverRegistry';
|
||||
import { Model, ModelList, ProviderMetadata } from '../../types';
|
||||
import GeminiEmbedding from './geminiEmbedding';
|
||||
import BaseEmbedding from '../../base/embedding';
|
||||
import BaseModelProvider from '../../base/provider';
|
||||
import BaseLLM from '../../base/llm';
|
||||
import GeminiLLM from './geminiLLM';
|
||||
|
||||
interface GeminiConfig {
|
||||
apiKey: string;
|
||||
}
|
||||
|
||||
const providerConfigFields: UIConfigField[] = [
|
||||
{
|
||||
type: 'password',
|
||||
name: 'API Key',
|
||||
key: 'apiKey',
|
||||
description: 'Your Gemini API key',
|
||||
required: true,
|
||||
placeholder: 'Gemini API Key',
|
||||
env: 'GEMINI_API_KEY',
|
||||
scope: 'server',
|
||||
},
|
||||
];
|
||||
|
||||
class GeminiProvider extends BaseModelProvider<GeminiConfig> {
|
||||
constructor(id: string, name: string, config: GeminiConfig) {
|
||||
super(id, name, config);
|
||||
}
|
||||
|
||||
async getDefaultModels(): Promise<ModelList> {
|
||||
const res = await fetch(
|
||||
`https://generativelanguage.googleapis.com/v1beta/models?key=${this.config.apiKey}`,
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const data = await res.json();
|
||||
|
||||
let defaultEmbeddingModels: Model[] = [];
|
||||
let defaultChatModels: Model[] = [];
|
||||
|
||||
data.models.forEach((m: any) => {
|
||||
if (
|
||||
m.supportedGenerationMethods.some(
|
||||
(genMethod: string) =>
|
||||
genMethod === 'embedText' || genMethod === 'embedContent',
|
||||
)
|
||||
) {
|
||||
defaultEmbeddingModels.push({
|
||||
key: m.name,
|
||||
name: m.displayName,
|
||||
});
|
||||
} else if (m.supportedGenerationMethods.includes('generateContent')) {
|
||||
defaultChatModels.push({
|
||||
key: m.name,
|
||||
name: m.displayName,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
embedding: defaultEmbeddingModels,
|
||||
chat: defaultChatModels,
|
||||
};
|
||||
}
|
||||
|
||||
async getModelList(): Promise<ModelList> {
|
||||
const defaultModels = await this.getDefaultModels();
|
||||
const configProvider = getConfiguredModelProviderById(this.id)!;
|
||||
|
||||
return {
|
||||
embedding: [
|
||||
...defaultModels.embedding,
|
||||
...configProvider.embeddingModels,
|
||||
],
|
||||
chat: [...defaultModels.chat, ...configProvider.chatModels],
|
||||
};
|
||||
}
|
||||
|
||||
async loadChatModel(key: string): Promise<BaseLLM<any>> {
|
||||
const modelList = await this.getModelList();
|
||||
|
||||
const exists = modelList.chat.find((m) => m.key === key);
|
||||
|
||||
if (!exists) {
|
||||
throw new Error(
|
||||
'Error Loading Gemini Chat Model. Invalid Model Selected',
|
||||
);
|
||||
}
|
||||
|
||||
return new GeminiLLM({
|
||||
apiKey: this.config.apiKey,
|
||||
model: key,
|
||||
baseURL: 'https://generativelanguage.googleapis.com/v1beta/openai',
|
||||
});
|
||||
}
|
||||
|
||||
async loadEmbeddingModel(key: string): Promise<BaseEmbedding<any>> {
|
||||
const modelList = await this.getModelList();
|
||||
const exists = modelList.embedding.find((m) => m.key === key);
|
||||
|
||||
if (!exists) {
|
||||
throw new Error(
|
||||
'Error Loading Gemini Embedding Model. Invalid Model Selected.',
|
||||
);
|
||||
}
|
||||
|
||||
return new GeminiEmbedding({
|
||||
apiKey: this.config.apiKey,
|
||||
model: key,
|
||||
baseURL: 'https://generativelanguage.googleapis.com/v1beta/openai',
|
||||
});
|
||||
}
|
||||
|
||||
static parseAndValidate(raw: any): GeminiConfig {
|
||||
if (!raw || typeof raw !== 'object')
|
||||
throw new Error('Invalid config provided. Expected object');
|
||||
if (!raw.apiKey)
|
||||
throw new Error('Invalid config provided. API key must be provided');
|
||||
|
||||
return {
|
||||
apiKey: String(raw.apiKey),
|
||||
};
|
||||
}
|
||||
|
||||
static getProviderConfigFields(): UIConfigField[] {
|
||||
return providerConfigFields;
|
||||
}
|
||||
|
||||
static getProviderMetadata(): ProviderMetadata {
|
||||
return {
|
||||
key: 'gemini',
|
||||
name: 'Gemini',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default GeminiProvider;
|
||||
5
src/lib/models/providers/groq/groqLLM.ts
Normal file
5
src/lib/models/providers/groq/groqLLM.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import OpenAILLM from '../openai/openaiLLM';
|
||||
|
||||
class GroqLLM extends OpenAILLM {}
|
||||
|
||||
export default GroqLLM;
|
||||
113
src/lib/models/providers/groq/index.ts
Normal file
113
src/lib/models/providers/groq/index.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
import { UIConfigField } from '@/lib/config/types';
|
||||
import { getConfiguredModelProviderById } from '@/lib/config/serverRegistry';
|
||||
import { Model, ModelList, ProviderMetadata } from '../../types';
|
||||
import BaseEmbedding from '../../base/embedding';
|
||||
import BaseModelProvider from '../../base/provider';
|
||||
import BaseLLM from '../../base/llm';
|
||||
import GroqLLM from './groqLLM';
|
||||
|
||||
interface GroqConfig {
|
||||
apiKey: string;
|
||||
}
|
||||
|
||||
const providerConfigFields: UIConfigField[] = [
|
||||
{
|
||||
type: 'password',
|
||||
name: 'API Key',
|
||||
key: 'apiKey',
|
||||
description: 'Your Groq API key',
|
||||
required: true,
|
||||
placeholder: 'Groq API Key',
|
||||
env: 'GROQ_API_KEY',
|
||||
scope: 'server',
|
||||
},
|
||||
];
|
||||
|
||||
class GroqProvider extends BaseModelProvider<GroqConfig> {
|
||||
constructor(id: string, name: string, config: GroqConfig) {
|
||||
super(id, name, config);
|
||||
}
|
||||
|
||||
async getDefaultModels(): Promise<ModelList> {
|
||||
const res = await fetch(`https://api.groq.com/openai/v1/models`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${this.config.apiKey}`,
|
||||
},
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
|
||||
const defaultChatModels: Model[] = [];
|
||||
|
||||
data.data.forEach((m: any) => {
|
||||
defaultChatModels.push({
|
||||
key: m.id,
|
||||
name: m.id,
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
embedding: [],
|
||||
chat: defaultChatModels,
|
||||
};
|
||||
}
|
||||
|
||||
async getModelList(): Promise<ModelList> {
|
||||
const defaultModels = await this.getDefaultModels();
|
||||
const configProvider = getConfiguredModelProviderById(this.id)!;
|
||||
|
||||
return {
|
||||
embedding: [
|
||||
...defaultModels.embedding,
|
||||
...configProvider.embeddingModels,
|
||||
],
|
||||
chat: [...defaultModels.chat, ...configProvider.chatModels],
|
||||
};
|
||||
}
|
||||
|
||||
async loadChatModel(key: string): Promise<BaseLLM<any>> {
|
||||
const modelList = await this.getModelList();
|
||||
|
||||
const exists = modelList.chat.find((m) => m.key === key);
|
||||
|
||||
if (!exists) {
|
||||
throw new Error('Error Loading Groq Chat Model. Invalid Model Selected');
|
||||
}
|
||||
|
||||
return new GroqLLM({
|
||||
apiKey: this.config.apiKey,
|
||||
model: key,
|
||||
baseURL: 'https://api.groq.com/openai/v1',
|
||||
});
|
||||
}
|
||||
|
||||
async loadEmbeddingModel(key: string): Promise<BaseEmbedding<any>> {
|
||||
throw new Error('Groq Provider does not support embedding models.');
|
||||
}
|
||||
|
||||
static parseAndValidate(raw: any): GroqConfig {
|
||||
if (!raw || typeof raw !== 'object')
|
||||
throw new Error('Invalid config provided. Expected object');
|
||||
if (!raw.apiKey)
|
||||
throw new Error('Invalid config provided. API key must be provided');
|
||||
|
||||
return {
|
||||
apiKey: String(raw.apiKey),
|
||||
};
|
||||
}
|
||||
|
||||
static getProviderConfigFields(): UIConfigField[] {
|
||||
return providerConfigFields;
|
||||
}
|
||||
|
||||
static getProviderMetadata(): ProviderMetadata {
|
||||
return {
|
||||
key: 'groq',
|
||||
name: 'Groq',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default GroqProvider;
|
||||
@@ -2,10 +2,20 @@ import { ModelProviderUISection } from '@/lib/config/types';
|
||||
import { ProviderConstructor } from '../base/provider';
|
||||
import OpenAIProvider from './openai';
|
||||
import OllamaProvider from './ollama';
|
||||
import GeminiProvider from './gemini';
|
||||
import TransformersProvider from './transformers';
|
||||
import GroqProvider from './groq';
|
||||
import LemonadeProvider from './lemonade';
|
||||
import AnthropicProvider from './anthropic';
|
||||
|
||||
export const providers: Record<string, ProviderConstructor<any>> = {
|
||||
openai: OpenAIProvider,
|
||||
ollama: OllamaProvider,
|
||||
gemini: GeminiProvider,
|
||||
transformers: TransformersProvider,
|
||||
groq: GroqProvider,
|
||||
lemonade: LemonadeProvider,
|
||||
anthropic: AnthropicProvider
|
||||
};
|
||||
|
||||
export const getModelProvidersUIConfigSection =
|
||||
|
||||
149
src/lib/models/providers/lemonade/index.ts
Normal file
149
src/lib/models/providers/lemonade/index.ts
Normal file
@@ -0,0 +1,149 @@
|
||||
import { UIConfigField } from '@/lib/config/types';
|
||||
import { getConfiguredModelProviderById } from '@/lib/config/serverRegistry';
|
||||
import BaseModelProvider from '../../base/provider';
|
||||
import { Model, ModelList, ProviderMetadata } from '../../types';
|
||||
import BaseLLM from '../../base/llm';
|
||||
import LemonadeLLM from './lemonadeLLM';
|
||||
import BaseEmbedding from '../../base/embedding';
|
||||
import LemonadeEmbedding from './lemonadeEmbedding';
|
||||
|
||||
interface LemonadeConfig {
|
||||
baseURL: string;
|
||||
apiKey?: string;
|
||||
}
|
||||
|
||||
const providerConfigFields: UIConfigField[] = [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'Base URL',
|
||||
key: 'baseURL',
|
||||
description: 'The base URL for Lemonade API',
|
||||
required: true,
|
||||
placeholder: 'https://api.lemonade.ai/v1',
|
||||
env: 'LEMONADE_BASE_URL',
|
||||
scope: 'server',
|
||||
},
|
||||
{
|
||||
type: 'password',
|
||||
name: 'API Key',
|
||||
key: 'apiKey',
|
||||
description: 'Your Lemonade API key (optional)',
|
||||
required: false,
|
||||
placeholder: 'Lemonade API Key',
|
||||
env: 'LEMONADE_API_KEY',
|
||||
scope: 'server',
|
||||
},
|
||||
];
|
||||
|
||||
class LemonadeProvider extends BaseModelProvider<LemonadeConfig> {
|
||||
constructor(id: string, name: string, config: LemonadeConfig) {
|
||||
super(id, name, config);
|
||||
}
|
||||
|
||||
async getDefaultModels(): Promise<ModelList> {
|
||||
try {
|
||||
const res = await fetch(`${this.config.baseURL}/models`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...this.config.apiKey ? {'Authorization': `Bearer ${this.config.apiKey}`} : {}
|
||||
},
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
|
||||
const models: Model[] = data.data.filter((m: any) => m.recipe === 'llamacpp').map((m: any) => {
|
||||
return {
|
||||
name: m.id,
|
||||
key: m.id,
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
embedding: models,
|
||||
chat: models,
|
||||
};
|
||||
} catch (err) {
|
||||
if (err instanceof TypeError) {
|
||||
throw new Error(
|
||||
'Error connecting to Lemonade API. Please ensure the base URL is correct and the service is available.',
|
||||
);
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async getModelList(): Promise<ModelList> {
|
||||
const defaultModels = await this.getDefaultModels();
|
||||
const configProvider = getConfiguredModelProviderById(this.id)!;
|
||||
|
||||
return {
|
||||
embedding: [
|
||||
...defaultModels.embedding,
|
||||
...configProvider.embeddingModels,
|
||||
],
|
||||
chat: [...defaultModels.chat, ...configProvider.chatModels],
|
||||
};
|
||||
}
|
||||
|
||||
async loadChatModel(key: string): Promise<BaseLLM<any>> {
|
||||
const modelList = await this.getModelList();
|
||||
|
||||
const exists = modelList.chat.find((m) => m.key === key);
|
||||
|
||||
if (!exists) {
|
||||
throw new Error(
|
||||
'Error Loading Lemonade Chat Model. Invalid Model Selected',
|
||||
);
|
||||
}
|
||||
|
||||
return new LemonadeLLM({
|
||||
apiKey: this.config.apiKey || 'not-needed',
|
||||
model: key,
|
||||
baseURL: this.config.baseURL,
|
||||
});
|
||||
}
|
||||
|
||||
async loadEmbeddingModel(key: string): Promise<BaseEmbedding<any>> {
|
||||
const modelList = await this.getModelList();
|
||||
const exists = modelList.embedding.find((m) => m.key === key);
|
||||
|
||||
if (!exists) {
|
||||
throw new Error(
|
||||
'Error Loading Lemonade Embedding Model. Invalid Model Selected.',
|
||||
);
|
||||
}
|
||||
|
||||
return new LemonadeEmbedding({
|
||||
apiKey: this.config.apiKey || 'not-needed',
|
||||
model: key,
|
||||
baseURL: this.config.baseURL,
|
||||
});
|
||||
}
|
||||
|
||||
static parseAndValidate(raw: any): LemonadeConfig {
|
||||
if (!raw || typeof raw !== 'object')
|
||||
throw new Error('Invalid config provided. Expected object');
|
||||
if (!raw.baseURL)
|
||||
throw new Error('Invalid config provided. Base URL must be provided');
|
||||
|
||||
return {
|
||||
baseURL: String(raw.baseURL),
|
||||
apiKey: raw.apiKey ? String(raw.apiKey) : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
static getProviderConfigFields(): UIConfigField[] {
|
||||
return providerConfigFields;
|
||||
}
|
||||
|
||||
static getProviderMetadata(): ProviderMetadata {
|
||||
return {
|
||||
key: 'lemonade',
|
||||
name: 'Lemonade',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default LemonadeProvider;
|
||||
5
src/lib/models/providers/lemonade/lemonadeEmbedding.ts
Normal file
5
src/lib/models/providers/lemonade/lemonadeEmbedding.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import OpenAIEmbedding from "../openai/openaiEmbedding";
|
||||
|
||||
class LemonadeEmbedding extends OpenAIEmbedding {}
|
||||
|
||||
export default LemonadeEmbedding;
|
||||
5
src/lib/models/providers/lemonade/lemonadeLLM.ts
Normal file
5
src/lib/models/providers/lemonade/lemonadeLLM.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import OpenAILLM from "../openai/openaiLLM";
|
||||
|
||||
class LemonadeLLM extends OpenAILLM {}
|
||||
|
||||
export default LemonadeLLM;
|
||||
@@ -24,6 +24,7 @@ const reasoningModels = [
|
||||
'qwen3',
|
||||
'deepseek-v3.1',
|
||||
'magistral',
|
||||
'nemotron-3-nano',
|
||||
];
|
||||
|
||||
class OllamaLLM extends BaseLLM<OllamaConfig> {
|
||||
|
||||
88
src/lib/models/providers/transformers/index.ts
Normal file
88
src/lib/models/providers/transformers/index.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import { UIConfigField } from '@/lib/config/types';
|
||||
import { getConfiguredModelProviderById } from '@/lib/config/serverRegistry';
|
||||
import { Model, ModelList, ProviderMetadata } from '../../types';
|
||||
import BaseModelProvider from '../../base/provider';
|
||||
import BaseLLM from '../../base/llm';
|
||||
import BaseEmbedding from '../../base/embedding';
|
||||
import TransformerEmbedding from './transformerEmbedding';
|
||||
|
||||
interface TransformersConfig {}
|
||||
|
||||
const defaultEmbeddingModels: Model[] = [
|
||||
{
|
||||
name: 'all-MiniLM-L6-v2',
|
||||
key: 'Xenova/all-MiniLM-L6-v2',
|
||||
},
|
||||
{
|
||||
name: 'mxbai-embed-large-v1',
|
||||
key: 'mixedbread-ai/mxbai-embed-large-v1',
|
||||
},
|
||||
{
|
||||
name: 'nomic-embed-text-v1',
|
||||
key: 'Xenova/nomic-embed-text-v1',
|
||||
},
|
||||
];
|
||||
|
||||
const providerConfigFields: UIConfigField[] = [];
|
||||
|
||||
class TransformersProvider extends BaseModelProvider<TransformersConfig> {
|
||||
constructor(id: string, name: string, config: TransformersConfig) {
|
||||
super(id, name, config);
|
||||
}
|
||||
|
||||
async getDefaultModels(): Promise<ModelList> {
|
||||
return {
|
||||
embedding: [...defaultEmbeddingModels],
|
||||
chat: [],
|
||||
};
|
||||
}
|
||||
|
||||
async getModelList(): Promise<ModelList> {
|
||||
const defaultModels = await this.getDefaultModels();
|
||||
const configProvider = getConfiguredModelProviderById(this.id)!;
|
||||
|
||||
return {
|
||||
embedding: [
|
||||
...defaultModels.embedding,
|
||||
...configProvider.embeddingModels,
|
||||
],
|
||||
chat: [],
|
||||
};
|
||||
}
|
||||
|
||||
async loadChatModel(key: string): Promise<BaseLLM<any>> {
|
||||
throw new Error('Transformers Provider does not support chat models.');
|
||||
}
|
||||
|
||||
async loadEmbeddingModel(key: string): Promise<BaseEmbedding<any>> {
|
||||
const modelList = await this.getModelList();
|
||||
const exists = modelList.embedding.find((m) => m.key === key);
|
||||
|
||||
if (!exists) {
|
||||
throw new Error(
|
||||
'Error Loading OpenAI Embedding Model. Invalid Model Selected.',
|
||||
);
|
||||
}
|
||||
|
||||
return new TransformerEmbedding({
|
||||
model: key,
|
||||
});
|
||||
}
|
||||
|
||||
static parseAndValidate(raw: any): TransformersConfig {
|
||||
return {};
|
||||
}
|
||||
|
||||
static getProviderConfigFields(): UIConfigField[] {
|
||||
return providerConfigFields;
|
||||
}
|
||||
|
||||
static getProviderMetadata(): ProviderMetadata {
|
||||
return {
|
||||
key: 'transformers',
|
||||
name: 'Transformers',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default TransformersProvider;
|
||||
@@ -0,0 +1,43 @@
|
||||
import { Chunk } from '@/lib/types';
|
||||
import BaseEmbedding from '../../base/embedding';
|
||||
import { FeatureExtractionPipeline, pipeline } from '@huggingface/transformers';
|
||||
|
||||
type TransformerConfig = {
|
||||
model: string;
|
||||
};
|
||||
|
||||
class TransformerEmbedding extends BaseEmbedding<TransformerConfig> {
|
||||
private pipelinePromise: Promise<FeatureExtractionPipeline> | null = null;
|
||||
|
||||
constructor(protected config: TransformerConfig) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
async embedText(texts: string[]): Promise<number[][]> {
|
||||
return this.embed(texts);
|
||||
}
|
||||
|
||||
async embedChunks(chunks: Chunk[]): Promise<number[][]> {
|
||||
return this.embed(chunks.map((c) => c.content));
|
||||
}
|
||||
|
||||
async embed(texts: string[]): Promise<number[][]> {
|
||||
if (!this.pipelinePromise) {
|
||||
this.pipelinePromise = (async () => {
|
||||
const transformers = await import('@huggingface/transformers');
|
||||
return (await transformers.pipeline(
|
||||
'feature-extraction',
|
||||
this.config.model,
|
||||
)) as unknown as FeatureExtractionPipeline;
|
||||
})();
|
||||
}
|
||||
|
||||
const pipeline = await this.pipelinePromise;
|
||||
|
||||
const output = await pipeline(texts, { pooling: 'mean', normalize: true });
|
||||
|
||||
return output.tolist() as number[][];
|
||||
}
|
||||
}
|
||||
|
||||
export default TransformerEmbedding;
|
||||
@@ -55,7 +55,8 @@ You must respond in the following JSON format without any extra text, explanatio
|
||||
"academicSearch": boolean,
|
||||
"discussionSearch": boolean,
|
||||
"showWeatherWidget": boolean,
|
||||
"showStockWidget": boolean
|
||||
"showStockWidget": boolean,
|
||||
"showCalculationWidget": boolean,
|
||||
},
|
||||
"standaloneFollowUp": string
|
||||
}
|
||||
|
||||
@@ -109,12 +109,12 @@ const getBalancedPrompt = (
|
||||
|
||||
<goal>
|
||||
Fulfill the user's request with concise reasoning plus focused actions.
|
||||
You must call the 0_reasoning tool before every tool call in this assistant turn. Alternate: 0_reasoning → tool → 0_reasoning → tool ... and finish with 0_reasoning → done. Open each 0_reasoning with a brief intent phrase (e.g., "Okay, the user wants to...", "Searching for...", "Looking into...") and lay out your reasoning for the next step. Keep it natural language, no tool names.
|
||||
You must call the __reasoning_preamble tool before every tool call in this assistant turn. Alternate: __reasoning_preamble → tool → __reasoning_preamble → tool ... and finish with __reasoning_preamble → done. Open each __reasoning_preamble with a brief intent phrase (e.g., "Okay, the user wants to...", "Searching for...", "Looking into...") and lay out your reasoning for the next step. Keep it natural language, no tool names.
|
||||
</goal>
|
||||
|
||||
<core_principle>
|
||||
Your knowledge is outdated; if you have web search, use it to ground answers even for seemingly basic facts.
|
||||
You can call at most 6 tools total per turn: up to 2 reasoning (0_reasoning counts as reasoning), 2-3 information-gathering calls, and 1 done. If you hit the cap, stop after done.
|
||||
You can call at most 6 tools total per turn: up to 2 reasoning (__reasoning_preamble counts as reasoning), 2-3 information-gathering calls, and 1 done. If you hit the cap, stop after done.
|
||||
Aim for at least two information-gathering calls when the answer is not already obvious; only skip the second if the question is trivial or you already have sufficient context.
|
||||
Do not spam searches—pick the most targeted queries.
|
||||
</core_principle>
|
||||
@@ -144,7 +144,7 @@ const getBalancedPrompt = (
|
||||
</examples>
|
||||
|
||||
<available_tools>
|
||||
YOU MUST CALL 0_reasoning BEFORE EVERY TOOL CALL IN THIS ASSISTANT TURN. IF YOU DO NOT CALL IT, THE TOOL CALL WILL BE IGNORED.
|
||||
YOU MUST CALL __reasoning_preamble BEFORE EVERY TOOL CALL IN THIS ASSISTANT TURN. IF YOU DO NOT CALL IT, THE TOOL CALL WILL BE IGNORED.
|
||||
${actionDesc}
|
||||
</available_tools>
|
||||
|
||||
@@ -160,16 +160,16 @@ const getBalancedPrompt = (
|
||||
|
||||
5. **Overthinking**: Keep reasoning simple and tool calls focused
|
||||
|
||||
6. **Skipping the reasoning step**: Always call 0_reasoning first to outline your approach before other actions
|
||||
6. **Skipping the reasoning step**: Always call __reasoning_preamble first to outline your approach before other actions
|
||||
|
||||
</mistakes_to_avoid>
|
||||
|
||||
<response_protocol>
|
||||
- NEVER output normal text to the user. ONLY call tools.
|
||||
- Start with 0_reasoning and call 0_reasoning before every tool call (including done): open with intent phrase ("Okay, the user wants to...", "Looking into...", etc.) and lay out your reasoning for the next step. No tool names.
|
||||
- Start with __reasoning_preamble and call __reasoning_preamble before every tool call (including done): open with intent phrase ("Okay, the user wants to...", "Looking into...", etc.) and lay out your reasoning for the next step. No tool names.
|
||||
- Choose tools based on the action descriptions provided above.
|
||||
- Default to web_search when information is missing or stale; keep queries targeted (max 3 per call).
|
||||
- Use at most 6 tool calls total (0_reasoning + 2-3 info calls + 0_reasoning + done). If done is called early, stop.
|
||||
- Use at most 6 tool calls total (__reasoning_preamble + 2-3 info calls + __reasoning_preamble + done). If done is called early, stop.
|
||||
- Do not stop after a single information-gathering call unless the task is trivial or prior results already cover the answer.
|
||||
- Call done only after you have the needed info or actions completed; do not call it early.
|
||||
- Do not invent tools. Do not return JSON.
|
||||
@@ -210,15 +210,15 @@ const getQualityPrompt = (
|
||||
|
||||
<goal>
|
||||
Conduct the deepest, most thorough research possible. Leave no stone unturned.
|
||||
Follow an iterative reason-act loop: call 0_reasoning before every tool call to outline the next step, then call the tool, then 0_reasoning again to reflect and decide the next step. Repeat until you have exhaustive coverage.
|
||||
Open each 0_reasoning with a brief intent phrase (e.g., "Okay, the user wants to know about...", "From the results, it looks like...", "Now I need to dig into...") and describe what you'll do next. Keep it natural language, no tool names.
|
||||
Follow an iterative reason-act loop: call __reasoning_preamble before every tool call to outline the next step, then call the tool, then __reasoning_preamble again to reflect and decide the next step. Repeat until you have exhaustive coverage.
|
||||
Open each __reasoning_preamble with a brief intent phrase (e.g., "Okay, the user wants to know about...", "From the results, it looks like...", "Now I need to dig into...") and describe what you'll do next. Keep it natural language, no tool names.
|
||||
Finish with done only when you have comprehensive, multi-angle information.
|
||||
</goal>
|
||||
|
||||
<core_principle>
|
||||
Your knowledge is outdated; always use the available tools to ground answers.
|
||||
This is DEEP RESEARCH mode—be exhaustive. Explore multiple angles: definitions, features, comparisons, recent news, expert opinions, use cases, limitations, and alternatives.
|
||||
You can call up to 10 tools total per turn. Use an iterative loop: 0_reasoning → tool call(s) → 0_reasoning → tool call(s) → ... → 0_reasoning → done.
|
||||
You can call up to 10 tools total per turn. Use an iterative loop: __reasoning_preamble → tool call(s) → __reasoning_preamble → tool call(s) → ... → __reasoning_preamble → done.
|
||||
Never settle for surface-level answers. If results hint at more depth, reason about your next step and follow up. Cross-reference information from multiple queries.
|
||||
</core_principle>
|
||||
|
||||
@@ -264,7 +264,7 @@ const getQualityPrompt = (
|
||||
</examples>
|
||||
|
||||
<available_tools>
|
||||
YOU MUST CALL 0_reasoning BEFORE EVERY TOOL CALL IN THIS ASSISTANT TURN. IF YOU DO NOT CALL IT, THE TOOL CALL WILL BE IGNORED.
|
||||
YOU MUST CALL __reasoning_preamble BEFORE EVERY TOOL CALL IN THIS ASSISTANT TURN. IF YOU DO NOT CALL IT, THE TOOL CALL WILL BE IGNORED.
|
||||
${actionDesc}
|
||||
</available_tools>
|
||||
|
||||
@@ -291,14 +291,14 @@ const getQualityPrompt = (
|
||||
|
||||
5. **Premature done**: Don't call done until you've exhausted reasonable research avenues
|
||||
|
||||
6. **Skipping the reasoning step**: Always call 0_reasoning first to outline your research strategy
|
||||
6. **Skipping the reasoning step**: Always call __reasoning_preamble first to outline your research strategy
|
||||
|
||||
</mistakes_to_avoid>
|
||||
|
||||
<response_protocol>
|
||||
- NEVER output normal text to the user. ONLY call tools.
|
||||
- Follow an iterative loop: 0_reasoning → tool call → 0_reasoning → tool call → ... → 0_reasoning → done.
|
||||
- Each 0_reasoning should reflect on previous results (if any) and state the next research step. No tool names in the reasoning.
|
||||
- Follow an iterative loop: __reasoning_preamble → tool call → __reasoning_preamble → tool call → ... → __reasoning_preamble → done.
|
||||
- Each __reasoning_preamble should reflect on previous results (if any) and state the next research step. No tool names in the reasoning.
|
||||
- Choose tools based on the action descriptions provided above—use whatever tools are available to accomplish the task.
|
||||
- Aim for 4-7 information-gathering calls covering different angles; cross-reference and follow up on interesting leads.
|
||||
- Call done only after comprehensive, multi-angle research is complete.
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
export const getWriterPrompt = (context: string) => {
|
||||
export const getWriterPrompt = (
|
||||
context: string,
|
||||
systemInstructions: string,
|
||||
mode: 'speed' | 'balanced' | 'quality',
|
||||
) => {
|
||||
return `
|
||||
You are Perplexica, an AI model skilled in web search and crafting detailed, engaging, and well-structured answers. You excel at summarizing web pages and extracting relevant information to create professional, blog-style responses.
|
||||
|
||||
@@ -29,7 +33,11 @@ You are Perplexica, an AI model skilled in web search and crafting detailed, eng
|
||||
- If the query involves technical, historical, or complex topics, provide detailed background and explanatory sections to ensure clarity.
|
||||
- If the user provides vague input or if relevant information is missing, explain what additional details might help refine the search.
|
||||
- If no relevant information is found, say: "Hmm, sorry I could not find any relevant information on this topic. Would you like me to search again or ask something else?" Be transparent about limitations and suggest alternatives or ways to reframe the query.
|
||||
${mode === 'quality' ? "- YOU ARE CURRENTLY SET IN QUALITY MODE, GENERATE VERY DEEP, DETAILED AND COMPREHENSIVE RESPONSES USING THE FULL CONTEXT PROVIDED. ASSISTANT'S RESPONSES SHALL NOT BE LESS THAN AT LEAST 2000 WORDS, COVER EVERYTHING AND FRAME IT LIKE A RESEARCH REPORT." : ''}
|
||||
|
||||
### User instructions
|
||||
These instructions are shared to you by the user and not by the system. You will have to follow them but give them less priority than the above instructions. If the user has provided specific instructions or preferences, incorporate them into your response while adhering to the overall guidelines.
|
||||
${systemInstructions}
|
||||
|
||||
### Example Output
|
||||
- Begin with a brief introduction summarizing the event or query topic.
|
||||
|
||||
233
yarn.lock
233
yarn.lock
@@ -392,6 +392,14 @@
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.8.tgz#21a907684723bbbaa5f0974cf7730bd797eb8e62"
|
||||
integrity sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==
|
||||
|
||||
"@google/genai@^1.34.0":
|
||||
version "1.34.0"
|
||||
resolved "https://registry.yarnpkg.com/@google/genai/-/genai-1.34.0.tgz#8a6a85c2c7eb94afbb1a999967e828cae43ee6dd"
|
||||
integrity sha512-vu53UMPvjmb7PGzlYu6Tzxso8Dfhn+a7eQFaS2uNemVtDZKwzSpJ5+ikqBbXplF7RGB1STcVDqCkPvquiwb2sw==
|
||||
dependencies:
|
||||
google-auth-library "^10.3.0"
|
||||
ws "^8.18.0"
|
||||
|
||||
"@headlessui/react@^2.2.0":
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-2.2.0.tgz#a8e32f0899862849a1ce1615fa280e7891431ab7"
|
||||
@@ -407,17 +415,17 @@
|
||||
resolved "https://registry.yarnpkg.com/@headlessui/tailwindcss/-/tailwindcss-0.2.2.tgz#8ebde73fabca72d48636ea56ae790209dc5f0d49"
|
||||
integrity sha512-xNe42KjdyA4kfUKLLPGzME9zkH7Q3rOZ5huFihWNWOQFxnItxPB3/67yBI8/qBfY8nwBRx5GHn4VprsoluVMGw==
|
||||
|
||||
"@huggingface/jinja@^0.5.1":
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@huggingface/jinja/-/jinja-0.5.1.tgz#081d334ddcf6237f65561ae3d665bb713a8ff74f"
|
||||
integrity sha512-yUZLld4lrM9iFxHCwFQ7D1HW2MWMwSbeB7WzWqFYDWK+rEb+WldkLdAJxUPOmgICMHZLzZGVcVjFh3w/YGubng==
|
||||
"@huggingface/jinja@^0.5.3":
|
||||
version "0.5.3"
|
||||
resolved "https://registry.yarnpkg.com/@huggingface/jinja/-/jinja-0.5.3.tgz#8182a2d6fc9f84c1539fa12c219a5915cdc41264"
|
||||
integrity sha512-asqfZ4GQS0hD876Uw4qiUb7Tr/V5Q+JZuo2L+BtdrD4U40QU58nIRq3ZSgAzJgT874VLjhGVacaYfrdpXtEvtA==
|
||||
|
||||
"@huggingface/transformers@^3.7.5":
|
||||
version "3.7.5"
|
||||
resolved "https://registry.yarnpkg.com/@huggingface/transformers/-/transformers-3.7.5.tgz#63d6b5792c74904168959561c6a05a05d680092f"
|
||||
integrity sha512-5jvrIwHyRXfOKVaGKYvUZM6ZjJKQXWeKzIOdKBE5pdzPSNzTwBNx5NdWcGElf4Ddv7Dl2mWsvJh+G5RnCUxMmA==
|
||||
"@huggingface/transformers@^3.8.1":
|
||||
version "3.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@huggingface/transformers/-/transformers-3.8.1.tgz#317da003865322396796173223eeaaf0f9723f0a"
|
||||
integrity sha512-tsTk4zVjImqdqjS8/AOZg2yNLd1z9S5v+7oUPpXaasDRwEDhB+xnglK1k5cad26lL5/ZIaeREgWWy0bs9y9pPA==
|
||||
dependencies:
|
||||
"@huggingface/jinja" "^0.5.1"
|
||||
"@huggingface/jinja" "^0.5.3"
|
||||
onnxruntime-node "1.21.0"
|
||||
onnxruntime-web "1.22.0-dev.20250409-89f8206ba4"
|
||||
sharp "^0.34.1"
|
||||
@@ -1496,6 +1504,11 @@ acorn@^8.9.0:
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a"
|
||||
integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==
|
||||
|
||||
agent-base@^7.1.2:
|
||||
version "7.1.4"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8"
|
||||
integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==
|
||||
|
||||
ajv@^6.12.4:
|
||||
version "6.12.6"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
|
||||
@@ -1729,7 +1742,7 @@ base64-arraybuffer@^1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#1c37589a7c4b0746e34bd1feb951da2df01c1bdc"
|
||||
integrity sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==
|
||||
|
||||
base64-js@^1.3.1, base64-js@^1.5.1:
|
||||
base64-js@^1.3.0, base64-js@^1.3.1, base64-js@^1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
||||
@@ -1742,6 +1755,11 @@ better-sqlite3@^11.9.1:
|
||||
bindings "^1.5.0"
|
||||
prebuild-install "^7.1.1"
|
||||
|
||||
bignumber.js@^9.0.0:
|
||||
version "9.3.1"
|
||||
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.3.1.tgz#759c5aaddf2ffdc4f154f7b493e1c8770f88c4d7"
|
||||
integrity sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==
|
||||
|
||||
binary-extensions@^2.0.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522"
|
||||
@@ -1810,6 +1828,11 @@ buffer-crc32@~0.2.3:
|
||||
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
|
||||
integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==
|
||||
|
||||
buffer-equal-constant-time@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
|
||||
integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==
|
||||
|
||||
buffer-from@^1.0.0:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
|
||||
@@ -2029,6 +2052,11 @@ damerau-levenshtein@^1.0.8:
|
||||
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7"
|
||||
integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==
|
||||
|
||||
data-uri-to-buffer@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e"
|
||||
integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==
|
||||
|
||||
data-view-buffer@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2"
|
||||
@@ -2056,6 +2084,13 @@ data-view-byte-offset@^1.0.0:
|
||||
es-errors "^1.3.0"
|
||||
is-data-view "^1.0.1"
|
||||
|
||||
debug@4:
|
||||
version "4.4.3"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a"
|
||||
integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==
|
||||
dependencies:
|
||||
ms "^2.1.3"
|
||||
|
||||
debug@^3.2.7:
|
||||
version "3.2.7"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
|
||||
@@ -2213,6 +2248,13 @@ eastasianwidth@^0.2.0:
|
||||
resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
|
||||
integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
|
||||
|
||||
ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11:
|
||||
version "1.0.11"
|
||||
resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf"
|
||||
integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
electron-to-chromium@^1.4.668:
|
||||
version "1.4.729"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.729.tgz#8477d21e2a50993781950885b2731d92ad532c00"
|
||||
@@ -2676,6 +2718,11 @@ expand-template@^2.0.3:
|
||||
resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c"
|
||||
integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==
|
||||
|
||||
extend@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
|
||||
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
|
||||
|
||||
fancy-canvas@2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fancy-canvas/-/fancy-canvas-2.1.0.tgz#44b40e40419ad8ef8304df365e4276767e918552"
|
||||
@@ -2730,6 +2777,14 @@ fault@^1.0.0:
|
||||
dependencies:
|
||||
format "^0.2.0"
|
||||
|
||||
fetch-blob@^3.1.2, fetch-blob@^3.1.4:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9"
|
||||
integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==
|
||||
dependencies:
|
||||
node-domexception "^1.0.0"
|
||||
web-streams-polyfill "^3.0.3"
|
||||
|
||||
"fetch-mock-cache@npm:fetch-mock-cache@^2.1.3":
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/fetch-mock-cache/-/fetch-mock-cache-2.3.1.tgz#1018f5fc2f91cf2511abcea8a5e3a3b05e2d02bf"
|
||||
@@ -2854,6 +2909,13 @@ format@^0.2.0:
|
||||
resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b"
|
||||
integrity sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==
|
||||
|
||||
formdata-polyfill@^4.0.10:
|
||||
version "4.0.10"
|
||||
resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423"
|
||||
integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==
|
||||
dependencies:
|
||||
fetch-blob "^3.1.2"
|
||||
|
||||
fraction.js@^4.3.7:
|
||||
version "4.3.7"
|
||||
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7"
|
||||
@@ -2908,6 +2970,25 @@ functions-have-names@^1.2.3:
|
||||
resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
|
||||
integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
|
||||
|
||||
gaxios@^7.0.0:
|
||||
version "7.1.3"
|
||||
resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-7.1.3.tgz#c5312f4254abc1b8ab53aef30c22c5229b80b1e1"
|
||||
integrity sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==
|
||||
dependencies:
|
||||
extend "^3.0.2"
|
||||
https-proxy-agent "^7.0.1"
|
||||
node-fetch "^3.3.2"
|
||||
rimraf "^5.0.1"
|
||||
|
||||
gcp-metadata@^8.0.0:
|
||||
version "8.1.2"
|
||||
resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-8.1.2.tgz#e62e3373ddf41fc727ccc31c55c687b798bee898"
|
||||
integrity sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==
|
||||
dependencies:
|
||||
gaxios "^7.0.0"
|
||||
google-logging-utils "^1.0.0"
|
||||
json-bigint "^1.0.0"
|
||||
|
||||
gel@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/gel/-/gel-2.0.1.tgz#587d89db54351c2d436de981d136481e37d06a7a"
|
||||
@@ -2995,6 +3076,18 @@ glob@^10.3.10:
|
||||
minipass "^7.0.4"
|
||||
path-scurry "^1.10.2"
|
||||
|
||||
glob@^10.3.7:
|
||||
version "10.5.0"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-10.5.0.tgz#8ec0355919cd3338c28428a23d4f24ecc5fe738c"
|
||||
integrity sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==
|
||||
dependencies:
|
||||
foreground-child "^3.1.0"
|
||||
jackspeak "^3.1.2"
|
||||
minimatch "^9.0.4"
|
||||
minipass "^7.1.2"
|
||||
package-json-from-dist "^1.0.0"
|
||||
path-scurry "^1.11.1"
|
||||
|
||||
glob@^7.1.3:
|
||||
version "7.2.3"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
|
||||
@@ -3053,6 +3146,24 @@ globby@^11.1.0:
|
||||
merge2 "^1.4.1"
|
||||
slash "^3.0.0"
|
||||
|
||||
google-auth-library@^10.3.0:
|
||||
version "10.5.0"
|
||||
resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-10.5.0.tgz#3f0ebd47173496b91d2868f572bb8a8180c4b561"
|
||||
integrity sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w==
|
||||
dependencies:
|
||||
base64-js "^1.3.0"
|
||||
ecdsa-sig-formatter "^1.0.11"
|
||||
gaxios "^7.0.0"
|
||||
gcp-metadata "^8.0.0"
|
||||
google-logging-utils "^1.0.0"
|
||||
gtoken "^8.0.0"
|
||||
jws "^4.0.0"
|
||||
|
||||
google-logging-utils@^1.0.0:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/google-logging-utils/-/google-logging-utils-1.1.3.tgz#17b71f1f95d266d2ddd356b8f00178433f041b17"
|
||||
integrity sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==
|
||||
|
||||
gopd@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
|
||||
@@ -3070,6 +3181,14 @@ graphemer@^1.4.0:
|
||||
resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6"
|
||||
integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==
|
||||
|
||||
gtoken@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-8.0.0.tgz#d67a0e346dd441bfb54ad14040ddc3b632886575"
|
||||
integrity sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==
|
||||
dependencies:
|
||||
gaxios "^7.0.0"
|
||||
jws "^4.0.0"
|
||||
|
||||
guid-typescript@^1.0.9:
|
||||
version "1.0.9"
|
||||
resolved "https://registry.yarnpkg.com/guid-typescript/-/guid-typescript-1.0.9.tgz#e35f77003535b0297ea08548f5ace6adb1480ddc"
|
||||
@@ -3152,6 +3271,14 @@ html2canvas@^1.0.0-rc.5:
|
||||
css-line-break "^2.1.0"
|
||||
text-segmentation "^1.0.3"
|
||||
|
||||
https-proxy-agent@^7.0.1:
|
||||
version "7.0.6"
|
||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9"
|
||||
integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==
|
||||
dependencies:
|
||||
agent-base "^7.1.2"
|
||||
debug "4"
|
||||
|
||||
humanize-url@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/humanize-url/-/humanize-url-2.1.1.tgz#1be3dc2b8a23ee28fdf9db95b22962b3eb5e4683"
|
||||
@@ -3464,6 +3591,15 @@ jackspeak@^2.3.5, jackspeak@^2.3.6:
|
||||
optionalDependencies:
|
||||
"@pkgjs/parseargs" "^0.11.0"
|
||||
|
||||
jackspeak@^3.1.2:
|
||||
version "3.4.3"
|
||||
resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a"
|
||||
integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==
|
||||
dependencies:
|
||||
"@isaacs/cliui" "^8.0.2"
|
||||
optionalDependencies:
|
||||
"@pkgjs/parseargs" "^0.11.0"
|
||||
|
||||
javascript-natural-sort@^0.7.1:
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59"
|
||||
@@ -3493,6 +3629,13 @@ js-yaml@^4.1.0:
|
||||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
|
||||
json-bigint@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1"
|
||||
integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==
|
||||
dependencies:
|
||||
bignumber.js "^9.0.0"
|
||||
|
||||
json-buffer@3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
|
||||
@@ -3559,6 +3702,23 @@ jszip@^3.7.1:
|
||||
readable-stream "~2.3.6"
|
||||
setimmediate "^1.0.5"
|
||||
|
||||
jwa@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.1.tgz#bf8176d1ad0cd72e0f3f58338595a13e110bc804"
|
||||
integrity sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==
|
||||
dependencies:
|
||||
buffer-equal-constant-time "^1.0.1"
|
||||
ecdsa-sig-formatter "1.0.11"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
jws@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.1.tgz#07edc1be8fac20e677b283ece261498bd38f0690"
|
||||
integrity sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==
|
||||
dependencies:
|
||||
jwa "^2.0.1"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
keyv@^4.5.3:
|
||||
version "4.5.4"
|
||||
resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93"
|
||||
@@ -3777,6 +3937,13 @@ minimatch@^9.0.1:
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@^9.0.4:
|
||||
version "9.0.5"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5"
|
||||
integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.6:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
|
||||
@@ -3829,7 +3996,7 @@ ms@2.1.2:
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
ms@^2.1.1:
|
||||
ms@^2.1.1, ms@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
@@ -3896,11 +4063,25 @@ node-abi@^3.3.0:
|
||||
dependencies:
|
||||
semver "^7.3.5"
|
||||
|
||||
node-domexception@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5"
|
||||
integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==
|
||||
|
||||
node-ensure@^0.0.0:
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/node-ensure/-/node-ensure-0.0.0.tgz#ecae764150de99861ec5c810fd5d096b183932a7"
|
||||
integrity sha512-DRI60hzo2oKN1ma0ckc6nQWlHU69RH6xN0sjQTjMpChPfTYvKZdcQFfdYK2RWbJcKyUizSIy/l8OTGxMAM1QDw==
|
||||
|
||||
node-fetch@^3.3.2:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b"
|
||||
integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==
|
||||
dependencies:
|
||||
data-uri-to-buffer "^4.0.0"
|
||||
fetch-blob "^3.1.4"
|
||||
formdata-polyfill "^4.0.10"
|
||||
|
||||
node-releases@^2.0.14:
|
||||
version "2.0.14"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b"
|
||||
@@ -4090,6 +4271,11 @@ p-locate@^5.0.0:
|
||||
dependencies:
|
||||
p-limit "^3.0.2"
|
||||
|
||||
package-json-from-dist@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505"
|
||||
integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==
|
||||
|
||||
pako@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86"
|
||||
@@ -4153,6 +4339,14 @@ path-scurry@^1.10.1, path-scurry@^1.10.2:
|
||||
lru-cache "^10.2.0"
|
||||
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
|
||||
|
||||
path-scurry@^1.11.1:
|
||||
version "1.11.1"
|
||||
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2"
|
||||
integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==
|
||||
dependencies:
|
||||
lru-cache "^10.2.0"
|
||||
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
|
||||
|
||||
path-type@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
|
||||
@@ -4620,6 +4814,13 @@ rimraf@^3.0.2:
|
||||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
rimraf@^5.0.1:
|
||||
version "5.0.10"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.10.tgz#23b9843d3dc92db71f96e1a2ce92e39fd2a8221c"
|
||||
integrity sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==
|
||||
dependencies:
|
||||
glob "^10.3.7"
|
||||
|
||||
roarr@^2.15.3:
|
||||
version "2.15.4"
|
||||
resolved "https://registry.yarnpkg.com/roarr/-/roarr-2.15.4.tgz#f5fe795b7b838ccfe35dc608e0282b9eba2e7afd"
|
||||
@@ -5449,6 +5650,11 @@ utrie@^1.0.2:
|
||||
dependencies:
|
||||
base64-arraybuffer "^1.0.2"
|
||||
|
||||
web-streams-polyfill@^3.0.3:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b"
|
||||
integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==
|
||||
|
||||
whatwg-fetch@^3.6.20:
|
||||
version "3.6.20"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70"
|
||||
@@ -5541,6 +5747,11 @@ wrappy@1:
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
|
||||
|
||||
ws@^8.18.0:
|
||||
version "8.18.3"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.3.tgz#b56b88abffde62791c639170400c93dcb0c95472"
|
||||
integrity sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==
|
||||
|
||||
xmlbuilder@^10.0.0:
|
||||
version "10.1.1"
|
||||
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-10.1.1.tgz#8cae6688cc9b38d850b7c8d3c0a4161dcaf475b0"
|
||||
|
||||
Reference in New Issue
Block a user