mirror of
https://github.com/onyx-dot-app/onyx.git
synced 2026-03-16 05:02:39 +00:00
Compare commits
1 Commits
bo/custom_
...
v1.0.0-clo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b16c3e80b |
@@ -1,6 +1,5 @@
|
||||
from collections.abc import Sequence
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from uuid import UUID
|
||||
|
||||
from fastapi import HTTPException
|
||||
@@ -12,6 +11,7 @@ from sqlalchemy import select
|
||||
from sqlalchemy import update
|
||||
from sqlalchemy.orm import aliased
|
||||
from sqlalchemy.orm import joinedload
|
||||
from sqlalchemy.orm import selectinload
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from onyx.auth.schemas import UserRole
|
||||
@@ -22,7 +22,6 @@ from onyx.configs.chat_configs import CONTEXT_CHUNKS_BELOW
|
||||
from onyx.configs.constants import NotificationType
|
||||
from onyx.context.search.enums import RecencyBiasSetting
|
||||
from onyx.db.constants import SLACK_BOT_PERSONA_PREFIX
|
||||
from onyx.db.models import ConnectorCredentialPair
|
||||
from onyx.db.models import DocumentSet
|
||||
from onyx.db.models import Persona
|
||||
from onyx.db.models import Persona__User
|
||||
@@ -46,12 +45,6 @@ from onyx.utils.variable_functionality import fetch_versioned_implementation
|
||||
logger = setup_logger()
|
||||
|
||||
|
||||
class PersonaLoadType(Enum):
|
||||
NONE = "none"
|
||||
MINIMAL = "minimal"
|
||||
FULL = "full"
|
||||
|
||||
|
||||
def _add_user_filters(
|
||||
stmt: Select, user: User | None, get_editable: bool = True
|
||||
) -> Select:
|
||||
@@ -329,8 +322,6 @@ def update_persona_public_status(
|
||||
|
||||
|
||||
def get_personas_for_user(
|
||||
# defines how much of the persona to pre-load
|
||||
load_type: PersonaLoadType,
|
||||
# if user is `None` assume the user is an admin or auth is disabled
|
||||
user: User | None,
|
||||
db_session: Session,
|
||||
@@ -338,6 +329,9 @@ def get_personas_for_user(
|
||||
include_default: bool = True,
|
||||
include_slack_bot_personas: bool = False,
|
||||
include_deleted: bool = False,
|
||||
joinedload_all: bool = False,
|
||||
# a bit jank
|
||||
include_prompt: bool = True,
|
||||
) -> Sequence[Persona]:
|
||||
stmt = select(Persona)
|
||||
stmt = _add_user_filters(stmt, user, get_editable)
|
||||
@@ -349,45 +343,20 @@ def get_personas_for_user(
|
||||
if not include_deleted:
|
||||
stmt = stmt.where(Persona.deleted.is_(False))
|
||||
|
||||
if load_type == PersonaLoadType.MINIMAL:
|
||||
# For ChatPage, only load essential relationships
|
||||
if joinedload_all:
|
||||
stmt = stmt.options(
|
||||
# Used for retrieval capability checking
|
||||
joinedload(Persona.tools),
|
||||
# Used for filtering
|
||||
joinedload(Persona.labels),
|
||||
# only show document sets in the UI that the assistant has access to
|
||||
joinedload(Persona.document_sets),
|
||||
joinedload(Persona.document_sets)
|
||||
.joinedload(DocumentSet.connector_credential_pairs)
|
||||
.joinedload(ConnectorCredentialPair.connector),
|
||||
joinedload(Persona.document_sets)
|
||||
.joinedload(DocumentSet.connector_credential_pairs)
|
||||
.joinedload(ConnectorCredentialPair.credential),
|
||||
# user
|
||||
joinedload(Persona.user),
|
||||
)
|
||||
elif load_type == PersonaLoadType.FULL:
|
||||
stmt = stmt.options(
|
||||
joinedload(Persona.user),
|
||||
joinedload(Persona.tools),
|
||||
joinedload(Persona.document_sets)
|
||||
.joinedload(DocumentSet.connector_credential_pairs)
|
||||
.joinedload(ConnectorCredentialPair.connector),
|
||||
joinedload(Persona.document_sets)
|
||||
.joinedload(DocumentSet.connector_credential_pairs)
|
||||
.joinedload(ConnectorCredentialPair.credential),
|
||||
joinedload(Persona.document_sets).joinedload(DocumentSet.users),
|
||||
joinedload(Persona.document_sets).joinedload(DocumentSet.groups),
|
||||
joinedload(Persona.groups),
|
||||
joinedload(Persona.users),
|
||||
joinedload(Persona.labels),
|
||||
joinedload(Persona.user_files),
|
||||
joinedload(Persona.user_folders),
|
||||
joinedload(Persona.prompts),
|
||||
selectinload(Persona.tools),
|
||||
selectinload(Persona.document_sets),
|
||||
selectinload(Persona.groups),
|
||||
selectinload(Persona.users),
|
||||
selectinload(Persona.labels),
|
||||
selectinload(Persona.user_files),
|
||||
selectinload(Persona.user_folders),
|
||||
)
|
||||
if include_prompt:
|
||||
stmt = stmt.options(selectinload(Persona.prompts))
|
||||
|
||||
results = db_session.execute(stmt).unique().scalars().all()
|
||||
results = db_session.execute(stmt).scalars().all()
|
||||
return results
|
||||
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@ from onyx.db.persona import get_persona_by_id
|
||||
from onyx.db.persona import get_personas_for_user
|
||||
from onyx.db.persona import mark_persona_as_deleted
|
||||
from onyx.db.persona import mark_persona_as_not_deleted
|
||||
from onyx.db.persona import PersonaLoadType
|
||||
from onyx.db.persona import update_all_personas_display_priority
|
||||
from onyx.db.persona import update_persona_is_default
|
||||
from onyx.db.persona import update_persona_label
|
||||
@@ -46,7 +45,6 @@ from onyx.secondary_llm_flows.starter_message_creation import (
|
||||
from onyx.server.features.persona.models import FullPersonaSnapshot
|
||||
from onyx.server.features.persona.models import GenerateStarterMessageRequest
|
||||
from onyx.server.features.persona.models import ImageGenerationToolStatus
|
||||
from onyx.server.features.persona.models import MinimalPersonaSnapshot
|
||||
from onyx.server.features.persona.models import PersonaLabelCreate
|
||||
from onyx.server.features.persona.models import PersonaLabelResponse
|
||||
from onyx.server.features.persona.models import PersonaSharedNotificationData
|
||||
@@ -156,7 +154,7 @@ def list_personas_admin(
|
||||
user=user,
|
||||
get_editable=get_editable,
|
||||
include_deleted=include_deleted,
|
||||
load_type=PersonaLoadType.FULL,
|
||||
joinedload_all=True,
|
||||
)
|
||||
]
|
||||
|
||||
@@ -395,13 +393,14 @@ def list_personas(
|
||||
db_session: Session = Depends(get_session),
|
||||
include_deleted: bool = False,
|
||||
persona_ids: list[int] = Query(None),
|
||||
) -> list[MinimalPersonaSnapshot]:
|
||||
) -> list[PersonaSnapshot]:
|
||||
personas = get_personas_for_user(
|
||||
load_type=PersonaLoadType.MINIMAL,
|
||||
user=user,
|
||||
include_deleted=include_deleted,
|
||||
db_session=db_session,
|
||||
get_editable=False,
|
||||
joinedload_all=True,
|
||||
include_prompt=False,
|
||||
)
|
||||
|
||||
if persona_ids:
|
||||
@@ -417,8 +416,7 @@ def list_personas(
|
||||
)
|
||||
]
|
||||
|
||||
result = [MinimalPersonaSnapshot.from_model(p) for p in personas]
|
||||
return result
|
||||
return [PersonaSnapshot.from_model(p) for p in personas]
|
||||
|
||||
|
||||
@basic_router.get("/{persona_id}")
|
||||
|
||||
@@ -18,64 +18,6 @@ from onyx.utils.logger import setup_logger
|
||||
logger = setup_logger()
|
||||
|
||||
|
||||
class MinimalPersonaSnapshot(BaseModel):
|
||||
"""Minimal persona model optimized for ChatPage.tsx - only includes fields actually used"""
|
||||
|
||||
# Core fields used by ChatPage
|
||||
id: int
|
||||
name: str
|
||||
description: str
|
||||
tools: list[ToolSnapshot]
|
||||
starter_messages: list[StarterMessage] | None
|
||||
document_sets: list[DocumentSet]
|
||||
llm_model_version_override: str | None
|
||||
llm_model_provider_override: str | None
|
||||
|
||||
uploaded_image_id: str | None
|
||||
icon_shape: int | None
|
||||
icon_color: str | None
|
||||
|
||||
is_public: bool
|
||||
is_visible: bool
|
||||
display_priority: int | None
|
||||
is_default_persona: bool
|
||||
builtin_persona: bool
|
||||
|
||||
labels: list["PersonaLabelSnapshot"]
|
||||
owner: MinimalUserSnapshot | None
|
||||
|
||||
@classmethod
|
||||
def from_model(cls, persona: Persona) -> "MinimalPersonaSnapshot":
|
||||
return MinimalPersonaSnapshot(
|
||||
# Core fields actually used by ChatPage
|
||||
id=persona.id,
|
||||
name=persona.name,
|
||||
description=persona.description,
|
||||
tools=[ToolSnapshot.from_model(tool) for tool in persona.tools],
|
||||
starter_messages=persona.starter_messages,
|
||||
document_sets=[
|
||||
DocumentSet.from_model(document_set)
|
||||
for document_set in persona.document_sets
|
||||
],
|
||||
llm_model_version_override=persona.llm_model_version_override,
|
||||
llm_model_provider_override=persona.llm_model_provider_override,
|
||||
uploaded_image_id=persona.uploaded_image_id,
|
||||
icon_shape=persona.icon_shape,
|
||||
icon_color=persona.icon_color,
|
||||
is_public=persona.is_public,
|
||||
is_visible=persona.is_visible,
|
||||
display_priority=persona.display_priority,
|
||||
is_default_persona=persona.is_default_persona,
|
||||
builtin_persona=persona.builtin_persona,
|
||||
labels=[PersonaLabelSnapshot.from_model(label) for label in persona.labels],
|
||||
owner=(
|
||||
MinimalUserSnapshot(id=persona.user.id, email=persona.user.email)
|
||||
if persona.user
|
||||
else None
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class PromptSnapshot(BaseModel):
|
||||
id: int
|
||||
name: str
|
||||
|
||||
@@ -17,7 +17,6 @@ from onyx.db.models import User
|
||||
from onyx.db.persona import get_persona_by_id
|
||||
from onyx.db.persona import get_personas_for_user
|
||||
from onyx.db.persona import mark_persona_as_deleted
|
||||
from onyx.db.persona import PersonaLoadType
|
||||
from onyx.db.persona import upsert_persona
|
||||
from onyx.db.prompts import upsert_prompt
|
||||
from onyx.db.tools import get_tool_by_name
|
||||
@@ -245,10 +244,10 @@ def list_assistants(
|
||||
) -> ListAssistantsResponse:
|
||||
personas = list(
|
||||
get_personas_for_user(
|
||||
load_type=PersonaLoadType.FULL,
|
||||
user=user,
|
||||
db_session=db_session,
|
||||
get_editable=False,
|
||||
joinedload_all=True,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -258,7 +258,7 @@ export function AssistantEditor({
|
||||
existingPersona?.llm_model_version_override ?? null,
|
||||
starter_messages: existingPersona?.starter_messages?.length
|
||||
? existingPersona.starter_messages
|
||||
: [{ message: "", name: "" }],
|
||||
: [{ message: "" }],
|
||||
enabled_tools_map: enabledToolsMap,
|
||||
icon_color: existingPersona?.icon_color ?? defautIconColor,
|
||||
icon_shape: existingPersona?.icon_shape ?? defaultIconShape,
|
||||
@@ -526,8 +526,10 @@ export function AssistantEditor({
|
||||
// to tell the backend to not fetch any documents
|
||||
const numChunks = searchToolEnabled ? values.num_chunks || 25 : 0;
|
||||
const starterMessages = values.starter_messages
|
||||
.filter((message: StarterMessage) => message.message.trim() !== "")
|
||||
.map((message: StarterMessage) => ({
|
||||
.filter(
|
||||
(message: { message: string }) => message.message.trim() !== ""
|
||||
)
|
||||
.map((message: { message: string; name?: string }) => ({
|
||||
message: message.message,
|
||||
name: message.message,
|
||||
}));
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
import { FiEdit2 } from "react-icons/fi";
|
||||
import { TrashIcon } from "@/components/icons/icons";
|
||||
import { useUser } from "@/components/user/UserProvider";
|
||||
import { useAssistants } from "@/components/context/AssistantsContext";
|
||||
import { ConfirmEntityModal } from "@/components/modals/ConfirmEntityModal";
|
||||
|
||||
function PersonaTypeDisplay({ persona }: { persona: Persona }) {
|
||||
@@ -39,18 +40,16 @@ function PersonaTypeDisplay({ persona }: { persona: Persona }) {
|
||||
return <Text>Personal {persona.owner && <>({persona.owner.email})</>}</Text>;
|
||||
}
|
||||
|
||||
export function PersonasTable({
|
||||
personas,
|
||||
refreshPersonas,
|
||||
}: {
|
||||
personas: Persona[];
|
||||
refreshPersonas: () => void;
|
||||
}) {
|
||||
export function PersonasTable() {
|
||||
const router = useRouter();
|
||||
const { popup, setPopup } = usePopup();
|
||||
const { refreshUser, isAdmin } = useUser();
|
||||
const {
|
||||
allAssistants: assistants,
|
||||
refreshAssistants,
|
||||
editablePersonas,
|
||||
} = useAssistants();
|
||||
|
||||
const editablePersonas = personas.filter((p) => !p.builtin_persona);
|
||||
const editablePersonaIds = useMemo(() => {
|
||||
return new Set(editablePersonas.map((p) => p.id.toString()));
|
||||
}, [editablePersonas]);
|
||||
@@ -64,18 +63,18 @@ export function PersonasTable({
|
||||
|
||||
useEffect(() => {
|
||||
const editable = editablePersonas.sort(personaComparator);
|
||||
const nonEditable = personas
|
||||
const nonEditable = assistants
|
||||
.filter((p) => !editablePersonaIds.has(p.id.toString()))
|
||||
.sort(personaComparator);
|
||||
setFinalPersonas([...editable, ...nonEditable]);
|
||||
}, [editablePersonas, personas, editablePersonaIds]);
|
||||
}, [editablePersonas, assistants, editablePersonaIds]);
|
||||
|
||||
const updatePersonaOrder = async (orderedPersonaIds: UniqueIdentifier[]) => {
|
||||
const reorderedPersonas = orderedPersonaIds.map(
|
||||
(id) => personas.find((persona) => persona.id.toString() === id)!
|
||||
const reorderedAssistants = orderedPersonaIds.map(
|
||||
(id) => assistants.find((assistant) => assistant.id.toString() === id)!
|
||||
);
|
||||
|
||||
setFinalPersonas(reorderedPersonas);
|
||||
setFinalPersonas(reorderedAssistants);
|
||||
|
||||
const displayPriorityMap = new Map<UniqueIdentifier, number>();
|
||||
orderedPersonaIds.forEach((personaId, ind) => {
|
||||
@@ -97,12 +96,12 @@ export function PersonasTable({
|
||||
type: "error",
|
||||
message: `Failed to update persona order - ${await response.text()}`,
|
||||
});
|
||||
setFinalPersonas(personas);
|
||||
await refreshPersonas();
|
||||
setFinalPersonas(assistants);
|
||||
await refreshAssistants();
|
||||
return;
|
||||
}
|
||||
|
||||
await refreshPersonas();
|
||||
await refreshAssistants();
|
||||
await refreshUser();
|
||||
};
|
||||
|
||||
@@ -120,7 +119,7 @@ export function PersonasTable({
|
||||
if (personaToDelete) {
|
||||
const response = await deletePersona(personaToDelete.id);
|
||||
if (response.ok) {
|
||||
refreshPersonas();
|
||||
await refreshAssistants();
|
||||
closeDeleteModal();
|
||||
} else {
|
||||
setPopup({
|
||||
@@ -148,7 +147,7 @@ export function PersonasTable({
|
||||
personaToToggleDefault.is_default_persona
|
||||
);
|
||||
if (response.ok) {
|
||||
refreshPersonas();
|
||||
await refreshAssistants();
|
||||
closeDefaultModal();
|
||||
} else {
|
||||
setPopup({
|
||||
@@ -268,7 +267,7 @@ export function PersonasTable({
|
||||
persona.is_visible
|
||||
);
|
||||
if (response.ok) {
|
||||
refreshPersonas();
|
||||
await refreshAssistants();
|
||||
} else {
|
||||
setPopup({
|
||||
type: "error",
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
import useSWR from "swr";
|
||||
import { errorHandlingFetcher } from "@/lib/fetcher";
|
||||
import { buildApiPath } from "@/lib/urlBuilder";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
|
||||
interface UseAdminPersonasOptions {
|
||||
includeDeleted?: boolean;
|
||||
getEditable?: boolean;
|
||||
}
|
||||
|
||||
export const useAdminPersonas = (options?: UseAdminPersonasOptions) => {
|
||||
const { includeDeleted = false, getEditable = false } = options || {};
|
||||
|
||||
const url = buildApiPath("/api/admin/persona", {
|
||||
include_deleted: includeDeleted.toString(),
|
||||
get_editable: getEditable.toString(),
|
||||
});
|
||||
|
||||
const { data, error, isLoading, mutate } = useSWR<Persona[]>(
|
||||
url,
|
||||
errorHandlingFetcher
|
||||
);
|
||||
|
||||
return {
|
||||
personas: data,
|
||||
error,
|
||||
isLoading,
|
||||
refresh: mutate,
|
||||
};
|
||||
};
|
||||
@@ -18,36 +18,29 @@ export interface Prompt {
|
||||
datetime_aware: boolean;
|
||||
default_prompt: boolean;
|
||||
}
|
||||
|
||||
export interface MinimalPersonaSnapshot {
|
||||
export interface Persona {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
tools: ToolSnapshot[];
|
||||
starter_messages: StarterMessage[] | null;
|
||||
document_sets: DocumentSetSummary[];
|
||||
llm_model_version_override?: string;
|
||||
llm_model_provider_override?: string;
|
||||
|
||||
uploaded_image_id?: string;
|
||||
icon_shape?: number;
|
||||
icon_color?: string;
|
||||
|
||||
is_public: boolean;
|
||||
is_visible: boolean;
|
||||
icon_shape?: number;
|
||||
icon_color?: string;
|
||||
uploaded_image_id?: string;
|
||||
user_file_ids: number[];
|
||||
user_folder_ids: number[];
|
||||
display_priority: number | null;
|
||||
is_default_persona: boolean;
|
||||
builtin_persona: boolean;
|
||||
|
||||
starter_messages: StarterMessage[] | null;
|
||||
tools: ToolSnapshot[];
|
||||
labels?: PersonaLabel[];
|
||||
owner: MinimalUserSnapshot | null;
|
||||
}
|
||||
|
||||
export interface Persona extends MinimalPersonaSnapshot {
|
||||
user_file_ids: number[];
|
||||
user_folder_ids: number[];
|
||||
users: MinimalUserSnapshot[];
|
||||
groups: number[];
|
||||
document_sets: DocumentSetSummary[];
|
||||
llm_model_provider_override?: string;
|
||||
llm_model_version_override?: string;
|
||||
num_chunks?: number;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { LLMProviderView } from "../configuration/llm/interfaces";
|
||||
import { MinimalPersonaSnapshot, Persona, StarterMessage } from "./interfaces";
|
||||
import { Persona, StarterMessage } from "./interfaces";
|
||||
|
||||
interface PersonaUpsertRequest {
|
||||
name: string;
|
||||
@@ -250,10 +250,7 @@ function closerToZeroNegativesFirstComparator(a: number, b: number) {
|
||||
return absA > absB ? 1 : -1;
|
||||
}
|
||||
|
||||
export function personaComparator(
|
||||
a: MinimalPersonaSnapshot | Persona,
|
||||
b: MinimalPersonaSnapshot | Persona
|
||||
) {
|
||||
export function personaComparator(a: Persona, b: Persona) {
|
||||
if (a.display_priority === null && b.display_priority === null) {
|
||||
return closerToZeroNegativesFirstComparator(a.id, b.id);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
"use client";
|
||||
|
||||
import { PersonasTable } from "./PersonaTable";
|
||||
import Text from "@/components/ui/text";
|
||||
import Title from "@/components/ui/title";
|
||||
@@ -8,20 +6,11 @@ import { AssistantsIcon } from "@/components/icons/icons";
|
||||
import { AdminPageTitle } from "@/components/admin/Title";
|
||||
import { SubLabel } from "@/components/Field";
|
||||
import CreateButton from "@/components/ui/createButton";
|
||||
import { useAdminPersonas } from "./hooks";
|
||||
import { Persona } from "./interfaces";
|
||||
import { ThreeDotsLoader } from "@/components/Loading";
|
||||
import { ErrorCallout } from "@/components/ErrorCallout";
|
||||
|
||||
function MainContent({
|
||||
personas,
|
||||
refreshPersonas,
|
||||
}: {
|
||||
personas: Persona[];
|
||||
refreshPersonas: () => void;
|
||||
}) {
|
||||
export default async function Page() {
|
||||
return (
|
||||
<div>
|
||||
<div className="mx-auto container">
|
||||
<AdminPageTitle icon={<AssistantsIcon size={32} />} title="Assistants" />
|
||||
|
||||
<Text className="mb-2">
|
||||
Assistants are a way to build custom search/question-answering
|
||||
experiences for different use cases.
|
||||
@@ -51,35 +40,8 @@ function MainContent({
|
||||
hidden will not be displayed. Editable assistants are shown at the
|
||||
top.
|
||||
</SubLabel>
|
||||
<PersonasTable personas={personas} refreshPersonas={refreshPersonas} />
|
||||
<PersonasTable />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Page() {
|
||||
const { personas, isLoading, error, refresh } = useAdminPersonas();
|
||||
|
||||
return (
|
||||
<div className="mx-auto container">
|
||||
<AdminPageTitle icon={<AssistantsIcon size={32} />} title="Assistants" />
|
||||
|
||||
{isLoading && <ThreeDotsLoader />}
|
||||
|
||||
{error && (
|
||||
<ErrorCallout
|
||||
errorTitle="Failed to load assistants"
|
||||
errorMsg={
|
||||
error?.info?.message ||
|
||||
error?.info?.detail ||
|
||||
"An unknown error occurred"
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
{!isLoading && !error && (
|
||||
<MainContent personas={personas || []} refreshPersonas={refresh} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { PageSelector } from "@/components/PageSelector";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
import { FiEdit } from "react-icons/fi";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
} from "../lib";
|
||||
import CardSection from "@/components/admin/CardSection";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { MinimalPersonaSnapshot } from "@/app/admin/assistants/interfaces";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import { StandardAnswerCategoryResponse } from "@/components/standardAnswers/getStandardAnswerCategoriesIfEE";
|
||||
import { SEARCH_TOOL_ID } from "@/app/chat/tools/constants";
|
||||
import { SlackChannelConfigFormFields } from "./SlackChannelConfigFormFields";
|
||||
@@ -30,7 +30,7 @@ export const SlackChannelConfigCreationForm = ({
|
||||
}: {
|
||||
slack_bot_id: number;
|
||||
documentSets: DocumentSetSummary[];
|
||||
personas: MinimalPersonaSnapshot[];
|
||||
personas: Persona[];
|
||||
standardAnswerCategoryResponse: StandardAnswerCategoryResponse;
|
||||
existingSlackChannelConfig?: SlackChannelConfig;
|
||||
}) => {
|
||||
@@ -59,7 +59,7 @@ export const SlackChannelConfigCreationForm = ({
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
[[], []] as [MinimalPersonaSnapshot[], MinimalPersonaSnapshot[]]
|
||||
[[], []] as [Persona[], Persona[]]
|
||||
);
|
||||
}, [personas]);
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
TextFormField,
|
||||
} from "@/components/Field";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { MinimalPersonaSnapshot } from "@/app/admin/assistants/interfaces";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import { DocumentSetSelectable } from "@/components/documentSet/DocumentSetSelectable";
|
||||
import CollapsibleSection from "@/app/admin/assistants/CollapsibleSection";
|
||||
import { StandardAnswerCategoryResponse } from "@/components/standardAnswers/getStandardAnswerCategoriesIfEE";
|
||||
@@ -44,8 +44,8 @@ export interface SlackChannelConfigFormFieldsProps {
|
||||
isUpdate: boolean;
|
||||
isDefault: boolean;
|
||||
documentSets: DocumentSetSummary[];
|
||||
searchEnabledAssistants: MinimalPersonaSnapshot[];
|
||||
nonSearchAssistants: MinimalPersonaSnapshot[];
|
||||
searchEnabledAssistants: Persona[];
|
||||
nonSearchAssistants: Persona[];
|
||||
standardAnswerCategoryResponse: StandardAnswerCategoryResponse;
|
||||
setPopup: (popup: {
|
||||
message: string;
|
||||
@@ -92,8 +92,8 @@ export function SlackChannelConfigFormFields({
|
||||
};
|
||||
|
||||
const [syncEnabledAssistants, availableAssistants] = useMemo(() => {
|
||||
const sync: MinimalPersonaSnapshot[] = [];
|
||||
const available: MinimalPersonaSnapshot[] = [];
|
||||
const sync: Persona[] = [];
|
||||
const available: Persona[] = [];
|
||||
|
||||
searchEnabledAssistants.forEach((persona) => {
|
||||
const hasSyncSet = persona.document_sets.some(documentSetContainsSync);
|
||||
@@ -380,25 +380,23 @@ export function SlackChannelConfigFormFields({
|
||||
Un-selectable assistants:
|
||||
</p>
|
||||
<div className="mb-3 mt-2 flex gap-2 flex-wrap text-sm">
|
||||
{syncEnabledAssistants.map(
|
||||
(persona: MinimalPersonaSnapshot) => (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() =>
|
||||
router.push(`/admin/assistants/${persona.id}`)
|
||||
}
|
||||
key={persona.id}
|
||||
className="p-2 bg-background-100 cursor-pointer rounded-md flex items-center gap-2"
|
||||
>
|
||||
<AssistantIcon
|
||||
assistant={persona}
|
||||
size={16}
|
||||
className="flex-none"
|
||||
/>
|
||||
{persona.name}
|
||||
</button>
|
||||
)
|
||||
)}
|
||||
{syncEnabledAssistants.map((persona: Persona) => (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() =>
|
||||
router.push(`/admin/assistants/${persona.id}`)
|
||||
}
|
||||
key={persona.id}
|
||||
className="p-2 bg-background-100 cursor-pointer rounded-md flex items-center gap-2"
|
||||
>
|
||||
<AssistantIcon
|
||||
assistant={persona}
|
||||
size={16}
|
||||
className="flex-none"
|
||||
/>
|
||||
{persona.name}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -5,8 +5,12 @@ import { ErrorCallout } from "@/components/ErrorCallout";
|
||||
import { DocumentSetSummary, ValidSources } from "@/lib/types";
|
||||
import { BackButton } from "@/components/BackButton";
|
||||
import { fetchAssistantsSS } from "@/lib/assistants/fetchAssistantsSS";
|
||||
import { getStandardAnswerCategoriesIfEE } from "@/components/standardAnswers/getStandardAnswerCategoriesIfEE";
|
||||
import {
|
||||
getStandardAnswerCategoriesIfEE,
|
||||
StandardAnswerCategoryResponse,
|
||||
} from "@/components/standardAnswers/getStandardAnswerCategoriesIfEE";
|
||||
import { redirect } from "next/navigation";
|
||||
import { Persona } from "../../../../assistants/interfaces";
|
||||
import { SourceIcon } from "@/components/SourceIcon";
|
||||
|
||||
async function NewChannelConfigPage(props: {
|
||||
@@ -28,8 +32,8 @@ async function NewChannelConfigPage(props: {
|
||||
standardAnswerCategoryResponse,
|
||||
] = await Promise.all([
|
||||
fetchSS("/manage/document-set") as Promise<Response>,
|
||||
fetchAssistantsSS(),
|
||||
getStandardAnswerCategoriesIfEE(),
|
||||
fetchAssistantsSS() as Promise<[Persona[], string | null]>,
|
||||
getStandardAnswerCategoriesIfEE() as Promise<StandardAnswerCategoryResponse>,
|
||||
]);
|
||||
|
||||
if (!documentSetsResponse.ok) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useState } from "react";
|
||||
import { PopupSpec } from "@/components/admin/connectors/Popup";
|
||||
import { usePopup, PopupSpec } from "@/components/admin/connectors/Popup";
|
||||
import { triggerIndexing } from "./lib";
|
||||
import { Modal } from "@/components/Modal";
|
||||
import Text from "@/components/ui/text";
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
PopoverContent,
|
||||
} from "@/components/ui/popover";
|
||||
import { AssistantIcon } from "@/components/assistants/AssistantIcon";
|
||||
import { MinimalPersonaSnapshot } from "@/app/admin/assistants/interfaces";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import { useUser } from "@/components/user/UserProvider";
|
||||
import { useAssistants } from "@/components/context/AssistantsContext";
|
||||
import { checkUserOwnsAssistant } from "@/lib/assistants/utils";
|
||||
@@ -54,7 +54,7 @@ export const AssistantBadge = ({
|
||||
};
|
||||
|
||||
const AssistantCard: React.FC<{
|
||||
persona: MinimalPersonaSnapshot;
|
||||
persona: Persona;
|
||||
pinned: boolean;
|
||||
closeModal: () => void;
|
||||
}> = ({ persona, pinned, closeModal }) => {
|
||||
|
||||
@@ -9,6 +9,7 @@ import * as Yup from "yup";
|
||||
import { requestEmailVerification } from "../lib";
|
||||
import { useState } from "react";
|
||||
import { Spinner } from "@/components/Spinner";
|
||||
import { NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED } from "@/lib/constants";
|
||||
import Link from "next/link";
|
||||
import { useUser } from "@/components/user/UserProvider";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
import { AssistantIcon } from "@/components/assistants/AssistantIcon";
|
||||
import { MinimalPersonaSnapshot } from "../admin/assistants/interfaces";
|
||||
import { Persona } from "../admin/assistants/interfaces";
|
||||
|
||||
export function ChatIntro({
|
||||
selectedPersona,
|
||||
}: {
|
||||
selectedPersona: MinimalPersonaSnapshot;
|
||||
}) {
|
||||
export function ChatIntro({ selectedPersona }: { selectedPersona: Persona }) {
|
||||
return (
|
||||
<div data-testid="chat-intro" className="flex flex-col items-center gap-6">
|
||||
<div className="relative flex flex-col gap-y-4 w-fit mx-auto justify-center">
|
||||
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
import Prism from "prismjs";
|
||||
import Cookies from "js-cookie";
|
||||
import { HistorySidebar } from "./sessionSidebar/HistorySidebar";
|
||||
import { MinimalPersonaSnapshot } from "../admin/assistants/interfaces";
|
||||
import { Persona } from "../admin/assistants/interfaces";
|
||||
import { HealthCheckBanner } from "@/components/health/healthcheck";
|
||||
import {
|
||||
buildChatUrl,
|
||||
@@ -49,6 +49,7 @@ import {
|
||||
setMessageAsLatest,
|
||||
updateLlmOverrideForChatSession,
|
||||
updateParentChildren,
|
||||
uploadFilesForChat,
|
||||
useScrollonStream,
|
||||
} from "./lib";
|
||||
import {
|
||||
@@ -404,7 +405,7 @@ export function ChatPage({
|
||||
|
||||
const existingChatSessionAssistantId = selectedChatSession?.persona_id;
|
||||
const [selectedAssistant, setSelectedAssistant] = useState<
|
||||
MinimalPersonaSnapshot | undefined
|
||||
Persona | undefined
|
||||
>(
|
||||
// NOTE: look through available assistants here, so that even if the user
|
||||
// has hidden this assistant it still shows the correct assistant when
|
||||
@@ -434,7 +435,7 @@ export function ChatPage({
|
||||
};
|
||||
|
||||
const [alternativeAssistant, setAlternativeAssistant] =
|
||||
useState<MinimalPersonaSnapshot | null>(null);
|
||||
useState<Persona | null>(null);
|
||||
|
||||
const [presentingDocument, setPresentingDocument] =
|
||||
useState<MinimalOnyxDocument | null>(null);
|
||||
@@ -445,7 +446,7 @@ export function ChatPage({
|
||||
// 3. First pinned assistants (ordered list of pinned assistants)
|
||||
// 4. Available assistants (ordered list of available assistants)
|
||||
// Relevant test: `live_assistant.spec.ts`
|
||||
const liveAssistant: MinimalPersonaSnapshot | undefined = useMemo(
|
||||
const liveAssistant: Persona | undefined = useMemo(
|
||||
() =>
|
||||
alternativeAssistant ||
|
||||
selectedAssistant ||
|
||||
@@ -534,7 +535,7 @@ export function ChatPage({
|
||||
// 2. we "@"ed the `GPT` assistant and sent a message
|
||||
// 3. while the `GPT` assistant message is generating, we "@" the `Paraphrase` assistant
|
||||
const [alternativeGeneratingAssistant, setAlternativeGeneratingAssistant] =
|
||||
useState<MinimalPersonaSnapshot | null>(null);
|
||||
useState<Persona | null>(null);
|
||||
|
||||
// used to track whether or not the initial "submit on load" has been performed
|
||||
// this only applies if `?submit-on-load=true` or `?submit-on-load=1` is in the URL
|
||||
@@ -1326,7 +1327,7 @@ export function ChatPage({
|
||||
queryOverride?: string;
|
||||
forceSearch?: boolean;
|
||||
isSeededChat?: boolean;
|
||||
alternativeAssistantOverride?: MinimalPersonaSnapshot | null;
|
||||
alternativeAssistantOverride?: Persona | null;
|
||||
modelOverride?: LlmDescriptor;
|
||||
regenerationRequest?: RegenerationRequest | null;
|
||||
overrideFileDescriptors?: FileDescriptor[];
|
||||
@@ -2196,7 +2197,10 @@ export function ChatPage({
|
||||
useEffect(() => {
|
||||
if (liveAssistant) {
|
||||
const hasSearchTool = liveAssistant.tools.some(
|
||||
(tool) => tool.in_code_tool_id === SEARCH_TOOL_ID
|
||||
(tool) =>
|
||||
tool.in_code_tool_id === SEARCH_TOOL_ID &&
|
||||
liveAssistant.user_file_ids?.length == 0 &&
|
||||
liveAssistant.user_folder_ids?.length == 0
|
||||
);
|
||||
setRetrievalEnabled(hasSearchTool);
|
||||
if (!hasSearchTool) {
|
||||
@@ -2208,7 +2212,10 @@ export function ChatPage({
|
||||
const [retrievalEnabled, setRetrievalEnabled] = useState(() => {
|
||||
if (liveAssistant) {
|
||||
return liveAssistant.tools.some(
|
||||
(tool) => tool.in_code_tool_id === SEARCH_TOOL_ID
|
||||
(tool) =>
|
||||
tool.in_code_tool_id === SEARCH_TOOL_ID &&
|
||||
liveAssistant.user_file_ids?.length == 0 &&
|
||||
liveAssistant.user_folder_ids?.length == 0
|
||||
);
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
useLlmManager,
|
||||
} from "@/lib/hooks";
|
||||
|
||||
import { MinimalPersonaSnapshot } from "@/app/admin/assistants/interfaces";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import { parseLlmDescriptor } from "@/lib/llm/utils";
|
||||
import { useState } from "react";
|
||||
import { Hoverable } from "@/components/Hoverable";
|
||||
@@ -19,7 +19,7 @@ export default function RegenerateOption({
|
||||
overriddenModel,
|
||||
onDropdownVisibleChange,
|
||||
}: {
|
||||
selectedAssistant: MinimalPersonaSnapshot;
|
||||
selectedAssistant: Persona;
|
||||
regenerate: (modelOverRide: LlmDescriptor) => Promise<void>;
|
||||
overriddenModel?: string;
|
||||
onDropdownVisibleChange: (isVisible: boolean) => void;
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useContext, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { FiPlusCircle, FiPlus, FiX, FiFilter } from "react-icons/fi";
|
||||
import { FiLoader } from "react-icons/fi";
|
||||
import { ChatInputOption } from "./ChatInputOption";
|
||||
import { MinimalPersonaSnapshot } from "@/app/admin/assistants/interfaces";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import LLMPopover from "./LLMPopover";
|
||||
import { InputPrompt } from "@/app/chat/interfaces";
|
||||
|
||||
@@ -39,6 +39,7 @@ import { AgenticToggle } from "./AgenticToggle";
|
||||
import { SettingsContext } from "@/components/settings/SettingsProvider";
|
||||
import { getProviderIcon } from "@/app/admin/configuration/llm/utils";
|
||||
import { useDocumentsContext } from "../my-documents/DocumentsContext";
|
||||
import { UploadIntent } from "../ChatPage";
|
||||
|
||||
const MAX_INPUT_HEIGHT = 200;
|
||||
export const SourceChip2 = ({
|
||||
@@ -181,12 +182,10 @@ interface ChatInputBarProps {
|
||||
onSubmit: () => void;
|
||||
llmManager: LlmManager;
|
||||
chatState: ChatState;
|
||||
alternativeAssistant: MinimalPersonaSnapshot | null;
|
||||
alternativeAssistant: Persona | null;
|
||||
// assistants
|
||||
selectedAssistant: MinimalPersonaSnapshot;
|
||||
setAlternativeAssistant: (
|
||||
alternativeAssistant: MinimalPersonaSnapshot | null
|
||||
) => void;
|
||||
selectedAssistant: Persona;
|
||||
setAlternativeAssistant: (alternativeAssistant: Persona | null) => void;
|
||||
toggleDocumentSidebar: () => void;
|
||||
setFiles: (files: FileDescriptor[]) => void;
|
||||
handleFileUpload: (files: File[]) => void;
|
||||
@@ -307,7 +306,7 @@ export function ChatInputBar({
|
||||
};
|
||||
}, []);
|
||||
|
||||
const updatedTaggedAssistant = (assistant: MinimalPersonaSnapshot) => {
|
||||
const updatedTaggedAssistant = (assistant: Persona) => {
|
||||
setAlternativeAssistant(
|
||||
assistant.id == selectedAssistant.id ? null : assistant
|
||||
);
|
||||
|
||||
@@ -8,7 +8,7 @@ import { getDisplayNameForModel, LlmDescriptor } from "@/lib/hooks";
|
||||
import { modelSupportsImageInput } from "@/lib/llm/utils";
|
||||
import { LLMProviderDescriptor } from "@/app/admin/configuration/llm/interfaces";
|
||||
import { getProviderIcon } from "@/app/admin/configuration/llm/utils";
|
||||
import { MinimalPersonaSnapshot } from "@/app/admin/assistants/interfaces";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import { LlmManager } from "@/lib/hooks";
|
||||
|
||||
import {
|
||||
@@ -28,7 +28,7 @@ interface LLMPopoverProps {
|
||||
llmProviders: LLMProviderDescriptor[];
|
||||
llmManager: LlmManager;
|
||||
requiresImageGeneration?: boolean;
|
||||
currentAssistant?: MinimalPersonaSnapshot;
|
||||
currentAssistant?: Persona;
|
||||
trigger?: React.ReactElement;
|
||||
onSelect?: (value: string) => void;
|
||||
currentModelName?: string;
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
AgenticMessageResponseIDInfo,
|
||||
UserKnowledgeFilePacket,
|
||||
} from "./interfaces";
|
||||
import { MinimalPersonaSnapshot } from "../admin/assistants/interfaces";
|
||||
import { Persona } from "../admin/assistants/interfaces";
|
||||
import { ReadonlyURLSearchParams } from "next/navigation";
|
||||
import { SEARCH_PARAM_NAMES } from "./searchParams";
|
||||
import { Settings } from "../admin/settings/interfaces";
|
||||
@@ -631,8 +631,8 @@ export function removeMessage(
|
||||
|
||||
export function checkAnyAssistantHasSearch(
|
||||
messageHistory: Message[],
|
||||
availableAssistants: MinimalPersonaSnapshot[],
|
||||
livePersona: MinimalPersonaSnapshot
|
||||
availableAssistants: Persona[],
|
||||
livePersona: Persona
|
||||
): boolean {
|
||||
const response =
|
||||
messageHistory.some((message) => {
|
||||
@@ -653,17 +653,19 @@ export function checkAnyAssistantHasSearch(
|
||||
return response;
|
||||
}
|
||||
|
||||
export function personaIncludesRetrieval(
|
||||
selectedPersona: MinimalPersonaSnapshot
|
||||
) {
|
||||
export function personaIncludesRetrieval(selectedPersona: Persona) {
|
||||
return selectedPersona.tools.some(
|
||||
(tool) =>
|
||||
tool.in_code_tool_id &&
|
||||
[SEARCH_TOOL_ID, INTERNET_SEARCH_TOOL_ID].includes(tool.in_code_tool_id)
|
||||
[SEARCH_TOOL_ID, INTERNET_SEARCH_TOOL_ID].includes(
|
||||
tool.in_code_tool_id
|
||||
) &&
|
||||
selectedPersona.user_file_ids?.length === 0 &&
|
||||
selectedPersona.user_folder_ids?.length === 0
|
||||
);
|
||||
}
|
||||
|
||||
export function personaIncludesImage(selectedPersona: MinimalPersonaSnapshot) {
|
||||
export function personaIncludesImage(selectedPersona: Persona) {
|
||||
return selectedPersona.tools.some(
|
||||
(tool) =>
|
||||
tool.in_code_tool_id && tool.in_code_tool_id == IIMAGE_GENERATION_TOOL_ID
|
||||
|
||||
@@ -27,7 +27,7 @@ import rehypePrism from "rehype-prism-plus";
|
||||
|
||||
import "prismjs/themes/prism-tomorrow.css";
|
||||
import "./custom-code-styles.css";
|
||||
import { MinimalPersonaSnapshot } from "@/app/admin/assistants/interfaces";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import { AssistantIcon } from "@/components/assistants/AssistantIcon";
|
||||
|
||||
import { LikeFeedback, DislikeFeedback } from "@/components/icons/icons";
|
||||
@@ -107,8 +107,8 @@ export const AgenticMessage = ({
|
||||
onMessageSelection?: (messageId: number) => void;
|
||||
toggleDocumentSelection?: (second: boolean) => void;
|
||||
docs?: OnyxDocument[] | null;
|
||||
alternativeAssistant?: MinimalPersonaSnapshot | null;
|
||||
currentPersona: MinimalPersonaSnapshot;
|
||||
alternativeAssistant?: Persona | null;
|
||||
currentPersona: Persona;
|
||||
messageId: number | null;
|
||||
content: string | JSX.Element;
|
||||
files?: FileDescriptor[];
|
||||
|
||||
@@ -40,7 +40,7 @@ import { CodeBlock } from "./CodeBlock";
|
||||
import rehypePrism from "rehype-prism-plus";
|
||||
import "prismjs/themes/prism-tomorrow.css";
|
||||
import "./custom-code-styles.css";
|
||||
import { MinimalPersonaSnapshot } from "@/app/admin/assistants/interfaces";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import { AssistantIcon } from "@/components/assistants/AssistantIcon";
|
||||
import { LikeFeedback, DislikeFeedback } from "@/components/icons/icons";
|
||||
import {
|
||||
@@ -254,8 +254,8 @@ export const AIMessage = ({
|
||||
selectedDocuments?: OnyxDocument[] | null;
|
||||
toggleDocumentSelection?: () => void;
|
||||
docs?: OnyxDocument[] | null;
|
||||
alternativeAssistant?: MinimalPersonaSnapshot | null;
|
||||
currentPersona: MinimalPersonaSnapshot;
|
||||
alternativeAssistant?: Persona | null;
|
||||
currentPersona: Persona;
|
||||
messageId: number | null;
|
||||
content: string | JSX.Element;
|
||||
files?: FileDescriptor[];
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
sortableKeyboardCoordinates,
|
||||
verticalListSortingStrategy,
|
||||
} from "@dnd-kit/sortable";
|
||||
import { MinimalPersonaSnapshot } from "@/app/admin/assistants/interfaces";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import { LLMProviderDescriptor } from "@/app/admin/configuration/llm/interfaces";
|
||||
import { getFinalLLM } from "@/lib/llm/utils";
|
||||
import React, { useEffect, useState } from "react";
|
||||
@@ -27,9 +27,9 @@ export function AssistantsTab({
|
||||
llmProviders,
|
||||
onSelect,
|
||||
}: {
|
||||
selectedAssistant: MinimalPersonaSnapshot;
|
||||
selectedAssistant: Persona;
|
||||
llmProviders: LLMProviderDescriptor[];
|
||||
onSelect: (assistant: MinimalPersonaSnapshot) => void;
|
||||
onSelect: (assistant: Persona) => void;
|
||||
}) {
|
||||
const { refreshUser } = useUser();
|
||||
const [_, llmName] = getFinalLLM(llmProviders, null, null);
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
ArrowUp,
|
||||
ArrowDown,
|
||||
Trash,
|
||||
Upload,
|
||||
} from "lucide-react";
|
||||
import { useDocumentsContext } from "../DocumentsContext";
|
||||
import { useChatContext } from "@/components/context/ChatContext";
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
TooltipTrigger,
|
||||
TooltipContent,
|
||||
} from "@/components/ui/tooltip";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { usePopup } from "@/components/admin/connectors/Popup";
|
||||
import { getFormattedDateTime } from "@/lib/dateUtils";
|
||||
import { FileUploadSection } from "../[id]/components/upload/FileUploadSection";
|
||||
|
||||
@@ -2,6 +2,7 @@ import React from "react";
|
||||
import { cn, truncateString } from "@/lib/utils";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { X, FolderIcon, Loader2 } from "lucide-react";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
import { FolderResponse, FileResponse } from "../DocumentsContext";
|
||||
import { getFileIconFromFileNameAndLink } from "@/lib/assistantIconUtils";
|
||||
import { MinimalOnyxDocument } from "@/lib/search/interfaces";
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
import { PagesTab } from "./PagesTab";
|
||||
import { pageType } from "./types";
|
||||
import LogoWithText from "@/components/header/LogoWithText";
|
||||
import { MinimalPersonaSnapshot } from "@/app/admin/assistants/interfaces";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import { DragEndEvent } from "@dnd-kit/core";
|
||||
import { useAssistants } from "@/components/context/AssistantsContext";
|
||||
import { AssistantIcon } from "@/components/assistants/AssistantIcon";
|
||||
@@ -56,7 +56,7 @@ import { restrictToVerticalAxis } from "@dnd-kit/modifiers";
|
||||
import { TruncatedText } from "@/components/ui/truncatedText";
|
||||
|
||||
interface HistorySidebarProps {
|
||||
liveAssistant?: MinimalPersonaSnapshot | null;
|
||||
liveAssistant?: Persona | null;
|
||||
page: pageType;
|
||||
existingChats?: ChatSession[];
|
||||
currentChatSession?: ChatSession | null | undefined;
|
||||
@@ -73,7 +73,7 @@ interface HistorySidebarProps {
|
||||
}
|
||||
|
||||
interface SortableAssistantProps {
|
||||
assistant: MinimalPersonaSnapshot;
|
||||
assistant: Persona;
|
||||
active: boolean;
|
||||
onClick: () => void;
|
||||
onPinAction: (e: React.MouseEvent) => void;
|
||||
@@ -213,22 +213,18 @@ export const HistorySidebar = forwardRef<HTMLDivElement, HistorySidebarProps>(
|
||||
const { active, over } = event;
|
||||
|
||||
if (active.id !== over?.id) {
|
||||
setPinnedAssistants((prevAssistants: MinimalPersonaSnapshot[]) => {
|
||||
setPinnedAssistants((prevAssistants: Persona[]) => {
|
||||
const oldIndex = prevAssistants.findIndex(
|
||||
(a: MinimalPersonaSnapshot) =>
|
||||
(a.id === 0 ? "assistant-0" : a.id) === active.id
|
||||
(a: Persona) => (a.id === 0 ? "assistant-0" : a.id) === active.id
|
||||
);
|
||||
const newIndex = prevAssistants.findIndex(
|
||||
(a: MinimalPersonaSnapshot) =>
|
||||
(a.id === 0 ? "assistant-0" : a.id) === over?.id
|
||||
(a: Persona) => (a.id === 0 ? "assistant-0" : a.id) === over?.id
|
||||
);
|
||||
|
||||
const newOrder = arrayMove(prevAssistants, oldIndex, newIndex);
|
||||
|
||||
// Ensure we're sending the correct IDs to the API
|
||||
const reorderedIds = newOrder.map(
|
||||
(a: MinimalPersonaSnapshot) => a.id
|
||||
);
|
||||
const reorderedIds = newOrder.map((a: Persona) => a.id);
|
||||
reorderPinnedAssistants(reorderedIds);
|
||||
|
||||
return newOrder;
|
||||
@@ -355,7 +351,7 @@ export const HistorySidebar = forwardRef<HTMLDivElement, HistorySidebarProps>(
|
||||
strategy={verticalListSortingStrategy}
|
||||
>
|
||||
<div className="flex px-0 mr-4 flex-col gap-y-1 mt-1">
|
||||
{pinnedAssistants.map((assistant: MinimalPersonaSnapshot) => (
|
||||
{pinnedAssistants.map((assistant: Persona) => (
|
||||
<SortableAssistant
|
||||
key={assistant.id === 0 ? "assistant-0" : assistant.id}
|
||||
assistant={assistant}
|
||||
|
||||
@@ -15,12 +15,14 @@ import { useContext, useEffect, useState } from "react";
|
||||
import { SettingsContext } from "@/components/settings/SettingsProvider";
|
||||
import { OnyxInitializingLoader } from "@/components/OnyxInitializingLoader";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { MinimalOnyxDocument } from "@/lib/search/interfaces";
|
||||
import TextView from "@/components/chat/TextView";
|
||||
import { DocumentResults } from "../../documentSidebar/DocumentResults";
|
||||
import { Modal } from "@/components/Modal";
|
||||
import FunctionalHeader from "@/components/chat/Header";
|
||||
import FixedLogo from "@/components/logo/FixedLogo";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
|
||||
function BackToOnyxButton({
|
||||
|
||||
@@ -25,6 +25,7 @@ import { deleteStandardAnswer } from "./lib";
|
||||
import { FilterDropdown } from "@/components/search/filtering/FilterDropdown";
|
||||
import { FiTag } from "react-icons/fi";
|
||||
import { PageSelector } from "@/components/PageSelector";
|
||||
import { CustomCheckbox } from "@/components/CustomCheckbox";
|
||||
import Text from "@/components/ui/text";
|
||||
import { TableHeader } from "@/components/ui/table";
|
||||
import CreateButton from "@/components/ui/createButton";
|
||||
|
||||
@@ -35,7 +35,7 @@ import { CheckedState } from "@radix-ui/react-checkbox";
|
||||
|
||||
import { transformLinkUri } from "@/lib/utils";
|
||||
import FileInput from "@/app/admin/connectors/[connector]/pages/ConnectorInput/FileInput";
|
||||
import { DatePicker } from "./ui/datePicker";
|
||||
import { DatePicker, DatePickerProps } from "./ui/datePicker";
|
||||
import { Textarea, TextareaProps } from "./ui/textarea";
|
||||
|
||||
export function SectionHeader({
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState, useEffect } from "react";
|
||||
import "./loading.css";
|
||||
import { ThreeDots } from "react-loader-spinner";
|
||||
|
||||
@@ -40,6 +40,8 @@ import {
|
||||
} from "@/app/admin/settings/interfaces";
|
||||
import Link from "next/link";
|
||||
import { Button } from "../ui/button";
|
||||
import useSWR from "swr";
|
||||
import { errorHandlingFetcher } from "@/lib/fetcher";
|
||||
import { useIsKGExposed } from "@/app/admin/kg/utils";
|
||||
import { useFederatedOAuthStatus } from "@/lib/hooks/useFederatedOAuthStatus";
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MinimalPersonaSnapshot } from "@/app/admin/assistants/interfaces";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import { AssistantIcon } from "@/components/assistants/AssistantIcon";
|
||||
import { useSortable } from "@dnd-kit/sortable";
|
||||
import React from "react";
|
||||
@@ -14,9 +14,9 @@ export const AssistantCard = ({
|
||||
isSelected,
|
||||
onSelect,
|
||||
}: {
|
||||
assistant: MinimalPersonaSnapshot;
|
||||
assistant: Persona;
|
||||
isSelected: boolean;
|
||||
onSelect: (assistant: MinimalPersonaSnapshot) => void;
|
||||
onSelect: (assistant: Persona) => void;
|
||||
}) => {
|
||||
const renderBadgeContent = (tool: { name: string }) => {
|
||||
switch (tool.name) {
|
||||
@@ -73,9 +73,9 @@ export const AssistantCard = ({
|
||||
};
|
||||
|
||||
export function DraggableAssistantCard(props: {
|
||||
assistant: MinimalPersonaSnapshot;
|
||||
assistant: Persona;
|
||||
isSelected: boolean;
|
||||
onSelect: (assistant: MinimalPersonaSnapshot) => void;
|
||||
onSelect: (assistant: Persona) => void;
|
||||
llmName: string;
|
||||
}) {
|
||||
const {
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import React from "react";
|
||||
import crypto from "crypto";
|
||||
import {
|
||||
MinimalPersonaSnapshot,
|
||||
Persona,
|
||||
} from "@/app/admin/assistants/interfaces";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import { buildImgUrl } from "@/app/chat/files/images/utils";
|
||||
import {
|
||||
ArtAsistantIcon,
|
||||
@@ -95,7 +92,7 @@ export function AssistantIcon({
|
||||
className,
|
||||
disableToolip,
|
||||
}: {
|
||||
assistant: MinimalPersonaSnapshot | Persona;
|
||||
assistant: Persona;
|
||||
size?: IconSize;
|
||||
className?: string;
|
||||
border?: boolean;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { useContext } from "react";
|
||||
import { MinimalPersonaSnapshot } from "../../app/admin/assistants/interfaces";
|
||||
import { Persona } from "../../app/admin/assistants/interfaces";
|
||||
import { SettingsContext } from "../settings/SettingsProvider";
|
||||
|
||||
export function StarterMessages({
|
||||
currentPersona,
|
||||
onSubmit,
|
||||
}: {
|
||||
currentPersona: MinimalPersonaSnapshot;
|
||||
currentPersona: Persona;
|
||||
onSubmit: (messageOverride: string) => void;
|
||||
}) {
|
||||
const settings = useContext(SettingsContext);
|
||||
|
||||
@@ -4,7 +4,7 @@ import { UserProvider } from "../user/UserProvider";
|
||||
import { ProviderContextProvider } from "../chat/ProviderContext";
|
||||
import { SettingsProvider } from "../settings/SettingsProvider";
|
||||
import { AssistantsProvider } from "./AssistantsContext";
|
||||
import { MinimalPersonaSnapshot } from "@/app/admin/assistants/interfaces";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import { User } from "@/lib/types";
|
||||
import { ModalProvider } from "./ModalContext";
|
||||
import { AuthTypeMetadata } from "@/lib/userSS";
|
||||
@@ -13,7 +13,7 @@ interface AppProviderProps {
|
||||
children: React.ReactNode;
|
||||
user: User | null;
|
||||
settings: CombinedSettings;
|
||||
assistants: MinimalPersonaSnapshot[];
|
||||
assistants: Persona[];
|
||||
hasAnyConnectors: boolean;
|
||||
hasImageCompatibleModel: boolean;
|
||||
authTypeMetadata: AuthTypeMetadata;
|
||||
|
||||
@@ -8,7 +8,7 @@ import React, {
|
||||
SetStateAction,
|
||||
Dispatch,
|
||||
} from "react";
|
||||
import { MinimalPersonaSnapshot } from "@/app/admin/assistants/interfaces";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import {
|
||||
classifyAssistants,
|
||||
orderAssistantsForUser,
|
||||
@@ -18,18 +18,18 @@ import {
|
||||
import { useUser } from "../user/UserProvider";
|
||||
|
||||
interface AssistantsContextProps {
|
||||
assistants: MinimalPersonaSnapshot[];
|
||||
visibleAssistants: MinimalPersonaSnapshot[];
|
||||
hiddenAssistants: MinimalPersonaSnapshot[];
|
||||
finalAssistants: MinimalPersonaSnapshot[];
|
||||
ownedButHiddenAssistants: MinimalPersonaSnapshot[];
|
||||
assistants: Persona[];
|
||||
visibleAssistants: Persona[];
|
||||
hiddenAssistants: Persona[];
|
||||
finalAssistants: Persona[];
|
||||
ownedButHiddenAssistants: Persona[];
|
||||
refreshAssistants: () => Promise<void>;
|
||||
isImageGenerationAvailable: boolean;
|
||||
// Admin only
|
||||
editablePersonas: MinimalPersonaSnapshot[];
|
||||
allAssistants: MinimalPersonaSnapshot[];
|
||||
pinnedAssistants: MinimalPersonaSnapshot[];
|
||||
setPinnedAssistants: Dispatch<SetStateAction<MinimalPersonaSnapshot[]>>;
|
||||
editablePersonas: Persona[];
|
||||
allAssistants: Persona[];
|
||||
pinnedAssistants: Persona[];
|
||||
setPinnedAssistants: Dispatch<SetStateAction<Persona[]>>;
|
||||
}
|
||||
|
||||
const AssistantsContext = createContext<AssistantsContextProps | undefined>(
|
||||
@@ -38,36 +38,27 @@ const AssistantsContext = createContext<AssistantsContextProps | undefined>(
|
||||
|
||||
export const AssistantsProvider: React.FC<{
|
||||
children: React.ReactNode;
|
||||
initialAssistants: MinimalPersonaSnapshot[];
|
||||
hasAnyConnectors?: boolean;
|
||||
hasImageCompatibleModel?: boolean;
|
||||
initialAssistants: Persona[];
|
||||
hasAnyConnectors: boolean;
|
||||
hasImageCompatibleModel: boolean;
|
||||
}> = ({
|
||||
children,
|
||||
initialAssistants,
|
||||
hasAnyConnectors,
|
||||
hasImageCompatibleModel,
|
||||
}) => {
|
||||
const [assistants, setAssistants] = useState<MinimalPersonaSnapshot[]>(
|
||||
const [assistants, setAssistants] = useState<Persona[]>(
|
||||
initialAssistants || []
|
||||
);
|
||||
const { user, isAdmin, isCurator } = useUser();
|
||||
const [editablePersonas, setEditablePersonas] = useState<
|
||||
MinimalPersonaSnapshot[]
|
||||
>([]);
|
||||
const [allAssistants, setAllAssistants] = useState<MinimalPersonaSnapshot[]>(
|
||||
[]
|
||||
);
|
||||
const [editablePersonas, setEditablePersonas] = useState<Persona[]>([]);
|
||||
const [allAssistants, setAllAssistants] = useState<Persona[]>([]);
|
||||
|
||||
const [pinnedAssistants, setPinnedAssistants] = useState<
|
||||
MinimalPersonaSnapshot[]
|
||||
>(() => {
|
||||
const [pinnedAssistants, setPinnedAssistants] = useState<Persona[]>(() => {
|
||||
if (user?.preferences.pinned_assistants) {
|
||||
return user.preferences.pinned_assistants
|
||||
.map((id) => assistants.find((assistant) => assistant.id === id))
|
||||
.filter(
|
||||
(assistant): assistant is MinimalPersonaSnapshot =>
|
||||
assistant !== undefined
|
||||
);
|
||||
.filter((assistant): assistant is Persona => assistant !== undefined);
|
||||
} else {
|
||||
return assistants.filter((a) => a.is_default_persona);
|
||||
}
|
||||
@@ -78,10 +69,7 @@ export const AssistantsProvider: React.FC<{
|
||||
if (user?.preferences.pinned_assistants) {
|
||||
return user.preferences.pinned_assistants
|
||||
.map((id) => assistants.find((assistant) => assistant.id === id))
|
||||
.filter(
|
||||
(assistant): assistant is MinimalPersonaSnapshot =>
|
||||
assistant !== undefined
|
||||
);
|
||||
.filter((assistant): assistant is Persona => assistant !== undefined);
|
||||
} else {
|
||||
return assistants.filter((a) => a.is_default_persona);
|
||||
}
|
||||
@@ -147,9 +135,13 @@ export const AssistantsProvider: React.FC<{
|
||||
},
|
||||
});
|
||||
if (!response.ok) throw new Error("Failed to fetch assistants");
|
||||
let assistants: MinimalPersonaSnapshot[] = await response.json();
|
||||
let assistants: Persona[] = await response.json();
|
||||
|
||||
let filteredAssistants = filterAssistants(assistants);
|
||||
let filteredAssistants = filterAssistants(
|
||||
assistants,
|
||||
hasAnyConnectors,
|
||||
hasImageCompatibleModel
|
||||
);
|
||||
|
||||
setAssistants(filteredAssistants);
|
||||
|
||||
|
||||
@@ -3,13 +3,17 @@ import { Button } from "@/components/ui/button";
|
||||
import { ValidSources, AccessType } from "@/lib/types";
|
||||
import { FaAccusoft } from "react-icons/fa";
|
||||
import { submitCredential } from "@/components/admin/connectors/CredentialForm";
|
||||
import { TextFormField } from "@/components/Field";
|
||||
import { BooleanFormField, TextFormField } from "@/components/Field";
|
||||
import { Form, Formik, FormikHelpers } from "formik";
|
||||
import { PopupSpec } from "@/components/admin/connectors/Popup";
|
||||
import { getSourceDocLink } from "@/lib/sources";
|
||||
import GDriveMain from "@/app/admin/connectors/[connector]/pages/gdrive/GoogleDrivePage";
|
||||
import { Connector } from "@/lib/connectors/connectors";
|
||||
import { Credential, credentialTemplates } from "@/lib/connectors/credentials";
|
||||
import {
|
||||
Credential,
|
||||
credentialTemplates,
|
||||
getDisplayNameForCredentialKey,
|
||||
} from "@/lib/connectors/credentials";
|
||||
import { PlusCircleIcon } from "../../icons/icons";
|
||||
import { GmailMain } from "@/app/admin/connectors/[connector]/pages/gmail/GmailPage";
|
||||
import { ActionType, dictionaryType } from "../types";
|
||||
|
||||
@@ -1,20 +1,14 @@
|
||||
import {
|
||||
MinimalPersonaSnapshot,
|
||||
Persona,
|
||||
} from "@/app/admin/assistants/interfaces";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import { User } from "../types";
|
||||
import { checkUserIsNoAuthUser } from "../user";
|
||||
|
||||
export function checkUserOwnsAssistant(
|
||||
user: User | null,
|
||||
assistant: MinimalPersonaSnapshot | Persona
|
||||
) {
|
||||
export function checkUserOwnsAssistant(user: User | null, assistant: Persona) {
|
||||
return checkUserIdOwnsAssistant(user?.id, assistant);
|
||||
}
|
||||
|
||||
export function checkUserIdOwnsAssistant(
|
||||
userId: string | undefined,
|
||||
assistant: MinimalPersonaSnapshot | Persona
|
||||
assistant: Persona
|
||||
) {
|
||||
return (
|
||||
(!userId ||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { MinimalPersonaSnapshot } from "@/app/admin/assistants/interfaces";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import { fetchSS } from "../utilsSS";
|
||||
|
||||
export type FetchAssistantsResponse = [MinimalPersonaSnapshot[], string | null];
|
||||
export type FetchAssistantsResponse = [Persona[], string | null];
|
||||
|
||||
export async function fetchAssistantsSS(): Promise<FetchAssistantsResponse> {
|
||||
const response = await fetchSS("/persona");
|
||||
if (response.ok) {
|
||||
return [(await response.json()) as MinimalPersonaSnapshot[], null];
|
||||
return [(await response.json()) as Persona[], null];
|
||||
}
|
||||
return [[], (await response.json()).detail || "Unknown Error"];
|
||||
}
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
import { MinimalPersonaSnapshot } from "@/app/admin/assistants/interfaces";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import { User } from "../types";
|
||||
import { checkUserIsNoAuthUser } from "../user";
|
||||
import { personaComparator } from "@/app/admin/assistants/lib";
|
||||
|
||||
export function checkUserOwnsAssistant(
|
||||
user: User | null,
|
||||
assistant: MinimalPersonaSnapshot
|
||||
) {
|
||||
export function checkUserOwnsAssistant(user: User | null, assistant: Persona) {
|
||||
return checkUserIdOwnsAssistant(user?.id, assistant);
|
||||
}
|
||||
|
||||
export function checkUserIdOwnsAssistant(
|
||||
userId: string | undefined,
|
||||
assistant: MinimalPersonaSnapshot
|
||||
assistant: Persona
|
||||
) {
|
||||
return (
|
||||
(!userId ||
|
||||
@@ -22,10 +19,7 @@ export function checkUserIdOwnsAssistant(
|
||||
);
|
||||
}
|
||||
|
||||
export function classifyAssistants(
|
||||
user: User | null,
|
||||
assistants: MinimalPersonaSnapshot[]
|
||||
) {
|
||||
export function classifyAssistants(user: User | null, assistants: Persona[]) {
|
||||
if (!user) {
|
||||
return {
|
||||
visibleAssistants: assistants.filter(
|
||||
@@ -65,7 +59,7 @@ export function classifyAssistants(
|
||||
}
|
||||
|
||||
export function orderAssistantsForUser(
|
||||
assistants: MinimalPersonaSnapshot[],
|
||||
assistants: Persona[],
|
||||
user: User | null
|
||||
) {
|
||||
let orderedAssistants = [...assistants];
|
||||
@@ -118,7 +112,7 @@ export function orderAssistantsForUser(
|
||||
|
||||
export function getUserCreatedAssistants(
|
||||
user: User | null,
|
||||
assistants: MinimalPersonaSnapshot[]
|
||||
assistants: Persona[]
|
||||
) {
|
||||
return assistants.filter((assistant) =>
|
||||
checkUserOwnsAssistant(user, assistant)
|
||||
@@ -127,10 +121,29 @@ export function getUserCreatedAssistants(
|
||||
|
||||
// Filter assistants based on connector status, image compatibility and visibility
|
||||
export function filterAssistants(
|
||||
assistants: MinimalPersonaSnapshot[]
|
||||
): MinimalPersonaSnapshot[] {
|
||||
assistants: Persona[],
|
||||
hasAnyConnectors: boolean,
|
||||
hasImageCompatibleModel: boolean
|
||||
): Persona[] {
|
||||
let filteredAssistants = assistants.filter(
|
||||
(assistant) => assistant.is_visible
|
||||
);
|
||||
|
||||
if (!hasAnyConnectors) {
|
||||
filteredAssistants = filteredAssistants.filter(
|
||||
(assistant) =>
|
||||
assistant.num_chunks === 0 || assistant.document_sets.length > 0
|
||||
);
|
||||
}
|
||||
|
||||
if (!hasImageCompatibleModel) {
|
||||
filteredAssistants = filteredAssistants.filter(
|
||||
(assistant) =>
|
||||
!assistant.tools.some(
|
||||
(tool) => tool.in_code_tool_id === "ImageGenerationTool"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return filteredAssistants.sort(personaComparator);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { fetchSS } from "@/lib/utilsSS";
|
||||
import { MinimalPersonaSnapshot } from "@/app/admin/assistants/interfaces";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import { fetchLLMProvidersSS } from "@/lib/llm/fetchLLMs";
|
||||
import { fetchAssistantsSS } from "../assistants/fetchAssistantsSS";
|
||||
import { modelSupportsImageInput } from "../llm/utils";
|
||||
import { filterAssistants } from "../assistants/utils";
|
||||
|
||||
interface AssistantData {
|
||||
assistants: MinimalPersonaSnapshot[];
|
||||
assistants: Persona[];
|
||||
hasAnyConnectors: boolean;
|
||||
hasImageCompatibleModel: boolean;
|
||||
}
|
||||
@@ -51,7 +51,11 @@ export async function fetchAssistantData(): Promise<AssistantData> {
|
||||
)
|
||||
);
|
||||
|
||||
let filteredAssistants = filterAssistants(assistants);
|
||||
let filteredAssistants = filterAssistants(
|
||||
assistants,
|
||||
hasAnyConnectors,
|
||||
hasImageCompatibleModel
|
||||
);
|
||||
|
||||
return {
|
||||
assistants: filteredAssistants,
|
||||
|
||||
@@ -18,10 +18,7 @@ import { ChatSession } from "@/app/chat/interfaces";
|
||||
import { AllUsersResponse } from "./types";
|
||||
import { Credential } from "./connectors/credentials";
|
||||
import { SettingsContext } from "@/components/settings/SettingsProvider";
|
||||
import {
|
||||
MinimalPersonaSnapshot,
|
||||
PersonaLabel,
|
||||
} from "@/app/admin/assistants/interfaces";
|
||||
import { Persona, PersonaLabel } from "@/app/admin/assistants/interfaces";
|
||||
import { LLMProviderDescriptor } from "@/app/admin/configuration/llm/interfaces";
|
||||
import { isAnthropic } from "@/app/admin/configuration/llm/utils";
|
||||
import { getSourceMetadata } from "./sources";
|
||||
@@ -383,7 +380,7 @@ export interface LlmManager {
|
||||
updateModelOverrideBasedOnChatSession: (chatSession?: ChatSession) => void;
|
||||
imageFilesPresent: boolean;
|
||||
updateImageFilesPresent: (present: boolean) => void;
|
||||
liveAssistant: MinimalPersonaSnapshot | null;
|
||||
liveAssistant: Persona | null;
|
||||
maxTemperature: number;
|
||||
}
|
||||
|
||||
@@ -431,7 +428,7 @@ providing appropriate defaults for new conversations based on the available tool
|
||||
export function useLlmManager(
|
||||
llmProviders: LLMProviderDescriptor[],
|
||||
currentChatSession?: ChatSession,
|
||||
liveAssistant?: MinimalPersonaSnapshot
|
||||
liveAssistant?: Persona
|
||||
): LlmManager {
|
||||
const { user } = useUser();
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MinimalPersonaSnapshot } from "@/app/admin/assistants/interfaces";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import {
|
||||
LLMProviderDescriptor,
|
||||
ModelConfiguration,
|
||||
@@ -7,7 +7,7 @@ import { LlmDescriptor } from "@/lib/hooks";
|
||||
|
||||
export function getFinalLLM(
|
||||
llmProviders: LLMProviderDescriptor[],
|
||||
persona: MinimalPersonaSnapshot | null,
|
||||
persona: Persona | null,
|
||||
currentLlm: LlmDescriptor | null
|
||||
): [string, string] {
|
||||
const defaultProvider = llmProviders.find(
|
||||
@@ -38,7 +38,7 @@ export function getFinalLLM(
|
||||
}
|
||||
|
||||
export function getLLMProviderOverrideForPersona(
|
||||
liveAssistant: MinimalPersonaSnapshot,
|
||||
liveAssistant: Persona,
|
||||
llmProviders: LLMProviderDescriptor[]
|
||||
): LlmDescriptor | null {
|
||||
const overrideProvider = liveAssistant.llm_model_provider_override;
|
||||
|
||||
Reference in New Issue
Block a user