mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-04-14 23:09:34 +02:00
k
This commit is contained in:
parent
eff93825e8
commit
c602ee2ed5
@ -226,7 +226,6 @@ async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
|
||||
setup_onyx(db_session, POSTGRES_DEFAULT_SCHEMA)
|
||||
else:
|
||||
setup_multitenant_onyx()
|
||||
print("onyz set up")
|
||||
|
||||
if not MULTI_TENANT:
|
||||
# don't emit a metric for every pod rollover/restart
|
||||
|
@ -594,7 +594,7 @@ def prefilter_requests(req: SocketModeRequest, client: TenantSocketModeClient) -
|
||||
bot_tag_id = get_onyx_bot_slack_bot_id(client.web_client)
|
||||
if event_type == "message":
|
||||
is_dm = event.get("channel_type") == "im"
|
||||
is_tagged = bot_tag_id and bot_tag_id in msg
|
||||
is_tagged = bot_tag_id and f"<@{bot_tag_id}>" in msg
|
||||
is_onyx_bot_msg = bot_tag_id and bot_tag_id in event.get("user", "")
|
||||
|
||||
# OnyxBot should never respond to itself
|
||||
@ -727,7 +727,11 @@ def build_request_details(
|
||||
event = cast(dict[str, Any], req.payload["event"])
|
||||
msg = cast(str, event["text"])
|
||||
channel = cast(str, event["channel"])
|
||||
tagged = event.get("type") == "app_mention"
|
||||
# Check for both app_mention events and messages containing bot tag
|
||||
bot_tag_id = get_onyx_bot_slack_bot_id(client.web_client)
|
||||
tagged = (event.get("type") == "app_mention") or (
|
||||
event.get("type") == "message" and bot_tag_id and f"<@{bot_tag_id}>" in msg
|
||||
)
|
||||
message_ts = event.get("ts")
|
||||
thread_ts = event.get("thread_ts")
|
||||
sender_id = event.get("user") or None
|
||||
|
@ -145,7 +145,7 @@ def update_emote_react(
|
||||
|
||||
def remove_onyx_bot_tag(message_str: str, client: WebClient) -> str:
|
||||
bot_tag_id = get_onyx_bot_slack_bot_id(web_client=client)
|
||||
return re.sub(rf"<@{bot_tag_id}>\s", "", message_str)
|
||||
return re.sub(rf"<@{bot_tag_id}>\s*", "", message_str)
|
||||
|
||||
|
||||
def _check_for_url_in_block(block: Block) -> bool:
|
||||
|
@ -25,6 +25,7 @@ from onyx.db.connector_credential_pair import add_credential_to_connector
|
||||
from onyx.db.credentials import create_credential
|
||||
from onyx.db.engine import get_session
|
||||
from onyx.db.enums import AccessType
|
||||
from onyx.db.enums import ConnectorCredentialPairStatus
|
||||
from onyx.db.models import ConnectorCredentialPair
|
||||
from onyx.db.models import User
|
||||
from onyx.db.models import UserFile
|
||||
@ -488,6 +489,9 @@ def reindex_file(
|
||||
|
||||
# Trigger immediate reindexing with highest priority
|
||||
tenant_id = get_current_tenant_id()
|
||||
# Update the cc_pair status to ACTIVE to ensure it's processed
|
||||
cc_pair.status = ConnectorCredentialPairStatus.ACTIVE
|
||||
db_session.commit()
|
||||
try:
|
||||
trigger_indexing_for_cc_pair(
|
||||
[], cc_pair.connector_id, True, tenant_id, db_session, is_user_file=True
|
||||
|
@ -6,7 +6,6 @@ from uuid import UUID
|
||||
from pydantic import BaseModel
|
||||
|
||||
from onyx.db.enums import ConnectorCredentialPairStatus
|
||||
from onyx.db.enums import IndexingStatus
|
||||
from onyx.db.models import UserFile
|
||||
from onyx.db.models import UserFolder
|
||||
|
||||
@ -49,11 +48,7 @@ class UserFileSnapshot(BaseModel):
|
||||
if model.cc_pair
|
||||
and len(model.cc_pair.index_attempts) > 0
|
||||
and model.cc_pair.last_successful_index_time is None
|
||||
and (
|
||||
model.cc_pair.status == ConnectorCredentialPairStatus.PAUSED
|
||||
or len(model.cc_pair.index_attempts) == 1
|
||||
and model.cc_pair.index_attempts[0].status == IndexingStatus.FAILED
|
||||
)
|
||||
and model.cc_pair.status == ConnectorCredentialPairStatus.PAUSED
|
||||
else UserFileStatus.INDEXED
|
||||
if model.cc_pair
|
||||
and model.cc_pair.last_successful_index_time is not None
|
||||
|
@ -82,6 +82,7 @@ import {
|
||||
FileIcon,
|
||||
FolderIcon,
|
||||
InfoIcon,
|
||||
BookIcon,
|
||||
} from "lucide-react";
|
||||
import { LLMSelector } from "@/components/llm/LLMSelector";
|
||||
import useSWR from "swr";
|
||||
@ -99,6 +100,7 @@ import { RadioGroupItemField } from "@/components/ui/RadioGroupItemField";
|
||||
import { SEARCH_TOOL_ID } from "@/app/chat/tools/constants";
|
||||
import TextView from "@/components/chat/TextView";
|
||||
import { MinimalOnyxDocument } from "@/lib/search/interfaces";
|
||||
import { TabToggle } from "@/components/ui/TabToggle";
|
||||
|
||||
function findSearchTool(tools: ToolSnapshot[]) {
|
||||
return tools.find((tool) => tool.in_code_tool_id === SEARCH_TOOL_ID);
|
||||
@ -905,27 +907,25 @@ export function AssistantEditor({
|
||||
<div>
|
||||
{canShowKnowledgeSource && (
|
||||
<>
|
||||
<Label>Knowledge Source</Label>
|
||||
<RadioGroup
|
||||
className="flex flex-col gap-y-4 mt-2"
|
||||
<TabToggle
|
||||
options={[
|
||||
{
|
||||
id: "user_files",
|
||||
label: "User Knowledge",
|
||||
icon: <FileIcon size={16} />,
|
||||
},
|
||||
{
|
||||
id: "team_knowledge",
|
||||
label: "Team Knowledge",
|
||||
icon: <BookIcon size={16} />,
|
||||
},
|
||||
]}
|
||||
value={values.knowledge_source}
|
||||
onValueChange={(value: string) => {
|
||||
onChange={(value) => {
|
||||
setFieldValue("knowledge_source", value);
|
||||
}}
|
||||
>
|
||||
<RadioGroupItemField
|
||||
value="user_files"
|
||||
id="user_files"
|
||||
label="User Knowledge"
|
||||
sublabel="Select specific user files and groups for this Assistant to use"
|
||||
/>
|
||||
<RadioGroupItemField
|
||||
value="team_knowledge"
|
||||
id="team_knowledge"
|
||||
label="Team Knowledge"
|
||||
sublabel="Use team-wide document sets for this Assistant"
|
||||
/>
|
||||
</RadioGroup>
|
||||
className="mt-2 mb-4 w-full max-w-sm"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
|
@ -158,16 +158,15 @@ export const DocumentsProvider: React.FC<DocumentsProviderProps> = ({
|
||||
fetchFolders();
|
||||
}, []);
|
||||
|
||||
const refreshFolders = useCallback(async () => {
|
||||
const refreshFolders = async () => {
|
||||
try {
|
||||
const data = await documentsService.fetchFolders();
|
||||
|
||||
setFolders(data);
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch folders:", error);
|
||||
setError("Failed to fetch folders");
|
||||
}
|
||||
}, []);
|
||||
};
|
||||
|
||||
const uploadFile = useCallback(
|
||||
async (
|
||||
|
@ -68,7 +68,8 @@ export const FileListItem: React.FC<FileListItemProps> = ({
|
||||
const { setPopup, popup } = usePopup();
|
||||
const [showMoveOptions, setShowMoveOptions] = useState(false);
|
||||
const [indexingStatus, setIndexingStatus] = useState<boolean | null>(null);
|
||||
const { getFilesIndexingStatus, refreshFolders } = useDocumentsContext();
|
||||
const { getFilesIndexingStatus, refreshFolderDetails } =
|
||||
useDocumentsContext();
|
||||
|
||||
useEffect(() => {
|
||||
const checkStatus = async () => {
|
||||
@ -78,7 +79,7 @@ export const FileListItem: React.FC<FileListItemProps> = ({
|
||||
|
||||
checkStatus();
|
||||
const interval = setInterval(() => {
|
||||
refreshFolders();
|
||||
refreshFolderDetails();
|
||||
if (indexingStatus === false) {
|
||||
checkStatus();
|
||||
}
|
||||
@ -133,7 +134,7 @@ export const FileListItem: React.FC<FileListItemProps> = ({
|
||||
throw new Error("Failed to reindex file");
|
||||
}
|
||||
setIndexingStatus(false); // Set to false to show indexing status
|
||||
refreshFolders(); // Refresh the folder list
|
||||
refreshFolderDetails();
|
||||
setPopup({
|
||||
type: "success",
|
||||
message: "Reindexing will start shortly.",
|
||||
@ -217,12 +218,15 @@ export const FileListItem: React.FC<FileListItemProps> = ({
|
||||
</div>
|
||||
|
||||
<div className="w-[30%] text-sm text-text-400 dark:text-neutral-400">
|
||||
{indexingStatus == false ? (
|
||||
{file.status == FileStatus.INDEXING ||
|
||||
file.status == FileStatus.REINDEXING ? (
|
||||
<>
|
||||
N/A, indexing
|
||||
<AnimatedDots />
|
||||
</>
|
||||
) : indexingStatus != undefined && file.token_count !== undefined ? (
|
||||
) : file.status == FileStatus.FAILED ? (
|
||||
<>Failed</>
|
||||
) : file.token_count !== undefined ? (
|
||||
`${file.token_count?.toLocaleString()} tokens`
|
||||
) : (
|
||||
"N/A"
|
||||
|
@ -119,7 +119,9 @@ const DraggableItem: React.FC<{
|
||||
>
|
||||
<div className="w-6 flex items-center justify-center shrink-0">
|
||||
<div
|
||||
className="opacity-0 group-hover:opacity-100 transition-opacity duration-150"
|
||||
className={`${
|
||||
isSelected ? "" : "opacity-0 group-hover:opacity-100"
|
||||
} transition-opacity duration-150`}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
@ -258,18 +260,24 @@ const FilePickerFolderItem: React.FC<{
|
||||
<div className="flex text-sm items-center gap-2 w-[65%] min-w-0">
|
||||
<FolderIcon className="h-5 w-5 text-black dark:text-black shrink-0 fill-black dark:fill-black" />
|
||||
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<span className="truncate text-text-dark dark:text-text-dark">
|
||||
{folder.name}
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>{folder.name}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
{folder.name.length > 40 ? (
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<span className="truncate text-text-dark dark:text-text-dark">
|
||||
{truncateString(folder.name, 40)}
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>{folder.name}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
) : (
|
||||
<span className="truncate text-text-dark dark:text-text-dark">
|
||||
{folder.name}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="w-[35%] text-right text-sm text-text-400 dark:text-neutral-400 pr-4">
|
||||
@ -1222,7 +1230,6 @@ export const FilePickerModal: React.FC<FilePickerModalProps> = ({
|
||||
isSelected={selectedFileIds.has(file.id)}
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* Add uploading files visualization */}
|
||||
</div>
|
||||
</SortableContext>
|
||||
|
53
web/src/components/ui/TabToggle.tsx
Normal file
53
web/src/components/ui/TabToggle.tsx
Normal file
@ -0,0 +1,53 @@
|
||||
import React from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export interface TabOption {
|
||||
id: string;
|
||||
label: string;
|
||||
icon?: React.ReactNode;
|
||||
}
|
||||
|
||||
interface TabToggleProps {
|
||||
options: TabOption[];
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function TabToggle({
|
||||
options,
|
||||
value,
|
||||
onChange,
|
||||
className,
|
||||
}: TabToggleProps) {
|
||||
return (
|
||||
<div className={cn("flex w-fit border-b border-border", className)}>
|
||||
{options.map((option) => (
|
||||
<button
|
||||
key={option.id}
|
||||
type="button"
|
||||
onClick={() => onChange(option.id)}
|
||||
className={cn(
|
||||
"flex items-center justify-center gap-2 px-6 py-2 text-sm font-medium transition-colors",
|
||||
"border-b-2 -mb-[2px]",
|
||||
value === option.id
|
||||
? "border-primary text-primary font-semibold"
|
||||
: "border-transparent text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-300"
|
||||
)}
|
||||
>
|
||||
{option.icon && (
|
||||
<span
|
||||
className={cn(
|
||||
"flex-shrink-0",
|
||||
value === option.id ? "text-primary" : ""
|
||||
)}
|
||||
>
|
||||
{option.icon}
|
||||
</span>
|
||||
)}
|
||||
<span>{option.label}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user