mirror of
https://github.com/onyx-dot-app/onyx.git
synced 2026-02-16 23:35:46 +00:00
Compare commits
10 Commits
debug-shar
...
temp/gray-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
135e63b231 | ||
|
|
eac2566c13 | ||
|
|
4929feed18 | ||
|
|
3bec4b07ee | ||
|
|
e8994369fb | ||
|
|
e6b4f93137 | ||
|
|
79cb2ffd02 | ||
|
|
4b6723c32b | ||
|
|
391f0a010c | ||
|
|
5cbe47e13a |
@@ -226,21 +226,30 @@ def fetch_available_well_known_llms() -> list[WellKnownLLMProviderDescriptor]:
|
||||
name="AWS_ACCESS_KEY_ID",
|
||||
display_name="AWS Access Key ID",
|
||||
is_required=False,
|
||||
description="If using AWS IAM roles, AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY can be left blank.",
|
||||
description="If using IAM role or a long-term API key, leave this field blank.",
|
||||
),
|
||||
CustomConfigKey(
|
||||
name="AWS_SECRET_ACCESS_KEY",
|
||||
display_name="AWS Secret Access Key",
|
||||
is_required=False,
|
||||
is_secret=True,
|
||||
description="If using AWS IAM roles, AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY can be left blank.",
|
||||
description="If using IAM role or a long-term API key, leave this field blank.",
|
||||
),
|
||||
CustomConfigKey(
|
||||
name="AWS_BEARER_TOKEN_BEDROCK",
|
||||
display_name="AWS Bedrock Long-term API Key",
|
||||
is_required=False,
|
||||
is_secret=True,
|
||||
description=(
|
||||
"If using IAM role or access key, leave this field blank."
|
||||
),
|
||||
),
|
||||
],
|
||||
model_configurations=fetch_model_configurations_for_provider(
|
||||
BEDROCK_PROVIDER_NAME
|
||||
),
|
||||
default_model=BEDROCK_DEFAULT_MODEL,
|
||||
default_fast_model=BEDROCK_DEFAULT_MODEL,
|
||||
default_fast_model=None,
|
||||
),
|
||||
WellKnownLLMProviderDescriptor(
|
||||
name=VERTEXAI_PROVIDER_NAME,
|
||||
@@ -304,6 +313,7 @@ def fetch_model_configurations_for_provider(
|
||||
visible_model_names = (
|
||||
fetch_visible_model_names_for_provider_as_set(provider_name) or set()
|
||||
)
|
||||
|
||||
return [
|
||||
ModelConfigurationView(
|
||||
name=model_name,
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import os
|
||||
from collections.abc import Callable
|
||||
from datetime import datetime
|
||||
from datetime import timezone
|
||||
|
||||
import boto3
|
||||
from botocore.exceptions import BotoCoreError
|
||||
from botocore.exceptions import ClientError
|
||||
from botocore.exceptions import NoCredentialsError
|
||||
from fastapi import APIRouter
|
||||
from fastapi import Depends
|
||||
from fastapi import HTTPException
|
||||
@@ -22,12 +27,14 @@ from onyx.db.models import User
|
||||
from onyx.llm.factory import get_default_llms
|
||||
from onyx.llm.factory import get_llm
|
||||
from onyx.llm.factory import get_max_input_tokens_from_llm_provider
|
||||
from onyx.llm.llm_provider_options import BEDROCK_MODEL_NAMES
|
||||
from onyx.llm.llm_provider_options import fetch_available_well_known_llms
|
||||
from onyx.llm.llm_provider_options import WellKnownLLMProviderDescriptor
|
||||
from onyx.llm.utils import get_llm_contextual_cost
|
||||
from onyx.llm.utils import litellm_exception_to_error_msg
|
||||
from onyx.llm.utils import model_supports_image_input
|
||||
from onyx.llm.utils import test_llm
|
||||
from onyx.server.manage.llm.models import BedrockModelsRequest
|
||||
from onyx.server.manage.llm.models import LLMCost
|
||||
from onyx.server.manage.llm.models import LLMProviderDescriptor
|
||||
from onyx.server.manage.llm.models import LLMProviderUpsertRequest
|
||||
@@ -386,3 +393,77 @@ def get_provider_contextual_cost(
|
||||
)
|
||||
|
||||
return costs
|
||||
|
||||
|
||||
@admin_router.post("/bedrock/available-models")
|
||||
def get_bedrock_available_models(
|
||||
request: BedrockModelsRequest,
|
||||
_: User | None = Depends(current_admin_user),
|
||||
) -> list[str]:
|
||||
"""Fetch available Bedrock models for a specific region and credentials"""
|
||||
try:
|
||||
# Build a session with the simplest precedence: bearer, keys, IAM
|
||||
if request.aws_bearer_token_bedrock:
|
||||
os.environ["AWS_BEARER_TOKEN_BEDROCK"] = request.aws_bearer_token_bedrock
|
||||
elif request.aws_access_key_id and request.aws_secret_access_key:
|
||||
os.environ["AWS_ACCESS_KEY_ID"] = request.aws_access_key_id
|
||||
os.environ["AWS_SECRET_ACCESS_KEY"] = request.aws_secret_access_key
|
||||
|
||||
session = boto3.Session(region_name=request.aws_region_name)
|
||||
|
||||
try:
|
||||
bedrock = session.client("bedrock")
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"Failed to create Bedrock client: {e}. Check AWS credentials and region.",
|
||||
)
|
||||
|
||||
# Available Bedrock models: text-only, streaming supported
|
||||
model_summaries = bedrock.list_foundation_models().get("modelSummaries", [])
|
||||
available_models = {
|
||||
model.get("modelId", "")
|
||||
for model in model_summaries
|
||||
if model.get("modelId")
|
||||
and "embed" not in model.get("modelId", "").lower()
|
||||
and model.get("responseStreamingSupported", False)
|
||||
}
|
||||
|
||||
# Available inference profiles. Invoking these allows cross-region inference (preferred over base models).
|
||||
profile_ids: set[str] = set()
|
||||
cross_region_models: set[str] = set()
|
||||
try:
|
||||
inference_profiles = bedrock.list_inference_profiles(
|
||||
typeEquals="SYSTEM_DEFINED"
|
||||
).get("inferenceProfileSummaries", [])
|
||||
for profile in inference_profiles:
|
||||
if profile_id := profile.get("inferenceProfileId"):
|
||||
profile_ids.add(profile_id)
|
||||
|
||||
# The model id is everything after the first period in the profile id
|
||||
if "." in profile_id:
|
||||
model_id = profile_id.split(".", 1)[1]
|
||||
cross_region_models.add(model_id)
|
||||
except Exception as e:
|
||||
# Cross-region inference isn't guaranteed; ignore failures here.
|
||||
logger.warning(f"Couldn't fetch inference profiles for Bedrock: {e}")
|
||||
|
||||
# Prefer profiles: de-dupe available models, then add profile IDs
|
||||
candidates = (available_models - cross_region_models) | profile_ids
|
||||
|
||||
# Keep only models we support (compatibility with litellm)
|
||||
filtered = sorted(
|
||||
[model for model in candidates if model in BEDROCK_MODEL_NAMES],
|
||||
reverse=True,
|
||||
)
|
||||
|
||||
return filtered
|
||||
|
||||
except (ClientError, NoCredentialsError, BotoCoreError) as e:
|
||||
raise HTTPException(
|
||||
status_code=400, detail=f"Failed to connect to AWS Bedrock: {e}"
|
||||
)
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Unexpected error fetching Bedrock models: {e}"
|
||||
)
|
||||
|
||||
@@ -188,3 +188,11 @@ class LLMCost(BaseModel):
|
||||
provider: str
|
||||
model_name: str
|
||||
cost: float
|
||||
|
||||
|
||||
class BedrockModelsRequest(BaseModel):
|
||||
aws_region_name: str
|
||||
aws_access_key_id: str | None = None
|
||||
aws_secret_access_key: str | None = None
|
||||
aws_bearer_token_bedrock: str | None = None
|
||||
provider_name: str | None = None # Optional: to save models to existing provider
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
aioboto3==14.0.0
|
||||
aioboto3==15.1.0
|
||||
aiohttp==3.11.16
|
||||
alembic==1.10.4
|
||||
asyncpg==0.30.0
|
||||
atlassian-python-api==3.41.16
|
||||
beautifulsoup4==4.12.3
|
||||
boto3==1.36.23
|
||||
boto3==1.39.11
|
||||
celery==5.5.1
|
||||
chardet==5.2.0
|
||||
chonkie==1.0.10
|
||||
@@ -93,7 +93,7 @@ zulip==0.8.2
|
||||
hubspot-api-client==8.1.0
|
||||
asana==5.0.8
|
||||
dropbox==11.36.2
|
||||
boto3-stubs[s3]==1.34.133
|
||||
boto3-stubs[s3]==1.39.11
|
||||
shapely==2.0.6
|
||||
stripe==10.12.0
|
||||
urllib3==2.2.3
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
black==25.1.0
|
||||
boto3-stubs[s3]==1.34.133
|
||||
boto3-stubs[s3]==1.39.11
|
||||
celery-types==0.19.0
|
||||
cohere==5.6.1
|
||||
faker==37.1.0
|
||||
|
||||
@@ -17,5 +17,5 @@ uvicorn==0.35.0
|
||||
voyageai==0.2.3
|
||||
litellm==1.76.2
|
||||
sentry-sdk[fastapi,celery,starlette]==2.14.0
|
||||
aioboto3==14.0.0
|
||||
aioboto3==15.1.0
|
||||
prometheus_fastapi_instrumentator==7.1.0
|
||||
|
||||
@@ -779,18 +779,16 @@ export function AssistantEditor({
|
||||
Edit assistant <b>{existingPersona.name}</b>
|
||||
</>
|
||||
) : (
|
||||
"Create an Assistant"
|
||||
"Create an Agent"
|
||||
)}
|
||||
</p>
|
||||
<div className="max-w-4xl w-full">
|
||||
<Separator />
|
||||
<div className="flex gap-x-2 items-center">
|
||||
<div className="block font-medium text-sm">
|
||||
Assistant Icon
|
||||
</div>
|
||||
<div className="block font-medium text-sm">Agent Icon</div>
|
||||
</div>
|
||||
<SubLabel>
|
||||
The icon that will visually represent your Assistant
|
||||
The icon that will visually represent your Agent
|
||||
</SubLabel>
|
||||
<div className="flex gap-x-2 items-center">
|
||||
<div
|
||||
@@ -804,14 +802,14 @@ export function AssistantEditor({
|
||||
{values.uploaded_image ? (
|
||||
<img
|
||||
src={URL.createObjectURL(values.uploaded_image)}
|
||||
alt="Uploaded assistant icon"
|
||||
alt="Uploaded agent icon"
|
||||
className="w-12 h-12 rounded-full object-cover"
|
||||
/>
|
||||
) : existingPersona?.uploaded_image_id &&
|
||||
!removePersonaImage ? (
|
||||
<img
|
||||
src={buildImgUrl(existingPersona?.uploaded_image_id)}
|
||||
alt="Uploaded assistant icon"
|
||||
alt="Uploaded agent icon"
|
||||
className="w-12 h-12 rounded-full object-cover"
|
||||
/>
|
||||
) : (
|
||||
@@ -935,7 +933,7 @@ export function AssistantEditor({
|
||||
maxWidth="max-w-lg"
|
||||
name="name"
|
||||
label="Name"
|
||||
placeholder="Email Assistant"
|
||||
placeholder="Email Agent"
|
||||
aria-label="assistant-name-input"
|
||||
className="[&_input]:placeholder:text-text-muted/50"
|
||||
/>
|
||||
@@ -944,7 +942,7 @@ export function AssistantEditor({
|
||||
maxWidth="max-w-lg"
|
||||
name="description"
|
||||
label="Description"
|
||||
placeholder="Use this Assistant to help draft professional emails"
|
||||
placeholder="Use this Agent to help draft professional emails"
|
||||
className="[&_input]:placeholder:text-text-muted/50"
|
||||
/>
|
||||
|
||||
@@ -1125,9 +1123,9 @@ export function AssistantEditor({
|
||||
) : (
|
||||
"Team Document Sets"
|
||||
)}{" "}
|
||||
this Assistant should use to inform its
|
||||
this Agent should use to inform its
|
||||
responses. If none are specified, the
|
||||
Assistant will reference all available
|
||||
Agent will reference all available
|
||||
documents.
|
||||
</>
|
||||
</SubLabel>
|
||||
@@ -1198,7 +1196,7 @@ export function AssistantEditor({
|
||||
}
|
||||
disabledTooltip={
|
||||
!currentLLMSupportsImageOutput
|
||||
? "To use Image Generation, select GPT-4 or another image compatible model as the default model for this Assistant."
|
||||
? "To use Image Generation, select GPT-4 or another image compatible model as the default model for this Agent."
|
||||
: "Image Generation requires an OpenAI or Azure Dall-E configuration."
|
||||
}
|
||||
/>
|
||||
@@ -1381,8 +1379,8 @@ export function AssistantEditor({
|
||||
}
|
||||
}}
|
||||
name="is_default_persona"
|
||||
label="Featured Assistant"
|
||||
subtext="If set, this assistant will be pinned for all new users and appear in the Featured list in the assistant explorer. This also makes the assistant public."
|
||||
label="Featured Agent"
|
||||
subtext="If set, this agent will be pinned for all new users and appear in the Featured list in the agent explorer. This also makes the agent public."
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -1392,7 +1390,7 @@ export function AssistantEditor({
|
||||
<div className="block font-medium text-sm">Access</div>
|
||||
</div>
|
||||
<SubLabel>
|
||||
Control who can access and use this assistant
|
||||
Control who can access and use this agent
|
||||
</SubLabel>
|
||||
|
||||
<div className="min-h-[100px]">
|
||||
@@ -1609,7 +1607,7 @@ export function AssistantEditor({
|
||||
className="text-sm text-subtle"
|
||||
style={{ color: "rgb(113, 114, 121)" }}
|
||||
>
|
||||
Select labels to categorize this assistant
|
||||
Select labels to categorize this agent
|
||||
</p>
|
||||
<div className="mt-3">
|
||||
<SearchMultiSelectDropdown
|
||||
@@ -1754,7 +1752,7 @@ export function AssistantEditor({
|
||||
removeIndent
|
||||
name="datetime_aware"
|
||||
label="Date and Time Aware"
|
||||
subtext='Toggle this option to let the assistant know the current date and time (formatted like: "Thursday Jan 1, 1970 00:01"). To inject it in a specific place in the prompt, use the pattern [[CURRENT_DATETIME]]'
|
||||
subtext='Toggle this option to let the agent know the current date and time (formatted like: "Thursday Jan 1, 1970 00:01"). To inject it in a specific place in the prompt, use the pattern [[CURRENT_DATETIME]]'
|
||||
/>
|
||||
|
||||
<Separator />
|
||||
|
||||
@@ -204,7 +204,7 @@ export function PersonasTable({
|
||||
"Name",
|
||||
"Description",
|
||||
"Type",
|
||||
"Featured Assistant",
|
||||
"Featured Agent",
|
||||
"Is Visible",
|
||||
"Delete",
|
||||
]}
|
||||
|
||||
@@ -23,8 +23,8 @@ function MainContent({
|
||||
return (
|
||||
<div>
|
||||
<Text className="mb-2">
|
||||
Assistants are a way to build custom search/question-answering
|
||||
experiences for different use cases.
|
||||
Agents are a way to build custom search/question-answering experiences
|
||||
for different use cases.
|
||||
</Text>
|
||||
<Text className="mt-2">They allow you to customize:</Text>
|
||||
<div className="text-sm">
|
||||
@@ -39,17 +39,16 @@ function MainContent({
|
||||
<div>
|
||||
<Separator />
|
||||
|
||||
<Title>Create an Assistant</Title>
|
||||
<CreateButton href="/assistants/new?admin=true" text="New Assistant" />
|
||||
<Title>Create an Agent</Title>
|
||||
<CreateButton href="/assistants/new?admin=true" text="New Agent" />
|
||||
|
||||
<Separator />
|
||||
|
||||
<Title>Existing Assistants</Title>
|
||||
<Title>Existing Agents</Title>
|
||||
<SubLabel>
|
||||
Assistants will be displayed as options on the Chat / Search
|
||||
interfaces in the order they are displayed below. Assistants marked as
|
||||
hidden will not be displayed. Editable assistants are shown at the
|
||||
top.
|
||||
Agents will be displayed as options on the Chat / Search interfaces in
|
||||
the order they are displayed below. Agents marked as hidden will not
|
||||
be displayed. Editable agents are shown at the top.
|
||||
</SubLabel>
|
||||
<PersonasTable personas={personas} refreshPersonas={refreshPersonas} />
|
||||
</div>
|
||||
@@ -62,13 +61,13 @@ export default function Page() {
|
||||
|
||||
return (
|
||||
<div className="mx-auto container">
|
||||
<AdminPageTitle icon={<AssistantsIcon size={32} />} title="Assistants" />
|
||||
<AdminPageTitle icon={<AssistantsIcon size={32} />} title="Agents" />
|
||||
|
||||
{isLoading && <ThreeDotsLoader />}
|
||||
|
||||
{error && (
|
||||
<ErrorCallout
|
||||
errorTitle="Failed to load assistants"
|
||||
errorTitle="Failed to load agents"
|
||||
errorMsg={
|
||||
error?.info?.message ||
|
||||
error?.info?.detail ||
|
||||
|
||||
@@ -66,7 +66,7 @@ export function SlackChannelConfigsTable({
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Channel</TableHead>
|
||||
<TableHead>Assistant</TableHead>
|
||||
<TableHead>Agent</TableHead>
|
||||
<TableHead>Document Sets</TableHead>
|
||||
<TableHead>Actions</TableHead>
|
||||
</TableRow>
|
||||
|
||||
@@ -159,7 +159,7 @@ export const SlackChannelConfigCreationForm = ({
|
||||
is: "assistant",
|
||||
then: (schema) =>
|
||||
schema.required(
|
||||
"A persona is required when using the'Assistant' knowledge source"
|
||||
"A persona is required when using the'Agent' knowledge source"
|
||||
),
|
||||
}),
|
||||
standard_answer_categories: Yup.array(),
|
||||
|
||||
@@ -230,14 +230,14 @@ export function SlackChannelConfigFormFields({
|
||||
<RadioGroupItemField
|
||||
value="assistant"
|
||||
id="assistant"
|
||||
label="Search Assistant"
|
||||
label="Search Agent"
|
||||
sublabel="Control both the documents and the prompt to use for answering questions"
|
||||
/>
|
||||
<RadioGroupItemField
|
||||
value="non_search_assistant"
|
||||
id="non_search_assistant"
|
||||
label="Non-Search Assistant"
|
||||
sublabel="Chat with an assistant that does not use documents"
|
||||
label="Non-Search Agent"
|
||||
sublabel="Chat with an agent that does not use documents"
|
||||
/>
|
||||
</RadioGroup>
|
||||
</div>
|
||||
|
||||
@@ -48,6 +48,8 @@ export function LLMProviderUpdateForm({
|
||||
|
||||
const [isTesting, setIsTesting] = useState(false);
|
||||
const [testError, setTestError] = useState<string>("");
|
||||
const [isFetchingModels, setIsFetchingModels] = useState(false);
|
||||
const [fetchModelsError, setFetchModelsError] = useState<string>("");
|
||||
|
||||
const [showAdvancedOptions, setShowAdvancedOptions] = useState(false);
|
||||
|
||||
@@ -90,6 +92,9 @@ export function LLMProviderUpdateForm({
|
||||
(llmProviderDescriptor.model_configurations
|
||||
.filter((modelConfiguration) => modelConfiguration.is_visible)
|
||||
.map((modelConfiguration) => modelConfiguration.name) as string[]),
|
||||
|
||||
// Helper field to force re-renders when model list updates
|
||||
_modelListUpdated: 0,
|
||||
};
|
||||
|
||||
// Setup validation schema if required
|
||||
@@ -142,6 +147,99 @@ export function LLMProviderUpdateForm({
|
||||
);
|
||||
};
|
||||
|
||||
const fetchBedrockModels = async (values: any, setFieldValue: any) => {
|
||||
if (llmProviderDescriptor.name !== "bedrock") {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsFetchingModels(true);
|
||||
setFetchModelsError("");
|
||||
|
||||
try {
|
||||
const response = await fetch("/api/admin/llm/bedrock/available-models", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
aws_region_name: values.custom_config?.AWS_REGION_NAME,
|
||||
aws_access_key_id: values.custom_config?.AWS_ACCESS_KEY_ID,
|
||||
aws_secret_access_key: values.custom_config?.AWS_SECRET_ACCESS_KEY,
|
||||
aws_bearer_token_bedrock:
|
||||
values.custom_config?.AWS_BEARER_TOKEN_BEDROCK,
|
||||
provider_name: existingLlmProvider?.name, // Save models to existing provider if editing
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json();
|
||||
throw new Error(errorData.detail || "Failed to fetch models");
|
||||
}
|
||||
|
||||
const availableModels: string[] = await response.json();
|
||||
|
||||
// Update the model configurations with the fetched models
|
||||
const updatedModelConfigs = availableModels.map((modelName) => {
|
||||
// Find existing configuration to preserve is_visible setting
|
||||
const existingConfig = llmProviderDescriptor.model_configurations.find(
|
||||
(config) => config.name === modelName
|
||||
);
|
||||
|
||||
return {
|
||||
name: modelName,
|
||||
is_visible: existingConfig?.is_visible ?? false, // Preserve existing visibility or default to false
|
||||
max_input_tokens: null,
|
||||
supports_image_input: false, // Will be determined by the backend
|
||||
};
|
||||
});
|
||||
|
||||
// Update the descriptor and form values
|
||||
llmProviderDescriptor.model_configurations = updatedModelConfigs;
|
||||
|
||||
// Update selected model names to only include previously visible models that are available
|
||||
const previouslySelectedModels = values.selected_model_names || [];
|
||||
const stillAvailableSelectedModels = previouslySelectedModels.filter(
|
||||
(modelName: string) => availableModels.includes(modelName)
|
||||
);
|
||||
setFieldValue("selected_model_names", stillAvailableSelectedModels);
|
||||
|
||||
// Set a default model if none is set
|
||||
if (
|
||||
(!values.default_model_name ||
|
||||
!availableModels.includes(values.default_model_name)) &&
|
||||
availableModels.length > 0
|
||||
) {
|
||||
setFieldValue("default_model_name", availableModels[0]);
|
||||
}
|
||||
|
||||
// Clear fast model if it's not in the new list
|
||||
if (
|
||||
values.fast_default_model_name &&
|
||||
!availableModels.includes(values.fast_default_model_name)
|
||||
) {
|
||||
setFieldValue("fast_default_model_name", null);
|
||||
}
|
||||
|
||||
// Force a re-render by updating a timestamp or counter
|
||||
setFieldValue("_modelListUpdated", Date.now());
|
||||
|
||||
setPopup?.({
|
||||
message: `Successfully fetched ${availableModels.length} models for the selected region (including cross-region inference models).`,
|
||||
type: "success",
|
||||
});
|
||||
} catch (error) {
|
||||
const errorMessage =
|
||||
error instanceof Error ? error.message : "Unknown error";
|
||||
setFetchModelsError(errorMessage);
|
||||
setPopup?.({
|
||||
message: `Failed to fetch models: ${errorMessage}`,
|
||||
type: "error",
|
||||
});
|
||||
} finally {
|
||||
setIsFetchingModels(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
@@ -153,6 +251,7 @@ export function LLMProviderUpdateForm({
|
||||
const {
|
||||
selected_model_names: visibleModels,
|
||||
model_configurations: modelConfigurations,
|
||||
_modelListUpdated,
|
||||
...rest
|
||||
} = values;
|
||||
|
||||
@@ -323,6 +422,7 @@ export function LLMProviderUpdateForm({
|
||||
</ReactMarkdown>
|
||||
}
|
||||
placeholder={customConfigKey.default_value || undefined}
|
||||
type={customConfigKey.is_secret ? "password" : "text"}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@@ -340,6 +440,47 @@ export function LLMProviderUpdateForm({
|
||||
}
|
||||
})}
|
||||
|
||||
{/* Bedrock-specific fetch models button */}
|
||||
{llmProviderDescriptor.name === "bedrock" && (
|
||||
<div className="flex flex-col gap-2">
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() =>
|
||||
fetchBedrockModels(
|
||||
formikProps.values,
|
||||
formikProps.setFieldValue
|
||||
)
|
||||
}
|
||||
disabled={
|
||||
isFetchingModels ||
|
||||
!formikProps.values.custom_config?.AWS_REGION_NAME
|
||||
}
|
||||
className="w-fit"
|
||||
>
|
||||
{isFetchingModels ? (
|
||||
<>
|
||||
<LoadingAnimation size="text-sm" />
|
||||
<span className="ml-2">Fetching Models...</span>
|
||||
</>
|
||||
) : (
|
||||
"Fetch Available Models for Region"
|
||||
)}
|
||||
</Button>
|
||||
|
||||
{fetchModelsError && (
|
||||
<Text className="text-red-600 text-sm">{fetchModelsError}</Text>
|
||||
)}
|
||||
|
||||
<Text className="text-sm text-gray-600">
|
||||
Enter your AWS region, then click this button to fetch available
|
||||
Bedrock models.
|
||||
<br />
|
||||
If you're updating your existing provider, you'll need
|
||||
to click this button to fetch the latest models.
|
||||
</Text>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!firstTimeConfiguration && (
|
||||
<>
|
||||
<Separator />
|
||||
|
||||
@@ -6,8 +6,17 @@ export default async function Page(props: {
|
||||
}) {
|
||||
const params = await props.params;
|
||||
return (
|
||||
<ConnectorWrapper
|
||||
connector={params.connector.replace("-", "_") as ConfigurableSources}
|
||||
/>
|
||||
<div
|
||||
className="min-h-screen w-screen bg-background"
|
||||
style={{
|
||||
["--background-input-background" as any]: "#FAFAFA",
|
||||
["--background" as any]: "#FAFAFA",
|
||||
["--background-chatbar-sidebar" as any]: "#F0F0F1",
|
||||
}}
|
||||
>
|
||||
<ConnectorWrapper
|
||||
connector={params.connector.replace("-", "_") as ConfigurableSources}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,14 @@ import EmbeddingForm from "./pages/EmbeddingFormPage";
|
||||
export default function EmbeddingWrapper() {
|
||||
return (
|
||||
<EmbeddingFormProvider>
|
||||
<div className="flex justify-center w-full h-full">
|
||||
<div
|
||||
className="flex justify-center w-full h-full bg-background"
|
||||
style={{
|
||||
["--background-input-background" as any]: "#FAFAFA",
|
||||
["--background" as any]: "#FAFAFA",
|
||||
["--background-chatbar-sidebar" as any]: "#F0F0F1",
|
||||
}}
|
||||
>
|
||||
<EmbeddingSidebar />
|
||||
<div className="mt-12 w-full max-w-5xl mx-auto">
|
||||
<EmbeddingForm />
|
||||
|
||||
@@ -327,7 +327,7 @@ const AssistantCard: React.FC<{
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
Start a new chat with this assistant
|
||||
Start a new chat with this agent
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
|
||||
@@ -143,7 +143,7 @@ export function AssistantModal({ hideModal }: AssistantModalProps) {
|
||||
transform: "translateX(-50%)",
|
||||
margin: 0,
|
||||
}}
|
||||
aria-label="Assistant Modal"
|
||||
aria-label="Agent Modal"
|
||||
>
|
||||
<div className="absolute top-2 right-2">
|
||||
<button
|
||||
@@ -232,7 +232,7 @@ export function AssistantModal({ hideModal }: AssistantModalProps) {
|
||||
|
||||
<div className="flex-grow overflow-y-auto">
|
||||
<h2 className="text-2xl font-semibold text-text-800 mb-2 px-4 py-2">
|
||||
Featured Assistants
|
||||
Featured Agents
|
||||
</h2>
|
||||
|
||||
<div className="w-full px-2 pb-10 grid grid-cols-1 md:grid-cols-2 gap-x-6 gap-y-6">
|
||||
@@ -258,7 +258,7 @@ export function AssistantModal({ hideModal }: AssistantModalProps) {
|
||||
{allAssistants && allAssistants.length > 0 && (
|
||||
<>
|
||||
<h2 className="text-2xl font-semibold text-text-800 mt-4 mb-2 px-4 py-2">
|
||||
All Assistants
|
||||
All Agents
|
||||
</h2>
|
||||
|
||||
<div className="w-full mt-2 px-2 pb-2 grid grid-cols-1 md:grid-cols-2 gap-x-6 gap-y-6">
|
||||
|
||||
@@ -139,7 +139,7 @@ export function AssistantSharingModal({
|
||||
>
|
||||
<div>
|
||||
<p className="text-text-600 text-lg mb-6">
|
||||
Manage access to this assistant by sharing it with other users.
|
||||
Manage access to this agent by sharing it with other users.
|
||||
</p>
|
||||
|
||||
<div className="mb-8 flex flex-col gap-y-4">
|
||||
@@ -148,7 +148,7 @@ export function AssistantSharingModal({
|
||||
</div>
|
||||
|
||||
<div className="mb-8 flex flex-col gap-y-4">
|
||||
<h3 className="text-lg font-semibold">Share Assistant</h3>
|
||||
<h3 className="text-lg font-semibold">Share Agent</h3>
|
||||
<SearchMultiSelectDropdown
|
||||
options={allUsers
|
||||
.filter(
|
||||
|
||||
@@ -126,7 +126,7 @@ export function AssistantSharingPopover({
|
||||
</h2>
|
||||
</div>
|
||||
<p className="text-text-600 text-sm mb-4">
|
||||
Manage access to this assistant by sharing it with other users.
|
||||
Manage access to this agent by sharing it with other users.
|
||||
</p>
|
||||
|
||||
<div className="mb-4">
|
||||
@@ -135,7 +135,7 @@ export function AssistantSharingPopover({
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<h3 className="text-sm font-semibold mb-2">Share Assistant</h3>
|
||||
<h3 className="text-sm font-semibold mb-2">Share Agent</h3>
|
||||
<SearchMultiSelectDropdown
|
||||
options={allUsers
|
||||
.filter(
|
||||
|
||||
@@ -16,16 +16,16 @@ export function MakePublicAssistantPopover({
|
||||
return (
|
||||
<div className="p-4 space-y-4">
|
||||
<h2 className="text-lg font-semibold">
|
||||
{isPublic ? "Public Assistant" : "Make Assistant Public"}
|
||||
{isPublic ? "Public Agent" : "Make Agent Public"}
|
||||
</h2>
|
||||
|
||||
<p className="text-sm">
|
||||
This assistant is currently{" "}
|
||||
This agent is currently{" "}
|
||||
<span className="font-semibold">{isPublic ? "public" : "private"}</span>
|
||||
.
|
||||
{isPublic
|
||||
? " Anyone can currently access this assistant."
|
||||
: " Only you can access this assistant."}
|
||||
? " Anyone can currently access this agent."
|
||||
: " Only you can access this agent."}
|
||||
</p>
|
||||
|
||||
<Separator />
|
||||
@@ -33,7 +33,7 @@ export function MakePublicAssistantPopover({
|
||||
{isPublic ? (
|
||||
<div className="space-y-4">
|
||||
<p className="text-sm">
|
||||
To restrict access to this assistant, you can make it private again.
|
||||
To restrict access to this agent, you can make it private again.
|
||||
</p>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
@@ -43,15 +43,15 @@ export function MakePublicAssistantPopover({
|
||||
size="sm"
|
||||
variant="destructive"
|
||||
>
|
||||
Make Assistant Private
|
||||
Make Agent Private
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
<p className="text-sm">
|
||||
Making this assistant public will allow anyone with the link to view
|
||||
and use it. Ensure that all content and capabilities of the
|
||||
assistant are safe to share.
|
||||
Making this agent public will allow anyone with the link to view and
|
||||
use it. Ensure that all content and capabilities of the agent are
|
||||
safe to share.
|
||||
</p>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
@@ -60,7 +60,7 @@ export function MakePublicAssistantPopover({
|
||||
}}
|
||||
size="sm"
|
||||
>
|
||||
Make Assistant Public
|
||||
Make Agent Public
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -16,18 +16,18 @@ export function MakePublicAssistantModal({
|
||||
<Modal onOutsideClick={onClose} width="max-w-3xl">
|
||||
<div className="space-y-6">
|
||||
<h2 className="text-2xl font-bold text-text-darker">
|
||||
{isPublic ? "Public Assistant" : "Make Assistant Public"}
|
||||
{isPublic ? "Public Agent" : "Make Agent Public"}
|
||||
</h2>
|
||||
|
||||
<Text>
|
||||
This assistant is currently{" "}
|
||||
This agent is currently{" "}
|
||||
<span className="font-semibold">
|
||||
{isPublic ? "public" : "private"}
|
||||
</span>
|
||||
.
|
||||
{isPublic
|
||||
? " Anyone can currently access this assistant."
|
||||
: " Only you can access this assistant."}
|
||||
? " Anyone can currently access this agent."
|
||||
: " Only you can access this agent."}
|
||||
</Text>
|
||||
|
||||
<Separator />
|
||||
@@ -35,8 +35,7 @@ export function MakePublicAssistantModal({
|
||||
{isPublic ? (
|
||||
<div className="space-y-4">
|
||||
<Text>
|
||||
To restrict access to this assistant, you can make it private
|
||||
again.
|
||||
To restrict access to this agent, you can make it private again.
|
||||
</Text>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
@@ -46,15 +45,15 @@ export function MakePublicAssistantModal({
|
||||
size="sm"
|
||||
variant="destructive"
|
||||
>
|
||||
Make Assistant Private
|
||||
Make Agent Private
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
<Text>
|
||||
Making this assistant public will allow anyone with the link to
|
||||
view and use it. Ensure that all content and capabilities of the
|
||||
assistant are safe to share.
|
||||
Making this agent public will allow anyone with the link to view
|
||||
and use it. Ensure that all content and capabilities of the agent
|
||||
are safe to share.
|
||||
</Text>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
@@ -64,7 +63,7 @@ export function MakePublicAssistantModal({
|
||||
size="sm"
|
||||
variant="submit"
|
||||
>
|
||||
Make Assistant Public
|
||||
Make Agent Public
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -66,7 +66,7 @@ export function AssistantsTab({
|
||||
|
||||
return (
|
||||
<div className="py-4">
|
||||
<h3 className="px-4 text-lg font-semibold">Change Assistant</h3>
|
||||
<h3 className="px-4 text-lg font-semibold">Change Agent</h3>
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCenter}
|
||||
|
||||
@@ -470,7 +470,7 @@ export const GroupDisplay = ({
|
||||
|
||||
<Separator />
|
||||
|
||||
<h2 className="text-xl font-bold mt-8 mb-2">Assistants</h2>
|
||||
<h2 className="text-xl font-bold mt-8 mb-2">Agents</h2>
|
||||
|
||||
<div>
|
||||
{userGroup.document_sets.length > 0 ? (
|
||||
@@ -488,7 +488,7 @@ export const GroupDisplay = ({
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<Text>No Assistants in this group...</Text>
|
||||
<Text>No Agents in this group...</Text>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -152,7 +152,7 @@ export function PersonaMessagesChart({
|
||||
} else if (selectedPersonaId === undefined) {
|
||||
content = (
|
||||
<div className="h-80 text-text-500 flex flex-col">
|
||||
<p className="m-auto">Select an assistant to view analytics</p>
|
||||
<p className="m-auto">Select an agent to view analytics</p>
|
||||
</div>
|
||||
);
|
||||
} else if (!personaMessagesData?.length) {
|
||||
@@ -178,11 +178,9 @@ export function PersonaMessagesChart({
|
||||
|
||||
return (
|
||||
<CardSection className="mt-8">
|
||||
<Title>Assistant Analytics</Title>
|
||||
<Title>Agent Analytics</Title>
|
||||
<div className="flex flex-col gap-4">
|
||||
<Text>
|
||||
Messages and unique users per day for the selected assistant
|
||||
</Text>
|
||||
<Text>Messages and unique users per day for the selected agent</Text>
|
||||
<div className="flex items-center gap-4">
|
||||
<Select
|
||||
value={selectedPersonaId?.toString() ?? ""}
|
||||
@@ -191,14 +189,14 @@ export function PersonaMessagesChart({
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="flex w-full max-w-xs">
|
||||
<SelectValue placeholder="Select an assistant to display" />
|
||||
<SelectValue placeholder="Select an agent to display" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<div className="flex items-center px-2 pb-2 sticky top-0 bg-background border-b">
|
||||
<Search className="h-4 w-4 mr-2 shrink-0 opacity-50" />
|
||||
<input
|
||||
className="flex h-8 w-full rounded-sm bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50"
|
||||
placeholder="Search assistants..."
|
||||
placeholder="Search agents..."
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
|
||||
@@ -125,7 +125,7 @@ export function AssistantStats({ assistantId }: { assistantId: number }) {
|
||||
content = (
|
||||
<div className="h-80 text-text-500 flex flex-col">
|
||||
<p className="m-auto">
|
||||
No data found for this assistant in the selected date range
|
||||
No data found for this agent in the selected date range
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
@@ -145,7 +145,7 @@ export function AssistantStats({ assistantId }: { assistantId: number }) {
|
||||
return (
|
||||
<Card className="w-full">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<p className="text-base font-normal text-2xl">Assistant Analytics</p>
|
||||
<p className="text-base font-normal text-2xl">Agent Analytics</p>
|
||||
<AdminDateRangeSelector
|
||||
value={dateRange}
|
||||
onValueChange={setDateRange}
|
||||
|
||||
@@ -63,7 +63,8 @@ export function Modal({
|
||||
<div
|
||||
onMouseDown={handleMouseDown}
|
||||
className={cn(
|
||||
`fixed inset-0 bg-neutral-950/50 border border-neutral-200 dark:border-neutral-800 bg-opacity-30 backdrop-blur-sm h-full
|
||||
`fixed inset-0 h-full w-full
|
||||
bg-neutral-950/50 dark:bg-neutral-950/60 backdrop-blur-sm
|
||||
flex items-center justify-center z-50 transition-opacity duration-300 ease-in-out`
|
||||
)}
|
||||
>
|
||||
@@ -75,7 +76,7 @@ export function Modal({
|
||||
}
|
||||
}}
|
||||
className={`
|
||||
bg-neutral-50 dark:bg-neutral-800
|
||||
bg-white dark:bg-neutral-800 opacity-100
|
||||
text-neutral-950 dark:text-neutral-50
|
||||
rounded
|
||||
shadow-2xl
|
||||
|
||||
@@ -28,12 +28,12 @@ export default function SourceTile({
|
||||
w-40
|
||||
cursor-pointer
|
||||
shadow-md
|
||||
hover:bg-accent-background-hovered
|
||||
hover:bg-background-settings-hover/50
|
||||
relative
|
||||
${
|
||||
preSelect
|
||||
? "bg-accent-background-hovered subtle-pulse"
|
||||
: "bg-accent-background"
|
||||
? "bg-background-settings-hover subtle-pulse"
|
||||
: "bg-background-sidebar"
|
||||
}
|
||||
`}
|
||||
href={navigationUrl}
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
|
||||
import { AdminSidebar } from "@/components/admin/connectors/AdminSidebar";
|
||||
import {
|
||||
ClipboardIcon,
|
||||
NotebookIconSkeleton,
|
||||
ConnectorIconSkeleton,
|
||||
ThumbsUpIconSkeleton,
|
||||
ToolIconSkeleton,
|
||||
CpuIconSkeleton,
|
||||
UsersIconSkeleton,
|
||||
@@ -15,7 +13,6 @@ import {
|
||||
DatabaseIconSkeleton,
|
||||
SettingsIconSkeleton,
|
||||
PaintingIconSkeleton,
|
||||
ZoomInIconSkeleton,
|
||||
SlackIconSkeleton,
|
||||
DocumentSetIconSkeleton,
|
||||
AssistantsIconSkeleton,
|
||||
@@ -65,35 +62,7 @@ const connectors_items = () => [
|
||||
},
|
||||
];
|
||||
|
||||
const document_management_items = () => [
|
||||
{
|
||||
name: (
|
||||
<div className="flex">
|
||||
<DocumentSetIconSkeleton className="text-text-700" size={18} />
|
||||
<div className="ml-1">Document Sets</div>
|
||||
</div>
|
||||
),
|
||||
link: "/admin/documents/sets",
|
||||
},
|
||||
{
|
||||
name: (
|
||||
<div className="flex">
|
||||
<ZoomInIconSkeleton className="text-text-700" size={18} />
|
||||
<div className="ml-1">Explorer</div>
|
||||
</div>
|
||||
),
|
||||
link: "/admin/documents/explorer",
|
||||
},
|
||||
{
|
||||
name: (
|
||||
<div className="flex">
|
||||
<ThumbsUpIconSkeleton className="text-text-700" size={18} />
|
||||
<div className="ml-1">Feedback</div>
|
||||
</div>
|
||||
),
|
||||
link: "/admin/documents/feedback",
|
||||
},
|
||||
];
|
||||
// Document Management group removed; Document Sets moved under Assistants
|
||||
|
||||
const custom_assistants_items = (
|
||||
isCurator: boolean,
|
||||
@@ -104,11 +73,20 @@ const custom_assistants_items = (
|
||||
name: (
|
||||
<div className="flex">
|
||||
<AssistantsIconSkeleton className="text-text-700" size={18} />
|
||||
<div className="ml-1">Assistants</div>
|
||||
<div className="ml-1">Agents</div>
|
||||
</div>
|
||||
),
|
||||
link: "/admin/assistants",
|
||||
},
|
||||
{
|
||||
name: (
|
||||
<div className="flex">
|
||||
<DocumentSetIconSkeleton className="text-text-700" size={18} />
|
||||
<div className="ml-1">Document Sets</div>
|
||||
</div>
|
||||
),
|
||||
link: "/admin/documents/sets",
|
||||
},
|
||||
];
|
||||
|
||||
if (!isCurator) {
|
||||
@@ -134,17 +112,7 @@ const custom_assistants_items = (
|
||||
);
|
||||
}
|
||||
|
||||
if (enableEnterprise) {
|
||||
items.push({
|
||||
name: (
|
||||
<div className="flex">
|
||||
<ClipboardIcon className="text-text-700" size={18} />
|
||||
<div className="ml-1">Standard Answers</div>
|
||||
</div>
|
||||
),
|
||||
link: "/admin/standard-answer",
|
||||
});
|
||||
}
|
||||
// Standard Answers removed from sidebar
|
||||
|
||||
return items;
|
||||
};
|
||||
@@ -162,11 +130,7 @@ const collections = (
|
||||
items: connectors_items(),
|
||||
},
|
||||
{
|
||||
name: "Document Management",
|
||||
items: document_management_items(),
|
||||
},
|
||||
{
|
||||
name: "Custom Assistants",
|
||||
name: "Custom Agents",
|
||||
items: custom_assistants_items(isCurator, enableEnterprise),
|
||||
},
|
||||
...(isCurator
|
||||
@@ -427,7 +391,14 @@ export function ClientLayout({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="h-screen w-screen flex overflow-y-hidden">
|
||||
<div
|
||||
className="h-screen w-screen flex overflow-y-hidden"
|
||||
style={{
|
||||
["--background-input-background" as any]: "#FAFAFA",
|
||||
["--background" as any]: "#FAFAFA",
|
||||
["--background-chatbar-sidebar" as any]: "#F0F0F1",
|
||||
}}
|
||||
>
|
||||
{popup}
|
||||
|
||||
{userSettingsOpen && (
|
||||
@@ -472,7 +443,7 @@ export function ClientLayout({
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="overflow-y-scroll w-full">
|
||||
<div className="overflow-y-scroll w-full bg-background">
|
||||
<div className="fixed left-0 gap-x-4 px-4 top-4 h-8 mb-auto w-full items-start flex justify-end">
|
||||
<UserDropdown toggleUserSettings={toggleUserSettings} />
|
||||
</div>
|
||||
|
||||
@@ -161,7 +161,7 @@ export const Notifications = ({
|
||||
)}
|
||||
<div className="flex-grow">
|
||||
<p className="font-semibold text-sm text-text-800">
|
||||
New Assistant Shared: {persona?.name}
|
||||
New Agent Shared: {persona?.name}
|
||||
</p>
|
||||
{persona?.description && (
|
||||
<p className="text-xs text-text-600 mt-1">
|
||||
|
||||
@@ -24,13 +24,12 @@ export default function EmbeddingSidebar() {
|
||||
className={`flex-none
|
||||
h-screen
|
||||
transition-all
|
||||
bg-opacity-80
|
||||
duration-300
|
||||
ease-in-out
|
||||
w-[250px]
|
||||
`}
|
||||
>
|
||||
<div className="fixed h-full left-0 top-0 bg- w-[250px]">
|
||||
<div className="fixed h-full left-0 top-0 w-[250px] bg-background-sidebar">
|
||||
<div className="ml-4 mr-3 flex flex gap-x-1 items-center mt-2 my-auto text-text-700 text-xl">
|
||||
<div className="mr-1 my-auto h-6 w-6">
|
||||
<Logo height={24} width={24} />
|
||||
|
||||
@@ -5,17 +5,17 @@ export const NoAssistantModal = ({ isAdmin }: { isAdmin: boolean }) => {
|
||||
<Modal width="bg-white max-w-2xl rounded-lg shadow-xl text-center">
|
||||
<>
|
||||
<h2 className="text-3xl font-bold text-text-800 mb-4">
|
||||
No Assistant Available
|
||||
No Agent Available
|
||||
</h2>
|
||||
<p className="text-text-600 mb-6">
|
||||
You currently have no assistant configured. To use this feature, you
|
||||
need to take action.
|
||||
You currently have no agent configured. To use this feature, you need
|
||||
to take action.
|
||||
</p>
|
||||
{isAdmin ? (
|
||||
<>
|
||||
<p className="text-text-600 mb-6">
|
||||
As an administrator, you can create a new assistant by visiting
|
||||
the admin panel.
|
||||
As an administrator, you can create a new agent by visiting the
|
||||
admin panel.
|
||||
</p>
|
||||
<button
|
||||
onClick={() => {
|
||||
@@ -28,7 +28,7 @@ export const NoAssistantModal = ({ isAdmin }: { isAdmin: boolean }) => {
|
||||
</>
|
||||
) : (
|
||||
<p className="text-text-600 mb-2">
|
||||
Please contact your administrator to configure an assistant for you.
|
||||
Please contact your administrator to configure an agent for you.
|
||||
</p>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -160,8 +160,8 @@ const SortableAssistant: React.FC<SortableAssistantProps> = ({
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{pinned
|
||||
? "Unpin this assistant from the sidebar"
|
||||
: "Pin this assistant to the sidebar"}
|
||||
? "Unpin this agent from the sidebar"
|
||||
: "Pin this agent to the sidebar"}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
@@ -342,7 +342,7 @@ export const HistorySidebar = React.memo(
|
||||
)}
|
||||
<div className="h-full relative overflow-x-hidden overflow-y-auto">
|
||||
<div className="flex px-4 font-normal text-sm gap-x-2 leading-normal text-text-500/80 dark:text-[#D4D4D4] items-center font-normal leading-normal">
|
||||
Assistants
|
||||
Agents
|
||||
</div>
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
@@ -412,11 +412,11 @@ export const HistorySidebar = React.memo(
|
||||
|
||||
<div className="w-full px-4">
|
||||
<button
|
||||
aria-label="Explore Assistants"
|
||||
aria-label="Explore Agents"
|
||||
onClick={() => setShowAssistantsModal(true)}
|
||||
className="w-full cursor-pointer text-base text-black dark:text-[#D4D4D4] hover:bg-background-chat-hover flex items-center gap-x-2 py-1 px-2 rounded-md"
|
||||
>
|
||||
Explore Assistants
|
||||
Explore Agents
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user