"
+
+ @staticmethod
+ def _ensure_id(chat_id: Optional[str]) -> None:
+ if not chat_id or not str(chat_id).strip():
+ raise ValueError("chat_id must be a non-empty string")
+
+
+chat_manager = ChatHandler()
diff --git a/backend/open_webui/jms/check_user.py b/backend/open_webui/jms/check_user.py
new file mode 100644
index 000000000000..e163cdaa1290
--- /dev/null
+++ b/backend/open_webui/jms/check_user.py
@@ -0,0 +1,50 @@
+import logging
+from http.cookies import SimpleCookie
+from typing import Mapping
+
+from fastapi import Request
+from open_webui.jms.wisp.protobuf import service_pb2
+from open_webui.jms.wisp.exceptions import WispError
+from open_webui.jms.wisp.protobuf.common_pb2 import User
+from open_webui.env import SRC_LOG_LEVELS
+
+from .base import BaseWisp
+
+logger = logging.getLogger(__name__)
+logger.setLevel(SRC_LOG_LEVELS["WISP"])
+
+
+class CheckUserHandler(BaseWisp):
+
+ def check_user_by_cookies(self, request: Request) -> User:
+ req = service_pb2.CookiesRequest()
+ for name, value in request.cookies.items():
+ c = req.cookies.add()
+ c.name = name
+ c.value = value
+
+ user_resp = self.stub.CheckUserByCookies(req)
+ if not user_resp.status.ok:
+ error_message = f'Failed to check user: {user_resp.status.err}'
+ logger.error(error_message)
+ raise WispError(error_message)
+ return user_resp.data
+
+ def check_user_by_cookie_map(self, cookies: Mapping[str, str]) -> User:
+ req = service_pb2.CookiesRequest()
+ for name, value in cookies.items():
+ c = req.cookies.add()
+ c.name = name
+ c.value = value
+ user_resp = self.stub.CheckUserByCookies(req)
+ if not user_resp.status.ok:
+ error_message = f'Failed to check user: {user_resp.status.err}'
+ logger.error(error_message)
+ raise WispError(error_message)
+ return user_resp.data
+
+ def check_user_by_cookie_header(self, cookie_header: str) -> User:
+ cookie = SimpleCookie()
+ cookie.load(cookie_header or "")
+ cookies = {k: morsel.value for k, morsel in cookie.items()}
+ return self.check_user_by_cookie_map(cookies)
diff --git a/backend/open_webui/jms/command.py b/backend/open_webui/jms/command.py
new file mode 100644
index 000000000000..2cc370120a30
--- /dev/null
+++ b/backend/open_webui/jms/command.py
@@ -0,0 +1,41 @@
+import logging
+from typing import Optional
+from datetime import datetime
+
+from open_webui.env import SRC_LOG_LEVELS
+from open_webui.jms.wisp.protobuf import service_pb2
+from open_webui.jms.wisp.exceptions import WispError
+from open_webui.jms.base import BaseWisp
+from open_webui.jms.schemas import CommandRecord
+
+logger = logging.getLogger(__name__)
+logger.setLevel(SRC_LOG_LEVELS["WISP"])
+
+
+class CommandHandler(BaseWisp):
+
+ def __init__(self, session_id: str, session_info: dict):
+ super().__init__()
+ self.session_id = session_id
+ self.session_info = session_info
+ self.command_record: Optional[CommandRecord] = None
+
+ async def record_command(self):
+ req = service_pb2.CommandRequest(
+ sid=self.session_id,
+ org_id=self.session_info['org_id'],
+ asset=self.session_info['asset'],
+ account=self.session_info['account'],
+ user=self.session_info['user'],
+ timestamp=int(datetime.timestamp(datetime.now())),
+ input=self.command_record.input,
+ output=self.command_record.output,
+ risk_level=self.command_record.risk_level,
+ cmd_acl_id='',
+ cmd_group_id='',
+ )
+ resp = self.stub.UploadCommand(req)
+ if not resp.status.ok:
+ error_message = f'Failed to upload command: {resp.status.err}'
+ logger.error(error_message)
+ raise WispError(error_message)
diff --git a/backend/open_webui/jms/poll.py b/backend/open_webui/jms/poll.py
new file mode 100644
index 000000000000..0b1694e1dab7
--- /dev/null
+++ b/backend/open_webui/jms/poll.py
@@ -0,0 +1,62 @@
+import os
+import queue
+import logging
+import asyncio
+import threading
+
+from open_webui.env import SRC_LOG_LEVELS
+from open_webui.jms.wisp import PROJECT_DIR
+from open_webui.jms.wisp.protobuf import service_pb2
+from open_webui.jms.wisp.exceptions import WispError
+from open_webui.jms.wisp.protobuf.common_pb2 import KillSession
+from .base import BaseWisp
+from .session import JMSSession
+
+logger = logging.getLogger(__name__)
+logger.setLevel(SRC_LOG_LEVELS["WISP"])
+
+
+class PollJMSEvent(BaseWisp):
+ @staticmethod
+ async def close_session(target_session: JMSSession):
+ await target_session.close()
+
+ def clear_zombie_session(self):
+ replay_dir = os.path.join(PROJECT_DIR, 'data/replay')
+ req = service_pb2.RemainReplayRequest(replay_dir=replay_dir)
+ resp = self.stub.ScanRemainReplays(req)
+ if not resp.status.ok:
+ error_message = f'Failed to scan remain replay: {resp.status.err}'
+ logger.error(error_message)
+ raise WispError(error_message)
+ else:
+ logger.info('Scan remain replay success')
+
+ def wait_for_kill_session_message(self):
+ from open_webui.jms import chat_manager
+ q = queue.Queue(maxsize=1000)
+ for resp in self.stub.DispatchTask(iter(q.get, None)):
+ task = resp.task
+ session_id = task.session_id
+ task_action = task.action
+
+ if task_action == KillSession:
+ filtered = chat_manager.list(query={'ids': session_id})
+ for chat in filtered:
+ asyncio.run(self.close_session(JMSSession(chat)))
+
+ req = service_pb2.FinishedTaskRequest(task_id=session_id)
+ self.stub.FinishSession(req)
+
+ def start_session_killer(self):
+ self.wait_for_kill_session_message()
+
+ def start(self):
+ self.clear_zombie_session()
+ self.start_session_killer()
+
+
+def setup_poll_jms_event():
+ jms_event = PollJMSEvent()
+ thread = threading.Thread(target=jms_event.start)
+ thread.start()
diff --git a/backend/open_webui/jms/replay/__init__.py b/backend/open_webui/jms/replay/__init__.py
new file mode 100644
index 000000000000..cacb003b8cce
--- /dev/null
+++ b/backend/open_webui/jms/replay/__init__.py
@@ -0,0 +1,122 @@
+import os
+import textwrap
+import logging
+from pathlib import Path
+from datetime import datetime
+
+from open_webui.jms.wisp import PROJECT_DIR
+from open_webui.jms.wisp.protobuf import service_pb2
+from open_webui.jms.wisp.exceptions import WispError
+from open_webui.env import SRC_LOG_LEVELS
+from .asciinema import AsciinemaWriter
+from ..base import BaseWisp
+
+logger = logging.getLogger(__name__)
+logger.setLevel(SRC_LOG_LEVELS["WISP"])
+
+
+class ReplayHandler(BaseWisp):
+ DEFAULT_ENCODING = "utf-8"
+ REPLAY_DIR = os.path.join(PROJECT_DIR, 'data/replay')
+
+ def __init__(self, session_id: str):
+ super().__init__()
+ self.session_id = session_id
+ self.replay_writer: AsciinemaWriter | None = None
+ self.file_writer = None
+ self.file: Path | None = None
+
+ async def _prepare(self):
+ self.ensure_replay_dir()
+ path = self._replay_path()
+
+ if self.file is None:
+ self.file = path
+
+ if not path.exists():
+ try:
+ path.touch()
+ except Exception as e:
+ logger.error(f"Failed to create replay file: {path.name} -> {e}")
+ raise
+
+ try:
+ self.file_writer = path.open(mode="w", encoding=self.DEFAULT_ENCODING, buffering=1)
+ self.replay_writer = AsciinemaWriter(self.file_writer)
+ self.replay_writer.write_header()
+ except Exception as e:
+ logger.error(f"Failed to init writer for new file {path.name}: {e}")
+ self.file_writer = None
+ self.replay_writer = None
+ raise
+ return
+
+ if self.file_writer and not self.file_writer.closed and self.replay_writer is not None:
+ return
+
+ try:
+ self.file_writer = path.open(mode="a", encoding=self.DEFAULT_ENCODING, buffering=1)
+ self.replay_writer = AsciinemaWriter(self.file_writer)
+ except Exception as e:
+ logger.error(f"Failed to reopen writer for {path.name}: {e}")
+ self.file_writer = None
+ self.replay_writer = None
+
+ def ensure_replay_dir(self):
+ os.makedirs(self.REPLAY_DIR, exist_ok=True)
+
+ def _replay_path(self) -> Path:
+ return Path(os.path.join(self.REPLAY_DIR, f"{self.session_id}.cast"))
+
+ def _write_row(self, row):
+ row = row.replace("\n", "\r\n")
+ row = row.replace("\r\r\n", "\r\n")
+ row = f"{row} \r\n"
+
+ try:
+ self.replay_writer.write_row(row.encode(self.DEFAULT_ENCODING))
+ except Exception as e:
+ logger.error(f"Failed to write replay row: {e}")
+
+ async def write_input(self, input_str):
+ await self._prepare()
+ current_time = datetime.now()
+ formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
+ input_str = f"[{formatted_time}]#: {input_str}"
+ self._write_row(input_str)
+
+ async def write_output(self, output_str):
+ await self._prepare()
+ wrapper = textwrap.TextWrapper(width=self.replay_writer.WIDTH)
+ output_str = wrapper.fill(output_str)
+ output_str = f"\r\n {output_str} \r\n"
+ self._write_row(output_str)
+
+ async def upload(self):
+ await self._prepare()
+ try:
+ if self.file_writer and not self.file_writer.closed:
+ try:
+ self.file_writer.flush()
+ except Exception:
+ pass
+ self.file_writer.close()
+ except Exception as e:
+ logger.warning(f"Failed to flush/close before upload: {e}")
+
+ try:
+ replay_request = service_pb2.ReplayRequest(
+ session_id=self.session_id,
+ replay_file_path=self.file.absolute().as_posix()
+ )
+ resp = self.stub.UploadReplayFile(replay_request)
+
+ if not resp.status.ok:
+ error_message = f'Failed to upload replay file: {self.file.name} {resp.status.err}'
+ logger.error(error_message)
+ raise WispError(error_message)
+ except Exception as e:
+ logger.error(f'Failed to upload replay file upload {e}')
+ finally:
+ self.replay_writer = None
+ self.file_writer = None
diff --git a/backend/open_webui/jms/replay/asciinema.py b/backend/open_webui/jms/replay/asciinema.py
new file mode 100644
index 000000000000..74f0d1b4b4e6
--- /dev/null
+++ b/backend/open_webui/jms/replay/asciinema.py
@@ -0,0 +1,49 @@
+import json
+import time
+from datetime import datetime
+
+
+class AsciinemaWriter:
+ VERSION = 2
+ WIDTH = 80
+ HEIGHT = 40
+ DEFAULT_SHELL = "/bin/bash"
+ DEFAULT_TERM = "xterm"
+ NEW_LINE = "\n"
+
+ def __init__(self, writer):
+ self.config = {
+ "width": self.WIDTH,
+ "height": self.HEIGHT,
+ "envShell": self.DEFAULT_SHELL,
+ "envTerm": self.DEFAULT_TERM,
+ "timestamp": int(datetime.timestamp(datetime.now())),
+ "title": None
+ }
+ self.writer = writer
+ self.timestampNano = time.time_ns()
+
+ def write_header(self):
+ header = {
+ "version": self.VERSION,
+ "width": self.config["width"],
+ "height": self.config["height"],
+ "timestamp": self.config["timestamp"],
+ "title": self.config["title"],
+ "env": {
+ "shell": self.config["envShell"],
+ "term": self.config["envTerm"]
+ }
+ }
+ json_data = json.dumps(header) + self.NEW_LINE
+ self.writer.write(json_data)
+
+ def write_row(self, p):
+ now = time.time_ns()
+ ts = (now - self.timestampNano) / 1_000_000_000.0
+ self.write_stdout(ts, p)
+
+ def write_stdout(self, ts, data):
+ row = [ts, "o", data.decode("utf-8")]
+ json_data = json.dumps(row) + self.NEW_LINE
+ self.writer.write(json_data)
diff --git a/backend/open_webui/jms/schemas.py b/backend/open_webui/jms/schemas.py
new file mode 100644
index 000000000000..e877d17b191b
--- /dev/null
+++ b/backend/open_webui/jms/schemas.py
@@ -0,0 +1,10 @@
+from pydantic import BaseModel
+from typing import Optional
+
+from open_webui.jms.wisp.protobuf.common_pb2 import RiskLevel
+
+
+class CommandRecord(BaseModel):
+ input: Optional[str] = None
+ output: Optional[str] = None
+ risk_level: str = RiskLevel.Normal
diff --git a/backend/open_webui/jms/session/__init__.py b/backend/open_webui/jms/session/__init__.py
new file mode 100644
index 000000000000..98745a0fed50
--- /dev/null
+++ b/backend/open_webui/jms/session/__init__.py
@@ -0,0 +1 @@
+from .handler import *
diff --git a/backend/open_webui/jms/session/handler.py b/backend/open_webui/jms/session/handler.py
new file mode 100644
index 000000000000..740d3297bcef
--- /dev/null
+++ b/backend/open_webui/jms/session/handler.py
@@ -0,0 +1,74 @@
+import asyncio
+import logging
+from datetime import datetime
+
+from open_webui.jms.wisp.protobuf import service_pb2
+from open_webui.jms.wisp.exceptions import WispError
+from open_webui.jms.wisp.protobuf.common_pb2 import Session, User
+from open_webui.jms import CommandHandler, ReplayHandler
+from open_webui.env import SRC_LOG_LEVELS
+from ..account import AccountChatHandler
+from ..base import BaseWisp
+
+logger = logging.getLogger(__name__)
+logger.setLevel(SRC_LOG_LEVELS["WISP"])
+
+
+class JMSSession(BaseWisp):
+ def __init__(self, chat: dict):
+ super().__init__()
+ self.chat_id = chat['id']
+
+ self.command_handler = CommandHandler(self.chat_id, chat['session_info'])
+ self.replay_handler = ReplayHandler(self.chat_id)
+
+ async def close_session(self) -> None:
+ req = service_pb2.SessionFinishRequest(
+ id=self.chat_id,
+ date_end=int(datetime.now().timestamp())
+ )
+ resp = self.stub.FinishSession(req)
+
+ if not resp.status.ok:
+ error_message = f'Failed to close session: {resp.status.err}'
+ logger.error(error_message)
+ raise WispError(error_message)
+
+ async def close(self) -> None:
+ await asyncio.sleep(1)
+ await self.replay_handler.upload()
+ await self.close_session()
+
+
+class SessionHandler(BaseWisp):
+
+ def __init__(self, sid: str, ip: str, user: User):
+ super().__init__()
+ self.sid = sid
+ self.remote_address = ip
+ self.user = user
+
+ def create_session(self, chat_model: str) -> Session:
+ account_handler = AccountChatHandler()
+ account_data = account_handler.get_account()
+
+ req_session = Session(
+ user_id=self.user.id,
+ user=f'{self.user.name}({self.user.username})',
+ account_id=account_data['id'],
+ account=f'{account_data["name"]}({account_data["username"]})',
+ org_id=account_data['org_id'],
+ asset_id=account_data['asset']['id'],
+ asset=account_data['asset']['name'],
+ login_from=Session.LoginFrom.WT,
+ protocol=chat_model,
+ date_start=int(datetime.now().timestamp()),
+ remote_addr=self.remote_address,
+ )
+ req = service_pb2.SessionCreateRequest(data=req_session)
+ resp = self.stub.CreateSession(req)
+ if not resp.status.ok:
+ error_message = f'Failed to create session: {resp.status.err}'
+ logger.error(error_message)
+ raise WispError(error_message)
+ return resp.data
diff --git a/backend/open_webui/jms/wisp/__init__.py b/backend/open_webui/jms/wisp/__init__.py
new file mode 100644
index 000000000000..e6973e461814
--- /dev/null
+++ b/backend/open_webui/jms/wisp/__init__.py
@@ -0,0 +1,30 @@
+import os
+import sys
+import grpc
+from typing import Optional
+
+grpc_channel: Optional[grpc.Channel] = None
+BASE_DIR = os.path.dirname(os.path.abspath(__file__))
+PROJECT_DIR = os.path.dirname(BASE_DIR)
+
+
+def setup_protobuf():
+ global grpc_channel
+ current_dir = os.path.dirname(os.path.abspath(__file__))
+ protobuf_path = os.path.join(current_dir, 'protobuf')
+ if protobuf_path not in sys.path:
+ sys.path.insert(0, protobuf_path)
+
+ grpc_channel = grpc.insecure_channel('localhost:9090')
+
+
+def shutdown_protobuf():
+ global grpc_channel
+ ch = grpc_channel
+ if ch is None:
+ return
+ ch.close()
+ grpc_channel = None
+
+
+setup_protobuf()
diff --git a/backend/open_webui/jms/wisp/exceptions.py b/backend/open_webui/jms/wisp/exceptions.py
new file mode 100644
index 000000000000..8de2d408708f
--- /dev/null
+++ b/backend/open_webui/jms/wisp/exceptions.py
@@ -0,0 +1,2 @@
+class WispError(Exception):
+ pass
diff --git a/backend/open_webui/jms/wisp/protobuf/common_pb2.py b/backend/open_webui/jms/wisp/protobuf/common_pb2.py
new file mode 100644
index 000000000000..13cb0e95ca48
--- /dev/null
+++ b/backend/open_webui/jms/wisp/protobuf/common_pb2.py
@@ -0,0 +1,95 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: common.proto
+# Protobuf Python Version: 5.29.0
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 0,
+ '',
+ 'common.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0c\x63ommon.proto\x12\x07message\"e\n\x04User\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x10\n\x08username\x18\x03 \x01(\t\x12\x0c\n\x04role\x18\x04 \x01(\t\x12\x10\n\x08is_valid\x18\x05 \x01(\x08\x12\x11\n\tis_active\x18\x06 \x01(\x08\"n\n\x07\x41\x63\x63ount\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x10\n\x08username\x18\x04 \x01(\t\x12\x0e\n\x06secret\x18\x05 \x01(\t\x12\'\n\nsecretType\x18\x06 \x01(\x0b\x32\x13.message.LabelValue\"*\n\nLabelValue\x12\r\n\x05label\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\"\xc5\x03\n\x05\x41sset\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\x03 \x01(\t\x12\x0e\n\x06org_id\x18\x04 \x01(\t\x12\x10\n\x08org_name\x18\x05 \x01(\t\x12$\n\tprotocols\x18\x06 \x03(\x0b\x32\x11.message.Protocol\x12)\n\x08specific\x18\x07 \x01(\x0b\x32\x17.message.Asset.Specific\x1a\x9d\x02\n\x08Specific\x12\x0f\n\x07\x64\x62_name\x18\x01 \x01(\t\x12\x0f\n\x07use_ssl\x18\x02 \x01(\x08\x12\x0f\n\x07\x63\x61_cert\x18\x03 \x01(\t\x12\x13\n\x0b\x63lient_cert\x18\x04 \x01(\t\x12\x12\n\nclient_key\x18\x05 \x01(\t\x12\x1a\n\x12\x61llow_invalid_cert\x18\x06 \x01(\x08\x12\x11\n\tauto_fill\x18\x07 \x01(\t\x12\x19\n\x11username_selector\x18\x08 \x01(\t\x12\x19\n\x11password_selector\x18\t \x01(\t\x12\x17\n\x0fsubmit_selector\x18\n \x01(\t\x12\x0e\n\x06script\x18\x0b \x01(\t\x12\x12\n\nhttp_proxy\x18\x0c \x01(\t\x12\x13\n\x0bpg_ssl_mode\x18\r \x01(\t\"2\n\x08Protocol\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x0c\n\x04port\x18\x03 \x01(\x05\"\x88\x01\n\x07Gateway\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\n\n\x02ip\x18\x03 \x01(\t\x12\x0c\n\x04port\x18\x04 \x01(\x05\x12\x10\n\x08protocol\x18\x05 \x01(\t\x12\x10\n\x08username\x18\x06 \x01(\t\x12\x10\n\x08password\x18\x07 \x01(\t\x12\x13\n\x0bprivate_key\x18\x08 \x01(\t\"\x7f\n\nPermission\x12\x16\n\x0e\x65nable_connect\x18\x01 \x01(\x08\x12\x17\n\x0f\x65nable_download\x18\x02 \x01(\x08\x12\x15\n\renable_upload\x18\x03 \x01(\x08\x12\x13\n\x0b\x65nable_copy\x18\x04 \x01(\x08\x12\x14\n\x0c\x65nable_paste\x18\x05 \x01(\x08\"\x81\x02\n\nCommandACL\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x10\n\x08priority\x18\x03 \x01(\x05\x12*\n\x06\x61\x63tion\x18\x05 \x01(\x0e\x32\x1a.message.CommandACL.Action\x12\x11\n\tis_active\x18\x06 \x01(\x08\x12-\n\x0e\x63ommand_groups\x18\x07 \x03(\x0b\x32\x15.message.CommandGroup\"Y\n\x06\x41\x63tion\x12\n\n\x06Reject\x10\x00\x12\n\n\x06\x41\x63\x63\x65pt\x10\x01\x12\n\n\x06Review\x10\x02\x12\x0b\n\x07Warning\x10\x03\x12\x11\n\rNotifyWarning\x10\x04\x12\x0b\n\x07Unknown\x10\x05\"\x96\x01\n\x0f\x44\x61taMaskingRule\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x10\n\x08priority\x18\x03 \x01(\x05\x12\x11\n\tis_active\x18\x04 \x01(\x08\x12\x16\n\x0emasking_method\x18\x05 \x01(\t\x12\x14\n\x0cmask_pattern\x18\x06 \x01(\t\x12\x16\n\x0e\x66ields_pattern\x18\x07 \x01(\t\"m\n\x0c\x43ommandGroup\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x03 \x01(\t\x12\x0c\n\x04Type\x18\x04 \x01(\t\x12\x0f\n\x07pattern\x18\x05 \x01(\t\x12\x13\n\x0bignore_case\x18\x06 \x01(\x08\"\x1f\n\nExpireInfo\x12\x11\n\texpire_at\x18\x01 \x01(\x03\"\xb4\x02\n\x07Session\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04user\x18\x02 \x01(\t\x12\r\n\x05\x61sset\x18\x03 \x01(\t\x12\x0f\n\x07\x61\x63\x63ount\x18\x04 \x01(\t\x12.\n\nlogin_from\x18\x05 \x01(\x0e\x32\x1a.message.Session.LoginFrom\x12\x13\n\x0bremote_addr\x18\x06 \x01(\t\x12\x10\n\x08protocol\x18\x07 \x01(\t\x12\x12\n\ndate_start\x18\x08 \x01(\x03\x12\x0e\n\x06org_id\x18\t \x01(\t\x12\x0f\n\x07user_id\x18\n \x01(\t\x12\x10\n\x08\x61sset_id\x18\x0b \x01(\t\x12\x12\n\naccount_id\x18\x0c \x01(\t\x12\x10\n\x08token_id\x18\r \x01(\t\"+\n\tLoginFrom\x12\x06\n\x02WT\x10\x00\x12\x06\n\x02ST\x10\x01\x12\x06\n\x02RT\x10\x02\x12\x06\n\x02\x44T\x10\x03\"?\n\x0bTokenStatus\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0e\n\x06\x64\x65tail\x18\x02 \x01(\t\x12\x12\n\nis_expired\x18\x03 \x01(\x08\"\xaa\x01\n\x0cTerminalTask\x12\n\n\x02id\x18\x01 \x01(\t\x12#\n\x06\x61\x63tion\x18\x02 \x01(\x0e\x32\x13.message.TaskAction\x12\x12\n\nsession_id\x18\x03 \x01(\t\x12\x15\n\rterminated_by\x18\x04 \x01(\t\x12\x12\n\ncreated_by\x18\x05 \x01(\t\x12*\n\x0ctoken_status\x18\x06 \x01(\x0b\x32\x14.message.TokenStatus\"\xd5\x03\n\rTokenAuthInfo\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\x12\n\nsecrete_id\x18\x02 \x01(\t\x12\x1d\n\x05\x61sset\x18\x03 \x01(\x0b\x32\x0e.message.Asset\x12\x1b\n\x04user\x18\x04 \x01(\x0b\x32\r.message.User\x12!\n\x07\x61\x63\x63ount\x18\x05 \x01(\x0b\x32\x10.message.Account\x12\'\n\npermission\x18\x06 \x01(\x0b\x32\x13.message.Permission\x12(\n\x0b\x65xpire_info\x18\x07 \x01(\x0b\x32\x13.message.ExpireInfo\x12)\n\x0c\x66ilter_rules\x18\x08 \x03(\x0b\x32\x13.message.CommandACL\x12\"\n\x08gateways\x18\t \x03(\x0b\x32\x10.message.Gateway\x12*\n\x07setting\x18\n \x01(\x0b\x32\x19.message.ComponentSetting\x12#\n\x08platform\x18\x0b \x01(\x0b\x32\x11.message.Platform\x12\x18\n\x10\x46\x61\x63\x65MonitorToken\x18\x0c \x01(\t\x12\x34\n\x12\x64\x61ta_masking_rules\x18\r \x03(\x0b\x32\x18.message.DataMaskingRule\"\x83\x01\n\x08Platform\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x10\n\x08\x63\x61tegory\x18\x03 \x01(\t\x12\x0f\n\x07\x63harset\x18\x04 \x01(\t\x12\x0c\n\x04type\x18\x05 \x01(\t\x12,\n\tprotocols\x18\x06 \x03(\x0b\x32\x19.message.PlatformProtocol\"\xa6\x01\n\x10PlatformProtocol\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0c\n\x04port\x18\x03 \x01(\x05\x12\x39\n\x08settings\x18\x04 \x03(\x0b\x32\'.message.PlatformProtocol.SettingsEntry\x1a/\n\rSettingsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"C\n\x10\x43omponentSetting\x12\x15\n\rmax_idle_time\x18\x01 \x01(\x05\x12\x18\n\x10max_session_time\x18\x02 \x01(\x05\"1\n\x07\x46orward\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04Host\x18\x02 \x01(\t\x12\x0c\n\x04port\x18\x03 \x01(\x05\"\xa7\x01\n\rPublicSetting\x12\x15\n\rxpack_enabled\x18\x01 \x01(\x08\x12\x15\n\rvalid_license\x18\x02 \x01(\x08\x12\x14\n\x0cgpt_base_url\x18\x03 \x01(\t\x12\x13\n\x0bgpt_api_key\x18\x04 \x01(\t\x12\x11\n\tgpt_proxy\x18\x05 \x01(\t\x12\x11\n\tgpt_model\x18\x06 \x01(\t\x12\x17\n\x0flicense_content\x18\x07 \x01(\t\"%\n\x06\x43ookie\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\"\xa8\x03\n\x10LifecycleLogData\x12\x33\n\x05\x65vent\x18\x01 \x01(\x0e\x32$.message.LifecycleLogData.event_type\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x0c\n\x04user\x18\x03 \x01(\t\"\xc0\x02\n\nevent_type\x12\x17\n\x13\x41ssetConnectSuccess\x10\x00\x12\x18\n\x14\x41ssetConnectFinished\x10\x01\x12\x13\n\x0f\x43reateShareLink\x10\x02\x12\x13\n\x0fUserJoinSession\x10\x03\x12\x14\n\x10UserLeaveSession\x10\x04\x12\x14\n\x10\x41\x64minJoinMonitor\x10\x05\x12\x14\n\x10\x41\x64minExitMonitor\x10\x06\x12\x16\n\x12ReplayConvertStart\x10\x07\x12\x18\n\x14ReplayConvertSuccess\x10\x08\x12\x18\n\x14ReplayConvertFailure\x10\t\x12\x15\n\x11ReplayUploadStart\x10\n\x12\x17\n\x13ReplayUploadSuccess\x10\x0b\x12\x17\n\x13ReplayUploadFailure\x10\x0c*k\n\nTaskAction\x12\x0f\n\x0bKillSession\x10\x00\x12\x0f\n\x0bLockSession\x10\x01\x12\x11\n\rUnlockSession\x10\x02\x12\x14\n\x10TokenPermExpired\x10\x03\x12\x12\n\x0eTokenPermValid\x10\x04*f\n\tRiskLevel\x12\n\n\x06Normal\x10\x00\x12\x0b\n\x07Warning\x10\x01\x12\n\n\x06Reject\x10\x02\x12\x10\n\x0cReviewReject\x10\x03\x12\x10\n\x0cReviewAccept\x10\x04\x12\x10\n\x0cReviewCancel\x10\x05\x42 \n\x13org.jumpserver.wispZ\t/protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'common_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\023org.jumpserver.wispZ\t/protobuf'
+ _globals['_PLATFORMPROTOCOL_SETTINGSENTRY']._loaded_options = None
+ _globals['_PLATFORMPROTOCOL_SETTINGSENTRY']._serialized_options = b'8\001'
+ _globals['_TASKACTION']._serialized_start=3697
+ _globals['_TASKACTION']._serialized_end=3804
+ _globals['_RISKLEVEL']._serialized_start=3806
+ _globals['_RISKLEVEL']._serialized_end=3908
+ _globals['_USER']._serialized_start=25
+ _globals['_USER']._serialized_end=126
+ _globals['_ACCOUNT']._serialized_start=128
+ _globals['_ACCOUNT']._serialized_end=238
+ _globals['_LABELVALUE']._serialized_start=240
+ _globals['_LABELVALUE']._serialized_end=282
+ _globals['_ASSET']._serialized_start=285
+ _globals['_ASSET']._serialized_end=738
+ _globals['_ASSET_SPECIFIC']._serialized_start=453
+ _globals['_ASSET_SPECIFIC']._serialized_end=738
+ _globals['_PROTOCOL']._serialized_start=740
+ _globals['_PROTOCOL']._serialized_end=790
+ _globals['_GATEWAY']._serialized_start=793
+ _globals['_GATEWAY']._serialized_end=929
+ _globals['_PERMISSION']._serialized_start=931
+ _globals['_PERMISSION']._serialized_end=1058
+ _globals['_COMMANDACL']._serialized_start=1061
+ _globals['_COMMANDACL']._serialized_end=1318
+ _globals['_COMMANDACL_ACTION']._serialized_start=1229
+ _globals['_COMMANDACL_ACTION']._serialized_end=1318
+ _globals['_DATAMASKINGRULE']._serialized_start=1321
+ _globals['_DATAMASKINGRULE']._serialized_end=1471
+ _globals['_COMMANDGROUP']._serialized_start=1473
+ _globals['_COMMANDGROUP']._serialized_end=1582
+ _globals['_EXPIREINFO']._serialized_start=1584
+ _globals['_EXPIREINFO']._serialized_end=1615
+ _globals['_SESSION']._serialized_start=1618
+ _globals['_SESSION']._serialized_end=1926
+ _globals['_SESSION_LOGINFROM']._serialized_start=1883
+ _globals['_SESSION_LOGINFROM']._serialized_end=1926
+ _globals['_TOKENSTATUS']._serialized_start=1928
+ _globals['_TOKENSTATUS']._serialized_end=1991
+ _globals['_TERMINALTASK']._serialized_start=1994
+ _globals['_TERMINALTASK']._serialized_end=2164
+ _globals['_TOKENAUTHINFO']._serialized_start=2167
+ _globals['_TOKENAUTHINFO']._serialized_end=2636
+ _globals['_PLATFORM']._serialized_start=2639
+ _globals['_PLATFORM']._serialized_end=2770
+ _globals['_PLATFORMPROTOCOL']._serialized_start=2773
+ _globals['_PLATFORMPROTOCOL']._serialized_end=2939
+ _globals['_PLATFORMPROTOCOL_SETTINGSENTRY']._serialized_start=2892
+ _globals['_PLATFORMPROTOCOL_SETTINGSENTRY']._serialized_end=2939
+ _globals['_COMPONENTSETTING']._serialized_start=2941
+ _globals['_COMPONENTSETTING']._serialized_end=3008
+ _globals['_FORWARD']._serialized_start=3010
+ _globals['_FORWARD']._serialized_end=3059
+ _globals['_PUBLICSETTING']._serialized_start=3062
+ _globals['_PUBLICSETTING']._serialized_end=3229
+ _globals['_COOKIE']._serialized_start=3231
+ _globals['_COOKIE']._serialized_end=3268
+ _globals['_LIFECYCLELOGDATA']._serialized_start=3271
+ _globals['_LIFECYCLELOGDATA']._serialized_end=3695
+ _globals['_LIFECYCLELOGDATA_EVENT_TYPE']._serialized_start=3375
+ _globals['_LIFECYCLELOGDATA_EVENT_TYPE']._serialized_end=3695
+# @@protoc_insertion_point(module_scope)
diff --git a/backend/open_webui/jms/wisp/protobuf/common_pb2.pyi b/backend/open_webui/jms/wisp/protobuf/common_pb2.pyi
new file mode 100644
index 000000000000..016e0a3b986f
--- /dev/null
+++ b/backend/open_webui/jms/wisp/protobuf/common_pb2.pyi
@@ -0,0 +1,447 @@
+from google.protobuf.internal import containers as _containers
+from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union
+
+DESCRIPTOR: _descriptor.FileDescriptor
+
+class TaskAction(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
+ __slots__ = ()
+ KillSession: _ClassVar[TaskAction]
+ LockSession: _ClassVar[TaskAction]
+ UnlockSession: _ClassVar[TaskAction]
+ TokenPermExpired: _ClassVar[TaskAction]
+ TokenPermValid: _ClassVar[TaskAction]
+
+class RiskLevel(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
+ __slots__ = ()
+ Normal: _ClassVar[RiskLevel]
+ Warning: _ClassVar[RiskLevel]
+ Reject: _ClassVar[RiskLevel]
+ ReviewReject: _ClassVar[RiskLevel]
+ ReviewAccept: _ClassVar[RiskLevel]
+ ReviewCancel: _ClassVar[RiskLevel]
+KillSession: TaskAction
+LockSession: TaskAction
+UnlockSession: TaskAction
+TokenPermExpired: TaskAction
+TokenPermValid: TaskAction
+Normal: RiskLevel
+Warning: RiskLevel
+Reject: RiskLevel
+ReviewReject: RiskLevel
+ReviewAccept: RiskLevel
+ReviewCancel: RiskLevel
+
+class User(_message.Message):
+ __slots__ = ("id", "name", "username", "role", "is_valid", "is_active")
+ ID_FIELD_NUMBER: _ClassVar[int]
+ NAME_FIELD_NUMBER: _ClassVar[int]
+ USERNAME_FIELD_NUMBER: _ClassVar[int]
+ ROLE_FIELD_NUMBER: _ClassVar[int]
+ IS_VALID_FIELD_NUMBER: _ClassVar[int]
+ IS_ACTIVE_FIELD_NUMBER: _ClassVar[int]
+ id: str
+ name: str
+ username: str
+ role: str
+ is_valid: bool
+ is_active: bool
+ def __init__(self, id: _Optional[str] = ..., name: _Optional[str] = ..., username: _Optional[str] = ..., role: _Optional[str] = ..., is_valid: bool = ..., is_active: bool = ...) -> None: ...
+
+class Account(_message.Message):
+ __slots__ = ("id", "name", "username", "secret", "secretType")
+ ID_FIELD_NUMBER: _ClassVar[int]
+ NAME_FIELD_NUMBER: _ClassVar[int]
+ USERNAME_FIELD_NUMBER: _ClassVar[int]
+ SECRET_FIELD_NUMBER: _ClassVar[int]
+ SECRETTYPE_FIELD_NUMBER: _ClassVar[int]
+ id: str
+ name: str
+ username: str
+ secret: str
+ secretType: LabelValue
+ def __init__(self, id: _Optional[str] = ..., name: _Optional[str] = ..., username: _Optional[str] = ..., secret: _Optional[str] = ..., secretType: _Optional[_Union[LabelValue, _Mapping]] = ...) -> None: ...
+
+class LabelValue(_message.Message):
+ __slots__ = ("label", "value")
+ LABEL_FIELD_NUMBER: _ClassVar[int]
+ VALUE_FIELD_NUMBER: _ClassVar[int]
+ label: str
+ value: str
+ def __init__(self, label: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ...
+
+class Asset(_message.Message):
+ __slots__ = ("id", "name", "address", "org_id", "org_name", "protocols", "specific")
+ class Specific(_message.Message):
+ __slots__ = ("db_name", "use_ssl", "ca_cert", "client_cert", "client_key", "allow_invalid_cert", "auto_fill", "username_selector", "password_selector", "submit_selector", "script", "http_proxy", "pg_ssl_mode")
+ DB_NAME_FIELD_NUMBER: _ClassVar[int]
+ USE_SSL_FIELD_NUMBER: _ClassVar[int]
+ CA_CERT_FIELD_NUMBER: _ClassVar[int]
+ CLIENT_CERT_FIELD_NUMBER: _ClassVar[int]
+ CLIENT_KEY_FIELD_NUMBER: _ClassVar[int]
+ ALLOW_INVALID_CERT_FIELD_NUMBER: _ClassVar[int]
+ AUTO_FILL_FIELD_NUMBER: _ClassVar[int]
+ USERNAME_SELECTOR_FIELD_NUMBER: _ClassVar[int]
+ PASSWORD_SELECTOR_FIELD_NUMBER: _ClassVar[int]
+ SUBMIT_SELECTOR_FIELD_NUMBER: _ClassVar[int]
+ SCRIPT_FIELD_NUMBER: _ClassVar[int]
+ HTTP_PROXY_FIELD_NUMBER: _ClassVar[int]
+ PG_SSL_MODE_FIELD_NUMBER: _ClassVar[int]
+ db_name: str
+ use_ssl: bool
+ ca_cert: str
+ client_cert: str
+ client_key: str
+ allow_invalid_cert: bool
+ auto_fill: str
+ username_selector: str
+ password_selector: str
+ submit_selector: str
+ script: str
+ http_proxy: str
+ pg_ssl_mode: str
+ def __init__(self, db_name: _Optional[str] = ..., use_ssl: bool = ..., ca_cert: _Optional[str] = ..., client_cert: _Optional[str] = ..., client_key: _Optional[str] = ..., allow_invalid_cert: bool = ..., auto_fill: _Optional[str] = ..., username_selector: _Optional[str] = ..., password_selector: _Optional[str] = ..., submit_selector: _Optional[str] = ..., script: _Optional[str] = ..., http_proxy: _Optional[str] = ..., pg_ssl_mode: _Optional[str] = ...) -> None: ...
+ ID_FIELD_NUMBER: _ClassVar[int]
+ NAME_FIELD_NUMBER: _ClassVar[int]
+ ADDRESS_FIELD_NUMBER: _ClassVar[int]
+ ORG_ID_FIELD_NUMBER: _ClassVar[int]
+ ORG_NAME_FIELD_NUMBER: _ClassVar[int]
+ PROTOCOLS_FIELD_NUMBER: _ClassVar[int]
+ SPECIFIC_FIELD_NUMBER: _ClassVar[int]
+ id: str
+ name: str
+ address: str
+ org_id: str
+ org_name: str
+ protocols: _containers.RepeatedCompositeFieldContainer[Protocol]
+ specific: Asset.Specific
+ def __init__(self, id: _Optional[str] = ..., name: _Optional[str] = ..., address: _Optional[str] = ..., org_id: _Optional[str] = ..., org_name: _Optional[str] = ..., protocols: _Optional[_Iterable[_Union[Protocol, _Mapping]]] = ..., specific: _Optional[_Union[Asset.Specific, _Mapping]] = ...) -> None: ...
+
+class Protocol(_message.Message):
+ __slots__ = ("name", "id", "port")
+ NAME_FIELD_NUMBER: _ClassVar[int]
+ ID_FIELD_NUMBER: _ClassVar[int]
+ PORT_FIELD_NUMBER: _ClassVar[int]
+ name: str
+ id: int
+ port: int
+ def __init__(self, name: _Optional[str] = ..., id: _Optional[int] = ..., port: _Optional[int] = ...) -> None: ...
+
+class Gateway(_message.Message):
+ __slots__ = ("id", "name", "ip", "port", "protocol", "username", "password", "private_key")
+ ID_FIELD_NUMBER: _ClassVar[int]
+ NAME_FIELD_NUMBER: _ClassVar[int]
+ IP_FIELD_NUMBER: _ClassVar[int]
+ PORT_FIELD_NUMBER: _ClassVar[int]
+ PROTOCOL_FIELD_NUMBER: _ClassVar[int]
+ USERNAME_FIELD_NUMBER: _ClassVar[int]
+ PASSWORD_FIELD_NUMBER: _ClassVar[int]
+ PRIVATE_KEY_FIELD_NUMBER: _ClassVar[int]
+ id: str
+ name: str
+ ip: str
+ port: int
+ protocol: str
+ username: str
+ password: str
+ private_key: str
+ def __init__(self, id: _Optional[str] = ..., name: _Optional[str] = ..., ip: _Optional[str] = ..., port: _Optional[int] = ..., protocol: _Optional[str] = ..., username: _Optional[str] = ..., password: _Optional[str] = ..., private_key: _Optional[str] = ...) -> None: ...
+
+class Permission(_message.Message):
+ __slots__ = ("enable_connect", "enable_download", "enable_upload", "enable_copy", "enable_paste")
+ ENABLE_CONNECT_FIELD_NUMBER: _ClassVar[int]
+ ENABLE_DOWNLOAD_FIELD_NUMBER: _ClassVar[int]
+ ENABLE_UPLOAD_FIELD_NUMBER: _ClassVar[int]
+ ENABLE_COPY_FIELD_NUMBER: _ClassVar[int]
+ ENABLE_PASTE_FIELD_NUMBER: _ClassVar[int]
+ enable_connect: bool
+ enable_download: bool
+ enable_upload: bool
+ enable_copy: bool
+ enable_paste: bool
+ def __init__(self, enable_connect: bool = ..., enable_download: bool = ..., enable_upload: bool = ..., enable_copy: bool = ..., enable_paste: bool = ...) -> None: ...
+
+class CommandACL(_message.Message):
+ __slots__ = ("id", "name", "priority", "action", "is_active", "command_groups")
+ class Action(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
+ __slots__ = ()
+ Reject: _ClassVar[CommandACL.Action]
+ Accept: _ClassVar[CommandACL.Action]
+ Review: _ClassVar[CommandACL.Action]
+ Warning: _ClassVar[CommandACL.Action]
+ NotifyWarning: _ClassVar[CommandACL.Action]
+ Unknown: _ClassVar[CommandACL.Action]
+ Reject: CommandACL.Action
+ Accept: CommandACL.Action
+ Review: CommandACL.Action
+ Warning: CommandACL.Action
+ NotifyWarning: CommandACL.Action
+ Unknown: CommandACL.Action
+ ID_FIELD_NUMBER: _ClassVar[int]
+ NAME_FIELD_NUMBER: _ClassVar[int]
+ PRIORITY_FIELD_NUMBER: _ClassVar[int]
+ ACTION_FIELD_NUMBER: _ClassVar[int]
+ IS_ACTIVE_FIELD_NUMBER: _ClassVar[int]
+ COMMAND_GROUPS_FIELD_NUMBER: _ClassVar[int]
+ id: str
+ name: str
+ priority: int
+ action: CommandACL.Action
+ is_active: bool
+ command_groups: _containers.RepeatedCompositeFieldContainer[CommandGroup]
+ def __init__(self, id: _Optional[str] = ..., name: _Optional[str] = ..., priority: _Optional[int] = ..., action: _Optional[_Union[CommandACL.Action, str]] = ..., is_active: bool = ..., command_groups: _Optional[_Iterable[_Union[CommandGroup, _Mapping]]] = ...) -> None: ...
+
+class DataMaskingRule(_message.Message):
+ __slots__ = ("id", "name", "priority", "is_active", "masking_method", "mask_pattern", "fields_pattern")
+ ID_FIELD_NUMBER: _ClassVar[int]
+ NAME_FIELD_NUMBER: _ClassVar[int]
+ PRIORITY_FIELD_NUMBER: _ClassVar[int]
+ IS_ACTIVE_FIELD_NUMBER: _ClassVar[int]
+ MASKING_METHOD_FIELD_NUMBER: _ClassVar[int]
+ MASK_PATTERN_FIELD_NUMBER: _ClassVar[int]
+ FIELDS_PATTERN_FIELD_NUMBER: _ClassVar[int]
+ id: str
+ name: str
+ priority: int
+ is_active: bool
+ masking_method: str
+ mask_pattern: str
+ fields_pattern: str
+ def __init__(self, id: _Optional[str] = ..., name: _Optional[str] = ..., priority: _Optional[int] = ..., is_active: bool = ..., masking_method: _Optional[str] = ..., mask_pattern: _Optional[str] = ..., fields_pattern: _Optional[str] = ...) -> None: ...
+
+class CommandGroup(_message.Message):
+ __slots__ = ("id", "name", "content", "Type", "pattern", "ignore_case")
+ ID_FIELD_NUMBER: _ClassVar[int]
+ NAME_FIELD_NUMBER: _ClassVar[int]
+ CONTENT_FIELD_NUMBER: _ClassVar[int]
+ TYPE_FIELD_NUMBER: _ClassVar[int]
+ PATTERN_FIELD_NUMBER: _ClassVar[int]
+ IGNORE_CASE_FIELD_NUMBER: _ClassVar[int]
+ id: str
+ name: str
+ content: str
+ Type: str
+ pattern: str
+ ignore_case: bool
+ def __init__(self, id: _Optional[str] = ..., name: _Optional[str] = ..., content: _Optional[str] = ..., Type: _Optional[str] = ..., pattern: _Optional[str] = ..., ignore_case: bool = ...) -> None: ...
+
+class ExpireInfo(_message.Message):
+ __slots__ = ("expire_at",)
+ EXPIRE_AT_FIELD_NUMBER: _ClassVar[int]
+ expire_at: int
+ def __init__(self, expire_at: _Optional[int] = ...) -> None: ...
+
+class Session(_message.Message):
+ __slots__ = ("id", "user", "asset", "account", "login_from", "remote_addr", "protocol", "date_start", "org_id", "user_id", "asset_id", "account_id", "token_id")
+ class LoginFrom(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
+ __slots__ = ()
+ WT: _ClassVar[Session.LoginFrom]
+ ST: _ClassVar[Session.LoginFrom]
+ RT: _ClassVar[Session.LoginFrom]
+ DT: _ClassVar[Session.LoginFrom]
+ WT: Session.LoginFrom
+ ST: Session.LoginFrom
+ RT: Session.LoginFrom
+ DT: Session.LoginFrom
+ ID_FIELD_NUMBER: _ClassVar[int]
+ USER_FIELD_NUMBER: _ClassVar[int]
+ ASSET_FIELD_NUMBER: _ClassVar[int]
+ ACCOUNT_FIELD_NUMBER: _ClassVar[int]
+ LOGIN_FROM_FIELD_NUMBER: _ClassVar[int]
+ REMOTE_ADDR_FIELD_NUMBER: _ClassVar[int]
+ PROTOCOL_FIELD_NUMBER: _ClassVar[int]
+ DATE_START_FIELD_NUMBER: _ClassVar[int]
+ ORG_ID_FIELD_NUMBER: _ClassVar[int]
+ USER_ID_FIELD_NUMBER: _ClassVar[int]
+ ASSET_ID_FIELD_NUMBER: _ClassVar[int]
+ ACCOUNT_ID_FIELD_NUMBER: _ClassVar[int]
+ TOKEN_ID_FIELD_NUMBER: _ClassVar[int]
+ id: str
+ user: str
+ asset: str
+ account: str
+ login_from: Session.LoginFrom
+ remote_addr: str
+ protocol: str
+ date_start: int
+ org_id: str
+ user_id: str
+ asset_id: str
+ account_id: str
+ token_id: str
+ def __init__(self, id: _Optional[str] = ..., user: _Optional[str] = ..., asset: _Optional[str] = ..., account: _Optional[str] = ..., login_from: _Optional[_Union[Session.LoginFrom, str]] = ..., remote_addr: _Optional[str] = ..., protocol: _Optional[str] = ..., date_start: _Optional[int] = ..., org_id: _Optional[str] = ..., user_id: _Optional[str] = ..., asset_id: _Optional[str] = ..., account_id: _Optional[str] = ..., token_id: _Optional[str] = ...) -> None: ...
+
+class TokenStatus(_message.Message):
+ __slots__ = ("code", "detail", "is_expired")
+ CODE_FIELD_NUMBER: _ClassVar[int]
+ DETAIL_FIELD_NUMBER: _ClassVar[int]
+ IS_EXPIRED_FIELD_NUMBER: _ClassVar[int]
+ code: str
+ detail: str
+ is_expired: bool
+ def __init__(self, code: _Optional[str] = ..., detail: _Optional[str] = ..., is_expired: bool = ...) -> None: ...
+
+class TerminalTask(_message.Message):
+ __slots__ = ("id", "action", "session_id", "terminated_by", "created_by", "token_status")
+ ID_FIELD_NUMBER: _ClassVar[int]
+ ACTION_FIELD_NUMBER: _ClassVar[int]
+ SESSION_ID_FIELD_NUMBER: _ClassVar[int]
+ TERMINATED_BY_FIELD_NUMBER: _ClassVar[int]
+ CREATED_BY_FIELD_NUMBER: _ClassVar[int]
+ TOKEN_STATUS_FIELD_NUMBER: _ClassVar[int]
+ id: str
+ action: TaskAction
+ session_id: str
+ terminated_by: str
+ created_by: str
+ token_status: TokenStatus
+ def __init__(self, id: _Optional[str] = ..., action: _Optional[_Union[TaskAction, str]] = ..., session_id: _Optional[str] = ..., terminated_by: _Optional[str] = ..., created_by: _Optional[str] = ..., token_status: _Optional[_Union[TokenStatus, _Mapping]] = ...) -> None: ...
+
+class TokenAuthInfo(_message.Message):
+ __slots__ = ("key_id", "secrete_id", "asset", "user", "account", "permission", "expire_info", "filter_rules", "gateways", "setting", "platform", "FaceMonitorToken", "data_masking_rules")
+ KEY_ID_FIELD_NUMBER: _ClassVar[int]
+ SECRETE_ID_FIELD_NUMBER: _ClassVar[int]
+ ASSET_FIELD_NUMBER: _ClassVar[int]
+ USER_FIELD_NUMBER: _ClassVar[int]
+ ACCOUNT_FIELD_NUMBER: _ClassVar[int]
+ PERMISSION_FIELD_NUMBER: _ClassVar[int]
+ EXPIRE_INFO_FIELD_NUMBER: _ClassVar[int]
+ FILTER_RULES_FIELD_NUMBER: _ClassVar[int]
+ GATEWAYS_FIELD_NUMBER: _ClassVar[int]
+ SETTING_FIELD_NUMBER: _ClassVar[int]
+ PLATFORM_FIELD_NUMBER: _ClassVar[int]
+ FACEMONITORTOKEN_FIELD_NUMBER: _ClassVar[int]
+ DATA_MASKING_RULES_FIELD_NUMBER: _ClassVar[int]
+ key_id: str
+ secrete_id: str
+ asset: Asset
+ user: User
+ account: Account
+ permission: Permission
+ expire_info: ExpireInfo
+ filter_rules: _containers.RepeatedCompositeFieldContainer[CommandACL]
+ gateways: _containers.RepeatedCompositeFieldContainer[Gateway]
+ setting: ComponentSetting
+ platform: Platform
+ FaceMonitorToken: str
+ data_masking_rules: _containers.RepeatedCompositeFieldContainer[DataMaskingRule]
+ def __init__(self, key_id: _Optional[str] = ..., secrete_id: _Optional[str] = ..., asset: _Optional[_Union[Asset, _Mapping]] = ..., user: _Optional[_Union[User, _Mapping]] = ..., account: _Optional[_Union[Account, _Mapping]] = ..., permission: _Optional[_Union[Permission, _Mapping]] = ..., expire_info: _Optional[_Union[ExpireInfo, _Mapping]] = ..., filter_rules: _Optional[_Iterable[_Union[CommandACL, _Mapping]]] = ..., gateways: _Optional[_Iterable[_Union[Gateway, _Mapping]]] = ..., setting: _Optional[_Union[ComponentSetting, _Mapping]] = ..., platform: _Optional[_Union[Platform, _Mapping]] = ..., FaceMonitorToken: _Optional[str] = ..., data_masking_rules: _Optional[_Iterable[_Union[DataMaskingRule, _Mapping]]] = ...) -> None: ...
+
+class Platform(_message.Message):
+ __slots__ = ("id", "name", "category", "charset", "type", "protocols")
+ ID_FIELD_NUMBER: _ClassVar[int]
+ NAME_FIELD_NUMBER: _ClassVar[int]
+ CATEGORY_FIELD_NUMBER: _ClassVar[int]
+ CHARSET_FIELD_NUMBER: _ClassVar[int]
+ TYPE_FIELD_NUMBER: _ClassVar[int]
+ PROTOCOLS_FIELD_NUMBER: _ClassVar[int]
+ id: int
+ name: str
+ category: str
+ charset: str
+ type: str
+ protocols: _containers.RepeatedCompositeFieldContainer[PlatformProtocol]
+ def __init__(self, id: _Optional[int] = ..., name: _Optional[str] = ..., category: _Optional[str] = ..., charset: _Optional[str] = ..., type: _Optional[str] = ..., protocols: _Optional[_Iterable[_Union[PlatformProtocol, _Mapping]]] = ...) -> None: ...
+
+class PlatformProtocol(_message.Message):
+ __slots__ = ("id", "name", "port", "settings")
+ class SettingsEntry(_message.Message):
+ __slots__ = ("key", "value")
+ KEY_FIELD_NUMBER: _ClassVar[int]
+ VALUE_FIELD_NUMBER: _ClassVar[int]
+ key: str
+ value: str
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ...
+ ID_FIELD_NUMBER: _ClassVar[int]
+ NAME_FIELD_NUMBER: _ClassVar[int]
+ PORT_FIELD_NUMBER: _ClassVar[int]
+ SETTINGS_FIELD_NUMBER: _ClassVar[int]
+ id: int
+ name: str
+ port: int
+ settings: _containers.ScalarMap[str, str]
+ def __init__(self, id: _Optional[int] = ..., name: _Optional[str] = ..., port: _Optional[int] = ..., settings: _Optional[_Mapping[str, str]] = ...) -> None: ...
+
+class ComponentSetting(_message.Message):
+ __slots__ = ("max_idle_time", "max_session_time")
+ MAX_IDLE_TIME_FIELD_NUMBER: _ClassVar[int]
+ MAX_SESSION_TIME_FIELD_NUMBER: _ClassVar[int]
+ max_idle_time: int
+ max_session_time: int
+ def __init__(self, max_idle_time: _Optional[int] = ..., max_session_time: _Optional[int] = ...) -> None: ...
+
+class Forward(_message.Message):
+ __slots__ = ("id", "Host", "port")
+ ID_FIELD_NUMBER: _ClassVar[int]
+ HOST_FIELD_NUMBER: _ClassVar[int]
+ PORT_FIELD_NUMBER: _ClassVar[int]
+ id: str
+ Host: str
+ port: int
+ def __init__(self, id: _Optional[str] = ..., Host: _Optional[str] = ..., port: _Optional[int] = ...) -> None: ...
+
+class PublicSetting(_message.Message):
+ __slots__ = ("xpack_enabled", "valid_license", "gpt_base_url", "gpt_api_key", "gpt_proxy", "gpt_model", "license_content")
+ XPACK_ENABLED_FIELD_NUMBER: _ClassVar[int]
+ VALID_LICENSE_FIELD_NUMBER: _ClassVar[int]
+ GPT_BASE_URL_FIELD_NUMBER: _ClassVar[int]
+ GPT_API_KEY_FIELD_NUMBER: _ClassVar[int]
+ GPT_PROXY_FIELD_NUMBER: _ClassVar[int]
+ GPT_MODEL_FIELD_NUMBER: _ClassVar[int]
+ LICENSE_CONTENT_FIELD_NUMBER: _ClassVar[int]
+ xpack_enabled: bool
+ valid_license: bool
+ gpt_base_url: str
+ gpt_api_key: str
+ gpt_proxy: str
+ gpt_model: str
+ license_content: str
+ def __init__(self, xpack_enabled: bool = ..., valid_license: bool = ..., gpt_base_url: _Optional[str] = ..., gpt_api_key: _Optional[str] = ..., gpt_proxy: _Optional[str] = ..., gpt_model: _Optional[str] = ..., license_content: _Optional[str] = ...) -> None: ...
+
+class Cookie(_message.Message):
+ __slots__ = ("name", "value")
+ NAME_FIELD_NUMBER: _ClassVar[int]
+ VALUE_FIELD_NUMBER: _ClassVar[int]
+ name: str
+ value: str
+ def __init__(self, name: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ...
+
+class LifecycleLogData(_message.Message):
+ __slots__ = ("event", "reason", "user")
+ class event_type(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
+ __slots__ = ()
+ AssetConnectSuccess: _ClassVar[LifecycleLogData.event_type]
+ AssetConnectFinished: _ClassVar[LifecycleLogData.event_type]
+ CreateShareLink: _ClassVar[LifecycleLogData.event_type]
+ UserJoinSession: _ClassVar[LifecycleLogData.event_type]
+ UserLeaveSession: _ClassVar[LifecycleLogData.event_type]
+ AdminJoinMonitor: _ClassVar[LifecycleLogData.event_type]
+ AdminExitMonitor: _ClassVar[LifecycleLogData.event_type]
+ ReplayConvertStart: _ClassVar[LifecycleLogData.event_type]
+ ReplayConvertSuccess: _ClassVar[LifecycleLogData.event_type]
+ ReplayConvertFailure: _ClassVar[LifecycleLogData.event_type]
+ ReplayUploadStart: _ClassVar[LifecycleLogData.event_type]
+ ReplayUploadSuccess: _ClassVar[LifecycleLogData.event_type]
+ ReplayUploadFailure: _ClassVar[LifecycleLogData.event_type]
+ AssetConnectSuccess: LifecycleLogData.event_type
+ AssetConnectFinished: LifecycleLogData.event_type
+ CreateShareLink: LifecycleLogData.event_type
+ UserJoinSession: LifecycleLogData.event_type
+ UserLeaveSession: LifecycleLogData.event_type
+ AdminJoinMonitor: LifecycleLogData.event_type
+ AdminExitMonitor: LifecycleLogData.event_type
+ ReplayConvertStart: LifecycleLogData.event_type
+ ReplayConvertSuccess: LifecycleLogData.event_type
+ ReplayConvertFailure: LifecycleLogData.event_type
+ ReplayUploadStart: LifecycleLogData.event_type
+ ReplayUploadSuccess: LifecycleLogData.event_type
+ ReplayUploadFailure: LifecycleLogData.event_type
+ EVENT_FIELD_NUMBER: _ClassVar[int]
+ REASON_FIELD_NUMBER: _ClassVar[int]
+ USER_FIELD_NUMBER: _ClassVar[int]
+ event: LifecycleLogData.event_type
+ reason: str
+ user: str
+ def __init__(self, event: _Optional[_Union[LifecycleLogData.event_type, str]] = ..., reason: _Optional[str] = ..., user: _Optional[str] = ...) -> None: ...
diff --git a/backend/open_webui/jms/wisp/protobuf/common_pb2_grpc.py b/backend/open_webui/jms/wisp/protobuf/common_pb2_grpc.py
new file mode 100644
index 000000000000..f80da210ff0d
--- /dev/null
+++ b/backend/open_webui/jms/wisp/protobuf/common_pb2_grpc.py
@@ -0,0 +1,24 @@
+# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
+"""Client and server classes corresponding to protobuf-defined services."""
+import grpc
+import warnings
+
+
+GRPC_GENERATED_VERSION = '1.69.0'
+GRPC_VERSION = grpc.__version__
+_version_not_supported = False
+
+try:
+ from grpc._utilities import first_version_is_lower
+ _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
+except ImportError:
+ _version_not_supported = True
+
+if _version_not_supported:
+ raise RuntimeError(
+ f'The grpc package installed is at version {GRPC_VERSION},'
+ + f' but the generated code in common_pb2_grpc.py depends on'
+ + f' grpcio>={GRPC_GENERATED_VERSION}.'
+ + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
+ + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
+ )
diff --git a/backend/open_webui/jms/wisp/protobuf/service_pb2.py b/backend/open_webui/jms/wisp/protobuf/service_pb2.py
new file mode 100644
index 000000000000..ca51901bbda2
--- /dev/null
+++ b/backend/open_webui/jms/wisp/protobuf/service_pb2.py
@@ -0,0 +1,147 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: service.proto
+# Protobuf Python Version: 5.29.0
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 0,
+ '',
+ 'service.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import common_pb2 as common__pb2
+from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\rservice.proto\x12\x07message\x1a\x0c\x63ommon.proto\x1a\x1cgoogle/protobuf/struct.proto\"H\n\x16JoinFaceMonitorRequest\x12\x1a\n\x12\x66\x61\x63\x65_monitor_token\x18\x01 \x01(\t\x12\x12\n\nsession_id\x18\x02 \x01(\t\":\n\x17JoinFaceMonitorResponse\x12\x1f\n\x06status\x18\x01 \x01(\x0b\x32\x0f.message.Status\"\x8c\x01\n\x1a\x46\x61\x63\x65MonitorCallbackRequest\x12\r\n\x05token\x18\x01 \x01(\t\x12\x0f\n\x07success\x18\x02 \x01(\x08\x12\x15\n\rerror_message\x18\x03 \x01(\t\x12\x13\n\x0bis_finished\x18\x04 \x01(\x08\x12\x0e\n\x06\x61\x63tion\x18\x05 \x01(\t\x12\x12\n\nface_codes\x18\x06 \x03(\t\">\n\x1b\x46\x61\x63\x65MonitorCallbackResponse\x12\x1f\n\x06status\x18\x01 \x01(\x0b\x32\x0f.message.Status\"j\n\x1e\x46\x61\x63\x65RecognitionCallbackRequest\x12\r\n\x05token\x18\x01 \x01(\t\x12\x0f\n\x07success\x18\x02 \x01(\x08\x12\x15\n\rerror_message\x18\x03 \x01(\t\x12\x11\n\tface_code\x18\x04 \x01(\t\"B\n\x1f\x46\x61\x63\x65RecognitionCallbackResponse\x12\x1f\n\x06status\x18\x01 \x01(\x0b\x32\x0f.message.Status\"V\n\x17\x41ssetLoginTicketRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x10\n\x08\x61sset_id\x18\x02 \x01(\t\x12\x18\n\x10\x61\x63\x63ount_username\x18\x04 \x01(\t\"\x8e\x01\n\x18\x41ssetLoginTicketResponse\x12\x1f\n\x06status\x18\x01 \x01(\x0b\x32\x0f.message.Status\x12(\n\x0bticket_info\x18\x02 \x01(\x0b\x32\x13.message.TicketInfo\x12\x14\n\x0cneed_confirm\x18\x03 \x01(\x08\x12\x11\n\tticket_id\x18\x04 \x01(\t\"!\n\x06Status\x12\n\n\x02ok\x18\x01 \x01(\x08\x12\x0b\n\x03\x65rr\x18\x02 \x01(\t\"\x1d\n\x0cTokenRequest\x12\r\n\x05token\x18\x01 \x01(\t\"V\n\rTokenResponse\x12\x1f\n\x06status\x18\x01 \x01(\x0b\x32\x0f.message.Status\x12$\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x16.message.TokenAuthInfo\"6\n\x14SessionCreateRequest\x12\x1e\n\x04\x64\x61ta\x18\x01 \x01(\x0b\x32\x10.message.Session\"X\n\x15SessionCreateResponse\x12\x1f\n\x06status\x18\x01 \x01(\x0b\x32\x0f.message.Status\x12\x1e\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x10.message.Session\"R\n\x14SessionFinishRequest\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0f\n\x07success\x18\x02 \x01(\x08\x12\x10\n\x08\x64\x61te_end\x18\x03 \x01(\x03\x12\x0b\n\x03\x65rr\x18\x04 \x01(\t\"4\n\x11SessionFinishResp\x12\x1f\n\x06status\x18\x01 \x01(\x0b\x32\x0f.message.Status\"=\n\rReplayRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x18\n\x10replay_file_path\x18\x02 \x01(\t\"1\n\x0eReplayResponse\x12\x1f\n\x06status\x18\x01 \x01(\x0b\x32\x0f.message.Status\"\xdf\x01\n\x0e\x43ommandRequest\x12\x0b\n\x03sid\x18\x01 \x01(\t\x12\x0e\n\x06org_id\x18\x02 \x01(\t\x12\r\n\x05input\x18\x03 \x01(\t\x12\x0e\n\x06output\x18\x04 \x01(\t\x12\x0c\n\x04user\x18\x05 \x01(\t\x12\r\n\x05\x61sset\x18\x06 \x01(\t\x12\x0f\n\x07\x61\x63\x63ount\x18\x07 \x01(\t\x12\x11\n\ttimestamp\x18\x08 \x01(\x03\x12&\n\nrisk_level\x18\t \x01(\x0e\x32\x12.message.RiskLevel\x12\x12\n\ncmd_acl_id\x18\n \x01(\t\x12\x14\n\x0c\x63md_group_id\x18\x0b \x01(\t\"2\n\x0f\x43ommandResponse\x12\x1f\n\x06status\x18\x01 \x01(\x0b\x32\x0f.message.Status\"&\n\x13\x46inishedTaskRequest\x12\x0f\n\x07task_id\x18\x01 \x01(\t\"3\n\x0cTaskResponse\x12#\n\x04task\x18\x01 \x01(\x0b\x32\x15.message.TerminalTask\")\n\x13RemainReplayRequest\x12\x12\n\nreplay_dir\x18\x01 \x01(\t\"{\n\x14RemainReplayResponse\x12\x1f\n\x06status\x18\x01 \x01(\x0b\x32\x0f.message.Status\x12\x15\n\rsuccess_files\x18\x02 \x03(\t\x12\x15\n\rfailure_files\x18\x03 \x03(\t\x12\x14\n\x0c\x66\x61ilure_errs\x18\x04 \x03(\t\"1\n\x0eStatusResponse\x12\x1f\n\x06status\x18\x01 \x01(\x0b\x32\x0f.message.Status\"L\n\x15\x43ommandConfirmRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x12\n\ncmd_acl_id\x18\x02 \x01(\t\x12\x0b\n\x03\x63md\x18\x03 \x01(\t\"&\n\x07ReqInfo\x12\x0e\n\x06method\x18\x01 \x01(\t\x12\x0b\n\x03url\x18\x02 \x01(\t\"\\\n\x16\x43ommandConfirmResponse\x12\x1f\n\x06status\x18\x01 \x01(\x0b\x32\x0f.message.Status\x12!\n\x04info\x18\x02 \x01(\x0b\x32\x13.message.TicketInfo\"\x85\x01\n\nTicketInfo\x12#\n\tcheck_req\x18\x01 \x01(\x0b\x32\x10.message.ReqInfo\x12$\n\ncancel_req\x18\x02 \x01(\x0b\x32\x10.message.ReqInfo\x12\x19\n\x11ticket_detail_url\x18\x03 \x01(\t\x12\x11\n\treviewers\x18\x04 \x03(\t\".\n\rTicketRequest\x12\x1d\n\x03req\x18\x01 \x01(\x0b\x32\x10.message.ReqInfo\"Z\n\x13TicketStateResponse\x12\"\n\x04\x44\x61ta\x18\x01 \x01(\x0b\x32\x14.message.TicketState\x12\x1f\n\x06status\x18\x02 \x01(\x0b\x32\x0f.message.Status\"\x86\x01\n\x0bTicketState\x12)\n\x05state\x18\x01 \x01(\x0e\x32\x1a.message.TicketState.State\x12\x11\n\tprocessor\x18\x02 \x01(\t\"9\n\x05State\x12\x08\n\x04Open\x10\x00\x12\x0c\n\x08\x41pproved\x10\x01\x12\x0c\n\x08Rejected\x10\x02\x12\n\n\x06\x43losed\x10\x03\"P\n\x0e\x46orwardRequest\x12\x0c\n\x04host\x18\x01 \x01(\t\x12\x0c\n\x04port\x18\x02 \x01(\x05\x12\"\n\x08gateways\x18\x03 \x03(\x0b\x32\x10.message.Gateway\"\"\n\x14\x46orwardDeleteRequest\x12\n\n\x02id\x18\x01 \x01(\t\"Z\n\x0f\x46orwardResponse\x12\x1f\n\x06status\x18\x01 \x01(\x0b\x32\x0f.message.Status\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0c\n\x04host\x18\x03 \x01(\t\x12\x0c\n\x04port\x18\x04 \x01(\x05\"^\n\x15PublicSettingResponse\x12\x1f\n\x06status\x18\x01 \x01(\x0b\x32\x0f.message.Status\x12$\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x16.message.PublicSetting\"\x07\n\x05\x45mpty\"D\n\x12ListenPortResponse\x12\x1f\n\x06status\x18\x01 \x01(\x0b\x32\x0f.message.Status\x12\r\n\x05ports\x18\x02 \x03(\x05\"\x1f\n\x0fPortInfoRequest\x12\x0c\n\x04port\x18\x01 \x01(\x05\"T\n\x10PortInfoResponse\x12\x1f\n\x06status\x18\x01 \x01(\x0b\x32\x0f.message.Status\x12\x1f\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x11.message.PortInfo\"M\n\x08PortInfo\x12\x1d\n\x05\x61sset\x18\x01 \x01(\x0b\x32\x0e.message.Asset\x12\"\n\x08gateways\x18\x02 \x03(\x0b\x32\x10.message.Gateway\"+\n\x0bPortFailure\x12\x0c\n\x04port\x18\x01 \x01(\x05\x12\x0e\n\x06reason\x18\x02 \x01(\t\"8\n\x12PortFailureRequest\x12\"\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x14.message.PortFailure\"2\n\x0e\x43ookiesRequest\x12 \n\x07\x63ookies\x18\x01 \x03(\x0b\x32\x0f.message.Cookie\"L\n\x0cUserResponse\x12\x1f\n\x06status\x18\x01 \x01(\x0b\x32\x0f.message.Status\x12\x1b\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\r.message.User\"\xce\x03\n\x1aSessionLifecycleLogRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12<\n\x05\x65vent\x18\x02 \x01(\x0e\x32-.message.SessionLifecycleLogRequest.EventType\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x0c\n\x04user\x18\x04 \x01(\t\"\xbf\x02\n\tEventType\x12\x17\n\x13\x41ssetConnectSuccess\x10\x00\x12\x18\n\x14\x41ssetConnectFinished\x10\x01\x12\x13\n\x0f\x43reateShareLink\x10\x02\x12\x13\n\x0fUserJoinSession\x10\x03\x12\x14\n\x10UserLeaveSession\x10\x04\x12\x14\n\x10\x41\x64minJoinMonitor\x10\x05\x12\x14\n\x10\x41\x64minExitMonitor\x10\x06\x12\x16\n\x12ReplayConvertStart\x10\x07\x12\x18\n\x14ReplayConvertSuccess\x10\x08\x12\x18\n\x14ReplayConvertFailure\x10\t\x12\x15\n\x11ReplayUploadStart\x10\n\x12\x17\n\x13ReplayUploadSuccess\x10\x0b\x12\x17\n\x13ReplayUploadFailure\x10\x0c\"b\n\x15\x41\x63\x63ountDetailResponse\x12\x1f\n\x06status\x18\x01 \x01(\x0b\x32\x0f.message.Status\x12(\n\x07payload\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct\"\xf8\x01\n\x0bHTTPRequest\x12\x0e\n\x06method\x18\x01 \x01(\t\x12\x0c\n\x04path\x18\x02 \x01(\t\x12.\n\x05query\x18\x03 \x03(\x0b\x32\x1f.message.HTTPRequest.QueryEntry\x12\x30\n\x06header\x18\x04 \x03(\x0b\x32 .message.HTTPRequest.HeaderEntry\x12\x0c\n\x04\x62ody\x18\x05 \x01(\x0c\x1a,\n\nQueryEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a-\n\x0bHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"=\n\x0cHTTPResponse\x12\x1f\n\x06status\x18\x01 \x01(\x0b\x32\x0f.message.Status\x12\x0c\n\x04\x62ody\x18\x02 \x01(\x0c\x32\xa5\x0f\n\x07Service\x12\x43\n\x10GetTokenAuthInfo\x12\x15.message.TokenRequest\x1a\x16.message.TokenResponse\"\x00\x12>\n\nRenewToken\x12\x15.message.TokenRequest\x1a\x17.message.StatusResponse\"\x00\x12P\n\rCreateSession\x12\x1d.message.SessionCreateRequest\x1a\x1e.message.SessionCreateResponse\"\x00\x12L\n\rFinishSession\x12\x1d.message.SessionFinishRequest\x1a\x1a.message.SessionFinishResp\"\x00\x12\x45\n\x10UploadReplayFile\x12\x16.message.ReplayRequest\x1a\x17.message.ReplayResponse\"\x00\x12\x44\n\rUploadCommand\x12\x17.message.CommandRequest\x1a\x18.message.CommandResponse\"\x00\x12I\n\x0c\x44ispatchTask\x12\x1c.message.FinishedTaskRequest\x1a\x15.message.TaskResponse\"\x00(\x01\x30\x01\x12R\n\x11ScanRemainReplays\x12\x1c.message.RemainReplayRequest\x1a\x1d.message.RemainReplayResponse\"\x00\x12X\n\x13\x43reateCommandTicket\x12\x1e.message.CommandConfirmRequest\x1a\x1f.message.CommandConfirmResponse\"\x00\x12\x66\n\x1d\x43heckOrCreateAssetLoginTicket\x12 .message.AssetLoginTicketRequest\x1a!.message.AssetLoginTicketResponse\"\x00\x12J\n\x10\x43heckTicketState\x12\x16.message.TicketRequest\x1a\x1c.message.TicketStateResponse\"\x00\x12\x41\n\x0c\x43\x61ncelTicket\x12\x16.message.TicketRequest\x1a\x17.message.StatusResponse\"\x00\x12\x44\n\rCreateForward\x12\x17.message.ForwardRequest\x1a\x18.message.ForwardResponse\"\x00\x12I\n\rDeleteForward\x12\x1d.message.ForwardDeleteRequest\x1a\x17.message.StatusResponse\"\x00\x12\x44\n\x10GetPublicSetting\x12\x0e.message.Empty\x1a\x1e.message.PublicSettingResponse\"\x00\x12?\n\x0eGetListenPorts\x12\x0e.message.Empty\x1a\x1b.message.ListenPortResponse\"\x00\x12\x44\n\x0bGetPortInfo\x12\x18.message.PortInfoRequest\x1a\x19.message.PortInfoResponse\"\x00\x12K\n\x11HandlePortFailure\x12\x1b.message.PortFailureRequest\x1a\x17.message.StatusResponse\"\x00\x12\x46\n\x12\x43heckUserByCookies\x12\x17.message.CookiesRequest\x1a\x15.message.UserResponse\"\x00\x12[\n\x19RecordSessionLifecycleLog\x12#.message.SessionLifecycleLogRequest\x1a\x17.message.StatusResponse\"\x00\x12n\n\x17\x46\x61\x63\x65RecognitionCallback\x12\'.message.FaceRecognitionCallbackRequest\x1a(.message.FaceRecognitionCallbackResponse\"\x00\x12\x62\n\x13\x46\x61\x63\x65MonitorCallback\x12#.message.FaceMonitorCallbackRequest\x1a$.message.FaceMonitorCallbackResponse\"\x00\x12V\n\x0fJoinFaceMonitor\x12\x1f.message.JoinFaceMonitorRequest\x1a .message.JoinFaceMonitorResponse\"\x00\x12\x42\n\x0eGetAccountChat\x12\x0e.message.Empty\x1a\x1e.message.AccountDetailResponse\"\x00\x12\x38\n\x07\x43\x61llAPI\x12\x14.message.HTTPRequest\x1a\x15.message.HTTPResponse\"\x00\x42 \n\x13org.jumpserver.wispZ\t/protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'service_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\023org.jumpserver.wispZ\t/protobuf'
+ _globals['_HTTPREQUEST_QUERYENTRY']._loaded_options = None
+ _globals['_HTTPREQUEST_QUERYENTRY']._serialized_options = b'8\001'
+ _globals['_HTTPREQUEST_HEADERENTRY']._loaded_options = None
+ _globals['_HTTPREQUEST_HEADERENTRY']._serialized_options = b'8\001'
+ _globals['_JOINFACEMONITORREQUEST']._serialized_start=70
+ _globals['_JOINFACEMONITORREQUEST']._serialized_end=142
+ _globals['_JOINFACEMONITORRESPONSE']._serialized_start=144
+ _globals['_JOINFACEMONITORRESPONSE']._serialized_end=202
+ _globals['_FACEMONITORCALLBACKREQUEST']._serialized_start=205
+ _globals['_FACEMONITORCALLBACKREQUEST']._serialized_end=345
+ _globals['_FACEMONITORCALLBACKRESPONSE']._serialized_start=347
+ _globals['_FACEMONITORCALLBACKRESPONSE']._serialized_end=409
+ _globals['_FACERECOGNITIONCALLBACKREQUEST']._serialized_start=411
+ _globals['_FACERECOGNITIONCALLBACKREQUEST']._serialized_end=517
+ _globals['_FACERECOGNITIONCALLBACKRESPONSE']._serialized_start=519
+ _globals['_FACERECOGNITIONCALLBACKRESPONSE']._serialized_end=585
+ _globals['_ASSETLOGINTICKETREQUEST']._serialized_start=587
+ _globals['_ASSETLOGINTICKETREQUEST']._serialized_end=673
+ _globals['_ASSETLOGINTICKETRESPONSE']._serialized_start=676
+ _globals['_ASSETLOGINTICKETRESPONSE']._serialized_end=818
+ _globals['_STATUS']._serialized_start=820
+ _globals['_STATUS']._serialized_end=853
+ _globals['_TOKENREQUEST']._serialized_start=855
+ _globals['_TOKENREQUEST']._serialized_end=884
+ _globals['_TOKENRESPONSE']._serialized_start=886
+ _globals['_TOKENRESPONSE']._serialized_end=972
+ _globals['_SESSIONCREATEREQUEST']._serialized_start=974
+ _globals['_SESSIONCREATEREQUEST']._serialized_end=1028
+ _globals['_SESSIONCREATERESPONSE']._serialized_start=1030
+ _globals['_SESSIONCREATERESPONSE']._serialized_end=1118
+ _globals['_SESSIONFINISHREQUEST']._serialized_start=1120
+ _globals['_SESSIONFINISHREQUEST']._serialized_end=1202
+ _globals['_SESSIONFINISHRESP']._serialized_start=1204
+ _globals['_SESSIONFINISHRESP']._serialized_end=1256
+ _globals['_REPLAYREQUEST']._serialized_start=1258
+ _globals['_REPLAYREQUEST']._serialized_end=1319
+ _globals['_REPLAYRESPONSE']._serialized_start=1321
+ _globals['_REPLAYRESPONSE']._serialized_end=1370
+ _globals['_COMMANDREQUEST']._serialized_start=1373
+ _globals['_COMMANDREQUEST']._serialized_end=1596
+ _globals['_COMMANDRESPONSE']._serialized_start=1598
+ _globals['_COMMANDRESPONSE']._serialized_end=1648
+ _globals['_FINISHEDTASKREQUEST']._serialized_start=1650
+ _globals['_FINISHEDTASKREQUEST']._serialized_end=1688
+ _globals['_TASKRESPONSE']._serialized_start=1690
+ _globals['_TASKRESPONSE']._serialized_end=1741
+ _globals['_REMAINREPLAYREQUEST']._serialized_start=1743
+ _globals['_REMAINREPLAYREQUEST']._serialized_end=1784
+ _globals['_REMAINREPLAYRESPONSE']._serialized_start=1786
+ _globals['_REMAINREPLAYRESPONSE']._serialized_end=1909
+ _globals['_STATUSRESPONSE']._serialized_start=1911
+ _globals['_STATUSRESPONSE']._serialized_end=1960
+ _globals['_COMMANDCONFIRMREQUEST']._serialized_start=1962
+ _globals['_COMMANDCONFIRMREQUEST']._serialized_end=2038
+ _globals['_REQINFO']._serialized_start=2040
+ _globals['_REQINFO']._serialized_end=2078
+ _globals['_COMMANDCONFIRMRESPONSE']._serialized_start=2080
+ _globals['_COMMANDCONFIRMRESPONSE']._serialized_end=2172
+ _globals['_TICKETINFO']._serialized_start=2175
+ _globals['_TICKETINFO']._serialized_end=2308
+ _globals['_TICKETREQUEST']._serialized_start=2310
+ _globals['_TICKETREQUEST']._serialized_end=2356
+ _globals['_TICKETSTATERESPONSE']._serialized_start=2358
+ _globals['_TICKETSTATERESPONSE']._serialized_end=2448
+ _globals['_TICKETSTATE']._serialized_start=2451
+ _globals['_TICKETSTATE']._serialized_end=2585
+ _globals['_TICKETSTATE_STATE']._serialized_start=2528
+ _globals['_TICKETSTATE_STATE']._serialized_end=2585
+ _globals['_FORWARDREQUEST']._serialized_start=2587
+ _globals['_FORWARDREQUEST']._serialized_end=2667
+ _globals['_FORWARDDELETEREQUEST']._serialized_start=2669
+ _globals['_FORWARDDELETEREQUEST']._serialized_end=2703
+ _globals['_FORWARDRESPONSE']._serialized_start=2705
+ _globals['_FORWARDRESPONSE']._serialized_end=2795
+ _globals['_PUBLICSETTINGRESPONSE']._serialized_start=2797
+ _globals['_PUBLICSETTINGRESPONSE']._serialized_end=2891
+ _globals['_EMPTY']._serialized_start=2893
+ _globals['_EMPTY']._serialized_end=2900
+ _globals['_LISTENPORTRESPONSE']._serialized_start=2902
+ _globals['_LISTENPORTRESPONSE']._serialized_end=2970
+ _globals['_PORTINFOREQUEST']._serialized_start=2972
+ _globals['_PORTINFOREQUEST']._serialized_end=3003
+ _globals['_PORTINFORESPONSE']._serialized_start=3005
+ _globals['_PORTINFORESPONSE']._serialized_end=3089
+ _globals['_PORTINFO']._serialized_start=3091
+ _globals['_PORTINFO']._serialized_end=3168
+ _globals['_PORTFAILURE']._serialized_start=3170
+ _globals['_PORTFAILURE']._serialized_end=3213
+ _globals['_PORTFAILUREREQUEST']._serialized_start=3215
+ _globals['_PORTFAILUREREQUEST']._serialized_end=3271
+ _globals['_COOKIESREQUEST']._serialized_start=3273
+ _globals['_COOKIESREQUEST']._serialized_end=3323
+ _globals['_USERRESPONSE']._serialized_start=3325
+ _globals['_USERRESPONSE']._serialized_end=3401
+ _globals['_SESSIONLIFECYCLELOGREQUEST']._serialized_start=3404
+ _globals['_SESSIONLIFECYCLELOGREQUEST']._serialized_end=3866
+ _globals['_SESSIONLIFECYCLELOGREQUEST_EVENTTYPE']._serialized_start=3547
+ _globals['_SESSIONLIFECYCLELOGREQUEST_EVENTTYPE']._serialized_end=3866
+ _globals['_ACCOUNTDETAILRESPONSE']._serialized_start=3868
+ _globals['_ACCOUNTDETAILRESPONSE']._serialized_end=3966
+ _globals['_HTTPREQUEST']._serialized_start=3969
+ _globals['_HTTPREQUEST']._serialized_end=4217
+ _globals['_HTTPREQUEST_QUERYENTRY']._serialized_start=4126
+ _globals['_HTTPREQUEST_QUERYENTRY']._serialized_end=4170
+ _globals['_HTTPREQUEST_HEADERENTRY']._serialized_start=4172
+ _globals['_HTTPREQUEST_HEADERENTRY']._serialized_end=4217
+ _globals['_HTTPRESPONSE']._serialized_start=4219
+ _globals['_HTTPRESPONSE']._serialized_end=4280
+ _globals['_SERVICE']._serialized_start=4283
+ _globals['_SERVICE']._serialized_end=6240
+# @@protoc_insertion_point(module_scope)
diff --git a/backend/open_webui/jms/wisp/protobuf/service_pb2.pyi b/backend/open_webui/jms/wisp/protobuf/service_pb2.pyi
new file mode 100644
index 000000000000..8c1dcbe835aa
--- /dev/null
+++ b/backend/open_webui/jms/wisp/protobuf/service_pb2.pyi
@@ -0,0 +1,473 @@
+import common_pb2 as _common_pb2
+from google.protobuf import struct_pb2 as _struct_pb2
+from google.protobuf.internal import containers as _containers
+from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union
+
+DESCRIPTOR: _descriptor.FileDescriptor
+
+class JoinFaceMonitorRequest(_message.Message):
+ __slots__ = ("face_monitor_token", "session_id")
+ FACE_MONITOR_TOKEN_FIELD_NUMBER: _ClassVar[int]
+ SESSION_ID_FIELD_NUMBER: _ClassVar[int]
+ face_monitor_token: str
+ session_id: str
+ def __init__(self, face_monitor_token: _Optional[str] = ..., session_id: _Optional[str] = ...) -> None: ...
+
+class JoinFaceMonitorResponse(_message.Message):
+ __slots__ = ("status",)
+ STATUS_FIELD_NUMBER: _ClassVar[int]
+ status: Status
+ def __init__(self, status: _Optional[_Union[Status, _Mapping]] = ...) -> None: ...
+
+class FaceMonitorCallbackRequest(_message.Message):
+ __slots__ = ("token", "success", "error_message", "is_finished", "action", "face_codes")
+ TOKEN_FIELD_NUMBER: _ClassVar[int]
+ SUCCESS_FIELD_NUMBER: _ClassVar[int]
+ ERROR_MESSAGE_FIELD_NUMBER: _ClassVar[int]
+ IS_FINISHED_FIELD_NUMBER: _ClassVar[int]
+ ACTION_FIELD_NUMBER: _ClassVar[int]
+ FACE_CODES_FIELD_NUMBER: _ClassVar[int]
+ token: str
+ success: bool
+ error_message: str
+ is_finished: bool
+ action: str
+ face_codes: _containers.RepeatedScalarFieldContainer[str]
+ def __init__(self, token: _Optional[str] = ..., success: bool = ..., error_message: _Optional[str] = ..., is_finished: bool = ..., action: _Optional[str] = ..., face_codes: _Optional[_Iterable[str]] = ...) -> None: ...
+
+class FaceMonitorCallbackResponse(_message.Message):
+ __slots__ = ("status",)
+ STATUS_FIELD_NUMBER: _ClassVar[int]
+ status: Status
+ def __init__(self, status: _Optional[_Union[Status, _Mapping]] = ...) -> None: ...
+
+class FaceRecognitionCallbackRequest(_message.Message):
+ __slots__ = ("token", "success", "error_message", "face_code")
+ TOKEN_FIELD_NUMBER: _ClassVar[int]
+ SUCCESS_FIELD_NUMBER: _ClassVar[int]
+ ERROR_MESSAGE_FIELD_NUMBER: _ClassVar[int]
+ FACE_CODE_FIELD_NUMBER: _ClassVar[int]
+ token: str
+ success: bool
+ error_message: str
+ face_code: str
+ def __init__(self, token: _Optional[str] = ..., success: bool = ..., error_message: _Optional[str] = ..., face_code: _Optional[str] = ...) -> None: ...
+
+class FaceRecognitionCallbackResponse(_message.Message):
+ __slots__ = ("status",)
+ STATUS_FIELD_NUMBER: _ClassVar[int]
+ status: Status
+ def __init__(self, status: _Optional[_Union[Status, _Mapping]] = ...) -> None: ...
+
+class AssetLoginTicketRequest(_message.Message):
+ __slots__ = ("user_id", "asset_id", "account_username")
+ USER_ID_FIELD_NUMBER: _ClassVar[int]
+ ASSET_ID_FIELD_NUMBER: _ClassVar[int]
+ ACCOUNT_USERNAME_FIELD_NUMBER: _ClassVar[int]
+ user_id: str
+ asset_id: str
+ account_username: str
+ def __init__(self, user_id: _Optional[str] = ..., asset_id: _Optional[str] = ..., account_username: _Optional[str] = ...) -> None: ...
+
+class AssetLoginTicketResponse(_message.Message):
+ __slots__ = ("status", "ticket_info", "need_confirm", "ticket_id")
+ STATUS_FIELD_NUMBER: _ClassVar[int]
+ TICKET_INFO_FIELD_NUMBER: _ClassVar[int]
+ NEED_CONFIRM_FIELD_NUMBER: _ClassVar[int]
+ TICKET_ID_FIELD_NUMBER: _ClassVar[int]
+ status: Status
+ ticket_info: TicketInfo
+ need_confirm: bool
+ ticket_id: str
+ def __init__(self, status: _Optional[_Union[Status, _Mapping]] = ..., ticket_info: _Optional[_Union[TicketInfo, _Mapping]] = ..., need_confirm: bool = ..., ticket_id: _Optional[str] = ...) -> None: ...
+
+class Status(_message.Message):
+ __slots__ = ("ok", "err")
+ OK_FIELD_NUMBER: _ClassVar[int]
+ ERR_FIELD_NUMBER: _ClassVar[int]
+ ok: bool
+ err: str
+ def __init__(self, ok: bool = ..., err: _Optional[str] = ...) -> None: ...
+
+class TokenRequest(_message.Message):
+ __slots__ = ("token",)
+ TOKEN_FIELD_NUMBER: _ClassVar[int]
+ token: str
+ def __init__(self, token: _Optional[str] = ...) -> None: ...
+
+class TokenResponse(_message.Message):
+ __slots__ = ("status", "data")
+ STATUS_FIELD_NUMBER: _ClassVar[int]
+ DATA_FIELD_NUMBER: _ClassVar[int]
+ status: Status
+ data: _common_pb2.TokenAuthInfo
+ def __init__(self, status: _Optional[_Union[Status, _Mapping]] = ..., data: _Optional[_Union[_common_pb2.TokenAuthInfo, _Mapping]] = ...) -> None: ...
+
+class SessionCreateRequest(_message.Message):
+ __slots__ = ("data",)
+ DATA_FIELD_NUMBER: _ClassVar[int]
+ data: _common_pb2.Session
+ def __init__(self, data: _Optional[_Union[_common_pb2.Session, _Mapping]] = ...) -> None: ...
+
+class SessionCreateResponse(_message.Message):
+ __slots__ = ("status", "data")
+ STATUS_FIELD_NUMBER: _ClassVar[int]
+ DATA_FIELD_NUMBER: _ClassVar[int]
+ status: Status
+ data: _common_pb2.Session
+ def __init__(self, status: _Optional[_Union[Status, _Mapping]] = ..., data: _Optional[_Union[_common_pb2.Session, _Mapping]] = ...) -> None: ...
+
+class SessionFinishRequest(_message.Message):
+ __slots__ = ("id", "success", "date_end", "err")
+ ID_FIELD_NUMBER: _ClassVar[int]
+ SUCCESS_FIELD_NUMBER: _ClassVar[int]
+ DATE_END_FIELD_NUMBER: _ClassVar[int]
+ ERR_FIELD_NUMBER: _ClassVar[int]
+ id: str
+ success: bool
+ date_end: int
+ err: str
+ def __init__(self, id: _Optional[str] = ..., success: bool = ..., date_end: _Optional[int] = ..., err: _Optional[str] = ...) -> None: ...
+
+class SessionFinishResp(_message.Message):
+ __slots__ = ("status",)
+ STATUS_FIELD_NUMBER: _ClassVar[int]
+ status: Status
+ def __init__(self, status: _Optional[_Union[Status, _Mapping]] = ...) -> None: ...
+
+class ReplayRequest(_message.Message):
+ __slots__ = ("session_id", "replay_file_path")
+ SESSION_ID_FIELD_NUMBER: _ClassVar[int]
+ REPLAY_FILE_PATH_FIELD_NUMBER: _ClassVar[int]
+ session_id: str
+ replay_file_path: str
+ def __init__(self, session_id: _Optional[str] = ..., replay_file_path: _Optional[str] = ...) -> None: ...
+
+class ReplayResponse(_message.Message):
+ __slots__ = ("status",)
+ STATUS_FIELD_NUMBER: _ClassVar[int]
+ status: Status
+ def __init__(self, status: _Optional[_Union[Status, _Mapping]] = ...) -> None: ...
+
+class CommandRequest(_message.Message):
+ __slots__ = ("sid", "org_id", "input", "output", "user", "asset", "account", "timestamp", "risk_level", "cmd_acl_id", "cmd_group_id")
+ SID_FIELD_NUMBER: _ClassVar[int]
+ ORG_ID_FIELD_NUMBER: _ClassVar[int]
+ INPUT_FIELD_NUMBER: _ClassVar[int]
+ OUTPUT_FIELD_NUMBER: _ClassVar[int]
+ USER_FIELD_NUMBER: _ClassVar[int]
+ ASSET_FIELD_NUMBER: _ClassVar[int]
+ ACCOUNT_FIELD_NUMBER: _ClassVar[int]
+ TIMESTAMP_FIELD_NUMBER: _ClassVar[int]
+ RISK_LEVEL_FIELD_NUMBER: _ClassVar[int]
+ CMD_ACL_ID_FIELD_NUMBER: _ClassVar[int]
+ CMD_GROUP_ID_FIELD_NUMBER: _ClassVar[int]
+ sid: str
+ org_id: str
+ input: str
+ output: str
+ user: str
+ asset: str
+ account: str
+ timestamp: int
+ risk_level: _common_pb2.RiskLevel
+ cmd_acl_id: str
+ cmd_group_id: str
+ def __init__(self, sid: _Optional[str] = ..., org_id: _Optional[str] = ..., input: _Optional[str] = ..., output: _Optional[str] = ..., user: _Optional[str] = ..., asset: _Optional[str] = ..., account: _Optional[str] = ..., timestamp: _Optional[int] = ..., risk_level: _Optional[_Union[_common_pb2.RiskLevel, str]] = ..., cmd_acl_id: _Optional[str] = ..., cmd_group_id: _Optional[str] = ...) -> None: ...
+
+class CommandResponse(_message.Message):
+ __slots__ = ("status",)
+ STATUS_FIELD_NUMBER: _ClassVar[int]
+ status: Status
+ def __init__(self, status: _Optional[_Union[Status, _Mapping]] = ...) -> None: ...
+
+class FinishedTaskRequest(_message.Message):
+ __slots__ = ("task_id",)
+ TASK_ID_FIELD_NUMBER: _ClassVar[int]
+ task_id: str
+ def __init__(self, task_id: _Optional[str] = ...) -> None: ...
+
+class TaskResponse(_message.Message):
+ __slots__ = ("task",)
+ TASK_FIELD_NUMBER: _ClassVar[int]
+ task: _common_pb2.TerminalTask
+ def __init__(self, task: _Optional[_Union[_common_pb2.TerminalTask, _Mapping]] = ...) -> None: ...
+
+class RemainReplayRequest(_message.Message):
+ __slots__ = ("replay_dir",)
+ REPLAY_DIR_FIELD_NUMBER: _ClassVar[int]
+ replay_dir: str
+ def __init__(self, replay_dir: _Optional[str] = ...) -> None: ...
+
+class RemainReplayResponse(_message.Message):
+ __slots__ = ("status", "success_files", "failure_files", "failure_errs")
+ STATUS_FIELD_NUMBER: _ClassVar[int]
+ SUCCESS_FILES_FIELD_NUMBER: _ClassVar[int]
+ FAILURE_FILES_FIELD_NUMBER: _ClassVar[int]
+ FAILURE_ERRS_FIELD_NUMBER: _ClassVar[int]
+ status: Status
+ success_files: _containers.RepeatedScalarFieldContainer[str]
+ failure_files: _containers.RepeatedScalarFieldContainer[str]
+ failure_errs: _containers.RepeatedScalarFieldContainer[str]
+ def __init__(self, status: _Optional[_Union[Status, _Mapping]] = ..., success_files: _Optional[_Iterable[str]] = ..., failure_files: _Optional[_Iterable[str]] = ..., failure_errs: _Optional[_Iterable[str]] = ...) -> None: ...
+
+class StatusResponse(_message.Message):
+ __slots__ = ("status",)
+ STATUS_FIELD_NUMBER: _ClassVar[int]
+ status: Status
+ def __init__(self, status: _Optional[_Union[Status, _Mapping]] = ...) -> None: ...
+
+class CommandConfirmRequest(_message.Message):
+ __slots__ = ("session_id", "cmd_acl_id", "cmd")
+ SESSION_ID_FIELD_NUMBER: _ClassVar[int]
+ CMD_ACL_ID_FIELD_NUMBER: _ClassVar[int]
+ CMD_FIELD_NUMBER: _ClassVar[int]
+ session_id: str
+ cmd_acl_id: str
+ cmd: str
+ def __init__(self, session_id: _Optional[str] = ..., cmd_acl_id: _Optional[str] = ..., cmd: _Optional[str] = ...) -> None: ...
+
+class ReqInfo(_message.Message):
+ __slots__ = ("method", "url")
+ METHOD_FIELD_NUMBER: _ClassVar[int]
+ URL_FIELD_NUMBER: _ClassVar[int]
+ method: str
+ url: str
+ def __init__(self, method: _Optional[str] = ..., url: _Optional[str] = ...) -> None: ...
+
+class CommandConfirmResponse(_message.Message):
+ __slots__ = ("status", "info")
+ STATUS_FIELD_NUMBER: _ClassVar[int]
+ INFO_FIELD_NUMBER: _ClassVar[int]
+ status: Status
+ info: TicketInfo
+ def __init__(self, status: _Optional[_Union[Status, _Mapping]] = ..., info: _Optional[_Union[TicketInfo, _Mapping]] = ...) -> None: ...
+
+class TicketInfo(_message.Message):
+ __slots__ = ("check_req", "cancel_req", "ticket_detail_url", "reviewers")
+ CHECK_REQ_FIELD_NUMBER: _ClassVar[int]
+ CANCEL_REQ_FIELD_NUMBER: _ClassVar[int]
+ TICKET_DETAIL_URL_FIELD_NUMBER: _ClassVar[int]
+ REVIEWERS_FIELD_NUMBER: _ClassVar[int]
+ check_req: ReqInfo
+ cancel_req: ReqInfo
+ ticket_detail_url: str
+ reviewers: _containers.RepeatedScalarFieldContainer[str]
+ def __init__(self, check_req: _Optional[_Union[ReqInfo, _Mapping]] = ..., cancel_req: _Optional[_Union[ReqInfo, _Mapping]] = ..., ticket_detail_url: _Optional[str] = ..., reviewers: _Optional[_Iterable[str]] = ...) -> None: ...
+
+class TicketRequest(_message.Message):
+ __slots__ = ("req",)
+ REQ_FIELD_NUMBER: _ClassVar[int]
+ req: ReqInfo
+ def __init__(self, req: _Optional[_Union[ReqInfo, _Mapping]] = ...) -> None: ...
+
+class TicketStateResponse(_message.Message):
+ __slots__ = ("Data", "status")
+ DATA_FIELD_NUMBER: _ClassVar[int]
+ STATUS_FIELD_NUMBER: _ClassVar[int]
+ Data: TicketState
+ status: Status
+ def __init__(self, Data: _Optional[_Union[TicketState, _Mapping]] = ..., status: _Optional[_Union[Status, _Mapping]] = ...) -> None: ...
+
+class TicketState(_message.Message):
+ __slots__ = ("state", "processor")
+ class State(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
+ __slots__ = ()
+ Open: _ClassVar[TicketState.State]
+ Approved: _ClassVar[TicketState.State]
+ Rejected: _ClassVar[TicketState.State]
+ Closed: _ClassVar[TicketState.State]
+ Open: TicketState.State
+ Approved: TicketState.State
+ Rejected: TicketState.State
+ Closed: TicketState.State
+ STATE_FIELD_NUMBER: _ClassVar[int]
+ PROCESSOR_FIELD_NUMBER: _ClassVar[int]
+ state: TicketState.State
+ processor: str
+ def __init__(self, state: _Optional[_Union[TicketState.State, str]] = ..., processor: _Optional[str] = ...) -> None: ...
+
+class ForwardRequest(_message.Message):
+ __slots__ = ("host", "port", "gateways")
+ HOST_FIELD_NUMBER: _ClassVar[int]
+ PORT_FIELD_NUMBER: _ClassVar[int]
+ GATEWAYS_FIELD_NUMBER: _ClassVar[int]
+ host: str
+ port: int
+ gateways: _containers.RepeatedCompositeFieldContainer[_common_pb2.Gateway]
+ def __init__(self, host: _Optional[str] = ..., port: _Optional[int] = ..., gateways: _Optional[_Iterable[_Union[_common_pb2.Gateway, _Mapping]]] = ...) -> None: ...
+
+class ForwardDeleteRequest(_message.Message):
+ __slots__ = ("id",)
+ ID_FIELD_NUMBER: _ClassVar[int]
+ id: str
+ def __init__(self, id: _Optional[str] = ...) -> None: ...
+
+class ForwardResponse(_message.Message):
+ __slots__ = ("status", "id", "host", "port")
+ STATUS_FIELD_NUMBER: _ClassVar[int]
+ ID_FIELD_NUMBER: _ClassVar[int]
+ HOST_FIELD_NUMBER: _ClassVar[int]
+ PORT_FIELD_NUMBER: _ClassVar[int]
+ status: Status
+ id: str
+ host: str
+ port: int
+ def __init__(self, status: _Optional[_Union[Status, _Mapping]] = ..., id: _Optional[str] = ..., host: _Optional[str] = ..., port: _Optional[int] = ...) -> None: ...
+
+class PublicSettingResponse(_message.Message):
+ __slots__ = ("status", "data")
+ STATUS_FIELD_NUMBER: _ClassVar[int]
+ DATA_FIELD_NUMBER: _ClassVar[int]
+ status: Status
+ data: _common_pb2.PublicSetting
+ def __init__(self, status: _Optional[_Union[Status, _Mapping]] = ..., data: _Optional[_Union[_common_pb2.PublicSetting, _Mapping]] = ...) -> None: ...
+
+class Empty(_message.Message):
+ __slots__ = ()
+ def __init__(self) -> None: ...
+
+class ListenPortResponse(_message.Message):
+ __slots__ = ("status", "ports")
+ STATUS_FIELD_NUMBER: _ClassVar[int]
+ PORTS_FIELD_NUMBER: _ClassVar[int]
+ status: Status
+ ports: _containers.RepeatedScalarFieldContainer[int]
+ def __init__(self, status: _Optional[_Union[Status, _Mapping]] = ..., ports: _Optional[_Iterable[int]] = ...) -> None: ...
+
+class PortInfoRequest(_message.Message):
+ __slots__ = ("port",)
+ PORT_FIELD_NUMBER: _ClassVar[int]
+ port: int
+ def __init__(self, port: _Optional[int] = ...) -> None: ...
+
+class PortInfoResponse(_message.Message):
+ __slots__ = ("status", "data")
+ STATUS_FIELD_NUMBER: _ClassVar[int]
+ DATA_FIELD_NUMBER: _ClassVar[int]
+ status: Status
+ data: PortInfo
+ def __init__(self, status: _Optional[_Union[Status, _Mapping]] = ..., data: _Optional[_Union[PortInfo, _Mapping]] = ...) -> None: ...
+
+class PortInfo(_message.Message):
+ __slots__ = ("asset", "gateways")
+ ASSET_FIELD_NUMBER: _ClassVar[int]
+ GATEWAYS_FIELD_NUMBER: _ClassVar[int]
+ asset: _common_pb2.Asset
+ gateways: _containers.RepeatedCompositeFieldContainer[_common_pb2.Gateway]
+ def __init__(self, asset: _Optional[_Union[_common_pb2.Asset, _Mapping]] = ..., gateways: _Optional[_Iterable[_Union[_common_pb2.Gateway, _Mapping]]] = ...) -> None: ...
+
+class PortFailure(_message.Message):
+ __slots__ = ("port", "reason")
+ PORT_FIELD_NUMBER: _ClassVar[int]
+ REASON_FIELD_NUMBER: _ClassVar[int]
+ port: int
+ reason: str
+ def __init__(self, port: _Optional[int] = ..., reason: _Optional[str] = ...) -> None: ...
+
+class PortFailureRequest(_message.Message):
+ __slots__ = ("data",)
+ DATA_FIELD_NUMBER: _ClassVar[int]
+ data: _containers.RepeatedCompositeFieldContainer[PortFailure]
+ def __init__(self, data: _Optional[_Iterable[_Union[PortFailure, _Mapping]]] = ...) -> None: ...
+
+class CookiesRequest(_message.Message):
+ __slots__ = ("cookies",)
+ COOKIES_FIELD_NUMBER: _ClassVar[int]
+ cookies: _containers.RepeatedCompositeFieldContainer[_common_pb2.Cookie]
+ def __init__(self, cookies: _Optional[_Iterable[_Union[_common_pb2.Cookie, _Mapping]]] = ...) -> None: ...
+
+class UserResponse(_message.Message):
+ __slots__ = ("status", "data")
+ STATUS_FIELD_NUMBER: _ClassVar[int]
+ DATA_FIELD_NUMBER: _ClassVar[int]
+ status: Status
+ data: _common_pb2.User
+ def __init__(self, status: _Optional[_Union[Status, _Mapping]] = ..., data: _Optional[_Union[_common_pb2.User, _Mapping]] = ...) -> None: ...
+
+class SessionLifecycleLogRequest(_message.Message):
+ __slots__ = ("session_id", "event", "reason", "user")
+ class EventType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
+ __slots__ = ()
+ AssetConnectSuccess: _ClassVar[SessionLifecycleLogRequest.EventType]
+ AssetConnectFinished: _ClassVar[SessionLifecycleLogRequest.EventType]
+ CreateShareLink: _ClassVar[SessionLifecycleLogRequest.EventType]
+ UserJoinSession: _ClassVar[SessionLifecycleLogRequest.EventType]
+ UserLeaveSession: _ClassVar[SessionLifecycleLogRequest.EventType]
+ AdminJoinMonitor: _ClassVar[SessionLifecycleLogRequest.EventType]
+ AdminExitMonitor: _ClassVar[SessionLifecycleLogRequest.EventType]
+ ReplayConvertStart: _ClassVar[SessionLifecycleLogRequest.EventType]
+ ReplayConvertSuccess: _ClassVar[SessionLifecycleLogRequest.EventType]
+ ReplayConvertFailure: _ClassVar[SessionLifecycleLogRequest.EventType]
+ ReplayUploadStart: _ClassVar[SessionLifecycleLogRequest.EventType]
+ ReplayUploadSuccess: _ClassVar[SessionLifecycleLogRequest.EventType]
+ ReplayUploadFailure: _ClassVar[SessionLifecycleLogRequest.EventType]
+ AssetConnectSuccess: SessionLifecycleLogRequest.EventType
+ AssetConnectFinished: SessionLifecycleLogRequest.EventType
+ CreateShareLink: SessionLifecycleLogRequest.EventType
+ UserJoinSession: SessionLifecycleLogRequest.EventType
+ UserLeaveSession: SessionLifecycleLogRequest.EventType
+ AdminJoinMonitor: SessionLifecycleLogRequest.EventType
+ AdminExitMonitor: SessionLifecycleLogRequest.EventType
+ ReplayConvertStart: SessionLifecycleLogRequest.EventType
+ ReplayConvertSuccess: SessionLifecycleLogRequest.EventType
+ ReplayConvertFailure: SessionLifecycleLogRequest.EventType
+ ReplayUploadStart: SessionLifecycleLogRequest.EventType
+ ReplayUploadSuccess: SessionLifecycleLogRequest.EventType
+ ReplayUploadFailure: SessionLifecycleLogRequest.EventType
+ SESSION_ID_FIELD_NUMBER: _ClassVar[int]
+ EVENT_FIELD_NUMBER: _ClassVar[int]
+ REASON_FIELD_NUMBER: _ClassVar[int]
+ USER_FIELD_NUMBER: _ClassVar[int]
+ session_id: str
+ event: SessionLifecycleLogRequest.EventType
+ reason: str
+ user: str
+ def __init__(self, session_id: _Optional[str] = ..., event: _Optional[_Union[SessionLifecycleLogRequest.EventType, str]] = ..., reason: _Optional[str] = ..., user: _Optional[str] = ...) -> None: ...
+
+class AccountDetailResponse(_message.Message):
+ __slots__ = ("status", "payload")
+ STATUS_FIELD_NUMBER: _ClassVar[int]
+ PAYLOAD_FIELD_NUMBER: _ClassVar[int]
+ status: Status
+ payload: _struct_pb2.Struct
+ def __init__(self, status: _Optional[_Union[Status, _Mapping]] = ..., payload: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ...
+
+class HTTPRequest(_message.Message):
+ __slots__ = ("method", "path", "query", "header", "body")
+ class QueryEntry(_message.Message):
+ __slots__ = ("key", "value")
+ KEY_FIELD_NUMBER: _ClassVar[int]
+ VALUE_FIELD_NUMBER: _ClassVar[int]
+ key: str
+ value: str
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ...
+ class HeaderEntry(_message.Message):
+ __slots__ = ("key", "value")
+ KEY_FIELD_NUMBER: _ClassVar[int]
+ VALUE_FIELD_NUMBER: _ClassVar[int]
+ key: str
+ value: str
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ...
+ METHOD_FIELD_NUMBER: _ClassVar[int]
+ PATH_FIELD_NUMBER: _ClassVar[int]
+ QUERY_FIELD_NUMBER: _ClassVar[int]
+ HEADER_FIELD_NUMBER: _ClassVar[int]
+ BODY_FIELD_NUMBER: _ClassVar[int]
+ method: str
+ path: str
+ query: _containers.ScalarMap[str, str]
+ header: _containers.ScalarMap[str, str]
+ body: bytes
+ def __init__(self, method: _Optional[str] = ..., path: _Optional[str] = ..., query: _Optional[_Mapping[str, str]] = ..., header: _Optional[_Mapping[str, str]] = ..., body: _Optional[bytes] = ...) -> None: ...
+
+class HTTPResponse(_message.Message):
+ __slots__ = ("status", "body")
+ STATUS_FIELD_NUMBER: _ClassVar[int]
+ BODY_FIELD_NUMBER: _ClassVar[int]
+ status: Status
+ body: bytes
+ def __init__(self, status: _Optional[_Union[Status, _Mapping]] = ..., body: _Optional[bytes] = ...) -> None: ...
diff --git a/backend/open_webui/jms/wisp/protobuf/service_pb2_grpc.py b/backend/open_webui/jms/wisp/protobuf/service_pb2_grpc.py
new file mode 100644
index 000000000000..98bdde67d8ce
--- /dev/null
+++ b/backend/open_webui/jms/wisp/protobuf/service_pb2_grpc.py
@@ -0,0 +1,1129 @@
+# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
+"""Client and server classes corresponding to protobuf-defined services."""
+import grpc
+import warnings
+
+import service_pb2 as service__pb2
+
+GRPC_GENERATED_VERSION = '1.69.0'
+GRPC_VERSION = grpc.__version__
+_version_not_supported = False
+
+try:
+ from grpc._utilities import first_version_is_lower
+ _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
+except ImportError:
+ _version_not_supported = True
+
+if _version_not_supported:
+ raise RuntimeError(
+ f'The grpc package installed is at version {GRPC_VERSION},'
+ + f' but the generated code in service_pb2_grpc.py depends on'
+ + f' grpcio>={GRPC_GENERATED_VERSION}.'
+ + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
+ + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
+ )
+
+
+class ServiceStub(object):
+ """Missing associated documentation comment in .proto file."""
+
+ def __init__(self, channel):
+ """Constructor.
+
+ Args:
+ channel: A grpc.Channel.
+ """
+ self.GetTokenAuthInfo = channel.unary_unary(
+ '/message.Service/GetTokenAuthInfo',
+ request_serializer=service__pb2.TokenRequest.SerializeToString,
+ response_deserializer=service__pb2.TokenResponse.FromString,
+ _registered_method=True)
+ self.RenewToken = channel.unary_unary(
+ '/message.Service/RenewToken',
+ request_serializer=service__pb2.TokenRequest.SerializeToString,
+ response_deserializer=service__pb2.StatusResponse.FromString,
+ _registered_method=True)
+ self.CreateSession = channel.unary_unary(
+ '/message.Service/CreateSession',
+ request_serializer=service__pb2.SessionCreateRequest.SerializeToString,
+ response_deserializer=service__pb2.SessionCreateResponse.FromString,
+ _registered_method=True)
+ self.FinishSession = channel.unary_unary(
+ '/message.Service/FinishSession',
+ request_serializer=service__pb2.SessionFinishRequest.SerializeToString,
+ response_deserializer=service__pb2.SessionFinishResp.FromString,
+ _registered_method=True)
+ self.UploadReplayFile = channel.unary_unary(
+ '/message.Service/UploadReplayFile',
+ request_serializer=service__pb2.ReplayRequest.SerializeToString,
+ response_deserializer=service__pb2.ReplayResponse.FromString,
+ _registered_method=True)
+ self.UploadCommand = channel.unary_unary(
+ '/message.Service/UploadCommand',
+ request_serializer=service__pb2.CommandRequest.SerializeToString,
+ response_deserializer=service__pb2.CommandResponse.FromString,
+ _registered_method=True)
+ self.DispatchTask = channel.stream_stream(
+ '/message.Service/DispatchTask',
+ request_serializer=service__pb2.FinishedTaskRequest.SerializeToString,
+ response_deserializer=service__pb2.TaskResponse.FromString,
+ _registered_method=True)
+ self.ScanRemainReplays = channel.unary_unary(
+ '/message.Service/ScanRemainReplays',
+ request_serializer=service__pb2.RemainReplayRequest.SerializeToString,
+ response_deserializer=service__pb2.RemainReplayResponse.FromString,
+ _registered_method=True)
+ self.CreateCommandTicket = channel.unary_unary(
+ '/message.Service/CreateCommandTicket',
+ request_serializer=service__pb2.CommandConfirmRequest.SerializeToString,
+ response_deserializer=service__pb2.CommandConfirmResponse.FromString,
+ _registered_method=True)
+ self.CheckOrCreateAssetLoginTicket = channel.unary_unary(
+ '/message.Service/CheckOrCreateAssetLoginTicket',
+ request_serializer=service__pb2.AssetLoginTicketRequest.SerializeToString,
+ response_deserializer=service__pb2.AssetLoginTicketResponse.FromString,
+ _registered_method=True)
+ self.CheckTicketState = channel.unary_unary(
+ '/message.Service/CheckTicketState',
+ request_serializer=service__pb2.TicketRequest.SerializeToString,
+ response_deserializer=service__pb2.TicketStateResponse.FromString,
+ _registered_method=True)
+ self.CancelTicket = channel.unary_unary(
+ '/message.Service/CancelTicket',
+ request_serializer=service__pb2.TicketRequest.SerializeToString,
+ response_deserializer=service__pb2.StatusResponse.FromString,
+ _registered_method=True)
+ self.CreateForward = channel.unary_unary(
+ '/message.Service/CreateForward',
+ request_serializer=service__pb2.ForwardRequest.SerializeToString,
+ response_deserializer=service__pb2.ForwardResponse.FromString,
+ _registered_method=True)
+ self.DeleteForward = channel.unary_unary(
+ '/message.Service/DeleteForward',
+ request_serializer=service__pb2.ForwardDeleteRequest.SerializeToString,
+ response_deserializer=service__pb2.StatusResponse.FromString,
+ _registered_method=True)
+ self.GetPublicSetting = channel.unary_unary(
+ '/message.Service/GetPublicSetting',
+ request_serializer=service__pb2.Empty.SerializeToString,
+ response_deserializer=service__pb2.PublicSettingResponse.FromString,
+ _registered_method=True)
+ self.GetListenPorts = channel.unary_unary(
+ '/message.Service/GetListenPorts',
+ request_serializer=service__pb2.Empty.SerializeToString,
+ response_deserializer=service__pb2.ListenPortResponse.FromString,
+ _registered_method=True)
+ self.GetPortInfo = channel.unary_unary(
+ '/message.Service/GetPortInfo',
+ request_serializer=service__pb2.PortInfoRequest.SerializeToString,
+ response_deserializer=service__pb2.PortInfoResponse.FromString,
+ _registered_method=True)
+ self.HandlePortFailure = channel.unary_unary(
+ '/message.Service/HandlePortFailure',
+ request_serializer=service__pb2.PortFailureRequest.SerializeToString,
+ response_deserializer=service__pb2.StatusResponse.FromString,
+ _registered_method=True)
+ self.CheckUserByCookies = channel.unary_unary(
+ '/message.Service/CheckUserByCookies',
+ request_serializer=service__pb2.CookiesRequest.SerializeToString,
+ response_deserializer=service__pb2.UserResponse.FromString,
+ _registered_method=True)
+ self.RecordSessionLifecycleLog = channel.unary_unary(
+ '/message.Service/RecordSessionLifecycleLog',
+ request_serializer=service__pb2.SessionLifecycleLogRequest.SerializeToString,
+ response_deserializer=service__pb2.StatusResponse.FromString,
+ _registered_method=True)
+ self.FaceRecognitionCallback = channel.unary_unary(
+ '/message.Service/FaceRecognitionCallback',
+ request_serializer=service__pb2.FaceRecognitionCallbackRequest.SerializeToString,
+ response_deserializer=service__pb2.FaceRecognitionCallbackResponse.FromString,
+ _registered_method=True)
+ self.FaceMonitorCallback = channel.unary_unary(
+ '/message.Service/FaceMonitorCallback',
+ request_serializer=service__pb2.FaceMonitorCallbackRequest.SerializeToString,
+ response_deserializer=service__pb2.FaceMonitorCallbackResponse.FromString,
+ _registered_method=True)
+ self.JoinFaceMonitor = channel.unary_unary(
+ '/message.Service/JoinFaceMonitor',
+ request_serializer=service__pb2.JoinFaceMonitorRequest.SerializeToString,
+ response_deserializer=service__pb2.JoinFaceMonitorResponse.FromString,
+ _registered_method=True)
+ self.GetAccountChat = channel.unary_unary(
+ '/message.Service/GetAccountChat',
+ request_serializer=service__pb2.Empty.SerializeToString,
+ response_deserializer=service__pb2.AccountDetailResponse.FromString,
+ _registered_method=True)
+ self.CallAPI = channel.unary_unary(
+ '/message.Service/CallAPI',
+ request_serializer=service__pb2.HTTPRequest.SerializeToString,
+ response_deserializer=service__pb2.HTTPResponse.FromString,
+ _registered_method=True)
+
+
+class ServiceServicer(object):
+ """Missing associated documentation comment in .proto file."""
+
+ def GetTokenAuthInfo(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def RenewToken(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def CreateSession(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def FinishSession(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def UploadReplayFile(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def UploadCommand(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def DispatchTask(self, request_iterator, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def ScanRemainReplays(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def CreateCommandTicket(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def CheckOrCreateAssetLoginTicket(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def CheckTicketState(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def CancelTicket(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def CreateForward(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def DeleteForward(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def GetPublicSetting(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def GetListenPorts(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def GetPortInfo(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def HandlePortFailure(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def CheckUserByCookies(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def RecordSessionLifecycleLog(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def FaceRecognitionCallback(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def FaceMonitorCallback(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def JoinFaceMonitor(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def GetAccountChat(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def CallAPI(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+
+def add_ServiceServicer_to_server(servicer, server):
+ rpc_method_handlers = {
+ 'GetTokenAuthInfo': grpc.unary_unary_rpc_method_handler(
+ servicer.GetTokenAuthInfo,
+ request_deserializer=service__pb2.TokenRequest.FromString,
+ response_serializer=service__pb2.TokenResponse.SerializeToString,
+ ),
+ 'RenewToken': grpc.unary_unary_rpc_method_handler(
+ servicer.RenewToken,
+ request_deserializer=service__pb2.TokenRequest.FromString,
+ response_serializer=service__pb2.StatusResponse.SerializeToString,
+ ),
+ 'CreateSession': grpc.unary_unary_rpc_method_handler(
+ servicer.CreateSession,
+ request_deserializer=service__pb2.SessionCreateRequest.FromString,
+ response_serializer=service__pb2.SessionCreateResponse.SerializeToString,
+ ),
+ 'FinishSession': grpc.unary_unary_rpc_method_handler(
+ servicer.FinishSession,
+ request_deserializer=service__pb2.SessionFinishRequest.FromString,
+ response_serializer=service__pb2.SessionFinishResp.SerializeToString,
+ ),
+ 'UploadReplayFile': grpc.unary_unary_rpc_method_handler(
+ servicer.UploadReplayFile,
+ request_deserializer=service__pb2.ReplayRequest.FromString,
+ response_serializer=service__pb2.ReplayResponse.SerializeToString,
+ ),
+ 'UploadCommand': grpc.unary_unary_rpc_method_handler(
+ servicer.UploadCommand,
+ request_deserializer=service__pb2.CommandRequest.FromString,
+ response_serializer=service__pb2.CommandResponse.SerializeToString,
+ ),
+ 'DispatchTask': grpc.stream_stream_rpc_method_handler(
+ servicer.DispatchTask,
+ request_deserializer=service__pb2.FinishedTaskRequest.FromString,
+ response_serializer=service__pb2.TaskResponse.SerializeToString,
+ ),
+ 'ScanRemainReplays': grpc.unary_unary_rpc_method_handler(
+ servicer.ScanRemainReplays,
+ request_deserializer=service__pb2.RemainReplayRequest.FromString,
+ response_serializer=service__pb2.RemainReplayResponse.SerializeToString,
+ ),
+ 'CreateCommandTicket': grpc.unary_unary_rpc_method_handler(
+ servicer.CreateCommandTicket,
+ request_deserializer=service__pb2.CommandConfirmRequest.FromString,
+ response_serializer=service__pb2.CommandConfirmResponse.SerializeToString,
+ ),
+ 'CheckOrCreateAssetLoginTicket': grpc.unary_unary_rpc_method_handler(
+ servicer.CheckOrCreateAssetLoginTicket,
+ request_deserializer=service__pb2.AssetLoginTicketRequest.FromString,
+ response_serializer=service__pb2.AssetLoginTicketResponse.SerializeToString,
+ ),
+ 'CheckTicketState': grpc.unary_unary_rpc_method_handler(
+ servicer.CheckTicketState,
+ request_deserializer=service__pb2.TicketRequest.FromString,
+ response_serializer=service__pb2.TicketStateResponse.SerializeToString,
+ ),
+ 'CancelTicket': grpc.unary_unary_rpc_method_handler(
+ servicer.CancelTicket,
+ request_deserializer=service__pb2.TicketRequest.FromString,
+ response_serializer=service__pb2.StatusResponse.SerializeToString,
+ ),
+ 'CreateForward': grpc.unary_unary_rpc_method_handler(
+ servicer.CreateForward,
+ request_deserializer=service__pb2.ForwardRequest.FromString,
+ response_serializer=service__pb2.ForwardResponse.SerializeToString,
+ ),
+ 'DeleteForward': grpc.unary_unary_rpc_method_handler(
+ servicer.DeleteForward,
+ request_deserializer=service__pb2.ForwardDeleteRequest.FromString,
+ response_serializer=service__pb2.StatusResponse.SerializeToString,
+ ),
+ 'GetPublicSetting': grpc.unary_unary_rpc_method_handler(
+ servicer.GetPublicSetting,
+ request_deserializer=service__pb2.Empty.FromString,
+ response_serializer=service__pb2.PublicSettingResponse.SerializeToString,
+ ),
+ 'GetListenPorts': grpc.unary_unary_rpc_method_handler(
+ servicer.GetListenPorts,
+ request_deserializer=service__pb2.Empty.FromString,
+ response_serializer=service__pb2.ListenPortResponse.SerializeToString,
+ ),
+ 'GetPortInfo': grpc.unary_unary_rpc_method_handler(
+ servicer.GetPortInfo,
+ request_deserializer=service__pb2.PortInfoRequest.FromString,
+ response_serializer=service__pb2.PortInfoResponse.SerializeToString,
+ ),
+ 'HandlePortFailure': grpc.unary_unary_rpc_method_handler(
+ servicer.HandlePortFailure,
+ request_deserializer=service__pb2.PortFailureRequest.FromString,
+ response_serializer=service__pb2.StatusResponse.SerializeToString,
+ ),
+ 'CheckUserByCookies': grpc.unary_unary_rpc_method_handler(
+ servicer.CheckUserByCookies,
+ request_deserializer=service__pb2.CookiesRequest.FromString,
+ response_serializer=service__pb2.UserResponse.SerializeToString,
+ ),
+ 'RecordSessionLifecycleLog': grpc.unary_unary_rpc_method_handler(
+ servicer.RecordSessionLifecycleLog,
+ request_deserializer=service__pb2.SessionLifecycleLogRequest.FromString,
+ response_serializer=service__pb2.StatusResponse.SerializeToString,
+ ),
+ 'FaceRecognitionCallback': grpc.unary_unary_rpc_method_handler(
+ servicer.FaceRecognitionCallback,
+ request_deserializer=service__pb2.FaceRecognitionCallbackRequest.FromString,
+ response_serializer=service__pb2.FaceRecognitionCallbackResponse.SerializeToString,
+ ),
+ 'FaceMonitorCallback': grpc.unary_unary_rpc_method_handler(
+ servicer.FaceMonitorCallback,
+ request_deserializer=service__pb2.FaceMonitorCallbackRequest.FromString,
+ response_serializer=service__pb2.FaceMonitorCallbackResponse.SerializeToString,
+ ),
+ 'JoinFaceMonitor': grpc.unary_unary_rpc_method_handler(
+ servicer.JoinFaceMonitor,
+ request_deserializer=service__pb2.JoinFaceMonitorRequest.FromString,
+ response_serializer=service__pb2.JoinFaceMonitorResponse.SerializeToString,
+ ),
+ 'GetAccountChat': grpc.unary_unary_rpc_method_handler(
+ servicer.GetAccountChat,
+ request_deserializer=service__pb2.Empty.FromString,
+ response_serializer=service__pb2.AccountDetailResponse.SerializeToString,
+ ),
+ 'CallAPI': grpc.unary_unary_rpc_method_handler(
+ servicer.CallAPI,
+ request_deserializer=service__pb2.HTTPRequest.FromString,
+ response_serializer=service__pb2.HTTPResponse.SerializeToString,
+ ),
+ }
+ generic_handler = grpc.method_handlers_generic_handler(
+ 'message.Service', rpc_method_handlers)
+ server.add_generic_rpc_handlers((generic_handler,))
+ server.add_registered_method_handlers('message.Service', rpc_method_handlers)
+
+
+ # This class is part of an EXPERIMENTAL API.
+class Service(object):
+ """Missing associated documentation comment in .proto file."""
+
+ @staticmethod
+ def GetTokenAuthInfo(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/GetTokenAuthInfo',
+ service__pb2.TokenRequest.SerializeToString,
+ service__pb2.TokenResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def RenewToken(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/RenewToken',
+ service__pb2.TokenRequest.SerializeToString,
+ service__pb2.StatusResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def CreateSession(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/CreateSession',
+ service__pb2.SessionCreateRequest.SerializeToString,
+ service__pb2.SessionCreateResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def FinishSession(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/FinishSession',
+ service__pb2.SessionFinishRequest.SerializeToString,
+ service__pb2.SessionFinishResp.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def UploadReplayFile(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/UploadReplayFile',
+ service__pb2.ReplayRequest.SerializeToString,
+ service__pb2.ReplayResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def UploadCommand(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/UploadCommand',
+ service__pb2.CommandRequest.SerializeToString,
+ service__pb2.CommandResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def DispatchTask(request_iterator,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.stream_stream(
+ request_iterator,
+ target,
+ '/message.Service/DispatchTask',
+ service__pb2.FinishedTaskRequest.SerializeToString,
+ service__pb2.TaskResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def ScanRemainReplays(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/ScanRemainReplays',
+ service__pb2.RemainReplayRequest.SerializeToString,
+ service__pb2.RemainReplayResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def CreateCommandTicket(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/CreateCommandTicket',
+ service__pb2.CommandConfirmRequest.SerializeToString,
+ service__pb2.CommandConfirmResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def CheckOrCreateAssetLoginTicket(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/CheckOrCreateAssetLoginTicket',
+ service__pb2.AssetLoginTicketRequest.SerializeToString,
+ service__pb2.AssetLoginTicketResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def CheckTicketState(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/CheckTicketState',
+ service__pb2.TicketRequest.SerializeToString,
+ service__pb2.TicketStateResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def CancelTicket(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/CancelTicket',
+ service__pb2.TicketRequest.SerializeToString,
+ service__pb2.StatusResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def CreateForward(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/CreateForward',
+ service__pb2.ForwardRequest.SerializeToString,
+ service__pb2.ForwardResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def DeleteForward(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/DeleteForward',
+ service__pb2.ForwardDeleteRequest.SerializeToString,
+ service__pb2.StatusResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def GetPublicSetting(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/GetPublicSetting',
+ service__pb2.Empty.SerializeToString,
+ service__pb2.PublicSettingResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def GetListenPorts(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/GetListenPorts',
+ service__pb2.Empty.SerializeToString,
+ service__pb2.ListenPortResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def GetPortInfo(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/GetPortInfo',
+ service__pb2.PortInfoRequest.SerializeToString,
+ service__pb2.PortInfoResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def HandlePortFailure(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/HandlePortFailure',
+ service__pb2.PortFailureRequest.SerializeToString,
+ service__pb2.StatusResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def CheckUserByCookies(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/CheckUserByCookies',
+ service__pb2.CookiesRequest.SerializeToString,
+ service__pb2.UserResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def RecordSessionLifecycleLog(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/RecordSessionLifecycleLog',
+ service__pb2.SessionLifecycleLogRequest.SerializeToString,
+ service__pb2.StatusResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def FaceRecognitionCallback(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/FaceRecognitionCallback',
+ service__pb2.FaceRecognitionCallbackRequest.SerializeToString,
+ service__pb2.FaceRecognitionCallbackResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def FaceMonitorCallback(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/FaceMonitorCallback',
+ service__pb2.FaceMonitorCallbackRequest.SerializeToString,
+ service__pb2.FaceMonitorCallbackResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def JoinFaceMonitor(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/JoinFaceMonitor',
+ service__pb2.JoinFaceMonitorRequest.SerializeToString,
+ service__pb2.JoinFaceMonitorResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def GetAccountChat(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/GetAccountChat',
+ service__pb2.Empty.SerializeToString,
+ service__pb2.AccountDetailResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def CallAPI(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/message.Service/CallAPI',
+ service__pb2.HTTPRequest.SerializeToString,
+ service__pb2.HTTPResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
diff --git a/backend/open_webui/main.py b/backend/open_webui/main.py
index f0aeeab02a53..12048d33f7ff 100644
--- a/backend/open_webui/main.py
+++ b/backend/open_webui/main.py
@@ -1,525 +1,71 @@
import asyncio
-import inspect
-import json
import logging
import mimetypes
import os
-import shutil
import sys
-import time
-import random
-import re
-from uuid import uuid4
-
from contextlib import asynccontextmanager
-from urllib.parse import urlencode, parse_qs, urlparse
-from pydantic import BaseModel
-from sqlalchemy import text
-
-from typing import Optional
-from aiocache import cached
-import aiohttp
import anyio.to_thread
-import requests
-from redis import Redis
-
from fastapi import (
- Depends,
FastAPI,
- File,
- Form,
HTTPException,
Request,
- UploadFile,
- status,
- applications,
- BackgroundTasks,
+ applications
)
-from fastapi.openapi.docs import get_swagger_ui_html
-
-from fastapi.middleware.cors import CORSMiddleware
-from fastapi.responses import FileResponse, JSONResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
-
-from starlette_compress import CompressMiddleware
+from fastapi.openapi.docs import get_swagger_ui_html
from starlette.exceptions import HTTPException as StarletteHTTPException
-from starlette.middleware.base import BaseHTTPMiddleware
-from starlette.middleware.sessions import SessionMiddleware
-from starlette.responses import Response, StreamingResponse
from starlette.datastructures import Headers
-from starsessions import (
- SessionMiddleware as StarSessionsMiddleware,
- SessionAutoloadMiddleware,
-)
-from starsessions.stores.redis import RedisStore
-
-from open_webui.utils import logger
-from open_webui.utils.audit import AuditLevel, AuditLoggingMiddleware
+from open_webui.jms import setup_poll_jms_event
from open_webui.utils.logger import start_logger
from open_webui.socket.main import (
app as socket_app,
periodic_usage_pool_cleanup,
- get_event_emitter,
- get_models_in_use,
- get_active_user_ids,
-)
-from open_webui.routers import (
- audio,
- images,
- ollama,
- openai,
- retrieval,
- pipelines,
- tasks,
- auths,
- channels,
- chats,
- notes,
- folders,
- configs,
- groups,
- files,
- functions,
- memories,
- models,
- knowledge,
- prompts,
- evaluations,
- tools,
- users,
- utils,
- scim,
-)
-
-from open_webui.routers.retrieval import (
- get_embedding_function,
- get_reranking_function,
- get_ef,
- get_rf,
)
-from open_webui.internal.db import Session, engine
-
from open_webui.models.functions import Functions
-from open_webui.models.models import Models
-from open_webui.models.users import UserModel, Users
-from open_webui.models.chats import Chats
from open_webui.config import (
- # Ollama
- ENABLE_OLLAMA_API,
- OLLAMA_BASE_URLS,
- OLLAMA_API_CONFIGS,
- # OpenAI
- ENABLE_OPENAI_API,
- OPENAI_API_BASE_URLS,
- OPENAI_API_KEYS,
- OPENAI_API_CONFIGS,
- # Direct Connections
- ENABLE_DIRECT_CONNECTIONS,
- # Model list
- ENABLE_BASE_MODELS_CACHE,
- # Thread pool size for FastAPI/AnyIO
THREAD_POOL_SIZE,
- # Tool Server Configs
- TOOL_SERVER_CONNECTIONS,
- # Code Execution
- ENABLE_CODE_EXECUTION,
- CODE_EXECUTION_ENGINE,
- CODE_EXECUTION_JUPYTER_URL,
- CODE_EXECUTION_JUPYTER_AUTH,
- CODE_EXECUTION_JUPYTER_AUTH_TOKEN,
- CODE_EXECUTION_JUPYTER_AUTH_PASSWORD,
- CODE_EXECUTION_JUPYTER_TIMEOUT,
- ENABLE_CODE_INTERPRETER,
- CODE_INTERPRETER_ENGINE,
- CODE_INTERPRETER_PROMPT_TEMPLATE,
- CODE_INTERPRETER_JUPYTER_URL,
- CODE_INTERPRETER_JUPYTER_AUTH,
- CODE_INTERPRETER_JUPYTER_AUTH_TOKEN,
- CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD,
- CODE_INTERPRETER_JUPYTER_TIMEOUT,
- # Image
- AUTOMATIC1111_API_AUTH,
- AUTOMATIC1111_BASE_URL,
- AUTOMATIC1111_PARAMS,
- COMFYUI_BASE_URL,
- COMFYUI_API_KEY,
- COMFYUI_WORKFLOW,
- COMFYUI_WORKFLOW_NODES,
- ENABLE_IMAGE_GENERATION,
- ENABLE_IMAGE_PROMPT_GENERATION,
- IMAGE_GENERATION_ENGINE,
- IMAGE_GENERATION_MODEL,
- IMAGE_SIZE,
- IMAGE_STEPS,
- IMAGES_OPENAI_API_BASE_URL,
- IMAGES_OPENAI_API_VERSION,
- IMAGES_OPENAI_API_KEY,
- IMAGES_GEMINI_API_BASE_URL,
- IMAGES_GEMINI_API_KEY,
- IMAGES_GEMINI_ENDPOINT_METHOD,
- IMAGE_EDIT_ENGINE,
- IMAGE_EDIT_MODEL,
- IMAGE_EDIT_SIZE,
- IMAGES_EDIT_OPENAI_API_BASE_URL,
- IMAGES_EDIT_OPENAI_API_KEY,
- IMAGES_EDIT_OPENAI_API_VERSION,
- IMAGES_EDIT_GEMINI_API_BASE_URL,
- IMAGES_EDIT_GEMINI_API_KEY,
- IMAGES_EDIT_COMFYUI_BASE_URL,
- IMAGES_EDIT_COMFYUI_API_KEY,
- IMAGES_EDIT_COMFYUI_WORKFLOW,
- IMAGES_EDIT_COMFYUI_WORKFLOW_NODES,
- # Audio
- AUDIO_STT_ENGINE,
- AUDIO_STT_MODEL,
- AUDIO_STT_SUPPORTED_CONTENT_TYPES,
- AUDIO_STT_OPENAI_API_BASE_URL,
- AUDIO_STT_OPENAI_API_KEY,
- AUDIO_STT_AZURE_API_KEY,
- AUDIO_STT_AZURE_REGION,
- AUDIO_STT_AZURE_LOCALES,
- AUDIO_STT_AZURE_BASE_URL,
- AUDIO_STT_AZURE_MAX_SPEAKERS,
- AUDIO_STT_MISTRAL_API_KEY,
- AUDIO_STT_MISTRAL_API_BASE_URL,
- AUDIO_STT_MISTRAL_USE_CHAT_COMPLETIONS,
- AUDIO_TTS_ENGINE,
- AUDIO_TTS_MODEL,
- AUDIO_TTS_VOICE,
- AUDIO_TTS_OPENAI_API_BASE_URL,
- AUDIO_TTS_OPENAI_API_KEY,
- AUDIO_TTS_OPENAI_PARAMS,
- AUDIO_TTS_API_KEY,
- AUDIO_TTS_SPLIT_ON,
- AUDIO_TTS_AZURE_SPEECH_REGION,
- AUDIO_TTS_AZURE_SPEECH_BASE_URL,
- AUDIO_TTS_AZURE_SPEECH_OUTPUT_FORMAT,
- PLAYWRIGHT_WS_URL,
- PLAYWRIGHT_TIMEOUT,
- FIRECRAWL_API_BASE_URL,
- FIRECRAWL_API_KEY,
- WEB_LOADER_ENGINE,
- WEB_LOADER_CONCURRENT_REQUESTS,
- WHISPER_MODEL,
- WHISPER_VAD_FILTER,
- WHISPER_LANGUAGE,
- DEEPGRAM_API_KEY,
- WHISPER_MODEL_AUTO_UPDATE,
- WHISPER_MODEL_DIR,
- # Retrieval
- RAG_TEMPLATE,
- DEFAULT_RAG_TEMPLATE,
- RAG_FULL_CONTEXT,
- BYPASS_EMBEDDING_AND_RETRIEVAL,
- RAG_EMBEDDING_MODEL,
- RAG_EMBEDDING_MODEL_AUTO_UPDATE,
- RAG_EMBEDDING_MODEL_TRUST_REMOTE_CODE,
- RAG_RERANKING_ENGINE,
- RAG_RERANKING_MODEL,
- RAG_EXTERNAL_RERANKER_URL,
- RAG_EXTERNAL_RERANKER_API_KEY,
- RAG_RERANKING_MODEL_AUTO_UPDATE,
- RAG_RERANKING_MODEL_TRUST_REMOTE_CODE,
- RAG_EMBEDDING_ENGINE,
- RAG_EMBEDDING_BATCH_SIZE,
- RAG_TOP_K,
- RAG_TOP_K_RERANKER,
- RAG_RELEVANCE_THRESHOLD,
- RAG_HYBRID_BM25_WEIGHT,
- RAG_ALLOWED_FILE_EXTENSIONS,
- RAG_FILE_MAX_COUNT,
- RAG_FILE_MAX_SIZE,
- FILE_IMAGE_COMPRESSION_WIDTH,
- FILE_IMAGE_COMPRESSION_HEIGHT,
- RAG_OPENAI_API_BASE_URL,
- RAG_OPENAI_API_KEY,
- RAG_AZURE_OPENAI_BASE_URL,
- RAG_AZURE_OPENAI_API_KEY,
- RAG_AZURE_OPENAI_API_VERSION,
- RAG_OLLAMA_BASE_URL,
- RAG_OLLAMA_API_KEY,
- CHUNK_OVERLAP,
- CHUNK_SIZE,
- CONTENT_EXTRACTION_ENGINE,
- DATALAB_MARKER_API_KEY,
- DATALAB_MARKER_API_BASE_URL,
- DATALAB_MARKER_ADDITIONAL_CONFIG,
- DATALAB_MARKER_SKIP_CACHE,
- DATALAB_MARKER_FORCE_OCR,
- DATALAB_MARKER_PAGINATE,
- DATALAB_MARKER_STRIP_EXISTING_OCR,
- DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION,
- DATALAB_MARKER_FORMAT_LINES,
- DATALAB_MARKER_OUTPUT_FORMAT,
- MINERU_API_MODE,
- MINERU_API_URL,
- MINERU_API_KEY,
- MINERU_PARAMS,
- DATALAB_MARKER_USE_LLM,
- EXTERNAL_DOCUMENT_LOADER_URL,
- EXTERNAL_DOCUMENT_LOADER_API_KEY,
- TIKA_SERVER_URL,
- DOCLING_SERVER_URL,
- DOCLING_PARAMS,
- DOCLING_DO_OCR,
- DOCLING_FORCE_OCR,
- DOCLING_OCR_ENGINE,
- DOCLING_OCR_LANG,
- DOCLING_PDF_BACKEND,
- DOCLING_TABLE_MODE,
- DOCLING_PIPELINE,
- DOCLING_DO_PICTURE_DESCRIPTION,
- DOCLING_PICTURE_DESCRIPTION_MODE,
- DOCLING_PICTURE_DESCRIPTION_LOCAL,
- DOCLING_PICTURE_DESCRIPTION_API,
- DOCUMENT_INTELLIGENCE_ENDPOINT,
- DOCUMENT_INTELLIGENCE_KEY,
- MISTRAL_OCR_API_BASE_URL,
- MISTRAL_OCR_API_KEY,
- RAG_TEXT_SPLITTER,
- TIKTOKEN_ENCODING_NAME,
- PDF_EXTRACT_IMAGES,
- YOUTUBE_LOADER_LANGUAGE,
- YOUTUBE_LOADER_PROXY_URL,
- # Retrieval (Web Search)
- ENABLE_WEB_SEARCH,
- WEB_SEARCH_ENGINE,
- BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL,
- BYPASS_WEB_SEARCH_WEB_LOADER,
- WEB_SEARCH_RESULT_COUNT,
- WEB_SEARCH_CONCURRENT_REQUESTS,
- WEB_SEARCH_TRUST_ENV,
- WEB_SEARCH_DOMAIN_FILTER_LIST,
- OLLAMA_CLOUD_WEB_SEARCH_API_KEY,
- JINA_API_KEY,
- SEARCHAPI_API_KEY,
- SEARCHAPI_ENGINE,
- SERPAPI_API_KEY,
- SERPAPI_ENGINE,
- SEARXNG_QUERY_URL,
- YACY_QUERY_URL,
- YACY_USERNAME,
- YACY_PASSWORD,
- SERPER_API_KEY,
- SERPLY_API_KEY,
- SERPSTACK_API_KEY,
- SERPSTACK_HTTPS,
- TAVILY_API_KEY,
- TAVILY_EXTRACT_DEPTH,
- BING_SEARCH_V7_ENDPOINT,
- BING_SEARCH_V7_SUBSCRIPTION_KEY,
- BRAVE_SEARCH_API_KEY,
- EXA_API_KEY,
- PERPLEXITY_API_KEY,
- PERPLEXITY_MODEL,
- PERPLEXITY_SEARCH_CONTEXT_USAGE,
- SOUGOU_API_SID,
- SOUGOU_API_SK,
- KAGI_SEARCH_API_KEY,
- MOJEEK_SEARCH_API_KEY,
- BOCHA_SEARCH_API_KEY,
- GOOGLE_PSE_API_KEY,
- GOOGLE_PSE_ENGINE_ID,
- GOOGLE_DRIVE_CLIENT_ID,
- GOOGLE_DRIVE_API_KEY,
- ENABLE_ONEDRIVE_INTEGRATION,
- ONEDRIVE_CLIENT_ID_PERSONAL,
- ONEDRIVE_CLIENT_ID_BUSINESS,
- ONEDRIVE_SHAREPOINT_URL,
- ONEDRIVE_SHAREPOINT_TENANT_ID,
- ENABLE_ONEDRIVE_PERSONAL,
- ENABLE_ONEDRIVE_BUSINESS,
- ENABLE_RAG_HYBRID_SEARCH,
- ENABLE_RAG_LOCAL_WEB_FETCH,
- ENABLE_WEB_LOADER_SSL_VERIFICATION,
- ENABLE_GOOGLE_DRIVE_INTEGRATION,
- UPLOAD_DIR,
- EXTERNAL_WEB_SEARCH_URL,
- EXTERNAL_WEB_SEARCH_API_KEY,
- EXTERNAL_WEB_LOADER_URL,
- EXTERNAL_WEB_LOADER_API_KEY,
- # WebUI
- WEBUI_AUTH,
- WEBUI_NAME,
- WEBUI_BANNERS,
- WEBHOOK_URL,
- ADMIN_EMAIL,
- SHOW_ADMIN_DETAILS,
- JWT_EXPIRES_IN,
- ENABLE_SIGNUP,
- ENABLE_LOGIN_FORM,
- ENABLE_API_KEY,
- ENABLE_API_KEY_ENDPOINT_RESTRICTIONS,
- API_KEY_ALLOWED_ENDPOINTS,
- ENABLE_CHANNELS,
- ENABLE_NOTES,
- ENABLE_COMMUNITY_SHARING,
- ENABLE_MESSAGE_RATING,
- ENABLE_USER_WEBHOOKS,
- ENABLE_EVALUATION_ARENA_MODELS,
- BYPASS_ADMIN_ACCESS_CONTROL,
- USER_PERMISSIONS,
- DEFAULT_USER_ROLE,
- PENDING_USER_OVERLAY_CONTENT,
- PENDING_USER_OVERLAY_TITLE,
- DEFAULT_PROMPT_SUGGESTIONS,
- DEFAULT_MODELS,
- DEFAULT_ARENA_MODEL,
- MODEL_ORDER_LIST,
- EVALUATION_ARENA_MODELS,
- # WebUI (OAuth)
- ENABLE_OAUTH_ROLE_MANAGEMENT,
- OAUTH_ROLES_CLAIM,
- OAUTH_EMAIL_CLAIM,
- OAUTH_PICTURE_CLAIM,
- OAUTH_USERNAME_CLAIM,
- OAUTH_ALLOWED_ROLES,
- OAUTH_ADMIN_ROLES,
- # WebUI (LDAP)
- ENABLE_LDAP,
- LDAP_SERVER_LABEL,
- LDAP_SERVER_HOST,
- LDAP_SERVER_PORT,
- LDAP_ATTRIBUTE_FOR_MAIL,
- LDAP_ATTRIBUTE_FOR_USERNAME,
- LDAP_SEARCH_FILTERS,
- LDAP_SEARCH_BASE,
- LDAP_APP_DN,
- LDAP_APP_PASSWORD,
- LDAP_USE_TLS,
- LDAP_CA_CERT_FILE,
- LDAP_VALIDATE_CERT,
- LDAP_CIPHERS,
- # LDAP Group Management
- ENABLE_LDAP_GROUP_MANAGEMENT,
- ENABLE_LDAP_GROUP_CREATION,
- LDAP_ATTRIBUTE_FOR_GROUPS,
- # Misc
ENV,
- CACHE_DIR,
- STATIC_DIR,
- FRONTEND_BUILD_DIR,
- CORS_ALLOW_ORIGIN,
- DEFAULT_LOCALE,
- OAUTH_PROVIDERS,
- WEBUI_URL,
- RESPONSE_WATERMARK,
- # Admin
- ENABLE_ADMIN_CHAT_ACCESS,
- BYPASS_ADMIN_ACCESS_CONTROL,
- ENABLE_ADMIN_EXPORT,
- # Tasks
- TASK_MODEL,
- TASK_MODEL_EXTERNAL,
- ENABLE_TAGS_GENERATION,
- ENABLE_TITLE_GENERATION,
- ENABLE_FOLLOW_UP_GENERATION,
- ENABLE_SEARCH_QUERY_GENERATION,
- ENABLE_RETRIEVAL_QUERY_GENERATION,
- ENABLE_AUTOCOMPLETE_GENERATION,
- TITLE_GENERATION_PROMPT_TEMPLATE,
- FOLLOW_UP_GENERATION_PROMPT_TEMPLATE,
- TAGS_GENERATION_PROMPT_TEMPLATE,
- IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE,
- TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE,
- QUERY_GENERATION_PROMPT_TEMPLATE,
- AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE,
- AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH,
- AppConfig,
reset_config,
)
from open_webui.env import (
LICENSE_KEY,
- AUDIT_EXCLUDED_PATHS,
- AUDIT_LOG_LEVEL,
- CHANGELOG,
REDIS_URL,
REDIS_CLUSTER,
- REDIS_KEY_PREFIX,
REDIS_SENTINEL_HOSTS,
REDIS_SENTINEL_PORT,
GLOBAL_LOG_LEVEL,
- MAX_BODY_LOG_SIZE,
SAFE_MODE,
SRC_LOG_LEVELS,
VERSION,
INSTANCE_ID,
WEBUI_BUILD_HASH,
- WEBUI_SECRET_KEY,
- WEBUI_SESSION_COOKIE_SAME_SITE,
- WEBUI_SESSION_COOKIE_SECURE,
- ENABLE_SIGNUP_PASSWORD_CONFIRMATION,
- WEBUI_AUTH_TRUSTED_EMAIL_HEADER,
- WEBUI_AUTH_TRUSTED_NAME_HEADER,
- WEBUI_AUTH_SIGNOUT_REDIRECT_URL,
- # SCIM
- SCIM_ENABLED,
- SCIM_TOKEN,
- ENABLE_COMPRESSION_MIDDLEWARE,
- ENABLE_WEBSOCKET_SUPPORT,
- BYPASS_MODEL_ACCESS_CONTROL,
- RESET_CONFIG_ON_START,
- ENABLE_VERSION_UPDATE_CHECK,
- ENABLE_OTEL,
- EXTERNAL_PWA_MANIFEST_URL,
- AIOHTTP_CLIENT_SESSION_SSL,
- ENABLE_STAR_SESSIONS_MIDDLEWARE,
+ RESET_CONFIG_ON_START, FRONTEND_BUILD_DIR,
)
-
from open_webui.utils.models import (
get_all_models,
- get_all_base_models,
- check_model_access,
- get_filtered_models,
)
-from open_webui.utils.chat import (
- generate_chat_completion as chat_completion_handler,
- chat_completed as chat_completed_handler,
- chat_action as chat_action_handler,
-)
-from open_webui.utils.embeddings import generate_embeddings
-from open_webui.utils.middleware import process_chat_payload, process_chat_response
-from open_webui.utils.access_control import has_access
from open_webui.utils.auth import (
get_license_data,
- get_http_authorization_cred,
- decode_token,
- get_admin_user,
- get_verified_user,
)
from open_webui.utils.plugin import install_tool_and_function_dependencies
-from open_webui.utils.oauth import (
- get_oauth_client_info_with_dynamic_client_registration,
- encrypt_data,
- decrypt_data,
- OAuthManager,
- OAuthClientManager,
- OAuthClientInformationFull,
-)
-from open_webui.utils.security_headers import SecurityHeadersMiddleware
from open_webui.utils.redis import get_redis_connection
from open_webui.tasks import (
redis_task_command_listener,
- list_task_ids_by_item_id,
- create_task,
- stop_task,
- list_tasks,
) # Import from tasks.py
from open_webui.utils.redis import get_sentinels_from_env
-
-
-from open_webui.constants import ERROR_MESSAGES
-
+from open_webui.app import init_app_config
+from open_webui.middlewares import init_middlewares
+from open_webui.urls import setup_routes
if SAFE_MODE:
print("SAFE MODE ENABLED")
@@ -619,6 +165,7 @@ async def lifespan(app: FastAPI):
None,
)
+ setup_poll_jms_event()
yield
if hasattr(app.state, "redis_task_command_listener"):
@@ -626,1614 +173,17 @@ async def lifespan(app: FastAPI):
app = FastAPI(
- title="Open WebUI",
+ title="JumpServer Chat && Open WebUI",
docs_url="/docs" if ENV == "dev" else None,
openapi_url="/openapi.json" if ENV == "dev" else None,
redoc_url=None,
lifespan=lifespan,
)
-# For Open WebUI OIDC/OAuth2
-oauth_manager = OAuthManager(app)
-app.state.oauth_manager = oauth_manager
-
-# For Integrations
-oauth_client_manager = OAuthClientManager(app)
-app.state.oauth_client_manager = oauth_client_manager
-
-app.state.instance_id = None
-app.state.config = AppConfig(
- redis_url=REDIS_URL,
- redis_sentinels=get_sentinels_from_env(REDIS_SENTINEL_HOSTS, REDIS_SENTINEL_PORT),
- redis_cluster=REDIS_CLUSTER,
- redis_key_prefix=REDIS_KEY_PREFIX,
-)
-app.state.redis = None
-
-app.state.WEBUI_NAME = WEBUI_NAME
-app.state.LICENSE_METADATA = None
-
-
-########################################
-#
-# OPENTELEMETRY
-#
-########################################
-
-if ENABLE_OTEL:
- from open_webui.utils.telemetry.setup import setup as setup_opentelemetry
-
- setup_opentelemetry(app=app, db_engine=engine)
-
-
-########################################
-#
-# OLLAMA
-#
-########################################
-
-
-app.state.config.ENABLE_OLLAMA_API = ENABLE_OLLAMA_API
-app.state.config.OLLAMA_BASE_URLS = OLLAMA_BASE_URLS
-app.state.config.OLLAMA_API_CONFIGS = OLLAMA_API_CONFIGS
-
-app.state.OLLAMA_MODELS = {}
-
-########################################
-#
-# OPENAI
-#
-########################################
-
-app.state.config.ENABLE_OPENAI_API = ENABLE_OPENAI_API
-app.state.config.OPENAI_API_BASE_URLS = OPENAI_API_BASE_URLS
-app.state.config.OPENAI_API_KEYS = OPENAI_API_KEYS
-app.state.config.OPENAI_API_CONFIGS = OPENAI_API_CONFIGS
-
-app.state.OPENAI_MODELS = {}
-
-########################################
-#
-# TOOL SERVERS
-#
-########################################
-
-app.state.config.TOOL_SERVER_CONNECTIONS = TOOL_SERVER_CONNECTIONS
-app.state.TOOL_SERVERS = []
-
-########################################
-#
-# DIRECT CONNECTIONS
-#
-########################################
-
-app.state.config.ENABLE_DIRECT_CONNECTIONS = ENABLE_DIRECT_CONNECTIONS
-
-########################################
-#
-# SCIM
-#
-########################################
-
-app.state.SCIM_ENABLED = SCIM_ENABLED
-app.state.SCIM_TOKEN = SCIM_TOKEN
-
-########################################
-#
-# MODELS
-#
-########################################
-
-app.state.config.ENABLE_BASE_MODELS_CACHE = ENABLE_BASE_MODELS_CACHE
-app.state.BASE_MODELS = []
-
-########################################
-#
-# WEBUI
-#
-########################################
-
-app.state.config.WEBUI_URL = WEBUI_URL
-app.state.config.ENABLE_SIGNUP = ENABLE_SIGNUP
-app.state.config.ENABLE_LOGIN_FORM = ENABLE_LOGIN_FORM
-
-app.state.config.ENABLE_API_KEY = ENABLE_API_KEY
-app.state.config.ENABLE_API_KEY_ENDPOINT_RESTRICTIONS = (
- ENABLE_API_KEY_ENDPOINT_RESTRICTIONS
-)
-app.state.config.API_KEY_ALLOWED_ENDPOINTS = API_KEY_ALLOWED_ENDPOINTS
-
-app.state.config.JWT_EXPIRES_IN = JWT_EXPIRES_IN
-
-app.state.config.SHOW_ADMIN_DETAILS = SHOW_ADMIN_DETAILS
-app.state.config.ADMIN_EMAIL = ADMIN_EMAIL
-
-
-app.state.config.DEFAULT_MODELS = DEFAULT_MODELS
-app.state.config.DEFAULT_PROMPT_SUGGESTIONS = DEFAULT_PROMPT_SUGGESTIONS
-app.state.config.DEFAULT_USER_ROLE = DEFAULT_USER_ROLE
-
-app.state.config.PENDING_USER_OVERLAY_CONTENT = PENDING_USER_OVERLAY_CONTENT
-app.state.config.PENDING_USER_OVERLAY_TITLE = PENDING_USER_OVERLAY_TITLE
-
-app.state.config.RESPONSE_WATERMARK = RESPONSE_WATERMARK
-
-app.state.config.USER_PERMISSIONS = USER_PERMISSIONS
-app.state.config.WEBHOOK_URL = WEBHOOK_URL
-app.state.config.BANNERS = WEBUI_BANNERS
-app.state.config.MODEL_ORDER_LIST = MODEL_ORDER_LIST
-
-
-app.state.config.ENABLE_CHANNELS = ENABLE_CHANNELS
-app.state.config.ENABLE_NOTES = ENABLE_NOTES
-app.state.config.ENABLE_COMMUNITY_SHARING = ENABLE_COMMUNITY_SHARING
-app.state.config.ENABLE_MESSAGE_RATING = ENABLE_MESSAGE_RATING
-app.state.config.ENABLE_USER_WEBHOOKS = ENABLE_USER_WEBHOOKS
-
-app.state.config.ENABLE_EVALUATION_ARENA_MODELS = ENABLE_EVALUATION_ARENA_MODELS
-app.state.config.EVALUATION_ARENA_MODELS = EVALUATION_ARENA_MODELS
-
-app.state.config.OAUTH_USERNAME_CLAIM = OAUTH_USERNAME_CLAIM
-app.state.config.OAUTH_PICTURE_CLAIM = OAUTH_PICTURE_CLAIM
-app.state.config.OAUTH_EMAIL_CLAIM = OAUTH_EMAIL_CLAIM
-
-app.state.config.ENABLE_OAUTH_ROLE_MANAGEMENT = ENABLE_OAUTH_ROLE_MANAGEMENT
-app.state.config.OAUTH_ROLES_CLAIM = OAUTH_ROLES_CLAIM
-app.state.config.OAUTH_ALLOWED_ROLES = OAUTH_ALLOWED_ROLES
-app.state.config.OAUTH_ADMIN_ROLES = OAUTH_ADMIN_ROLES
-
-app.state.config.ENABLE_LDAP = ENABLE_LDAP
-app.state.config.LDAP_SERVER_LABEL = LDAP_SERVER_LABEL
-app.state.config.LDAP_SERVER_HOST = LDAP_SERVER_HOST
-app.state.config.LDAP_SERVER_PORT = LDAP_SERVER_PORT
-app.state.config.LDAP_ATTRIBUTE_FOR_MAIL = LDAP_ATTRIBUTE_FOR_MAIL
-app.state.config.LDAP_ATTRIBUTE_FOR_USERNAME = LDAP_ATTRIBUTE_FOR_USERNAME
-app.state.config.LDAP_APP_DN = LDAP_APP_DN
-app.state.config.LDAP_APP_PASSWORD = LDAP_APP_PASSWORD
-app.state.config.LDAP_SEARCH_BASE = LDAP_SEARCH_BASE
-app.state.config.LDAP_SEARCH_FILTERS = LDAP_SEARCH_FILTERS
-app.state.config.LDAP_USE_TLS = LDAP_USE_TLS
-app.state.config.LDAP_CA_CERT_FILE = LDAP_CA_CERT_FILE
-app.state.config.LDAP_VALIDATE_CERT = LDAP_VALIDATE_CERT
-app.state.config.LDAP_CIPHERS = LDAP_CIPHERS
-
-# For LDAP Group Management
-app.state.config.ENABLE_LDAP_GROUP_MANAGEMENT = ENABLE_LDAP_GROUP_MANAGEMENT
-app.state.config.ENABLE_LDAP_GROUP_CREATION = ENABLE_LDAP_GROUP_CREATION
-app.state.config.LDAP_ATTRIBUTE_FOR_GROUPS = LDAP_ATTRIBUTE_FOR_GROUPS
-
-
-app.state.AUTH_TRUSTED_EMAIL_HEADER = WEBUI_AUTH_TRUSTED_EMAIL_HEADER
-app.state.AUTH_TRUSTED_NAME_HEADER = WEBUI_AUTH_TRUSTED_NAME_HEADER
-app.state.WEBUI_AUTH_SIGNOUT_REDIRECT_URL = WEBUI_AUTH_SIGNOUT_REDIRECT_URL
-app.state.EXTERNAL_PWA_MANIFEST_URL = EXTERNAL_PWA_MANIFEST_URL
-
-app.state.USER_COUNT = None
-
-app.state.TOOLS = {}
-app.state.TOOL_CONTENTS = {}
-
-app.state.FUNCTIONS = {}
-app.state.FUNCTION_CONTENTS = {}
-
-########################################
-#
-# RETRIEVAL
-#
-########################################
-
-
-app.state.config.TOP_K = RAG_TOP_K
-app.state.config.TOP_K_RERANKER = RAG_TOP_K_RERANKER
-app.state.config.RELEVANCE_THRESHOLD = RAG_RELEVANCE_THRESHOLD
-app.state.config.HYBRID_BM25_WEIGHT = RAG_HYBRID_BM25_WEIGHT
-
-
-app.state.config.ALLOWED_FILE_EXTENSIONS = RAG_ALLOWED_FILE_EXTENSIONS
-app.state.config.FILE_MAX_SIZE = RAG_FILE_MAX_SIZE
-app.state.config.FILE_MAX_COUNT = RAG_FILE_MAX_COUNT
-app.state.config.FILE_IMAGE_COMPRESSION_WIDTH = FILE_IMAGE_COMPRESSION_WIDTH
-app.state.config.FILE_IMAGE_COMPRESSION_HEIGHT = FILE_IMAGE_COMPRESSION_HEIGHT
-
-
-app.state.config.RAG_FULL_CONTEXT = RAG_FULL_CONTEXT
-app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL = BYPASS_EMBEDDING_AND_RETRIEVAL
-app.state.config.ENABLE_RAG_HYBRID_SEARCH = ENABLE_RAG_HYBRID_SEARCH
-app.state.config.ENABLE_WEB_LOADER_SSL_VERIFICATION = ENABLE_WEB_LOADER_SSL_VERIFICATION
-
-app.state.config.CONTENT_EXTRACTION_ENGINE = CONTENT_EXTRACTION_ENGINE
-app.state.config.DATALAB_MARKER_API_KEY = DATALAB_MARKER_API_KEY
-app.state.config.DATALAB_MARKER_API_BASE_URL = DATALAB_MARKER_API_BASE_URL
-app.state.config.DATALAB_MARKER_ADDITIONAL_CONFIG = DATALAB_MARKER_ADDITIONAL_CONFIG
-app.state.config.DATALAB_MARKER_SKIP_CACHE = DATALAB_MARKER_SKIP_CACHE
-app.state.config.DATALAB_MARKER_FORCE_OCR = DATALAB_MARKER_FORCE_OCR
-app.state.config.DATALAB_MARKER_PAGINATE = DATALAB_MARKER_PAGINATE
-app.state.config.DATALAB_MARKER_STRIP_EXISTING_OCR = DATALAB_MARKER_STRIP_EXISTING_OCR
-app.state.config.DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION = (
- DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION
-)
-app.state.config.DATALAB_MARKER_FORMAT_LINES = DATALAB_MARKER_FORMAT_LINES
-app.state.config.DATALAB_MARKER_USE_LLM = DATALAB_MARKER_USE_LLM
-app.state.config.DATALAB_MARKER_OUTPUT_FORMAT = DATALAB_MARKER_OUTPUT_FORMAT
-app.state.config.EXTERNAL_DOCUMENT_LOADER_URL = EXTERNAL_DOCUMENT_LOADER_URL
-app.state.config.EXTERNAL_DOCUMENT_LOADER_API_KEY = EXTERNAL_DOCUMENT_LOADER_API_KEY
-app.state.config.TIKA_SERVER_URL = TIKA_SERVER_URL
-app.state.config.DOCLING_SERVER_URL = DOCLING_SERVER_URL
-app.state.config.DOCLING_PARAMS = DOCLING_PARAMS
-app.state.config.DOCLING_DO_OCR = DOCLING_DO_OCR
-app.state.config.DOCLING_FORCE_OCR = DOCLING_FORCE_OCR
-app.state.config.DOCLING_OCR_ENGINE = DOCLING_OCR_ENGINE
-app.state.config.DOCLING_OCR_LANG = DOCLING_OCR_LANG
-app.state.config.DOCLING_PDF_BACKEND = DOCLING_PDF_BACKEND
-app.state.config.DOCLING_TABLE_MODE = DOCLING_TABLE_MODE
-app.state.config.DOCLING_PIPELINE = DOCLING_PIPELINE
-app.state.config.DOCLING_DO_PICTURE_DESCRIPTION = DOCLING_DO_PICTURE_DESCRIPTION
-app.state.config.DOCLING_PICTURE_DESCRIPTION_MODE = DOCLING_PICTURE_DESCRIPTION_MODE
-app.state.config.DOCLING_PICTURE_DESCRIPTION_LOCAL = DOCLING_PICTURE_DESCRIPTION_LOCAL
-app.state.config.DOCLING_PICTURE_DESCRIPTION_API = DOCLING_PICTURE_DESCRIPTION_API
-app.state.config.DOCUMENT_INTELLIGENCE_ENDPOINT = DOCUMENT_INTELLIGENCE_ENDPOINT
-app.state.config.DOCUMENT_INTELLIGENCE_KEY = DOCUMENT_INTELLIGENCE_KEY
-app.state.config.MISTRAL_OCR_API_BASE_URL = MISTRAL_OCR_API_BASE_URL
-app.state.config.MISTRAL_OCR_API_KEY = MISTRAL_OCR_API_KEY
-app.state.config.MINERU_API_MODE = MINERU_API_MODE
-app.state.config.MINERU_API_URL = MINERU_API_URL
-app.state.config.MINERU_API_KEY = MINERU_API_KEY
-app.state.config.MINERU_PARAMS = MINERU_PARAMS
-
-app.state.config.TEXT_SPLITTER = RAG_TEXT_SPLITTER
-app.state.config.TIKTOKEN_ENCODING_NAME = TIKTOKEN_ENCODING_NAME
-
-app.state.config.CHUNK_SIZE = CHUNK_SIZE
-app.state.config.CHUNK_OVERLAP = CHUNK_OVERLAP
-
-app.state.config.RAG_EMBEDDING_ENGINE = RAG_EMBEDDING_ENGINE
-app.state.config.RAG_EMBEDDING_MODEL = RAG_EMBEDDING_MODEL
-app.state.config.RAG_EMBEDDING_BATCH_SIZE = RAG_EMBEDDING_BATCH_SIZE
-
-app.state.config.RAG_RERANKING_ENGINE = RAG_RERANKING_ENGINE
-app.state.config.RAG_RERANKING_MODEL = RAG_RERANKING_MODEL
-app.state.config.RAG_EXTERNAL_RERANKER_URL = RAG_EXTERNAL_RERANKER_URL
-app.state.config.RAG_EXTERNAL_RERANKER_API_KEY = RAG_EXTERNAL_RERANKER_API_KEY
-
-app.state.config.RAG_TEMPLATE = RAG_TEMPLATE
-
-app.state.config.RAG_OPENAI_API_BASE_URL = RAG_OPENAI_API_BASE_URL
-app.state.config.RAG_OPENAI_API_KEY = RAG_OPENAI_API_KEY
-
-app.state.config.RAG_AZURE_OPENAI_BASE_URL = RAG_AZURE_OPENAI_BASE_URL
-app.state.config.RAG_AZURE_OPENAI_API_KEY = RAG_AZURE_OPENAI_API_KEY
-app.state.config.RAG_AZURE_OPENAI_API_VERSION = RAG_AZURE_OPENAI_API_VERSION
-
-app.state.config.RAG_OLLAMA_BASE_URL = RAG_OLLAMA_BASE_URL
-app.state.config.RAG_OLLAMA_API_KEY = RAG_OLLAMA_API_KEY
-
-app.state.config.PDF_EXTRACT_IMAGES = PDF_EXTRACT_IMAGES
-
-app.state.config.YOUTUBE_LOADER_LANGUAGE = YOUTUBE_LOADER_LANGUAGE
-app.state.config.YOUTUBE_LOADER_PROXY_URL = YOUTUBE_LOADER_PROXY_URL
-
-
-app.state.config.ENABLE_WEB_SEARCH = ENABLE_WEB_SEARCH
-app.state.config.WEB_SEARCH_ENGINE = WEB_SEARCH_ENGINE
-app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST = WEB_SEARCH_DOMAIN_FILTER_LIST
-app.state.config.WEB_SEARCH_RESULT_COUNT = WEB_SEARCH_RESULT_COUNT
-app.state.config.WEB_SEARCH_CONCURRENT_REQUESTS = WEB_SEARCH_CONCURRENT_REQUESTS
-
-app.state.config.WEB_LOADER_ENGINE = WEB_LOADER_ENGINE
-app.state.config.WEB_LOADER_CONCURRENT_REQUESTS = WEB_LOADER_CONCURRENT_REQUESTS
-
-app.state.config.WEB_SEARCH_TRUST_ENV = WEB_SEARCH_TRUST_ENV
-app.state.config.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL = (
- BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL
-)
-app.state.config.BYPASS_WEB_SEARCH_WEB_LOADER = BYPASS_WEB_SEARCH_WEB_LOADER
-
-app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION = ENABLE_GOOGLE_DRIVE_INTEGRATION
-app.state.config.ENABLE_ONEDRIVE_INTEGRATION = ENABLE_ONEDRIVE_INTEGRATION
-
-app.state.config.OLLAMA_CLOUD_WEB_SEARCH_API_KEY = OLLAMA_CLOUD_WEB_SEARCH_API_KEY
-app.state.config.SEARXNG_QUERY_URL = SEARXNG_QUERY_URL
-app.state.config.YACY_QUERY_URL = YACY_QUERY_URL
-app.state.config.YACY_USERNAME = YACY_USERNAME
-app.state.config.YACY_PASSWORD = YACY_PASSWORD
-app.state.config.GOOGLE_PSE_API_KEY = GOOGLE_PSE_API_KEY
-app.state.config.GOOGLE_PSE_ENGINE_ID = GOOGLE_PSE_ENGINE_ID
-app.state.config.BRAVE_SEARCH_API_KEY = BRAVE_SEARCH_API_KEY
-app.state.config.KAGI_SEARCH_API_KEY = KAGI_SEARCH_API_KEY
-app.state.config.MOJEEK_SEARCH_API_KEY = MOJEEK_SEARCH_API_KEY
-app.state.config.BOCHA_SEARCH_API_KEY = BOCHA_SEARCH_API_KEY
-app.state.config.SERPSTACK_API_KEY = SERPSTACK_API_KEY
-app.state.config.SERPSTACK_HTTPS = SERPSTACK_HTTPS
-app.state.config.SERPER_API_KEY = SERPER_API_KEY
-app.state.config.SERPLY_API_KEY = SERPLY_API_KEY
-app.state.config.TAVILY_API_KEY = TAVILY_API_KEY
-app.state.config.SEARCHAPI_API_KEY = SEARCHAPI_API_KEY
-app.state.config.SEARCHAPI_ENGINE = SEARCHAPI_ENGINE
-app.state.config.SERPAPI_API_KEY = SERPAPI_API_KEY
-app.state.config.SERPAPI_ENGINE = SERPAPI_ENGINE
-app.state.config.JINA_API_KEY = JINA_API_KEY
-app.state.config.BING_SEARCH_V7_ENDPOINT = BING_SEARCH_V7_ENDPOINT
-app.state.config.BING_SEARCH_V7_SUBSCRIPTION_KEY = BING_SEARCH_V7_SUBSCRIPTION_KEY
-app.state.config.EXA_API_KEY = EXA_API_KEY
-app.state.config.PERPLEXITY_API_KEY = PERPLEXITY_API_KEY
-app.state.config.PERPLEXITY_MODEL = PERPLEXITY_MODEL
-app.state.config.PERPLEXITY_SEARCH_CONTEXT_USAGE = PERPLEXITY_SEARCH_CONTEXT_USAGE
-app.state.config.SOUGOU_API_SID = SOUGOU_API_SID
-app.state.config.SOUGOU_API_SK = SOUGOU_API_SK
-app.state.config.EXTERNAL_WEB_SEARCH_URL = EXTERNAL_WEB_SEARCH_URL
-app.state.config.EXTERNAL_WEB_SEARCH_API_KEY = EXTERNAL_WEB_SEARCH_API_KEY
-app.state.config.EXTERNAL_WEB_LOADER_URL = EXTERNAL_WEB_LOADER_URL
-app.state.config.EXTERNAL_WEB_LOADER_API_KEY = EXTERNAL_WEB_LOADER_API_KEY
-
-
-app.state.config.PLAYWRIGHT_WS_URL = PLAYWRIGHT_WS_URL
-app.state.config.PLAYWRIGHT_TIMEOUT = PLAYWRIGHT_TIMEOUT
-app.state.config.FIRECRAWL_API_BASE_URL = FIRECRAWL_API_BASE_URL
-app.state.config.FIRECRAWL_API_KEY = FIRECRAWL_API_KEY
-app.state.config.TAVILY_EXTRACT_DEPTH = TAVILY_EXTRACT_DEPTH
-
-app.state.EMBEDDING_FUNCTION = None
-app.state.RERANKING_FUNCTION = None
-app.state.ef = None
-app.state.rf = None
-
-app.state.YOUTUBE_LOADER_TRANSLATION = None
-
-
-try:
- app.state.ef = get_ef(
- app.state.config.RAG_EMBEDDING_ENGINE,
- app.state.config.RAG_EMBEDDING_MODEL,
- RAG_EMBEDDING_MODEL_AUTO_UPDATE,
- )
- if (
- app.state.config.ENABLE_RAG_HYBRID_SEARCH
- and not app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL
- ):
- app.state.rf = get_rf(
- app.state.config.RAG_RERANKING_ENGINE,
- app.state.config.RAG_RERANKING_MODEL,
- app.state.config.RAG_EXTERNAL_RERANKER_URL,
- app.state.config.RAG_EXTERNAL_RERANKER_API_KEY,
- RAG_RERANKING_MODEL_AUTO_UPDATE,
- )
- else:
- app.state.rf = None
-except Exception as e:
- log.error(f"Error updating models: {e}")
- pass
-
-
-app.state.EMBEDDING_FUNCTION = get_embedding_function(
- app.state.config.RAG_EMBEDDING_ENGINE,
- app.state.config.RAG_EMBEDDING_MODEL,
- embedding_function=app.state.ef,
- url=(
- app.state.config.RAG_OPENAI_API_BASE_URL
- if app.state.config.RAG_EMBEDDING_ENGINE == "openai"
- else (
- app.state.config.RAG_OLLAMA_BASE_URL
- if app.state.config.RAG_EMBEDDING_ENGINE == "ollama"
- else app.state.config.RAG_AZURE_OPENAI_BASE_URL
- )
- ),
- key=(
- app.state.config.RAG_OPENAI_API_KEY
- if app.state.config.RAG_EMBEDDING_ENGINE == "openai"
- else (
- app.state.config.RAG_OLLAMA_API_KEY
- if app.state.config.RAG_EMBEDDING_ENGINE == "ollama"
- else app.state.config.RAG_AZURE_OPENAI_API_KEY
- )
- ),
- embedding_batch_size=app.state.config.RAG_EMBEDDING_BATCH_SIZE,
- azure_api_version=(
- app.state.config.RAG_AZURE_OPENAI_API_VERSION
- if app.state.config.RAG_EMBEDDING_ENGINE == "azure_openai"
- else None
- ),
-)
-
-app.state.RERANKING_FUNCTION = get_reranking_function(
- app.state.config.RAG_RERANKING_ENGINE,
- app.state.config.RAG_RERANKING_MODEL,
- reranking_function=app.state.rf,
-)
-
-########################################
-#
-# CODE EXECUTION
-#
-########################################
-
-app.state.config.ENABLE_CODE_EXECUTION = ENABLE_CODE_EXECUTION
-app.state.config.CODE_EXECUTION_ENGINE = CODE_EXECUTION_ENGINE
-app.state.config.CODE_EXECUTION_JUPYTER_URL = CODE_EXECUTION_JUPYTER_URL
-app.state.config.CODE_EXECUTION_JUPYTER_AUTH = CODE_EXECUTION_JUPYTER_AUTH
-app.state.config.CODE_EXECUTION_JUPYTER_AUTH_TOKEN = CODE_EXECUTION_JUPYTER_AUTH_TOKEN
-app.state.config.CODE_EXECUTION_JUPYTER_AUTH_PASSWORD = (
- CODE_EXECUTION_JUPYTER_AUTH_PASSWORD
-)
-app.state.config.CODE_EXECUTION_JUPYTER_TIMEOUT = CODE_EXECUTION_JUPYTER_TIMEOUT
-
-app.state.config.ENABLE_CODE_INTERPRETER = ENABLE_CODE_INTERPRETER
-app.state.config.CODE_INTERPRETER_ENGINE = CODE_INTERPRETER_ENGINE
-app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE = CODE_INTERPRETER_PROMPT_TEMPLATE
-
-app.state.config.CODE_INTERPRETER_JUPYTER_URL = CODE_INTERPRETER_JUPYTER_URL
-app.state.config.CODE_INTERPRETER_JUPYTER_AUTH = CODE_INTERPRETER_JUPYTER_AUTH
-app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN = (
- CODE_INTERPRETER_JUPYTER_AUTH_TOKEN
-)
-app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD = (
- CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD
-)
-app.state.config.CODE_INTERPRETER_JUPYTER_TIMEOUT = CODE_INTERPRETER_JUPYTER_TIMEOUT
-
-########################################
-#
-# IMAGES
-#
-########################################
-
-app.state.config.IMAGE_GENERATION_ENGINE = IMAGE_GENERATION_ENGINE
-app.state.config.ENABLE_IMAGE_GENERATION = ENABLE_IMAGE_GENERATION
-app.state.config.ENABLE_IMAGE_PROMPT_GENERATION = ENABLE_IMAGE_PROMPT_GENERATION
-
-app.state.config.IMAGE_GENERATION_MODEL = IMAGE_GENERATION_MODEL
-app.state.config.IMAGE_SIZE = IMAGE_SIZE
-app.state.config.IMAGE_STEPS = IMAGE_STEPS
-
-app.state.config.IMAGES_OPENAI_API_BASE_URL = IMAGES_OPENAI_API_BASE_URL
-app.state.config.IMAGES_OPENAI_API_VERSION = IMAGES_OPENAI_API_VERSION
-app.state.config.IMAGES_OPENAI_API_KEY = IMAGES_OPENAI_API_KEY
-
-app.state.config.IMAGES_GEMINI_API_BASE_URL = IMAGES_GEMINI_API_BASE_URL
-app.state.config.IMAGES_GEMINI_API_KEY = IMAGES_GEMINI_API_KEY
-app.state.config.IMAGES_GEMINI_ENDPOINT_METHOD = IMAGES_GEMINI_ENDPOINT_METHOD
-
-app.state.config.AUTOMATIC1111_BASE_URL = AUTOMATIC1111_BASE_URL
-app.state.config.AUTOMATIC1111_API_AUTH = AUTOMATIC1111_API_AUTH
-app.state.config.AUTOMATIC1111_PARAMS = AUTOMATIC1111_PARAMS
-
-app.state.config.COMFYUI_BASE_URL = COMFYUI_BASE_URL
-app.state.config.COMFYUI_API_KEY = COMFYUI_API_KEY
-app.state.config.COMFYUI_WORKFLOW = COMFYUI_WORKFLOW
-app.state.config.COMFYUI_WORKFLOW_NODES = COMFYUI_WORKFLOW_NODES
-
-
-app.state.config.IMAGE_EDIT_ENGINE = IMAGE_EDIT_ENGINE
-app.state.config.IMAGE_EDIT_MODEL = IMAGE_EDIT_MODEL
-app.state.config.IMAGE_EDIT_SIZE = IMAGE_EDIT_SIZE
-app.state.config.IMAGES_EDIT_OPENAI_API_BASE_URL = IMAGES_EDIT_OPENAI_API_BASE_URL
-app.state.config.IMAGES_EDIT_OPENAI_API_KEY = IMAGES_EDIT_OPENAI_API_KEY
-app.state.config.IMAGES_EDIT_OPENAI_API_VERSION = IMAGES_EDIT_OPENAI_API_VERSION
-app.state.config.IMAGES_EDIT_GEMINI_API_BASE_URL = IMAGES_EDIT_GEMINI_API_BASE_URL
-app.state.config.IMAGES_EDIT_GEMINI_API_KEY = IMAGES_EDIT_GEMINI_API_KEY
-app.state.config.IMAGES_EDIT_COMFYUI_BASE_URL = IMAGES_EDIT_COMFYUI_BASE_URL
-app.state.config.IMAGES_EDIT_COMFYUI_API_KEY = IMAGES_EDIT_COMFYUI_API_KEY
-app.state.config.IMAGES_EDIT_COMFYUI_WORKFLOW = IMAGES_EDIT_COMFYUI_WORKFLOW
-app.state.config.IMAGES_EDIT_COMFYUI_WORKFLOW_NODES = IMAGES_EDIT_COMFYUI_WORKFLOW_NODES
-
-
-########################################
-#
-# AUDIO
-#
-########################################
-
-app.state.config.STT_ENGINE = AUDIO_STT_ENGINE
-app.state.config.STT_MODEL = AUDIO_STT_MODEL
-app.state.config.STT_SUPPORTED_CONTENT_TYPES = AUDIO_STT_SUPPORTED_CONTENT_TYPES
-
-app.state.config.STT_OPENAI_API_BASE_URL = AUDIO_STT_OPENAI_API_BASE_URL
-app.state.config.STT_OPENAI_API_KEY = AUDIO_STT_OPENAI_API_KEY
-
-app.state.config.WHISPER_MODEL = WHISPER_MODEL
-app.state.config.WHISPER_VAD_FILTER = WHISPER_VAD_FILTER
-app.state.config.DEEPGRAM_API_KEY = DEEPGRAM_API_KEY
-
-app.state.config.AUDIO_STT_AZURE_API_KEY = AUDIO_STT_AZURE_API_KEY
-app.state.config.AUDIO_STT_AZURE_REGION = AUDIO_STT_AZURE_REGION
-app.state.config.AUDIO_STT_AZURE_LOCALES = AUDIO_STT_AZURE_LOCALES
-app.state.config.AUDIO_STT_AZURE_BASE_URL = AUDIO_STT_AZURE_BASE_URL
-app.state.config.AUDIO_STT_AZURE_MAX_SPEAKERS = AUDIO_STT_AZURE_MAX_SPEAKERS
-
-app.state.config.AUDIO_STT_MISTRAL_API_KEY = AUDIO_STT_MISTRAL_API_KEY
-app.state.config.AUDIO_STT_MISTRAL_API_BASE_URL = AUDIO_STT_MISTRAL_API_BASE_URL
-app.state.config.AUDIO_STT_MISTRAL_USE_CHAT_COMPLETIONS = (
- AUDIO_STT_MISTRAL_USE_CHAT_COMPLETIONS
-)
-
-app.state.config.TTS_ENGINE = AUDIO_TTS_ENGINE
-
-app.state.config.TTS_MODEL = AUDIO_TTS_MODEL
-app.state.config.TTS_VOICE = AUDIO_TTS_VOICE
-
-app.state.config.TTS_OPENAI_API_BASE_URL = AUDIO_TTS_OPENAI_API_BASE_URL
-app.state.config.TTS_OPENAI_API_KEY = AUDIO_TTS_OPENAI_API_KEY
-app.state.config.TTS_OPENAI_PARAMS = AUDIO_TTS_OPENAI_PARAMS
-
-app.state.config.TTS_API_KEY = AUDIO_TTS_API_KEY
-app.state.config.TTS_SPLIT_ON = AUDIO_TTS_SPLIT_ON
-
-
-app.state.config.TTS_AZURE_SPEECH_REGION = AUDIO_TTS_AZURE_SPEECH_REGION
-app.state.config.TTS_AZURE_SPEECH_BASE_URL = AUDIO_TTS_AZURE_SPEECH_BASE_URL
-app.state.config.TTS_AZURE_SPEECH_OUTPUT_FORMAT = AUDIO_TTS_AZURE_SPEECH_OUTPUT_FORMAT
-
-
-app.state.faster_whisper_model = None
-app.state.speech_synthesiser = None
-app.state.speech_speaker_embeddings_dataset = None
-
-
-########################################
-#
-# TASKS
-#
-########################################
-
-
-app.state.config.TASK_MODEL = TASK_MODEL
-app.state.config.TASK_MODEL_EXTERNAL = TASK_MODEL_EXTERNAL
-
-
-app.state.config.ENABLE_SEARCH_QUERY_GENERATION = ENABLE_SEARCH_QUERY_GENERATION
-app.state.config.ENABLE_RETRIEVAL_QUERY_GENERATION = ENABLE_RETRIEVAL_QUERY_GENERATION
-app.state.config.ENABLE_AUTOCOMPLETE_GENERATION = ENABLE_AUTOCOMPLETE_GENERATION
-app.state.config.ENABLE_TAGS_GENERATION = ENABLE_TAGS_GENERATION
-app.state.config.ENABLE_TITLE_GENERATION = ENABLE_TITLE_GENERATION
-app.state.config.ENABLE_FOLLOW_UP_GENERATION = ENABLE_FOLLOW_UP_GENERATION
-
-
-app.state.config.TITLE_GENERATION_PROMPT_TEMPLATE = TITLE_GENERATION_PROMPT_TEMPLATE
-app.state.config.TAGS_GENERATION_PROMPT_TEMPLATE = TAGS_GENERATION_PROMPT_TEMPLATE
-app.state.config.IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE = (
- IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE
-)
-app.state.config.FOLLOW_UP_GENERATION_PROMPT_TEMPLATE = (
- FOLLOW_UP_GENERATION_PROMPT_TEMPLATE
-)
-
-app.state.config.TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE = (
- TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE
-)
-app.state.config.QUERY_GENERATION_PROMPT_TEMPLATE = QUERY_GENERATION_PROMPT_TEMPLATE
-app.state.config.AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE = (
- AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE
-)
-app.state.config.AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH = (
- AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH
-)
-
-
-########################################
-#
-# WEBUI
-#
-########################################
-
-app.state.MODELS = {}
-
-
-class RedirectMiddleware(BaseHTTPMiddleware):
- async def dispatch(self, request: Request, call_next):
- # Check if the request is a GET request
- if request.method == "GET":
- path = request.url.path
- query_params = dict(parse_qs(urlparse(str(request.url)).query))
-
- redirect_params = {}
-
- # Check for the specific watch path and the presence of 'v' parameter
- if path.endswith("/watch") and "v" in query_params:
- # Extract the first 'v' parameter
- youtube_video_id = query_params["v"][0]
- redirect_params["youtube"] = youtube_video_id
-
- if "shared" in query_params and len(query_params["shared"]) > 0:
- # PWA share_target support
-
- text = query_params["shared"][0]
- if text:
- urls = re.match(r"https://\S+", text)
- if urls:
- from open_webui.retrieval.loaders.youtube import _parse_video_id
-
- if youtube_video_id := _parse_video_id(urls[0]):
- redirect_params["youtube"] = youtube_video_id
- else:
- redirect_params["load-url"] = urls[0]
- else:
- redirect_params["q"] = text
-
- if redirect_params:
- redirect_url = f"/?{urlencode(redirect_params)}"
- return RedirectResponse(url=redirect_url)
-
- # Proceed with the normal flow of other requests
- response = await call_next(request)
- return response
-
-
-# Add the middleware to the app
-if ENABLE_COMPRESSION_MIDDLEWARE:
- app.add_middleware(CompressMiddleware)
-
-app.add_middleware(RedirectMiddleware)
-app.add_middleware(SecurityHeadersMiddleware)
-
-
-@app.middleware("http")
-async def commit_session_after_request(request: Request, call_next):
- response = await call_next(request)
- # log.debug("Commit session after request")
- Session.commit()
- return response
-
-
-@app.middleware("http")
-async def check_url(request: Request, call_next):
- start_time = int(time.time())
- request.state.token = get_http_authorization_cred(
- request.headers.get("Authorization")
- )
-
- request.state.enable_api_key = app.state.config.ENABLE_API_KEY
- response = await call_next(request)
- process_time = int(time.time()) - start_time
- response.headers["X-Process-Time"] = str(process_time)
- return response
-
-
-@app.middleware("http")
-async def inspect_websocket(request: Request, call_next):
- if (
- "/ws/socket.io" in request.url.path
- and request.query_params.get("transport") == "websocket"
- ):
- upgrade = (request.headers.get("Upgrade") or "").lower()
- connection = (request.headers.get("Connection") or "").lower().split(",")
- # Check that there's the correct headers for an upgrade, else reject the connection
- # This is to work around this upstream issue: https://github.com/miguelgrinberg/python-engineio/issues/367
- if upgrade != "websocket" or "upgrade" not in connection:
- return JSONResponse(
- status_code=status.HTTP_400_BAD_REQUEST,
- content={"detail": "Invalid WebSocket upgrade request"},
- )
- return await call_next(request)
-
-
-app.add_middleware(
- CORSMiddleware,
- allow_origins=CORS_ALLOW_ORIGIN,
- allow_credentials=True,
- allow_methods=["*"],
- allow_headers=["*"],
-)
-
-
-app.mount("/ws", socket_app)
-
-
-app.include_router(ollama.router, prefix="/ollama", tags=["ollama"])
-app.include_router(openai.router, prefix="/openai", tags=["openai"])
-
-
-app.include_router(pipelines.router, prefix="/api/v1/pipelines", tags=["pipelines"])
-app.include_router(tasks.router, prefix="/api/v1/tasks", tags=["tasks"])
-app.include_router(images.router, prefix="/api/v1/images", tags=["images"])
-
-app.include_router(audio.router, prefix="/api/v1/audio", tags=["audio"])
-app.include_router(retrieval.router, prefix="/api/v1/retrieval", tags=["retrieval"])
-
-app.include_router(configs.router, prefix="/api/v1/configs", tags=["configs"])
-
-app.include_router(auths.router, prefix="/api/v1/auths", tags=["auths"])
-app.include_router(users.router, prefix="/api/v1/users", tags=["users"])
-
-
-app.include_router(channels.router, prefix="/api/v1/channels", tags=["channels"])
-app.include_router(chats.router, prefix="/api/v1/chats", tags=["chats"])
-app.include_router(notes.router, prefix="/api/v1/notes", tags=["notes"])
-
-
-app.include_router(models.router, prefix="/api/v1/models", tags=["models"])
-app.include_router(knowledge.router, prefix="/api/v1/knowledge", tags=["knowledge"])
-app.include_router(prompts.router, prefix="/api/v1/prompts", tags=["prompts"])
-app.include_router(tools.router, prefix="/api/v1/tools", tags=["tools"])
-
-app.include_router(memories.router, prefix="/api/v1/memories", tags=["memories"])
-app.include_router(folders.router, prefix="/api/v1/folders", tags=["folders"])
-app.include_router(groups.router, prefix="/api/v1/groups", tags=["groups"])
-app.include_router(files.router, prefix="/api/v1/files", tags=["files"])
-app.include_router(functions.router, prefix="/api/v1/functions", tags=["functions"])
-app.include_router(
- evaluations.router, prefix="/api/v1/evaluations", tags=["evaluations"]
-)
-app.include_router(utils.router, prefix="/api/v1/utils", tags=["utils"])
-
-# SCIM 2.0 API for identity management
-if SCIM_ENABLED:
- app.include_router(scim.router, prefix="/api/v1/scim/v2", tags=["scim"])
-
-
-try:
- audit_level = AuditLevel(AUDIT_LOG_LEVEL)
-except ValueError as e:
- logger.error(f"Invalid audit level: {AUDIT_LOG_LEVEL}. Error: {e}")
- audit_level = AuditLevel.NONE
-
-if audit_level != AuditLevel.NONE:
- app.add_middleware(
- AuditLoggingMiddleware,
- audit_level=audit_level,
- excluded_paths=AUDIT_EXCLUDED_PATHS,
- max_body_size=MAX_BODY_LOG_SIZE,
- )
-##################################
-#
-# Chat Endpoints
-#
-##################################
-
-
-@app.get("/api/models")
-@app.get("/api/v1/models") # Experimental: Compatibility with OpenAI API
-async def get_models(
- request: Request, refresh: bool = False, user=Depends(get_verified_user)
-):
- all_models = await get_all_models(request, refresh=refresh, user=user)
-
- models = []
- for model in all_models:
- # Filter out filter pipelines
- if "pipeline" in model and model["pipeline"].get("type", None) == "filter":
- continue
-
- try:
- model_tags = [
- tag.get("name")
- for tag in model.get("info", {}).get("meta", {}).get("tags", [])
- ]
- tags = [tag.get("name") for tag in model.get("tags", [])]
-
- tags = list(set(model_tags + tags))
- model["tags"] = [{"name": tag} for tag in tags]
- except Exception as e:
- log.debug(f"Error processing model tags: {e}")
- model["tags"] = []
- pass
-
- models.append(model)
-
- model_order_list = request.app.state.config.MODEL_ORDER_LIST
- if model_order_list:
- model_order_dict = {model_id: i for i, model_id in enumerate(model_order_list)}
- # Sort models by order list priority, with fallback for those not in the list
- models.sort(
- key=lambda model: (
- model_order_dict.get(model.get("id", ""), float("inf")),
- (model.get("name", "") or ""),
- )
- )
-
- models = get_filtered_models(models, user)
-
- log.debug(
- f"/api/models returned filtered models accessible to the user: {json.dumps([model.get('id') for model in models])}"
- )
- return {"data": models}
-
-
-@app.get("/api/models/base")
-async def get_base_models(request: Request, user=Depends(get_admin_user)):
- models = await get_all_base_models(request, user=user)
- return {"data": models}
-
-
-##################################
-# Embeddings
-##################################
-
-
-@app.post("/api/embeddings")
-@app.post("/api/v1/embeddings") # Experimental: Compatibility with OpenAI API
-async def embeddings(
- request: Request, form_data: dict, user=Depends(get_verified_user)
-):
- """
- OpenAI-compatible embeddings endpoint.
-
- This handler:
- - Performs user/model checks and dispatches to the correct backend.
- - Supports OpenAI, Ollama, arena models, pipelines, and any compatible provider.
-
- Args:
- request (Request): Request context.
- form_data (dict): OpenAI-like payload (e.g., {"model": "...", "input": [...]})
- user (UserModel): Authenticated user.
-
- Returns:
- dict: OpenAI-compatible embeddings response.
- """
- # Make sure models are loaded in app state
- if not request.app.state.MODELS:
- await get_all_models(request, user=user)
- # Use generic dispatcher in utils.embeddings
- return await generate_embeddings(request, form_data, user)
-
-
-@app.post("/api/chat/completions")
-@app.post("/api/v1/chat/completions") # Experimental: Compatibility with OpenAI API
-async def chat_completion(
- request: Request,
- form_data: dict,
- user=Depends(get_verified_user),
-):
- if not request.app.state.MODELS:
- await get_all_models(request, user=user)
-
- model_id = form_data.get("model", None)
- model_item = form_data.pop("model_item", {})
- tasks = form_data.pop("background_tasks", None)
-
- metadata = {}
- try:
- if not model_item.get("direct", False):
- if model_id not in request.app.state.MODELS:
- raise Exception("Model not found")
-
- model = request.app.state.MODELS[model_id]
- model_info = Models.get_model_by_id(model_id)
-
- # Check if user has access to the model
- if not BYPASS_MODEL_ACCESS_CONTROL and (
- user.role != "admin" or not BYPASS_ADMIN_ACCESS_CONTROL
- ):
- try:
- check_model_access(user, model)
- except Exception as e:
- raise e
- else:
- model = model_item
- model_info = None
-
- request.state.direct = True
- request.state.model = model
-
- model_info_params = (
- model_info.params.model_dump() if model_info and model_info.params else {}
- )
-
- # Chat Params
- stream_delta_chunk_size = form_data.get("params", {}).get(
- "stream_delta_chunk_size"
- )
- reasoning_tags = form_data.get("params", {}).get("reasoning_tags")
-
- # Model Params
- if model_info_params.get("stream_delta_chunk_size"):
- stream_delta_chunk_size = model_info_params.get("stream_delta_chunk_size")
-
- if model_info_params.get("reasoning_tags") is not None:
- reasoning_tags = model_info_params.get("reasoning_tags")
-
- metadata = {
- "user_id": user.id,
- "chat_id": form_data.pop("chat_id", None),
- "message_id": form_data.pop("id", None),
- "session_id": form_data.pop("session_id", None),
- "filter_ids": form_data.pop("filter_ids", []),
- "tool_ids": form_data.get("tool_ids", None),
- "tool_servers": form_data.pop("tool_servers", None),
- "files": form_data.get("files", None),
- "features": form_data.get("features", {}),
- "variables": form_data.get("variables", {}),
- "model": model,
- "direct": model_item.get("direct", False),
- "params": {
- "stream_delta_chunk_size": stream_delta_chunk_size,
- "reasoning_tags": reasoning_tags,
- "function_calling": (
- "native"
- if (
- form_data.get("params", {}).get("function_calling") == "native"
- or model_info_params.get("function_calling") == "native"
- )
- else "default"
- ),
- },
- }
-
- if metadata.get("chat_id") and (user and user.role != "admin"):
- if not metadata["chat_id"].startswith("local:"):
- chat = Chats.get_chat_by_id_and_user_id(metadata["chat_id"], user.id)
- if chat is None:
- raise HTTPException(
- status_code=status.HTTP_404_NOT_FOUND,
- detail=ERROR_MESSAGES.DEFAULT(),
- )
-
- request.state.metadata = metadata
- form_data["metadata"] = metadata
-
- except Exception as e:
- log.debug(f"Error processing chat metadata: {e}")
- raise HTTPException(
- status_code=status.HTTP_400_BAD_REQUEST,
- detail=str(e),
- )
-
- async def process_chat(request, form_data, user, metadata, model):
- try:
- form_data, metadata, events = await process_chat_payload(
- request, form_data, user, metadata, model
- )
-
- response = await chat_completion_handler(request, form_data, user)
- if metadata.get("chat_id") and metadata.get("message_id"):
- try:
- if not metadata["chat_id"].startswith("local:"):
- Chats.upsert_message_to_chat_by_id_and_message_id(
- metadata["chat_id"],
- metadata["message_id"],
- {
- "model": model_id,
- },
- )
- except:
- pass
-
- return await process_chat_response(
- request, response, form_data, user, metadata, model, events, tasks
- )
- except asyncio.CancelledError:
- log.info("Chat processing was cancelled")
- try:
- event_emitter = get_event_emitter(metadata)
- await asyncio.shield(
- event_emitter(
- {"type": "chat:tasks:cancel"},
- )
- )
- except Exception as e:
- pass
- finally:
- raise # re-raise to ensure proper task cancellation handling
- except Exception as e:
- log.debug(f"Error processing chat payload: {e}")
- if metadata.get("chat_id") and metadata.get("message_id"):
- # Update the chat message with the error
- try:
- if not metadata["chat_id"].startswith("local:"):
- Chats.upsert_message_to_chat_by_id_and_message_id(
- metadata["chat_id"],
- metadata["message_id"],
- {
- "error": {"content": str(e)},
- },
- )
-
- event_emitter = get_event_emitter(metadata)
- await event_emitter(
- {
- "type": "chat:message:error",
- "data": {"error": {"content": str(e)}},
- }
- )
- await event_emitter(
- {"type": "chat:tasks:cancel"},
- )
-
- except:
- pass
- finally:
- try:
- if mcp_clients := metadata.get("mcp_clients"):
- for client in reversed(mcp_clients.values()):
- await client.disconnect()
- except Exception as e:
- log.debug(f"Error cleaning up: {e}")
- pass
-
- if (
- metadata.get("session_id")
- and metadata.get("chat_id")
- and metadata.get("message_id")
- ):
- # Asynchronous Chat Processing
- task_id, _ = await create_task(
- request.app.state.redis,
- process_chat(request, form_data, user, metadata, model),
- id=metadata["chat_id"],
- )
- return {"status": True, "task_id": task_id}
- else:
- return await process_chat(request, form_data, user, metadata, model)
-
-
-# Alias for chat_completion (Legacy)
-generate_chat_completions = chat_completion
-generate_chat_completion = chat_completion
-
-
-@app.post("/api/chat/completed")
-async def chat_completed(
- request: Request, form_data: dict, user=Depends(get_verified_user)
-):
- try:
- model_item = form_data.pop("model_item", {})
-
- if model_item.get("direct", False):
- request.state.direct = True
- request.state.model = model_item
-
- return await chat_completed_handler(request, form_data, user)
- except Exception as e:
- raise HTTPException(
- status_code=status.HTTP_400_BAD_REQUEST,
- detail=str(e),
- )
-
-
-@app.post("/api/chat/actions/{action_id}")
-async def chat_action(
- request: Request, action_id: str, form_data: dict, user=Depends(get_verified_user)
-):
- try:
- model_item = form_data.pop("model_item", {})
-
- if model_item.get("direct", False):
- request.state.direct = True
- request.state.model = model_item
-
- return await chat_action_handler(request, action_id, form_data, user)
- except Exception as e:
- raise HTTPException(
- status_code=status.HTTP_400_BAD_REQUEST,
- detail=str(e),
- )
-
-
-@app.post("/api/tasks/stop/{task_id}")
-async def stop_task_endpoint(
- request: Request, task_id: str, user=Depends(get_verified_user)
-):
- try:
- result = await stop_task(request.app.state.redis, task_id)
- return result
- except ValueError as e:
- raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
-
-
-@app.get("/api/tasks")
-async def list_tasks_endpoint(request: Request, user=Depends(get_verified_user)):
- return {"tasks": await list_tasks(request.app.state.redis)}
-
-
-@app.get("/api/tasks/chat/{chat_id}")
-async def list_tasks_by_chat_id_endpoint(
- request: Request, chat_id: str, user=Depends(get_verified_user)
-):
- chat = Chats.get_chat_by_id(chat_id)
- if chat is None or chat.user_id != user.id:
- return {"task_ids": []}
-
- task_ids = await list_task_ids_by_item_id(request.app.state.redis, chat_id)
-
- log.debug(f"Task IDs for chat {chat_id}: {task_ids}")
- return {"task_ids": task_ids}
-
-
-##################################
-#
-# Config Endpoints
-#
-##################################
-
-
-@app.get("/api/config")
-async def get_app_config(request: Request):
- user = None
- token = None
-
- auth_header = request.headers.get("Authorization")
- if auth_header:
- cred = get_http_authorization_cred(auth_header)
- if cred:
- token = cred.credentials
-
- if not token and "token" in request.cookies:
- token = request.cookies.get("token")
-
- if token:
- try:
- data = decode_token(token)
- except Exception as e:
- log.debug(e)
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Invalid token",
- )
- if data is not None and "id" in data:
- user = Users.get_user_by_id(data["id"])
-
- user_count = Users.get_num_users()
- onboarding = False
-
- if user is None:
- onboarding = user_count == 0
-
- return {
- **({"onboarding": True} if onboarding else {}),
- "status": True,
- "name": app.state.WEBUI_NAME,
- "version": VERSION,
- "default_locale": str(DEFAULT_LOCALE),
- "oauth": {
- "providers": {
- name: config.get("name", name)
- for name, config in OAUTH_PROVIDERS.items()
- }
- },
- "features": {
- "auth": WEBUI_AUTH,
- "auth_trusted_header": bool(app.state.AUTH_TRUSTED_EMAIL_HEADER),
- "enable_signup_password_confirmation": ENABLE_SIGNUP_PASSWORD_CONFIRMATION,
- "enable_ldap": app.state.config.ENABLE_LDAP,
- "enable_api_key": app.state.config.ENABLE_API_KEY,
- "enable_signup": app.state.config.ENABLE_SIGNUP,
- "enable_login_form": app.state.config.ENABLE_LOGIN_FORM,
- "enable_websocket": ENABLE_WEBSOCKET_SUPPORT,
- "enable_version_update_check": ENABLE_VERSION_UPDATE_CHECK,
- **(
- {
- "enable_direct_connections": app.state.config.ENABLE_DIRECT_CONNECTIONS,
- "enable_channels": app.state.config.ENABLE_CHANNELS,
- "enable_notes": app.state.config.ENABLE_NOTES,
- "enable_web_search": app.state.config.ENABLE_WEB_SEARCH,
- "enable_code_execution": app.state.config.ENABLE_CODE_EXECUTION,
- "enable_code_interpreter": app.state.config.ENABLE_CODE_INTERPRETER,
- "enable_image_generation": app.state.config.ENABLE_IMAGE_GENERATION,
- "enable_autocomplete_generation": app.state.config.ENABLE_AUTOCOMPLETE_GENERATION,
- "enable_community_sharing": app.state.config.ENABLE_COMMUNITY_SHARING,
- "enable_message_rating": app.state.config.ENABLE_MESSAGE_RATING,
- "enable_user_webhooks": app.state.config.ENABLE_USER_WEBHOOKS,
- "enable_admin_export": ENABLE_ADMIN_EXPORT,
- "enable_admin_chat_access": ENABLE_ADMIN_CHAT_ACCESS,
- "enable_google_drive_integration": app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION,
- "enable_onedrive_integration": app.state.config.ENABLE_ONEDRIVE_INTEGRATION,
- **(
- {
- "enable_onedrive_personal": ENABLE_ONEDRIVE_PERSONAL,
- "enable_onedrive_business": ENABLE_ONEDRIVE_BUSINESS,
- }
- if app.state.config.ENABLE_ONEDRIVE_INTEGRATION
- else {}
- ),
- }
- if user is not None
- else {}
- ),
- },
- **(
- {
- "default_models": app.state.config.DEFAULT_MODELS,
- "default_prompt_suggestions": app.state.config.DEFAULT_PROMPT_SUGGESTIONS,
- "user_count": user_count,
- "code": {
- "engine": app.state.config.CODE_EXECUTION_ENGINE,
- },
- "audio": {
- "tts": {
- "engine": app.state.config.TTS_ENGINE,
- "voice": app.state.config.TTS_VOICE,
- "split_on": app.state.config.TTS_SPLIT_ON,
- },
- "stt": {
- "engine": app.state.config.STT_ENGINE,
- },
- },
- "file": {
- "max_size": app.state.config.FILE_MAX_SIZE,
- "max_count": app.state.config.FILE_MAX_COUNT,
- "image_compression": {
- "width": app.state.config.FILE_IMAGE_COMPRESSION_WIDTH,
- "height": app.state.config.FILE_IMAGE_COMPRESSION_HEIGHT,
- },
- },
- "permissions": {**app.state.config.USER_PERMISSIONS},
- "google_drive": {
- "client_id": GOOGLE_DRIVE_CLIENT_ID.value,
- "api_key": GOOGLE_DRIVE_API_KEY.value,
- },
- "onedrive": {
- "client_id_personal": ONEDRIVE_CLIENT_ID_PERSONAL,
- "client_id_business": ONEDRIVE_CLIENT_ID_BUSINESS,
- "sharepoint_url": ONEDRIVE_SHAREPOINT_URL.value,
- "sharepoint_tenant_id": ONEDRIVE_SHAREPOINT_TENANT_ID.value,
- },
- "ui": {
- "pending_user_overlay_title": app.state.config.PENDING_USER_OVERLAY_TITLE,
- "pending_user_overlay_content": app.state.config.PENDING_USER_OVERLAY_CONTENT,
- "response_watermark": app.state.config.RESPONSE_WATERMARK,
- },
- "license_metadata": app.state.LICENSE_METADATA,
- **(
- {
- "active_entries": app.state.USER_COUNT,
- }
- if user.role == "admin"
- else {}
- ),
- }
- if user is not None and (user.role in ["admin", "user"])
- else {
- **(
- {
- "ui": {
- "pending_user_overlay_title": app.state.config.PENDING_USER_OVERLAY_TITLE,
- "pending_user_overlay_content": app.state.config.PENDING_USER_OVERLAY_CONTENT,
- }
- }
- if user and user.role == "pending"
- else {}
- ),
- **(
- {
- "metadata": {
- "login_footer": app.state.LICENSE_METADATA.get(
- "login_footer", ""
- ),
- "auth_logo_position": app.state.LICENSE_METADATA.get(
- "auth_logo_position", ""
- ),
- }
- }
- if app.state.LICENSE_METADATA
- else {}
- ),
- }
- ),
- }
-
-
-class UrlForm(BaseModel):
- url: str
-
-
-@app.get("/api/webhook")
-async def get_webhook_url(user=Depends(get_admin_user)):
- return {
- "url": app.state.config.WEBHOOK_URL,
- }
-
-
-@app.post("/api/webhook")
-async def update_webhook_url(form_data: UrlForm, user=Depends(get_admin_user)):
- app.state.config.WEBHOOK_URL = form_data.url
- app.state.WEBHOOK_URL = app.state.config.WEBHOOK_URL
- return {"url": app.state.config.WEBHOOK_URL}
-
-
-@app.get("/api/version")
-async def get_app_version():
- return {
- "version": VERSION,
- }
-
-
-@app.get("/api/version/updates")
-async def get_app_latest_release_version(user=Depends(get_verified_user)):
- if not ENABLE_VERSION_UPDATE_CHECK:
- log.debug(
- f"Version update check is disabled, returning current version as latest version"
- )
- return {"current": VERSION, "latest": VERSION}
- try:
- timeout = aiohttp.ClientTimeout(total=1)
- async with aiohttp.ClientSession(timeout=timeout, trust_env=True) as session:
- async with session.get(
- "https://api.github.com/repos/open-webui/open-webui/releases/latest",
- ssl=AIOHTTP_CLIENT_SESSION_SSL,
- ) as response:
- response.raise_for_status()
- data = await response.json()
- latest_version = data["tag_name"]
-
- return {"current": VERSION, "latest": latest_version[1:]}
- except Exception as e:
- log.debug(e)
- return {"current": VERSION, "latest": VERSION}
-
-
-@app.get("/api/changelog")
-async def get_app_changelog():
- return {key: CHANGELOG[key] for idx, key in enumerate(CHANGELOG) if idx < 5}
-
-
-@app.get("/api/usage")
-async def get_current_usage(user=Depends(get_verified_user)):
- """
- Get current usage statistics for Open WebUI.
- This is an experimental endpoint and subject to change.
- """
- try:
- return {"model_ids": get_models_in_use(), "user_ids": get_active_user_ids()}
- except Exception as e:
- log.error(f"Error getting usage statistics: {e}")
- raise HTTPException(status_code=500, detail="Internal Server Error")
-
-
-############################
-# OAuth Login & Callback
-############################
-
-
-# Initialize OAuth client manager with any MCP tool servers using OAuth 2.1
-if len(app.state.config.TOOL_SERVER_CONNECTIONS) > 0:
- for tool_server_connection in app.state.config.TOOL_SERVER_CONNECTIONS:
- if tool_server_connection.get("type", "openapi") == "mcp":
- server_id = tool_server_connection.get("info", {}).get("id")
- auth_type = tool_server_connection.get("auth_type", "none")
-
- if server_id and auth_type == "oauth_2.1":
- oauth_client_info = tool_server_connection.get("info", {}).get(
- "oauth_client_info", ""
- )
-
- try:
- oauth_client_info = decrypt_data(oauth_client_info)
- app.state.oauth_client_manager.add_client(
- f"mcp:{server_id}",
- OAuthClientInformationFull(**oauth_client_info),
- )
- except Exception as e:
- log.error(
- f"Error adding OAuth client for MCP tool server {server_id}: {e}"
- )
- pass
-
-try:
- if ENABLE_STAR_SESSIONS_MIDDLEWARE:
- redis_session_store = RedisStore(
- url=REDIS_URL,
- prefix=(f"{REDIS_KEY_PREFIX}:session:" if REDIS_KEY_PREFIX else "session:"),
- )
-
- app.add_middleware(SessionAutoloadMiddleware)
- app.add_middleware(
- StarSessionsMiddleware,
- store=redis_session_store,
- cookie_name="owui-session",
- cookie_same_site=WEBUI_SESSION_COOKIE_SAME_SITE,
- cookie_https_only=WEBUI_SESSION_COOKIE_SECURE,
- )
- log.info("Using Redis for session")
- else:
- raise ValueError("No Redis URL provided")
-except Exception as e:
- app.add_middleware(
- SessionMiddleware,
- secret_key=WEBUI_SECRET_KEY,
- session_cookie="owui-session",
- same_site=WEBUI_SESSION_COOKIE_SAME_SITE,
- https_only=WEBUI_SESSION_COOKIE_SECURE,
- )
-
-
-async def register_client(self, request, client_id: str) -> bool:
- server_type, server_id = client_id.split(":", 1)
-
- connection = None
- connection_idx = None
-
- for idx, conn in enumerate(request.app.state.config.TOOL_SERVER_CONNECTIONS or []):
- if conn.get("type", "openapi") == server_type:
- info = conn.get("info", {})
- if info.get("id") == server_id:
- connection = conn
- connection_idx = idx
- break
-
- if connection is None or connection_idx is None:
- log.warning(
- f"Unable to locate MCP tool server configuration for client {client_id} during re-registration"
- )
- return False
-
- server_url = connection.get("url")
- oauth_server_key = (connection.get("config") or {}).get("oauth_server_key")
-
- try:
- oauth_client_info = (
- await get_oauth_client_info_with_dynamic_client_registration(
- request,
- client_id,
- server_url,
- oauth_server_key,
- )
- )
- except Exception as e:
- log.error(f"Dynamic client re-registration failed for {client_id}: {e}")
- return False
-
- try:
- request.app.state.config.TOOL_SERVER_CONNECTIONS[connection_idx] = {
- **connection,
- "info": {
- **connection.get("info", {}),
- "oauth_client_info": encrypt_data(
- oauth_client_info.model_dump(mode="json")
- ),
- },
- }
- except Exception as e:
- log.error(
- f"Failed to persist updated OAuth client info for tool server {client_id}: {e}"
- )
- return False
-
- oauth_client_manager.remove_client(client_id)
- oauth_client_manager.add_client(client_id, oauth_client_info)
- log.info(f"Re-registered OAuth client {client_id} for tool server")
- return True
-
-
-@app.get("/oauth/clients/{client_id}/authorize")
-async def oauth_client_authorize(
- client_id: str,
- request: Request,
- response: Response,
- user=Depends(get_verified_user),
-):
- # ensure_valid_client_registration
- client = oauth_client_manager.get_client(client_id)
- client_info = oauth_client_manager.get_client_info(client_id)
- if client is None or client_info is None:
- raise HTTPException(status.HTTP_404_NOT_FOUND)
-
- if not await oauth_client_manager._preflight_authorization_url(client, client_info):
- log.info(
- "Detected invalid OAuth client %s; attempting re-registration",
- client_id,
- )
-
- registered = await register_client(request, client_id)
- if not registered:
- raise HTTPException(
- status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
- detail="Failed to re-register OAuth client",
- )
-
- client = oauth_client_manager.get_client(client_id)
- client_info = oauth_client_manager.get_client_info(client_id)
- if client is None or client_info is None:
- raise HTTPException(
- status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
- detail="OAuth client unavailable after re-registration",
- )
-
- if not await oauth_client_manager._preflight_authorization_url(
- client, client_info
- ):
- raise HTTPException(
- status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
- detail="OAuth client registration is still invalid after re-registration",
- )
-
- return await oauth_client_manager.handle_authorize(request, client_id=client_id)
-
-
-@app.get("/oauth/clients/{client_id}/callback")
-async def oauth_client_callback(
- client_id: str,
- request: Request,
- response: Response,
- user=Depends(get_verified_user),
-):
- return await oauth_client_manager.handle_callback(
- request,
- client_id=client_id,
- user_id=user.id if user else None,
- response=response,
- )
-
-
-@app.get("/oauth/{provider}/login")
-async def oauth_login(provider: str, request: Request):
- return await oauth_manager.handle_login(request, provider)
-
-
-# OAuth login logic is as follows:
-# 1. Attempt to find a user with matching subject ID, tied to the provider
-# 2. If OAUTH_MERGE_ACCOUNTS_BY_EMAIL is true, find a user with the email address provided via OAuth
-# - This is considered insecure in general, as OAuth providers do not always verify email addresses
-# 3. If there is no user, and ENABLE_OAUTH_SIGNUP is true, create a user
-# - Email addresses are considered unique, so we fail registration if the email address is already taken
-@app.get("/oauth/{provider}/login/callback")
-@app.get("/oauth/{provider}/callback") # Legacy endpoint
-async def oauth_login_callback(provider: str, request: Request, response: Response):
- return await oauth_manager.handle_callback(request, provider, response)
-
-
-@app.get("/manifest.json")
-async def get_manifest_json():
- if app.state.EXTERNAL_PWA_MANIFEST_URL:
- return requests.get(app.state.EXTERNAL_PWA_MANIFEST_URL).json()
- else:
- return {
- "name": app.state.WEBUI_NAME,
- "short_name": app.state.WEBUI_NAME,
- "description": f"{app.state.WEBUI_NAME} is an open, extensible, user-friendly interface for AI that adapts to your workflow.",
- "start_url": "/",
- "display": "standalone",
- "background_color": "#343541",
- "icons": [
- {
- "src": "/static/logo.png",
- "type": "image/png",
- "sizes": "500x500",
- "purpose": "any",
- },
- {
- "src": "/static/logo.png",
- "type": "image/png",
- "sizes": "500x500",
- "purpose": "maskable",
- },
- ],
- "share_target": {
- "action": "/",
- "method": "GET",
- "params": {"text": "shared"},
- },
- }
-
-
-@app.get("/opensearch.xml")
-async def get_opensearch_xml():
- xml_content = rf"""
-
- {app.state.WEBUI_NAME}
- Search {app.state.WEBUI_NAME}
- UTF-8
- {app.state.config.WEBUI_URL}/static/favicon.png
-
- {app.state.config.WEBUI_URL}
-
- """
- return Response(content=xml_content, media_type="application/xml")
-
-
-@app.get("/health")
-async def healthcheck():
- return {"status": True}
-
-
-@app.get("/health/db")
-async def healthcheck_with_db():
- Session.execute(text("SELECT 1;")).all()
- return {"status": True}
-
-
-app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
-
-
-@app.get("/cache/{path:path}")
-async def serve_cache_file(
- path: str,
- user=Depends(get_verified_user),
-):
- file_path = os.path.abspath(os.path.join(CACHE_DIR, path))
- # prevent path traversal
- if not file_path.startswith(os.path.abspath(CACHE_DIR)):
- raise HTTPException(status_code=404, detail="File not found")
- if not os.path.isfile(file_path):
- raise HTTPException(status_code=404, detail="File not found")
- return FileResponse(file_path)
+init_app_config(app)
+init_middlewares(app)
+# Setup all routes
+setup_routes(app, socket_app)
def swagger_ui_html(*args, **kwargs):
@@ -2247,11 +197,11 @@ def swagger_ui_html(*args, **kwargs):
applications.get_swagger_ui_html = swagger_ui_html
-
+BASE_PATH = "/kael"
if os.path.exists(FRONTEND_BUILD_DIR):
mimetypes.add_type("text/javascript", ".js")
app.mount(
- "/",
+ BASE_PATH,
SPAStaticFiles(directory=FRONTEND_BUILD_DIR, html=True),
name="spa-static-files",
)
diff --git a/backend/open_webui/middlewares.py b/backend/open_webui/middlewares.py
new file mode 100644
index 000000000000..43fcd33b10b4
--- /dev/null
+++ b/backend/open_webui/middlewares.py
@@ -0,0 +1,219 @@
+import logging
+import time
+import re
+
+from urllib.parse import urlencode, parse_qs, urlparse
+
+from fastapi import (
+ Request,
+ status,
+)
+
+from fastapi.middleware.cors import CORSMiddleware
+from fastapi.responses import JSONResponse, RedirectResponse
+
+from starlette_compress import CompressMiddleware
+
+from starlette.middleware.base import BaseHTTPMiddleware
+from starlette.middleware.sessions import SessionMiddleware
+
+from starsessions import (
+ SessionMiddleware as StarSessionsMiddleware,
+ SessionAutoloadMiddleware,
+)
+from starsessions.stores.redis import RedisStore
+
+from open_webui.utils import logger
+from open_webui.utils.audit import AuditLevel, AuditLoggingMiddleware
+from open_webui.internal.db import Session
+
+from open_webui.config import CORS_ALLOW_ORIGIN
+from open_webui.env import (
+ AUDIT_EXCLUDED_PATHS,
+ AUDIT_LOG_LEVEL,
+ REDIS_URL,
+ REDIS_KEY_PREFIX,
+ MAX_BODY_LOG_SIZE,
+ WEBUI_SECRET_KEY,
+ WEBUI_SESSION_COOKIE_SAME_SITE,
+ WEBUI_SESSION_COOKIE_SECURE,
+ ENABLE_COMPRESSION_MIDDLEWARE,
+ ENABLE_STAR_SESSIONS_MIDDLEWARE, SRC_LOG_LEVELS,
+)
+
+from open_webui.utils.auth import (
+ get_http_authorization_cred,
+)
+from open_webui.utils.oauth import (
+ decrypt_data,
+ OAuthClientInformationFull,
+)
+from open_webui.utils.security_headers import SecurityHeadersMiddleware
+
+log = logging.getLogger(__name__)
+log.setLevel(SRC_LOG_LEVELS["MAIN"])
+
+BASE_PATH = "/kael"
+
+
+class RedirectMiddleware(BaseHTTPMiddleware):
+ async def dispatch(self, request: Request, call_next):
+ # Check if the request is a GET request
+ if request.method == "GET":
+ path = request.url.path
+ query_params = dict(parse_qs(urlparse(str(request.url)).query))
+
+ redirect_params = {}
+
+ # Check for the specific watch path and the presence of 'v' parameter
+ if path.endswith("/watch") and "v" in query_params:
+ # Extract the first 'v' parameter
+ youtube_video_id = query_params["v"][0]
+ redirect_params["youtube"] = youtube_video_id
+
+ if "shared" in query_params and len(query_params["shared"]) > 0:
+ # PWA share_target support
+
+ text = query_params["shared"][0]
+ if text:
+ urls = re.match(r"https://\S+", text)
+ if urls:
+ from open_webui.retrieval.loaders.youtube import _parse_video_id
+
+ if youtube_video_id := _parse_video_id(urls[0]):
+ redirect_params["youtube"] = youtube_video_id
+ else:
+ redirect_params["load-url"] = urls[0]
+ else:
+ redirect_params["q"] = text
+
+ if redirect_params:
+ redirect_url = f"/?{urlencode(redirect_params)}"
+ return RedirectResponse(url=redirect_url)
+
+ # Proceed with the normal flow of other requests
+ response = await call_next(request)
+ return response
+
+
+def init_middlewares(app):
+ # Add the middleware to the app
+ if ENABLE_COMPRESSION_MIDDLEWARE:
+ app.add_middleware(CompressMiddleware)
+
+ app.add_middleware(RedirectMiddleware)
+ app.add_middleware(SecurityHeadersMiddleware)
+
+ @app.middleware("http")
+ async def commit_session_after_request(request: Request, call_next):
+ response = await call_next(request)
+ # log.debug("Commit session after request")
+ Session.commit()
+ return response
+
+ @app.middleware("http")
+ async def check_url(request: Request, call_next):
+ start_time = int(time.time())
+ request.state.token = get_http_authorization_cred(
+ request.headers.get("Authorization")
+ )
+
+ request.state.enable_api_key = app.state.config.ENABLE_API_KEY
+ response = await call_next(request)
+ process_time = int(time.time()) - start_time
+ response.headers["X-Process-Time"] = str(process_time)
+ return response
+
+ @app.middleware("http")
+ async def inspect_websocket(request: Request, call_next):
+ if (
+ f"{BASE_PATH}/ws/socket.io" in request.url.path
+ and request.query_params.get("transport") == "websocket"
+ ):
+ upgrade = (request.headers.get("Upgrade") or "").lower()
+ connection = (request.headers.get("Connection") or "").lower().split(",")
+ # Check that there's the correct headers for an upgrade, else reject the connection
+ # This is to work around this upstream issue: https://github.com/miguelgrinberg/python-engineio/issues/367
+ if upgrade != "websocket" or "upgrade" not in connection:
+ return JSONResponse(
+ status_code=status.HTTP_400_BAD_REQUEST,
+ content={"detail": "Invalid WebSocket upgrade request"},
+ )
+ return await call_next(request)
+
+ app.add_middleware(
+ CORSMiddleware,
+ allow_origins=CORS_ALLOW_ORIGIN,
+ allow_credentials=True,
+ allow_methods=["*"],
+ allow_headers=["*"],
+ )
+
+ try:
+ audit_level = AuditLevel(AUDIT_LOG_LEVEL)
+ except ValueError as e:
+ logger.error(f"Invalid audit level: {AUDIT_LOG_LEVEL}. Error: {e}")
+ audit_level = AuditLevel.NONE
+
+ if audit_level != AuditLevel.NONE:
+ app.add_middleware(
+ AuditLoggingMiddleware,
+ audit_level=audit_level,
+ excluded_paths=AUDIT_EXCLUDED_PATHS,
+ max_body_size=MAX_BODY_LOG_SIZE,
+ )
+
+ ############################
+ # OAuth Login & Callback
+ ############################
+
+ # Initialize OAuth client manager with any MCP tool servers using OAuth 2.1
+ if len(app.state.config.TOOL_SERVER_CONNECTIONS) > 0:
+ for tool_server_connection in app.state.config.TOOL_SERVER_CONNECTIONS:
+ if tool_server_connection.get("type", "openapi") == "mcp":
+ server_id = tool_server_connection.get("info", {}).get("id")
+ auth_type = tool_server_connection.get("auth_type", "none")
+
+ if server_id and auth_type == "oauth_2.1":
+ oauth_client_info = tool_server_connection.get("info", {}).get(
+ "oauth_client_info", ""
+ )
+
+ try:
+ oauth_client_info = decrypt_data(oauth_client_info)
+ app.state.oauth_client_manager.add_client(
+ f"mcp:{server_id}",
+ OAuthClientInformationFull(**oauth_client_info),
+ )
+ except Exception as e:
+ log.error(
+ f"Error adding OAuth client for MCP tool server {server_id}: {e}"
+ )
+ pass
+
+ try:
+ if ENABLE_STAR_SESSIONS_MIDDLEWARE:
+ redis_session_store = RedisStore(
+ url=REDIS_URL,
+ prefix=(f"{REDIS_KEY_PREFIX}:session:" if REDIS_KEY_PREFIX else "session:"),
+ )
+
+ app.add_middleware(SessionAutoloadMiddleware)
+ app.add_middleware(
+ StarSessionsMiddleware,
+ store=redis_session_store,
+ cookie_name="owui-session",
+ cookie_same_site=WEBUI_SESSION_COOKIE_SAME_SITE,
+ cookie_https_only=WEBUI_SESSION_COOKIE_SECURE,
+ )
+ log.info("Using Redis for session")
+ else:
+ raise ValueError("No Redis URL provided")
+ except Exception as e:
+ app.add_middleware(
+ SessionMiddleware,
+ secret_key=WEBUI_SECRET_KEY,
+ session_cookie="owui-session",
+ same_site=WEBUI_SESSION_COOKIE_SAME_SITE,
+ https_only=WEBUI_SESSION_COOKIE_SECURE,
+ )
diff --git a/backend/open_webui/models/chats.py b/backend/open_webui/models/chats.py
index c559932bcdbc..de7bb737bdac 100644
--- a/backend/open_webui/models/chats.py
+++ b/backend/open_webui/models/chats.py
@@ -1,18 +1,20 @@
import logging
-import json
import time
import uuid
from typing import Optional
+from fastapi import Request
+from open_webui.jms import chat_manager
+from open_webui.jms import SessionHandler
+from open_webui.jms.wisp.protobuf.common_pb2 import User
from open_webui.internal.db import Base, get_db
-from open_webui.models.tags import TagModel, Tag, Tags
+from open_webui.models.tags import TagModel, Tags
from open_webui.models.folders import Folders
from open_webui.env import SRC_LOG_LEVELS
from pydantic import BaseModel, ConfigDict
from sqlalchemy import BigInteger, Boolean, Column, String, Text, JSON, Index
-from sqlalchemy import or_, func, select, and_, text
-from sqlalchemy.sql import exists
+from sqlalchemy import or_, and_, text
from sqlalchemy.sql.expression import bindparam
####################
@@ -112,6 +114,7 @@ class ChatResponse(BaseModel):
archived: bool
pinned: Optional[bool] = False
meta: dict = {}
+ session_info: dict = {}
folder_id: Optional[str] = None
@@ -123,33 +126,46 @@ class ChatTitleIdResponse(BaseModel):
class ChatTable:
- def insert_new_chat(self, user_id: str, form_data: ChatForm) -> Optional[ChatModel]:
- with get_db() as db:
- id = str(uuid.uuid4())
- chat = ChatModel(
- **{
- "id": id,
- "user_id": user_id,
- "title": (
- form_data.chat["title"]
- if "title" in form_data.chat
- else "New Chat"
- ),
- "chat": form_data.chat,
- "folder_id": form_data.folder_id,
- "created_at": int(time.time()),
- "updated_at": int(time.time()),
- }
- )
+ @staticmethod
+ def get_ip(request: Request):
+ client_host, client_port = request.client or (None, None)
+ ip = client_host
+
+ xff = request.headers.get("x-forwarded-for")
+ xri = request.headers.get("x-real-ip")
+ if xff:
+ ip = xff.split(",")[0].strip()
+ elif xri:
+ ip = xri.strip()
+ return ip
+
+ def insert_new_chat(self, form_data: ChatForm, sid: str, request: Request, user: User):
+ ip = self.get_ip(request)
+ session_handler = SessionHandler(sid=sid, ip=ip, user=user)
+ chat_model = form_data.chat.get("models", [None])[0] or ''
+ session = session_handler.create_session(chat_model)
+
+ data = {
+ 'id': session.id,
+ 'user_id': session.user_id,
+ 'title': form_data.chat['title'] if 'title' in form_data.chat else 'New Chat',
+ 'chat': form_data.chat,
+ 'socket_id': sid,
+ 'folder_id': form_data.folder_id or '',
+ 'session_info': {
+ 'org_id': session.org_id,
+ 'asset': session.asset,
+ 'account': session.account,
+ 'user': session.user
+ }
+ }
- result = Chat(**chat.model_dump())
- db.add(result)
- db.commit()
- db.refresh(result)
- return ChatModel.model_validate(result) if result else None
+ chat = chat_manager.create(data)
+ return chat
+ # TODO
def import_chat(
- self, user_id: str, form_data: ChatImportForm
+ self, user_id: str, form_data: ChatImportForm
) -> Optional[ChatModel]:
with get_db() as db:
id = str(uuid.uuid4())
@@ -185,32 +201,29 @@ def import_chat(
db.refresh(result)
return ChatModel.model_validate(result) if result else None
- def update_chat_by_id(self, id: str, chat: dict) -> Optional[ChatModel]:
- try:
- with get_db() as db:
- chat_item = db.get(Chat, id)
- chat_item.chat = chat
- chat_item.title = chat["title"] if "title" in chat else "New Chat"
- chat_item.updated_at = int(time.time())
- db.commit()
- db.refresh(chat_item)
-
- return ChatModel.model_validate(chat_item)
- except Exception:
- return None
+ @staticmethod
+ def update_chat_by_id(_id: str, chat: dict) -> Optional[ChatModel]:
+ chat_dict = chat_manager.update(
+ _id,
+ {
+ 'chat': chat,
+ 'title': chat["title"] if "title" in chat else "New Chat",
+ }
+ )
+ return chat_dict
- def update_chat_title_by_id(self, id: str, title: str) -> Optional[ChatModel]:
- chat = self.get_chat_by_id(id)
- if chat is None:
+ def update_chat_title_by_id(self, _id: str, title: str) -> Optional[ChatModel]:
+ chat_dict = self.get_chat_by_id(_id)
+ if chat_dict is None:
return None
- chat = chat.chat
+ chat = chat_dict['chat']
chat["title"] = title
+ return self.update_chat_by_id(_id, chat)
- return self.update_chat_by_id(id, chat)
-
+ # TODO
def update_chat_tags_by_id(
- self, id: str, tags: list[str], user
+ self, id: str, tags: list[str], user
) -> Optional[ChatModel]:
chat = self.get_chat_by_id(id)
if chat is None:
@@ -229,41 +242,41 @@ def update_chat_tags_by_id(
self.add_chat_tag_by_id_and_user_id_and_tag_name(id, user.id, tag_name)
return self.get_chat_by_id(id)
- def get_chat_title_by_id(self, id: str) -> Optional[str]:
- chat = self.get_chat_by_id(id)
- if chat is None:
+ def get_chat_title_by_id(self, _id: str) -> Optional[str]:
+ chat_dict = self.get_chat_by_id(_id)
+ if chat_dict is None:
return None
- return chat.chat.get("title", "New Chat")
+ return chat_dict['chat'].get("title", "New Chat")
- def get_messages_map_by_chat_id(self, id: str) -> Optional[dict]:
- chat = self.get_chat_by_id(id)
- if chat is None:
+ def get_messages_map_by_chat_id(self, _id: str) -> Optional[dict]:
+ chat_dict = self.get_chat_by_id(_id)
+ if chat_dict is None:
return None
- return chat.chat.get("history", {}).get("messages", {}) or {}
+ return chat_dict['chat'].get("history", {}).get("messages", {}) or {}
def get_message_by_id_and_message_id(
- self, id: str, message_id: str
+ self, _id: str, message_id: str
) -> Optional[dict]:
- chat = self.get_chat_by_id(id)
- if chat is None:
+ chat_dict = self.get_chat_by_id(_id)
+ if chat_dict is None:
return None
- return chat.chat.get("history", {}).get("messages", {}).get(message_id, {})
+ return chat_dict['chat'].get("history", {}).get("messages", {}).get(message_id, {})
def upsert_message_to_chat_by_id_and_message_id(
- self, id: str, message_id: str, message: dict
- ) -> Optional[ChatModel]:
- chat = self.get_chat_by_id(id)
- if chat is None:
+ self, _id: str, message_id: str, message: dict
+ ):
+ chat_dict = self.get_chat_by_id(_id)
+ if chat_dict is None:
return None
# Sanitize message content for null characters before upserting
if isinstance(message.get("content"), str):
message["content"] = message["content"].replace("\x00", "")
- chat = chat.chat
+ chat = chat_dict['chat']
history = chat.get("history", {})
if message_id in history.get("messages", {}):
@@ -277,16 +290,16 @@ def upsert_message_to_chat_by_id_and_message_id(
history["currentId"] = message_id
chat["history"] = history
- return self.update_chat_by_id(id, chat)
+ return self.update_chat_by_id(_id, chat)
def add_message_status_to_chat_by_id_and_message_id(
- self, id: str, message_id: str, status: dict
- ) -> Optional[ChatModel]:
- chat = self.get_chat_by_id(id)
- if chat is None:
+ self, _id: str, message_id: str, status: dict
+ ):
+ chat_dict = self.get_chat_by_id(_id)
+ if chat_dict is None:
return None
- chat = chat.chat
+ chat = chat_dict['chat']
history = chat.get("history", {})
if message_id in history.get("messages", {}):
@@ -295,8 +308,9 @@ def add_message_status_to_chat_by_id_and_message_id(
history["messages"][message_id]["statusHistory"] = status_history
chat["history"] = history
- return self.update_chat_by_id(id, chat)
+ return self.update_chat_by_id(_id, chat)
+ # TODO
def insert_shared_chat_by_chat_id(self, chat_id: str) -> Optional[ChatModel]:
with get_db() as db:
# Get the existing chat to share
@@ -332,6 +346,7 @@ def insert_shared_chat_by_chat_id(self, chat_id: str) -> Optional[ChatModel]:
db.commit()
return shared_chat if (shared_result and result) else None
+ # TODO
def update_shared_chat_by_chat_id(self, chat_id: str) -> Optional[ChatModel]:
try:
with get_db() as db:
@@ -356,6 +371,7 @@ def update_shared_chat_by_chat_id(self, chat_id: str) -> Optional[ChatModel]:
except Exception:
return None
+ # TODO
def delete_shared_chat_by_chat_id(self, chat_id: str) -> bool:
try:
with get_db() as db:
@@ -366,206 +382,163 @@ def delete_shared_chat_by_chat_id(self, chat_id: str) -> bool:
except Exception:
return False
- def unarchive_all_chats_by_user_id(self, user_id: str) -> bool:
+ @staticmethod
+ def unarchive_all_chats_by_user_id(user_id: str) -> bool:
try:
- with get_db() as db:
- db.query(Chat).filter_by(user_id=user_id).update({"archived": False})
- db.commit()
- return True
+ chat_manager.update(data={"archived": False}, query={"user_id": user_id})
+ return True
except Exception:
return False
+ @staticmethod
def update_chat_share_id_by_id(
- self, id: str, share_id: Optional[str]
- ) -> Optional[ChatModel]:
- try:
- with get_db() as db:
- chat = db.get(Chat, id)
- chat.share_id = share_id
- db.commit()
- db.refresh(chat)
- return ChatModel.model_validate(chat)
- except Exception:
- return None
-
- def toggle_chat_pinned_by_id(self, id: str) -> Optional[ChatModel]:
- try:
- with get_db() as db:
- chat = db.get(Chat, id)
- chat.pinned = not chat.pinned
- chat.updated_at = int(time.time())
- db.commit()
- db.refresh(chat)
- return ChatModel.model_validate(chat)
- except Exception:
- return None
-
- def toggle_chat_archive_by_id(self, id: str) -> Optional[ChatModel]:
- try:
- with get_db() as db:
- chat = db.get(Chat, id)
- chat.archived = not chat.archived
- chat.updated_at = int(time.time())
- db.commit()
- db.refresh(chat)
- return ChatModel.model_validate(chat)
- except Exception:
- return None
-
- def archive_all_chats_by_user_id(self, user_id: str) -> bool:
+ _id: str, share_id: Optional[str]
+ ):
+ data = {'share_id': share_id}
+ chat_dict = chat_manager.update(_id, data)
+ return chat_dict
+
+ def toggle_chat_pinned_by_id(self, _id: str):
+ chat_dict = self.get_chat_by_id(_id)
+ pinned = not chat_dict.get('pinned', False)
+ data = {'pinned': pinned}
+ return chat_manager.update(_id, data)
+
+ def toggle_chat_archive_by_id(self, _id: str):
+ chat_dict = self.get_chat_by_id(_id)
+ archived = not chat_dict.get('archived', False)
+ data = {'archived': archived}
+ chat_dict = chat_manager.update(_id, data)
+ return chat_dict
+
+ @staticmethod
+ def archive_all_chats_by_user_id(user_id: str) -> bool:
try:
- with get_db() as db:
- db.query(Chat).filter_by(user_id=user_id).update({"archived": True})
- db.commit()
- return True
+ chat_manager.update(data={"archived": True}, query={"user_id": user_id})
+ return True
except Exception:
return False
+ @staticmethod
def get_archived_chat_list_by_user_id(
- self,
- user_id: str,
- filter: Optional[dict] = None,
- skip: int = 0,
- limit: int = 50,
- ) -> list[ChatModel]:
-
- with get_db() as db:
- query = db.query(Chat).filter_by(user_id=user_id, archived=True)
-
- if filter:
- query_key = filter.get("query")
- if query_key:
- query = query.filter(Chat.title.ilike(f"%{query_key}%"))
-
- order_by = filter.get("order_by")
- direction = filter.get("direction")
-
- if order_by and direction:
- if not getattr(Chat, order_by, None):
- raise ValueError("Invalid order_by field")
-
- if direction.lower() == "asc":
- query = query.order_by(getattr(Chat, order_by).asc())
- elif direction.lower() == "desc":
- query = query.order_by(getattr(Chat, order_by).desc())
- else:
- raise ValueError("Invalid direction for ordering")
- else:
- query = query.order_by(Chat.updated_at.desc())
-
- if skip:
- query = query.offset(skip)
- if limit:
- query = query.limit(limit)
-
- all_chats = query.all()
- return [ChatModel.model_validate(chat) for chat in all_chats]
-
+ user_id: str,
+ filter: Optional[dict] = None,
+ skip: int = 0,
+ limit: int = 50,
+ ) -> list:
+ query = {
+ 'user_id': user_id,
+ 'archived': True,
+ 'offset': skip,
+ 'limit': limit,
+ }
+
+ if filter:
+ query_key = filter.get("query")
+ if query_key:
+ query['search'] = query_key
+
+ order_by = filter.get("order_by")
+ direction = filter.get("direction")
+
+ if order_by and direction:
+ if direction.lower() == "asc":
+ query['ordering'] = 'date_updated'
+
+ resp = chat_manager.list(query=query)
+ return resp['results']
+
+ @staticmethod
def get_chat_list_by_user_id(
- self,
- user_id: str,
- include_archived: bool = False,
- filter: Optional[dict] = None,
- skip: int = 0,
- limit: int = 50,
- ) -> list[ChatModel]:
- with get_db() as db:
- query = db.query(Chat).filter_by(user_id=user_id)
- if not include_archived:
- query = query.filter_by(archived=False)
-
- if filter:
- query_key = filter.get("query")
- if query_key:
- query = query.filter(Chat.title.ilike(f"%{query_key}%"))
-
- order_by = filter.get("order_by")
- direction = filter.get("direction")
-
- if order_by and direction and getattr(Chat, order_by):
- if direction.lower() == "asc":
- query = query.order_by(getattr(Chat, order_by).asc())
- elif direction.lower() == "desc":
- query = query.order_by(getattr(Chat, order_by).desc())
- else:
- raise ValueError("Invalid direction for ordering")
- else:
- query = query.order_by(Chat.updated_at.desc())
-
- if skip:
- query = query.offset(skip)
- if limit:
- query = query.limit(limit)
-
- all_chats = query.all()
- return [ChatModel.model_validate(chat) for chat in all_chats]
-
+ user_id: str,
+ include_archived: bool = False,
+ filter: Optional[dict] = None,
+ skip: int = 0,
+ limit: int = 50,
+ ) -> list:
+ query = {
+ 'user_id': user_id,
+ 'offset': skip,
+ 'limit': limit,
+ }
+
+ if not include_archived:
+ query['archived'] = False
+
+ if filter:
+ query_key = filter.get("query")
+ if query_key:
+ query['search'] = query_key
+
+ order_by = filter.get("order_by")
+ direction = filter.get("direction")
+
+ if order_by and direction:
+ if direction.lower() == "asc":
+ query['ordering'] = 'date_updated'
+
+ resp = chat_manager.list(query=query)
+ return resp['results']
+
+ @staticmethod
def get_chat_title_id_list_by_user_id(
- self,
- user_id: str,
- include_archived: bool = False,
- include_folders: bool = False,
- include_pinned: bool = False,
- skip: Optional[int] = None,
- limit: Optional[int] = None,
+ user_id: str,
+ include_archived: bool = False,
+ include_folders: bool = False,
+ include_pinned: bool = False,
+ skip: Optional[int] = 0,
+ limit: Optional[int] = 10,
) -> list[ChatTitleIdResponse]:
- with get_db() as db:
- query = db.query(Chat).filter_by(user_id=user_id)
-
- if not include_folders:
- query = query.filter_by(folder_id=None)
-
- if not include_pinned:
- query = query.filter(or_(Chat.pinned == False, Chat.pinned == None))
-
- if not include_archived:
- query = query.filter_by(archived=False)
-
- query = query.order_by(Chat.updated_at.desc()).with_entities(
- Chat.id, Chat.title, Chat.updated_at, Chat.created_at
+ query = {
+ 'user_id': user_id,
+ 'offset': skip,
+ 'limit': limit,
+ 'fields_size': 'mini'
+ }
+
+ if not include_folders:
+ query['folder_id'] = None
+
+ if not include_pinned:
+ query['pinned'] = False
+
+ if not include_archived:
+ query['archived'] = False
+
+ resp = chat_manager.list(query=query)
+ filtered = resp['results']
+ return [
+ ChatTitleIdResponse.model_validate(
+ {
+ "id": chat['id'],
+ "title": chat['title'],
+ "updated_at": chat['updated_at'],
+ "created_at": chat['created_at'],
+ }
)
+ for chat in filtered
+ ]
- if skip:
- query = query.offset(skip)
- if limit:
- query = query.limit(limit)
-
- all_chats = query.all()
-
- # result has to be destructured from sqlalchemy `row` and mapped to a dict since the `ChatModel`is not the returned dataclass.
- return [
- ChatTitleIdResponse.model_validate(
- {
- "id": chat[0],
- "title": chat[1],
- "updated_at": chat[2],
- "created_at": chat[3],
- }
- )
- for chat in all_chats
- ]
-
+ @staticmethod
def get_chat_list_by_chat_ids(
- self, chat_ids: list[str], skip: int = 0, limit: int = 50
- ) -> list[ChatModel]:
- with get_db() as db:
- all_chats = (
- db.query(Chat)
- .filter(Chat.id.in_(chat_ids))
- .filter_by(archived=False)
- .order_by(Chat.updated_at.desc())
- .all()
- )
- return [ChatModel.model_validate(chat) for chat in all_chats]
-
- def get_chat_by_id(self, id: str) -> Optional[ChatModel]:
- try:
- with get_db() as db:
- chat = db.get(Chat, id)
- return ChatModel.model_validate(chat)
- except Exception:
- return None
-
+ chat_ids: list[str], skip: int = 0, limit: int = 50
+ ) -> list:
+ query = {
+ 'archived': False,
+ 'ids': ','.join(chat_ids),
+ 'offset': skip,
+ 'limit': limit,
+ }
+
+ resp = chat_manager.list(query=query)
+ filtered = resp['results']
+ return filtered
+
+ @staticmethod
+ def get_chat_by_id(_id: str):
+ return chat_manager.retrieve(_id)
+
+ # TODO
def get_chat_by_share_id(self, id: str) -> Optional[ChatModel]:
try:
with get_db() as db:
@@ -580,57 +553,50 @@ def get_chat_by_share_id(self, id: str) -> Optional[ChatModel]:
except Exception:
return None
- def get_chat_by_id_and_user_id(self, id: str, user_id: str) -> Optional[ChatModel]:
- try:
- with get_db() as db:
- chat = db.query(Chat).filter_by(id=id, user_id=user_id).first()
- return ChatModel.model_validate(chat)
- except Exception:
- return None
-
- def get_chats(self, skip: int = 0, limit: int = 50) -> list[ChatModel]:
- with get_db() as db:
- all_chats = (
- db.query(Chat)
- # .limit(limit).offset(skip)
- .order_by(Chat.updated_at.desc())
- )
- return [ChatModel.model_validate(chat) for chat in all_chats]
-
- def get_chats_by_user_id(self, user_id: str) -> list[ChatModel]:
- with get_db() as db:
- all_chats = (
- db.query(Chat)
- .filter_by(user_id=user_id)
- .order_by(Chat.updated_at.desc())
- )
- return [ChatModel.model_validate(chat) for chat in all_chats]
-
- def get_pinned_chats_by_user_id(self, user_id: str) -> list[ChatModel]:
- with get_db() as db:
- all_chats = (
- db.query(Chat)
- .filter_by(user_id=user_id, pinned=True, archived=False)
- .order_by(Chat.updated_at.desc())
- )
- return [ChatModel.model_validate(chat) for chat in all_chats]
-
- def get_archived_chats_by_user_id(self, user_id: str) -> list[ChatModel]:
- with get_db() as db:
- all_chats = (
- db.query(Chat)
- .filter_by(user_id=user_id, archived=True)
- .order_by(Chat.updated_at.desc())
- )
- return [ChatModel.model_validate(chat) for chat in all_chats]
+ def get_chat_by_id_and_user_id(self, _id: str, user_id: str):
+ return self.get_chat_by_id(_id)
+ # try:
+ # with get_db() as db:
+ # chat = db.query(Chat).filter_by(id=id, user_id=user_id).first()
+ # return ChatModel.model_validate(chat)
+ # except Exception:
+ # return None
+
+ @staticmethod
+ def get_chats(skip: int = 0, limit: int = 50):
+ return chat_manager.list()
+
+ @staticmethod
+ def get_chats_by_user_id(user_id: str):
+ query = {
+ 'user_id': user_id,
+ }
+ return chat_manager.list(query=query)
+
+ @staticmethod
+ def get_pinned_chats_by_user_id(user_id: str):
+ query = {
+ 'user_id': user_id,
+ 'pinned': True,
+ 'archived': False,
+ }
+ return chat_manager.list(query=query)
+
+ @staticmethod
+ def get_archived_chats_by_user_id(user_id: str):
+ query = {
+ 'user_id': user_id,
+ 'archived': True,
+ }
+ return chat_manager.list(query=query)
def get_chats_by_user_id_and_search_text(
- self,
- user_id: str,
- search_text: str,
- include_archived: bool = False,
- skip: int = 0,
- limit: int = 60,
+ self,
+ user_id: str,
+ search_text: str,
+ include_archived: bool = False,
+ skip: int = 0,
+ limit: int = 60,
) -> list[ChatModel]:
"""
Filters chats based on a search query using Python, allowing pagination using skip and limit.
@@ -644,24 +610,6 @@ def get_chats_by_user_id_and_search_text(
search_text_words = search_text.split(" ")
- # search_text might contain 'tag:tag_name' format so we need to extract the tag_name, split the search_text and remove the tags
- tag_ids = [
- word.replace("tag:", "").replace(" ", "_").lower()
- for word in search_text_words
- if word.startswith("tag:")
- ]
-
- # Extract folder names - handle spaces and case insensitivity
- folders = Folders.search_folders_by_names(
- user_id,
- [
- word.replace("folder:", "")
- for word in search_text_words
- if word.startswith("folder:")
- ],
- )
- folder_ids = [folder.id for folder in folders]
-
is_pinned = None
if "pinned:true" in search_text_words:
is_pinned = True
@@ -674,162 +622,41 @@ def get_chats_by_user_id_and_search_text(
elif "archived:false" in search_text_words:
is_archived = False
- is_shared = None
- if "shared:true" in search_text_words:
- is_shared = True
- elif "shared:false" in search_text_words:
- is_shared = False
-
search_text_words = [
word
for word in search_text_words
if (
- not word.startswith("tag:")
- and not word.startswith("folder:")
- and not word.startswith("pinned:")
- and not word.startswith("archived:")
- and not word.startswith("shared:")
+ not word.startswith("tag:")
+ and not word.startswith("folder:")
+ and not word.startswith("pinned:")
+ and not word.startswith("archived:")
+ and not word.startswith("shared:")
)
]
search_text = " ".join(search_text_words)
+ query = {
+ 'user_id': user_id,
+ 'skip': skip,
+ 'limit': limit,
+ }
- with get_db() as db:
- query = db.query(Chat).filter(Chat.user_id == user_id)
-
- if is_archived is not None:
- query = query.filter(Chat.archived == is_archived)
- elif not include_archived:
- query = query.filter(Chat.archived == False)
-
- if is_pinned is not None:
- query = query.filter(Chat.pinned == is_pinned)
+ if is_archived is not None:
+ query['archived'] = is_archived
+ elif not include_archived:
+ query['archived'] = False
- if is_shared is not None:
- if is_shared:
- query = query.filter(Chat.share_id.isnot(None))
- else:
- query = query.filter(Chat.share_id.is_(None))
-
- if folder_ids:
- query = query.filter(Chat.folder_id.in_(folder_ids))
+ if is_pinned is not None:
+ query['pinned'] = is_pinned
- query = query.order_by(Chat.updated_at.desc())
+ query['search'] = search_text
+ resp = chat_manager.list(query=query)
- # Check if the database dialect is either 'sqlite' or 'postgresql'
- dialect_name = db.bind.dialect.name
- if dialect_name == "sqlite":
- # SQLite case: using JSON1 extension for JSON searching
- sqlite_content_sql = (
- "EXISTS ("
- " SELECT 1 "
- " FROM json_each(Chat.chat, '$.messages') AS message "
- " WHERE LOWER(message.value->>'content') LIKE '%' || :content_key || '%'"
- ")"
- )
- sqlite_content_clause = text(sqlite_content_sql)
- query = query.filter(
- or_(
- Chat.title.ilike(bindparam("title_key")), sqlite_content_clause
- ).params(title_key=f"%{search_text}%", content_key=search_text)
- )
-
- # Check if there are any tags to filter, it should have all the tags
- if "none" in tag_ids:
- query = query.filter(
- text(
- """
- NOT EXISTS (
- SELECT 1
- FROM json_each(Chat.meta, '$.tags') AS tag
- )
- """
- )
- )
- elif tag_ids:
- query = query.filter(
- and_(
- *[
- text(
- f"""
- EXISTS (
- SELECT 1
- FROM json_each(Chat.meta, '$.tags') AS tag
- WHERE tag.value = :tag_id_{tag_idx}
- )
- """
- ).params(**{f"tag_id_{tag_idx}": tag_id})
- for tag_idx, tag_id in enumerate(tag_ids)
- ]
- )
- )
-
- elif dialect_name == "postgresql":
- # PostgreSQL doesn't allow null bytes in text. We filter those out by checking
- # the JSON representation for \u0000 before attempting text extraction
- postgres_content_sql = (
- "EXISTS ("
- " SELECT 1 "
- " FROM json_array_elements(Chat.chat->'messages') AS message "
- " WHERE message->'content' IS NOT NULL "
- " AND (message->'content')::text NOT LIKE '%\\u0000%' "
- " AND LOWER(message->>'content') LIKE '%' || :content_key || '%'"
- ")"
- )
- postgres_content_clause = text(postgres_content_sql)
- # Also filter out chats with null bytes in title
- query = query.filter(text("Chat.title::text NOT LIKE '%\\x00%'"))
- query = query.filter(
- or_(
- Chat.title.ilike(bindparam("title_key")),
- postgres_content_clause,
- ).params(title_key=f"%{search_text}%", content_key=search_text)
- )
-
- # Check if there are any tags to filter, it should have all the tags
- if "none" in tag_ids:
- query = query.filter(
- text(
- """
- NOT EXISTS (
- SELECT 1
- FROM json_array_elements_text(Chat.meta->'tags') AS tag
- )
- """
- )
- )
- elif tag_ids:
- query = query.filter(
- and_(
- *[
- text(
- f"""
- EXISTS (
- SELECT 1
- FROM json_array_elements_text(Chat.meta->'tags') AS tag
- WHERE tag = :tag_id_{tag_idx}
- )
- """
- ).params(**{f"tag_id_{tag_idx}": tag_id})
- for tag_idx, tag_id in enumerate(tag_ids)
- ]
- )
- )
- else:
- raise NotImplementedError(
- f"Unsupported dialect: {db.bind.dialect.name}"
- )
-
- # Perform pagination at the SQL level
- all_chats = query.offset(skip).limit(limit).all()
-
- log.info(f"The number of chats: {len(all_chats)}")
-
- # Validate and return chats
- return [ChatModel.model_validate(chat) for chat in all_chats]
+ # Validate and return chats
+ return resp['results']
def get_chats_by_folder_id_and_user_id(
- self, folder_id: str, user_id: str, skip: int = 0, limit: int = 60
+ self, folder_id: str, user_id: str, skip: int = 0, limit: int = 60
) -> list[ChatModel]:
with get_db() as db:
query = db.query(Chat).filter_by(folder_id=folder_id, user_id=user_id)
@@ -846,8 +673,9 @@ def get_chats_by_folder_id_and_user_id(
all_chats = query.all()
return [ChatModel.model_validate(chat) for chat in all_chats]
+ # TODO
def get_chats_by_folder_ids_and_user_id(
- self, folder_ids: list[str], user_id: str
+ self, folder_ids: list[str], user_id: str
) -> list[ChatModel]:
with get_db() as db:
query = db.query(Chat).filter(
@@ -861,29 +689,26 @@ def get_chats_by_folder_ids_and_user_id(
all_chats = query.all()
return [ChatModel.model_validate(chat) for chat in all_chats]
+ @staticmethod
def update_chat_folder_id_by_id_and_user_id(
- self, id: str, user_id: str, folder_id: str
- ) -> Optional[ChatModel]:
- try:
- with get_db() as db:
- chat = db.get(Chat, id)
- chat.folder_id = folder_id
- chat.updated_at = int(time.time())
- chat.pinned = False
- db.commit()
- db.refresh(chat)
- return ChatModel.model_validate(chat)
- except Exception:
- return None
-
+ _id: str, user_id: str, folder_id: str
+ ):
+ data = {
+ 'folder_id': folder_id,
+ 'pinned': False
+ }
+ return chat_manager.update(_id, data)
+
+ # TODO
def get_chat_tags_by_id_and_user_id(self, id: str, user_id: str) -> list[TagModel]:
with get_db() as db:
chat = db.get(Chat, id)
tags = chat.meta.get("tags", [])
return [Tags.get_tag_by_name_and_user_id(tag, user_id) for tag in tags]
+ # TODO
def get_chat_list_by_user_id_and_tag_name(
- self, user_id: str, tag_name: str, skip: int = 0, limit: int = 50
+ self, user_id: str, tag_name: str, skip: int = 0, limit: int = 50
) -> list[ChatModel]:
with get_db() as db:
query = db.query(Chat).filter_by(user_id=user_id)
@@ -913,15 +738,16 @@ def get_chat_list_by_user_id_and_tag_name(
log.debug(f"all_chats: {all_chats}")
return [ChatModel.model_validate(chat) for chat in all_chats]
+ # TODO
def add_chat_tag_by_id_and_user_id_and_tag_name(
- self, id: str, user_id: str, tag_name: str
+ self, _id: str, user_id: str, tag_name: str
) -> Optional[ChatModel]:
tag = Tags.get_tag_by_name_and_user_id(tag_name, user_id)
if tag is None:
tag = Tags.insert_new_tag(tag_name, user_id)
try:
with get_db() as db:
- chat = db.get(Chat, id)
+ chat = db.get(Chat, _id)
tag_id = tag.id
if tag_id not in chat.meta.get("tags", []):
@@ -936,41 +762,43 @@ def add_chat_tag_by_id_and_user_id_and_tag_name(
except Exception:
return None
- def count_chats_by_tag_name_and_user_id(self, tag_name: str, user_id: str) -> int:
- with get_db() as db: # Assuming `get_db()` returns a session object
- query = db.query(Chat).filter_by(user_id=user_id, archived=False)
-
- # Normalize the tag_name for consistency
- tag_id = tag_name.replace(" ", "_").lower()
-
- if db.bind.dialect.name == "sqlite":
- # SQLite JSON1 support for querying the tags inside the `meta` JSON field
- query = query.filter(
- text(
- f"EXISTS (SELECT 1 FROM json_each(Chat.meta, '$.tags') WHERE json_each.value = :tag_id)"
- )
- ).params(tag_id=tag_id)
-
- elif db.bind.dialect.name == "postgresql":
- # PostgreSQL JSONB support for querying the tags inside the `meta` JSON field
- query = query.filter(
- text(
- "EXISTS (SELECT 1 FROM json_array_elements_text(Chat.meta->'tags') elem WHERE elem = :tag_id)"
- )
- ).params(tag_id=tag_id)
-
- else:
- raise NotImplementedError(
- f"Unsupported dialect: {db.bind.dialect.name}"
- )
-
- # Get the count of matching records
- count = query.count()
-
- # Debugging output for inspection
- log.info(f"Count of chats for tag '{tag_name}': {count}")
-
- return count
+ @staticmethod
+ def count_chats_by_tag_name_and_user_id(tag_name: str, user_id: str) -> int:
+ return 0
+ # with get_db() as db: # Assuming `get_db()` returns a session object
+ # query = db.query(Chat).filter_by(user_id=user_id, archived=False)
+ #
+ # # Normalize the tag_name for consistency
+ # tag_id = tag_name.replace(" ", "_").lower()
+ #
+ # if db.bind.dialect.name == "sqlite":
+ # # SQLite JSON1 support for querying the tags inside the `meta` JSON field
+ # query = query.filter(
+ # text(
+ # f"EXISTS (SELECT 1 FROM json_each(Chat.meta, '$.tags') WHERE json_each.value = :tag_id)"
+ # )
+ # ).params(tag_id=tag_id)
+ #
+ # elif db.bind.dialect.name == "postgresql":
+ # # PostgreSQL JSONB support for querying the tags inside the `meta` JSON field
+ # query = query.filter(
+ # text(
+ # "EXISTS (SELECT 1 FROM json_array_elements_text(Chat.meta->'tags') elem WHERE elem = :tag_id)"
+ # )
+ # ).params(tag_id=tag_id)
+ #
+ # else:
+ # raise NotImplementedError(
+ # f"Unsupported dialect: {db.bind.dialect.name}"
+ # )
+ #
+ # # Get the count of matching records
+ # count = query.count()
+ #
+ # # Debugging output for inspection
+ # log.info(f"Count of chats for tag '{tag_name}': {count}")
+ #
+ # return count
def count_chats_by_folder_id_and_user_id(self, folder_id: str, user_id: str) -> int:
with get_db() as db:
@@ -983,82 +811,74 @@ def count_chats_by_folder_id_and_user_id(self, folder_id: str, user_id: str) ->
return count
def delete_tag_by_id_and_user_id_and_tag_name(
- self, id: str, user_id: str, tag_name: str
+ self, _id: str, user_id: str, tag_name: str
) -> bool:
try:
- with get_db() as db:
- chat = db.get(Chat, id)
- tags = chat.meta.get("tags", [])
- tag_id = tag_name.replace(" ", "_").lower()
-
- tags = [tag for tag in tags if tag != tag_id]
- chat.meta = {
- **chat.meta,
- "tags": list(set(tags)),
- }
- db.commit()
- return True
+ chat_dict = self.get_chat_by_id(_id)
+ tags = chat_dict['meta'].get("tags", [])
+ tag_id = tag_name.replace(" ", "_").lower()
+ tags = [tag for tag in tags if tag != tag_id]
+ meta = {
+ **chat_dict['meta'],
+ "tags": list(set(tags)),
+ }
+ chat_manager.update(_id, {'meta': meta})
+ return True
except Exception:
return False
- def delete_all_tags_by_id_and_user_id(self, id: str, user_id: str) -> bool:
+ def delete_all_tags_by_id_and_user_id(self, _id: str, user_id: str) -> bool:
try:
- with get_db() as db:
- chat = db.get(Chat, id)
- chat.meta = {
- **chat.meta,
+ chat_dict = self.get_chat_by_id(_id)
+ data = {
+ 'meta': {
+ **chat_dict['meta'],
"tags": [],
}
- db.commit()
-
- return True
+ }
+ chat_manager.update(_id, data)
+ return True
except Exception:
return False
- def delete_chat_by_id(self, id: str) -> bool:
+ @staticmethod
+ def delete_chat_by_id(self, _id: str) -> bool:
try:
- with get_db() as db:
- db.query(Chat).filter_by(id=id).delete()
- db.commit()
-
- return True and self.delete_shared_chat_by_chat_id(id)
+ chat_manager.destroy(_id)
+ return True
+ # return True and self.delete_shared_chat_by_chat_id(id)
except Exception:
return False
- def delete_chat_by_id_and_user_id(self, id: str, user_id: str) -> bool:
+ @staticmethod
+ def delete_chat_by_id_and_user_id(_id: str, user_id: str) -> bool:
try:
- with get_db() as db:
- db.query(Chat).filter_by(id=id, user_id=user_id).delete()
- db.commit()
-
- return True and self.delete_shared_chat_by_chat_id(id)
+ chat_manager.destroy(_id, {'user_id': user_id})
+ return True
+ # return True and self.delete_shared_chat_by_chat_id(id)
except Exception:
return False
- def delete_chats_by_user_id(self, user_id: str) -> bool:
+ @staticmethod
+ def delete_chats_by_user_id(user_id: str) -> bool:
try:
- with get_db() as db:
- self.delete_shared_chats_by_user_id(user_id)
-
- db.query(Chat).filter_by(user_id=user_id).delete()
- db.commit()
-
- return True
+ # self.delete_shared_chats_by_user_id(user_id)
+ chat_manager.destroy('', {'user_id': user_id})
+ return True
except Exception:
return False
+ @staticmethod
def delete_chats_by_user_id_and_folder_id(
- self, user_id: str, folder_id: str
+ user_id: str, folder_id: str
) -> bool:
try:
- with get_db() as db:
- db.query(Chat).filter_by(user_id=user_id, folder_id=folder_id).delete()
- db.commit()
-
- return True
+ chat_manager.destroy('', {'user_id': user_id, 'folder_id': folder_id})
+ return True
except Exception:
return False
+ # TODO
def delete_shared_chats_by_user_id(self, user_id: str) -> bool:
try:
with get_db() as db:
diff --git a/backend/open_webui/retrieval/models/external.py b/backend/open_webui/retrieval/models/external.py
index a9be526b6d18..6b3fbd5d271b 100644
--- a/backend/open_webui/retrieval/models/external.py
+++ b/backend/open_webui/retrieval/models/external.py
@@ -16,7 +16,7 @@ class ExternalReranker(BaseReranker):
def __init__(
self,
api_key: str,
- url: str = "http://localhost:8080/v1/rerank",
+ url: str = "http://localhost:8083/v1/rerank",
model: str = "reranker",
):
self.api_key = api_key
@@ -49,8 +49,8 @@ def predict(
{
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
"X-OpenWebUI-User-Id": user.id,
- "X-OpenWebUI-User-Email": user.email,
- "X-OpenWebUI-User-Role": user.role,
+ "X-OpenWebUI-User-Username": user.username,
+ "X-OpenWebUI-User-Role": 'admin',
}
if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {}
diff --git a/backend/open_webui/retrieval/utils.py b/backend/open_webui/retrieval/utils.py
index da570330b372..f56209f93da0 100644
--- a/backend/open_webui/retrieval/utils.py
+++ b/backend/open_webui/retrieval/utils.py
@@ -861,8 +861,8 @@ def generate_openai_batch_embeddings(
{
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
"X-OpenWebUI-User-Id": user.id,
- "X-OpenWebUI-User-Email": user.email,
- "X-OpenWebUI-User-Role": user.role,
+ "X-OpenWebUI-User-Username": user.username,
+ "X-OpenWebUI-User-Role": 'admin',
}
if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {}
@@ -910,8 +910,8 @@ def generate_azure_openai_batch_embeddings(
{
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
"X-OpenWebUI-User-Id": user.id,
- "X-OpenWebUI-User-Email": user.email,
- "X-OpenWebUI-User-Role": user.role,
+ "X-OpenWebUI-User-Username": user.username,
+ "X-OpenWebUI-User-Role": 'admin',
}
if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {}
@@ -960,8 +960,8 @@ def generate_ollama_batch_embeddings(
{
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
"X-OpenWebUI-User-Id": user.id,
- "X-OpenWebUI-User-Email": user.email,
- "X-OpenWebUI-User-Role": user.role,
+ "X-OpenWebUI-User-Username": user.username,
+ "X-OpenWebUI-User-Role": 'admin',
}
if ENABLE_FORWARD_USER_INFO_HEADERS
else {}
diff --git a/backend/open_webui/routers/audio.py b/backend/open_webui/routers/audio.py
index 45b4f1e69233..3eac52cc9ad9 100644
--- a/backend/open_webui/routers/audio.py
+++ b/backend/open_webui/routers/audio.py
@@ -374,8 +374,8 @@ async def speech(request: Request, user=Depends(get_verified_user)):
{
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
"X-OpenWebUI-User-Id": user.id,
- "X-OpenWebUI-User-Email": user.email,
- "X-OpenWebUI-User-Role": user.role,
+ "X-OpenWebUI-User-Username": user.username,
+ "X-OpenWebUI-User-Role": 'admin',
}
if ENABLE_FORWARD_USER_INFO_HEADERS
else {}
diff --git a/backend/open_webui/routers/auths.py b/backend/open_webui/routers/auths.py
index f261673f3874..7d2efe864d42 100644
--- a/backend/open_webui/routers/auths.py
+++ b/backend/open_webui/routers/auths.py
@@ -80,58 +80,16 @@ class SessionUserInfoResponse(SessionUserResponse):
date_of_birth: Optional[datetime.date] = None
-@router.get("/", response_model=SessionUserInfoResponse)
+@router.get("/")
async def get_session_user(
- request: Request, response: Response, user=Depends(get_current_user)
+ request: Request, user=Depends(get_current_user)
):
-
- auth_header = request.headers.get("Authorization")
- auth_token = get_http_authorization_cred(auth_header)
- token = auth_token.credentials
- data = decode_token(token)
-
- expires_at = None
-
- if data:
- expires_at = data.get("exp")
-
- if (expires_at is not None) and int(time.time()) > expires_at:
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail=ERROR_MESSAGES.INVALID_TOKEN,
- )
-
- # Set the cookie token
- response.set_cookie(
- key="token",
- value=token,
- expires=(
- datetime.datetime.fromtimestamp(expires_at, datetime.timezone.utc)
- if expires_at
- else None
- ),
- httponly=True, # Ensures the cookie is not accessible via JavaScript
- samesite=WEBUI_AUTH_COOKIE_SAME_SITE,
- secure=WEBUI_AUTH_COOKIE_SECURE,
- )
-
- user_permissions = get_permissions(
- user.id, request.app.state.config.USER_PERMISSIONS
- )
-
return {
- "token": token,
- "token_type": "Bearer",
- "expires_at": expires_at,
+ "expires_at": None,
"id": user.id,
- "email": user.email,
"name": user.name,
- "role": user.role,
- "profile_image_url": user.profile_image_url,
- "bio": user.bio,
- "gender": user.gender,
- "date_of_birth": user.date_of_birth,
- "permissions": user_permissions,
+ "role": 'admin',
+ "permissions": request.app.state.config.USER_PERMISSIONS,
}
diff --git a/backend/open_webui/routers/chats.py b/backend/open_webui/routers/chats.py
index 2587c5ff8e5d..35c9e650ba17 100644
--- a/backend/open_webui/routers/chats.py
+++ b/backend/open_webui/routers/chats.py
@@ -17,7 +17,7 @@
from open_webui.config import ENABLE_ADMIN_CHAT_ACCESS, ENABLE_ADMIN_EXPORT
from open_webui.constants import ERROR_MESSAGES
from open_webui.env import SRC_LOG_LEVELS
-from fastapi import APIRouter, Depends, HTTPException, Request, status
+from fastapi import APIRouter, Depends, HTTPException, Request, status, Header
from pydantic import BaseModel
@@ -130,17 +130,22 @@ async def get_user_chat_list_by_user_id(
@router.post("/new", response_model=Optional[ChatResponse])
-async def create_new_chat(form_data: ChatForm, user=Depends(get_verified_user)):
+async def create_new_chat(
+ form_data: ChatForm,
+ sid: str = Header(...),
+ user=Depends(get_verified_user),
+ request: Request = None
+):
try:
- chat = Chats.insert_new_chat(user.id, form_data)
- return ChatResponse(**chat.model_dump())
+ log.debug(f"Creating new chat with form_data: {form_data}, sid: {sid}, user: {user.id}")
+ chat = Chats.insert_new_chat(form_data, sid, request, user)
+ return ChatResponse(**chat)
except Exception as e:
- log.exception(e)
+ log.exception(f"Error creating new chat: {e}")
raise HTTPException(
- status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT()
+ status_code=status.HTTP_400_BAD_REQUEST, detail=f"Error creating chat: {str(e)}"
)
-
############################
# ImportChat
############################
@@ -161,7 +166,7 @@ async def import_chat(form_data: ChatImportForm, user=Depends(get_verified_user)
):
Tags.insert_new_tag(tag_name, user.id)
- return ChatResponse(**chat.model_dump())
+ return ChatResponse(**chat)
except Exception as e:
log.exception(e)
raise HTTPException(
@@ -185,7 +190,7 @@ def search_user_chats(
skip = (page - 1) * limit
chat_list = [
- ChatTitleIdResponse(**chat.model_dump())
+ ChatTitleIdResponse(**chat)
for chat in Chats.get_chats_by_user_id_and_search_text(
user.id, text, skip=skip, limit=limit
)
@@ -218,7 +223,7 @@ async def get_chats_by_folder_id(folder_id: str, user=Depends(get_verified_user)
folder_ids.extend([folder.id for folder in children_folders])
return [
- ChatResponse(**chat.model_dump())
+ ChatResponse(**chat)
for chat in Chats.get_chats_by_folder_ids_and_user_id(folder_ids, user.id)
]
@@ -253,7 +258,7 @@ async def get_chat_list_by_folder_id(
@router.get("/pinned", response_model=list[ChatTitleIdResponse])
async def get_user_pinned_chats(user=Depends(get_verified_user)):
return [
- ChatTitleIdResponse(**chat.model_dump())
+ ChatTitleIdResponse(**chat)
for chat in Chats.get_pinned_chats_by_user_id(user.id)
]
@@ -266,7 +271,7 @@ async def get_user_pinned_chats(user=Depends(get_verified_user)):
@router.get("/all", response_model=list[ChatResponse])
async def get_user_chats(user=Depends(get_verified_user)):
return [
- ChatResponse(**chat.model_dump())
+ ChatResponse(**chat)
for chat in Chats.get_chats_by_user_id(user.id)
]
@@ -279,7 +284,7 @@ async def get_user_chats(user=Depends(get_verified_user)):
@router.get("/all/archived", response_model=list[ChatResponse])
async def get_user_archived_chats(user=Depends(get_verified_user)):
return [
- ChatResponse(**chat.model_dump())
+ ChatResponse(**chat)
for chat in Chats.get_archived_chats_by_user_id(user.id)
]
@@ -313,7 +318,7 @@ async def get_all_user_chats_in_db(user=Depends(get_admin_user)):
status_code=status.HTTP_401_UNAUTHORIZED,
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
)
- return [ChatResponse(**chat.model_dump()) for chat in Chats.get_chats()]
+ return [ChatResponse(**chat) for chat in Chats.get_chats()]
############################
@@ -344,7 +349,7 @@ async def get_archived_session_user_chat_list(
filter["direction"] = direction
chat_list = [
- ChatTitleIdResponse(**chat.model_dump())
+ ChatTitleIdResponse(**chat)
for chat in Chats.get_archived_chat_list_by_user_id(
user.id,
filter=filter,
@@ -394,7 +399,7 @@ async def get_shared_chat_by_id(share_id: str, user=Depends(get_verified_user)):
chat = Chats.get_chat_by_id(share_id)
if chat:
- return ChatResponse(**chat.model_dump())
+ return ChatResponse(**chat)
else:
raise HTTPException(
@@ -434,12 +439,12 @@ async def get_user_chat_list_by_tag_name(
############################
-@router.get("/{id}", response_model=Optional[ChatResponse])
-async def get_chat_by_id(id: str, user=Depends(get_verified_user)):
- chat = Chats.get_chat_by_id_and_user_id(id, user.id)
+@router.get("/{_id}", response_model=Optional[ChatResponse])
+async def get_chat_by_id(_id: str, user=Depends(get_verified_user)):
+ chat = Chats.get_chat_by_id_and_user_id(_id, user.id)
if chat:
- return ChatResponse(**chat.model_dump())
+ return ChatResponse(**chat)
else:
raise HTTPException(
@@ -458,9 +463,9 @@ async def update_chat_by_id(
):
chat = Chats.get_chat_by_id_and_user_id(id, user.id)
if chat:
- updated_chat = {**chat.chat, **form_data.chat}
+ updated_chat = {**chat['chat'], **form_data.chat}
chat = Chats.update_chat_by_id(id, updated_chat)
- return ChatResponse(**chat.model_dump())
+ return ChatResponse(**chat)
else:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
@@ -522,7 +527,7 @@ async def update_chat_message_by_id(
}
)
- return ChatResponse(**chat.model_dump())
+ return ChatResponse(**chat)
############################
@@ -561,7 +566,7 @@ async def send_chat_message_event_by_id(
try:
if event_emitter:
- await event_emitter(form_data.model_dump())
+ await event_emitter(form_data)
else:
return False
return True
@@ -670,7 +675,7 @@ async def clone_chat_by_id(
),
)
- return ChatResponse(**chat.model_dump())
+ return ChatResponse(**chat)
else:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.DEFAULT()
@@ -709,7 +714,7 @@ async def clone_shared_chat_by_id(id: str, user=Depends(get_verified_user)):
}
),
)
- return ChatResponse(**chat.model_dump())
+ return ChatResponse(**chat)
else:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.DEFAULT()
@@ -740,7 +745,7 @@ async def archive_chat_by_id(id: str, user=Depends(get_verified_user)):
log.debug(f"inserting tag: {tag_id}")
tag = Tags.insert_new_tag(tag_id, user.id)
- return ChatResponse(**chat.model_dump())
+ return ChatResponse(**chat)
else:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.DEFAULT()
@@ -769,7 +774,7 @@ async def share_chat_by_id(request: Request, id: str, user=Depends(get_verified_
if chat:
if chat.share_id:
shared_chat = Chats.update_shared_chat_by_chat_id(chat.id)
- return ChatResponse(**shared_chat.model_dump())
+ return ChatResponse(**shared_chat)
shared_chat = Chats.insert_shared_chat_by_chat_id(chat.id)
if not shared_chat:
@@ -777,7 +782,7 @@ async def share_chat_by_id(request: Request, id: str, user=Depends(get_verified_
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=ERROR_MESSAGES.DEFAULT(),
)
- return ChatResponse(**shared_chat.model_dump())
+ return ChatResponse(**shared_chat)
else:
raise HTTPException(
@@ -827,7 +832,7 @@ async def update_chat_folder_id_by_id(
chat = Chats.update_chat_folder_id_by_id_and_user_id(
id, user.id, form_data.folder_id
)
- return ChatResponse(**chat.model_dump())
+ return ChatResponse(**chat)
else:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.DEFAULT()
@@ -839,11 +844,11 @@ async def update_chat_folder_id_by_id(
############################
-@router.get("/{id}/tags", response_model=list[TagModel])
-async def get_chat_tags_by_id(id: str, user=Depends(get_verified_user)):
- chat = Chats.get_chat_by_id_and_user_id(id, user.id)
+@router.get("/{_id}/tags", response_model=list[TagModel])
+async def get_chat_tags_by_id(_id: str, user=Depends(get_verified_user)):
+ chat = Chats.get_chat_by_id_and_user_id(_id, user.id)
if chat:
- tags = chat.meta.get("tags", [])
+ tags = chat['meta'].get("tags", [])
return Tags.get_tags_by_ids_and_user_id(tags, user.id)
else:
raise HTTPException(
diff --git a/backend/open_webui/routers/common.py b/backend/open_webui/routers/common.py
new file mode 100644
index 000000000000..46e39873b803
--- /dev/null
+++ b/backend/open_webui/routers/common.py
@@ -0,0 +1,856 @@
+import asyncio
+import json
+import logging
+import os
+import datetime as dt
+from pydantic import BaseModel
+from sqlalchemy import text
+import aiohttp
+import requests
+
+from fastapi import (
+ Depends,
+ HTTPException,
+ Request,
+ status,
+)
+
+from fastapi.responses import FileResponse
+
+from starlette.responses import Response
+
+from open_webui.socket.main import (
+ get_event_emitter,
+ get_models_in_use,
+ get_active_user_ids,
+)
+from open_webui.internal.db import Session
+from open_webui.models.models import Models
+from open_webui.models.users import UserModel, Users
+from open_webui.models.chats import Chats
+
+from open_webui.config import (
+ # Retrieval (Web Search)
+ GOOGLE_DRIVE_CLIENT_ID,
+ GOOGLE_DRIVE_API_KEY,
+ ONEDRIVE_CLIENT_ID_PERSONAL,
+ ONEDRIVE_CLIENT_ID_BUSINESS,
+ ONEDRIVE_SHAREPOINT_URL,
+ ONEDRIVE_SHAREPOINT_TENANT_ID,
+ ENABLE_ONEDRIVE_PERSONAL,
+ ENABLE_ONEDRIVE_BUSINESS,
+ # WebUI
+ WEBUI_AUTH,
+ # Misc
+ CACHE_DIR,
+ DEFAULT_LOCALE,
+ OAUTH_PROVIDERS,
+ # Admin
+ ENABLE_ADMIN_CHAT_ACCESS,
+ BYPASS_ADMIN_ACCESS_CONTROL,
+ ENABLE_ADMIN_EXPORT,
+)
+from open_webui.env import (
+ CHANGELOG,
+ VERSION,
+ ENABLE_SIGNUP_PASSWORD_CONFIRMATION,
+ # SCIM
+ ENABLE_WEBSOCKET_SUPPORT,
+ BYPASS_MODEL_ACCESS_CONTROL,
+ ENABLE_VERSION_UPDATE_CHECK,
+ AIOHTTP_CLIENT_SESSION_SSL, SRC_LOG_LEVELS,
+)
+
+from open_webui.utils.models import (
+ get_all_models,
+ get_all_base_models,
+ check_model_access,
+ get_filtered_models,
+)
+from open_webui.utils.chat import (
+ generate_chat_completion as chat_completion_handler,
+ chat_completed as chat_completed_handler,
+ chat_action as chat_action_handler,
+)
+from open_webui.utils.embeddings import generate_embeddings
+from open_webui.utils.middleware import process_chat_payload, process_chat_response
+
+from open_webui.utils.auth import (
+ get_http_authorization_cred,
+ decode_token,
+ get_admin_user,
+ get_verified_user,
+)
+from open_webui.utils.oauth import (
+ get_oauth_client_info_with_dynamic_client_registration,
+ encrypt_data, OAuthClientManager, OAuthManager,
+)
+
+from open_webui.tasks import (
+ list_task_ids_by_item_id,
+ create_task,
+ stop_task,
+ list_tasks,
+) # Import from tasks.py
+
+from open_webui.constants import ERROR_MESSAGES
+
+log = logging.getLogger(__name__)
+log.setLevel(SRC_LOG_LEVELS["MAIN"])
+
+BASE_PATH = "/kael"
+
+
+def setup_lazy_routes(app):
+ oauth_client_manager = OAuthClientManager(app)
+ oauth_manager = OAuthManager(app)
+
+ ##################################
+ #
+ # Chat Endpoints
+ #
+ ##################################
+
+ @app.get(f"{BASE_PATH}/api/models")
+ @app.get(f"{BASE_PATH}/api/v1/models") # Experimental: Compatibility with OpenAI API
+ async def get_models(
+ request: Request, refresh: bool = False, user=Depends(get_verified_user)
+ ):
+ all_models = await get_all_models(request, refresh=refresh, user=user)
+
+ models = []
+ for model in all_models:
+ # Filter out filter pipelines
+ if "pipeline" in model and model["pipeline"].get("type", None) == "filter":
+ continue
+
+ try:
+ model_tags = [
+ tag.get("name")
+ for tag in model.get("info", {}).get("meta", {}).get("tags", [])
+ ]
+ tags = [tag.get("name") for tag in model.get("tags", [])]
+
+ tags = list(set(model_tags + tags))
+ model["tags"] = [{"name": tag} for tag in tags]
+ except Exception as e:
+ log.debug(f"Error processing model tags: {e}")
+ model["tags"] = []
+ pass
+
+ models.append(model)
+
+ model_order_list = request.app.state.config.MODEL_ORDER_LIST
+ if model_order_list:
+ model_order_dict = {model_id: i for i, model_id in enumerate(model_order_list)}
+ # Sort models by order list priority, with fallback for those not in the list
+ models.sort(
+ key=lambda model: (
+ model_order_dict.get(model.get("id", ""), float("inf")),
+ (model.get("name", "") or ""),
+ )
+ )
+
+ models = get_filtered_models(models, user)
+
+ log.debug(
+ f"/api/models returned filtered models accessible to the user: {json.dumps([model.get('id') for model in models])}"
+ )
+ return {"data": models}
+
+ @app.get(f"{BASE_PATH}/api/models/base")
+ async def get_base_models(request: Request, user=Depends(get_admin_user)):
+ models = await get_all_base_models(request, user=user)
+ return {"data": models}
+
+ ##################################
+ # Embeddings
+ ##################################
+
+ @app.post(f"{BASE_PATH}/api/embeddings")
+ @app.post(f"{BASE_PATH}/api/v1/embeddings") # Experimental: Compatibility with OpenAI API
+ async def embeddings(
+ request: Request, form_data: dict, user=Depends(get_verified_user)
+ ):
+ """
+ OpenAI-compatible embeddings endpoint.
+
+ This handler:
+ - Performs user/model checks and dispatches to the correct backend.
+ - Supports OpenAI, Ollama, arena models, pipelines, and any compatible provider.
+
+ Args:
+ request (Request): Request context.
+ form_data (dict): OpenAI-like payload (e.g., {"model": "...", "input": [...]})
+ user (UserModel): Authenticated user.
+
+ Returns:
+ dict: OpenAI-compatible embeddings response.
+ """
+ # Make sure models are loaded in app state
+ if not request.app.state.MODELS:
+ await get_all_models(request, user=user)
+ # Use generic dispatcher in utils.embeddings
+ return await generate_embeddings(request, form_data, user)
+
+ @app.post(f"{BASE_PATH}/api/chat/completions")
+ @app.post(f"{BASE_PATH}/api/v1/chat/completions") # Experimental: Compatibility with OpenAI API
+ async def chat_completion(
+ request: Request,
+ form_data: dict,
+ user=Depends(get_verified_user),
+ ):
+ if not request.app.state.MODELS:
+ await get_all_models(request, user=user)
+
+ model_id = form_data.get("model", None)
+ model_item = form_data.pop("model_item", {})
+ tasks = form_data.pop("background_tasks", None)
+
+ metadata = {}
+ try:
+ if not model_item.get("direct", False):
+ if model_id not in request.app.state.MODELS:
+ raise Exception("Model not found")
+
+ model = request.app.state.MODELS[model_id]
+ # model_info = Models.get_model_by_id(model_id)
+ model_info = None
+
+ # Check if user has access to the model
+ # if not BYPASS_MODEL_ACCESS_CONTROL and (
+ # user.role != "admin" or not BYPASS_ADMIN_ACCESS_CONTROL
+ # ):
+ # try:
+ # check_model_access(user, model)
+ # except Exception as e:
+ # raise e
+ else:
+ model = model_item
+ model_info = None
+
+ request.state.direct = True
+ request.state.model = model
+
+ model_info_params = (
+ model_info.params.model_dump() if model_info and model_info.params else {}
+ )
+
+ # Chat Params
+ stream_delta_chunk_size = form_data.get("params", {}).get(
+ "stream_delta_chunk_size"
+ )
+ reasoning_tags = form_data.get("params", {}).get("reasoning_tags")
+
+ # Model Params
+ if model_info_params.get("stream_delta_chunk_size"):
+ stream_delta_chunk_size = model_info_params.get("stream_delta_chunk_size")
+
+ if model_info_params.get("reasoning_tags") is not None:
+ reasoning_tags = model_info_params.get("reasoning_tags")
+
+ metadata = {
+ "user_id": user.id,
+ "chat_id": form_data.pop("chat_id", None),
+ "message_id": form_data.pop("id", None),
+ "session_id": form_data.pop("session_id", None),
+ "filter_ids": form_data.pop("filter_ids", []),
+ "tool_ids": form_data.get("tool_ids", None),
+ "tool_servers": form_data.pop("tool_servers", None),
+ "files": form_data.get("files", None),
+ "features": form_data.get("features", {}),
+ "variables": form_data.get("variables", {}),
+ "model": model,
+ "direct": model_item.get("direct", False),
+ "params": {
+ "stream_delta_chunk_size": stream_delta_chunk_size,
+ "reasoning_tags": reasoning_tags,
+ "function_calling": (
+ "native"
+ if (
+ form_data.get("params", {}).get("function_calling") == "native"
+ or model_info_params.get("function_calling") == "native"
+ )
+ else "default"
+ ),
+ },
+ }
+
+ if metadata.get("chat_id") and (user and user.role != "admin"):
+ if not metadata["chat_id"].startswith("local:"):
+ chat = Chats.get_chat_by_id_and_user_id(metadata["chat_id"], user.id)
+ if chat is None:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND,
+ detail=ERROR_MESSAGES.DEFAULT(),
+ )
+
+ request.state.metadata = metadata
+ form_data["metadata"] = metadata
+
+ except Exception as e:
+ log.debug(f"Error processing chat metadata: {e}")
+ raise HTTPException(
+ status_code=status.HTTP_400_BAD_REQUEST,
+ detail=str(e),
+ )
+
+ async def process_chat(request, form_data, user, metadata, model):
+ try:
+ form_data, metadata, events = await process_chat_payload(
+ request, form_data, user, metadata, model
+ )
+
+ response = await chat_completion_handler(request, form_data, user)
+ if metadata.get("chat_id") and metadata.get("message_id"):
+ try:
+ if not metadata["chat_id"].startswith("local:"):
+ Chats.upsert_message_to_chat_by_id_and_message_id(
+ metadata["chat_id"],
+ metadata["message_id"],
+ {
+ "model": model_id,
+ },
+ )
+ except:
+ pass
+
+ return await process_chat_response(
+ request, response, form_data, user, metadata, model, events, tasks
+ )
+ except asyncio.CancelledError:
+ log.info("Chat processing was cancelled")
+ try:
+ event_emitter = get_event_emitter(metadata)
+ await asyncio.shield(
+ event_emitter(
+ {"type": "chat:tasks:cancel"},
+ )
+ )
+ except Exception as e:
+ pass
+ finally:
+ raise # re-raise to ensure proper task cancellation handling
+ except Exception as e:
+ log.debug(f"Error processing chat payload: {e}")
+ if metadata.get("chat_id") and metadata.get("message_id"):
+ # Update the chat message with the error
+ try:
+ if not metadata["chat_id"].startswith("local:"):
+ Chats.upsert_message_to_chat_by_id_and_message_id(
+ metadata["chat_id"],
+ metadata["message_id"],
+ {
+ "error": {"content": str(e)},
+ },
+ )
+
+ event_emitter = get_event_emitter(metadata)
+ await event_emitter(
+ {
+ "type": "chat:message:error",
+ "data": {"error": {"content": str(e)}},
+ }
+ )
+ await event_emitter(
+ {"type": "chat:tasks:cancel"},
+ )
+
+ except:
+ pass
+ finally:
+ try:
+ if mcp_clients := metadata.get("mcp_clients"):
+ for client in reversed(mcp_clients.values()):
+ await client.disconnect()
+ except Exception as e:
+ log.debug(f"Error cleaning up: {e}")
+ pass
+
+ if (
+ metadata.get("session_id")
+ and metadata.get("chat_id")
+ and metadata.get("message_id")
+ ):
+ # Asynchronous Chat Processing
+ task_id, _ = await create_task(
+ request.app.state.redis,
+ process_chat(request, form_data, user, metadata, model),
+ id=metadata["chat_id"],
+ )
+ return {"status": True, "task_id": task_id}
+ else:
+ return await process_chat(request, form_data, user, metadata, model)
+
+ # Alias for chat_completion (Legacy)
+ generate_chat_completions = chat_completion
+ generate_chat_completion = chat_completion
+
+ @app.post(f"{BASE_PATH}/api/chat/completed")
+ async def chat_completed(
+ request: Request, form_data: dict, user=Depends(get_verified_user)
+ ):
+ try:
+ model_item = form_data.pop("model_item", {})
+
+ if model_item.get("direct", False):
+ request.state.direct = True
+ request.state.model = model_item
+
+ return await chat_completed_handler(request, form_data, user)
+ except Exception as e:
+ raise HTTPException(
+ status_code=status.HTTP_400_BAD_REQUEST,
+ detail=str(e),
+ )
+
+ @app.post(BASE_PATH + "/api/chat/actions/{action_id}")
+ async def chat_action(
+ request: Request, action_id: str, form_data: dict, user=Depends(get_verified_user)
+ ):
+ try:
+ model_item = form_data.pop("model_item", {})
+
+ if model_item.get("direct", False):
+ request.state.direct = True
+ request.state.model = model_item
+
+ return await chat_action_handler(request, action_id, form_data, user)
+ except Exception as e:
+ raise HTTPException(
+ status_code=status.HTTP_400_BAD_REQUEST,
+ detail=str(e),
+ )
+
+ @app.post(BASE_PATH + "/api/tasks/stop/{task_id}")
+ async def stop_task_endpoint(
+ request: Request, task_id: str, user=Depends(get_verified_user)
+ ):
+ try:
+ result = await stop_task(request.app.state.redis, task_id)
+ return result
+ except ValueError as e:
+ raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
+
+ @app.get(f"{BASE_PATH}/api/tasks")
+ async def list_tasks_endpoint(request: Request, user=Depends(get_verified_user)):
+ return {"tasks": await list_tasks(request.app.state.redis)}
+
+ @app.get(BASE_PATH + "/api/tasks/chat/{chat_id}")
+ async def list_tasks_by_chat_id_endpoint(
+ request: Request, chat_id: str, user=Depends(get_verified_user)
+ ):
+ chat = Chats.get_chat_by_id(chat_id)
+ if chat is None or chat.user_id != user.id:
+ return {"task_ids": []}
+
+ task_ids = await list_task_ids_by_item_id(request.app.state.redis, chat_id)
+
+ log.debug(f"Task IDs for chat {chat_id}: {task_ids}")
+ return {"task_ids": task_ids}
+
+ ##################################
+ #
+ # Config Endpoints
+ #
+ ##################################
+
+ @app.get(f"{BASE_PATH}/api/config")
+ async def get_app_config(request: Request, user=Depends(get_verified_user)):
+ user_count = 1
+ onboarding = False
+
+ if user is None:
+ onboarding = user_count == 0
+
+ return {
+ **({"onboarding": True} if onboarding else {}),
+ "status": True,
+ "name": app.state.WEBUI_NAME,
+ "version": VERSION,
+ "default_locale": str(DEFAULT_LOCALE),
+ "oauth": {
+ "providers": {
+ name: config.get("name", name)
+ for name, config in OAUTH_PROVIDERS.items()
+ }
+ },
+ "features": {
+ "auth": WEBUI_AUTH,
+ "auth_trusted_header": bool(app.state.AUTH_TRUSTED_EMAIL_HEADER),
+ "enable_signup_password_confirmation": ENABLE_SIGNUP_PASSWORD_CONFIRMATION,
+ "enable_ldap": app.state.config.ENABLE_LDAP,
+ "enable_api_key": app.state.config.ENABLE_API_KEY,
+ "enable_signup": app.state.config.ENABLE_SIGNUP,
+ "enable_login_form": app.state.config.ENABLE_LOGIN_FORM,
+ "enable_websocket": ENABLE_WEBSOCKET_SUPPORT,
+ "enable_version_update_check": ENABLE_VERSION_UPDATE_CHECK,
+ **(
+ {
+ "enable_direct_connections": app.state.config.ENABLE_DIRECT_CONNECTIONS,
+ "enable_channels": app.state.config.ENABLE_CHANNELS,
+ "enable_notes": app.state.config.ENABLE_NOTES,
+ "enable_web_search": app.state.config.ENABLE_WEB_SEARCH,
+ "enable_code_execution": app.state.config.ENABLE_CODE_EXECUTION,
+ "enable_code_interpreter": app.state.config.ENABLE_CODE_INTERPRETER,
+ "enable_image_generation": app.state.config.ENABLE_IMAGE_GENERATION,
+ "enable_autocomplete_generation": app.state.config.ENABLE_AUTOCOMPLETE_GENERATION,
+ "enable_community_sharing": app.state.config.ENABLE_COMMUNITY_SHARING,
+ "enable_message_rating": app.state.config.ENABLE_MESSAGE_RATING,
+ "enable_user_webhooks": app.state.config.ENABLE_USER_WEBHOOKS,
+ "enable_admin_export": ENABLE_ADMIN_EXPORT,
+ "enable_admin_chat_access": ENABLE_ADMIN_CHAT_ACCESS,
+ "enable_google_drive_integration": app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION,
+ "enable_onedrive_integration": app.state.config.ENABLE_ONEDRIVE_INTEGRATION,
+ **(
+ {
+ "enable_onedrive_personal": ENABLE_ONEDRIVE_PERSONAL,
+ "enable_onedrive_business": ENABLE_ONEDRIVE_BUSINESS,
+ }
+ if app.state.config.ENABLE_ONEDRIVE_INTEGRATION
+ else {}
+ ),
+ }
+ if user is not None
+ else {}
+ ),
+ },
+ **(
+ {
+ "default_models": app.state.config.DEFAULT_MODELS,
+ "default_prompt_suggestions": app.state.config.DEFAULT_PROMPT_SUGGESTIONS,
+ "user_count": user_count,
+ "code": {
+ "engine": app.state.config.CODE_EXECUTION_ENGINE,
+ },
+ "audio": {
+ "tts": {
+ "engine": app.state.config.TTS_ENGINE,
+ "voice": app.state.config.TTS_VOICE,
+ "split_on": app.state.config.TTS_SPLIT_ON,
+ },
+ "stt": {
+ "engine": app.state.config.STT_ENGINE,
+ },
+ },
+ "file": {
+ "max_size": app.state.config.FILE_MAX_SIZE,
+ "max_count": app.state.config.FILE_MAX_COUNT,
+ "image_compression": {
+ "width": app.state.config.FILE_IMAGE_COMPRESSION_WIDTH,
+ "height": app.state.config.FILE_IMAGE_COMPRESSION_HEIGHT,
+ },
+ },
+ "permissions": {**app.state.config.USER_PERMISSIONS},
+ "google_drive": {
+ "client_id": GOOGLE_DRIVE_CLIENT_ID.value,
+ "api_key": GOOGLE_DRIVE_API_KEY.value,
+ },
+ "onedrive": {
+ "client_id_personal": ONEDRIVE_CLIENT_ID_PERSONAL,
+ "client_id_business": ONEDRIVE_CLIENT_ID_BUSINESS,
+ "sharepoint_url": ONEDRIVE_SHAREPOINT_URL.value,
+ "sharepoint_tenant_id": ONEDRIVE_SHAREPOINT_TENANT_ID.value,
+ },
+ "ui": {
+ "pending_user_overlay_title": app.state.config.PENDING_USER_OVERLAY_TITLE,
+ "pending_user_overlay_content": app.state.config.PENDING_USER_OVERLAY_CONTENT,
+ "response_watermark": app.state.config.RESPONSE_WATERMARK,
+ },
+ "license_metadata": app.state.LICENSE_METADATA,
+ "active_entries": app.state.USER_COUNT,
+ }
+ if user is not None
+ else {
+ **(
+ {
+ "ui": {
+ "pending_user_overlay_title": app.state.config.PENDING_USER_OVERLAY_TITLE,
+ "pending_user_overlay_content": app.state.config.PENDING_USER_OVERLAY_CONTENT,
+ }
+ }
+ if user and user.role == "pending"
+ else {}
+ ),
+ **(
+ {
+ "metadata": {
+ "login_footer": app.state.LICENSE_METADATA.get(
+ "login_footer", ""
+ ),
+ "auth_logo_position": app.state.LICENSE_METADATA.get(
+ "auth_logo_position", ""
+ ),
+ }
+ }
+ if app.state.LICENSE_METADATA
+ else {}
+ ),
+ }
+ ),
+ }
+
+ class UrlForm(BaseModel):
+ url: str
+
+ @app.get(f"{BASE_PATH}/api/webhook")
+ async def get_webhook_url(user=Depends(get_admin_user)):
+ return {
+ "url": app.state.config.WEBHOOK_URL,
+ }
+
+ @app.post(f"{BASE_PATH}/api/webhook")
+ async def update_webhook_url(form_data: UrlForm, user=Depends(get_admin_user)):
+ app.state.config.WEBHOOK_URL = form_data.url
+ app.state.WEBHOOK_URL = app.state.config.WEBHOOK_URL
+ return {"url": app.state.config.WEBHOOK_URL}
+
+ @app.get(f"{BASE_PATH}/api/version")
+ async def get_app_version():
+ return {
+ "version": VERSION,
+ }
+
+ @app.get(f"{BASE_PATH}/api/version/updates")
+ async def get_app_latest_release_version(user=Depends(get_verified_user)):
+ if not ENABLE_VERSION_UPDATE_CHECK:
+ log.debug(
+ f"Version update check is disabled, returning current version as latest version"
+ )
+ return {"current": VERSION, "latest": VERSION}
+ try:
+ timeout = aiohttp.ClientTimeout(total=1)
+ async with aiohttp.ClientSession(timeout=timeout, trust_env=True) as session:
+ async with session.get(
+ "https://api.github.com/repos/open-webui/open-webui/releases/latest",
+ ssl=AIOHTTP_CLIENT_SESSION_SSL,
+ ) as response:
+ response.raise_for_status()
+ data = await response.json()
+ latest_version = data["tag_name"]
+
+ return {"current": VERSION, "latest": latest_version[1:]}
+ except Exception as e:
+ log.debug(e)
+ return {"current": VERSION, "latest": VERSION}
+
+ @app.get(f"{BASE_PATH}/api/changelog")
+ async def get_app_changelog():
+ return {key: CHANGELOG[key] for idx, key in enumerate(CHANGELOG) if idx < 5}
+
+ @app.get(f"{BASE_PATH}/api/usage")
+ async def get_current_usage(user=Depends(get_verified_user)):
+ """
+ Get current usage statistics for Open WebUI.
+ This is an experimental endpoint and subject to change.
+ """
+ try:
+ return {"model_ids": get_models_in_use(), "user_ids": get_active_user_ids()}
+ except Exception as e:
+ log.error(f"Error getting usage statistics: {e}")
+ raise HTTPException(status_code=500, detail="Internal Server Error")
+
+ async def register_client(self, request, client_id: str) -> bool:
+ server_type, server_id = client_id.split(":", 1)
+
+ connection = None
+ connection_idx = None
+
+ for idx, conn in enumerate(request.app.state.config.TOOL_SERVER_CONNECTIONS or []):
+ if conn.get("type", "openapi") == server_type:
+ info = conn.get("info", {})
+ if info.get("id") == server_id:
+ connection = conn
+ connection_idx = idx
+ break
+
+ if connection is None or connection_idx is None:
+ log.warning(
+ f"Unable to locate MCP tool server configuration for client {client_id} during re-registration"
+ )
+ return False
+
+ server_url = connection.get("url")
+ oauth_server_key = (connection.get("config") or {}).get("oauth_server_key")
+
+ try:
+ oauth_client_info = (
+ await get_oauth_client_info_with_dynamic_client_registration(
+ request,
+ client_id,
+ server_url,
+ oauth_server_key,
+ )
+ )
+ except Exception as e:
+ log.error(f"Dynamic client re-registration failed for {client_id}: {e}")
+ return False
+
+ try:
+ request.app.state.config.TOOL_SERVER_CONNECTIONS[connection_idx] = {
+ **connection,
+ "info": {
+ **connection.get("info", {}),
+ "oauth_client_info": encrypt_data(
+ oauth_client_info.model_dump(mode="json")
+ ),
+ },
+ }
+ except Exception as e:
+ log.error(
+ f"Failed to persist updated OAuth client info for tool server {client_id}: {e}"
+ )
+ return False
+
+ oauth_client_manager.remove_client(client_id)
+ oauth_client_manager.add_client(client_id, oauth_client_info)
+ log.info(f"Re-registered OAuth client {client_id} for tool server")
+ return True
+
+ @app.get(BASE_PATH + "/oauth/clients/{client_id}/authorize")
+ async def oauth_client_authorize(
+ client_id: str,
+ request: Request,
+ response: Response,
+ user=Depends(get_verified_user),
+ ):
+ # ensure_valid_client_registration
+ client = oauth_client_manager.get_client(client_id)
+ client_info = oauth_client_manager.get_client_info(client_id)
+ if client is None or client_info is None:
+ raise HTTPException(status.HTTP_404_NOT_FOUND)
+
+ if not await oauth_client_manager._preflight_authorization_url(client, client_info):
+ log.info(
+ "Detected invalid OAuth client %s; attempting re-registration",
+ client_id,
+ )
+
+ registered = await register_client(request, client_id)
+ if not registered:
+ raise HTTPException(
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
+ detail="Failed to re-register OAuth client",
+ )
+
+ client = oauth_client_manager.get_client(client_id)
+ client_info = oauth_client_manager.get_client_info(client_id)
+ if client is None or client_info is None:
+ raise HTTPException(
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
+ detail="OAuth client unavailable after re-registration",
+ )
+
+ if not await oauth_client_manager._preflight_authorization_url(
+ client, client_info
+ ):
+ raise HTTPException(
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
+ detail="OAuth client registration is still invalid after re-registration",
+ )
+
+ return await oauth_client_manager.handle_authorize(request, client_id=client_id)
+
+ @app.get(BASE_PATH + "/oauth/clients/{client_id}/callback")
+ async def oauth_client_callback(
+ client_id: str,
+ request: Request,
+ response: Response,
+ user=Depends(get_verified_user),
+ ):
+ return await oauth_client_manager.handle_callback(
+ request,
+ client_id=client_id,
+ user_id=user.id if user else None,
+ response=response,
+ )
+
+ @app.get(BASE_PATH + "/oauth/{provider}/login")
+ async def oauth_login(provider: str, request: Request):
+ return await oauth_manager.handle_login(request, provider)
+
+ # OAuth login logic is as follows:
+ # 1. Attempt to find a user with matching subject ID, tied to the provider
+ # 2. If OAUTH_MERGE_ACCOUNTS_BY_EMAIL is true, find a user with the email address provided via OAuth
+ # - This is considered insecure in general, as OAuth providers do not always verify email addresses
+ # 3. If there is no user, and ENABLE_OAUTH_SIGNUP is true, create a user
+ # - Email addresses are considered unique, so we fail registration if the email address is already taken
+ @app.get(BASE_PATH + "/oauth/{provider}/login/callback")
+ @app.get(BASE_PATH + "/oauth/{provider}/callback") # Legacy endpoint
+ async def oauth_login_callback(provider: str, request: Request, response: Response):
+ return await oauth_manager.handle_callback(request, provider, response)
+
+ @app.get(f"{BASE_PATH}/manifest.json")
+ async def get_manifest_json():
+ if app.state.EXTERNAL_PWA_MANIFEST_URL:
+ return requests.get(app.state.EXTERNAL_PWA_MANIFEST_URL).json()
+ else:
+ return {
+ "name": app.state.WEBUI_NAME,
+ "short_name": app.state.WEBUI_NAME,
+ "description": f"{app.state.WEBUI_NAME} is an open, extensible, user-friendly interface for AI that adapts to your workflow.",
+ "start_url": "/",
+ "display": "standalone",
+ "background_color": "#343541",
+ "icons": [
+ {
+ "src": "/static/logo.png",
+ "type": "image/png",
+ "sizes": "500x500",
+ "purpose": "any",
+ },
+ {
+ "src": "/static/logo.png",
+ "type": "image/png",
+ "sizes": "500x500",
+ "purpose": "maskable",
+ },
+ ],
+ "share_target": {
+ "action": "/",
+ "method": "GET",
+ "params": {"text": "shared"},
+ },
+ }
+
+ @app.get(f"{BASE_PATH}/opensearch.xml")
+ async def get_opensearch_xml():
+ xml_content = rf"""
+
+ {app.state.WEBUI_NAME}
+ Search {app.state.WEBUI_NAME}
+ UTF-8
+ {app.state.config.WEBUI_URL}/static/favicon.png
+
+ {app.state.config.WEBUI_URL}
+
+ """
+ return Response(content=xml_content, media_type="application/xml")
+
+ @app.get(f"{BASE_PATH}/health")
+ async def healthcheck():
+ UTC = getattr(dt, "UTC", dt.timezone.utc)
+ upTime = dt.datetime.now().astimezone().astimezone(UTC)
+ now_utc = dt.datetime.now(UTC)
+ return {
+ "timestamp": now_utc.isoformat().replace("+00:00", "Z"), # ISO8601 with Z
+ "uptime": str(now_utc - upTime),
+ }
+
+ @app.get(f"{BASE_PATH}/health/db")
+ async def healthcheck_with_db():
+ Session.execute(text("SELECT 1;")).all()
+ return {"status": True}
+
+ @app.get(BASE_PATH + "/cache/{path:path}")
+ async def serve_cache_file(
+ path: str,
+ user=Depends(get_verified_user),
+ ):
+ file_path = os.path.abspath(os.path.join(CACHE_DIR, path))
+ # prevent path traversal
+ if not file_path.startswith(os.path.abspath(CACHE_DIR)):
+ raise HTTPException(status_code=404, detail="File not found")
+ if not os.path.isfile(file_path):
+ raise HTTPException(status_code=404, detail="File not found")
+ return FileResponse(file_path)
diff --git a/backend/open_webui/routers/files.py b/backend/open_webui/routers/files.py
index 2a5c3e5bb169..f6993dd9f449 100644
--- a/backend/open_webui/routers/files.py
+++ b/backend/open_webui/routers/files.py
@@ -206,7 +206,7 @@ def upload_file_handler(
file.file,
filename,
{
- "OpenWebUI-User-Email": user.email,
+ "OpenWebUI-User-Username": user.username,
"OpenWebUI-User-Id": user.id,
"OpenWebUI-User-Name": user.name,
"OpenWebUI-File-Id": id,
diff --git a/backend/open_webui/routers/ollama.py b/backend/open_webui/routers/ollama.py
index 64b0687afa09..c73564eae3ff 100644
--- a/backend/open_webui/routers/ollama.py
+++ b/backend/open_webui/routers/ollama.py
@@ -91,7 +91,7 @@ async def send_get_request(url, key=None, user: UserModel = None):
{
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
"X-OpenWebUI-User-Id": user.id,
- "X-OpenWebUI-User-Email": user.email,
+ "X-OpenWebUI-User-Username": user.username,
"X-OpenWebUI-User-Role": user.role,
}
if ENABLE_FORWARD_USER_INFO_HEADERS and user
@@ -143,7 +143,7 @@ async def send_post_request(
{
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
"X-OpenWebUI-User-Id": user.id,
- "X-OpenWebUI-User-Email": user.email,
+ "X-OpenWebUI-User-Username": user.username,
"X-OpenWebUI-User-Role": user.role,
**(
{"X-OpenWebUI-Chat-Id": metadata.get("chat_id")}
@@ -254,7 +254,7 @@ async def verify_connection(
{
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
"X-OpenWebUI-User-Id": user.id,
- "X-OpenWebUI-User-Email": user.email,
+ "X-OpenWebUI-User-Username": user.username,
"X-OpenWebUI-User-Role": user.role,
}
if ENABLE_FORWARD_USER_INFO_HEADERS and user
@@ -478,8 +478,8 @@ async def get_ollama_tags(
{
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
"X-OpenWebUI-User-Id": user.id,
- "X-OpenWebUI-User-Email": user.email,
- "X-OpenWebUI-User-Role": user.role,
+ "X-OpenWebUI-User-Username": user.username,
+ "X-OpenWebUI-User-Role": 'admin',
}
if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {}
@@ -848,8 +848,8 @@ async def copy_model(
{
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
"X-OpenWebUI-User-Id": user.id,
- "X-OpenWebUI-User-Email": user.email,
- "X-OpenWebUI-User-Role": user.role,
+ "X-OpenWebUI-User-Username": user.username,
+ "X-OpenWebUI-User-Role": 'admin',
}
if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {}
@@ -919,8 +919,8 @@ async def delete_model(
{
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
"X-OpenWebUI-User-Id": user.id,
- "X-OpenWebUI-User-Email": user.email,
- "X-OpenWebUI-User-Role": user.role,
+ "X-OpenWebUI-User-Username": user.username,
+ "X-OpenWebUI-User-Role": 'admin',
}
if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {}
@@ -983,8 +983,8 @@ async def show_model_info(
{
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
"X-OpenWebUI-User-Id": user.id,
- "X-OpenWebUI-User-Email": user.email,
- "X-OpenWebUI-User-Role": user.role,
+ "X-OpenWebUI-User-Username": user.username,
+ "X-OpenWebUI-User-Role": 'admin',
}
if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {}
@@ -1074,8 +1074,8 @@ async def embed(
{
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
"X-OpenWebUI-User-Id": user.id,
- "X-OpenWebUI-User-Email": user.email,
- "X-OpenWebUI-User-Role": user.role,
+ "X-OpenWebUI-User-Username": user.username,
+ "X-OpenWebUI-User-Role": 'admin',
}
if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {}
@@ -1161,8 +1161,8 @@ async def embeddings(
{
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
"X-OpenWebUI-User-Id": user.id,
- "X-OpenWebUI-User-Email": user.email,
- "X-OpenWebUI-User-Role": user.role,
+ "X-OpenWebUI-User-Username": user.username,
+ "X-OpenWebUI-User-Role": 'admin',
}
if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {}
diff --git a/backend/open_webui/routers/openai.py b/backend/open_webui/routers/openai.py
index 9f94d67ee4ff..d42377b395b1 100644
--- a/backend/open_webui/routers/openai.py
+++ b/backend/open_webui/routers/openai.py
@@ -74,8 +74,8 @@ async def send_get_request(url, key=None, user: UserModel = None):
{
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
"X-OpenWebUI-User-Id": user.id,
- "X-OpenWebUI-User-Email": user.email,
- "X-OpenWebUI-User-Role": user.role,
+ "X-OpenWebUI-User-Username": user.username,
+ "X-OpenWebUI-User-Role": 'admin',
}
if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {}
@@ -144,7 +144,7 @@ async def get_headers_and_cookies(
{
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
"X-OpenWebUI-User-Id": user.id,
- "X-OpenWebUI-User-Email": user.email,
+ "X-OpenWebUI-User-Username": user.username,
"X-OpenWebUI-User-Role": user.role,
**(
{"X-OpenWebUI-Chat-Id": metadata.get("chat_id")}
@@ -822,40 +822,40 @@ async def generate_chat_completion(
metadata = payload.pop("metadata", None)
model_id = form_data.get("model")
- model_info = Models.get_model_by_id(model_id)
+ # model_info = Models.get_model_by_id(model_id)
# Check model info and override the payload
- if model_info:
- if model_info.base_model_id:
- payload["model"] = model_info.base_model_id
- model_id = model_info.base_model_id
-
- params = model_info.params.model_dump()
-
- if params:
- system = params.pop("system", None)
-
- payload = apply_model_params_to_body_openai(params, payload)
- payload = apply_system_prompt_to_body(system, payload, metadata, user)
-
- # Check if user has access to the model
- if not bypass_filter and user.role == "user":
- if not (
- user.id == model_info.user_id
- or has_access(
- user.id, type="read", access_control=model_info.access_control
- )
- ):
- raise HTTPException(
- status_code=403,
- detail="Model not found",
- )
- elif not bypass_filter:
- if user.role != "admin":
- raise HTTPException(
- status_code=403,
- detail="Model not found",
- )
+ # if model_info:
+ # if model_info.base_model_id:
+ # payload["model"] = model_info.base_model_id
+ # model_id = model_info.base_model_id
+ #
+ # params = model_info.params.model_dump()
+ #
+ # if params:
+ # system = params.pop("system", None)
+ #
+ # payload = apply_model_params_to_body_openai(params, payload)
+ # payload = apply_system_prompt_to_body(system, payload, metadata, user)
+ #
+ # # Check if user has access to the model
+ # if not bypass_filter and user.role == "user":
+ # if not (
+ # user.id == model_info.user_id
+ # or has_access(
+ # user.id, type="read", access_control=model_info.access_control
+ # )
+ # ):
+ # raise HTTPException(
+ # status_code=403,
+ # detail="Model not found",
+ # )
+ # elif not bypass_filter:
+ # if user.role != "admin":
+ # raise HTTPException(
+ # status_code=403,
+ # detail="Model not found",
+ # )
await get_all_models(request, user=user)
model = request.app.state.OPENAI_MODELS.get(model_id)
@@ -884,8 +884,8 @@ async def generate_chat_completion(
payload["user"] = {
"name": user.name,
"id": user.id,
- "email": user.email,
- "role": user.role,
+ "username": user.username,
+ "role": 'admin',
}
url = request.app.state.config.OPENAI_API_BASE_URLS[idx]
diff --git a/backend/open_webui/routers/pipelines.py b/backend/open_webui/routers/pipelines.py
index f80ea91f848b..e7945a8e9905 100644
--- a/backend/open_webui/routers/pipelines.py
+++ b/backend/open_webui/routers/pipelines.py
@@ -58,7 +58,7 @@ def get_sorted_filters(model_id, models):
async def process_pipeline_inlet_filter(request, payload, user, models):
- user = {"id": user.id, "email": user.email, "name": user.name, "role": user.role}
+ user = {"id": user.id, "name": user.name, "role": user.role}
model_id = payload["model"]
sorted_filters = get_sorted_filters(model_id, models)
model = models[model_id]
@@ -111,7 +111,7 @@ async def process_pipeline_inlet_filter(request, payload, user, models):
async def process_pipeline_outlet_filter(request, payload, user, models):
- user = {"id": user.id, "email": user.email, "name": user.name, "role": user.role}
+ user = {"id": user.id, "name": user.name, "role": user.role}
model_id = payload["model"]
sorted_filters = get_sorted_filters(model_id, models)
model = models[model_id]
diff --git a/backend/open_webui/routers/tasks.py b/backend/open_webui/routers/tasks.py
index 7585466f69c1..30bfe90830db 100644
--- a/backend/open_webui/routers/tasks.py
+++ b/backend/open_webui/routers/tasks.py
@@ -190,7 +190,7 @@ async def generate_title(
)
log.debug(
- f"generating chat title using model {task_model_id} for user {user.email} "
+ f"generating chat title using model {task_model_id} for user {user.username} "
)
if request.app.state.config.TITLE_GENERATION_PROMPT_TEMPLATE != "":
@@ -274,7 +274,7 @@ async def generate_follow_ups(
)
log.debug(
- f"generating chat title using model {task_model_id} for user {user.email} "
+ f"generating chat title using model {task_model_id} for user {user.username} "
)
if request.app.state.config.FOLLOW_UP_GENERATION_PROMPT_TEMPLATE != "":
@@ -347,7 +347,7 @@ async def generate_chat_tags(
)
log.debug(
- f"generating chat tags using model {task_model_id} for user {user.email} "
+ f"generating chat tags using model {task_model_id} for user {user.username} "
)
if request.app.state.config.TAGS_GENERATION_PROMPT_TEMPLATE != "":
@@ -413,7 +413,7 @@ async def generate_image_prompt(
)
log.debug(
- f"generating image prompt using model {task_model_id} for user {user.email} "
+ f"generating image prompt using model {task_model_id} for user {user.username} "
)
if request.app.state.config.IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE != "":
@@ -498,7 +498,7 @@ async def generate_queries(
)
log.debug(
- f"generating {type} queries using model {task_model_id} for user {user.email}"
+ f"generating {type} queries using model {task_model_id} for user {user.username}"
)
if (request.app.state.config.QUERY_GENERATION_PROMPT_TEMPLATE).strip() != "":
@@ -583,7 +583,7 @@ async def generate_autocompletion(
)
log.debug(
- f"generating autocompletion using model {task_model_id} for user {user.email}"
+ f"generating autocompletion using model {task_model_id} for user {user.username}"
)
if (request.app.state.config.AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE).strip() != "":
@@ -649,7 +649,7 @@ async def generate_emoji(
models,
)
- log.debug(f"generating emoji using model {task_model_id} for user {user.email} ")
+ log.debug(f"generating emoji using model {task_model_id} for user {user.username} ")
template = DEFAULT_EMOJI_GENERATION_PROMPT_TEMPLATE
diff --git a/backend/open_webui/socket/main.py b/backend/open_webui/socket/main.py
index 818a57807f83..7d42c482c4c1 100644
--- a/backend/open_webui/socket/main.py
+++ b/backend/open_webui/socket/main.py
@@ -5,10 +5,10 @@
import logging
import sys
import time
-from typing import Dict, Set
-from redis import asyncio as aioredis
import pycrdt as Y
+from open_webui.jms import chat_manager, JMSSession
+from open_webui.jms import check_user
from open_webui.models.users import Users, UserNameResponse
from open_webui.models.channels import Channels
from open_webui.models.chats import Chats
@@ -39,17 +39,20 @@
from open_webui.utils.redis import get_redis_connection
from open_webui.utils.access_control import has_access, get_users_with_access
-
from open_webui.env import (
GLOBAL_LOG_LEVEL,
SRC_LOG_LEVELS,
)
-
logging.basicConfig(stream=sys.stdout, level=GLOBAL_LOG_LEVEL)
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["SOCKET"])
+# Import BASE_PATH from main module
+try:
+ from open_webui.main import BASE_PATH
+except ImportError:
+ BASE_PATH = "/kael"
REDIS = None
@@ -82,7 +85,6 @@
always_connect=True,
)
-
# Timeout duration in seconds
TIMEOUT_DURATION = 3
@@ -138,7 +140,6 @@
aquire_func = release_func = renew_func = lambda: True
-
YDOC_MANAGER = YdocManager(
redis=REDIS,
redis_key_prefix=f"{REDIS_KEY_PREFIX}:ydoc:documents",
@@ -199,7 +200,7 @@ async def periodic_usage_pool_cleanup():
app = socketio.ASGIApp(
sio,
- socketio_path="/ws/socket.io",
+ socketio_path=f"{BASE_PATH}/ws/socket.io",
)
@@ -266,26 +267,52 @@ async def usage(sid, data):
@sio.event
async def connect(sid, environ, auth):
- user = None
- if auth and "token" in auth:
- data = decode_token(auth["token"])
+ scope = environ.get("asgi.scope", {})
+ handler = check_user.CheckUserHandler()
- if data is not None and "id" in data:
- user = Users.get_user_by_id(data["id"])
+ cookie_header = ""
+ if scope and "headers" in scope:
+ for k, v in scope["headers"]:
+ if k == b"cookie":
+ cookie_header = v.decode("latin1")
+ break
- if user:
- SESSION_POOL[sid] = user.model_dump(
- exclude=["date_of_birth", "bio", "gender"]
- )
- if user.id in USER_POOL:
- USER_POOL[user.id] = USER_POOL[user.id] + [sid]
- else:
- USER_POOL[user.id] = [sid]
+ if not cookie_header and "HTTP_COOKIE" in environ:
+ cookie_header = environ["HTTP_COOKIE"]
+
+ user = handler.check_user_by_cookie_header(cookie_header)
+
+ if user:
+ SESSION_POOL[sid] = {
+ "id": user.id,
+ "name": user.name,
+ "username": user.username,
+ "role": 'admin',
+ }
+ if user.id in USER_POOL:
+ USER_POOL[user.id] = USER_POOL[user.id] + [sid]
+ else:
+ USER_POOL[user.id] = [sid]
+
+ # user = None
+ # if auth and "token" in auth:
+ # data = decode_token(auth["token"])
+ #
+ # if data is not None and "id" in data:
+ # user = Users.get_user_by_id(data["id"])
+ #
+ # if user:
+ # SESSION_POOL[sid] = user.model_dump(
+ # exclude=["date_of_birth", "bio", "gender"]
+ # )
+ # if user.id in USER_POOL:
+ # USER_POOL[user.id] = USER_POOL[user.id] + [sid]
+ # else:
+ # USER_POOL[user.id] = [sid]
@sio.on("user-join")
async def user_join(sid, data):
-
auth = data["auth"] if "auth" in data else None
if not auth or "token" not in auth:
return
@@ -353,9 +380,9 @@ async def join_note(sid, data):
return
if (
- user.role != "admin"
- and user.id != note.user_id
- and not has_access(user.id, type="read", access_control=note.access_control)
+ user.role != "admin"
+ and user.id != note.user_id
+ and not has_access(user.id, type="read", access_control=note.access_control)
):
log.error(f"User {user.id} does not have access to note {data['note_id']}")
return
@@ -408,11 +435,11 @@ async def ydoc_document_join(sid, data):
return
if (
- user.get("role") != "admin"
- and user.get("id") != note.user_id
- and not has_access(
- user.get("id"), type="read", access_control=note.access_control
- )
+ user.get("role") != "admin"
+ and user.get("id") != note.user_id
+ and not has_access(
+ user.get("id"), type="read", access_control=note.access_control
+ )
):
log.error(
f"User {user.get('id')} does not have access to note {note_id}"
@@ -478,11 +505,11 @@ async def document_save_handler(document_id, data, user):
return
if (
- user.get("role") != "admin"
- and user.get("id") != note.user_id
- and not has_access(
- user.get("id"), type="read", access_control=note.access_control
- )
+ user.get("role") != "admin"
+ and user.get("id") != note.user_id
+ and not has_access(
+ user.get("id"), type="read", access_control=note.access_control
+ )
):
log.error(f"User {user.get('id')} does not have access to note {note_id}")
return
@@ -598,8 +625,8 @@ async def yjs_document_leave(sid, data):
)
if (
- await YDOC_MANAGER.document_exists(document_id)
- and len(await YDOC_MANAGER.get_users(document_id)) == 0
+ await YDOC_MANAGER.document_exists(document_id)
+ and len(await YDOC_MANAGER.get_users(document_id)) == 0
):
log.info(f"Cleaning up document {document_id} as no users are left")
await YDOC_MANAGER.clear_document(document_id)
@@ -641,6 +668,12 @@ async def disconnect(sid):
del USER_POOL[user_id]
await YDOC_MANAGER.remove_user_from_all_documents(sid)
+
+ chats = chat_manager.list(query={'socket_id': sid})
+
+ for chat in chats:
+ jms_session = JMSSession(chat)
+ await jms_session.close()
else:
pass
# print(f"Unknown session ID {sid} disconnected")
@@ -679,9 +712,9 @@ async def __event_emitter__(event_data):
await asyncio.gather(*emit_tasks)
if (
- update_db
- and message_id
- and not request_info.get("chat_id", "").startswith("local:")
+ update_db
+ and message_id
+ and not request_info.get("chat_id", "").startswith("local:")
):
if "type" in event_data and event_data["type"] == "status":
Chats.add_message_status_to_chat_by_id_and_message_id(
diff --git a/backend/open_webui/urls.py b/backend/open_webui/urls.py
new file mode 100644
index 000000000000..f0f6c55484dd
--- /dev/null
+++ b/backend/open_webui/urls.py
@@ -0,0 +1,94 @@
+from fastapi import APIRouter
+from fastapi.staticfiles import StaticFiles
+
+from open_webui.routers import (
+ audio,
+ images,
+ ollama,
+ openai,
+ retrieval,
+ pipelines,
+ tasks,
+ auths,
+ channels,
+ chats,
+ notes,
+ folders,
+ configs,
+ groups,
+ files,
+ functions,
+ memories,
+ models,
+ knowledge,
+ prompts,
+ evaluations,
+ tools,
+ users,
+ utils,
+ scim,
+)
+
+from open_webui.config import (
+ # Misc
+ STATIC_DIR,
+)
+from open_webui.env import (
+ # SCIM
+ SCIM_ENABLED,
+)
+
+from open_webui.routers.common import setup_lazy_routes
+
+# Base path configuration - easily changeable
+BASE_PATH = "/kael"
+
+
+def setup_routes(app, socket_app):
+ # Create main API router
+ main_router = APIRouter()
+
+ main_router.include_router(ollama.router, prefix="/ollama", tags=["ollama"])
+ main_router.include_router(openai.router, prefix="/openai", tags=["openai"])
+
+ main_router.include_router(pipelines.router, prefix="/api/v1/pipelines", tags=["pipelines"])
+ main_router.include_router(tasks.router, prefix="/api/v1/tasks", tags=["tasks"])
+ main_router.include_router(images.router, prefix="/api/v1/images", tags=["images"])
+
+ main_router.include_router(audio.router, prefix="/api/v1/audio", tags=["audio"])
+ main_router.include_router(retrieval.router, prefix="/api/v1/retrieval", tags=["retrieval"])
+
+ main_router.include_router(configs.router, prefix="/api/v1/configs", tags=["configs"])
+
+ main_router.include_router(auths.router, prefix="/api/v1/auths", tags=["auths"])
+ main_router.include_router(users.router, prefix="/api/v1/users", tags=["users"])
+
+ main_router.include_router(channels.router, prefix="/api/v1/channels", tags=["channels"])
+ main_router.include_router(chats.router, prefix="/api/v1/chats", tags=["chats"])
+ main_router.include_router(notes.router, prefix="/api/v1/notes", tags=["notes"])
+
+ main_router.include_router(models.router, prefix="/api/v1/models", tags=["models"])
+ main_router.include_router(knowledge.router, prefix="/api/v1/knowledge", tags=["knowledge"])
+ main_router.include_router(prompts.router, prefix="/api/v1/prompts", tags=["prompts"])
+ main_router.include_router(tools.router, prefix="/api/v1/tools", tags=["tools"])
+
+ main_router.include_router(memories.router, prefix="/api/v1/memories", tags=["memories"])
+ main_router.include_router(folders.router, prefix="/api/v1/folders", tags=["folders"])
+ main_router.include_router(groups.router, prefix="/api/v1/groups", tags=["groups"])
+ main_router.include_router(files.router, prefix="/api/v1/files", tags=["files"])
+ main_router.include_router(functions.router, prefix="/api/v1/functions", tags=["functions"])
+ main_router.include_router(
+ evaluations.router, prefix="/api/v1/evaluations", tags=["evaluations"]
+ )
+ main_router.include_router(utils.router, prefix="/api/v1/utils", tags=["utils"])
+
+ # SCIM 2.0 API for identity management
+ if SCIM_ENABLED:
+ main_router.include_router(scim.router, prefix="/api/v1/scim/v2", tags=["scim"])
+
+ setup_lazy_routes(app)
+
+ app.include_router(main_router, prefix=BASE_PATH)
+ app.mount(f"{BASE_PATH}/ws", socket_app)
+ app.mount(f"{BASE_PATH}/kael", StaticFiles(directory=STATIC_DIR), name="kael")
+ app.mount(f"{BASE_PATH}/static", StaticFiles(directory=STATIC_DIR), name="static")
diff --git a/backend/open_webui/utils/auth.py b/backend/open_webui/utils/auth.py
index e34803ade1b1..a76fdd849c23 100644
--- a/backend/open_webui/utils/auth.py
+++ b/backend/open_webui/utils/auth.py
@@ -21,6 +21,7 @@
from opentelemetry import trace
+from open_webui.jms import check_user
from open_webui.models.users import Users
from open_webui.constants import ERROR_MESSAGES
@@ -213,118 +214,123 @@ def get_current_user(
request: Request,
response: Response,
background_tasks: BackgroundTasks,
- auth_token: HTTPAuthorizationCredentials = Depends(bearer_security),
):
- token = None
-
- if auth_token is not None:
- token = auth_token.credentials
-
- if token is None and "token" in request.cookies:
- token = request.cookies.get("token")
-
- if token is None:
- raise HTTPException(status_code=401, detail="Not authenticated")
+ # token = None
+ #
+ # if auth_token is not None:
+ # token = auth_token.credentials
+ #
+ # if token is None and "token" in request.cookies:
+ # token = request.cookies.get("token")
+ #
+ # if token is None:
+ # raise HTTPException(status_code=401, detail="Not authenticated")
# auth by api key
- if token.startswith("sk-"):
- if not request.state.enable_api_key:
- raise HTTPException(
- status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.API_KEY_NOT_ALLOWED
- )
-
- if request.app.state.config.ENABLE_API_KEY_ENDPOINT_RESTRICTIONS:
- allowed_paths = [
- path.strip()
- for path in str(
- request.app.state.config.API_KEY_ALLOWED_ENDPOINTS
- ).split(",")
- ]
-
- # Check if the request path matches any allowed endpoint.
- if not any(
- request.url.path == allowed
- or request.url.path.startswith(allowed + "/")
- for allowed in allowed_paths
- ):
- raise HTTPException(
- status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.API_KEY_NOT_ALLOWED
- )
-
- user = get_current_user_by_api_key(token)
-
- # Add user info to current span
- current_span = trace.get_current_span()
- if current_span:
- current_span.set_attribute("client.user.id", user.id)
- current_span.set_attribute("client.user.email", user.email)
- current_span.set_attribute("client.user.role", user.role)
- current_span.set_attribute("client.auth.type", "api_key")
-
- return user
-
- # auth by jwt token
-
+ # if token.startswith("sk-"):
+ # if not request.state.enable_api_key:
+ # raise HTTPException(
+ # status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.API_KEY_NOT_ALLOWED
+ # )
+ #
+ # if request.app.state.config.ENABLE_API_KEY_ENDPOINT_RESTRICTIONS:
+ # allowed_paths = [
+ # path.strip()
+ # for path in str(
+ # request.app.state.config.API_KEY_ALLOWED_ENDPOINTS
+ # ).split(",")
+ # ]
+ #
+ # # Check if the request path matches any allowed endpoint.
+ # if not any(
+ # request.url.path == allowed
+ # or request.url.path.startswith(allowed + "/")
+ # for allowed in allowed_paths
+ # ):
+ # raise HTTPException(
+ # status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.API_KEY_NOT_ALLOWED
+ # )
+ check_user_handler = check_user.CheckUserHandler()
try:
- try:
- data = decode_token(token)
- except Exception as e:
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Invalid token",
- )
-
- if data is not None and "id" in data:
- user = Users.get_user_by_id(data["id"])
- if user is None:
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail=ERROR_MESSAGES.INVALID_TOKEN,
- )
- else:
- if WEBUI_AUTH_TRUSTED_EMAIL_HEADER:
- trusted_email = request.headers.get(
- WEBUI_AUTH_TRUSTED_EMAIL_HEADER, ""
- ).lower()
- if trusted_email and user.email != trusted_email:
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="User mismatch. Please sign in again.",
- )
-
- # Add user info to current span
- current_span = trace.get_current_span()
- if current_span:
- current_span.set_attribute("client.user.id", user.id)
- current_span.set_attribute("client.user.email", user.email)
- current_span.set_attribute("client.user.role", user.role)
- current_span.set_attribute("client.auth.type", "jwt")
-
- # Refresh the user's last active timestamp asynchronously
- # to prevent blocking the request
- if background_tasks:
- background_tasks.add_task(
- Users.update_user_last_active_by_id, user.id
- )
- return user
- else:
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail=ERROR_MESSAGES.UNAUTHORIZED,
- )
- except Exception as e:
- # Delete the token cookie
- if request.cookies.get("token"):
- response.delete_cookie("token")
+ user = check_user_handler.check_user_by_cookies(request)
+ except Exception:
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail=ERROR_MESSAGES.UNAUTHORIZED,
+ )
- if request.cookies.get("oauth_id_token"):
- response.delete_cookie("oauth_id_token")
+ # Add user info to current span
+ current_span = trace.get_current_span()
+ if current_span:
+ current_span.set_attribute("client.user.id", user.id)
+ current_span.set_attribute("client.user.name", user.name)
+ current_span.set_attribute("client.user.username", user.username)
+ current_span.set_attribute("client.user.role", user.role)
+ # current_span.set_attribute("client.auth.type", "api_key")
- # Delete OAuth session if present
- if request.cookies.get("oauth_session_id"):
- response.delete_cookie("oauth_session_id")
+ return user
- raise e
+ # # auth by jwt token
+ # try:
+ # try:
+ # data = decode_token(token)
+ # except Exception as e:
+ # raise HTTPException(
+ # status_code=status.HTTP_401_UNAUTHORIZED,
+ # detail="Invalid token",
+ # )
+ #
+ # if data is not None and "id" in data:
+ # user = Users.get_user_by_id(data["id"])
+ # if user is None:
+ # raise HTTPException(
+ # status_code=status.HTTP_401_UNAUTHORIZED,
+ # detail=ERROR_MESSAGES.INVALID_TOKEN,
+ # )
+ # else:
+ # if WEBUI_AUTH_TRUSTED_EMAIL_HEADER:
+ # trusted_email = request.headers.get(
+ # WEBUI_AUTH_TRUSTED_EMAIL_HEADER, ""
+ # ).lower()
+ # if trusted_email and user.email != trusted_email:
+ # raise HTTPException(
+ # status_code=status.HTTP_401_UNAUTHORIZED,
+ # detail="User mismatch. Please sign in again.",
+ # )
+ #
+ # # Add user info to current span
+ # current_span = trace.get_current_span()
+ # if current_span:
+ # current_span.set_attribute("client.user.id", user.id)
+ # current_span.set_attribute("client.user.email", user.email)
+ # current_span.set_attribute("client.user.role", user.role)
+ # current_span.set_attribute("client.auth.type", "jwt")
+ #
+ # # Refresh the user's last active timestamp asynchronously
+ # # to prevent blocking the request
+ # if background_tasks:
+ # background_tasks.add_task(
+ # Users.update_user_last_active_by_id, user.id
+ # )
+ # return user
+ # else:
+ # raise HTTPException(
+ # status_code=status.HTTP_401_UNAUTHORIZED,
+ # detail=ERROR_MESSAGES.UNAUTHORIZED,
+ # )
+ # except Exception as e:
+ # # Delete the token cookie
+ # if request.cookies.get("token"):
+ # response.delete_cookie("token")
+ #
+ # if request.cookies.get("oauth_id_token"):
+ # response.delete_cookie("oauth_id_token")
+ #
+ # # Delete OAuth session if present
+ # if request.cookies.get("oauth_session_id"):
+ # response.delete_cookie("oauth_session_id")
+ #
+ # raise e
def get_current_user_by_api_key(api_key: str):
@@ -350,11 +356,6 @@ def get_current_user_by_api_key(api_key: str):
def get_verified_user(user=Depends(get_current_user)):
- if user.role not in {"user", "admin"}:
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
- )
return user
diff --git a/backend/open_webui/utils/headers.py b/backend/open_webui/utils/headers.py
index 3caee5033407..d42ba661a409 100644
--- a/backend/open_webui/utils/headers.py
+++ b/backend/open_webui/utils/headers.py
@@ -6,6 +6,6 @@ def include_user_info_headers(headers, user):
**headers,
"X-OpenWebUI-User-Name": quote(user.name, safe=" "),
"X-OpenWebUI-User-Id": user.id,
- "X-OpenWebUI-User-Email": user.email,
- "X-OpenWebUI-User-Role": user.role,
+ "X-OpenWebUI-User-Username": user.username,
+ "X-OpenWebUI-User-Role": 'admin',
}
diff --git a/backend/open_webui/utils/images/comfyui.py b/backend/open_webui/utils/images/comfyui.py
index 506723bc9291..4434c3cb7bf2 100644
--- a/backend/open_webui/utils/images/comfyui.py
+++ b/backend/open_webui/utils/images/comfyui.py
@@ -196,7 +196,7 @@ async def comfyui_create_image(
ws.connect(f"{ws_url}/ws?clientId={client_id}", header=headers)
log.info("WebSocket connection established.")
except Exception as e:
- log.exception(f"Failed to connect to WebSocket server: {e}")
+ log.exception(f"Failed to connect to WebSocket {e}")
return None
try:
diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py
index e5b84a3d792b..f875231e5e2e 100644
--- a/backend/open_webui/utils/middleware.py
+++ b/backend/open_webui/utils/middleware.py
@@ -1,30 +1,23 @@
import time
import logging
import sys
-import os
-import base64
import textwrap
import asyncio
-from aiocache import cached
-from typing import Any, Optional
-import random
+from typing import Optional
import json
import html
-import inspect
import re
import ast
from uuid import uuid4
from concurrent.futures import ThreadPoolExecutor
-
from fastapi import Request, HTTPException
from fastapi.responses import HTMLResponse
-from starlette.responses import Response, StreamingResponse, JSONResponse
-
+from starlette.responses import StreamingResponse, JSONResponse
-from open_webui.models.oauth_sessions import OAuthSessions
+from open_webui.jms import chat_manager, CommandHandler, CommandRecord, ReplayHandler
from open_webui.models.chats import Chats
from open_webui.models.folders import Folders
from open_webui.models.users import Users
@@ -63,14 +56,12 @@
get_image_url_from_base64,
)
-
from open_webui.models.users import UserModel
from open_webui.models.functions import Functions
from open_webui.models.models import Models
from open_webui.retrieval.utils import get_sources_from_items
-
from open_webui.utils.chat import generate_chat_completion
from open_webui.utils.task import (
get_task_model_id,
@@ -101,7 +92,6 @@
from open_webui.utils.payload import apply_system_prompt_to_body
from open_webui.utils.mcp.client import MCPClient
-
from open_webui.config import (
CACHE_DIR,
DEFAULT_TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE,
@@ -119,12 +109,10 @@
)
from open_webui.constants import TASKS
-
logging.basicConfig(stream=sys.stdout, level=GLOBAL_LOG_LEVEL)
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MAIN"])
-
DEFAULT_REASONING_TAGS = [
("", ""),
("", ""),
@@ -140,13 +128,13 @@
def process_tool_result(
- request,
- tool_function_name,
- tool_result,
- tool_type,
- direct_tool=False,
- metadata=None,
- user=None,
+ request,
+ tool_function_name,
+ tool_result,
+ tool_type,
+ direct_tool=False,
+ metadata=None,
+ user=None,
):
tool_result_embeds = []
@@ -184,7 +172,7 @@ def process_tool_result(
tool_result = tool_result.body.decode("utf-8", "replace")
elif (tool_type == "external" and isinstance(tool_result, tuple)) or (
- direct_tool and isinstance(tool_result, list) and len(tool_result) == 2
+ direct_tool and isinstance(tool_result, list) and len(tool_result) == 2
):
tool_result, tool_response_headers = tool_result
@@ -283,7 +271,7 @@ def process_tool_result(
async def chat_completion_tools_handler(
- request: Request, body: dict, extra_params: dict, user: UserModel, models, tools
+ request: Request, body: dict, extra_params: dict, user: UserModel, models, tools
) -> tuple[dict, dict]:
async def get_content_from_response(response) -> Optional[str]:
content = None
@@ -359,7 +347,7 @@ def get_tools_function_calling_payload(messages, task_model_id, content):
return body, {}
try:
- content = content[content.find("{") : content.rfind("}") + 1]
+ content = content[content.find("{"): content.rfind("}") + 1]
if not content:
raise Exception("No JSON object found in the response")
@@ -488,9 +476,9 @@ async def tool_call_handler(tool_call):
)
if (
- tools[tool_function_name]
- .get("metadata", {})
- .get("file_handler", False)
+ tools[tool_function_name]
+ .get("metadata", {})
+ .get("file_handler", False)
):
skip_files = True
@@ -517,7 +505,7 @@ async def tool_call_handler(tool_call):
async def chat_memory_handler(
- request: Request, form_data: dict, extra_params: dict, user
+ request: Request, form_data: dict, extra_params: dict, user
):
try:
results = await query_memory(
@@ -556,7 +544,7 @@ async def chat_memory_handler(
async def chat_web_search_handler(
- request: Request, form_data: dict, extra_params: dict, user
+ request: Request, form_data: dict, extra_params: dict, user
):
event_emitter = extra_params["__event_emitter__"]
await event_emitter(
@@ -649,7 +637,7 @@ async def chat_web_search_handler(
if results.get("collection_names"):
for col_idx, collection_name in enumerate(
- results.get("collection_names")
+ results.get("collection_names")
):
files.append(
{
@@ -734,7 +722,7 @@ def get_last_images(message_list):
async def chat_image_generation_handler(
- request: Request, form_data: dict, extra_params: dict, user
+ request: Request, form_data: dict, extra_params: dict, user
):
metadata = extra_params.get("__metadata__", {})
chat_id = metadata.get("chat_id", None)
@@ -906,7 +894,7 @@ async def chat_image_generation_handler(
async def chat_completion_files_handler(
- request: Request, body: dict, extra_params: dict, user: UserModel
+ request: Request, body: dict, extra_params: dict, user: UserModel
) -> tuple[dict, dict[str, list]]:
__event_emitter__ = extra_params["__event_emitter__"]
sources = []
@@ -987,7 +975,7 @@ async def chat_completion_files_handler(
hybrid_bm25_weight=request.app.state.config.HYBRID_BM25_WEIGHT,
hybrid_search=request.app.state.config.ENABLE_RAG_HYBRID_SEARCH,
full_context=all_full_context
- or request.app.state.config.RAG_FULL_CONTEXT,
+ or request.app.state.config.RAG_FULL_CONTEXT,
user=user,
),
)
@@ -1008,9 +996,9 @@ async def chat_completion_files_handler(
for index, _ in enumerate(documents):
metadata = metadatas[index] if index < len(metadatas) else None
_id = (
- (metadata or {}).get("source")
- or (src_info or {}).get("id")
- or "N/A"
+ (metadata or {}).get("source")
+ or (src_info or {}).get("id")
+ or "N/A"
)
unique_ids.add(_id)
@@ -1143,7 +1131,7 @@ async def process_chat_payload(request, form_data, user, metadata, model):
chat_id = metadata.get("chat_id", None)
if chat_id and user:
chat = Chats.get_chat_by_id_and_user_id(chat_id, user.id)
- if chat and chat.folder_id:
+ if chat and chat['folder_id']:
folder = Folders.get_folder_by_id_and_user_id(chat.folder_id, user.id)
if folder and folder.data:
@@ -1305,15 +1293,15 @@ async def process_chat_payload(request, form_data, user, metadata, model):
for tool_id in tool_ids:
if tool_id.startswith("server:mcp:"):
try:
- server_id = tool_id[len("server:mcp:") :]
+ server_id = tool_id[len("server:mcp:"):]
mcp_server_connection = None
for (
- server_connection
+ server_connection
) in request.app.state.config.TOOL_SERVER_CONNECTIONS:
if (
- server_connection.get("type", "") == "mcp"
- and server_connection.get("info", {}).get("id") == server_id
+ server_connection.get("type", "") == "mcp"
+ and server_connection.get("info", {}).get("id") == server_id
):
mcp_server_connection = server_connection
break
@@ -1367,7 +1355,6 @@ async def process_chat_payload(request, form_data, user, metadata, model):
tool_specs = await mcp_clients[server_id].list_tool_specs()
for tool_spec in tool_specs:
-
def make_tool_function(client, function_name):
async def tool_function(**kwargs):
return await client.call_tool(
@@ -1468,22 +1455,22 @@ async def tool_function(**kwargs):
for source in sources:
if "document" in source:
for document_text, document_metadata in zip(
- source["document"], source["metadata"]
+ source["document"], source["metadata"]
):
source_name = source.get("source", {}).get("name", None)
source_id = (
- document_metadata.get("source", None)
- or source.get("source", {}).get("id", None)
- or "N/A"
+ document_metadata.get("source", None)
+ or source.get("source", {}).get("id", None)
+ or "N/A"
)
if source_id not in citation_idx_map:
citation_idx_map[source_id] = len(citation_idx_map) + 1
context_string += (
- f'{document_text}\n"
+ f'{document_text}\n"
)
context_string = context_string.strip()
@@ -1506,7 +1493,7 @@ async def tool_function(**kwargs):
source
for source in sources
if source.get("source", {}).get("name", "")
- or source.get("source", {}).get("id", "")
+ or source.get("source", {}).get("id", "")
]
if len(sources) > 0:
@@ -1525,11 +1512,13 @@ async def tool_function(**kwargs):
}
)
+ chat_id = metadata.get("chat_id", '')
+ asyncio.create_task(ReplayHandler(chat_id).write_input(user_message))
return form_data, metadata, events
async def process_chat_response(
- request, response, form_data, user, metadata, model, events, tasks
+ request, response, form_data, user, metadata, model, events, tasks
):
async def background_tasks_handler():
message = None
@@ -1581,8 +1570,8 @@ async def background_tasks_handler():
if message and "model" in message:
if tasks and messages:
if (
- TASKS.FOLLOW_UP_GENERATION in tasks
- and tasks[TASKS.FOLLOW_UP_GENERATION]
+ TASKS.FOLLOW_UP_GENERATION in tasks
+ and tasks[TASKS.FOLLOW_UP_GENERATION]
):
res = await generate_follow_ups(
request,
@@ -1608,8 +1597,8 @@ async def background_tasks_handler():
follow_ups_string = ""
follow_ups_string = follow_ups_string[
- follow_ups_string.find("{") : follow_ups_string.rfind("}")
- + 1
+ follow_ups_string.find("{"): follow_ups_string.rfind("}")
+ + 1
]
try:
@@ -1638,7 +1627,7 @@ async def background_tasks_handler():
pass
if not metadata.get("chat_id", "").startswith(
- "local:"
+ "local:"
): # Only update titles and tags for non-temp chats
if TASKS.TITLE_GENERATION in tasks:
user_message = get_last_user_message(messages)
@@ -1664,17 +1653,17 @@ async def background_tasks_handler():
)
title_string = (
- response_message.get("content")
- or response_message.get(
- "reasoning_content",
- )
- or message.get("content", user_message)
+ response_message.get("content")
+ or response_message.get(
+ "reasoning_content",
+ )
+ or message.get("content", user_message)
)
else:
title_string = ""
title_string = title_string[
- title_string.find("{") : title_string.rfind("}") + 1
+ title_string.find("{"): title_string.rfind("}") + 1
]
try:
@@ -1734,7 +1723,7 @@ async def background_tasks_handler():
tags_string = ""
tags_string = tags_string[
- tags_string.find("{") : tags_string.rfind("}") + 1
+ tags_string.find("{"): tags_string.rfind("}") + 1
]
try:
@@ -1755,12 +1744,12 @@ async def background_tasks_handler():
event_emitter = None
event_caller = None
if (
- "session_id" in metadata
- and metadata["session_id"]
- and "chat_id" in metadata
- and metadata["chat_id"]
- and "message_id" in metadata
- and metadata["message_id"]
+ "session_id" in metadata
+ and metadata["session_id"]
+ and "chat_id" in metadata
+ and metadata["chat_id"]
+ and "message_id" in metadata
+ and metadata["message_id"]
):
event_emitter = get_event_emitter(metadata)
event_caller = get_event_call(metadata)
@@ -1775,7 +1764,7 @@ async def background_tasks_handler():
response = response[0]
if isinstance(response, JSONResponse) and isinstance(
- response.body, bytes
+ response.body, bytes
):
try:
response_data = json.loads(
@@ -1918,8 +1907,8 @@ async def background_tasks_handler():
# Non standard response
if not any(
- content_type in response.headers["Content-Type"]
- for content_type in ["text/event-stream", "application/x-ndjson"]
+ content_type in response.headers["Content-Type"]
+ for content_type in ["text/event-stream", "application/x-ndjson"]
):
return response
@@ -1957,7 +1946,7 @@ async def background_tasks_handler():
def split_content_and_whitespace(content):
content_stripped = content.rstrip()
original_whitespace = (
- content[len(content_stripped) :]
+ content[len(content_stripped):]
if len(content) > len(content_stripped)
else ""
)
@@ -2075,8 +2064,8 @@ def serialize_content_blocks(content_blocks, raw=False):
if is_opening_code_block(content_stripped):
# Remove trailing backticks that would open a new block
content = (
- content_stripped.rstrip("`").rstrip()
- + original_whitespace
+ content_stripped.rstrip("`").rstrip()
+ + original_whitespace
)
else:
# Keep content as is - either closing backticks or no backticks
@@ -2189,7 +2178,7 @@ def extract_attributes(tag_content):
: match.start()
] # Content before opening tag
after_tag = content[
- match.end() :
+ match.end():
] # Content after opening tag
# Remove the start tag and after from the currently handling text block
@@ -2358,8 +2347,8 @@ def extract_attributes(tag_content):
reasoning_tags = []
if DETECT_REASONING_TAGS:
if (
- isinstance(reasoning_tags_param, list)
- and len(reasoning_tags_param) == 2
+ isinstance(reasoning_tags_param, list)
+ and len(reasoning_tags_param) == 2
):
reasoning_tags = [
(reasoning_tags_param[0], reasoning_tags_param[1])
@@ -2432,7 +2421,7 @@ async def flush_pending_delta_data(threshold: int = 0):
continue
# Remove the prefix
- data = data[len("data:") :].strip()
+ data = data[len("data:"):].strip()
try:
data = json.loads(data)
@@ -2447,7 +2436,7 @@ async def flush_pending_delta_data(threshold: int = 0):
if data:
if "event" in data and not getattr(
- request.state, "direct", False
+ request.state, "direct", False
):
await event_emitter(data.get("event", {}))
@@ -2508,11 +2497,11 @@ async def flush_pending_delta_data(threshold: int = 0):
# Check if the tool call already exists
current_response_tool_call = None
for (
- response_tool_call
+ response_tool_call
) in response_tool_calls:
if (
- response_tool_call.get("index")
- == tool_call_index
+ response_tool_call.get("index")
+ == tool_call_index
):
current_response_tool_call = (
response_tool_call
@@ -2559,14 +2548,14 @@ async def flush_pending_delta_data(threshold: int = 0):
value = delta.get("content")
reasoning_content = (
- delta.get("reasoning_content")
- or delta.get("reasoning")
- or delta.get("thinking")
+ delta.get("reasoning_content")
+ or delta.get("reasoning")
+ or delta.get("thinking")
)
if reasoning_content:
if (
- not content_blocks
- or content_blocks[-1]["type"] != "reasoning"
+ not content_blocks
+ or content_blocks[-1]["type"] != "reasoning"
):
reasoning_block = {
"type": "reasoning",
@@ -2592,13 +2581,13 @@ async def flush_pending_delta_data(threshold: int = 0):
if value:
if (
- content_blocks
- and content_blocks[-1]["type"]
- == "reasoning"
- and content_blocks[-1]
- .get("attributes", {})
- .get("type")
- == "reasoning_content"
+ content_blocks
+ and content_blocks[-1]["type"]
+ == "reasoning"
+ and content_blocks[-1]
+ .get("attributes", {})
+ .get("type")
+ == "reasoning_content"
):
reasoning_block = content_blocks[-1]
reasoning_block["ended_at"] = time.time()
@@ -2624,7 +2613,7 @@ async def flush_pending_delta_data(threshold: int = 0):
)
content_blocks[-1]["content"] = (
- content_blocks[-1]["content"] + value
+ content_blocks[-1]["content"] + value
)
if DETECT_REASONING_TAGS:
@@ -2736,8 +2725,8 @@ async def flush_pending_delta_data(threshold: int = 0):
tool_call_retries = 0
while (
- len(tool_calls) > 0
- and tool_call_retries < CHAT_RESPONSE_MAX_TOOL_CALL_RETRIES
+ len(tool_calls) > 0
+ and tool_call_retries < CHAT_RESPONSE_MAX_TOOL_CALL_RETRIES
):
tool_call_retries += 1
@@ -2934,8 +2923,8 @@ async def flush_pending_delta_data(threshold: int = 0):
retries = 0
while (
- content_blocks[-1]["type"] == "code_interpreter"
- and retries < MAX_RETRIES
+ content_blocks[-1]["type"] == "code_interpreter"
+ and retries < MAX_RETRIES
):
await event_emitter(
@@ -2977,8 +2966,8 @@ def restricted_import(name, globals=None, locals=None, fromlist=(), level=0):
code = blocking_code + "\n" + code
if (
- request.app.state.config.CODE_INTERPRETER_ENGINE
- == "pyodide"
+ request.app.state.config.CODE_INTERPRETER_ENGINE
+ == "pyodide"
):
output = await event_caller(
{
@@ -2993,8 +2982,8 @@ def restricted_import(name, globals=None, locals=None, fromlist=(), level=0):
}
)
elif (
- request.app.state.config.CODE_INTERPRETER_ENGINE
- == "jupyter"
+ request.app.state.config.CODE_INTERPRETER_ENGINE
+ == "jupyter"
):
output = await execute_code_jupyter(
request.app.state.config.CODE_INTERPRETER_JUPYTER_URL,
@@ -3002,13 +2991,13 @@ def restricted_import(name, globals=None, locals=None, fromlist=(), level=0):
(
request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN
if request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH
- == "token"
+ == "token"
else None
),
(
request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD
if request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH
- == "password"
+ == "password"
else None
),
request.app.state.config.CODE_INTERPRETER_JUPYTER_TIMEOUT,
@@ -3115,6 +3104,17 @@ def restricted_import(name, globals=None, locals=None, fromlist=(), level=0):
"title": title,
}
+ chat_id = metadata.get("chat_id", '')
+
+ chat_data = chat_manager.retrieve(chat_id)
+ user_message = get_last_user_message(form_data["messages"])
+
+ command_handler = CommandHandler(chat_id, chat_data['session_info'])
+ command_handler.command_record = CommandRecord(
+ input=user_message, output=data['content']
+ )
+ asyncio.create_task(ReplayHandler(chat_id).write_input(data['content']))
+
if not ENABLE_REALTIME_CHAT_SAVE:
# Save message in the database
Chats.upsert_message_to_chat_by_id_and_message_id(
diff --git a/backend/start.sh b/backend/start.sh
index 31e87c95577a..106fa23c9c7d 100755
--- a/backend/start.sh
+++ b/backend/start.sh
@@ -20,7 +20,7 @@ else
KEY_FILE=".webui_secret_key"
fi
-PORT="${PORT:-8080}"
+PORT="${PORT:-8083}"
HOST="${HOST:-0.0.0.0}"
if test "$WEBUI_SECRET_KEY $WEBUI_JWT_SECRET_KEY" = " "; then
echo "Loading WEBUI_SECRET_KEY from file, not provided as an environment variable."
@@ -84,4 +84,4 @@ WEBUI_SECRET_KEY="$WEBUI_SECRET_KEY" exec "$PYTHON_CMD" -m uvicorn open_webui.ma
--host "$HOST" \
--port "$PORT" \
--forwarded-allow-ips '*' \
- "${ARGS[@]}"
\ No newline at end of file
+ "${ARGS[@]}"
diff --git a/backend/start_windows.bat b/backend/start_windows.bat
index f350d11cd196..691632f022c0 100644
--- a/backend/start_windows.bat
+++ b/backend/start_windows.bat
@@ -22,7 +22,7 @@ IF NOT "%WEBUI_SECRET_KEY_FILE%" == "" (
SET "KEY_FILE=%WEBUI_SECRET_KEY_FILE%"
)
-IF "%PORT%"=="" SET PORT=8080
+IF "%PORT%"=="" SET PORT=8083
IF "%HOST%"=="" SET HOST=0.0.0.0
SET "WEBUI_SECRET_KEY=%WEBUI_SECRET_KEY%"
SET "WEBUI_JWT_SECRET_KEY=%WEBUI_JWT_SECRET_KEY%"
diff --git a/cypress.config.ts b/cypress.config.ts
index dbb538233809..d28819487c64 100644
--- a/cypress.config.ts
+++ b/cypress.config.ts
@@ -2,7 +2,7 @@ import { defineConfig } from 'cypress';
export default defineConfig({
e2e: {
- baseUrl: 'http://localhost:8080'
+ baseUrl: 'http://localhost:8083'
},
video: true
});
diff --git a/docker-compose.otel.yaml b/docker-compose.otel.yaml
index 0ccadccddae0..01c070e72c01 100644
--- a/docker-compose.otel.yaml
+++ b/docker-compose.otel.yaml
@@ -20,7 +20,7 @@ services:
depends_on:
- grafana
ports:
- - ${OPEN_WEBUI_PORT-8088}:8080
+ - ${OPEN_WEBUI_PORT-8088}:8083
environment:
- ENABLE_OTEL=true
- ENABLE_OTEL_METRICS=true
diff --git a/docker-compose.yaml b/docker-compose.yaml
index 349734a93921..522087e85623 100644
--- a/docker-compose.yaml
+++ b/docker-compose.yaml
@@ -19,7 +19,7 @@ services:
depends_on:
- ollama
ports:
- - ${OPEN_WEBUI_PORT-3000}:8080
+ - ${OPEN_WEBUI_PORT-3000}:8083
environment:
- 'OLLAMA_BASE_URL=http://ollama:11434'
- 'WEBUI_SECRET_KEY='
diff --git a/kubernetes/manifest/base/webui-deployment.yaml b/kubernetes/manifest/base/webui-deployment.yaml
index 79a0a9a23c96..0414eac239b5 100644
--- a/kubernetes/manifest/base/webui-deployment.yaml
+++ b/kubernetes/manifest/base/webui-deployment.yaml
@@ -17,7 +17,7 @@ spec:
- name: open-webui
image: ghcr.io/open-webui/open-webui:main
ports:
- - containerPort: 8080
+ - containerPort: 8083
resources:
requests:
cpu: "500m"
@@ -35,4 +35,4 @@ spec:
volumes:
- name: webui-volume
persistentVolumeClaim:
- claimName: open-webui-pvc
\ No newline at end of file
+ claimName: open-webui-pvc
diff --git a/kubernetes/manifest/base/webui-ingress.yaml b/kubernetes/manifest/base/webui-ingress.yaml
index dc0b53ccd456..22474fb664b7 100644
--- a/kubernetes/manifest/base/webui-ingress.yaml
+++ b/kubernetes/manifest/base/webui-ingress.yaml
@@ -17,4 +17,4 @@ spec:
service:
name: open-webui-service
port:
- number: 8080
+ number: 8083
diff --git a/kubernetes/manifest/base/webui-service.yaml b/kubernetes/manifest/base/webui-service.yaml
index d73845f00a8e..64b71e8d0abb 100644
--- a/kubernetes/manifest/base/webui-service.yaml
+++ b/kubernetes/manifest/base/webui-service.yaml
@@ -9,7 +9,7 @@ spec:
app: open-webui
ports:
- protocol: TCP
- port: 8080
- targetPort: 8080
+ port: 8083
+ targetPort: 8083
# If using NodePort, you can optionally specify the nodePort:
- # nodePort: 30000
\ No newline at end of file
+ # nodePort: 30000
diff --git a/package.json b/package.json
index 9065bda0ce4b..023238ce84ca 100644
--- a/package.json
+++ b/package.json
@@ -3,10 +3,10 @@
"version": "0.6.36",
"private": true,
"scripts": {
- "dev": "npm run pyodide:fetch && vite dev --host",
- "dev:5050": "npm run pyodide:fetch && vite dev --port 5050",
- "build": "npm run pyodide:fetch && vite build",
- "build:watch": "npm run pyodide:fetch && vite build --watch",
+ "dev": "vite dev --host",
+ "dev:5050": "vite dev --port 5050",
+ "build": "vite build",
+ "build:watch": "vite build --watch",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
diff --git a/pyproject.toml b/pyproject.toml
index 87e88a1b06bd..843d71263524 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -60,7 +60,7 @@ dependencies = [
"fake-useragent==2.2.0",
"chromadb==1.0.20",
"opensearch-py==2.8.0",
-
+
"transformers",
"sentence-transformers==5.1.1",
"accelerate",
@@ -111,8 +111,9 @@ dependencies = [
"azure-identity==1.25.0",
"azure-storage-blob==12.24.1",
-
+ "protobuf==5.29.5",
"ldap3==2.9.1",
+ "grpcio==1.74.0",
]
readme = "README.md"
requires-python = ">= 3.11, < 3.13.0a1"
@@ -127,16 +128,16 @@ classifiers = [
"Topic :: Multimedia",
]
-[project.optional-dependencies]
-postgres = [
- "psycopg2-binary==2.9.10",
- "pgvector==0.4.1",
-]
+#[project.optional-dependencies]
+#postgres = [
+# "psycopg2-binary==2.9.10",
+# "pgvector==0.4.1",
+#]
all = [
"pymongo",
- "psycopg2-binary==2.9.9",
- "pgvector==0.4.0",
+# "psycopg2-binary==2.9.9",
+# "pgvector==0.4.0",
"moto[s3]>=5.0.26",
"gcp-storage-emulator>=2024.8.3",
"docker~=7.1.0",
@@ -154,8 +155,8 @@ all = [
"firecrawl-py==4.5.0",
]
-[project.scripts]
-open-webui = "open_webui:app"
+#[project.scripts]
+#open-webui = "open_webui:app"
[build-system]
requires = ["hatchling"]
@@ -187,7 +188,7 @@ exclude = [
"webui.db",
"chroma.sqlite3",
]
-force-include = { "CHANGELOG.md" = "open_webui/CHANGELOG.md", build = "open_webui/frontend" }
+#force-include = { "CHANGELOG.md" = "open_webui/CHANGELOG.md", build = "open_webui/frontend" }
[tool.codespell]
# Ref: https://github.com/codespell-project/codespell#using-a-config-file
diff --git a/run.sh b/run.sh
index 6793fe16271c..f6315589757a 100644
--- a/run.sh
+++ b/run.sh
@@ -3,7 +3,7 @@
image_name="open-webui"
container_name="open-webui"
host_port=3000
-container_port=8080
+container_port=8083
docker build -t "$image_name" .
docker stop "$container_name" &>/dev/null || true
diff --git a/src/app.html b/src/app.html
index 9333dc8ba3de..7b2b7fa93a7b 100644
--- a/src/app.html
+++ b/src/app.html
@@ -2,28 +2,28 @@
-
+
-
+
-
+
-
-
+
+
-
+
+
{#if version && compareVersion(version.latest, version.current) && ($settings?.showUpdateToast ?? true)}
diff --git a/src/routes/(app)/admin/+layout.svelte b/src/routes/(app)/admin/+layout.svelte
index fb3395fb6fcc..680e77a3eea4 100644
--- a/src/routes/(app)/admin/+layout.svelte
+++ b/src/routes/(app)/admin/+layout.svelte
@@ -14,7 +14,7 @@
onMount(async () => {
if ($user?.role !== 'admin') {
- await goto('/');
+ await goto('/kael/');
}
loaded = true;
});
diff --git a/src/routes/(app)/admin/+page.svelte b/src/routes/(app)/admin/+page.svelte
index 2f12bbab8050..cac8a9bcf92f 100644
--- a/src/routes/(app)/admin/+page.svelte
+++ b/src/routes/(app)/admin/+page.svelte
@@ -3,6 +3,6 @@
import { onMount } from 'svelte';
onMount(() => {
- goto('/admin/users');
+ goto('/kael/admin/users');
});
diff --git a/src/routes/(app)/admin/analytics/+page.svelte b/src/routes/(app)/admin/analytics/+page.svelte
index 176e3162f8eb..e8dc40c64c8b 100644
--- a/src/routes/(app)/admin/analytics/+page.svelte
+++ b/src/routes/(app)/admin/analytics/+page.svelte
@@ -5,7 +5,7 @@
import Evaluations from '$lib/components/admin/Evaluations.svelte';
onMount(() => {
- goto('/admin/evaluations/leaderboard');
+ goto('/kael/admin/evaluations/leaderboard');
});
diff --git a/src/routes/(app)/admin/evaluations/+page.svelte b/src/routes/(app)/admin/evaluations/+page.svelte
index 176e3162f8eb..e8dc40c64c8b 100644
--- a/src/routes/(app)/admin/evaluations/+page.svelte
+++ b/src/routes/(app)/admin/evaluations/+page.svelte
@@ -5,7 +5,7 @@
import Evaluations from '$lib/components/admin/Evaluations.svelte';
onMount(() => {
- goto('/admin/evaluations/leaderboard');
+ goto('/kael/admin/evaluations/leaderboard');
});
diff --git a/src/routes/(app)/admin/functions/create/+page.svelte b/src/routes/(app)/admin/functions/create/+page.svelte
index bb13a759fd93..b49d3450fdd4 100644
--- a/src/routes/(app)/admin/functions/create/+page.svelte
+++ b/src/routes/(app)/admin/functions/create/+page.svelte
@@ -56,7 +56,7 @@
)
);
- await goto('/admin/functions');
+ await goto('/kael/admin/functions');
}
};
diff --git a/src/routes/(app)/admin/functions/edit/+page.svelte b/src/routes/(app)/admin/functions/edit/+page.svelte
index 6a456b983ec9..84302a67c8ea 100644
--- a/src/routes/(app)/admin/functions/edit/+page.svelte
+++ b/src/routes/(app)/admin/functions/edit/+page.svelte
@@ -66,7 +66,7 @@
if (id) {
func = await getFunctionById(localStorage.token, id).catch((error) => {
toast.error(`${error}`);
- goto('/admin/functions');
+ goto('/kael/admin/functions');
return null;
});
diff --git a/src/routes/(app)/admin/settings/+page.svelte b/src/routes/(app)/admin/settings/+page.svelte
index d8a497cb246b..0754768cbd2d 100644
--- a/src/routes/(app)/admin/settings/+page.svelte
+++ b/src/routes/(app)/admin/settings/+page.svelte
@@ -4,7 +4,7 @@
import Settings from '$lib/components/admin/Settings.svelte';
onMount(() => {
- goto('/admin/settings/general');
+ goto('/kael/admin/settings/general');
});
diff --git a/src/routes/(app)/admin/users/+page.svelte b/src/routes/(app)/admin/users/+page.svelte
index 8a8e6be79fa4..9798be400158 100644
--- a/src/routes/(app)/admin/users/+page.svelte
+++ b/src/routes/(app)/admin/users/+page.svelte
@@ -5,7 +5,7 @@
import Users from '$lib/components/admin/Users.svelte';
onMount(() => {
- goto('/admin/users/overview');
+ goto('/kael/admin/users/overview');
});
diff --git a/src/routes/(app)/notes/+layout.svelte b/src/routes/(app)/notes/+layout.svelte
index 2ee828796695..e4204942142d 100644
--- a/src/routes/(app)/notes/+layout.svelte
+++ b/src/routes/(app)/notes/+layout.svelte
@@ -15,7 +15,7 @@
)
) {
// If the feature is not enabled, redirect to the home page
- goto('/');
+ goto('/kael');
}
loaded = true;
diff --git a/src/routes/(app)/workspace/+layout.svelte b/src/routes/(app)/workspace/+layout.svelte
index 4473a2bae333..8967a03e19ff 100644
--- a/src/routes/(app)/workspace/+layout.svelte
+++ b/src/routes/(app)/workspace/+layout.svelte
@@ -23,19 +23,19 @@
onMount(async () => {
if ($user?.role !== 'admin') {
if ($page.url.pathname.includes('/models') && !$user?.permissions?.workspace?.models) {
- goto('/');
+ goto('/kael');
} else if (
$page.url.pathname.includes('/knowledge') &&
!$user?.permissions?.workspace?.knowledge
) {
- goto('/');
+ goto('/kael');
} else if (
$page.url.pathname.includes('/prompts') &&
!$user?.permissions?.workspace?.prompts
) {
- goto('/');
+ goto('/kael');
} else if ($page.url.pathname.includes('/tools') && !$user?.permissions?.workspace?.tools) {
- goto('/');
+ goto('/kael');
}
}
diff --git a/src/routes/(app)/workspace/+page.svelte b/src/routes/(app)/workspace/+page.svelte
index 65f9d4cef364..4249fd5bfa80 100644
--- a/src/routes/(app)/workspace/+page.svelte
+++ b/src/routes/(app)/workspace/+page.svelte
@@ -4,20 +4,20 @@
import { onMount } from 'svelte';
onMount(() => {
- if ($user?.role !== 'admin') {
- if ($user?.permissions?.workspace?.models) {
- goto('/workspace/models');
- } else if ($user?.permissions?.workspace?.knowledge) {
- goto('/workspace/knowledge');
- } else if ($user?.permissions?.workspace?.prompts) {
- goto('/workspace/prompts');
- } else if ($user?.permissions?.workspace?.tools) {
- goto('/workspace/tools');
- } else {
- goto('/');
- }
- } else {
- goto('/workspace/models');
- }
+ // if ($user?.role !== 'admin') {
+ // if ($user?.permissions?.workspace?.models) {
+ // goto('/kael/workspace/models');
+ // } else if ($user?.permissions?.workspace?.knowledge) {
+ // goto('/kael/workspace/knowledge');
+ // } else if ($user?.permissions?.workspace?.prompts) {
+ // goto('/kael/workspace/prompts');
+ // } else if ($user?.permissions?.workspace?.tools) {
+ // goto('/kael/workspace/tools');
+ // } else {
+ // goto('/kael');
+ // }
+ // } else {
+ goto('/kael/workspace/models');
+ // }
});
diff --git a/src/routes/(app)/workspace/models/create/+page.svelte b/src/routes/(app)/workspace/models/create/+page.svelte
index 31bdd96c38e0..2d6f548ae91e 100644
--- a/src/routes/(app)/workspace/models/create/+page.svelte
+++ b/src/routes/(app)/workspace/models/create/+page.svelte
@@ -54,7 +54,7 @@
)
);
toast.success($i18n.t('Model created successfully!'));
- await goto('/workspace/models');
+ await goto('/kael/workspace/models');
}
}
};
diff --git a/src/routes/(app)/workspace/models/edit/+page.svelte b/src/routes/(app)/workspace/models/edit/+page.svelte
index 1ff9652c6f60..17113ee87b01 100644
--- a/src/routes/(app)/workspace/models/edit/+page.svelte
+++ b/src/routes/(app)/workspace/models/edit/+page.svelte
@@ -23,10 +23,10 @@
});
if (!model) {
- goto('/workspace/models');
+ goto('/kael/workspace/models');
}
} else {
- goto('/workspace/models');
+ goto('/kael/workspace/models');
}
});
@@ -41,7 +41,7 @@
)
);
toast.success($i18n.t('Model updated successfully'));
- await goto('/workspace/models');
+ await goto('/kael/workspace/models');
}
};
diff --git a/src/routes/(app)/workspace/prompts/create/+page.svelte b/src/routes/(app)/workspace/prompts/create/+page.svelte
index 2fa25de6bd4c..74bc49f54e16 100644
--- a/src/routes/(app)/workspace/prompts/create/+page.svelte
+++ b/src/routes/(app)/workspace/prompts/create/+page.svelte
@@ -28,7 +28,7 @@
toast.success($i18n.t('Prompt created successfully'));
await prompts.set(await getPrompts(localStorage.token));
- await goto('/workspace/prompts');
+ await goto('/kael/workspace/prompts');
}
};
diff --git a/src/routes/(app)/workspace/prompts/edit/+page.svelte b/src/routes/(app)/workspace/prompts/edit/+page.svelte
index 9a317cc7c532..36b8309b9d3a 100644
--- a/src/routes/(app)/workspace/prompts/edit/+page.svelte
+++ b/src/routes/(app)/workspace/prompts/edit/+page.svelte
@@ -22,7 +22,7 @@
if (prompt) {
toast.success($i18n.t('Prompt updated successfully'));
await prompts.set(await getPrompts(localStorage.token));
- await goto('/workspace/prompts');
+ await goto('/kael/workspace/prompts');
}
};
diff --git a/src/routes/(app)/workspace/tools/create/+page.svelte b/src/routes/(app)/workspace/tools/create/+page.svelte
index c50ca44cceb0..a91b64b3a3bb 100644
--- a/src/routes/(app)/workspace/tools/create/+page.svelte
+++ b/src/routes/(app)/workspace/tools/create/+page.svelte
@@ -47,7 +47,7 @@
toast.success($i18n.t('Tool created successfully'));
tools.set(await getTools(localStorage.token));
- await goto('/workspace/tools');
+ await goto('/kael/workspace/tools');
}
};
diff --git a/src/routes/(app)/workspace/tools/edit/+page.svelte b/src/routes/(app)/workspace/tools/edit/+page.svelte
index 8714a58c70f0..747a67b4ac55 100644
--- a/src/routes/(app)/workspace/tools/edit/+page.svelte
+++ b/src/routes/(app)/workspace/tools/edit/+page.svelte
@@ -58,7 +58,7 @@
if (id) {
tool = await getToolById(localStorage.token, id).catch((error) => {
toast.error(`${error}`);
- goto('/workspace/tools');
+ goto('/kael/workspace/tools');
return null;
});
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index 3985413ebdc9..b2af361d81a4 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -71,14 +71,13 @@
const BREAKPOINT = 768;
const setupSocket = async (enableWebsocket) => {
- const _socket = io(`${WEBUI_BASE_URL}` || undefined, {
+ const _socket = io(undefined, {
reconnection: true,
reconnectionDelay: 1000,
reconnectionDelayMax: 5000,
randomizationFactor: 0.5,
- path: '/ws/socket.io',
+ path: '/kael/ws/socket.io',
transports: enableWebsocket ? ['websocket'] : ['polling', 'websocket'],
- auth: { token: localStorage.token }
});
await socket.set(_socket);
@@ -87,7 +86,6 @@
});
_socket.on('connect', async () => {
- console.log('connected', _socket.id);
const version = await getVersion(localStorage.token);
if (version !== null) {
if ($WEBUI_VERSION !== null && version !== $WEBUI_VERSION) {
@@ -313,7 +311,7 @@
toast.custom(NotificationToast, {
componentProps: {
onClick: () => {
- goto(`/c/${event.chat_id}`);
+ goto(`/kael/c/${event.chat_id}`);
},
content: content,
title: title
@@ -462,7 +460,7 @@
toast.custom(NotificationToast, {
componentProps: {
onClick: () => {
- goto(`/channels/${event.channel_id}`);
+ goto(`/kael/channels/${event.channel_id}`);
},
content: data?.content,
title: `#${event?.channel?.name}`
@@ -636,32 +634,22 @@
const currentUrl = `${window.location.pathname}${window.location.search}`;
const encodedUrl = encodeURIComponent(currentUrl);
- if (localStorage.token) {
- // Get Session User Info
- const sessionUser = await getSessionUser(localStorage.token).catch((error) => {
- toast.error(`${error}`);
- return null;
- });
+ // Get Session User Info
+ const sessionUser = await getSessionUser().catch((error) => {
+ toast.error(`${error}`);
+ return null;
+ });
- if (sessionUser) {
- await user.set(sessionUser);
- await config.set(await getBackendConfig());
- } else {
- // Redirect Invalid Session User to /auth Page
- localStorage.removeItem('token');
- await goto(`/auth?redirect=${encodedUrl}`);
- }
+ if (sessionUser) {
+ await user.set(sessionUser);
+ await config.set(await getBackendConfig());
} else {
- // Don't redirect if we're already on the auth page
- // Needed because we pass in tokens from OAuth logins via URL fragments
- if ($page.url.pathname !== '/auth') {
- await goto(`/auth?redirect=${encodedUrl}`);
- }
+ await goto(`/core/auth/login/?next=/kael?redirect=${encodedUrl}`);
}
}
} else {
// Redirect to /error when Backend Not Detected
- await goto(`/error`);
+ await goto(`/kael/error`);
}
await tick();
diff --git a/src/routes/auth/+page.svelte b/src/routes/auth/+page.svelte
index a6dd15f99794..ef95dfb2336d 100644
--- a/src/routes/auth/+page.svelte
+++ b/src/routes/auth/+page.svelte
@@ -38,7 +38,6 @@
const setSessionUser = async (sessionUser, redirectPath: string | null = null) => {
if (sessionUser) {
- console.log(sessionUser);
toast.success($i18n.t(`You're now logged in.`));
if (sessionUser.token) {
localStorage.token = sessionUser.token;
@@ -48,7 +47,7 @@
await config.set(await getBackendConfig());
if (!redirectPath) {
- redirectPath = $page.url.searchParams.get('redirect') || '/';
+ redirectPath = $page.url.searchParams.get('redirect') || '/kael';
}
goto(redirectPath);
@@ -156,7 +155,8 @@
onMount(async () => {
const redirectPath = $page.url.searchParams.get('redirect');
if ($user !== undefined) {
- goto(redirectPath || '/');
+ const redirectPath = "/core/auth/login/?next=/kael"
+ goto(redirectPath);
} else {
if (redirectPath) {
localStorage.setItem('redirectPath', redirectPath);
diff --git a/src/routes/error/+page.svelte b/src/routes/error/+page.svelte
index 748b6d7d4454..8d0d6c943e62 100644
--- a/src/routes/error/+page.svelte
+++ b/src/routes/error/+page.svelte
@@ -9,7 +9,7 @@
onMount(async () => {
if ($config) {
- await goto('/');
+ await goto('/kael/');
}
loaded = true;
diff --git a/src/routes/s/[id]/+page.svelte b/src/routes/s/[id]/+page.svelte
index 02ed91389bfb..40a9a48e074f 100644
--- a/src/routes/s/[id]/+page.svelte
+++ b/src/routes/s/[id]/+page.svelte
@@ -50,7 +50,7 @@
await tick();
loaded = true;
} else {
- await goto('/');
+ await goto('/kael/');
}
})();
}
@@ -87,7 +87,7 @@
);
await chatId.set($page.params.id);
chat = await getChatByShareId(localStorage.token, $chatId).catch(async (error) => {
- await goto('/');
+ await goto('/kael/');
return null;
});
@@ -136,7 +136,7 @@
});
if (res) {
- goto(`/c/${res.id}`);
+ goto(`/kael/c/${res.id}`);
}
};
diff --git a/static/avatar.png b/static/avatar.png
new file mode 100644
index 000000000000..8462a8a18b02
Binary files /dev/null and b/static/avatar.png differ
diff --git a/svelte.config.js b/svelte.config.js
index 82e05951f3f5..2d7d2e4b928c 100644
--- a/svelte.config.js
+++ b/svelte.config.js
@@ -36,6 +36,9 @@ const config = {
}
})(),
pollInterval: 60000
+ },
+ paths: {
+ base: '/kael'
}
},
vitePlugin: {
diff --git a/uv.lock b/uv.lock
index 7bde0eeb0179..70cd4f23cf77 100644
--- a/uv.lock
+++ b/uv.lock
@@ -1,5 +1,5 @@
version = 1
-revision = 2
+revision = 3
requires-python = ">=3.11, <3.13.0"
resolution-markers = [
"python_full_version < '3.12' and sys_platform == 'darwin'",
@@ -52,16 +52,16 @@ wheels = [
[[package]]
name = "aiohappyeyeballs"
-version = "2.4.4"
+version = "2.6.1"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/7f/55/e4373e888fdacb15563ef6fa9fa8c8252476ea071e96fb46defac9f18bf2/aiohappyeyeballs-2.4.4.tar.gz", hash = "sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745", size = 21977, upload-time = "2024-11-30T18:44:00.701Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/26/30/f84a107a9c4331c14b2b586036f40965c128aa4fee4dda5d3d51cb14ad54/aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", size = 22760, upload-time = "2025-03-12T01:42:48.764Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/b9/74/fbb6559de3607b3300b9be3cc64e97548d55678e44623db17820dbd20002/aiohappyeyeballs-2.4.4-py3-none-any.whl", hash = "sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8", size = 14756, upload-time = "2024-11-30T18:43:39.849Z" },
+ { url = "https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8", size = 15265, upload-time = "2025-03-12T01:42:47.083Z" },
]
[[package]]
name = "aiohttp"
-version = "3.11.11"
+version = "3.12.15"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "aiohappyeyeballs" },
@@ -72,50 +72,55 @@ dependencies = [
{ name = "propcache" },
{ name = "yarl" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/fe/ed/f26db39d29cd3cb2f5a3374304c713fe5ab5a0e4c8ee25a0c45cc6adf844/aiohttp-3.11.11.tar.gz", hash = "sha256:bb49c7f1e6ebf3821a42d81d494f538107610c3a705987f53068546b0e90303e", size = 7669618, upload-time = "2024-12-18T21:20:50.191Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/34/ae/e8806a9f054e15f1d18b04db75c23ec38ec954a10c0a68d3bd275d7e8be3/aiohttp-3.11.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ba74ec819177af1ef7f59063c6d35a214a8fde6f987f7661f4f0eecc468a8f76", size = 708624, upload-time = "2024-12-18T21:18:10.575Z" },
- { url = "https://files.pythonhosted.org/packages/c7/e0/313ef1a333fb4d58d0c55a6acb3cd772f5d7756604b455181049e222c020/aiohttp-3.11.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4af57160800b7a815f3fe0eba9b46bf28aafc195555f1824555fa2cfab6c1538", size = 468507, upload-time = "2024-12-18T21:18:12.224Z" },
- { url = "https://files.pythonhosted.org/packages/a9/60/03455476bf1f467e5b4a32a465c450548b2ce724eec39d69f737191f936a/aiohttp-3.11.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ffa336210cf9cd8ed117011085817d00abe4c08f99968deef0013ea283547204", size = 455571, upload-time = "2024-12-18T21:18:15.506Z" },
- { url = "https://files.pythonhosted.org/packages/be/f9/469588603bd75bf02c8ffb8c8a0d4b217eed446b49d4a767684685aa33fd/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81b8fe282183e4a3c7a1b72f5ade1094ed1c6345a8f153506d114af5bf8accd9", size = 1685694, upload-time = "2024-12-18T21:18:17.512Z" },
- { url = "https://files.pythonhosted.org/packages/88/b9/1b7fa43faf6c8616fa94c568dc1309ffee2b6b68b04ac268e5d64b738688/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3af41686ccec6a0f2bdc66686dc0f403c41ac2089f80e2214a0f82d001052c03", size = 1743660, upload-time = "2024-12-18T21:18:20.878Z" },
- { url = "https://files.pythonhosted.org/packages/2a/8b/0248d19dbb16b67222e75f6aecedd014656225733157e5afaf6a6a07e2e8/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70d1f9dde0e5dd9e292a6d4d00058737052b01f3532f69c0c65818dac26dc287", size = 1785421, upload-time = "2024-12-18T21:18:22.948Z" },
- { url = "https://files.pythonhosted.org/packages/c4/11/f478e071815a46ca0a5ae974651ff0c7a35898c55063305a896e58aa1247/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:249cc6912405917344192b9f9ea5cd5b139d49e0d2f5c7f70bdfaf6b4dbf3a2e", size = 1675145, upload-time = "2024-12-18T21:18:24.788Z" },
- { url = "https://files.pythonhosted.org/packages/26/5d/284d182fecbb5075ae10153ff7374f57314c93a8681666600e3a9e09c505/aiohttp-3.11.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0eb98d90b6690827dcc84c246811feeb4e1eea683c0eac6caed7549be9c84665", size = 1619804, upload-time = "2024-12-18T21:18:26.602Z" },
- { url = "https://files.pythonhosted.org/packages/1b/78/980064c2ad685c64ce0e8aeeb7ef1e53f43c5b005edcd7d32e60809c4992/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ec82bf1fda6cecce7f7b915f9196601a1bd1a3079796b76d16ae4cce6d0ef89b", size = 1654007, upload-time = "2024-12-18T21:18:29.669Z" },
- { url = "https://files.pythonhosted.org/packages/21/8d/9e658d63b1438ad42b96f94da227f2e2c1d5c6001c9e8ffcc0bfb22e9105/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9fd46ce0845cfe28f108888b3ab17abff84ff695e01e73657eec3f96d72eef34", size = 1650022, upload-time = "2024-12-18T21:18:33.249Z" },
- { url = "https://files.pythonhosted.org/packages/85/fd/a032bf7f2755c2df4f87f9effa34ccc1ef5cea465377dbaeef93bb56bbd6/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:bd176afcf8f5d2aed50c3647d4925d0db0579d96f75a31e77cbaf67d8a87742d", size = 1732899, upload-time = "2024-12-18T21:18:35.225Z" },
- { url = "https://files.pythonhosted.org/packages/c5/0c/c2b85fde167dd440c7ba50af2aac20b5a5666392b174df54c00f888c5a75/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ec2aa89305006fba9ffb98970db6c8221541be7bee4c1d027421d6f6df7d1ce2", size = 1755142, upload-time = "2024-12-18T21:18:37.48Z" },
- { url = "https://files.pythonhosted.org/packages/bc/78/91ae1a3b3b3bed8b893c5d69c07023e151b1c95d79544ad04cf68f596c2f/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:92cde43018a2e17d48bb09c79e4d4cb0e236de5063ce897a5e40ac7cb4878773", size = 1692736, upload-time = "2024-12-18T21:18:40.967Z" },
- { url = "https://files.pythonhosted.org/packages/77/89/a7ef9c4b4cdb546fcc650ca7f7395aaffbd267f0e1f648a436bec33c9b95/aiohttp-3.11.11-cp311-cp311-win32.whl", hash = "sha256:aba807f9569455cba566882c8938f1a549f205ee43c27b126e5450dc9f83cc62", size = 416418, upload-time = "2024-12-18T21:18:44.281Z" },
- { url = "https://files.pythonhosted.org/packages/fc/db/2192489a8a51b52e06627506f8ac8df69ee221de88ab9bdea77aa793aa6a/aiohttp-3.11.11-cp311-cp311-win_amd64.whl", hash = "sha256:ae545f31489548c87b0cced5755cfe5a5308d00407000e72c4fa30b19c3220ac", size = 442509, upload-time = "2024-12-18T21:18:47.323Z" },
- { url = "https://files.pythonhosted.org/packages/69/cf/4bda538c502f9738d6b95ada11603c05ec260807246e15e869fc3ec5de97/aiohttp-3.11.11-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e595c591a48bbc295ebf47cb91aebf9bd32f3ff76749ecf282ea7f9f6bb73886", size = 704666, upload-time = "2024-12-18T21:18:49.254Z" },
- { url = "https://files.pythonhosted.org/packages/46/7b/87fcef2cad2fad420ca77bef981e815df6904047d0a1bd6aeded1b0d1d66/aiohttp-3.11.11-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3ea1b59dc06396b0b424740a10a0a63974c725b1c64736ff788a3689d36c02d2", size = 464057, upload-time = "2024-12-18T21:18:51.375Z" },
- { url = "https://files.pythonhosted.org/packages/5a/a6/789e1f17a1b6f4a38939fbc39d29e1d960d5f89f73d0629a939410171bc0/aiohttp-3.11.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8811f3f098a78ffa16e0ea36dffd577eb031aea797cbdba81be039a4169e242c", size = 455996, upload-time = "2024-12-18T21:18:53.11Z" },
- { url = "https://files.pythonhosted.org/packages/b7/dd/485061fbfef33165ce7320db36e530cd7116ee1098e9c3774d15a732b3fd/aiohttp-3.11.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7227b87a355ce1f4bf83bfae4399b1f5bb42e0259cb9405824bd03d2f4336a", size = 1682367, upload-time = "2024-12-18T21:18:55.053Z" },
- { url = "https://files.pythonhosted.org/packages/e9/d7/9ec5b3ea9ae215c311d88b2093e8da17e67b8856673e4166c994e117ee3e/aiohttp-3.11.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d40f9da8cabbf295d3a9dae1295c69975b86d941bc20f0a087f0477fa0a66231", size = 1736989, upload-time = "2024-12-18T21:18:56.933Z" },
- { url = "https://files.pythonhosted.org/packages/d6/fb/ea94927f7bfe1d86178c9d3e0a8c54f651a0a655214cce930b3c679b8f64/aiohttp-3.11.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffb3dc385f6bb1568aa974fe65da84723210e5d9707e360e9ecb51f59406cd2e", size = 1793265, upload-time = "2024-12-18T21:19:00.174Z" },
- { url = "https://files.pythonhosted.org/packages/40/7f/6de218084f9b653026bd7063cd8045123a7ba90c25176465f266976d8c82/aiohttp-3.11.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8f5f7515f3552d899c61202d99dcb17d6e3b0de777900405611cd747cecd1b8", size = 1691841, upload-time = "2024-12-18T21:19:02.3Z" },
- { url = "https://files.pythonhosted.org/packages/77/e2/992f43d87831cbddb6b09c57ab55499332f60ad6fdbf438ff4419c2925fc/aiohttp-3.11.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3499c7ffbfd9c6a3d8d6a2b01c26639da7e43d47c7b4f788016226b1e711caa8", size = 1619317, upload-time = "2024-12-18T21:19:04.33Z" },
- { url = "https://files.pythonhosted.org/packages/96/74/879b23cdd816db4133325a201287c95bef4ce669acde37f8f1b8669e1755/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8e2bf8029dbf0810c7bfbc3e594b51c4cc9101fbffb583a3923aea184724203c", size = 1641416, upload-time = "2024-12-18T21:19:09.842Z" },
- { url = "https://files.pythonhosted.org/packages/30/98/b123f6b15d87c54e58fd7ae3558ff594f898d7f30a90899718f3215ad328/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b6212a60e5c482ef90f2d788835387070a88d52cf6241d3916733c9176d39eab", size = 1646514, upload-time = "2024-12-18T21:19:12.154Z" },
- { url = "https://files.pythonhosted.org/packages/d7/38/257fda3dc99d6978ab943141d5165ec74fd4b4164baa15e9c66fa21da86b/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:d119fafe7b634dbfa25a8c597718e69a930e4847f0b88e172744be24515140da", size = 1702095, upload-time = "2024-12-18T21:19:15.51Z" },
- { url = "https://files.pythonhosted.org/packages/0c/f4/ddab089053f9fb96654df5505c0a69bde093214b3c3454f6bfdb1845f558/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:6fba278063559acc730abf49845d0e9a9e1ba74f85f0ee6efd5803f08b285853", size = 1734611, upload-time = "2024-12-18T21:19:18.849Z" },
- { url = "https://files.pythonhosted.org/packages/c3/d6/f30b2bc520c38c8aa4657ed953186e535ae84abe55c08d0f70acd72ff577/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:92fc484e34b733704ad77210c7957679c5c3877bd1e6b6d74b185e9320cc716e", size = 1694576, upload-time = "2024-12-18T21:19:21.257Z" },
- { url = "https://files.pythonhosted.org/packages/bc/97/b0a88c3f4c6d0020b34045ee6d954058abc870814f6e310c4c9b74254116/aiohttp-3.11.11-cp312-cp312-win32.whl", hash = "sha256:9f5b3c1ed63c8fa937a920b6c1bec78b74ee09593b3f5b979ab2ae5ef60d7600", size = 411363, upload-time = "2024-12-18T21:19:23.122Z" },
- { url = "https://files.pythonhosted.org/packages/7f/23/cc36d9c398980acaeeb443100f0216f50a7cfe20c67a9fd0a2f1a5a846de/aiohttp-3.11.11-cp312-cp312-win_amd64.whl", hash = "sha256:1e69966ea6ef0c14ee53ef7a3d68b564cc408121ea56c0caa2dc918c1b2f553d", size = 437666, upload-time = "2024-12-18T21:19:26.425Z" },
+sdist = { url = "https://files.pythonhosted.org/packages/9b/e7/d92a237d8802ca88483906c388f7c201bbe96cd80a165ffd0ac2f6a8d59f/aiohttp-3.12.15.tar.gz", hash = "sha256:4fc61385e9c98d72fcdf47e6dd81833f47b2f77c114c29cd64a361be57a763a2", size = 7823716, upload-time = "2025-07-29T05:52:32.215Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/20/19/9e86722ec8e835959bd97ce8c1efa78cf361fa4531fca372551abcc9cdd6/aiohttp-3.12.15-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d3ce17ce0220383a0f9ea07175eeaa6aa13ae5a41f30bc61d84df17f0e9b1117", size = 711246, upload-time = "2025-07-29T05:50:15.937Z" },
+ { url = "https://files.pythonhosted.org/packages/71/f9/0a31fcb1a7d4629ac9d8f01f1cb9242e2f9943f47f5d03215af91c3c1a26/aiohttp-3.12.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:010cc9bbd06db80fe234d9003f67e97a10fe003bfbedb40da7d71c1008eda0fe", size = 483515, upload-time = "2025-07-29T05:50:17.442Z" },
+ { url = "https://files.pythonhosted.org/packages/62/6c/94846f576f1d11df0c2e41d3001000527c0fdf63fce7e69b3927a731325d/aiohttp-3.12.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3f9d7c55b41ed687b9d7165b17672340187f87a773c98236c987f08c858145a9", size = 471776, upload-time = "2025-07-29T05:50:19.568Z" },
+ { url = "https://files.pythonhosted.org/packages/f8/6c/f766d0aaafcee0447fad0328da780d344489c042e25cd58fde566bf40aed/aiohttp-3.12.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc4fbc61bb3548d3b482f9ac7ddd0f18c67e4225aaa4e8552b9f1ac7e6bda9e5", size = 1741977, upload-time = "2025-07-29T05:50:21.665Z" },
+ { url = "https://files.pythonhosted.org/packages/17/e5/fb779a05ba6ff44d7bc1e9d24c644e876bfff5abe5454f7b854cace1b9cc/aiohttp-3.12.15-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7fbc8a7c410bb3ad5d595bb7118147dfbb6449d862cc1125cf8867cb337e8728", size = 1690645, upload-time = "2025-07-29T05:50:23.333Z" },
+ { url = "https://files.pythonhosted.org/packages/37/4e/a22e799c2035f5d6a4ad2cf8e7c1d1bd0923192871dd6e367dafb158b14c/aiohttp-3.12.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:74dad41b3458dbb0511e760fb355bb0b6689e0630de8a22b1b62a98777136e16", size = 1789437, upload-time = "2025-07-29T05:50:25.007Z" },
+ { url = "https://files.pythonhosted.org/packages/28/e5/55a33b991f6433569babb56018b2fb8fb9146424f8b3a0c8ecca80556762/aiohttp-3.12.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b6f0af863cf17e6222b1735a756d664159e58855da99cfe965134a3ff63b0b0", size = 1828482, upload-time = "2025-07-29T05:50:26.693Z" },
+ { url = "https://files.pythonhosted.org/packages/c6/82/1ddf0ea4f2f3afe79dffed5e8a246737cff6cbe781887a6a170299e33204/aiohttp-3.12.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b5b7fe4972d48a4da367043b8e023fb70a04d1490aa7d68800e465d1b97e493b", size = 1730944, upload-time = "2025-07-29T05:50:28.382Z" },
+ { url = "https://files.pythonhosted.org/packages/1b/96/784c785674117b4cb3877522a177ba1b5e4db9ce0fd519430b5de76eec90/aiohttp-3.12.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6443cca89553b7a5485331bc9bedb2342b08d073fa10b8c7d1c60579c4a7b9bd", size = 1668020, upload-time = "2025-07-29T05:50:30.032Z" },
+ { url = "https://files.pythonhosted.org/packages/12/8a/8b75f203ea7e5c21c0920d84dd24a5c0e971fe1e9b9ebbf29ae7e8e39790/aiohttp-3.12.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6c5f40ec615e5264f44b4282ee27628cea221fcad52f27405b80abb346d9f3f8", size = 1716292, upload-time = "2025-07-29T05:50:31.983Z" },
+ { url = "https://files.pythonhosted.org/packages/47/0b/a1451543475bb6b86a5cfc27861e52b14085ae232896a2654ff1231c0992/aiohttp-3.12.15-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:2abbb216a1d3a2fe86dbd2edce20cdc5e9ad0be6378455b05ec7f77361b3ab50", size = 1711451, upload-time = "2025-07-29T05:50:33.989Z" },
+ { url = "https://files.pythonhosted.org/packages/55/fd/793a23a197cc2f0d29188805cfc93aa613407f07e5f9da5cd1366afd9d7c/aiohttp-3.12.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:db71ce547012a5420a39c1b744d485cfb823564d01d5d20805977f5ea1345676", size = 1691634, upload-time = "2025-07-29T05:50:35.846Z" },
+ { url = "https://files.pythonhosted.org/packages/ca/bf/23a335a6670b5f5dfc6d268328e55a22651b440fca341a64fccf1eada0c6/aiohttp-3.12.15-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ced339d7c9b5030abad5854aa5413a77565e5b6e6248ff927d3e174baf3badf7", size = 1785238, upload-time = "2025-07-29T05:50:37.597Z" },
+ { url = "https://files.pythonhosted.org/packages/57/4f/ed60a591839a9d85d40694aba5cef86dde9ee51ce6cca0bb30d6eb1581e7/aiohttp-3.12.15-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:7c7dd29c7b5bda137464dc9bfc738d7ceea46ff70309859ffde8c022e9b08ba7", size = 1805701, upload-time = "2025-07-29T05:50:39.591Z" },
+ { url = "https://files.pythonhosted.org/packages/85/e0/444747a9455c5de188c0f4a0173ee701e2e325d4b2550e9af84abb20cdba/aiohttp-3.12.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:421da6fd326460517873274875c6c5a18ff225b40da2616083c5a34a7570b685", size = 1718758, upload-time = "2025-07-29T05:50:41.292Z" },
+ { url = "https://files.pythonhosted.org/packages/36/ab/1006278d1ffd13a698e5dd4bfa01e5878f6bddefc296c8b62649753ff249/aiohttp-3.12.15-cp311-cp311-win32.whl", hash = "sha256:4420cf9d179ec8dfe4be10e7d0fe47d6d606485512ea2265b0d8c5113372771b", size = 428868, upload-time = "2025-07-29T05:50:43.063Z" },
+ { url = "https://files.pythonhosted.org/packages/10/97/ad2b18700708452400278039272032170246a1bf8ec5d832772372c71f1a/aiohttp-3.12.15-cp311-cp311-win_amd64.whl", hash = "sha256:edd533a07da85baa4b423ee8839e3e91681c7bfa19b04260a469ee94b778bf6d", size = 453273, upload-time = "2025-07-29T05:50:44.613Z" },
+ { url = "https://files.pythonhosted.org/packages/63/97/77cb2450d9b35f517d6cf506256bf4f5bda3f93a66b4ad64ba7fc917899c/aiohttp-3.12.15-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:802d3868f5776e28f7bf69d349c26fc0efadb81676d0afa88ed00d98a26340b7", size = 702333, upload-time = "2025-07-29T05:50:46.507Z" },
+ { url = "https://files.pythonhosted.org/packages/83/6d/0544e6b08b748682c30b9f65640d006e51f90763b41d7c546693bc22900d/aiohttp-3.12.15-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f2800614cd560287be05e33a679638e586a2d7401f4ddf99e304d98878c29444", size = 476948, upload-time = "2025-07-29T05:50:48.067Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/1d/c8c40e611e5094330284b1aea8a4b02ca0858f8458614fa35754cab42b9c/aiohttp-3.12.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8466151554b593909d30a0a125d638b4e5f3836e5aecde85b66b80ded1cb5b0d", size = 469787, upload-time = "2025-07-29T05:50:49.669Z" },
+ { url = "https://files.pythonhosted.org/packages/38/7d/b76438e70319796bfff717f325d97ce2e9310f752a267bfdf5192ac6082b/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e5a495cb1be69dae4b08f35a6c4579c539e9b5706f606632102c0f855bcba7c", size = 1716590, upload-time = "2025-07-29T05:50:51.368Z" },
+ { url = "https://files.pythonhosted.org/packages/79/b1/60370d70cdf8b269ee1444b390cbd72ce514f0d1cd1a715821c784d272c9/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6404dfc8cdde35c69aaa489bb3542fb86ef215fc70277c892be8af540e5e21c0", size = 1699241, upload-time = "2025-07-29T05:50:53.628Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/2b/4968a7b8792437ebc12186db31523f541943e99bda8f30335c482bea6879/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3ead1c00f8521a5c9070fcb88f02967b1d8a0544e6d85c253f6968b785e1a2ab", size = 1754335, upload-time = "2025-07-29T05:50:55.394Z" },
+ { url = "https://files.pythonhosted.org/packages/fb/c1/49524ed553f9a0bec1a11fac09e790f49ff669bcd14164f9fab608831c4d/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6990ef617f14450bc6b34941dba4f12d5613cbf4e33805932f853fbd1cf18bfb", size = 1800491, upload-time = "2025-07-29T05:50:57.202Z" },
+ { url = "https://files.pythonhosted.org/packages/de/5e/3bf5acea47a96a28c121b167f5ef659cf71208b19e52a88cdfa5c37f1fcc/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd736ed420f4db2b8148b52b46b88ed038d0354255f9a73196b7bbce3ea97545", size = 1719929, upload-time = "2025-07-29T05:50:59.192Z" },
+ { url = "https://files.pythonhosted.org/packages/39/94/8ae30b806835bcd1cba799ba35347dee6961a11bd507db634516210e91d8/aiohttp-3.12.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c5092ce14361a73086b90c6efb3948ffa5be2f5b6fbcf52e8d8c8b8848bb97c", size = 1635733, upload-time = "2025-07-29T05:51:01.394Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/46/06cdef71dd03acd9da7f51ab3a9107318aee12ad38d273f654e4f981583a/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:aaa2234bb60c4dbf82893e934d8ee8dea30446f0647e024074237a56a08c01bd", size = 1696790, upload-time = "2025-07-29T05:51:03.657Z" },
+ { url = "https://files.pythonhosted.org/packages/02/90/6b4cfaaf92ed98d0ec4d173e78b99b4b1a7551250be8937d9d67ecb356b4/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:6d86a2fbdd14192e2f234a92d3b494dd4457e683ba07e5905a0b3ee25389ac9f", size = 1718245, upload-time = "2025-07-29T05:51:05.911Z" },
+ { url = "https://files.pythonhosted.org/packages/2e/e6/2593751670fa06f080a846f37f112cbe6f873ba510d070136a6ed46117c6/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a041e7e2612041a6ddf1c6a33b883be6a421247c7afd47e885969ee4cc58bd8d", size = 1658899, upload-time = "2025-07-29T05:51:07.753Z" },
+ { url = "https://files.pythonhosted.org/packages/8f/28/c15bacbdb8b8eb5bf39b10680d129ea7410b859e379b03190f02fa104ffd/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5015082477abeafad7203757ae44299a610e89ee82a1503e3d4184e6bafdd519", size = 1738459, upload-time = "2025-07-29T05:51:09.56Z" },
+ { url = "https://files.pythonhosted.org/packages/00/de/c269cbc4faa01fb10f143b1670633a8ddd5b2e1ffd0548f7aa49cb5c70e2/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:56822ff5ddfd1b745534e658faba944012346184fbfe732e0d6134b744516eea", size = 1766434, upload-time = "2025-07-29T05:51:11.423Z" },
+ { url = "https://files.pythonhosted.org/packages/52/b0/4ff3abd81aa7d929b27d2e1403722a65fc87b763e3a97b3a2a494bfc63bc/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b2acbbfff69019d9014508c4ba0401822e8bae5a5fdc3b6814285b71231b60f3", size = 1726045, upload-time = "2025-07-29T05:51:13.689Z" },
+ { url = "https://files.pythonhosted.org/packages/71/16/949225a6a2dd6efcbd855fbd90cf476052e648fb011aa538e3b15b89a57a/aiohttp-3.12.15-cp312-cp312-win32.whl", hash = "sha256:d849b0901b50f2185874b9a232f38e26b9b3d4810095a7572eacea939132d4e1", size = 423591, upload-time = "2025-07-29T05:51:15.452Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/d8/fa65d2a349fe938b76d309db1a56a75c4fb8cc7b17a398b698488a939903/aiohttp-3.12.15-cp312-cp312-win_amd64.whl", hash = "sha256:b390ef5f62bb508a9d67cb3bba9b8356e23b3996da7062f1a57ce1a79d2b3d34", size = 450266, upload-time = "2025-07-29T05:51:17.239Z" },
]
[[package]]
name = "aiosignal"
-version = "1.3.2"
+version = "1.4.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "frozenlist" },
+ { name = "typing-extensions" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/ba/b5/6d55e80f6d8a08ce22b982eafa278d823b541c925f11ee774b0b9c43473d/aiosignal-1.3.2.tar.gz", hash = "sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54", size = 19424, upload-time = "2024-12-13T17:10:40.86Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/ec/6a/bc7e17a3e87a2985d3e8f4da4cd0f481060eb78fb08596c42be62c90a4d9/aiosignal-1.3.2-py2.py3-none-any.whl", hash = "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5", size = 7597, upload-time = "2024-12-13T17:10:38.469Z" },
+ { url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" },
]
[[package]]
@@ -173,15 +178,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/46/eb/e7f063ad1fec6b3178a3cd82d1a3c4de82cccf283fc42746168188e1cdd5/anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a", size = 96041, upload-time = "2025-01-05T13:13:07.985Z" },
]
-[[package]]
-name = "appdirs"
-version = "1.4.4"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/d7/d8/05696357e0311f5b5c316d7b95f46c669dd9c15aaeecbb48c7d0aeb88c40/appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41", size = 13470, upload-time = "2020-05-11T07:59:51.037Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/3b/00/2344469e2084fb287c2e0b57b72910309874c3245463acd6cf5e3db69324/appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128", size = 9566, upload-time = "2020-05-11T07:59:49.499Z" },
-]
-
[[package]]
name = "apscheduler"
version = "3.10.4"
@@ -198,14 +194,14 @@ wheels = [
[[package]]
name = "argon2-cffi"
-version = "23.1.0"
+version = "25.1.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "argon2-cffi-bindings" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/31/fa/57ec2c6d16ecd2ba0cf15f3c7d1c3c2e7b5fcb83555ff56d7ab10888ec8f/argon2_cffi-23.1.0.tar.gz", hash = "sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08", size = 42798, upload-time = "2023-08-15T14:13:12.711Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/0e/89/ce5af8a7d472a67cc819d5d998aa8c82c5d860608c4db9f46f1162d7dab9/argon2_cffi-25.1.0.tar.gz", hash = "sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1", size = 45706, upload-time = "2025-06-03T06:55:32.073Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/a4/6a/e8a041599e78b6b3752da48000b14c8d1e8a04ded09c88c714ba047f34f5/argon2_cffi-23.1.0-py3-none-any.whl", hash = "sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea", size = 15124, upload-time = "2023-08-15T14:13:10.752Z" },
+ { url = "https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl", hash = "sha256:fdc8b074db390fccb6eb4a3604ae7231f219aa669a2652e0f20e16ba513d5741", size = 14657, upload-time = "2025-06-03T06:55:30.804Z" },
]
[[package]]
@@ -258,14 +254,14 @@ wheels = [
[[package]]
name = "authlib"
-version = "1.4.1"
+version = "1.6.5"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cryptography" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/58/73/0aa3d68b1c3caeac01ae0bad7a3d2a23029c4a3b42c7ccb89d752ed67eb2/authlib-1.4.1.tar.gz", hash = "sha256:30ead9ea4993cdbab821dc6e01e818362f92da290c04c7f6a1940f86507a790d", size = 147376, upload-time = "2025-01-28T13:05:27.309Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/cd/3f/1d3bbd0bf23bdd99276d4def22f29c27a914067b4cf66f753ff9b8bbd0f3/authlib-1.6.5.tar.gz", hash = "sha256:6aaf9c79b7cc96c900f0b284061691c5d4e61221640a948fe690b556a6d6d10b", size = 164553, upload-time = "2025-10-02T13:36:09.489Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/e8/6a/e83a6c04f8c6014c33d97c135782a55370cf60513f8d9f99f1279c7f9c13/Authlib-1.4.1-py2.py3-none-any.whl", hash = "sha256:edc29c3f6a3e72cd9e9f45fff67fc663a2c364022eb0371c003f22d5405915c1", size = 225610, upload-time = "2025-01-28T13:05:24.761Z" },
+ { url = "https://files.pythonhosted.org/packages/f8/aa/5082412d1ee302e9e7d80b6949bc4d2a8fa1149aaab610c5fc24709605d6/authlib-1.6.5-py2.py3-none-any.whl", hash = "sha256:3e0e0507807f842b02175507bdee8957a1d5707fd4afb17c32fb43fee90b6e3a", size = 243608, upload-time = "2025-10-02T13:36:07.637Z" },
]
[[package]]
@@ -318,7 +314,7 @@ wheels = [
[[package]]
name = "azure-identity"
-version = "1.20.0"
+version = "1.25.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "azure-core" },
@@ -327,9 +323,9 @@ dependencies = [
{ name = "msal-extensions" },
{ name = "typing-extensions" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/ee/89/7d170fab0b85d9650cdb7abda087e849644beb52bd28f6804620dd0cecd9/azure_identity-1.20.0.tar.gz", hash = "sha256:40597210d56c83e15031b0fe2ea3b26420189e1e7f3e20bdbb292315da1ba014", size = 264447, upload-time = "2025-02-12T00:40:41.225Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/4e/9e/4c9682a286c3c89e437579bd9f64f311020e5125c1321fd3a653166b5716/azure_identity-1.25.0.tar.gz", hash = "sha256:4177df34d684cddc026e6cf684e1abb57767aa9d84e7f2129b080ec45eee7733", size = 278507, upload-time = "2025-09-12T01:30:04.418Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/de/aa/819513c1dbef990af690bb5eefb5e337f8698d75dfdb7302528f50ce1994/azure_identity-1.20.0-py3-none-any.whl", hash = "sha256:5f23fc4889a66330e840bd78830287e14f3761820fe3c5f77ac875edcb9ec998", size = 188243, upload-time = "2025-02-12T00:40:44.99Z" },
+ { url = "https://files.pythonhosted.org/packages/75/54/81683b6756676a22e037b209695b08008258e603f7e47c56834029c5922a/azure_identity-1.25.0-py3-none-any.whl", hash = "sha256:becaec086bbdf8d1a6aa4fb080c2772a0f824a97d50c29637ec8cc4933f1e82d", size = 190861, upload-time = "2025-09-12T01:30:06.474Z" },
]
[[package]]
@@ -358,42 +354,44 @@ wheels = [
[[package]]
name = "bcrypt"
-version = "4.3.0"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/bb/5d/6d7433e0f3cd46ce0b43cd65e1db465ea024dbb8216fb2404e919c2ad77b/bcrypt-4.3.0.tar.gz", hash = "sha256:3a3fd2204178b6d2adcf09cb4f6426ffef54762577a7c9b54c159008cb288c18", size = 25697, upload-time = "2025-02-28T01:24:09.174Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/11/22/5ada0b9af72b60cbc4c9a399fdde4af0feaa609d27eb0adc61607997a3fa/bcrypt-4.3.0-cp38-abi3-macosx_10_12_universal2.whl", hash = "sha256:f81b0ed2639568bf14749112298f9e4e2b28853dab50a8b357e31798686a036d", size = 498019, upload-time = "2025-02-28T01:23:05.838Z" },
- { url = "https://files.pythonhosted.org/packages/b8/8c/252a1edc598dc1ce57905be173328eda073083826955ee3c97c7ff5ba584/bcrypt-4.3.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:864f8f19adbe13b7de11ba15d85d4a428c7e2f344bac110f667676a0ff84924b", size = 279174, upload-time = "2025-02-28T01:23:07.274Z" },
- { url = "https://files.pythonhosted.org/packages/29/5b/4547d5c49b85f0337c13929f2ccbe08b7283069eea3550a457914fc078aa/bcrypt-4.3.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e36506d001e93bffe59754397572f21bb5dc7c83f54454c990c74a468cd589e", size = 283870, upload-time = "2025-02-28T01:23:09.151Z" },
- { url = "https://files.pythonhosted.org/packages/be/21/7dbaf3fa1745cb63f776bb046e481fbababd7d344c5324eab47f5ca92dd2/bcrypt-4.3.0-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:842d08d75d9fe9fb94b18b071090220697f9f184d4547179b60734846461ed59", size = 279601, upload-time = "2025-02-28T01:23:11.461Z" },
- { url = "https://files.pythonhosted.org/packages/6d/64/e042fc8262e971347d9230d9abbe70d68b0a549acd8611c83cebd3eaec67/bcrypt-4.3.0-cp38-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7c03296b85cb87db865d91da79bf63d5609284fc0cab9472fdd8367bbd830753", size = 297660, upload-time = "2025-02-28T01:23:12.989Z" },
- { url = "https://files.pythonhosted.org/packages/50/b8/6294eb84a3fef3b67c69b4470fcdd5326676806bf2519cda79331ab3c3a9/bcrypt-4.3.0-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:62f26585e8b219cdc909b6a0069efc5e4267e25d4a3770a364ac58024f62a761", size = 284083, upload-time = "2025-02-28T01:23:14.5Z" },
- { url = "https://files.pythonhosted.org/packages/62/e6/baff635a4f2c42e8788fe1b1633911c38551ecca9a749d1052d296329da6/bcrypt-4.3.0-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:beeefe437218a65322fbd0069eb437e7c98137e08f22c4660ac2dc795c31f8bb", size = 279237, upload-time = "2025-02-28T01:23:16.686Z" },
- { url = "https://files.pythonhosted.org/packages/39/48/46f623f1b0c7dc2e5de0b8af5e6f5ac4cc26408ac33f3d424e5ad8da4a90/bcrypt-4.3.0-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:97eea7408db3a5bcce4a55d13245ab3fa566e23b4c67cd227062bb49e26c585d", size = 283737, upload-time = "2025-02-28T01:23:18.897Z" },
- { url = "https://files.pythonhosted.org/packages/49/8b/70671c3ce9c0fca4a6cc3cc6ccbaa7e948875a2e62cbd146e04a4011899c/bcrypt-4.3.0-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:191354ebfe305e84f344c5964c7cd5f924a3bfc5d405c75ad07f232b6dffb49f", size = 312741, upload-time = "2025-02-28T01:23:21.041Z" },
- { url = "https://files.pythonhosted.org/packages/27/fb/910d3a1caa2d249b6040a5caf9f9866c52114d51523ac2fb47578a27faee/bcrypt-4.3.0-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:41261d64150858eeb5ff43c753c4b216991e0ae16614a308a15d909503617732", size = 316472, upload-time = "2025-02-28T01:23:23.183Z" },
- { url = "https://files.pythonhosted.org/packages/dc/cf/7cf3a05b66ce466cfb575dbbda39718d45a609daa78500f57fa9f36fa3c0/bcrypt-4.3.0-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:33752b1ba962ee793fa2b6321404bf20011fe45b9afd2a842139de3011898fef", size = 343606, upload-time = "2025-02-28T01:23:25.361Z" },
- { url = "https://files.pythonhosted.org/packages/e3/b8/e970ecc6d7e355c0d892b7f733480f4aa8509f99b33e71550242cf0b7e63/bcrypt-4.3.0-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:50e6e80a4bfd23a25f5c05b90167c19030cf9f87930f7cb2eacb99f45d1c3304", size = 362867, upload-time = "2025-02-28T01:23:26.875Z" },
- { url = "https://files.pythonhosted.org/packages/a9/97/8d3118efd8354c555a3422d544163f40d9f236be5b96c714086463f11699/bcrypt-4.3.0-cp38-abi3-win32.whl", hash = "sha256:67a561c4d9fb9465ec866177e7aebcad08fe23aaf6fbd692a6fab69088abfc51", size = 160589, upload-time = "2025-02-28T01:23:28.381Z" },
- { url = "https://files.pythonhosted.org/packages/29/07/416f0b99f7f3997c69815365babbc2e8754181a4b1899d921b3c7d5b6f12/bcrypt-4.3.0-cp38-abi3-win_amd64.whl", hash = "sha256:584027857bc2843772114717a7490a37f68da563b3620f78a849bcb54dc11e62", size = 152794, upload-time = "2025-02-28T01:23:30.187Z" },
- { url = "https://files.pythonhosted.org/packages/6e/c1/3fa0e9e4e0bfd3fd77eb8b52ec198fd6e1fd7e9402052e43f23483f956dd/bcrypt-4.3.0-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:0d3efb1157edebfd9128e4e46e2ac1a64e0c1fe46fb023158a407c7892b0f8c3", size = 498969, upload-time = "2025-02-28T01:23:31.945Z" },
- { url = "https://files.pythonhosted.org/packages/ce/d4/755ce19b6743394787fbd7dff6bf271b27ee9b5912a97242e3caf125885b/bcrypt-4.3.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08bacc884fd302b611226c01014eca277d48f0a05187666bca23aac0dad6fe24", size = 279158, upload-time = "2025-02-28T01:23:34.161Z" },
- { url = "https://files.pythonhosted.org/packages/9b/5d/805ef1a749c965c46b28285dfb5cd272a7ed9fa971f970435a5133250182/bcrypt-4.3.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6746e6fec103fcd509b96bacdfdaa2fbde9a553245dbada284435173a6f1aef", size = 284285, upload-time = "2025-02-28T01:23:35.765Z" },
- { url = "https://files.pythonhosted.org/packages/ab/2b/698580547a4a4988e415721b71eb45e80c879f0fb04a62da131f45987b96/bcrypt-4.3.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:afe327968aaf13fc143a56a3360cb27d4ad0345e34da12c7290f1b00b8fe9a8b", size = 279583, upload-time = "2025-02-28T01:23:38.021Z" },
- { url = "https://files.pythonhosted.org/packages/f2/87/62e1e426418204db520f955ffd06f1efd389feca893dad7095bf35612eec/bcrypt-4.3.0-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d9af79d322e735b1fc33404b5765108ae0ff232d4b54666d46730f8ac1a43676", size = 297896, upload-time = "2025-02-28T01:23:39.575Z" },
- { url = "https://files.pythonhosted.org/packages/cb/c6/8fedca4c2ada1b6e889c52d2943b2f968d3427e5d65f595620ec4c06fa2f/bcrypt-4.3.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f1e3ffa1365e8702dc48c8b360fef8d7afeca482809c5e45e653af82ccd088c1", size = 284492, upload-time = "2025-02-28T01:23:40.901Z" },
- { url = "https://files.pythonhosted.org/packages/4d/4d/c43332dcaaddb7710a8ff5269fcccba97ed3c85987ddaa808db084267b9a/bcrypt-4.3.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:3004df1b323d10021fda07a813fd33e0fd57bef0e9a480bb143877f6cba996fe", size = 279213, upload-time = "2025-02-28T01:23:42.653Z" },
- { url = "https://files.pythonhosted.org/packages/dc/7f/1e36379e169a7df3a14a1c160a49b7b918600a6008de43ff20d479e6f4b5/bcrypt-4.3.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:531457e5c839d8caea9b589a1bcfe3756b0547d7814e9ce3d437f17da75c32b0", size = 284162, upload-time = "2025-02-28T01:23:43.964Z" },
- { url = "https://files.pythonhosted.org/packages/1c/0a/644b2731194b0d7646f3210dc4d80c7fee3ecb3a1f791a6e0ae6bb8684e3/bcrypt-4.3.0-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:17a854d9a7a476a89dcef6c8bd119ad23e0f82557afbd2c442777a16408e614f", size = 312856, upload-time = "2025-02-28T01:23:46.011Z" },
- { url = "https://files.pythonhosted.org/packages/dc/62/2a871837c0bb6ab0c9a88bf54de0fc021a6a08832d4ea313ed92a669d437/bcrypt-4.3.0-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6fb1fd3ab08c0cbc6826a2e0447610c6f09e983a281b919ed721ad32236b8b23", size = 316726, upload-time = "2025-02-28T01:23:47.575Z" },
- { url = "https://files.pythonhosted.org/packages/0c/a1/9898ea3faac0b156d457fd73a3cb9c2855c6fd063e44b8522925cdd8ce46/bcrypt-4.3.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e965a9c1e9a393b8005031ff52583cedc15b7884fce7deb8b0346388837d6cfe", size = 343664, upload-time = "2025-02-28T01:23:49.059Z" },
- { url = "https://files.pythonhosted.org/packages/40/f2/71b4ed65ce38982ecdda0ff20c3ad1b15e71949c78b2c053df53629ce940/bcrypt-4.3.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:79e70b8342a33b52b55d93b3a59223a844962bef479f6a0ea318ebbcadf71505", size = 363128, upload-time = "2025-02-28T01:23:50.399Z" },
- { url = "https://files.pythonhosted.org/packages/11/99/12f6a58eca6dea4be992d6c681b7ec9410a1d9f5cf368c61437e31daa879/bcrypt-4.3.0-cp39-abi3-win32.whl", hash = "sha256:b4d4e57f0a63fd0b358eb765063ff661328f69a04494427265950c71b992a39a", size = 160598, upload-time = "2025-02-28T01:23:51.775Z" },
- { url = "https://files.pythonhosted.org/packages/a9/cf/45fb5261ece3e6b9817d3d82b2f343a505fd58674a92577923bc500bd1aa/bcrypt-4.3.0-cp39-abi3-win_amd64.whl", hash = "sha256:e53e074b120f2877a35cc6c736b8eb161377caae8925c17688bd46ba56daaa5b", size = 152799, upload-time = "2025-02-28T01:23:53.139Z" },
- { url = "https://files.pythonhosted.org/packages/4c/b1/1289e21d710496b88340369137cc4c5f6ee036401190ea116a7b4ae6d32a/bcrypt-4.3.0-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a839320bf27d474e52ef8cb16449bb2ce0ba03ca9f44daba6d93fa1d8828e48a", size = 275103, upload-time = "2025-02-28T01:24:00.764Z" },
- { url = "https://files.pythonhosted.org/packages/94/41/19be9fe17e4ffc5d10b7b67f10e459fc4eee6ffe9056a88de511920cfd8d/bcrypt-4.3.0-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:bdc6a24e754a555d7316fa4774e64c6c3997d27ed2d1964d55920c7c227bc4ce", size = 280513, upload-time = "2025-02-28T01:24:02.243Z" },
- { url = "https://files.pythonhosted.org/packages/aa/73/05687a9ef89edebdd8ad7474c16d8af685eb4591c3c38300bb6aad4f0076/bcrypt-4.3.0-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:55a935b8e9a1d2def0626c4269db3fcd26728cbff1e84f0341465c31c4ee56d8", size = 274685, upload-time = "2025-02-28T01:24:04.512Z" },
- { url = "https://files.pythonhosted.org/packages/63/13/47bba97924ebe86a62ef83dc75b7c8a881d53c535f83e2c54c4bd701e05c/bcrypt-4.3.0-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:57967b7a28d855313a963aaea51bf6df89f833db4320da458e5b3c5ab6d4c938", size = 280110, upload-time = "2025-02-28T01:24:05.896Z" },
+version = "5.0.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d4/36/3329e2518d70ad8e2e5817d5a4cac6bba05a47767ec416c7d020a965f408/bcrypt-5.0.0.tar.gz", hash = "sha256:f748f7c2d6fd375cc93d3fba7ef4a9e3a092421b8dbf34d8d4dc06be9492dfdd", size = 25386, upload-time = "2025-09-25T19:50:47.829Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/84/29/6237f151fbfe295fe3e074ecc6d44228faa1e842a81f6d34a02937ee1736/bcrypt-5.0.0-cp38-abi3-macosx_10_12_universal2.whl", hash = "sha256:fc746432b951e92b58317af8e0ca746efe93e66555f1b40888865ef5bf56446b", size = 494553, upload-time = "2025-09-25T19:49:49.006Z" },
+ { url = "https://files.pythonhosted.org/packages/45/b6/4c1205dde5e464ea3bd88e8742e19f899c16fa8916fb8510a851fae985b5/bcrypt-5.0.0-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c2388ca94ffee269b6038d48747f4ce8df0ffbea43f31abfa18ac72f0218effb", size = 275009, upload-time = "2025-09-25T19:49:50.581Z" },
+ { url = "https://files.pythonhosted.org/packages/3b/71/427945e6ead72ccffe77894b2655b695ccf14ae1866cd977e185d606dd2f/bcrypt-5.0.0-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:560ddb6ec730386e7b3b26b8b4c88197aaed924430e7b74666a586ac997249ef", size = 278029, upload-time = "2025-09-25T19:49:52.533Z" },
+ { url = "https://files.pythonhosted.org/packages/17/72/c344825e3b83c5389a369c8a8e58ffe1480b8a699f46c127c34580c4666b/bcrypt-5.0.0-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d79e5c65dcc9af213594d6f7f1fa2c98ad3fc10431e7aa53c176b441943efbdd", size = 275907, upload-time = "2025-09-25T19:49:54.709Z" },
+ { url = "https://files.pythonhosted.org/packages/0b/7e/d4e47d2df1641a36d1212e5c0514f5291e1a956a7749f1e595c07a972038/bcrypt-5.0.0-cp38-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2b732e7d388fa22d48920baa267ba5d97cca38070b69c0e2d37087b381c681fd", size = 296500, upload-time = "2025-09-25T19:49:56.013Z" },
+ { url = "https://files.pythonhosted.org/packages/0f/c3/0ae57a68be2039287ec28bc463b82e4b8dc23f9d12c0be331f4782e19108/bcrypt-5.0.0-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:0c8e093ea2532601a6f686edbc2c6b2ec24131ff5c52f7610dd64fa4553b5464", size = 278412, upload-time = "2025-09-25T19:49:57.356Z" },
+ { url = "https://files.pythonhosted.org/packages/45/2b/77424511adb11e6a99e3a00dcc7745034bee89036ad7d7e255a7e47be7d8/bcrypt-5.0.0-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:5b1589f4839a0899c146e8892efe320c0fa096568abd9b95593efac50a87cb75", size = 275486, upload-time = "2025-09-25T19:49:59.116Z" },
+ { url = "https://files.pythonhosted.org/packages/43/0a/405c753f6158e0f3f14b00b462d8bca31296f7ecfc8fc8bc7919c0c7d73a/bcrypt-5.0.0-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:89042e61b5e808b67daf24a434d89bab164d4de1746b37a8d173b6b14f3db9ff", size = 277940, upload-time = "2025-09-25T19:50:00.869Z" },
+ { url = "https://files.pythonhosted.org/packages/62/83/b3efc285d4aadc1fa83db385ec64dcfa1707e890eb42f03b127d66ac1b7b/bcrypt-5.0.0-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:e3cf5b2560c7b5a142286f69bde914494b6d8f901aaa71e453078388a50881c4", size = 310776, upload-time = "2025-09-25T19:50:02.393Z" },
+ { url = "https://files.pythonhosted.org/packages/95/7d/47ee337dacecde6d234890fe929936cb03ebc4c3a7460854bbd9c97780b8/bcrypt-5.0.0-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f632fd56fc4e61564f78b46a2269153122db34988e78b6be8b32d28507b7eaeb", size = 312922, upload-time = "2025-09-25T19:50:04.232Z" },
+ { url = "https://files.pythonhosted.org/packages/d6/3a/43d494dfb728f55f4e1cf8fd435d50c16a2d75493225b54c8d06122523c6/bcrypt-5.0.0-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:801cad5ccb6b87d1b430f183269b94c24f248dddbbc5c1f78b6ed231743e001c", size = 341367, upload-time = "2025-09-25T19:50:05.559Z" },
+ { url = "https://files.pythonhosted.org/packages/55/ab/a0727a4547e383e2e22a630e0f908113db37904f58719dc48d4622139b5c/bcrypt-5.0.0-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3cf67a804fc66fc217e6914a5635000259fbbbb12e78a99488e4d5ba445a71eb", size = 359187, upload-time = "2025-09-25T19:50:06.916Z" },
+ { url = "https://files.pythonhosted.org/packages/1b/bb/461f352fdca663524b4643d8b09e8435b4990f17fbf4fea6bc2a90aa0cc7/bcrypt-5.0.0-cp38-abi3-win32.whl", hash = "sha256:3abeb543874b2c0524ff40c57a4e14e5d3a66ff33fb423529c88f180fd756538", size = 153752, upload-time = "2025-09-25T19:50:08.515Z" },
+ { url = "https://files.pythonhosted.org/packages/41/aa/4190e60921927b7056820291f56fc57d00d04757c8b316b2d3c0d1d6da2c/bcrypt-5.0.0-cp38-abi3-win_amd64.whl", hash = "sha256:35a77ec55b541e5e583eb3436ffbbf53b0ffa1fa16ca6782279daf95d146dcd9", size = 150881, upload-time = "2025-09-25T19:50:09.742Z" },
+ { url = "https://files.pythonhosted.org/packages/54/12/cd77221719d0b39ac0b55dbd39358db1cd1246e0282e104366ebbfb8266a/bcrypt-5.0.0-cp38-abi3-win_arm64.whl", hash = "sha256:cde08734f12c6a4e28dc6755cd11d3bdfea608d93d958fffbe95a7026ebe4980", size = 144931, upload-time = "2025-09-25T19:50:11.016Z" },
+ { url = "https://files.pythonhosted.org/packages/5d/ba/2af136406e1c3839aea9ecadc2f6be2bcd1eff255bd451dd39bcf302c47a/bcrypt-5.0.0-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:0c418ca99fd47e9c59a301744d63328f17798b5947b0f791e9af3c1c499c2d0a", size = 495313, upload-time = "2025-09-25T19:50:12.309Z" },
+ { url = "https://files.pythonhosted.org/packages/ac/ee/2f4985dbad090ace5ad1f7dd8ff94477fe089b5fab2040bd784a3d5f187b/bcrypt-5.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ddb4e1500f6efdd402218ffe34d040a1196c072e07929b9820f363a1fd1f4191", size = 275290, upload-time = "2025-09-25T19:50:13.673Z" },
+ { url = "https://files.pythonhosted.org/packages/e4/6e/b77ade812672d15cf50842e167eead80ac3514f3beacac8902915417f8b7/bcrypt-5.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7aeef54b60ceddb6f30ee3db090351ecf0d40ec6e2abf41430997407a46d2254", size = 278253, upload-time = "2025-09-25T19:50:15.089Z" },
+ { url = "https://files.pythonhosted.org/packages/36/c4/ed00ed32f1040f7990dac7115f82273e3c03da1e1a1587a778d8cea496d8/bcrypt-5.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f0ce778135f60799d89c9693b9b398819d15f1921ba15fe719acb3178215a7db", size = 276084, upload-time = "2025-09-25T19:50:16.699Z" },
+ { url = "https://files.pythonhosted.org/packages/e7/c4/fa6e16145e145e87f1fa351bbd54b429354fd72145cd3d4e0c5157cf4c70/bcrypt-5.0.0-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a71f70ee269671460b37a449f5ff26982a6f2ba493b3eabdd687b4bf35f875ac", size = 297185, upload-time = "2025-09-25T19:50:18.525Z" },
+ { url = "https://files.pythonhosted.org/packages/24/b4/11f8a31d8b67cca3371e046db49baa7c0594d71eb40ac8121e2fc0888db0/bcrypt-5.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f8429e1c410b4073944f03bd778a9e066e7fad723564a52ff91841d278dfc822", size = 278656, upload-time = "2025-09-25T19:50:19.809Z" },
+ { url = "https://files.pythonhosted.org/packages/ac/31/79f11865f8078e192847d2cb526e3fa27c200933c982c5b2869720fa5fce/bcrypt-5.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:edfcdcedd0d0f05850c52ba3127b1fce70b9f89e0fe5ff16517df7e81fa3cbb8", size = 275662, upload-time = "2025-09-25T19:50:21.567Z" },
+ { url = "https://files.pythonhosted.org/packages/d4/8d/5e43d9584b3b3591a6f9b68f755a4da879a59712981ef5ad2a0ac1379f7a/bcrypt-5.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:611f0a17aa4a25a69362dcc299fda5c8a3d4f160e2abb3831041feb77393a14a", size = 278240, upload-time = "2025-09-25T19:50:23.305Z" },
+ { url = "https://files.pythonhosted.org/packages/89/48/44590e3fc158620f680a978aafe8f87a4c4320da81ed11552f0323aa9a57/bcrypt-5.0.0-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:db99dca3b1fdc3db87d7c57eac0c82281242d1eabf19dcb8a6b10eb29a2e72d1", size = 311152, upload-time = "2025-09-25T19:50:24.597Z" },
+ { url = "https://files.pythonhosted.org/packages/5f/85/e4fbfc46f14f47b0d20493669a625da5827d07e8a88ee460af6cd9768b44/bcrypt-5.0.0-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:5feebf85a9cefda32966d8171f5db7e3ba964b77fdfe31919622256f80f9cf42", size = 313284, upload-time = "2025-09-25T19:50:26.268Z" },
+ { url = "https://files.pythonhosted.org/packages/25/ae/479f81d3f4594456a01ea2f05b132a519eff9ab5768a70430fa1132384b1/bcrypt-5.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3ca8a166b1140436e058298a34d88032ab62f15aae1c598580333dc21d27ef10", size = 341643, upload-time = "2025-09-25T19:50:28.02Z" },
+ { url = "https://files.pythonhosted.org/packages/df/d2/36a086dee1473b14276cd6ea7f61aef3b2648710b5d7f1c9e032c29b859f/bcrypt-5.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:61afc381250c3182d9078551e3ac3a41da14154fbff647ddf52a769f588c4172", size = 359698, upload-time = "2025-09-25T19:50:31.347Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/f6/688d2cd64bfd0b14d805ddb8a565e11ca1fb0fd6817175d58b10052b6d88/bcrypt-5.0.0-cp39-abi3-win32.whl", hash = "sha256:64d7ce196203e468c457c37ec22390f1a61c85c6f0b8160fd752940ccfb3a683", size = 153725, upload-time = "2025-09-25T19:50:34.384Z" },
+ { url = "https://files.pythonhosted.org/packages/9f/b9/9d9a641194a730bda138b3dfe53f584d61c58cd5230e37566e83ec2ffa0d/bcrypt-5.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:64ee8434b0da054d830fa8e89e1c8bf30061d539044a39524ff7dec90481e5c2", size = 150912, upload-time = "2025-09-25T19:50:35.69Z" },
+ { url = "https://files.pythonhosted.org/packages/27/44/d2ef5e87509158ad2187f4dd0852df80695bb1ee0cfe0a684727b01a69e0/bcrypt-5.0.0-cp39-abi3-win_arm64.whl", hash = "sha256:f2347d3534e76bf50bca5500989d6c1d05ed64b440408057a37673282c654927", size = 144953, upload-time = "2025-09-25T19:50:37.32Z" },
+ { url = "https://files.pythonhosted.org/packages/8a/75/4aa9f5a4d40d762892066ba1046000b329c7cd58e888a6db878019b282dc/bcrypt-5.0.0-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7edda91d5ab52b15636d9c30da87d2cc84f426c72b9dba7a9b4fe142ba11f534", size = 271180, upload-time = "2025-09-25T19:50:38.575Z" },
+ { url = "https://files.pythonhosted.org/packages/54/79/875f9558179573d40a9cc743038ac2bf67dfb79cecb1e8b5d70e88c94c3d/bcrypt-5.0.0-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:046ad6db88edb3c5ece4369af997938fb1c19d6a699b9c1b27b0db432faae4c4", size = 273791, upload-time = "2025-09-25T19:50:39.913Z" },
+ { url = "https://files.pythonhosted.org/packages/bc/fe/975adb8c216174bf70fc17535f75e85ac06ed5252ea077be10d9cff5ce24/bcrypt-5.0.0-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:dcd58e2b3a908b5ecc9b9df2f0085592506ac2d5110786018ee5e160f28e0911", size = 270746, upload-time = "2025-09-25T19:50:43.306Z" },
+ { url = "https://files.pythonhosted.org/packages/e4/f8/972c96f5a2b6c4b3deca57009d93e946bbdbe2241dca9806d502f29dd3ee/bcrypt-5.0.0-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:6b8f520b61e8781efee73cba14e3e8c9556ccfb375623f4f97429544734545b4", size = 273375, upload-time = "2025-09-25T19:50:45.43Z" },
]
[[package]]
@@ -417,47 +415,9 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl", hash = "sha256:5dae8d4d79b552a71cbabc7deb25dfe8ce710b17ff41711e13010ead2abfc3e5", size = 32764, upload-time = "2024-02-18T19:09:04.156Z" },
]
-[[package]]
-name = "bitarray"
-version = "3.0.0"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/85/62/dcfac53d22ef7e904ed10a8e710a36391d2d6753c34c869b51bfc5e4ad54/bitarray-3.0.0.tar.gz", hash = "sha256:a2083dc20f0d828a7cdf7a16b20dae56aab0f43dc4f347a3b3039f6577992b03", size = 126627, upload-time = "2024-10-15T21:53:33.592Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/61/41/321edc0fbf7e8c88552d5ff9ee07777d58e2078f2706c6478bc6651b1945/bitarray-3.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:44c3e78b60070389b824d5a654afa1c893df723153c81904088d4922c3cfb6ac", size = 172452, upload-time = "2024-10-15T21:49:45.77Z" },
- { url = "https://files.pythonhosted.org/packages/48/92/4c312d6d55ac30dae96749830c9f5007a914efcb591ee0828914078eec9f/bitarray-3.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:545d36332de81e4742a845a80df89530ff193213a50b4cbef937ed5a44c0e5e5", size = 123502, upload-time = "2024-10-15T21:49:46.923Z" },
- { url = "https://files.pythonhosted.org/packages/75/2c/9f3ed70ffac8e6d2b0880e132d9e5024e4ef9404a24220deca8dbd702f15/bitarray-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8a9eb510cde3fa78c2e302bece510bf5ed494ec40e6b082dec753d6e22d5d1b1", size = 121363, upload-time = "2024-10-15T21:49:48.107Z" },
- { url = "https://files.pythonhosted.org/packages/48/e0/8ec59416aaa7ca1461a0268c0fe2fbdc8d574ac41e307980f555b773d5f6/bitarray-3.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e3727ab63dfb6bde00b281934e2212bb7529ea3006c0031a556a84d2268bea5", size = 285792, upload-time = "2024-10-15T21:49:49.582Z" },
- { url = "https://files.pythonhosted.org/packages/b9/8a/fb9d76ecb44a79f02188240278574376e851d0ca81437f433c9e6481d2e5/bitarray-3.0.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2055206ed653bee0b56628f6a4d248d53e5660228d355bbec0014bdfa27050ae", size = 300848, upload-time = "2024-10-15T21:49:51.614Z" },
- { url = "https://files.pythonhosted.org/packages/63/c5/067b688553b23e99d61ecf930abf1ad5cb5f80c2ebe6f0e2fe8ecab00b3f/bitarray-3.0.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:147542299f458bdb177f798726e5f7d39ab8491de4182c3c6d9885ed275a3c2b", size = 303027, upload-time = "2024-10-15T21:49:53.419Z" },
- { url = "https://files.pythonhosted.org/packages/dc/46/25ebc667907736b2c5c84f4bd8260d9bece8b69719a33db5c3f3dcb281a5/bitarray-3.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3f761184b93092077c7f6b7dad7bd4e671c1620404a76620da7872ceb576a94", size = 286125, upload-time = "2024-10-15T21:49:54.754Z" },
- { url = "https://files.pythonhosted.org/packages/16/dd/f9a1d84965a992ff42cae5b61536e68fc944f3e31a349b690347d98fc5e0/bitarray-3.0.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e008b7b4ce6c7f7a54b250c45c28d4243cc2a3bbfd5298fa7dac92afda229842", size = 277111, upload-time = "2024-10-15T21:49:55.969Z" },
- { url = "https://files.pythonhosted.org/packages/16/5b/44f298586a09beb62ec553f9efa06c8a5356d2e230e4080c72cb2800a48f/bitarray-3.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dfea514e665af278b2e1d4deb542de1cd4f77413bee83dd15ae16175976ea8d5", size = 280941, upload-time = "2024-10-15T21:49:57.252Z" },
- { url = "https://files.pythonhosted.org/packages/28/7c/c6e157332227862727959057ba2987e6710985992b196a81f61995f21e19/bitarray-3.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:66d6134b7bb737b88f1d16478ad0927c571387f6054f4afa5557825a4c1b78e2", size = 272817, upload-time = "2024-10-15T21:49:58.443Z" },
- { url = "https://files.pythonhosted.org/packages/b7/5d/9f7aaaaf85b5247b4a69b93af60ac7dcfff5545bf544a35517618c4244a0/bitarray-3.0.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:3cd565253889940b4ec4768d24f101d9fe111cad4606fdb203ea16f9797cf9ed", size = 295830, upload-time = "2024-10-15T21:50:00.332Z" },
- { url = "https://files.pythonhosted.org/packages/14/1b/86dd50edd2e0612b092fe4caec3001a24298c9acab5e89a503f002ed3bef/bitarray-3.0.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:4800c91a14656789d2e67d9513359e23e8a534c8ee1482bb9b517a4cfc845200", size = 307592, upload-time = "2024-10-15T21:50:02.144Z" },
- { url = "https://files.pythonhosted.org/packages/d6/8f/45a1f1bcce5fd88d2f0bb2e1ebe8bbb55247edcb8e7a8ef06e4437e2b5e3/bitarray-3.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c2945e0390d1329c585c584c6b6d78be017d9c6a1288f9c92006fe907f69cc28", size = 278971, upload-time = "2024-10-15T21:50:03.591Z" },
- { url = "https://files.pythonhosted.org/packages/43/2d/948c5718fe901aa58c98cef52b8898a6bea865bea7528cff6c2bc703f9f3/bitarray-3.0.0-cp311-cp311-win32.whl", hash = "sha256:c23286abba0cb509733c6ce8f4013cd951672c332b2e184dbefbd7331cd234c8", size = 114242, upload-time = "2024-10-15T21:50:05.514Z" },
- { url = "https://files.pythonhosted.org/packages/8c/75/e921ada57bb0bcece5eb515927c031f0bc828f702b8f213639358d9df396/bitarray-3.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:ca79f02a98cbda1472449d440592a2fe2ad96fe55515a0447fa8864a38017cf8", size = 121524, upload-time = "2024-10-15T21:50:07.401Z" },
- { url = "https://files.pythonhosted.org/packages/4e/2e/2e4beb2b714dc83a9e90ac0e4bacb1a191c71125734f72962ee2a20b9cfb/bitarray-3.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:184972c96e1c7e691be60c3792ca1a51dd22b7f25d96ebea502fe3c9b554f25d", size = 172152, upload-time = "2024-10-15T21:50:08.598Z" },
- { url = "https://files.pythonhosted.org/packages/e0/1f/9ec96408c060ffc3df5ba64d2b520fd0484cb3393a96691df8f660a43b17/bitarray-3.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:787db8da5e9e29be712f7a6bce153c7bc8697ccc2c38633e347bb9c82475d5c9", size = 123319, upload-time = "2024-10-15T21:50:09.799Z" },
- { url = "https://files.pythonhosted.org/packages/80/9f/4dd05086308bfcc84ad88c663460a8ad9f5f638f9f96eb5fa08381054db6/bitarray-3.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2da91ab3633c66999c2a352f0ca9ae064f553e5fc0eca231d28e7e305b83e942", size = 121242, upload-time = "2024-10-15T21:50:11.695Z" },
- { url = "https://files.pythonhosted.org/packages/55/bb/8865b7380e9d20445bc775079f24f2279a8c0d9ee11d57c49b118d39beaf/bitarray-3.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7edb83089acbf2c86c8002b96599071931dc4ea5e1513e08306f6f7df879a48b", size = 287463, upload-time = "2024-10-15T21:50:12.957Z" },
- { url = "https://files.pythonhosted.org/packages/db/8b/779119ee438090a80cbfaa49f96e783651183ab4c25b9760fe360aa7cb31/bitarray-3.0.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:996d1b83eb904589f40974538223eaed1ab0f62be8a5105c280b9bd849e685c4", size = 301599, upload-time = "2024-10-15T21:50:14.224Z" },
- { url = "https://files.pythonhosted.org/packages/41/25/78f7ba7fa8ab428767dfb722fc1ea9aac4a9813e348023d8047d8fd32253/bitarray-3.0.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4817d73d995bd2b977d9cde6050be8d407791cf1f84c8047fa0bea88c1b815bc", size = 304837, upload-time = "2024-10-15T21:50:15.462Z" },
- { url = "https://files.pythonhosted.org/packages/f7/8d/30a448d3157b4239e635c92fc3b3789a5b87784875ca2776f65bd543d136/bitarray-3.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d47bc4ff9b0e1624d613563c6fa7b80aebe7863c56c3df5ab238bb7134e8755", size = 288588, upload-time = "2024-10-15T21:50:16.728Z" },
- { url = "https://files.pythonhosted.org/packages/86/e0/c1f1b595682244f55119d55f280b5a996bcd462b702ec220d976a7566d27/bitarray-3.0.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aca0a9cd376beaccd9f504961de83e776dd209c2de5a4c78dc87a78edf61839b", size = 279002, upload-time = "2024-10-15T21:50:17.993Z" },
- { url = "https://files.pythonhosted.org/packages/5c/4d/a17626923ad2c9d20ed1625fc5b27a8dfe2d1a3e877083e9422455ec302d/bitarray-3.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:572a61fba7e3a710a8324771322fba8488d134034d349dcd036a7aef74723a80", size = 281898, upload-time = "2024-10-15T21:50:19.599Z" },
- { url = "https://files.pythonhosted.org/packages/50/d8/5c410580a510e669d9a28bf17675e58843236c55c60fc6dc8f8747808757/bitarray-3.0.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a817ad70c1aff217530576b4f037dd9b539eb2926603354fcac605d824082ad1", size = 274622, upload-time = "2024-10-15T21:50:21.644Z" },
- { url = "https://files.pythonhosted.org/packages/e7/21/de2e8eda85c5f6a05bda75a00c22c94aee71ef09db0d5cbf22446de74312/bitarray-3.0.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:2ac67b658fa5426503e9581a3fb44a26a3b346c1abd17105735f07db572195b3", size = 296930, upload-time = "2024-10-15T21:50:24.601Z" },
- { url = "https://files.pythonhosted.org/packages/13/7b/7cfad12d77db2932fb745fa281693b0031c3dfd7f2ecf5803be688cc3798/bitarray-3.0.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:12f19ede03e685c5c588ab5ed63167999295ffab5e1126c5fe97d12c0718c18f", size = 309836, upload-time = "2024-10-15T21:50:25.953Z" },
- { url = "https://files.pythonhosted.org/packages/53/e1/5120fbb8438a0d718e063f70168a2975e03f00ce6b86e74b8eec079cb492/bitarray-3.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fcef31b062f756ba7eebcd7890c5d5de84b9d64ee877325257bcc9782288564a", size = 281535, upload-time = "2024-10-15T21:50:28.07Z" },
- { url = "https://files.pythonhosted.org/packages/73/75/8acebbbb4f85dcca73b8e91dde5d3e1e3e2317b36fae4f5b133c60720834/bitarray-3.0.0-cp312-cp312-win32.whl", hash = "sha256:656db7bdf1d81ec3b57b3cad7ec7276765964bcfd0eb81c5d1331f385298169c", size = 114423, upload-time = "2024-10-15T21:50:29.308Z" },
- { url = "https://files.pythonhosted.org/packages/ca/56/dadae4d4351b337de6e0269001fb40f3ebe9f72222190456713d2c1be53d/bitarray-3.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:f785af6b7cb07a9b1e5db0dea9ef9e3e8bb3d74874a0a61303eab9c16acc1999", size = 121680, upload-time = "2024-10-15T21:50:30.526Z" },
-]
-
[[package]]
name = "black"
-version = "25.1.0"
+version = "25.9.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "click" },
@@ -465,55 +425,47 @@ dependencies = [
{ name = "packaging" },
{ name = "pathspec" },
{ name = "platformdirs" },
+ { name = "pytokens" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/94/49/26a7b0f3f35da4b5a65f081943b7bcd22d7002f5f0fb8098ec1ff21cb6ef/black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666", size = 649449, upload-time = "2025-01-29T04:15:40.373Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/7e/4f/87f596aca05c3ce5b94b8663dbfe242a12843caaa82dd3f85f1ffdc3f177/black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0", size = 1614372, upload-time = "2025-01-29T05:37:11.71Z" },
- { url = "https://files.pythonhosted.org/packages/e7/d0/2c34c36190b741c59c901e56ab7f6e54dad8df05a6272a9747ecef7c6036/black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299", size = 1442865, upload-time = "2025-01-29T05:37:14.309Z" },
- { url = "https://files.pythonhosted.org/packages/21/d4/7518c72262468430ead45cf22bd86c883a6448b9eb43672765d69a8f1248/black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096", size = 1749699, upload-time = "2025-01-29T04:18:17.688Z" },
- { url = "https://files.pythonhosted.org/packages/58/db/4f5beb989b547f79096e035c4981ceb36ac2b552d0ac5f2620e941501c99/black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2", size = 1428028, upload-time = "2025-01-29T04:18:51.711Z" },
- { url = "https://files.pythonhosted.org/packages/83/71/3fe4741df7adf015ad8dfa082dd36c94ca86bb21f25608eb247b4afb15b2/black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b", size = 1650988, upload-time = "2025-01-29T05:37:16.707Z" },
- { url = "https://files.pythonhosted.org/packages/13/f3/89aac8a83d73937ccd39bbe8fc6ac8860c11cfa0af5b1c96d081facac844/black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc", size = 1453985, upload-time = "2025-01-29T05:37:18.273Z" },
- { url = "https://files.pythonhosted.org/packages/6f/22/b99efca33f1f3a1d2552c714b1e1b5ae92efac6c43e790ad539a163d1754/black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f", size = 1783816, upload-time = "2025-01-29T04:18:33.823Z" },
- { url = "https://files.pythonhosted.org/packages/18/7e/a27c3ad3822b6f2e0e00d63d58ff6299a99a5b3aee69fa77cd4b0076b261/black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba", size = 1440860, upload-time = "2025-01-29T04:19:12.944Z" },
- { url = "https://files.pythonhosted.org/packages/09/71/54e999902aed72baf26bca0d50781b01838251a462612966e9fc4891eadd/black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717", size = 207646, upload-time = "2025-01-29T04:15:38.082Z" },
-]
-
-[[package]]
-name = "blinker"
-version = "1.9.0"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/21/28/9b3f50ce0e048515135495f198351908d99540d69bfdc8c1d15b73dc55ce/blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf", size = 22460, upload-time = "2024-11-08T17:25:47.436Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/4b/43/20b5c90612d7bdb2bdbcceeb53d588acca3bb8f0e4c5d5c751a2c8fdd55a/black-25.9.0.tar.gz", hash = "sha256:0474bca9a0dd1b51791fcc507a4e02078a1c63f6d4e4ae5544b9848c7adfb619", size = 648393, upload-time = "2025-09-19T00:27:37.758Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc", size = 8458, upload-time = "2024-11-08T17:25:46.184Z" },
+ { url = "https://files.pythonhosted.org/packages/b7/f4/7531d4a336d2d4ac6cc101662184c8e7d068b548d35d874415ed9f4116ef/black-25.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:456386fe87bad41b806d53c062e2974615825c7a52159cde7ccaeb0695fa28fa", size = 1698727, upload-time = "2025-09-19T00:31:14.264Z" },
+ { url = "https://files.pythonhosted.org/packages/28/f9/66f26bfbbf84b949cc77a41a43e138d83b109502cd9c52dfc94070ca51f2/black-25.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a16b14a44c1af60a210d8da28e108e13e75a284bf21a9afa6b4571f96ab8bb9d", size = 1555679, upload-time = "2025-09-19T00:31:29.265Z" },
+ { url = "https://files.pythonhosted.org/packages/bf/59/61475115906052f415f518a648a9ac679d7afbc8da1c16f8fdf68a8cebed/black-25.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aaf319612536d502fdd0e88ce52d8f1352b2c0a955cc2798f79eeca9d3af0608", size = 1617453, upload-time = "2025-09-19T00:30:42.24Z" },
+ { url = "https://files.pythonhosted.org/packages/7f/5b/20fd5c884d14550c911e4fb1b0dae00d4abb60a4f3876b449c4d3a9141d5/black-25.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:c0372a93e16b3954208417bfe448e09b0de5cc721d521866cd9e0acac3c04a1f", size = 1333655, upload-time = "2025-09-19T00:30:56.715Z" },
+ { url = "https://files.pythonhosted.org/packages/fb/8e/319cfe6c82f7e2d5bfb4d3353c6cc85b523d677ff59edc61fdb9ee275234/black-25.9.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1b9dc70c21ef8b43248f1d86aedd2aaf75ae110b958a7909ad8463c4aa0880b0", size = 1742012, upload-time = "2025-09-19T00:33:08.678Z" },
+ { url = "https://files.pythonhosted.org/packages/94/cc/f562fe5d0a40cd2a4e6ae3f685e4c36e365b1f7e494af99c26ff7f28117f/black-25.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8e46eecf65a095fa62e53245ae2795c90bdecabd53b50c448d0a8bcd0d2e74c4", size = 1581421, upload-time = "2025-09-19T00:35:25.937Z" },
+ { url = "https://files.pythonhosted.org/packages/84/67/6db6dff1ebc8965fd7661498aea0da5d7301074b85bba8606a28f47ede4d/black-25.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9101ee58ddc2442199a25cb648d46ba22cd580b00ca4b44234a324e3ec7a0f7e", size = 1655619, upload-time = "2025-09-19T00:30:49.241Z" },
+ { url = "https://files.pythonhosted.org/packages/10/10/3faef9aa2a730306cf469d76f7f155a8cc1f66e74781298df0ba31f8b4c8/black-25.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:77e7060a00c5ec4b3367c55f39cf9b06e68965a4f2e61cecacd6d0d9b7ec945a", size = 1342481, upload-time = "2025-09-19T00:31:29.625Z" },
+ { url = "https://files.pythonhosted.org/packages/1b/46/863c90dcd3f9d41b109b7f19032ae0db021f0b2a81482ba0a1e28c84de86/black-25.9.0-py3-none-any.whl", hash = "sha256:474b34c1342cdc157d307b56c4c65bce916480c4a8f6551fdc6bf9b486a7c4ae", size = 203363, upload-time = "2025-09-19T00:27:35.724Z" },
]
[[package]]
name = "boto3"
-version = "1.35.53"
+version = "1.40.5"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "botocore" },
{ name = "jmespath" },
{ name = "s3transfer" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/12/c1/1dc34b322d2f022d190c34dd4aa7f1a242d73633c25061bf56bd1319fe05/boto3-1.35.53.tar.gz", hash = "sha256:f4124548bb831e13504e805f2fbbfcee06df42fffea0655862c6eb9b95d6d1be", size = 111004, upload-time = "2024-10-31T19:41:56.442Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/b8/75/45438d368f799a73d3ff4172606847d1c94c008286a5537e92711e0e00a7/boto3-1.40.5.tar.gz", hash = "sha256:7340706beffe93e3638adcd77cb266f46ba424f77623a5a6be591baa3cdbd3f3", size = 111989, upload-time = "2025-08-07T19:31:42.865Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/38/03/e76ff94253472c6aa7942b3efc726ca8e9c62fdebf884e017633258b7ba4/boto3-1.35.53-py3-none-any.whl", hash = "sha256:a9c0955df0b52b43749d81bde159343a40ea2a3537a46049336fe8193871b18e", size = 139159, upload-time = "2024-10-31T19:41:54.213Z" },
+ { url = "https://files.pythonhosted.org/packages/9f/a1/d6ab54adbe92e4ef4f38875776ff2fbd041a22a53d6a3235c5c6ccfc176f/boto3-1.40.5-py3-none-any.whl", hash = "sha256:8072f11a973709b582ef9834794721d543869cc506d029477172054dcc19c2da", size = 140061, upload-time = "2025-08-07T19:31:40.716Z" },
]
[[package]]
name = "botocore"
-version = "1.35.99"
+version = "1.40.70"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "jmespath" },
{ name = "python-dateutil" },
{ name = "urllib3" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/7c/9c/1df6deceee17c88f7170bad8325aa91452529d683486273928eecfd946d8/botocore-1.35.99.tar.gz", hash = "sha256:1eab44e969c39c5f3d9a3104a0836c24715579a455f12b3979a31d7cde51b3c3", size = 13490969, upload-time = "2025-01-14T20:20:11.419Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/35/c1/8c4c199ae1663feee579a15861e34f10b29da11ae6ea0ad7b6a847ef3823/botocore-1.40.70.tar.gz", hash = "sha256:61b1f2cecd54d1b28a081116fa113b97bf4e17da57c62ae2c2751fe4c528af1f", size = 14444592, upload-time = "2025-11-10T20:29:04.046Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/fc/dd/d87e2a145fad9e08d0ec6edcf9d71f838ccc7acdd919acc4c0d4a93515f8/botocore-1.35.99-py3-none-any.whl", hash = "sha256:b22d27b6b617fc2d7342090d6129000af2efd20174215948c0d7ae2da0fab445", size = 13293216, upload-time = "2025-01-14T20:20:06.427Z" },
+ { url = "https://files.pythonhosted.org/packages/55/d2/507fd0ee4dd574d2bdbdeac5df83f39d2cae1ffe97d4622cca6f6bab39f1/botocore-1.40.70-py3-none-any.whl", hash = "sha256:4a394ad25f5d9f1ef0bed610365744523eeb5c22de6862ab25d8c93f9f6d295c", size = 14106829, upload-time = "2025-11-10T20:29:01.101Z" },
]
[[package]]
@@ -641,15 +593,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976, upload-time = "2024-09-04T20:44:27.578Z" },
]
-[[package]]
-name = "chardet"
-version = "5.2.0"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/f3/0d/f7b6ab21ec75897ed80c17d79b15951a719226b9fababf1e40ea74d69079/chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7", size = 2069618, upload-time = "2023-08-01T19:23:02.662Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/38/6f/f5fbc992a329ee4e0f288c1fe0e2ad9485ed064cac731ed2fe47dcc38cbf/chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970", size = 199385, upload-time = "2023-08-01T19:23:00.661Z" },
-]
-
[[package]]
name = "charset-normalizer"
version = "3.4.1"
@@ -685,49 +628,28 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/0e/f6/65ecc6878a89bb1c23a086ea335ad4bf21a588990c3f535a227b9eea9108/charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85", size = 49767, upload-time = "2024-12-24T18:12:32.852Z" },
]
-[[package]]
-name = "chroma-hnswlib"
-version = "0.7.6"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "numpy" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/73/09/10d57569e399ce9cbc5eee2134996581c957f63a9addfa6ca657daf006b8/chroma_hnswlib-0.7.6.tar.gz", hash = "sha256:4dce282543039681160259d29fcde6151cc9106c6461e0485f57cdccd83059b7", size = 32256, upload-time = "2024-07-22T20:19:29.259Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/f5/af/d15fdfed2a204c0f9467ad35084fbac894c755820b203e62f5dcba2d41f1/chroma_hnswlib-0.7.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:81181d54a2b1e4727369486a631f977ffc53c5533d26e3d366dda243fb0998ca", size = 196911, upload-time = "2024-07-22T20:18:33.46Z" },
- { url = "https://files.pythonhosted.org/packages/0d/19/aa6f2139f1ff7ad23a690ebf2a511b2594ab359915d7979f76f3213e46c4/chroma_hnswlib-0.7.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4b4ab4e11f1083dd0a11ee4f0e0b183ca9f0f2ed63ededba1935b13ce2b3606f", size = 185000, upload-time = "2024-07-22T20:18:36.16Z" },
- { url = "https://files.pythonhosted.org/packages/79/b1/1b269c750e985ec7d40b9bbe7d66d0a890e420525187786718e7f6b07913/chroma_hnswlib-0.7.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53db45cd9173d95b4b0bdccb4dbff4c54a42b51420599c32267f3abbeb795170", size = 2377289, upload-time = "2024-07-22T20:18:37.761Z" },
- { url = "https://files.pythonhosted.org/packages/c7/2d/d5663e134436e5933bc63516a20b5edc08b4c1b1588b9680908a5f1afd04/chroma_hnswlib-0.7.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c093f07a010b499c00a15bc9376036ee4800d335360570b14f7fe92badcdcf9", size = 2411755, upload-time = "2024-07-22T20:18:39.949Z" },
- { url = "https://files.pythonhosted.org/packages/3e/79/1bce519cf186112d6d5ce2985392a89528c6e1e9332d680bf752694a4cdf/chroma_hnswlib-0.7.6-cp311-cp311-win_amd64.whl", hash = "sha256:0540b0ac96e47d0aa39e88ea4714358ae05d64bbe6bf33c52f316c664190a6a3", size = 151888, upload-time = "2024-07-22T20:18:45.003Z" },
- { url = "https://files.pythonhosted.org/packages/93/ac/782b8d72de1c57b64fdf5cb94711540db99a92768d93d973174c62d45eb8/chroma_hnswlib-0.7.6-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e87e9b616c281bfbe748d01705817c71211613c3b063021f7ed5e47173556cb7", size = 197804, upload-time = "2024-07-22T20:18:46.442Z" },
- { url = "https://files.pythonhosted.org/packages/32/4e/fd9ce0764228e9a98f6ff46af05e92804090b5557035968c5b4198bc7af9/chroma_hnswlib-0.7.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ec5ca25bc7b66d2ecbf14502b5729cde25f70945d22f2aaf523c2d747ea68912", size = 185421, upload-time = "2024-07-22T20:18:47.72Z" },
- { url = "https://files.pythonhosted.org/packages/d9/3d/b59a8dedebd82545d873235ef2d06f95be244dfece7ee4a1a6044f080b18/chroma_hnswlib-0.7.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:305ae491de9d5f3c51e8bd52d84fdf2545a4a2bc7af49765cda286b7bb30b1d4", size = 2389672, upload-time = "2024-07-22T20:18:49.583Z" },
- { url = "https://files.pythonhosted.org/packages/74/1e/80a033ea4466338824974a34f418e7b034a7748bf906f56466f5caa434b0/chroma_hnswlib-0.7.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:822ede968d25a2c88823ca078a58f92c9b5c4142e38c7c8b4c48178894a0a3c5", size = 2436986, upload-time = "2024-07-22T20:18:51.872Z" },
-]
-
[[package]]
name = "chromadb"
-version = "0.6.3"
+version = "1.0.20"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "bcrypt" },
{ name = "build" },
- { name = "chroma-hnswlib" },
- { name = "fastapi" },
{ name = "grpcio" },
{ name = "httpx" },
{ name = "importlib-resources" },
+ { name = "jsonschema" },
{ name = "kubernetes" },
{ name = "mmh3" },
{ name = "numpy" },
{ name = "onnxruntime" },
{ name = "opentelemetry-api" },
{ name = "opentelemetry-exporter-otlp-proto-grpc" },
- { name = "opentelemetry-instrumentation-fastapi" },
{ name = "opentelemetry-sdk" },
{ name = "orjson" },
{ name = "overrides" },
{ name = "posthog" },
+ { name = "pybase64" },
{ name = "pydantic" },
{ name = "pypika" },
{ name = "pyyaml" },
@@ -739,9 +661,13 @@ dependencies = [
{ name = "typing-extensions" },
{ name = "uvicorn", extra = ["standard"] },
]
-sdist = { url = "https://files.pythonhosted.org/packages/39/cd/f0f2de3f466ff514fb6b58271c14f6d22198402bb5b71b8d890231265946/chromadb-0.6.3.tar.gz", hash = "sha256:c8f34c0b704b9108b04491480a36d42e894a960429f87c6516027b5481d59ed3", size = 29297929, upload-time = "2025-01-14T22:20:40.184Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/e0/5d/430c4780738ed8385afb2031c619c71e4d354b435f1523fd628562d42377/chromadb-1.0.20.tar.gz", hash = "sha256:9ca88516f1eefa26e4c308ec9bdae9d209c0ba5fe1fae3f16b250e52246944db", size = 1244999, upload-time = "2025-08-18T17:03:31.195Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/28/8e/5c186c77bf749b6fe0528385e507e463f1667543328d76fd00a49e1a4e6a/chromadb-0.6.3-py3-none-any.whl", hash = "sha256:4851258489a3612b558488d98d09ae0fe0a28d5cad6bd1ba64b96fdc419dc0e5", size = 611129, upload-time = "2025-01-14T22:20:33.784Z" },
+ { url = "https://files.pythonhosted.org/packages/59/2f/d40a4aedd9298a012fb9f455a1e334fc875e12c9c667aab8a956a9dff559/chromadb-1.0.20-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:0955b9cbd0dfe23ecfd8d911254ff9e57750acbe9c5ff723e2975290092d9d29", size = 19069234, upload-time = "2025-08-18T17:03:28.714Z" },
+ { url = "https://files.pythonhosted.org/packages/6a/2e/fcc80bb635719d3cf0705be89e2510bd191d5f544d1c5e9e4392ba95cff4/chromadb-1.0.20-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:52819408a48f0209a0ce4e6655eaaa683cce03f8081f297f88699f00bc8281aa", size = 18264273, upload-time = "2025-08-18T17:03:25.614Z" },
+ { url = "https://files.pythonhosted.org/packages/4f/de/e93edfcebf863d652bb0c03c23ae5a4e9e448b6e01fdac8a8624aa7dd2a4/chromadb-1.0.20-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68dbe15270e743077d47360695e0af918d17b225011e00d491afefbee017097f", size = 18835560, upload-time = "2025-08-18T17:03:18.783Z" },
+ { url = "https://files.pythonhosted.org/packages/61/4f/c88ead80ae78c839152cca5dc6edae65b8a1da090b7220739b54c75549eb/chromadb-1.0.20-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2044e1400f67588271ebd2fa654dd5333e9ad108f800aa57a6fa09237afb6142", size = 19755334, upload-time = "2025-08-18T17:03:22.386Z" },
+ { url = "https://files.pythonhosted.org/packages/6f/81/6decbd21c67572d67707f7e168851f10404e2857897456c6ba220e9b09be/chromadb-1.0.20-cp39-abi3-win_amd64.whl", hash = "sha256:b81be370b7c34138c01a41d11304498a13598cf9b21ecde31bba932492071301", size = 19778671, upload-time = "2025-08-18T17:03:33.206Z" },
]
[[package]]
@@ -756,27 +682,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188, upload-time = "2024-12-21T18:38:41.666Z" },
]
-[[package]]
-name = "colbert-ai"
-version = "0.2.21"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "bitarray" },
- { name = "datasets" },
- { name = "flask" },
- { name = "git-python" },
- { name = "ninja" },
- { name = "python-dotenv" },
- { name = "scipy" },
- { name = "tqdm" },
- { name = "transformers" },
- { name = "ujson" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/bc/dc/7edb06e3bb01326610ecfdfc8e396c6867ba7de6e58cda2356a604419899/colbert_ai-0.2.21.tar.gz", hash = "sha256:a8d6fdb4e2272f2b08ed37f8e5096072160d8415d1e40585751898b77e625bab", size = 87978, upload-time = "2024-08-20T20:14:25.262Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/8d/9c/5d847be0f05e5266880fb1c183e642a6c34cd6a101c1d6219dfa74887543/colbert_ai-0.2.21-py3-none-any.whl", hash = "sha256:8c17e7be44e7f3989f2067f1176af4f65f4612d62850586657e8afb8314cb2a6", size = 116142, upload-time = "2024-08-20T20:14:23.32Z" },
-]
-
[[package]]
name = "colorama"
version = "0.4.6"
@@ -862,31 +767,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/c3/be/d0d44e092656fe7a06b55e6103cbce807cdbdee17884a5367c68c9860853/dataclasses_json-0.6.7-py3-none-any.whl", hash = "sha256:0dbf33f26c8d5305befd61b39d2b3414e8a407bedc2834dea9b8d642666fb40a", size = 28686, upload-time = "2024-06-09T16:20:16.715Z" },
]
-[[package]]
-name = "datasets"
-version = "3.2.0"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "aiohttp" },
- { name = "dill" },
- { name = "filelock" },
- { name = "fsspec", extra = ["http"] },
- { name = "huggingface-hub" },
- { name = "multiprocess" },
- { name = "numpy" },
- { name = "packaging" },
- { name = "pandas" },
- { name = "pyarrow" },
- { name = "pyyaml" },
- { name = "requests" },
- { name = "tqdm" },
- { name = "xxhash" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/fc/48/744286c044e2b942d4fa67f92816126522ad1f0675def0ea3264e6242005/datasets-3.2.0.tar.gz", hash = "sha256:9a6e1a356052866b5dbdd9c9eedb000bf3fc43d986e3584d9b028f4976937229", size = 558366, upload-time = "2024-12-10T16:56:38.162Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/d7/84/0df6c5981f5fc722381662ff8cfbdf8aad64bec875f75d80b55bfef394ce/datasets-3.2.0-py3-none-any.whl", hash = "sha256:f3d2ba2698b7284a4518019658596a6a8bc79f31e51516524249d6c59cf0fe2a", size = 480647, upload-time = "2024-12-10T16:56:34.742Z" },
-]
-
[[package]]
name = "ddgs"
version = "9.0.0"
@@ -922,15 +802,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/1d/8f/c7f227eb42cfeaddce3eb0c96c60cbca37797fa7b34f8e1aeadf6c5c0983/Deprecated-1.2.15-py2.py3-none-any.whl", hash = "sha256:353bc4a8ac4bfc96800ddab349d89c25dec1079f65fd53acdcc1e0b975b21320", size = 9941, upload-time = "2024-11-15T14:42:03.315Z" },
]
-[[package]]
-name = "dill"
-version = "0.3.8"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/17/4d/ac7ffa80c69ea1df30a8aa11b3578692a5118e7cd1aa157e3ef73b092d15/dill-0.3.8.tar.gz", hash = "sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca", size = 184847, upload-time = "2024-01-27T23:42:16.145Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/c9/7a/cef76fd8438a42f96db64ddaa85280485a9c395e7df3db8158cfec1eee34/dill-0.3.8-py3-none-any.whl", hash = "sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7", size = 116252, upload-time = "2024-01-27T23:42:14.239Z" },
-]
-
[[package]]
name = "distro"
version = "1.9.0"
@@ -940,49 +811,12 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" },
]
-[[package]]
-name = "dnspython"
-version = "2.7.0"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/b5/4a/263763cb2ba3816dd94b08ad3a33d5fdae34ecb856678773cc40a3605829/dnspython-2.7.0.tar.gz", hash = "sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1", size = 345197, upload-time = "2024-10-05T20:14:59.362Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/68/1b/e0a87d256e40e8c888847551b20a017a6b98139178505dc7ffb96f04e954/dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86", size = 313632, upload-time = "2024-10-05T20:14:57.687Z" },
-]
-
-[[package]]
-name = "docker"
-version = "7.1.0"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "pywin32", marker = "sys_platform == 'win32'" },
- { name = "requests" },
- { name = "urllib3" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/91/9b/4a2ea29aeba62471211598dac5d96825bb49348fa07e906ea930394a83ce/docker-7.1.0.tar.gz", hash = "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c", size = 117834, upload-time = "2024-05-23T11:13:57.216Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl", hash = "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0", size = 147774, upload-time = "2024-05-23T11:13:55.01Z" },
-]
-
[[package]]
name = "docx2txt"
version = "0.8"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/7d/7d/60ee3f2b16d9bfdfa72e8599470a2c1a5b759cb113c6fe1006be28359327/docx2txt-0.8.tar.gz", hash = "sha256:2c06d98d7cfe2d3947e5760a57d924e3ff07745b379c8737723922e7009236e5", size = 2814, upload-time = "2019-06-23T19:58:36.94Z" }
-[[package]]
-name = "duckduckgo-search"
-version = "8.0.2"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "click" },
- { name = "lxml" },
- { name = "primp" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/ad/c0/e18c2148d33a9d87f6a0cc00acba30b4e547be0f8cb85ccb313a6e8fbac7/duckduckgo_search-8.0.2.tar.gz", hash = "sha256:3109a99967b29cab8862823bbe320d140d5c792415de851b9d6288de2311b3ec", size = 21807, upload-time = "2025-05-15T08:43:25.311Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/bf/6c/e36d22e76f4aa4e1ea7ea9b443bd49b5ffd2f13d430840f47e35284f797a/duckduckgo_search-8.0.2-py3-none-any.whl", hash = "sha256:b5ff8b6b8f169b8e1b15a788a5749aa900ebcefd6e1ab485787582f8d5b4f1ef", size = 18184, upload-time = "2025-05-15T08:43:23.713Z" },
-]
-
[[package]]
name = "durationpy"
version = "0.9"
@@ -1013,33 +847,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/87/62/9773de14fe6c45c23649e98b83231fffd7b9892b6cf863251dc2afa73643/einops-0.8.1-py3-none-any.whl", hash = "sha256:919387eb55330f5757c6bea9165c5ff5cfe63a642682ea788a6d472576d81737", size = 64359, upload-time = "2025-02-09T03:17:01.998Z" },
]
-[[package]]
-name = "elastic-transport"
-version = "8.17.1"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "certifi" },
- { name = "urllib3" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/6a/54/d498a766ac8fa475f931da85a154666cc81a70f8eb4a780bc8e4e934e9ac/elastic_transport-8.17.1.tar.gz", hash = "sha256:5edef32ac864dca8e2f0a613ef63491ee8d6b8cfb52881fa7313ba9290cac6d2", size = 73425, upload-time = "2025-03-13T07:28:30.776Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/cf/cd/b71d5bc74cde7fc6fd9b2ff9389890f45d9762cbbbf81dc5e51fd7588c4a/elastic_transport-8.17.1-py3-none-any.whl", hash = "sha256:192718f498f1d10c5e9aa8b9cf32aed405e469a7f0e9d6a8923431dbb2c59fb8", size = 64969, upload-time = "2025-03-13T07:28:29.031Z" },
-]
-
-[[package]]
-name = "elasticsearch"
-version = "9.0.1"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "elastic-transport" },
- { name = "python-dateutil" },
- { name = "typing-extensions" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/39/58/0081e189ef83dd1f11cb600df842bffb8eaa05c097cb1672c5bd335b46c2/elasticsearch-9.0.1.tar.gz", hash = "sha256:76f9b519cfd15a860f615a94ba90dcb9543b721306bc5144ecc15f0b4d5d2781", size = 819519, upload-time = "2025-04-28T13:47:17.974Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/f3/eb/03140387b1a378878a4228d0d796e80298ac54fc4fe6fe9e39087d142efe/elasticsearch-9.0.1-py3-none-any.whl", hash = "sha256:9fd110f9bb77310343709d9cccbd523a431a6e528d8441b01a26b97eef3238a3", size = 905510, upload-time = "2025-04-28T13:47:13.531Z" },
-]
-
[[package]]
name = "emoji"
version = "2.14.1"
@@ -1058,15 +865,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/c1/8b/5fe2cc11fee489817272089c4203e679c63b570a5aaeb18d852ae3cbba6a/et_xmlfile-2.0.0-py3-none-any.whl", hash = "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa", size = 18059, upload-time = "2024-10-25T17:25:39.051Z" },
]
-[[package]]
-name = "eval-type-backport"
-version = "0.2.2"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/30/ea/8b0ac4469d4c347c6a385ff09dc3c048c2d021696664e26c7ee6791631b5/eval_type_backport-0.2.2.tar.gz", hash = "sha256:f0576b4cf01ebb5bd358d02314d31846af5e07678387486e2c798af0e7d849c1", size = 9079, upload-time = "2024-12-21T20:09:46.005Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/ce/31/55cd413eaccd39125368be33c46de24a1f639f2e12349b0361b4678f3915/eval_type_backport-0.2.2-py3-none-any.whl", hash = "sha256:cb6ad7c393517f476f96d456d0412ea80f0a8cf96f6892834cd9340149111b0a", size = 5830, upload-time = "2024-12-21T20:09:44.175Z" },
-]
-
[[package]]
name = "events"
version = "0.5"
@@ -1077,25 +875,25 @@ wheels = [
[[package]]
name = "fake-useragent"
-version = "2.1.0"
+version = "2.2.0"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/99/32/5b400819e6c4a71491f6a48723db8412bb057bf800d63d653b1641bd2bde/fake_useragent-2.1.0.tar.gz", hash = "sha256:cbb2cde0512ecefec1e6175e59d8bcc5cd94af25161432860769a4f3767ad62c", size = 124873, upload-time = "2025-03-12T17:25:36.882Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/41/43/948d10bf42735709edb5ae51e23297d034086f17fc7279fef385a7acb473/fake_useragent-2.2.0.tar.gz", hash = "sha256:4e6ab6571e40cc086d788523cf9e018f618d07f9050f822ff409a4dfe17c16b2", size = 158898, upload-time = "2025-04-14T15:32:19.238Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/9f/9e/1ed0964081abafb530173f68f9182a98aa2d82550cc843e1f7c844bc06e7/fake_useragent-2.1.0-py3-none-any.whl", hash = "sha256:1363d8be4934627f80a84c21cce72d33c5da650a9f1fd7398520b1edb6ecd873", size = 125764, upload-time = "2025-03-12T17:25:35.479Z" },
+ { url = "https://files.pythonhosted.org/packages/51/37/b3ea9cd5558ff4cb51957caca2193981c6b0ff30bd0d2630ac62505d99d0/fake_useragent-2.2.0-py3-none-any.whl", hash = "sha256:67f35ca4d847b0d298187443aaf020413746e56acd985a611908c73dba2daa24", size = 161695, upload-time = "2025-04-14T15:32:17.732Z" },
]
[[package]]
name = "fastapi"
-version = "0.115.7"
+version = "0.118.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pydantic" },
{ name = "starlette" },
{ name = "typing-extensions" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/a2/f5/3f921e59f189e513adb9aef826e2841672d50a399fead4e69afdeb808ff4/fastapi-0.115.7.tar.gz", hash = "sha256:0f106da6c01d88a6786b3248fb4d7a940d071f6f488488898ad5d354b25ed015", size = 293177, upload-time = "2025-01-22T22:54:27.791Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/28/3c/2b9345a6504e4055eaa490e0b41c10e338ad61d9aeaae41d97807873cdf2/fastapi-0.118.0.tar.gz", hash = "sha256:5e81654d98c4d2f53790a7d32d25a7353b30c81441be7d0958a26b5d761fa1c8", size = 310536, upload-time = "2025-09-29T03:37:23.126Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/e6/7f/bbd4dcf0faf61bc68a01939256e2ed02d681e9334c1a3cef24d5f77aba9f/fastapi-0.115.7-py3-none-any.whl", hash = "sha256:eb6a8c8bf7f26009e8147111ff15b5177a0e19bb4a45bc3486ab14804539d21e", size = 94777, upload-time = "2025-01-22T22:54:25.878Z" },
+ { url = "https://files.pythonhosted.org/packages/54/20/54e2bdaad22ca91a59455251998d43094d5c3d3567c52c7c04774b3f43f2/fastapi-0.118.0-py3-none-any.whl", hash = "sha256:705137a61e2ef71019d2445b123aa8845bd97273c395b744d5a7dfe559056855", size = 97694, upload-time = "2025-09-29T03:37:21.338Z" },
]
[[package]]
@@ -1133,38 +931,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/18/79/1b8fa1bb3568781e84c9200f951c735f3f157429f44be0495da55894d620/filetype-1.2.0-py2.py3-none-any.whl", hash = "sha256:7ce71b6880181241cf7ac8697a2f1eb6a8bd9b429f7ad6d27b8db9ba5f1c2d25", size = 19970, upload-time = "2022-11-02T17:34:01.425Z" },
]
-[[package]]
-name = "firecrawl-py"
-version = "1.12.0"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "nest-asyncio" },
- { name = "pydantic" },
- { name = "python-dotenv" },
- { name = "requests" },
- { name = "websockets" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/18/db/e4f8ef9f0475b91b7c16a15e02fe19069d443cc5516cdefa2f9a0924a9a3/firecrawl_py-1.12.0.tar.gz", hash = "sha256:bbf883f6c774f05a5426121b85978a5f7b5ab11e614aff609f0673b097c3e553", size = 19655, upload-time = "2025-02-13T15:40:15.745Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/cc/d8/301d829099082c606ed16ed2a9acd263c47a365d471b9636435bf5d858b3/firecrawl_py-1.12.0-py3-none-any.whl", hash = "sha256:2b9c549315027da32421aca2a7ca597cb05cdbb968cfe0a89f389c7bb20afa4a", size = 31854, upload-time = "2025-02-13T15:40:14.492Z" },
-]
-
-[[package]]
-name = "flask"
-version = "3.1.0"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "blinker" },
- { name = "click" },
- { name = "itsdangerous" },
- { name = "jinja2" },
- { name = "werkzeug" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/89/50/dff6380f1c7f84135484e176e0cac8690af72fa90e932ad2a0a60e28c69b/flask-3.1.0.tar.gz", hash = "sha256:5f873c5184c897c8d9d1b05df1e3d01b14910ce69607a117bd3277098a5836ac", size = 680824, upload-time = "2024-11-13T18:24:38.127Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/af/47/93213ee66ef8fae3b93b3e29206f6b251e65c97bd91d8e1c5596ef15af0a/flask-3.1.0-py3-none-any.whl", hash = "sha256:d667207822eb83f1c4b50949b1623c8fc8d51f2341d65f72e1a1815397551136", size = 102979, upload-time = "2024-11-13T18:24:36.135Z" },
-]
-
[[package]]
name = "flatbuffers"
version = "24.12.23"
@@ -1252,20 +1018,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/c6/c8/a5be5b7550c10858fcf9b0ea054baccab474da77d37f1e828ce043a3a5d4/frozenlist-1.5.0-py3-none-any.whl", hash = "sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3", size = 11901, upload-time = "2024-10-23T09:48:28.851Z" },
]
-[[package]]
-name = "fs"
-version = "2.4.16"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "appdirs" },
- { name = "setuptools" },
- { name = "six" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/5d/a9/af5bfd5a92592c16cdae5c04f68187a309be8a146b528eac3c6e30edbad2/fs-2.4.16.tar.gz", hash = "sha256:ae97c7d51213f4b70b6a958292530289090de3a7e15841e108fbe144f069d313", size = 187441, upload-time = "2022-05-02T09:25:54.22Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/b9/5c/a3d95dc1ec6cdeb032d789b552ecc76effa3557ea9186e1566df6aac18df/fs-2.4.16-py2.py3-none-any.whl", hash = "sha256:660064febbccda264ae0b6bace80a8d1be9e089e0a5eb2427b7d517f9a91545c", size = 135261, upload-time = "2022-05-02T09:25:52.363Z" },
-]
-
[[package]]
name = "fsspec"
version = "2024.9.0"
@@ -1275,11 +1027,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/1d/a0/6aaea0c2fbea2f89bfd5db25fb1e3481896a423002ebe4e55288907a97a3/fsspec-2024.9.0-py3-none-any.whl", hash = "sha256:a0947d552d8a6efa72cc2c730b12c41d043509156966cca4fb157b0f2a0c574b", size = 179253, upload-time = "2024-09-04T15:06:55.908Z" },
]
-[package.optional-dependencies]
-http = [
- { name = "aiohttp" },
-]
-
[[package]]
name = "ftfy"
version = "6.2.3"
@@ -1292,55 +1039,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/ed/46/14d230ad057048aea7ccd2f96a80905830866d281ea90a6662a825490659/ftfy-6.2.3-py3-none-any.whl", hash = "sha256:f15761b023f3061a66207d33f0c0149ad40a8319fd16da91796363e2c049fdf8", size = 43011, upload-time = "2024-08-06T01:30:44.955Z" },
]
-[[package]]
-name = "gcp-storage-emulator"
-version = "2024.8.3"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "fs" },
- { name = "google-crc32c" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/17/c2/a0b0e1e54fdd9453603d90939faf652e2488b617c8752edc4ebcd89f1686/gcp_storage_emulator-2024.8.3.tar.gz", hash = "sha256:e5d45e5c23a0344c1c4c44b8f8c36f7e8975ca1fcc5134cab608b96ddccd9225", size = 24928, upload-time = "2024-08-03T19:13:58.073Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/53/bf/b6c717bd7a5b59244388057d36789e72c28bfaa5e51f3a494563a4e3028e/gcp_storage_emulator-2024.8.3-py3-none-any.whl", hash = "sha256:1dc4ea56a0caf50fc6092898b9461d08b494824bfbbcca168e2af5da89c053ce", size = 19385, upload-time = "2024-08-03T19:13:56.296Z" },
-]
-
-[[package]]
-name = "git-python"
-version = "1.0.3"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "gitpython" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/5b/3c/f0726fd577517ff8f09e6fe49f153ec9c595f1964c02c209c757d473780a/git-python-1.0.3.zip", hash = "sha256:a7f51d07c7a0b0a15cb4dfa78601196dd20624211153d07c092b811edb6e86fb", size = 4286, upload-time = "2019-10-13T10:30:24.257Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/8a/de/0cc6353a45cdb1e137cffac5383097b300cc578e2e1133eeb847e23a1394/git_python-1.0.3-py2.py3-none-any.whl", hash = "sha256:8820ce93786cd11a76d44c7153708588e8056213e4c512406ea3732871aa9ad6", size = 1888, upload-time = "2019-10-13T10:30:22.489Z" },
-]
-
-[[package]]
-name = "gitdb"
-version = "4.0.12"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "smmap" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/72/94/63b0fc47eb32792c7ba1fe1b694daec9a63620db1e313033d18140c2320a/gitdb-4.0.12.tar.gz", hash = "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571", size = 394684, upload-time = "2025-01-02T07:20:46.413Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl", hash = "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf", size = 62794, upload-time = "2025-01-02T07:20:43.624Z" },
-]
-
-[[package]]
-name = "gitpython"
-version = "3.1.44"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "gitdb" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/c0/89/37df0b71473153574a5cdef8f242de422a0f5d26d7a9e231e6f169b4ad14/gitpython-3.1.44.tar.gz", hash = "sha256:c87e30b26253bf5418b01b0660f818967f3c503193838337fe5e573331249269", size = 214196, upload-time = "2025-01-02T07:32:43.59Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/1d/9a/4114a9057db2f1462d5c8f8390ab7383925fe1ac012eaa42402ad65c2963/GitPython-3.1.44-py3-none-any.whl", hash = "sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110", size = 207599, upload-time = "2025-01-02T07:32:40.731Z" },
-]
-
[[package]]
name = "google-ai-generativelanguage"
version = "0.6.15"
@@ -1484,7 +1182,7 @@ wheels = [
[[package]]
name = "google-genai"
-version = "1.15.0"
+version = "1.38.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@@ -1492,12 +1190,13 @@ dependencies = [
{ name = "httpx" },
{ name = "pydantic" },
{ name = "requests" },
+ { name = "tenacity" },
{ name = "typing-extensions" },
{ name = "websockets" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/f4/19/da5a085ce419c33b9e6ae308005efad9bfa1b10f59f449d075bba1f16a64/google_genai-1.15.0.tar.gz", hash = "sha256:118bb26960d6343cd64f1aeb5c2b02144a36ad06716d0d1eb1fa3e0904db51f1", size = 173452, upload-time = "2025-05-13T13:55:17.73Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/b4/11/108ddd3aca8af6a9e2369e59b9646a3a4c64aefb39d154f6467ab8d79f34/google_genai-1.38.0.tar.gz", hash = "sha256:363272fc4f677d0be6a1aed7ebabe8adf45e1626a7011a7886a587e9464ca9ec", size = 244903, upload-time = "2025-09-16T23:25:42.577Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/6f/e2/acc99d36fd439fb2e558c7aebd049329dbfc08a094faf17d847d393e2810/google_genai-1.15.0-py3-none-any.whl", hash = "sha256:6d7f149cc735038b680722bed495004720514c234e2a445ab2f27967955071dd", size = 171278, upload-time = "2025-05-13T13:55:16.314Z" },
+ { url = "https://files.pythonhosted.org/packages/53/6c/1de711bab3c118284904c3bedf870519e8c63a7a8e0905ac3833f1db9cbc/google_genai-1.38.0-py3-none-any.whl", hash = "sha256:95407425132d42b3fa11bc92b3f5cf61a0fbd8d9add1f0e89aac52c46fbba090", size = 245558, upload-time = "2025-09-16T23:25:41.141Z" },
]
[[package]]
@@ -1532,14 +1231,14 @@ wheels = [
[[package]]
name = "googleapis-common-protos"
-version = "1.63.2"
+version = "1.70.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "protobuf" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/0b/1a/41723ae380fa9c561cbe7b61c4eef9091d5fe95486465ccfc84845877331/googleapis-common-protos-1.63.2.tar.gz", hash = "sha256:27c5abdffc4911f28101e635de1533fb4cfd2c37fbaa9174587c799fac90aa87", size = 112890, upload-time = "2024-06-24T16:51:33.669Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/39/24/33db22342cf4a2ea27c9955e6713140fedd51e8b141b5ce5260897020f1a/googleapis_common_protos-1.70.0.tar.gz", hash = "sha256:0e1b44e0ea153e6594f9f394fef15193a68aaaea2d843f83e2742717ca753257", size = 145903, upload-time = "2025-04-14T10:17:02.924Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/02/48/87422ff1bddcae677fb6f58c97f5cfc613304a5e8ce2c3662760199c0a84/googleapis_common_protos-1.63.2-py2.py3-none-any.whl", hash = "sha256:27a2499c7e8aff199665b22741997e485eccc8645aa9176c7c988e6fae507945", size = 220001, upload-time = "2024-06-24T16:51:31.399Z" },
+ { url = "https://files.pythonhosted.org/packages/86/f1/62a193f0227cf15a920390abe675f386dec35f7ae3ffe6da582d3ade42c7/googleapis_common_protos-1.70.0-py3-none-any.whl", hash = "sha256:b8bfcca8c25a2bb253e0e0b0adaf8c00773e5e6af6fd92397576680b807e0fd8", size = 294530, upload-time = "2025-04-14T10:17:01.271Z" },
]
[[package]]
@@ -1570,28 +1269,30 @@ wheels = [
[[package]]
name = "grpcio"
-version = "1.67.1"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/20/53/d9282a66a5db45981499190b77790570617a604a38f3d103d0400974aeb5/grpcio-1.67.1.tar.gz", hash = "sha256:3dc2ed4cabea4dc14d5e708c2b426205956077cc5de419b4d4079315017e9732", size = 12580022, upload-time = "2024-10-29T06:30:07.787Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/59/2c/b60d6ea1f63a20a8d09c6db95c4f9a16497913fb3048ce0990ed81aeeca0/grpcio-1.67.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:7818c0454027ae3384235a65210bbf5464bd715450e30a3d40385453a85a70cb", size = 5119075, upload-time = "2024-10-29T06:24:04.696Z" },
- { url = "https://files.pythonhosted.org/packages/b3/9a/e1956f7ca582a22dd1f17b9e26fcb8229051b0ce6d33b47227824772feec/grpcio-1.67.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ea33986b70f83844cd00814cee4451055cd8cab36f00ac64a31f5bb09b31919e", size = 11009159, upload-time = "2024-10-29T06:24:07.781Z" },
- { url = "https://files.pythonhosted.org/packages/43/a8/35fbbba580c4adb1d40d12e244cf9f7c74a379073c0a0ca9d1b5338675a1/grpcio-1.67.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:c7a01337407dd89005527623a4a72c5c8e2894d22bead0895306b23c6695698f", size = 5629476, upload-time = "2024-10-29T06:24:11.444Z" },
- { url = "https://files.pythonhosted.org/packages/77/c9/864d336e167263d14dfccb4dbfa7fce634d45775609895287189a03f1fc3/grpcio-1.67.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:80b866f73224b0634f4312a4674c1be21b2b4afa73cb20953cbbb73a6b36c3cc", size = 6239901, upload-time = "2024-10-29T06:24:14.2Z" },
- { url = "https://files.pythonhosted.org/packages/f7/1e/0011408ebabf9bd69f4f87cc1515cbfe2094e5a32316f8714a75fd8ddfcb/grpcio-1.67.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9fff78ba10d4250bfc07a01bd6254a6d87dc67f9627adece85c0b2ed754fa96", size = 5881010, upload-time = "2024-10-29T06:24:17.451Z" },
- { url = "https://files.pythonhosted.org/packages/b4/7d/fbca85ee9123fb296d4eff8df566f458d738186d0067dec6f0aa2fd79d71/grpcio-1.67.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8a23cbcc5bb11ea7dc6163078be36c065db68d915c24f5faa4f872c573bb400f", size = 6580706, upload-time = "2024-10-29T06:24:20.038Z" },
- { url = "https://files.pythonhosted.org/packages/75/7a/766149dcfa2dfa81835bf7df623944c1f636a15fcb9b6138ebe29baf0bc6/grpcio-1.67.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1a65b503d008f066e994f34f456e0647e5ceb34cfcec5ad180b1b44020ad4970", size = 6161799, upload-time = "2024-10-29T06:24:22.604Z" },
- { url = "https://files.pythonhosted.org/packages/09/13/5b75ae88810aaea19e846f5380611837de411181df51fd7a7d10cb178dcb/grpcio-1.67.1-cp311-cp311-win32.whl", hash = "sha256:e29ca27bec8e163dca0c98084040edec3bc49afd10f18b412f483cc68c712744", size = 3616330, upload-time = "2024-10-29T06:24:25.775Z" },
- { url = "https://files.pythonhosted.org/packages/aa/39/38117259613f68f072778c9638a61579c0cfa5678c2558706b10dd1d11d3/grpcio-1.67.1-cp311-cp311-win_amd64.whl", hash = "sha256:786a5b18544622bfb1e25cc08402bd44ea83edfb04b93798d85dca4d1a0b5be5", size = 4354535, upload-time = "2024-10-29T06:24:28.614Z" },
- { url = "https://files.pythonhosted.org/packages/6e/25/6f95bd18d5f506364379eabc0d5874873cc7dbdaf0757df8d1e82bc07a88/grpcio-1.67.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:267d1745894200e4c604958da5f856da6293f063327cb049a51fe67348e4f953", size = 5089809, upload-time = "2024-10-29T06:24:31.24Z" },
- { url = "https://files.pythonhosted.org/packages/10/3f/d79e32e5d0354be33a12db2267c66d3cfeff700dd5ccdd09fd44a3ff4fb6/grpcio-1.67.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:85f69fdc1d28ce7cff8de3f9c67db2b0ca9ba4449644488c1e0303c146135ddb", size = 10981985, upload-time = "2024-10-29T06:24:34.942Z" },
- { url = "https://files.pythonhosted.org/packages/21/f2/36fbc14b3542e3a1c20fb98bd60c4732c55a44e374a4eb68f91f28f14aab/grpcio-1.67.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:f26b0b547eb8d00e195274cdfc63ce64c8fc2d3e2d00b12bf468ece41a0423a0", size = 5588770, upload-time = "2024-10-29T06:24:38.145Z" },
- { url = "https://files.pythonhosted.org/packages/0d/af/bbc1305df60c4e65de8c12820a942b5e37f9cf684ef5e49a63fbb1476a73/grpcio-1.67.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4422581cdc628f77302270ff839a44f4c24fdc57887dc2a45b7e53d8fc2376af", size = 6214476, upload-time = "2024-10-29T06:24:41.006Z" },
- { url = "https://files.pythonhosted.org/packages/92/cf/1d4c3e93efa93223e06a5c83ac27e32935f998bc368e276ef858b8883154/grpcio-1.67.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d7616d2ded471231c701489190379e0c311ee0a6c756f3c03e6a62b95a7146e", size = 5850129, upload-time = "2024-10-29T06:24:43.553Z" },
- { url = "https://files.pythonhosted.org/packages/ae/ca/26195b66cb253ac4d5ef59846e354d335c9581dba891624011da0e95d67b/grpcio-1.67.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8a00efecde9d6fcc3ab00c13f816313c040a28450e5e25739c24f432fc6d3c75", size = 6568489, upload-time = "2024-10-29T06:24:46.453Z" },
- { url = "https://files.pythonhosted.org/packages/d1/94/16550ad6b3f13b96f0856ee5dfc2554efac28539ee84a51d7b14526da985/grpcio-1.67.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:699e964923b70f3101393710793289e42845791ea07565654ada0969522d0a38", size = 6149369, upload-time = "2024-10-29T06:24:49.112Z" },
- { url = "https://files.pythonhosted.org/packages/33/0d/4c3b2587e8ad7f121b597329e6c2620374fccbc2e4e1aa3c73ccc670fde4/grpcio-1.67.1-cp312-cp312-win32.whl", hash = "sha256:4e7b904484a634a0fff132958dabdb10d63e0927398273917da3ee103e8d1f78", size = 3599176, upload-time = "2024-10-29T06:24:51.443Z" },
- { url = "https://files.pythonhosted.org/packages/7d/36/0c03e2d80db69e2472cf81c6123aa7d14741de7cf790117291a703ae6ae1/grpcio-1.67.1-cp312-cp312-win_amd64.whl", hash = "sha256:5721e66a594a6c4204458004852719b38f3d5522082be9061d6510b455c90afc", size = 4346574, upload-time = "2024-10-29T06:24:54.587Z" },
+version = "1.74.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/38/b4/35feb8f7cab7239c5b94bd2db71abb3d6adb5f335ad8f131abb6060840b6/grpcio-1.74.0.tar.gz", hash = "sha256:80d1f4fbb35b0742d3e3d3bb654b7381cd5f015f8497279a1e9c21ba623e01b1", size = 12756048, upload-time = "2025-07-24T18:54:23.039Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e7/77/b2f06db9f240a5abeddd23a0e49eae2b6ac54d85f0e5267784ce02269c3b/grpcio-1.74.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:69e1a8180868a2576f02356565f16635b99088da7df3d45aaa7e24e73a054e31", size = 5487368, upload-time = "2025-07-24T18:53:03.548Z" },
+ { url = "https://files.pythonhosted.org/packages/48/99/0ac8678a819c28d9a370a663007581744a9f2a844e32f0fa95e1ddda5b9e/grpcio-1.74.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:8efe72fde5500f47aca1ef59495cb59c885afe04ac89dd11d810f2de87d935d4", size = 10999804, upload-time = "2025-07-24T18:53:05.095Z" },
+ { url = "https://files.pythonhosted.org/packages/45/c6/a2d586300d9e14ad72e8dc211c7aecb45fe9846a51e558c5bca0c9102c7f/grpcio-1.74.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:a8f0302f9ac4e9923f98d8e243939a6fb627cd048f5cd38595c97e38020dffce", size = 5987667, upload-time = "2025-07-24T18:53:07.157Z" },
+ { url = "https://files.pythonhosted.org/packages/c9/57/5f338bf56a7f22584e68d669632e521f0de460bb3749d54533fc3d0fca4f/grpcio-1.74.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f609a39f62a6f6f05c7512746798282546358a37ea93c1fcbadf8b2fed162e3", size = 6655612, upload-time = "2025-07-24T18:53:09.244Z" },
+ { url = "https://files.pythonhosted.org/packages/82/ea/a4820c4c44c8b35b1903a6c72a5bdccec92d0840cf5c858c498c66786ba5/grpcio-1.74.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c98e0b7434a7fa4e3e63f250456eaef52499fba5ae661c58cc5b5477d11e7182", size = 6219544, upload-time = "2025-07-24T18:53:11.221Z" },
+ { url = "https://files.pythonhosted.org/packages/a4/17/0537630a921365928f5abb6d14c79ba4dcb3e662e0dbeede8af4138d9dcf/grpcio-1.74.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:662456c4513e298db6d7bd9c3b8df6f75f8752f0ba01fb653e252ed4a59b5a5d", size = 6334863, upload-time = "2025-07-24T18:53:12.925Z" },
+ { url = "https://files.pythonhosted.org/packages/e2/a6/85ca6cb9af3f13e1320d0a806658dca432ff88149d5972df1f7b51e87127/grpcio-1.74.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3d14e3c4d65e19d8430a4e28ceb71ace4728776fd6c3ce34016947474479683f", size = 7019320, upload-time = "2025-07-24T18:53:15.002Z" },
+ { url = "https://files.pythonhosted.org/packages/4f/a7/fe2beab970a1e25d2eff108b3cf4f7d9a53c185106377a3d1989216eba45/grpcio-1.74.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1bf949792cee20d2078323a9b02bacbbae002b9e3b9e2433f2741c15bdeba1c4", size = 6514228, upload-time = "2025-07-24T18:53:16.999Z" },
+ { url = "https://files.pythonhosted.org/packages/6a/c2/2f9c945c8a248cebc3ccda1b7a1bf1775b9d7d59e444dbb18c0014e23da6/grpcio-1.74.0-cp311-cp311-win32.whl", hash = "sha256:55b453812fa7c7ce2f5c88be3018fb4a490519b6ce80788d5913f3f9d7da8c7b", size = 3817216, upload-time = "2025-07-24T18:53:20.564Z" },
+ { url = "https://files.pythonhosted.org/packages/ff/d1/a9cf9c94b55becda2199299a12b9feef0c79946b0d9d34c989de6d12d05d/grpcio-1.74.0-cp311-cp311-win_amd64.whl", hash = "sha256:86ad489db097141a907c559988c29718719aa3e13370d40e20506f11b4de0d11", size = 4495380, upload-time = "2025-07-24T18:53:22.058Z" },
+ { url = "https://files.pythonhosted.org/packages/4c/5d/e504d5d5c4469823504f65687d6c8fb97b7f7bf0b34873b7598f1df24630/grpcio-1.74.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:8533e6e9c5bd630ca98062e3a1326249e6ada07d05acf191a77bc33f8948f3d8", size = 5445551, upload-time = "2025-07-24T18:53:23.641Z" },
+ { url = "https://files.pythonhosted.org/packages/43/01/730e37056f96f2f6ce9f17999af1556df62ee8dab7fa48bceeaab5fd3008/grpcio-1.74.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:2918948864fec2a11721d91568effffbe0a02b23ecd57f281391d986847982f6", size = 10979810, upload-time = "2025-07-24T18:53:25.349Z" },
+ { url = "https://files.pythonhosted.org/packages/79/3d/09fd100473ea5c47083889ca47ffd356576173ec134312f6aa0e13111dee/grpcio-1.74.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:60d2d48b0580e70d2e1954d0d19fa3c2e60dd7cbed826aca104fff518310d1c5", size = 5941946, upload-time = "2025-07-24T18:53:27.387Z" },
+ { url = "https://files.pythonhosted.org/packages/8a/99/12d2cca0a63c874c6d3d195629dcd85cdf5d6f98a30d8db44271f8a97b93/grpcio-1.74.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3601274bc0523f6dc07666c0e01682c94472402ac2fd1226fd96e079863bfa49", size = 6621763, upload-time = "2025-07-24T18:53:29.193Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/2c/930b0e7a2f1029bbc193443c7bc4dc2a46fedb0203c8793dcd97081f1520/grpcio-1.74.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:176d60a5168d7948539def20b2a3adcce67d72454d9ae05969a2e73f3a0feee7", size = 6180664, upload-time = "2025-07-24T18:53:30.823Z" },
+ { url = "https://files.pythonhosted.org/packages/db/d5/ff8a2442180ad0867717e670f5ec42bfd8d38b92158ad6bcd864e6d4b1ed/grpcio-1.74.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e759f9e8bc908aaae0412642afe5416c9f983a80499448fcc7fab8692ae044c3", size = 6301083, upload-time = "2025-07-24T18:53:32.454Z" },
+ { url = "https://files.pythonhosted.org/packages/b0/ba/b361d390451a37ca118e4ec7dccec690422e05bc85fba2ec72b06cefec9f/grpcio-1.74.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9e7c4389771855a92934b2846bd807fc25a3dfa820fd912fe6bd8136026b2707", size = 6994132, upload-time = "2025-07-24T18:53:34.506Z" },
+ { url = "https://files.pythonhosted.org/packages/3b/0c/3a5fa47d2437a44ced74141795ac0251bbddeae74bf81df3447edd767d27/grpcio-1.74.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cce634b10aeab37010449124814b05a62fb5f18928ca878f1bf4750d1f0c815b", size = 6489616, upload-time = "2025-07-24T18:53:36.217Z" },
+ { url = "https://files.pythonhosted.org/packages/ae/95/ab64703b436d99dc5217228babc76047d60e9ad14df129e307b5fec81fd0/grpcio-1.74.0-cp312-cp312-win32.whl", hash = "sha256:885912559974df35d92219e2dc98f51a16a48395f37b92865ad45186f294096c", size = 3807083, upload-time = "2025-07-24T18:53:37.911Z" },
+ { url = "https://files.pythonhosted.org/packages/84/59/900aa2445891fc47a33f7d2f76e00ca5d6ae6584b20d19af9c06fa09bf9a/grpcio-1.74.0-cp312-cp312-win_amd64.whl", hash = "sha256:42f8fee287427b94be63d916c90399ed310ed10aadbf9e2e5538b3e497d269bc", size = 4490123, upload-time = "2025-07-24T18:53:39.528Z" },
]
[[package]]
@@ -1608,35 +1309,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/90/40/972271de05f9315c0d69f9f7ebbcadd83bc85322f538637d11bb8c67803d/grpcio_status-1.62.3-py3-none-any.whl", hash = "sha256:f9049b762ba8de6b1086789d8315846e094edac2c50beaf462338b301a8fd4b8", size = 14448, upload-time = "2024-08-06T00:30:15.702Z" },
]
-[[package]]
-name = "grpcio-tools"
-version = "1.62.3"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "grpcio" },
- { name = "protobuf" },
- { name = "setuptools" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/54/fa/b69bd8040eafc09b88bb0ec0fea59e8aacd1a801e688af087cead213b0d0/grpcio-tools-1.62.3.tar.gz", hash = "sha256:7c7136015c3d62c3eef493efabaf9e3380e3e66d24ee8e94c01cb71377f57833", size = 4538520, upload-time = "2024-08-06T00:37:11.035Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/23/52/2dfe0a46b63f5ebcd976570aa5fc62f793d5a8b169e211c6a5aede72b7ae/grpcio_tools-1.62.3-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:703f46e0012af83a36082b5f30341113474ed0d91e36640da713355cd0ea5d23", size = 5147623, upload-time = "2024-08-06T00:30:54.894Z" },
- { url = "https://files.pythonhosted.org/packages/f0/2e/29fdc6c034e058482e054b4a3c2432f84ff2e2765c1342d4f0aa8a5c5b9a/grpcio_tools-1.62.3-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:7cc83023acd8bc72cf74c2edbe85b52098501d5b74d8377bfa06f3e929803492", size = 2719538, upload-time = "2024-08-06T00:30:57.928Z" },
- { url = "https://files.pythonhosted.org/packages/f9/60/abe5deba32d9ec2c76cdf1a2f34e404c50787074a2fee6169568986273f1/grpcio_tools-1.62.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ff7d58a45b75df67d25f8f144936a3e44aabd91afec833ee06826bd02b7fbe7", size = 3070964, upload-time = "2024-08-06T00:31:00.267Z" },
- { url = "https://files.pythonhosted.org/packages/bc/ad/e2b066684c75f8d9a48508cde080a3a36618064b9cadac16d019ca511444/grpcio_tools-1.62.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f2483ea232bd72d98a6dc6d7aefd97e5bc80b15cd909b9e356d6f3e326b6e43", size = 2805003, upload-time = "2024-08-06T00:31:02.565Z" },
- { url = "https://files.pythonhosted.org/packages/9c/3f/59bf7af786eae3f9d24ee05ce75318b87f541d0950190ecb5ffb776a1a58/grpcio_tools-1.62.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:962c84b4da0f3b14b3cdb10bc3837ebc5f136b67d919aea8d7bb3fd3df39528a", size = 3685154, upload-time = "2024-08-06T00:31:05.339Z" },
- { url = "https://files.pythonhosted.org/packages/f1/79/4dd62478b91e27084c67b35a2316ce8a967bd8b6cb8d6ed6c86c3a0df7cb/grpcio_tools-1.62.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8ad0473af5544f89fc5a1ece8676dd03bdf160fb3230f967e05d0f4bf89620e3", size = 3297942, upload-time = "2024-08-06T00:31:08.456Z" },
- { url = "https://files.pythonhosted.org/packages/b8/cb/86449ecc58bea056b52c0b891f26977afc8c4464d88c738f9648da941a75/grpcio_tools-1.62.3-cp311-cp311-win32.whl", hash = "sha256:db3bc9fa39afc5e4e2767da4459df82b095ef0cab2f257707be06c44a1c2c3e5", size = 910231, upload-time = "2024-08-06T00:31:11.464Z" },
- { url = "https://files.pythonhosted.org/packages/45/a4/9736215e3945c30ab6843280b0c6e1bff502910156ea2414cd77fbf1738c/grpcio_tools-1.62.3-cp311-cp311-win_amd64.whl", hash = "sha256:e0898d412a434e768a0c7e365acabe13ff1558b767e400936e26b5b6ed1ee51f", size = 1052496, upload-time = "2024-08-06T00:31:13.665Z" },
- { url = "https://files.pythonhosted.org/packages/2a/a5/d6887eba415ce318ae5005e8dfac3fa74892400b54b6d37b79e8b4f14f5e/grpcio_tools-1.62.3-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:d102b9b21c4e1e40af9a2ab3c6d41afba6bd29c0aa50ca013bf85c99cdc44ac5", size = 5147690, upload-time = "2024-08-06T00:31:16.436Z" },
- { url = "https://files.pythonhosted.org/packages/8a/7c/3cde447a045e83ceb4b570af8afe67ffc86896a2fe7f59594dc8e5d0a645/grpcio_tools-1.62.3-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:0a52cc9444df978438b8d2332c0ca99000521895229934a59f94f37ed896b133", size = 2720538, upload-time = "2024-08-06T00:31:18.905Z" },
- { url = "https://files.pythonhosted.org/packages/88/07/f83f2750d44ac4f06c07c37395b9c1383ef5c994745f73c6bfaf767f0944/grpcio_tools-1.62.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141d028bf5762d4a97f981c501da873589df3f7e02f4c1260e1921e565b376fa", size = 3071571, upload-time = "2024-08-06T00:31:21.684Z" },
- { url = "https://files.pythonhosted.org/packages/37/74/40175897deb61e54aca716bc2e8919155b48f33aafec8043dda9592d8768/grpcio_tools-1.62.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47a5c093ab256dec5714a7a345f8cc89315cb57c298b276fa244f37a0ba507f0", size = 2806207, upload-time = "2024-08-06T00:31:24.208Z" },
- { url = "https://files.pythonhosted.org/packages/ec/ee/d8de915105a217cbcb9084d684abdc032030dcd887277f2ef167372287fe/grpcio_tools-1.62.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:f6831fdec2b853c9daa3358535c55eed3694325889aa714070528cf8f92d7d6d", size = 3685815, upload-time = "2024-08-06T00:31:26.917Z" },
- { url = "https://files.pythonhosted.org/packages/fd/d9/4360a6c12be3d7521b0b8c39e5d3801d622fbb81cc2721dbd3eee31e28c8/grpcio_tools-1.62.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e02d7c1a02e3814c94ba0cfe43d93e872c758bd8fd5c2797f894d0c49b4a1dfc", size = 3298378, upload-time = "2024-08-06T00:31:30.401Z" },
- { url = "https://files.pythonhosted.org/packages/29/3b/7cdf4a9e5a3e0a35a528b48b111355cd14da601413a4f887aa99b6da468f/grpcio_tools-1.62.3-cp312-cp312-win32.whl", hash = "sha256:b881fd9505a84457e9f7e99362eeedd86497b659030cf57c6f0070df6d9c2b9b", size = 910416, upload-time = "2024-08-06T00:31:33.118Z" },
- { url = "https://files.pythonhosted.org/packages/6c/66/dd3ec249e44c1cc15e902e783747819ed41ead1336fcba72bf841f72c6e9/grpcio_tools-1.62.3-cp312-cp312-win_amd64.whl", hash = "sha256:11c625eebefd1fd40a228fc8bae385e448c7e32a6ae134e43cf13bbc23f902b7", size = 1052856, upload-time = "2024-08-06T00:31:36.519Z" },
-]
-
[[package]]
name = "h11"
version = "0.14.0"
@@ -1951,6 +1623,33 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942", size = 7595, upload-time = "2024-06-10T19:24:40.698Z" },
]
+[[package]]
+name = "jsonschema"
+version = "4.25.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "attrs" },
+ { name = "jsonschema-specifications" },
+ { name = "referencing" },
+ { name = "rpds-py" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/74/69/f7185de793a29082a9f3c7728268ffb31cb5095131a9c139a74078e27336/jsonschema-4.25.1.tar.gz", hash = "sha256:e4a9655ce0da0c0b67a085847e00a3a51449e1157f4f75e9fb5aa545e122eb85", size = 357342, upload-time = "2025-08-18T17:03:50.038Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/bf/9c/8c95d856233c1f82500c2450b8c68576b4cf1c871db3afac5c34ff84e6fd/jsonschema-4.25.1-py3-none-any.whl", hash = "sha256:3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63", size = 90040, upload-time = "2025-08-18T17:03:48.373Z" },
+]
+
+[[package]]
+name = "jsonschema-specifications"
+version = "2025.9.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "referencing" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" },
+]
+
[[package]]
name = "kubernetes"
version = "31.0.0"
@@ -1975,7 +1674,7 @@ wheels = [
[[package]]
name = "langchain"
-version = "0.3.26"
+version = "0.3.27"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "langchain-core" },
@@ -1986,14 +1685,14 @@ dependencies = [
{ name = "requests" },
{ name = "sqlalchemy" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/7f/13/a9931800ee42bbe0f8850dd540de14e80dda4945e7ee36e20b5d5964286e/langchain-0.3.26.tar.gz", hash = "sha256:8ff034ee0556d3e45eff1f1e96d0d745ced57858414dba7171c8ebdbeb5580c9", size = 10226808, upload-time = "2025-06-20T22:23:01.174Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/83/f6/f4f7f3a56626fe07e2bb330feb61254dbdf06c506e6b59a536a337da51cf/langchain-0.3.27.tar.gz", hash = "sha256:aa6f1e6274ff055d0fd36254176770f356ed0a8994297d1df47df341953cec62", size = 10233809, upload-time = "2025-07-24T14:42:32.959Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/f1/f2/c09a2e383283e3af1db669ab037ac05a45814f4b9c472c48dc24c0cef039/langchain-0.3.26-py3-none-any.whl", hash = "sha256:361bb2e61371024a8c473da9f9c55f4ee50f269c5ab43afdb2b1309cb7ac36cf", size = 1012336, upload-time = "2025-06-20T22:22:58.874Z" },
+ { url = "https://files.pythonhosted.org/packages/f6/d5/4861816a95b2f6993f1360cfb605aacb015506ee2090433a71de9cca8477/langchain-0.3.27-py3-none-any.whl", hash = "sha256:7b20c4f338826acb148d885b20a73a16e410ede9ee4f19bb02011852d5f98798", size = 1018194, upload-time = "2025-07-24T14:42:30.23Z" },
]
[[package]]
name = "langchain-community"
-version = "0.3.26"
+version = "0.3.29"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "aiohttp" },
@@ -2009,14 +1708,14 @@ dependencies = [
{ name = "sqlalchemy" },
{ name = "tenacity" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/aa/15/69940212569e7d7ac7b486fba244701448e8685f79069b73206c44e96fde/langchain_community-0.3.26.tar.gz", hash = "sha256:49f9d71dc20bc42ccecd6875d02fafef1be0e211a0b22cecbd678f5fd3719487", size = 33235791, upload-time = "2025-06-20T22:32:41.727Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/c5/71/72ddc8802d5edcd3b31bc4f0eb62cdf85c30c9b845e34cc879dab0b45679/langchain_community-0.3.29.tar.gz", hash = "sha256:1f3d37973b10458052bb3cc02dce9773a8ffbd02961698c6d395b8c8d7f9e004", size = 33238072, upload-time = "2025-08-27T15:29:14.249Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/44/8e/d3d201f648e8d09dc1072a734c4dc1f59455b91d7d162427256533bf5a87/langchain_community-0.3.26-py3-none-any.whl", hash = "sha256:b25a553ee9d44a6c02092a440da6c561a9312c7013ffc25365ac3f8694edb53a", size = 2529186, upload-time = "2025-06-20T22:32:39.738Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/3c/107819dbed0be3f7a041245bce861c8dd4883ed08040ed482d278a274f22/langchain_community-0.3.29-py3-none-any.whl", hash = "sha256:c876ec7ef40b46353af164197f4e08e157650e8a02c9fb9d49351cdc16c839fe", size = 2530803, upload-time = "2025-08-27T15:29:12.52Z" },
]
[[package]]
name = "langchain-core"
-version = "0.3.68"
+version = "0.3.79"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "jsonpatch" },
@@ -2027,21 +1726,21 @@ dependencies = [
{ name = "tenacity" },
{ name = "typing-extensions" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/23/20/f5b18a17bfbe3416177e702ab2fd230b7d168abb17be31fb48f43f0bb772/langchain_core-0.3.68.tar.gz", hash = "sha256:312e1932ac9aa2eaf111b70fdc171776fa571d1a86c1f873dcac88a094b19c6f", size = 563041, upload-time = "2025-07-03T17:02:28.704Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/c8/99/f926495f467e0f43289f12e951655d267d1eddc1136c3cf4dd907794a9a7/langchain_core-0.3.79.tar.gz", hash = "sha256:024ba54a346dd9b13fb8b2342e0c83d0111e7f26fa01f545ada23ad772b55a60", size = 580895, upload-time = "2025-10-09T21:59:08.359Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/f9/da/c89be0a272993bfcb762b2a356b9f55de507784c2755ad63caec25d183bf/langchain_core-0.3.68-py3-none-any.whl", hash = "sha256:5e5c1fbef419590537c91b8c2d86af896fbcbaf0d5ed7fdcdd77f7d8f3467ba0", size = 441405, upload-time = "2025-07-03T17:02:27.115Z" },
+ { url = "https://files.pythonhosted.org/packages/fc/71/46b0efaf3fc6ad2c2bd600aef500f1cb2b7038a4042f58905805630dd29d/langchain_core-0.3.79-py3-none-any.whl", hash = "sha256:92045bfda3e741f8018e1356f83be203ec601561c6a7becfefe85be5ddc58fdb", size = 449779, upload-time = "2025-10-09T21:59:06.493Z" },
]
[[package]]
name = "langchain-text-splitters"
-version = "0.3.8"
+version = "0.3.11"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "langchain-core" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/e7/ac/b4a25c5716bb0103b1515f1f52cc69ffb1035a5a225ee5afe3aed28bf57b/langchain_text_splitters-0.3.8.tar.gz", hash = "sha256:116d4b9f2a22dda357d0b79e30acf005c5518177971c66a9f1ab0edfdb0f912e", size = 42128, upload-time = "2025-04-04T14:03:51.521Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/11/43/dcda8fd25f0b19cb2835f2f6bb67f26ad58634f04ac2d8eae00526b0fa55/langchain_text_splitters-0.3.11.tar.gz", hash = "sha256:7a50a04ada9a133bbabb80731df7f6ddac51bc9f1b9cab7fa09304d71d38a6cc", size = 46458, upload-time = "2025-08-31T23:02:58.316Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/8b/a3/3696ff2444658053c01b6b7443e761f28bb71217d82bb89137a978c5f66f/langchain_text_splitters-0.3.8-py3-none-any.whl", hash = "sha256:e75cc0f4ae58dcf07d9f18776400cf8ade27fadd4ff6d264df6278bb302f6f02", size = 32440, upload-time = "2025-04-04T14:03:50.6Z" },
+ { url = "https://files.pythonhosted.org/packages/58/0d/41a51b40d24ff0384ec4f7ab8dd3dcea8353c05c973836b5e289f1465d4f/langchain_text_splitters-0.3.11-py3-none-any.whl", hash = "sha256:cf079131166a487f1372c8ab5d0bfaa6c0a4291733d9c43a34a16ac9bcd6a393", size = 33845, upload-time = "2025-08-31T23:02:57.195Z" },
]
[[package]]
@@ -2053,24 +1752,6 @@ dependencies = [
]
sdist = { url = "https://files.pythonhosted.org/packages/0e/72/a3add0e4eec4eb9e2569554f7c70f4a3c27712f40e3284d483e88094cc0e/langdetect-1.0.9.tar.gz", hash = "sha256:cbc1fef89f8d062739774bd51eda3da3274006b3661d199c2655f6b3f6d605a0", size = 981474, upload-time = "2021-05-07T07:54:13.562Z" }
-[[package]]
-name = "langfuse"
-version = "2.44.0"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "anyio" },
- { name = "backoff" },
- { name = "httpx" },
- { name = "idna" },
- { name = "packaging" },
- { name = "pydantic" },
- { name = "wrapt" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/a4/85/5a21a1d3be81e71f11f6d50affbb929eea3d5bbfab649bf8811bba83776f/langfuse-2.44.0.tar.gz", hash = "sha256:dfa5378ff7022ae9fe5b8b842c0365347c98f9ef2b772dcee6a93a45442de28c", size = 106834, upload-time = "2024-08-20T11:47:50.695Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/1f/54/03550a879a90ae4242542335b0883bb2d297c75f32cb58604064879a8f3b/langfuse-2.44.0-py3-none-any.whl", hash = "sha256:adb73400a6ad6d597cc95c31381c82f81face3d5fb69391181f224a26f7e8562", size = 195931, upload-time = "2024-08-20T11:47:48.623Z" },
-]
-
[[package]]
name = "langsmith"
version = "0.4.5"
@@ -2170,11 +1851,11 @@ wheels = [
[[package]]
name = "markdown"
-version = "3.7"
+version = "3.9"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/54/28/3af612670f82f4c056911fbbbb42760255801b3068c48de792d354ff4472/markdown-3.7.tar.gz", hash = "sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2", size = 357086, upload-time = "2024-08-16T15:55:17.812Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/8d/37/02347f6d6d8279247a5837082ebc26fc0d5aaeaf75aa013fcbb433c777ab/markdown-3.9.tar.gz", hash = "sha256:d2900fe1782bd33bdbbd56859defef70c2e78fc46668f8eb9df3128138f2cb6a", size = 364585, upload-time = "2025-09-04T20:25:22.885Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/3f/08/83871f3c50fc983b88547c196d11cf8c3340e37c32d2e9d6152abe2c61f7/Markdown-3.7-py3-none-any.whl", hash = "sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803", size = 106349, upload-time = "2024-08-16T15:55:16.176Z" },
+ { url = "https://files.pythonhosted.org/packages/70/ae/44c4a6a4cbb496d93c6257954260fe3a6e91b7bed2240e5dad2a717f5111/markdown-3.9-py3-none-any.whl", hash = "sha256:9f4d91ed810864ea88a6f32c07ba8bee1346c0cc1f6b1f9f6c822f2a9667d280", size = 107441, upload-time = "2025-09-04T20:25:21.784Z" },
]
[[package]]
@@ -2230,26 +1911,34 @@ wheels = [
]
[[package]]
-name = "mdurl"
-version = "0.1.2"
+name = "mcp"
+version = "1.14.1"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
+dependencies = [
+ { name = "anyio" },
+ { name = "httpx" },
+ { name = "httpx-sse" },
+ { name = "jsonschema" },
+ { name = "pydantic" },
+ { name = "pydantic-settings" },
+ { name = "python-multipart" },
+ { name = "pywin32", marker = "sys_platform == 'win32'" },
+ { name = "sse-starlette" },
+ { name = "starlette" },
+ { name = "uvicorn", marker = "sys_platform != 'emscripten'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/48/e9/242096400d702924b49f8d202c6ded7efb8841cacba826b5d2e6183aef7b/mcp-1.14.1.tar.gz", hash = "sha256:31c4406182ba15e8f30a513042719c3f0a38c615e76188ee5a736aaa89e20134", size = 454944, upload-time = "2025-09-18T13:37:19.971Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
+ { url = "https://files.pythonhosted.org/packages/8e/11/d334fbb7c2aeddd2e762b86d7a619acffae012643a5738e698f975a2a9e2/mcp-1.14.1-py3-none-any.whl", hash = "sha256:3b7a479e8e5cbf5361bdc1da8bc6d500d795dc3aff44b44077a363a7f7e945a4", size = 163809, upload-time = "2025-09-18T13:37:18.165Z" },
]
[[package]]
-name = "milvus-lite"
-version = "2.4.11"
+name = "mdurl"
+version = "0.1.2"
source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "tqdm" },
-]
+sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/85/42/6f4706066ec3251d5a3d42f7fc2bbb02deffa518e40ec63d9abdee58964b/milvus_lite-2.4.11-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:9e563ae0dca1b41bfd76b90f06b2bcc474460fe4eba142c9bab18d2747ff843b", size = 19841144, upload-time = "2024-12-31T02:16:35.679Z" },
- { url = "https://files.pythonhosted.org/packages/c9/69/eabed32162362ba460d81b5c26c6554c2ffef9427fc5d440aa74fbe675dc/milvus_lite-2.4.11-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d21472bd24eb327542817829ce7cb51878318e6173c4d62353c77421aecf98d6", size = 16872814, upload-time = "2024-12-31T08:44:42.047Z" },
- { url = "https://files.pythonhosted.org/packages/ed/85/feb5ef0d92ab4b62c20a5a91fdfc8515f1038d9947a41f5e8ba357724c28/milvus_lite-2.4.11-py3-none-manylinux2014_aarch64.whl", hash = "sha256:8e6ef27f7f84976f9fd0047b675ede746db2e0cc581c44a916ac9e71e0cef05d", size = 36006762, upload-time = "2025-01-02T11:29:11.907Z" },
- { url = "https://files.pythonhosted.org/packages/8d/c2/b294a7699ef097d7b0ab89f95f34fb0710726f12d7da912734e18c2558eb/milvus_lite-2.4.11-py3-none-manylinux2014_x86_64.whl", hash = "sha256:551f56b49fcfbb330b658b4a3c56ed29ba9b692ec201edd1f2dade7f5e39957d", size = 45177882, upload-time = "2024-12-31T02:16:47.42Z" },
+ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
]
[[package]]
@@ -2301,32 +1990,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/9a/67/7e8406a29b6c45be7af7740456f7f37025f0506ae2e05fb9009a53946860/monotonic-1.6-py2.py3-none-any.whl", hash = "sha256:68687e19a14f11f26d140dd5c86f3dba4bf5df58003000ed467e0e2a69bca96c", size = 8154, upload-time = "2021-04-09T21:58:05.122Z" },
]
-[[package]]
-name = "moto"
-version = "5.0.26"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "boto3" },
- { name = "botocore" },
- { name = "cryptography" },
- { name = "jinja2" },
- { name = "python-dateutil" },
- { name = "requests" },
- { name = "responses" },
- { name = "werkzeug" },
- { name = "xmltodict" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/8b/a9/996e9d0c8c5d6f8b044d4facfe6eb6c42feb4ab5c2a24d78f780bd942f61/moto-5.0.26.tar.gz", hash = "sha256:6829f58a670a087e7c5b63f8183c6b72d64a1444e420c212250b7326b69a9183", size = 6442983, upload-time = "2025-01-05T21:06:36.53Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/0b/dd/40c20b3bcdf335f56776e1adea5edd1b1026f3f98816944a123393f64df3/moto-5.0.26-py3-none-any.whl", hash = "sha256:803831f427ca6c0452ae4fb898d731cfc19906466a33a88cbc1076abcbfcbba7", size = 4614956, upload-time = "2025-01-05T21:06:32.282Z" },
-]
-
-[package.optional-dependencies]
-s3 = [
- { name = "py-partiql-parser" },
- { name = "pyyaml" },
-]
-
[[package]]
name = "mpmath"
version = "1.3.0"
@@ -2401,22 +2064,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/99/b7/b9e70fde2c0f0c9af4cc5277782a89b66d35948ea3369ec9f598358c3ac5/multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506", size = 10051, upload-time = "2024-09-09T23:49:36.506Z" },
]
-[[package]]
-name = "multiprocess"
-version = "0.70.16"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "dill" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/b5/ae/04f39c5d0d0def03247c2893d6f2b83c136bf3320a2154d7b8858f2ba72d/multiprocess-0.70.16.tar.gz", hash = "sha256:161af703d4652a0e1410be6abccecde4a7ddffd19341be0a7011b94aeb171ac1", size = 1772603, upload-time = "2024-01-28T18:52:34.85Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/bc/f7/7ec7fddc92e50714ea3745631f79bd9c96424cb2702632521028e57d3a36/multiprocess-0.70.16-py310-none-any.whl", hash = "sha256:c4a9944c67bd49f823687463660a2d6daae94c289adff97e0f9d696ba6371d02", size = 134824, upload-time = "2024-01-28T18:52:26.062Z" },
- { url = "https://files.pythonhosted.org/packages/50/15/b56e50e8debaf439f44befec5b2af11db85f6e0f344c3113ae0be0593a91/multiprocess-0.70.16-py311-none-any.whl", hash = "sha256:af4cabb0dac72abfb1e794fa7855c325fd2b55a10a44628a3c1ad3311c04127a", size = 143519, upload-time = "2024-01-28T18:52:28.115Z" },
- { url = "https://files.pythonhosted.org/packages/0a/7d/a988f258104dcd2ccf1ed40fdc97e26c4ac351eeaf81d76e266c52d84e2f/multiprocess-0.70.16-py312-none-any.whl", hash = "sha256:fc0544c531920dde3b00c29863377f87e1632601092ea2daca74e4beb40faa2e", size = 146741, upload-time = "2024-01-28T18:52:29.395Z" },
- { url = "https://files.pythonhosted.org/packages/ea/89/38df130f2c799090c978b366cfdf5b96d08de5b29a4a293df7f7429fa50b/multiprocess-0.70.16-py38-none-any.whl", hash = "sha256:a71d82033454891091a226dfc319d0cfa8019a4e888ef9ca910372a446de4435", size = 132628, upload-time = "2024-01-28T18:52:30.853Z" },
- { url = "https://files.pythonhosted.org/packages/da/d9/f7f9379981e39b8c2511c9e0326d212accacb82f12fbfdc1aa2ce2a7b2b6/multiprocess-0.70.16-py39-none-any.whl", hash = "sha256:a0bafd3ae1b732eac64be2e72038231c1ba97724b60b09400d68f229fcc2fbf3", size = 133351, upload-time = "2024-01-28T18:52:31.981Z" },
-]
-
[[package]]
name = "mypy-extensions"
version = "1.0.0"
@@ -2444,30 +2091,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/b9/54/dd730b32ea14ea797530a4479b2ed46a6fb250f682a9cfb997e968bf0261/networkx-3.4.2-py3-none-any.whl", hash = "sha256:df5d4365b724cf81b8c6a7312509d0c22386097011ad1abe274afd5e9d3bbc5f", size = 1723263, upload-time = "2024-10-21T12:39:36.247Z" },
]
-[[package]]
-name = "ninja"
-version = "1.11.1.3"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/bd/8f/21a2701f95b7d0d5137736561b3427ece0c4a1e085d4a223b92d16ab7d8b/ninja-1.11.1.3.tar.gz", hash = "sha256:edfa0d2e9d7ead1635b03e40a32ad56cc8f56798b6e2e9848d8300b174897076", size = 129532, upload-time = "2024-12-15T09:13:01.824Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/ea/ba/0069cd4a83d68f7b0308be70e219b15d675e50c8ea28763a3f0373c45bfc/ninja-1.11.1.3-py3-none-macosx_10_9_universal2.whl", hash = "sha256:2b4879ea3f1169f3d855182c57dcc84d1b5048628c8b7be0d702b81882a37237", size = 279132, upload-time = "2024-12-15T09:12:23.11Z" },
- { url = "https://files.pythonhosted.org/packages/72/6b/3805be87df8417a0c7b21078c8045f2a1e59b34f371bfe4cb4fb0d6df7f2/ninja-1.11.1.3-py3-none-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:bc3ebc8b2e47716149f3541742b5cd8e0b08f51013b825c05baca3e34854370d", size = 472101, upload-time = "2024-12-15T09:12:26.077Z" },
- { url = "https://files.pythonhosted.org/packages/6b/35/a8e38d54768e67324e365e2a41162be298f51ec93e6bd4b18d237d7250d8/ninja-1.11.1.3-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a27e78ca71316c8654965ee94b286a98c83877bfebe2607db96897bbfe458af0", size = 422884, upload-time = "2024-12-15T09:12:28.643Z" },
- { url = "https://files.pythonhosted.org/packages/2f/99/7996457319e139c02697fb2aa28e42fe32bb0752cef492edc69d56a3552e/ninja-1.11.1.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2883ea46b3c5079074f56820f9989c6261fcc6fd873d914ee49010ecf283c3b2", size = 157046, upload-time = "2024-12-15T09:12:31.489Z" },
- { url = "https://files.pythonhosted.org/packages/6d/8b/93f38e5cddf76ccfdab70946515b554f25d2b4c95ef9b2f9cfbc43fa7cc1/ninja-1.11.1.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c4bdb9fd2d0c06501ae15abfd23407660e95659e384acd36e013b6dd7d8a8e4", size = 180014, upload-time = "2024-12-15T09:12:32.864Z" },
- { url = "https://files.pythonhosted.org/packages/7d/1d/713884d0fa3c972164f69d552e0701d30e2bf25eba9ef160bfb3dc69926a/ninja-1.11.1.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:114ed5c61c8474df6a69ab89097a20749b769e2c219a452cb2fadc49b0d581b0", size = 157098, upload-time = "2024-12-15T09:12:35.738Z" },
- { url = "https://files.pythonhosted.org/packages/c7/22/ecb0f70e77c9e22ee250aa717a608a142756833a34d43943d7d658ee0e56/ninja-1.11.1.3-py3-none-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7fa2247fce98f683bc712562d82b22b8a0a5c000738a13147ca2d1b68c122298", size = 130089, upload-time = "2024-12-15T09:12:38.497Z" },
- { url = "https://files.pythonhosted.org/packages/ec/a6/3ee846c20ab6ad95b90c5c8703c76cb1f39cc8ce2d1ae468956e3b1b2581/ninja-1.11.1.3-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:a38c6c6c8032bed68b70c3b065d944c35e9f903342875d3a3218c1607987077c", size = 372508, upload-time = "2024-12-15T09:12:41.055Z" },
- { url = "https://files.pythonhosted.org/packages/95/0d/aa44abe4141f29148ce671ac8c92045878906b18691c6f87a29711c2ff1c/ninja-1.11.1.3-py3-none-musllinux_1_1_i686.whl", hash = "sha256:56ada5d33b8741d298836644042faddebc83ee669782d661e21563034beb5aba", size = 419369, upload-time = "2024-12-15T09:12:42.461Z" },
- { url = "https://files.pythonhosted.org/packages/f7/ec/48bf5105568ac9bd2016b701777bdd5000cc09a14ac837fef9f15e8d634e/ninja-1.11.1.3-py3-none-musllinux_1_1_ppc64le.whl", hash = "sha256:53409151da081f3c198bb0bfc220a7f4e821e022c5b7d29719adda892ddb31bb", size = 420304, upload-time = "2024-12-15T09:12:45.326Z" },
- { url = "https://files.pythonhosted.org/packages/18/e5/69df63976cf971a03379899f8520a036c9dbab26330b37197512aed5b3df/ninja-1.11.1.3-py3-none-musllinux_1_1_s390x.whl", hash = "sha256:1ad2112c2b0159ed7c4ae3731595191b1546ba62316fc40808edecd0306fefa3", size = 416056, upload-time = "2024-12-15T09:12:48.125Z" },
- { url = "https://files.pythonhosted.org/packages/6f/4f/bdb401af7ed0e24a3fef058e13a149f2de1ce4b176699076993615d55610/ninja-1.11.1.3-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:28aea3c1c280cba95b8608d50797169f3a34280e3e9a6379b6e340f0c9eaeeb0", size = 379725, upload-time = "2024-12-15T09:12:50.873Z" },
- { url = "https://files.pythonhosted.org/packages/bd/68/05e7863bf13128c61652eeb3ec7096c3d3a602f32f31752dbfb034e3fa07/ninja-1.11.1.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b6966f83064a88a51693073eea3decd47e08c3965241e09578ef7aa3a7738329", size = 434881, upload-time = "2024-12-15T09:12:54.754Z" },
- { url = "https://files.pythonhosted.org/packages/bd/ad/edc0d1efe77f29f45bbca2e1dab07ef597f61a88de6e4bccffc0aec2256c/ninja-1.11.1.3-py3-none-win32.whl", hash = "sha256:a4a3b71490557e18c010cbb26bd1ea9a0c32ee67e8f105e9731515b6e0af792e", size = 255988, upload-time = "2024-12-15T09:12:56.417Z" },
- { url = "https://files.pythonhosted.org/packages/03/93/09a9f7672b4f97438aca6217ac54212a63273f1cd3b46b731d0bb22c53e7/ninja-1.11.1.3-py3-none-win_amd64.whl", hash = "sha256:04d48d14ea7ba11951c156599ab526bdda575450797ff57c6fdf99b2554d09c7", size = 296502, upload-time = "2024-12-15T09:12:57.801Z" },
- { url = "https://files.pythonhosted.org/packages/d9/9d/0cc1e82849070ff3cbee69f326cb48a839407bcd15d8844443c30a5e7509/ninja-1.11.1.3-py3-none-win_arm64.whl", hash = "sha256:17978ad611d8ead578d83637f5ae80c2261b033db0b493a7ce94f88623f29e1b", size = 270571, upload-time = "2024-12-15T09:12:59.23Z" },
-]
-
[[package]]
name = "nltk"
version = "3.9.1"
@@ -2682,20 +2305,15 @@ dependencies = [
{ name = "black" },
{ name = "boto3" },
{ name = "chromadb" },
- { name = "colbert-ai" },
{ name = "cryptography" },
{ name = "ddgs" },
- { name = "docker" },
{ name = "docx2txt" },
{ name = "einops" },
- { name = "elasticsearch" },
{ name = "fake-useragent" },
{ name = "fastapi" },
{ name = "faster-whisper" },
- { name = "firecrawl-py" },
{ name = "fpdf2" },
{ name = "ftfy" },
- { name = "gcp-storage-emulator" },
{ name = "google-api-python-client" },
{ name = "google-auth-httplib2" },
{ name = "google-auth-oauthlib" },
@@ -2703,50 +2321,42 @@ dependencies = [
{ name = "google-genai" },
{ name = "google-generativeai" },
{ name = "googleapis-common-protos" },
+ { name = "grpcio" },
{ name = "httpx", extra = ["brotli", "cli", "http2", "socks", "zstd"] },
+ { name = "itsdangerous" },
{ name = "langchain" },
{ name = "langchain-community" },
- { name = "langfuse" },
{ name = "ldap3" },
{ name = "loguru" },
{ name = "markdown" },
- { name = "moto", extra = ["s3"] },
+ { name = "mcp" },
{ name = "nltk" },
{ name = "onnxruntime" },
{ name = "openai" },
{ name = "opencv-python-headless" },
{ name = "openpyxl" },
{ name = "opensearch-py" },
- { name = "oracledb" },
{ name = "pandas" },
- { name = "passlib", extra = ["bcrypt"] },
{ name = "peewee" },
{ name = "peewee-migrate" },
- { name = "pgvector" },
{ name = "pillow" },
- { name = "pinecone" },
- { name = "playwright" },
+ { name = "protobuf" },
{ name = "psutil" },
- { name = "psycopg2-binary" },
+ { name = "pyarrow" },
{ name = "pycrdt" },
{ name = "pydantic" },
{ name = "pydub" },
{ name = "pyjwt", extra = ["crypto"] },
{ name = "pymdown-extensions" },
- { name = "pymilvus" },
- { name = "pymongo" },
{ name = "pymysql" },
{ name = "pypandoc" },
{ name = "pypdf" },
- { name = "pytest" },
- { name = "pytest-docker" },
{ name = "python-jose" },
{ name = "python-multipart" },
{ name = "python-pptx" },
{ name = "python-socketio" },
{ name = "pytube" },
{ name = "pyxlsb" },
- { name = "qdrant-client" },
{ name = "rank-bm25" },
{ name = "rapidocr-onnxruntime" },
{ name = "redis" },
@@ -2757,7 +2367,7 @@ dependencies = [
{ name = "soundfile" },
{ name = "sqlalchemy" },
{ name = "starlette-compress" },
- { name = "tencentcloud-sdk-python" },
+ { name = "starsessions", extra = ["redis"] },
{ name = "tiktoken" },
{ name = "transformers" },
{ name = "unstructured" },
@@ -2777,105 +2387,91 @@ requires-dist = [
{ name = "accelerate" },
{ name = "aiocache" },
{ name = "aiofiles" },
- { name = "aiohttp", specifier = "==3.11.11" },
+ { name = "aiohttp", specifier = "==3.12.15" },
{ name = "alembic", specifier = "==1.14.0" },
{ name = "anthropic" },
{ name = "apscheduler", specifier = "==3.10.4" },
- { name = "argon2-cffi", specifier = "==23.1.0" },
+ { name = "argon2-cffi", specifier = "==25.1.0" },
{ name = "asgiref", specifier = "==3.8.1" },
{ name = "async-timeout" },
- { name = "authlib", specifier = "==1.4.1" },
+ { name = "authlib", specifier = "==1.6.5" },
{ name = "azure-ai-documentintelligence", specifier = "==1.0.2" },
- { name = "azure-identity", specifier = "==1.20.0" },
+ { name = "azure-identity", specifier = "==1.25.0" },
{ name = "azure-storage-blob", specifier = "==12.24.1" },
- { name = "bcrypt", specifier = "==4.3.0" },
- { name = "black", specifier = "==25.1.0" },
- { name = "boto3", specifier = "==1.35.53" },
- { name = "chromadb", specifier = "==0.6.3" },
- { name = "colbert-ai", specifier = "==0.2.21" },
+ { name = "bcrypt", specifier = "==5.0.0" },
+ { name = "black", specifier = "==25.9.0" },
+ { name = "boto3", specifier = "==1.40.5" },
+ { name = "chromadb", specifier = "==1.0.20" },
{ name = "cryptography" },
{ name = "ddgs", specifier = "==9.0.0" },
- { name = "docker", specifier = "~=7.1.0" },
{ name = "docx2txt", specifier = "==0.8" },
- { name = "duckduckgo-search", specifier = "==8.0.2" },
{ name = "einops", specifier = "==0.8.1" },
- { name = "elasticsearch", specifier = "==9.0.1" },
- { name = "fake-useragent", specifier = "==2.1.0" },
- { name = "fastapi", specifier = "==0.115.7" },
+ { name = "fake-useragent", specifier = "==2.2.0" },
+ { name = "fastapi", specifier = "==0.118.0" },
{ name = "faster-whisper", specifier = "==1.1.1" },
- { name = "firecrawl-py", specifier = "==1.12.0" },
{ name = "fpdf2", specifier = "==2.8.2" },
{ name = "ftfy", specifier = "==6.2.3" },
- { name = "gcp-storage-emulator", specifier = ">=2024.8.3" },
{ name = "google-api-python-client" },
{ name = "google-auth-httplib2" },
{ name = "google-auth-oauthlib" },
{ name = "google-cloud-storage", specifier = "==2.19.0" },
- { name = "google-genai", specifier = "==1.15.0" },
+ { name = "google-genai", specifier = "==1.38.0" },
{ name = "google-generativeai", specifier = "==0.8.5" },
- { name = "googleapis-common-protos", specifier = "==1.63.2" },
+ { name = "googleapis-common-protos", specifier = "==1.70.0" },
+ { name = "grpcio", specifier = "==1.74.0" },
{ name = "httpx", extras = ["brotli", "cli", "http2", "socks", "zstd"], specifier = "==0.28.1" },
- { name = "langchain", specifier = "==0.3.26" },
- { name = "langchain-community", specifier = "==0.3.26" },
- { name = "langfuse", specifier = "==2.44.0" },
+ { name = "itsdangerous", specifier = "==2.2.0" },
+ { name = "langchain", specifier = "==0.3.27" },
+ { name = "langchain-community", specifier = "==0.3.29" },
{ name = "ldap3", specifier = "==2.9.1" },
{ name = "loguru", specifier = "==0.7.3" },
- { name = "markdown", specifier = "==3.7" },
- { name = "moto", extras = ["s3"], specifier = ">=5.0.26" },
+ { name = "markdown", specifier = "==3.9" },
+ { name = "mcp", specifier = "==1.14.1" },
{ name = "nltk", specifier = "==3.9.1" },
{ name = "onnxruntime", specifier = "==1.20.1" },
{ name = "openai" },
{ name = "opencv-python-headless", specifier = "==4.11.0.86" },
{ name = "openpyxl", specifier = "==3.1.5" },
{ name = "opensearch-py", specifier = "==2.8.0" },
- { name = "oracledb", specifier = ">=3.2.0" },
{ name = "pandas", specifier = "==2.2.3" },
- { name = "passlib", extras = ["bcrypt"], specifier = "==1.7.4" },
{ name = "peewee", specifier = "==3.18.1" },
{ name = "peewee-migrate", specifier = "==1.12.2" },
- { name = "pgvector", specifier = "==0.4.0" },
- { name = "pillow", specifier = "==11.2.1" },
- { name = "pinecone", specifier = "==6.0.2" },
- { name = "playwright", specifier = "==1.49.1" },
+ { name = "pillow", specifier = "==11.3.0" },
+ { name = "protobuf", specifier = "==5.29.5" },
{ name = "psutil" },
- { name = "psycopg2-binary", specifier = "==2.9.9" },
+ { name = "pyarrow", specifier = "==20.0.0" },
{ name = "pycrdt", specifier = "==0.12.25" },
- { name = "pydantic", specifier = "==2.11.7" },
+ { name = "pydantic", specifier = "==2.11.9" },
{ name = "pydub" },
{ name = "pyjwt", extras = ["crypto"], specifier = "==2.10.1" },
{ name = "pymdown-extensions", specifier = "==10.14.2" },
- { name = "pymilvus", specifier = "==2.5.0" },
- { name = "pymongo" },
{ name = "pymysql", specifier = "==1.1.1" },
{ name = "pypandoc", specifier = "==1.15" },
- { name = "pypdf", specifier = "==4.3.1" },
- { name = "pytest", specifier = "~=8.3.2" },
- { name = "pytest-docker", specifier = "~=3.1.1" },
- { name = "python-jose", specifier = "==3.4.0" },
+ { name = "pypdf", specifier = "==6.0.0" },
+ { name = "python-jose", specifier = "==3.5.0" },
{ name = "python-multipart", specifier = "==0.0.20" },
{ name = "python-pptx", specifier = "==1.0.2" },
{ name = "python-socketio", specifier = "==5.13.0" },
{ name = "pytube", specifier = "==15.0.0" },
{ name = "pyxlsb", specifier = "==1.0.10" },
- { name = "qdrant-client", specifier = "==1.14.3" },
{ name = "rank-bm25", specifier = "==0.2.2" },
{ name = "rapidocr-onnxruntime", specifier = "==1.4.4" },
{ name = "redis" },
- { name = "requests", specifier = "==2.32.4" },
+ { name = "requests", specifier = "==2.32.5" },
{ name = "restrictedpython", specifier = "==8.0" },
- { name = "sentence-transformers", specifier = "==4.1.0" },
+ { name = "sentence-transformers", specifier = "==5.1.1" },
{ name = "sentencepiece" },
{ name = "soundfile", specifier = "==0.13.1" },
{ name = "sqlalchemy", specifier = "==2.0.38" },
{ name = "starlette-compress", specifier = "==1.6.0" },
- { name = "tencentcloud-sdk-python", specifier = "==3.0.1336" },
+ { name = "starsessions", extras = ["redis"], specifier = "==2.2.1" },
{ name = "tiktoken" },
{ name = "transformers" },
- { name = "unstructured", specifier = "==0.16.17" },
- { name = "uvicorn", extras = ["standard"], specifier = "==0.34.2" },
+ { name = "unstructured", specifier = "==0.18.15" },
+ { name = "uvicorn", extras = ["standard"], specifier = "==0.37.0" },
{ name = "validators", specifier = "==0.35.0" },
{ name = "xlrd", specifier = "==2.0.1" },
- { name = "youtube-transcript-api", specifier = "==1.1.0" },
+ { name = "youtube-transcript-api", specifier = "==1.2.2" },
]
[package.metadata.requires-dev]
@@ -2947,108 +2543,74 @@ wheels = [
]
[[package]]
-name = "opensearch-py"
-version = "2.8.0"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "certifi" },
- { name = "events" },
- { name = "python-dateutil" },
- { name = "requests" },
- { name = "urllib3" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/7c/e4/192c97ca676c81f69e138a22e10fb03f64e14a55633cb2acffb41bf6d061/opensearch_py-2.8.0.tar.gz", hash = "sha256:6598df0bc7a003294edd0ba88a331e0793acbb8c910c43edf398791e3b2eccda", size = 237923, upload-time = "2024-11-29T21:06:02.952Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/23/35/a957c6fb88ff6874996be688448b889475cf0ea978446cd5a30e764e0561/opensearch_py-2.8.0-py3-none-any.whl", hash = "sha256:52c60fdb5d4dcf6cce3ee746c13b194529b0161e0f41268b98ab8f1624abe2fa", size = 353492, upload-time = "2024-11-29T21:05:56.075Z" },
-]
-
-[[package]]
-name = "opentelemetry-api"
-version = "1.29.0"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "deprecated" },
- { name = "importlib-metadata" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/bc/8e/b886a5e9861afa188d1fe671fb96ff9a1d90a23d57799331e137cc95d573/opentelemetry_api-1.29.0.tar.gz", hash = "sha256:d04a6cf78aad09614f52964ecb38021e248f5714dc32c2e0d8fd99517b4d69cf", size = 62900, upload-time = "2024-12-11T17:02:23.275Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/43/53/5249ea860d417a26a3a6f1bdedfc0748c4f081a3adaec3d398bc0f7c6a71/opentelemetry_api-1.29.0-py3-none-any.whl", hash = "sha256:5fcd94c4141cc49c736271f3e1efb777bebe9cc535759c54c936cca4f1b312b8", size = 64304, upload-time = "2024-12-11T17:01:48.691Z" },
-]
-
-[[package]]
-name = "opentelemetry-exporter-otlp-proto-grpc"
-version = "1.15.0"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "backoff" },
- { name = "googleapis-common-protos" },
- { name = "grpcio" },
- { name = "opentelemetry-api" },
- { name = "opentelemetry-proto" },
- { name = "opentelemetry-sdk" },
+name = "opensearch-py"
+version = "2.8.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "certifi" },
+ { name = "events" },
+ { name = "python-dateutil" },
+ { name = "requests" },
+ { name = "urllib3" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/e4/ab/1be294b194af410f350f867a54621b4f33b7551adce2ae795e907148fc1e/opentelemetry_exporter_otlp_proto_grpc-1.15.0.tar.gz", hash = "sha256:844f2a4bb9bcda34e4eb6fe36765e5031aacb36dc60ed88c90fc246942ea26e7", size = 27262, upload-time = "2022-12-09T22:28:44.359Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/7c/e4/192c97ca676c81f69e138a22e10fb03f64e14a55633cb2acffb41bf6d061/opensearch_py-2.8.0.tar.gz", hash = "sha256:6598df0bc7a003294edd0ba88a331e0793acbb8c910c43edf398791e3b2eccda", size = 237923, upload-time = "2024-11-29T21:06:02.952Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/dd/8f/73ad108bcfd61b4169be5ad8b76acaf9158f224740da10ab9ea3469d551a/opentelemetry_exporter_otlp_proto_grpc-1.15.0-py3-none-any.whl", hash = "sha256:c2a5492ba7d140109968135d641d06ce3c5bd73c50665f787526065d57d7fd1d", size = 20378, upload-time = "2022-12-09T22:28:14.623Z" },
+ { url = "https://files.pythonhosted.org/packages/23/35/a957c6fb88ff6874996be688448b889475cf0ea978446cd5a30e764e0561/opensearch_py-2.8.0-py3-none-any.whl", hash = "sha256:52c60fdb5d4dcf6cce3ee746c13b194529b0161e0f41268b98ab8f1624abe2fa", size = 353492, upload-time = "2024-11-29T21:05:56.075Z" },
]
[[package]]
-name = "opentelemetry-instrumentation"
-version = "0.50b0"
+name = "opentelemetry-api"
+version = "1.29.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "opentelemetry-api" },
- { name = "opentelemetry-semantic-conventions" },
- { name = "packaging" },
- { name = "wrapt" },
+ { name = "deprecated" },
+ { name = "importlib-metadata" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/79/2e/2e59a7cb636dc394bd7cf1758ada5e8ed87590458ca6bb2f9c26e0243847/opentelemetry_instrumentation-0.50b0.tar.gz", hash = "sha256:7d98af72de8dec5323e5202e46122e5f908592b22c6d24733aad619f07d82979", size = 26539, upload-time = "2024-12-11T17:05:18.336Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/bc/8e/b886a5e9861afa188d1fe671fb96ff9a1d90a23d57799331e137cc95d573/opentelemetry_api-1.29.0.tar.gz", hash = "sha256:d04a6cf78aad09614f52964ecb38021e248f5714dc32c2e0d8fd99517b4d69cf", size = 62900, upload-time = "2024-12-11T17:02:23.275Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/ff/b1/55a77152a83ec8998e520a3a575f44af1020cfe4bdc000b7538583293b85/opentelemetry_instrumentation-0.50b0-py3-none-any.whl", hash = "sha256:b8f9fc8812de36e1c6dffa5bfc6224df258841fb387b6dfe5df15099daa10630", size = 30728, upload-time = "2024-12-11T17:03:54.948Z" },
+ { url = "https://files.pythonhosted.org/packages/43/53/5249ea860d417a26a3a6f1bdedfc0748c4f081a3adaec3d398bc0f7c6a71/opentelemetry_api-1.29.0-py3-none-any.whl", hash = "sha256:5fcd94c4141cc49c736271f3e1efb777bebe9cc535759c54c936cca4f1b312b8", size = 64304, upload-time = "2024-12-11T17:01:48.691Z" },
]
[[package]]
-name = "opentelemetry-instrumentation-asgi"
-version = "0.50b0"
+name = "opentelemetry-exporter-otlp-proto-common"
+version = "1.29.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "asgiref" },
- { name = "opentelemetry-api" },
- { name = "opentelemetry-instrumentation" },
- { name = "opentelemetry-semantic-conventions" },
- { name = "opentelemetry-util-http" },
+ { name = "opentelemetry-proto" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/49/cc/a7b2fd243c6d2621803092eba62e450071b6752dfe4f64f530bbfd91a328/opentelemetry_instrumentation_asgi-0.50b0.tar.gz", hash = "sha256:3ca4cb5616ae6a3e8ce86e7d5c360a8d8cc8ed722cf3dc8a5e44300774e87d49", size = 24105, upload-time = "2024-12-11T17:05:23.773Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/b1/58/f7fd7eaf592b2521999a4271ab3ce1c82fe37fe9b0dc25c348398d95d66a/opentelemetry_exporter_otlp_proto_common-1.29.0.tar.gz", hash = "sha256:e7c39b5dbd1b78fe199e40ddfe477e6983cb61aa74ba836df09c3869a3e3e163", size = 19133, upload-time = "2024-12-11T17:02:27.092Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/d2/81/0899c6b56b1023835f266d909250d439174afa0c34ed5944c5021d3da263/opentelemetry_instrumentation_asgi-0.50b0-py3-none-any.whl", hash = "sha256:2ba1297f746e55dec5a17fe825689da0613662fb25c004c3965a6c54b1d5be22", size = 16304, upload-time = "2024-12-11T17:04:03.555Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/75/7609bda3d72bf307839570b226180513e854c01443ebe265ed732a4980fc/opentelemetry_exporter_otlp_proto_common-1.29.0-py3-none-any.whl", hash = "sha256:a9d7376c06b4da9cf350677bcddb9618ed4b8255c3f6476975f5e38274ecd3aa", size = 18459, upload-time = "2024-12-11T17:01:54.817Z" },
]
[[package]]
-name = "opentelemetry-instrumentation-fastapi"
-version = "0.50b0"
+name = "opentelemetry-exporter-otlp-proto-grpc"
+version = "1.29.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
+ { name = "deprecated" },
+ { name = "googleapis-common-protos" },
+ { name = "grpcio" },
{ name = "opentelemetry-api" },
- { name = "opentelemetry-instrumentation" },
- { name = "opentelemetry-instrumentation-asgi" },
- { name = "opentelemetry-semantic-conventions" },
- { name = "opentelemetry-util-http" },
+ { name = "opentelemetry-exporter-otlp-proto-common" },
+ { name = "opentelemetry-proto" },
+ { name = "opentelemetry-sdk" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/8d/f8/1917b0b3e414e23c7d71c9a33f0ce020f94bc47d22a30f54ace704e07588/opentelemetry_instrumentation_fastapi-0.50b0.tar.gz", hash = "sha256:16b9181682136da210295def2bb304a32fb9bdee9a935cdc9da43567f7c1149e", size = 19214, upload-time = "2024-12-11T17:05:42.062Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/41/aa/b3f2190613141f35fe15145bf438334fdd1eac8aeeee4f7ecbc887999443/opentelemetry_exporter_otlp_proto_grpc-1.29.0.tar.gz", hash = "sha256:3d324d07d64574d72ed178698de3d717f62a059a93b6b7685ee3e303384e73ea", size = 26224, upload-time = "2024-12-11T17:02:28.911Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/cb/d6/37784bb30b213e2dd6838b9f96c2940907022c1b75ef1ff18a99afe42433/opentelemetry_instrumentation_fastapi-0.50b0-py3-none-any.whl", hash = "sha256:8f03b738495e4705fbae51a2826389c7369629dace89d0f291c06ffefdff5e52", size = 12079, upload-time = "2024-12-11T17:04:26.15Z" },
+ { url = "https://files.pythonhosted.org/packages/f2/de/4b4127a25d1594851d99032f3a9acb09cb512d11edec713410fb906607f4/opentelemetry_exporter_otlp_proto_grpc-1.29.0-py3-none-any.whl", hash = "sha256:5a2a3a741a2543ed162676cf3eefc2b4150e6f4f0a193187afb0d0e65039c69c", size = 18520, upload-time = "2024-12-11T17:01:57.001Z" },
]
[[package]]
name = "opentelemetry-proto"
-version = "1.15.0"
+version = "1.29.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "protobuf" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/1e/80/b3b2a98039574e57b6b15982219ae025d55f8c46d50dde258865ce5601b4/opentelemetry_proto-1.15.0.tar.gz", hash = "sha256:9c4008e40ac8cab359daac283fbe7002c5c29c77ea2674ad5626a249e64e0101", size = 35713, upload-time = "2022-12-09T22:28:55.409Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/80/52/fd3b3d79e1b00ad2dcac92db6885e49bedbf7a6828647954e4952d653132/opentelemetry_proto-1.29.0.tar.gz", hash = "sha256:3c136aa293782e9b44978c738fff72877a4b78b5d21a64e879898db7b2d93e5d", size = 34320, upload-time = "2024-12-11T17:02:44.709Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/3a/56/8343d94af8f32594f6b0bd273f72a40e430fb5970a353237af53af5d3031/opentelemetry_proto-1.15.0-py3-none-any.whl", hash = "sha256:044b6d044b4d10530f250856f933442b8753a17f94ae37c207607f733fb9a844", size = 52616, upload-time = "2022-12-09T22:28:30.03Z" },
+ { url = "https://files.pythonhosted.org/packages/bd/66/a500e38ee322d89fce61c74bd7769c8ef3bebc6c2f43fda5f3fc3441286d/opentelemetry_proto-1.29.0-py3-none-any.whl", hash = "sha256:495069c6f5495cbf732501cdcd3b7f60fda2b9d3d4255706ca99b7ca8dec53ff", size = 55818, upload-time = "2024-12-11T17:02:14.03Z" },
]
[[package]]
@@ -3078,36 +2640,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/da/fb/dc15fad105450a015e913cfa4f5c27b6a5f1bea8fb649f8cae11e699c8af/opentelemetry_semantic_conventions-0.50b0-py3-none-any.whl", hash = "sha256:e87efba8fdb67fb38113efea6a349531e75ed7ffc01562f65b802fcecb5e115e", size = 166602, upload-time = "2024-12-11T17:02:19.504Z" },
]
-[[package]]
-name = "opentelemetry-util-http"
-version = "0.50b0"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/69/10/ce3f0d1157cedbd819194f0b27a6bbb7c19a8bceb3941e4a4775014076cf/opentelemetry_util_http-0.50b0.tar.gz", hash = "sha256:dc4606027e1bc02aabb9533cc330dd43f874fca492e4175c31d7154f341754af", size = 7859, upload-time = "2024-12-11T17:06:14.206Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/64/8a/9e1b54f50d1fddebbeac9a9b0632f8db6ece7add904fb593ee2e268ee4de/opentelemetry_util_http-0.50b0-py3-none-any.whl", hash = "sha256:21f8aedac861ffa3b850f8c0a6c373026189eb8630ac6e14a2bf8c55695cc090", size = 6942, upload-time = "2024-12-11T17:05:13.342Z" },
-]
-
-[[package]]
-name = "oracledb"
-version = "3.2.0"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "cryptography" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/9d/2d/8336527f248dbeb7183b7b4bfafe3499119c467236f8916ce0ec3b8ef2b6/oracledb-3.2.0.tar.gz", hash = "sha256:9bf9f1c93e53142b33d1c5ebf5ababeebd2062a01d5ead68bbb640439ecf2223", size = 872574, upload-time = "2025-06-26T21:57:13.001Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/4c/02/8279be85defe274a5dbc565c27f927d7d772117c070008853d75d4d780a8/oracledb-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:42e936190c5c76b115e2803e9c51a416a895c31ca551bc154b8c52121a84ee78", size = 3985060, upload-time = "2025-06-26T21:57:30.753Z" },
- { url = "https://files.pythonhosted.org/packages/38/a2/ce33fca6a15b3357d00c92bffcfa614b2d9f008d8e997f57e0302c760fb6/oracledb-3.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a87a331df19a84cad3d50a99cd505f8d0ec500e5e22438a025bd66e037b20715", size = 2507408, upload-time = "2025-06-26T21:57:33.34Z" },
- { url = "https://files.pythonhosted.org/packages/17/1b/dcaeb174ca777f28e05ac3d862cb468ce4b0a9c36900aa5f12ecbf29029f/oracledb-3.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b62f0c018e437b91254f019715a5fd5daafcf3182afee86ccd9d0f3dac75c0a7", size = 2687910, upload-time = "2025-06-26T21:57:36.173Z" },
- { url = "https://files.pythonhosted.org/packages/c2/f6/a575191c027b89486947597a7b6ae9c2abbc05eae2b79de037a6039ae455/oracledb-3.2.0-cp311-cp311-win32.whl", hash = "sha256:01477e65f129f8927ef64cd4b48d68646fc0115e1e95484dac5b82dd9da7b98b", size = 1548061, upload-time = "2025-06-26T21:57:38.273Z" },
- { url = "https://files.pythonhosted.org/packages/4e/ec/a9b5488858d3b45213ce03f442c5cdf5aef356269071b84caecadb326e29/oracledb-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:a1dc529f06a95ca3560d233609c266c17e828a08a70b8a434e2c3fe7000825eb", size = 1891446, upload-time = "2025-06-26T21:57:40.737Z" },
- { url = "https://files.pythonhosted.org/packages/56/d1/04632c2fab7c9ab91c68630eb221e17019e74d5b023badc0c191e83119cf/oracledb-3.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1c2658983520b460776e74c75bb50e51a78e8ab743b64adc844a26a3a8a0bc7c", size = 3959613, upload-time = "2025-06-26T21:57:43.735Z" },
- { url = "https://files.pythonhosted.org/packages/7a/de/ebb82b6193583d0c7f13f908756d44bd2c03207b501457773b0793018231/oracledb-3.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c7a599ffe3238824951948992ab6b4532a0c1d4b33900d412f738a7da476d47", size = 2336800, upload-time = "2025-06-26T21:57:45.997Z" },
- { url = "https://files.pythonhosted.org/packages/1e/f5/f81f72fac3cfb52fc18965d4d07d76e26103c2cc60641a796b9618904b54/oracledb-3.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9388ad0e09dc4030cd62779acc0ae4e9dfd338da7d30c72768fb0589461485ff", size = 2509427, upload-time = "2025-06-26T21:57:48.686Z" },
- { url = "https://files.pythonhosted.org/packages/02/ad/ded50edb5010b27173f203421f69f90e5f00acaf5686ccd4f7963e1c695b/oracledb-3.2.0-cp312-cp312-win32.whl", hash = "sha256:94ac95e52e6f4a9394408aba6cc5f90581219ecb872d450b2a80df9aa3cc4216", size = 1511775, upload-time = "2025-06-26T21:57:50.474Z" },
- { url = "https://files.pythonhosted.org/packages/5f/75/684d2e18d57d72abf85366e8e1f61aaa2e6b15c71bf95f5bb6e9d7e0c9a5/oracledb-3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:a367604d091ee82c9e3f6d97e34b8ec919646209bda78337f6156b76252dd024", size = 1850296, upload-time = "2025-06-26T21:57:52.649Z" },
-]
-
[[package]]
name = "orjson"
version = "3.10.14"
@@ -3188,20 +2720,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/29/d4/1244ab8edf173a10fd601f7e13b9566c1b525c4f365d6bee918e68381889/pandas-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13", size = 11504248, upload-time = "2024-09-20T13:09:23.137Z" },
]
-[[package]]
-name = "passlib"
-version = "1.7.4"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/b6/06/9da9ee59a67fae7761aab3ccc84fa4f3f33f125b370f1ccdb915bf967c11/passlib-1.7.4.tar.gz", hash = "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04", size = 689844, upload-time = "2020-10-08T19:00:52.121Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/3b/a4/ab6b7589382ca3df236e03faa71deac88cae040af60c071a78d254a62172/passlib-1.7.4-py2.py3-none-any.whl", hash = "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1", size = 525554, upload-time = "2020-10-08T19:00:49.856Z" },
-]
-
-[package.optional-dependencies]
-bcrypt = [
- { name = "bcrypt" },
-]
-
[[package]]
name = "pathspec"
version = "0.12.1"
@@ -3230,78 +2748,41 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/8c/32/de329eb77c16ebe2d52971d55954e4c34c7302ab285df8897b8d8dfd705e/peewee_migrate-1.12.2-py3-none-any.whl", hash = "sha256:2930bf83ef802cdb5fb123116c5eb87cbf3756cb27674f674923be6bb27dabee", size = 18580, upload-time = "2023-08-07T11:40:02.468Z" },
]
-[[package]]
-name = "pgvector"
-version = "0.4.0"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "numpy" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/e2/40/296ffb7f97fc7ec7b7c34f46861a519c576d561fd31455fc75c5ce2fa8db/pgvector-0.4.0.tar.gz", hash = "sha256:f909f8e8081b57fb8a2442c36c3a1e521228d0d4ad66100c28c674806ff62688", size = 30688, upload-time = "2025-03-16T00:56:01.321Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/90/fb/77d29e98b36f1a0c6f770157001d3747557cae46f0e6f6d282461e554b80/pgvector-0.4.0-py3-none-any.whl", hash = "sha256:9d3e0c27f676c61d2fd4270ac1bc520d39b947b199200babe4a56d6d00c74a07", size = 27027, upload-time = "2025-03-16T00:55:59.948Z" },
-]
-
[[package]]
name = "pillow"
-version = "11.2.1"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/af/cb/bb5c01fcd2a69335b86c22142b2bccfc3464087efb7fd382eee5ffc7fdf7/pillow-11.2.1.tar.gz", hash = "sha256:a64dd61998416367b7ef979b73d3a85853ba9bec4c2925f74e588879a58716b6", size = 47026707, upload-time = "2025-04-12T17:50:03.289Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/68/08/3fbf4b98924c73037a8e8b4c2c774784805e0fb4ebca6c5bb60795c40125/pillow-11.2.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:35ca289f712ccfc699508c4658a1d14652e8033e9b69839edf83cbdd0ba39e70", size = 3198450, upload-time = "2025-04-12T17:47:37.135Z" },
- { url = "https://files.pythonhosted.org/packages/84/92/6505b1af3d2849d5e714fc75ba9e69b7255c05ee42383a35a4d58f576b16/pillow-11.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0409af9f829f87a2dfb7e259f78f317a5351f2045158be321fd135973fff7bf", size = 3030550, upload-time = "2025-04-12T17:47:39.345Z" },
- { url = "https://files.pythonhosted.org/packages/3c/8c/ac2f99d2a70ff966bc7eb13dacacfaab57c0549b2ffb351b6537c7840b12/pillow-11.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4e5c5edee874dce4f653dbe59db7c73a600119fbea8d31f53423586ee2aafd7", size = 4415018, upload-time = "2025-04-12T17:47:41.128Z" },
- { url = "https://files.pythonhosted.org/packages/1f/e3/0a58b5d838687f40891fff9cbaf8669f90c96b64dc8f91f87894413856c6/pillow-11.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b93a07e76d13bff9444f1a029e0af2964e654bfc2e2c2d46bfd080df5ad5f3d8", size = 4498006, upload-time = "2025-04-12T17:47:42.912Z" },
- { url = "https://files.pythonhosted.org/packages/21/f5/6ba14718135f08fbfa33308efe027dd02b781d3f1d5c471444a395933aac/pillow-11.2.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:e6def7eed9e7fa90fde255afaf08060dc4b343bbe524a8f69bdd2a2f0018f600", size = 4517773, upload-time = "2025-04-12T17:47:44.611Z" },
- { url = "https://files.pythonhosted.org/packages/20/f2/805ad600fc59ebe4f1ba6129cd3a75fb0da126975c8579b8f57abeb61e80/pillow-11.2.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8f4f3724c068be008c08257207210c138d5f3731af6c155a81c2b09a9eb3a788", size = 4607069, upload-time = "2025-04-12T17:47:46.46Z" },
- { url = "https://files.pythonhosted.org/packages/71/6b/4ef8a288b4bb2e0180cba13ca0a519fa27aa982875882392b65131401099/pillow-11.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a0a6709b47019dff32e678bc12c63008311b82b9327613f534e496dacaefb71e", size = 4583460, upload-time = "2025-04-12T17:47:49.255Z" },
- { url = "https://files.pythonhosted.org/packages/62/ae/f29c705a09cbc9e2a456590816e5c234382ae5d32584f451c3eb41a62062/pillow-11.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f6b0c664ccb879109ee3ca702a9272d877f4fcd21e5eb63c26422fd6e415365e", size = 4661304, upload-time = "2025-04-12T17:47:51.067Z" },
- { url = "https://files.pythonhosted.org/packages/6e/1a/c8217b6f2f73794a5e219fbad087701f412337ae6dbb956db37d69a9bc43/pillow-11.2.1-cp311-cp311-win32.whl", hash = "sha256:cc5d875d56e49f112b6def6813c4e3d3036d269c008bf8aef72cd08d20ca6df6", size = 2331809, upload-time = "2025-04-12T17:47:54.425Z" },
- { url = "https://files.pythonhosted.org/packages/e2/72/25a8f40170dc262e86e90f37cb72cb3de5e307f75bf4b02535a61afcd519/pillow-11.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:0f5c7eda47bf8e3c8a283762cab94e496ba977a420868cb819159980b6709193", size = 2676338, upload-time = "2025-04-12T17:47:56.535Z" },
- { url = "https://files.pythonhosted.org/packages/06/9e/76825e39efee61efea258b479391ca77d64dbd9e5804e4ad0fa453b4ba55/pillow-11.2.1-cp311-cp311-win_arm64.whl", hash = "sha256:4d375eb838755f2528ac8cbc926c3e31cc49ca4ad0cf79cff48b20e30634a4a7", size = 2414918, upload-time = "2025-04-12T17:47:58.217Z" },
- { url = "https://files.pythonhosted.org/packages/c7/40/052610b15a1b8961f52537cc8326ca6a881408bc2bdad0d852edeb6ed33b/pillow-11.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:78afba22027b4accef10dbd5eed84425930ba41b3ea0a86fa8d20baaf19d807f", size = 3190185, upload-time = "2025-04-12T17:48:00.417Z" },
- { url = "https://files.pythonhosted.org/packages/e5/7e/b86dbd35a5f938632093dc40d1682874c33dcfe832558fc80ca56bfcb774/pillow-11.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78092232a4ab376a35d68c4e6d5e00dfd73454bd12b230420025fbe178ee3b0b", size = 3030306, upload-time = "2025-04-12T17:48:02.391Z" },
- { url = "https://files.pythonhosted.org/packages/a4/5c/467a161f9ed53e5eab51a42923c33051bf8d1a2af4626ac04f5166e58e0c/pillow-11.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25a5f306095c6780c52e6bbb6109624b95c5b18e40aab1c3041da3e9e0cd3e2d", size = 4416121, upload-time = "2025-04-12T17:48:04.554Z" },
- { url = "https://files.pythonhosted.org/packages/62/73/972b7742e38ae0e2ac76ab137ca6005dcf877480da0d9d61d93b613065b4/pillow-11.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c7b29dbd4281923a2bfe562acb734cee96bbb129e96e6972d315ed9f232bef4", size = 4501707, upload-time = "2025-04-12T17:48:06.831Z" },
- { url = "https://files.pythonhosted.org/packages/e4/3a/427e4cb0b9e177efbc1a84798ed20498c4f233abde003c06d2650a6d60cb/pillow-11.2.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3e645b020f3209a0181a418bffe7b4a93171eef6c4ef6cc20980b30bebf17b7d", size = 4522921, upload-time = "2025-04-12T17:48:09.229Z" },
- { url = "https://files.pythonhosted.org/packages/fe/7c/d8b1330458e4d2f3f45d9508796d7caf0c0d3764c00c823d10f6f1a3b76d/pillow-11.2.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b2dbea1012ccb784a65349f57bbc93730b96e85b42e9bf7b01ef40443db720b4", size = 4612523, upload-time = "2025-04-12T17:48:11.631Z" },
- { url = "https://files.pythonhosted.org/packages/b3/2f/65738384e0b1acf451de5a573d8153fe84103772d139e1e0bdf1596be2ea/pillow-11.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:da3104c57bbd72948d75f6a9389e6727d2ab6333c3617f0a89d72d4940aa0443", size = 4587836, upload-time = "2025-04-12T17:48:13.592Z" },
- { url = "https://files.pythonhosted.org/packages/6a/c5/e795c9f2ddf3debb2dedd0df889f2fe4b053308bb59a3cc02a0cd144d641/pillow-11.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:598174aef4589af795f66f9caab87ba4ff860ce08cd5bb447c6fc553ffee603c", size = 4669390, upload-time = "2025-04-12T17:48:15.938Z" },
- { url = "https://files.pythonhosted.org/packages/96/ae/ca0099a3995976a9fce2f423166f7bff9b12244afdc7520f6ed38911539a/pillow-11.2.1-cp312-cp312-win32.whl", hash = "sha256:1d535df14716e7f8776b9e7fee118576d65572b4aad3ed639be9e4fa88a1cad3", size = 2332309, upload-time = "2025-04-12T17:48:17.885Z" },
- { url = "https://files.pythonhosted.org/packages/7c/18/24bff2ad716257fc03da964c5e8f05d9790a779a8895d6566e493ccf0189/pillow-11.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:14e33b28bf17c7a38eede290f77db7c664e4eb01f7869e37fa98a5aa95978941", size = 2676768, upload-time = "2025-04-12T17:48:19.655Z" },
- { url = "https://files.pythonhosted.org/packages/da/bb/e8d656c9543276517ee40184aaa39dcb41e683bca121022f9323ae11b39d/pillow-11.2.1-cp312-cp312-win_arm64.whl", hash = "sha256:21e1470ac9e5739ff880c211fc3af01e3ae505859392bf65458c224d0bf283eb", size = 2415087, upload-time = "2025-04-12T17:48:21.991Z" },
- { url = "https://files.pythonhosted.org/packages/a4/ad/2613c04633c7257d9481ab21d6b5364b59fc5d75faafd7cb8693523945a3/pillow-11.2.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:80f1df8dbe9572b4b7abdfa17eb5d78dd620b1d55d9e25f834efdbee872d3aed", size = 3181734, upload-time = "2025-04-12T17:49:46.789Z" },
- { url = "https://files.pythonhosted.org/packages/a4/fd/dcdda4471ed667de57bb5405bb42d751e6cfdd4011a12c248b455c778e03/pillow-11.2.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ea926cfbc3957090becbcbbb65ad177161a2ff2ad578b5a6ec9bb1e1cd78753c", size = 2999841, upload-time = "2025-04-12T17:49:48.812Z" },
- { url = "https://files.pythonhosted.org/packages/ac/89/8a2536e95e77432833f0db6fd72a8d310c8e4272a04461fb833eb021bf94/pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:738db0e0941ca0376804d4de6a782c005245264edaa253ffce24e5a15cbdc7bd", size = 3437470, upload-time = "2025-04-12T17:49:50.831Z" },
- { url = "https://files.pythonhosted.org/packages/9d/8f/abd47b73c60712f88e9eda32baced7bfc3e9bd6a7619bb64b93acff28c3e/pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9db98ab6565c69082ec9b0d4e40dd9f6181dab0dd236d26f7a50b8b9bfbd5076", size = 3460013, upload-time = "2025-04-12T17:49:53.278Z" },
- { url = "https://files.pythonhosted.org/packages/f6/20/5c0a0aa83b213b7a07ec01e71a3d6ea2cf4ad1d2c686cc0168173b6089e7/pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:036e53f4170e270ddb8797d4c590e6dd14d28e15c7da375c18978045f7e6c37b", size = 3527165, upload-time = "2025-04-12T17:49:55.164Z" },
- { url = "https://files.pythonhosted.org/packages/58/0e/2abab98a72202d91146abc839e10c14f7cf36166f12838ea0c4db3ca6ecb/pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:14f73f7c291279bd65fda51ee87affd7c1e097709f7fdd0188957a16c264601f", size = 3571586, upload-time = "2025-04-12T17:49:57.171Z" },
- { url = "https://files.pythonhosted.org/packages/21/2c/5e05f58658cf49b6667762cca03d6e7d85cededde2caf2ab37b81f80e574/pillow-11.2.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:208653868d5c9ecc2b327f9b9ef34e0e42a4cdd172c2988fd81d62d2bc9bc044", size = 2674751, upload-time = "2025-04-12T17:49:59.628Z" },
-]
-
-[[package]]
-name = "pinecone"
-version = "6.0.2"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "certifi" },
- { name = "pinecone-plugin-interface" },
- { name = "python-dateutil" },
- { name = "typing-extensions" },
- { name = "urllib3" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/40/e0/3584dcde7f2cb299b4deb5cc0491f2c9c130c7a72c1d4691fe2c9c3a3613/pinecone-6.0.2.tar.gz", hash = "sha256:9c2e74be8b3abe76909da9b4dae61bced49aade51f6fc39b87edb97a1f8df0e4", size = 175104, upload-time = "2025-03-13T21:05:18.763Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/5b/c7/2bc1210aa51528b9ba75aede1f169998f50942cc47cdd82dd2dbcba4faa5/pinecone-6.0.2-py3-none-any.whl", hash = "sha256:a85fa36d7d1451e7b7563ccfc7e3e2dadd39b33e5d53b2882468db8514ab8847", size = 421874, upload-time = "2025-03-13T21:05:17.11Z" },
-]
-
-[[package]]
-name = "pinecone-plugin-interface"
-version = "0.0.7"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/f4/fb/e8a4063264953ead9e2b24d9b390152c60f042c951c47f4592e9996e57ff/pinecone_plugin_interface-0.0.7.tar.gz", hash = "sha256:b8e6675e41847333aa13923cc44daa3f85676d7157324682dc1640588a982846", size = 3370, upload-time = "2024-06-05T01:57:52.093Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/3b/1d/a21fdfcd6d022cb64cef5c2a29ee6691c6c103c4566b41646b080b7536a5/pinecone_plugin_interface-0.0.7-py3-none-any.whl", hash = "sha256:875857ad9c9fc8bbc074dbe780d187a2afd21f5bfe0f3b08601924a61ef1bba8", size = 6249, upload-time = "2024-06-05T01:57:50.583Z" },
+version = "11.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f3/0d/d0d6dea55cd152ce3d6767bb38a8fc10e33796ba4ba210cbab9354b6d238/pillow-11.3.0.tar.gz", hash = "sha256:3828ee7586cd0b2091b6209e5ad53e20d0649bbe87164a459d0676e035e8f523", size = 47113069, upload-time = "2025-07-01T09:16:30.666Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/db/26/77f8ed17ca4ffd60e1dcd220a6ec6d71210ba398cfa33a13a1cd614c5613/pillow-11.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1cd110edf822773368b396281a2293aeb91c90a2db00d78ea43e7e861631b722", size = 5316531, upload-time = "2025-07-01T09:13:59.203Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/39/ee475903197ce709322a17a866892efb560f57900d9af2e55f86db51b0a5/pillow-11.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9c412fddd1b77a75aa904615ebaa6001f169b26fd467b4be93aded278266b288", size = 4686560, upload-time = "2025-07-01T09:14:01.101Z" },
+ { url = "https://files.pythonhosted.org/packages/d5/90/442068a160fd179938ba55ec8c97050a612426fae5ec0a764e345839f76d/pillow-11.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1aa4de119a0ecac0a34a9c8bde33f34022e2e8f99104e47a3ca392fd60e37d", size = 5870978, upload-time = "2025-07-03T13:09:55.638Z" },
+ { url = "https://files.pythonhosted.org/packages/13/92/dcdd147ab02daf405387f0218dcf792dc6dd5b14d2573d40b4caeef01059/pillow-11.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:91da1d88226663594e3f6b4b8c3c8d85bd504117d043740a8e0ec449087cc494", size = 7641168, upload-time = "2025-07-03T13:10:00.37Z" },
+ { url = "https://files.pythonhosted.org/packages/6e/db/839d6ba7fd38b51af641aa904e2960e7a5644d60ec754c046b7d2aee00e5/pillow-11.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:643f189248837533073c405ec2f0bb250ba54598cf80e8c1e043381a60632f58", size = 5973053, upload-time = "2025-07-01T09:14:04.491Z" },
+ { url = "https://files.pythonhosted.org/packages/f2/2f/d7675ecae6c43e9f12aa8d58b6012683b20b6edfbdac7abcb4e6af7a3784/pillow-11.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:106064daa23a745510dabce1d84f29137a37224831d88eb4ce94bb187b1d7e5f", size = 6640273, upload-time = "2025-07-01T09:14:06.235Z" },
+ { url = "https://files.pythonhosted.org/packages/45/ad/931694675ede172e15b2ff03c8144a0ddaea1d87adb72bb07655eaffb654/pillow-11.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cd8ff254faf15591e724dc7c4ddb6bf4793efcbe13802a4ae3e863cd300b493e", size = 6082043, upload-time = "2025-07-01T09:14:07.978Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/04/ba8f2b11fc80d2dd462d7abec16351b45ec99cbbaea4387648a44190351a/pillow-11.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:932c754c2d51ad2b2271fd01c3d121daaa35e27efae2a616f77bf164bc0b3e94", size = 6715516, upload-time = "2025-07-01T09:14:10.233Z" },
+ { url = "https://files.pythonhosted.org/packages/48/59/8cd06d7f3944cc7d892e8533c56b0acb68399f640786313275faec1e3b6f/pillow-11.3.0-cp311-cp311-win32.whl", hash = "sha256:b4b8f3efc8d530a1544e5962bd6b403d5f7fe8b9e08227c6b255f98ad82b4ba0", size = 6274768, upload-time = "2025-07-01T09:14:11.921Z" },
+ { url = "https://files.pythonhosted.org/packages/f1/cc/29c0f5d64ab8eae20f3232da8f8571660aa0ab4b8f1331da5c2f5f9a938e/pillow-11.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:1a992e86b0dd7aeb1f053cd506508c0999d710a8f07b4c791c63843fc6a807ac", size = 6986055, upload-time = "2025-07-01T09:14:13.623Z" },
+ { url = "https://files.pythonhosted.org/packages/c6/df/90bd886fabd544c25addd63e5ca6932c86f2b701d5da6c7839387a076b4a/pillow-11.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:30807c931ff7c095620fe04448e2c2fc673fcbb1ffe2a7da3fb39613489b1ddd", size = 2423079, upload-time = "2025-07-01T09:14:15.268Z" },
+ { url = "https://files.pythonhosted.org/packages/40/fe/1bc9b3ee13f68487a99ac9529968035cca2f0a51ec36892060edcc51d06a/pillow-11.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdae223722da47b024b867c1ea0be64e0df702c5e0a60e27daad39bf960dd1e4", size = 5278800, upload-time = "2025-07-01T09:14:17.648Z" },
+ { url = "https://files.pythonhosted.org/packages/2c/32/7e2ac19b5713657384cec55f89065fb306b06af008cfd87e572035b27119/pillow-11.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:921bd305b10e82b4d1f5e802b6850677f965d8394203d182f078873851dada69", size = 4686296, upload-time = "2025-07-01T09:14:19.828Z" },
+ { url = "https://files.pythonhosted.org/packages/8e/1e/b9e12bbe6e4c2220effebc09ea0923a07a6da1e1f1bfbc8d7d29a01ce32b/pillow-11.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb76541cba2f958032d79d143b98a3a6b3ea87f0959bbe256c0b5e416599fd5d", size = 5871726, upload-time = "2025-07-03T13:10:04.448Z" },
+ { url = "https://files.pythonhosted.org/packages/8d/33/e9200d2bd7ba00dc3ddb78df1198a6e80d7669cce6c2bdbeb2530a74ec58/pillow-11.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:67172f2944ebba3d4a7b54f2e95c786a3a50c21b88456329314caaa28cda70f6", size = 7644652, upload-time = "2025-07-03T13:10:10.391Z" },
+ { url = "https://files.pythonhosted.org/packages/41/f1/6f2427a26fc683e00d985bc391bdd76d8dd4e92fac33d841127eb8fb2313/pillow-11.3.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f07ed9f56a3b9b5f49d3661dc9607484e85c67e27f3e8be2c7d28ca032fec7", size = 5977787, upload-time = "2025-07-01T09:14:21.63Z" },
+ { url = "https://files.pythonhosted.org/packages/e4/c9/06dd4a38974e24f932ff5f98ea3c546ce3f8c995d3f0985f8e5ba48bba19/pillow-11.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:676b2815362456b5b3216b4fd5bd89d362100dc6f4945154ff172e206a22c024", size = 6645236, upload-time = "2025-07-01T09:14:23.321Z" },
+ { url = "https://files.pythonhosted.org/packages/40/e7/848f69fb79843b3d91241bad658e9c14f39a32f71a301bcd1d139416d1be/pillow-11.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3e184b2f26ff146363dd07bde8b711833d7b0202e27d13540bfe2e35a323a809", size = 6086950, upload-time = "2025-07-01T09:14:25.237Z" },
+ { url = "https://files.pythonhosted.org/packages/0b/1a/7cff92e695a2a29ac1958c2a0fe4c0b2393b60aac13b04a4fe2735cad52d/pillow-11.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6be31e3fc9a621e071bc17bb7de63b85cbe0bfae91bb0363c893cbe67247780d", size = 6723358, upload-time = "2025-07-01T09:14:27.053Z" },
+ { url = "https://files.pythonhosted.org/packages/26/7d/73699ad77895f69edff76b0f332acc3d497f22f5d75e5360f78cbcaff248/pillow-11.3.0-cp312-cp312-win32.whl", hash = "sha256:7b161756381f0918e05e7cb8a371fff367e807770f8fe92ecb20d905d0e1c149", size = 6275079, upload-time = "2025-07-01T09:14:30.104Z" },
+ { url = "https://files.pythonhosted.org/packages/8c/ce/e7dfc873bdd9828f3b6e5c2bbb74e47a98ec23cc5c74fc4e54462f0d9204/pillow-11.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a6444696fce635783440b7f7a9fc24b3ad10a9ea3f0ab66c5905be1c19ccf17d", size = 6986324, upload-time = "2025-07-01T09:14:31.899Z" },
+ { url = "https://files.pythonhosted.org/packages/16/8f/b13447d1bf0b1f7467ce7d86f6e6edf66c0ad7cf44cf5c87a37f9bed9936/pillow-11.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:2aceea54f957dd4448264f9bf40875da0415c83eb85f55069d89c0ed436e3542", size = 2423067, upload-time = "2025-07-01T09:14:33.709Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/e3/6fa84033758276fb31da12e5fb66ad747ae83b93c67af17f8c6ff4cc8f34/pillow-11.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7c8ec7a017ad1bd562f93dbd8505763e688d388cde6e4a010ae1486916e713e6", size = 5270566, upload-time = "2025-07-01T09:16:19.801Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/ee/e8d2e1ab4892970b561e1ba96cbd59c0d28cf66737fc44abb2aec3795a4e/pillow-11.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:9ab6ae226de48019caa8074894544af5b53a117ccb9d3b3dcb2871464c829438", size = 4654618, upload-time = "2025-07-01T09:16:21.818Z" },
+ { url = "https://files.pythonhosted.org/packages/f2/6d/17f80f4e1f0761f02160fc433abd4109fa1548dcfdca46cfdadaf9efa565/pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fe27fb049cdcca11f11a7bfda64043c37b30e6b91f10cb5bab275806c32f6ab3", size = 4874248, upload-time = "2025-07-03T13:11:20.738Z" },
+ { url = "https://files.pythonhosted.org/packages/de/5f/c22340acd61cef960130585bbe2120e2fd8434c214802f07e8c03596b17e/pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:465b9e8844e3c3519a983d58b80be3f668e2a7a5db97f2784e7079fbc9f9822c", size = 6583963, upload-time = "2025-07-03T13:11:26.283Z" },
+ { url = "https://files.pythonhosted.org/packages/31/5e/03966aedfbfcbb4d5f8aa042452d3361f325b963ebbadddac05b122e47dd/pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5418b53c0d59b3824d05e029669efa023bbef0f3e92e75ec8428f3799487f361", size = 4957170, upload-time = "2025-07-01T09:16:23.762Z" },
+ { url = "https://files.pythonhosted.org/packages/cc/2d/e082982aacc927fc2cab48e1e731bdb1643a1406acace8bed0900a61464e/pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:504b6f59505f08ae014f724b6207ff6222662aab5cc9542577fb084ed0676ac7", size = 5581505, upload-time = "2025-07-01T09:16:25.593Z" },
+ { url = "https://files.pythonhosted.org/packages/34/e7/ae39f538fd6844e982063c3a5e4598b8ced43b9633baa3a85ef33af8c05c/pillow-11.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c84d689db21a1c397d001aa08241044aa2069e7587b398c8cc63020390b1c1b8", size = 6984598, upload-time = "2025-07-01T09:16:27.732Z" },
]
[[package]]
@@ -3313,24 +2794,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439, upload-time = "2024-09-17T19:06:49.212Z" },
]
-[[package]]
-name = "playwright"
-version = "1.49.1"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "greenlet" },
- { name = "pyee" },
-]
-wheels = [
- { url = "https://files.pythonhosted.org/packages/ab/be/01025581052e43eb698092c4328d7497ca62bcb5c83f15a611d4a71b4b92/playwright-1.49.1-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:1041ffb45a0d0bc44d698d3a5aa3ac4b67c9bd03540da43a0b70616ad52592b8", size = 39559859, upload-time = "2024-12-10T17:32:14.907Z" },
- { url = "https://files.pythonhosted.org/packages/79/25/ef1010a42cc7d576282015d983c5451d73e369b198b6eb32a177fae281f8/playwright-1.49.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:9f38ed3d0c1f4e0a6d1c92e73dd9a61f8855133249d6f0cec28648d38a7137be", size = 38808973, upload-time = "2024-12-10T17:32:22.516Z" },
- { url = "https://files.pythonhosted.org/packages/70/4b/3930cf10f303a10d493a382e4448aaff898b4065698b3b8d92f902e53e08/playwright-1.49.1-py3-none-macosx_11_0_universal2.whl", hash = "sha256:3be48c6d26dc819ca0a26567c1ae36a980a0303dcd4249feb6f59e115aaddfb8", size = 39559863, upload-time = "2024-12-10T17:32:29.12Z" },
- { url = "https://files.pythonhosted.org/packages/9a/c1/ea765e72a746dc7ec2ce155ffea29d454e7171db78f3c09185e888387246/playwright-1.49.1-py3-none-manylinux1_x86_64.whl", hash = "sha256:753ca90ee31b4b03d165cfd36e477309ebf2b4381953f2a982ff612d85b147d2", size = 44163300, upload-time = "2024-12-10T17:32:35.647Z" },
- { url = "https://files.pythonhosted.org/packages/5a/52/95efac704bf36b770a2522d88a6dee298042845d10bfb35f7ca0fcc36d91/playwright-1.49.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd9bc8dab37aa25198a01f555f0a2e2c3813fe200fef018ac34dfe86b34994b9", size = 43744353, upload-time = "2024-12-10T17:32:43.189Z" },
- { url = "https://files.pythonhosted.org/packages/f9/97/a3fccc9aaa6da83890772e9980703b0ea6b1e1ad42042fb50df3aef6c641/playwright-1.49.1-py3-none-win32.whl", hash = "sha256:43b304be67f096058e587dac453ece550eff87b8fbed28de30f4f022cc1745bb", size = 34060663, upload-time = "2024-12-10T17:32:49.904Z" },
- { url = "https://files.pythonhosted.org/packages/71/a9/bd88ac0bd498c91aab3aba2e393d1fa59f72a7243e9265ccbf4861ca4f64/playwright-1.49.1-py3-none-win_amd64.whl", hash = "sha256:47b23cb346283278f5b4d1e1990bcb6d6302f80c0aa0ca93dd0601a1400191df", size = 34060667, upload-time = "2024-12-10T17:32:56.459Z" },
-]
-
[[package]]
name = "pluggy"
version = "1.5.0"
@@ -3340,18 +2803,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556, upload-time = "2024-04-20T21:34:40.434Z" },
]
-[[package]]
-name = "portalocker"
-version = "2.10.1"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "pywin32", marker = "sys_platform == 'win32'" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/ed/d3/c6c64067759e87af98cc668c1cc75171347d0f1577fab7ca3749134e3cd4/portalocker-2.10.1.tar.gz", hash = "sha256:ef1bf844e878ab08aee7e40184156e1151f228f103aa5c6bd0724cc330960f8f", size = 40891, upload-time = "2024-07-13T23:15:34.86Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/9b/fb/a70a4214956182e0d7a9099ab17d50bfcba1056188e9b14f35b9e2b62a0d/portalocker-2.10.1-py3-none-any.whl", hash = "sha256:53a5984ebc86a025552264b459b46a2086e269b21823cb572f8f28ee759e45bf", size = 18423, upload-time = "2024-07-13T23:15:32.602Z" },
-]
-
[[package]]
name = "posthog"
version = "3.8.3"
@@ -3439,16 +2890,16 @@ wheels = [
[[package]]
name = "protobuf"
-version = "4.25.5"
+version = "5.29.5"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/67/dd/48d5fdb68ec74d70fabcc252e434492e56f70944d9f17b6a15e3746d2295/protobuf-4.25.5.tar.gz", hash = "sha256:7f8249476b4a9473645db7f8ab42b02fe1488cbe5fb72fddd445e0665afd8584", size = 380315, upload-time = "2024-09-18T22:25:43.093Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/43/29/d09e70352e4e88c9c7a198d5645d7277811448d76c23b00345670f7c8a38/protobuf-5.29.5.tar.gz", hash = "sha256:bc1463bafd4b0929216c35f437a8e28731a2b7fe3d98bb77a600efced5a15c84", size = 425226, upload-time = "2025-05-28T23:51:59.82Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/00/35/1b3c5a5e6107859c4ca902f4fbb762e48599b78129a05d20684fef4a4d04/protobuf-4.25.5-cp310-abi3-win32.whl", hash = "sha256:5e61fd921603f58d2f5acb2806a929b4675f8874ff5f330b7d6f7e2e784bbcd8", size = 392457, upload-time = "2024-09-18T22:25:26.449Z" },
- { url = "https://files.pythonhosted.org/packages/a7/ad/bf3f358e90b7e70bf7fb520702cb15307ef268262292d3bdb16ad8ebc815/protobuf-4.25.5-cp310-abi3-win_amd64.whl", hash = "sha256:4be0571adcbe712b282a330c6e89eae24281344429ae95c6d85e79e84780f5ea", size = 413449, upload-time = "2024-09-18T22:25:29.409Z" },
- { url = "https://files.pythonhosted.org/packages/51/49/d110f0a43beb365758a252203c43eaaad169fe7749da918869a8c991f726/protobuf-4.25.5-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:b2fde3d805354df675ea4c7c6338c1aecd254dfc9925e88c6d31a2bcb97eb173", size = 394248, upload-time = "2024-09-18T22:25:30.727Z" },
- { url = "https://files.pythonhosted.org/packages/c6/ab/0f384ca0bc6054b1a7b6009000ab75d28a5506e4459378b81280ae7fd358/protobuf-4.25.5-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:919ad92d9b0310070f8356c24b855c98df2b8bd207ebc1c0c6fcc9ab1e007f3d", size = 293717, upload-time = "2024-09-18T22:25:32.023Z" },
- { url = "https://files.pythonhosted.org/packages/05/a6/094a2640be576d760baa34c902dcb8199d89bce9ed7dd7a6af74dcbbd62d/protobuf-4.25.5-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:fe14e16c22be926d3abfcb500e60cab068baf10b542b8c858fa27e098123e331", size = 294635, upload-time = "2024-09-18T22:25:33.49Z" },
- { url = "https://files.pythonhosted.org/packages/33/90/f198a61df8381fb43ae0fe81b3d2718e8dcc51ae8502c7657ab9381fbc4f/protobuf-4.25.5-py3-none-any.whl", hash = "sha256:0aebecb809cae990f8129ada5ca273d9d670b76d9bfc9b1809f0a9c02b7dbf41", size = 156467, upload-time = "2024-09-18T22:25:41.606Z" },
+ { url = "https://files.pythonhosted.org/packages/5f/11/6e40e9fc5bba02988a214c07cf324595789ca7820160bfd1f8be96e48539/protobuf-5.29.5-cp310-abi3-win32.whl", hash = "sha256:3f1c6468a2cfd102ff4703976138844f78ebd1fb45f49011afc5139e9e283079", size = 422963, upload-time = "2025-05-28T23:51:41.204Z" },
+ { url = "https://files.pythonhosted.org/packages/81/7f/73cefb093e1a2a7c3ffd839e6f9fcafb7a427d300c7f8aef9c64405d8ac6/protobuf-5.29.5-cp310-abi3-win_amd64.whl", hash = "sha256:3f76e3a3675b4a4d867b52e4a5f5b78a2ef9565549d4037e06cf7b0942b1d3fc", size = 434818, upload-time = "2025-05-28T23:51:44.297Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/73/10e1661c21f139f2c6ad9b23040ff36fee624310dc28fba20d33fdae124c/protobuf-5.29.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e38c5add5a311f2a6eb0340716ef9b039c1dfa428b28f25a7838ac329204a671", size = 418091, upload-time = "2025-05-28T23:51:45.907Z" },
+ { url = "https://files.pythonhosted.org/packages/6c/04/98f6f8cf5b07ab1294c13f34b4e69b3722bb609c5b701d6c169828f9f8aa/protobuf-5.29.5-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:fa18533a299d7ab6c55a238bf8629311439995f2e7eca5caaff08663606e9015", size = 319824, upload-time = "2025-05-28T23:51:47.545Z" },
+ { url = "https://files.pythonhosted.org/packages/85/e4/07c80521879c2d15f321465ac24c70efe2381378c00bf5e56a0f4fbac8cd/protobuf-5.29.5-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:63848923da3325e1bf7e9003d680ce6e14b07e55d0473253a690c3a8b8fd6e61", size = 319942, upload-time = "2025-05-28T23:51:49.11Z" },
+ { url = "https://files.pythonhosted.org/packages/7e/cc/7e77861000a0691aeea8f4566e5d3aa716f2b1dece4a24439437e41d3d25/protobuf-5.29.5-py3-none-any.whl", hash = "sha256:6cf42630262c59b2d8de33954443d94b746c952b01434fc58a417fdbd2e84bd5", size = 172823, upload-time = "2025-05-28T23:51:58.157Z" },
]
[[package]]
@@ -3466,76 +2917,39 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/7b/d7/7831438e6c3ebbfa6e01a927127a6cb42ad3ab844247f3c5b96bea25d73d/psutil-6.1.1-cp37-abi3-win_amd64.whl", hash = "sha256:f35cfccb065fff93529d2afb4a2e89e363fe63ca1e4a5da22b603a85833c2649", size = 254444, upload-time = "2024-12-19T18:22:11.335Z" },
]
-[[package]]
-name = "psycopg2-binary"
-version = "2.9.9"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/fc/07/e720e53bfab016ebcc34241695ccc06a9e3d91ba19b40ca81317afbdc440/psycopg2-binary-2.9.9.tar.gz", hash = "sha256:7f01846810177d829c7692f1f5ada8096762d9172af1b1a28d4ab5b77c923c1c", size = 384973, upload-time = "2023-10-03T12:48:55.128Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/a5/ac/702d300f3df169b9d0cbef0340d9f34a78bc18dc2dbafbcb39ff0f165cf8/psycopg2_binary-2.9.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ee825e70b1a209475622f7f7b776785bd68f34af6e7a46e2e42f27b659b5bc26", size = 2822581, upload-time = "2023-10-03T12:46:30.64Z" },
- { url = "https://files.pythonhosted.org/packages/7a/1f/a6cf0cdf944253f7c45d90fbc876cc8bed5cc9942349306245715c0d88d6/psycopg2_binary-2.9.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1ea665f8ce695bcc37a90ee52de7a7980be5161375d42a0b6c6abedbf0d81f0f", size = 2552633, upload-time = "2023-10-03T12:46:32.808Z" },
- { url = "https://files.pythonhosted.org/packages/81/0b/3adf561107c865928455891156d1dde5325253f7f4316fe56cd2c3f73570/psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:143072318f793f53819048fdfe30c321890af0c3ec7cb1dfc9cc87aa88241de2", size = 2851075, upload-time = "2023-10-03T12:46:35.138Z" },
- { url = "https://files.pythonhosted.org/packages/f7/98/c2fedcbf0a9607519a010dcf88571138b2251062dbde3610cdba5ba1eee1/psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c332c8d69fb64979ebf76613c66b985414927a40f8defa16cf1bc028b7b0a7b0", size = 3080509, upload-time = "2023-10-03T12:46:37.44Z" },
- { url = "https://files.pythonhosted.org/packages/c2/05/81e8bc7fca95574c9323e487d9ce1b58a4cfcc17f89b8fe843af46361211/psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7fc5a5acafb7d6ccca13bfa8c90f8c51f13d8fb87d95656d3950f0158d3ce53", size = 3264303, upload-time = "2023-10-03T12:46:40.73Z" },
- { url = "https://files.pythonhosted.org/packages/ce/85/62825cabc6aad53104b7b6d12eb2ad74737d268630032d07b74d4444cb72/psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:977646e05232579d2e7b9c59e21dbe5261f403a88417f6a6512e70d3f8a046be", size = 3019515, upload-time = "2023-10-03T12:46:43.038Z" },
- { url = "https://files.pythonhosted.org/packages/e9/b0/9ca2b8e01a0912c9a14234fd5df7a241a1e44778c5797bf4b8eaa8dc3d3a/psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b6356793b84728d9d50ead16ab43c187673831e9d4019013f1402c41b1db9b27", size = 2355892, upload-time = "2023-10-03T12:46:45.632Z" },
- { url = "https://files.pythonhosted.org/packages/73/17/ba28bb0022db5e2015a82d2df1c4b0d419c37fa07a588b3aff3adc4939f6/psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bc7bb56d04601d443f24094e9e31ae6deec9ccb23581f75343feebaf30423359", size = 2534903, upload-time = "2023-10-03T12:46:47.934Z" },
- { url = "https://files.pythonhosted.org/packages/3b/92/b463556409cdc12791cd8b1dae0072bf8efe817ef68b7ea3d9cf7d0e5656/psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:77853062a2c45be16fd6b8d6de2a99278ee1d985a7bd8b103e97e41c034006d2", size = 2486597, upload-time = "2023-10-03T12:46:50.598Z" },
- { url = "https://files.pythonhosted.org/packages/92/57/96576e07132d7f7a1ac1df939575e6fdd8951aea337ee152b586bb51a971/psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:78151aa3ec21dccd5cdef6c74c3e73386dcdfaf19bced944169697d7ac7482fc", size = 2454908, upload-time = "2023-10-03T12:46:52.903Z" },
- { url = "https://files.pythonhosted.org/packages/7c/ae/cedd56e1f4a2b0e37213283caf3733a875c4c76f3372241e19c0d2a87355/psycopg2_binary-2.9.9-cp311-cp311-win32.whl", hash = "sha256:dc4926288b2a3e9fd7b50dc6a1909a13bbdadfc67d93f3374d984e56f885579d", size = 1024240, upload-time = "2023-10-03T12:46:55.009Z" },
- { url = "https://files.pythonhosted.org/packages/25/1f/7ae31759142999a8d06b3e250c1346c4abcdcada8fa884376775dc1de686/psycopg2_binary-2.9.9-cp311-cp311-win_amd64.whl", hash = "sha256:b76bedd166805480ab069612119ea636f5ab8f8771e640ae103e05a4aae3e417", size = 1163655, upload-time = "2023-10-03T12:46:57.038Z" },
- { url = "https://files.pythonhosted.org/packages/a7/d0/5f2db14e7b53552276ab613399a83f83f85b173a862d3f20580bc7231139/psycopg2_binary-2.9.9-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8532fd6e6e2dc57bcb3bc90b079c60de896d2128c5d9d6f24a63875a95a088cf", size = 2823784, upload-time = "2023-10-03T12:47:00.404Z" },
- { url = "https://files.pythonhosted.org/packages/18/ca/da384fd47233e300e3e485c90e7aab5d7def896d1281239f75901faf87d4/psycopg2_binary-2.9.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b0605eaed3eb239e87df0d5e3c6489daae3f7388d455d0c0b4df899519c6a38d", size = 2553308, upload-time = "2023-11-01T10:40:33.984Z" },
- { url = "https://files.pythonhosted.org/packages/50/66/fa53d2d3d92f6e1ef469d92afc6a4fe3f6e8a9a04b687aa28fb1f1d954ee/psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f8544b092a29a6ddd72f3556a9fcf249ec412e10ad28be6a0c0d948924f2212", size = 2851283, upload-time = "2023-10-03T12:47:02.736Z" },
- { url = "https://files.pythonhosted.org/packages/04/37/2429360ac5547378202db14eec0dde76edbe1f6627df5a43c7e164922859/psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2d423c8d8a3c82d08fe8af900ad5b613ce3632a1249fd6a223941d0735fce493", size = 3081839, upload-time = "2023-10-03T12:47:05.027Z" },
- { url = "https://files.pythonhosted.org/packages/62/2a/c0530b59d7e0d09824bc2102ecdcec0456b8ca4d47c0caa82e86fce3ed4c/psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e5afae772c00980525f6d6ecf7cbca55676296b580c0e6abb407f15f3706996", size = 3264488, upload-time = "2023-10-03T12:47:08.962Z" },
- { url = "https://files.pythonhosted.org/packages/19/57/9f172b900795ea37246c78b5f52e00f4779984370855b3e161600156906d/psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e6f98446430fdf41bd36d4faa6cb409f5140c1c2cf58ce0bbdaf16af7d3f119", size = 3020700, upload-time = "2023-10-03T12:47:12.23Z" },
- { url = "https://files.pythonhosted.org/packages/94/68/1176fc14ea76861b7b8360be5176e87fb20d5091b137c76570eb4e237324/psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c77e3d1862452565875eb31bdb45ac62502feabbd53429fdc39a1cc341d681ba", size = 2355968, upload-time = "2023-10-03T12:47:14.817Z" },
- { url = "https://files.pythonhosted.org/packages/70/bb/aec2646a705a09079d008ce88073401cd61fc9b04f92af3eb282caa3a2ec/psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:cb16c65dcb648d0a43a2521f2f0a2300f40639f6f8c1ecbc662141e4e3e1ee07", size = 2536101, upload-time = "2023-10-03T12:47:17.454Z" },
- { url = "https://files.pythonhosted.org/packages/14/33/12818c157e333cb9d9e6753d1b2463b6f60dbc1fade115f8e4dc5c52cac4/psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:911dda9c487075abd54e644ccdf5e5c16773470a6a5d3826fda76699410066fb", size = 2487064, upload-time = "2023-10-03T12:47:20.717Z" },
- { url = "https://files.pythonhosted.org/packages/56/a2/7851c68fe8768f3c9c246198b6356ee3e4a8a7f6820cc798443faada3400/psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:57fede879f08d23c85140a360c6a77709113efd1c993923c59fde17aa27599fe", size = 2456257, upload-time = "2023-10-03T12:47:23.004Z" },
- { url = "https://files.pythonhosted.org/packages/6f/ee/3ba07c6dc7c3294e717e94720da1597aedc82a10b1b180203ce183d4631a/psycopg2_binary-2.9.9-cp312-cp312-win32.whl", hash = "sha256:64cf30263844fa208851ebb13b0732ce674d8ec6a0c86a4e160495d299ba3c93", size = 1024709, upload-time = "2023-10-28T09:37:24.991Z" },
- { url = "https://files.pythonhosted.org/packages/7b/08/9c66c269b0d417a0af9fb969535f0371b8c538633535a7a6a5ca3f9231e2/psycopg2_binary-2.9.9-cp312-cp312-win_amd64.whl", hash = "sha256:81ff62668af011f9a48787564ab7eded4e9fb17a4a6a74af5ffa6a457400d2ab", size = 1163864, upload-time = "2023-10-28T09:37:28.155Z" },
-]
-
-[[package]]
-name = "py-partiql-parser"
-version = "0.6.1"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/58/a1/0a2867e48b232b4f82c4929ef7135f2a5d72c3886b957dccf63c70aa2fcb/py_partiql_parser-0.6.1.tar.gz", hash = "sha256:8583ff2a0e15560ef3bc3df109a7714d17f87d81d33e8c38b7fed4e58a63215d", size = 17120, upload-time = "2024-12-25T22:06:41.327Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/97/84/0e410c20bbe9a504fc56e97908f13261c2b313d16cbb3b738556166f044a/py_partiql_parser-0.6.1-py2.py3-none-any.whl", hash = "sha256:ff6a48067bff23c37e9044021bf1d949c83e195490c17e020715e927fe5b2456", size = 23520, upload-time = "2024-12-25T22:06:39.106Z" },
-]
-
[[package]]
name = "pyarrow"
-version = "19.0.0"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/7b/01/fe1fd04744c2aa038e5a11c7a4adb3d62bce09798695e54f7274b5977134/pyarrow-19.0.0.tar.gz", hash = "sha256:8d47c691765cf497aaeed4954d226568563f1b3b74ff61139f2d77876717084b", size = 1129096, upload-time = "2025-01-16T04:24:25.844Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/82/42/fba3a35bef5833bf88ed35e6a810dc1781236e1d4f808d2df824a7d21819/pyarrow-19.0.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:8e3a839bf36ec03b4315dc924d36dcde5444a50066f1c10f8290293c0427b46a", size = 30711936, upload-time = "2025-01-16T04:20:24.904Z" },
- { url = "https://files.pythonhosted.org/packages/88/7a/0da93a3eaaf251a30e32f3221e874263cdcd366c2cd6b7c05293aad91152/pyarrow-19.0.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:ce42275097512d9e4e4a39aade58ef2b3798a93aa3026566b7892177c266f735", size = 32133182, upload-time = "2025-01-16T04:20:30.315Z" },
- { url = "https://files.pythonhosted.org/packages/2f/df/fe43b1c50d3100d0de53f988344118bc20362d0de005f8a407454fa565f8/pyarrow-19.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9348a0137568c45601b031a8d118275069435f151cbb77e6a08a27e8125f59d4", size = 41145489, upload-time = "2025-01-16T04:20:37.336Z" },
- { url = "https://files.pythonhosted.org/packages/45/bb/6f73b41b342a0342f2516a02db4aa97a4f9569cc35482a5c288090140cd4/pyarrow-19.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a0144a712d990d60f7f42b7a31f0acaccf4c1e43e957f7b1ad58150d6f639c1", size = 42177823, upload-time = "2025-01-16T04:20:44.23Z" },
- { url = "https://files.pythonhosted.org/packages/23/7b/f038a96f421e453a71bd7a0f78d62b1b2ae9bcac06ed51179ca532e6a0a2/pyarrow-19.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:2a1a109dfda558eb011e5f6385837daffd920d54ca00669f7a11132d0b1e6042", size = 40530609, upload-time = "2025-01-16T04:20:52.991Z" },
- { url = "https://files.pythonhosted.org/packages/b8/39/a2a6714b471c000e6dd6af4495dce00d7d1332351b8e3170dfb9f91dad1f/pyarrow-19.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:be686bf625aa7b9bada18defb3a3ea3981c1099697239788ff111d87f04cd263", size = 42081534, upload-time = "2025-01-16T04:21:02.925Z" },
- { url = "https://files.pythonhosted.org/packages/6c/a3/8396fb06ca05d807e89980c177be26617aad15211ece3184e0caa730b8a6/pyarrow-19.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:239ca66d9a05844bdf5af128861af525e14df3c9591bcc05bac25918e650d3a2", size = 25281090, upload-time = "2025-01-16T04:21:09.976Z" },
- { url = "https://files.pythonhosted.org/packages/bc/2e/152885f5ef421e80dae68b9c133ab261934f93a6d5e16b61d79c0ed597fb/pyarrow-19.0.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:a7bbe7109ab6198688b7079cbad5a8c22de4d47c4880d8e4847520a83b0d1b68", size = 30667964, upload-time = "2025-01-16T04:21:15.594Z" },
- { url = "https://files.pythonhosted.org/packages/80/c2/08bbee9a8610a47c9a1466845f405baf53a639ddd947c5133d8ba13544b6/pyarrow-19.0.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:4624c89d6f777c580e8732c27bb8e77fd1433b89707f17c04af7635dd9638351", size = 32125039, upload-time = "2025-01-16T04:21:22.681Z" },
- { url = "https://files.pythonhosted.org/packages/d2/56/06994df823212f5688d3c8bf4294928b12c9be36681872853655724d28c6/pyarrow-19.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b6d3ce4288793350dc2d08d1e184fd70631ea22a4ff9ea5c4ff182130249d9b", size = 41140729, upload-time = "2025-01-16T04:21:31.655Z" },
- { url = "https://files.pythonhosted.org/packages/94/65/38ad577c98140a9db71e9e1e594b6adb58a7478a5afec6456a8ca2df7f70/pyarrow-19.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:450a7d27e840e4d9a384b5c77199d489b401529e75a3b7a3799d4cd7957f2f9c", size = 42202267, upload-time = "2025-01-16T04:21:37.523Z" },
- { url = "https://files.pythonhosted.org/packages/b6/1f/966b722251a7354114ccbb71cf1a83922023e69efd8945ebf628a851ec4c/pyarrow-19.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:a08e2a8a039a3f72afb67a6668180f09fddaa38fe0d21f13212b4aba4b5d2451", size = 40505858, upload-time = "2025-01-16T04:21:43.639Z" },
- { url = "https://files.pythonhosted.org/packages/3b/5e/6bc81aa7fc9affc7d1c03b912fbcc984ca56c2a18513684da267715dab7b/pyarrow-19.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:f43f5aef2a13d4d56adadae5720d1fed4c1356c993eda8b59dace4b5983843c1", size = 42084973, upload-time = "2025-01-16T04:21:52.705Z" },
- { url = "https://files.pythonhosted.org/packages/53/c3/2f56da818b6a4758cbd514957c67bd0f078ebffa5390ee2e2bf0f9e8defc/pyarrow-19.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:2f672f5364b2d7829ef7c94be199bb88bf5661dd485e21d2d37de12ccb78a136", size = 25241976, upload-time = "2025-01-16T04:21:59.088Z" },
+version = "20.0.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/a2/ee/a7810cb9f3d6e9238e61d312076a9859bf3668fd21c69744de9532383912/pyarrow-20.0.0.tar.gz", hash = "sha256:febc4a913592573c8d5805091a6c2b5064c8bd6e002131f01061797d91c783c1", size = 1125187, upload-time = "2025-04-27T12:34:23.264Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/47/a2/b7930824181ceadd0c63c1042d01fa4ef63eee233934826a7a2a9af6e463/pyarrow-20.0.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:24ca380585444cb2a31324c546a9a56abbe87e26069189e14bdba19c86c049f0", size = 30856035, upload-time = "2025-04-27T12:28:40.78Z" },
+ { url = "https://files.pythonhosted.org/packages/9b/18/c765770227d7f5bdfa8a69f64b49194352325c66a5c3bb5e332dfd5867d9/pyarrow-20.0.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:95b330059ddfdc591a3225f2d272123be26c8fa76e8c9ee1a77aad507361cfdb", size = 32309552, upload-time = "2025-04-27T12:28:47.051Z" },
+ { url = "https://files.pythonhosted.org/packages/44/fb/dfb2dfdd3e488bb14f822d7335653092dde150cffc2da97de6e7500681f9/pyarrow-20.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f0fb1041267e9968c6d0d2ce3ff92e3928b243e2b6d11eeb84d9ac547308232", size = 41334704, upload-time = "2025-04-27T12:28:55.064Z" },
+ { url = "https://files.pythonhosted.org/packages/58/0d/08a95878d38808051a953e887332d4a76bc06c6ee04351918ee1155407eb/pyarrow-20.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8ff87cc837601532cc8242d2f7e09b4e02404de1b797aee747dd4ba4bd6313f", size = 42399836, upload-time = "2025-04-27T12:29:02.13Z" },
+ { url = "https://files.pythonhosted.org/packages/f3/cd/efa271234dfe38f0271561086eedcad7bc0f2ddd1efba423916ff0883684/pyarrow-20.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:7a3a5dcf54286e6141d5114522cf31dd67a9e7c9133d150799f30ee302a7a1ab", size = 40711789, upload-time = "2025-04-27T12:29:09.951Z" },
+ { url = "https://files.pythonhosted.org/packages/46/1f/7f02009bc7fc8955c391defee5348f510e589a020e4b40ca05edcb847854/pyarrow-20.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a6ad3e7758ecf559900261a4df985662df54fb7fdb55e8e3b3aa99b23d526b62", size = 42301124, upload-time = "2025-04-27T12:29:17.187Z" },
+ { url = "https://files.pythonhosted.org/packages/4f/92/692c562be4504c262089e86757a9048739fe1acb4024f92d39615e7bab3f/pyarrow-20.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6bb830757103a6cb300a04610e08d9636f0cd223d32f388418ea893a3e655f1c", size = 42916060, upload-time = "2025-04-27T12:29:24.253Z" },
+ { url = "https://files.pythonhosted.org/packages/a4/ec/9f5c7e7c828d8e0a3c7ef50ee62eca38a7de2fa6eb1b8fa43685c9414fef/pyarrow-20.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:96e37f0766ecb4514a899d9a3554fadda770fb57ddf42b63d80f14bc20aa7db3", size = 44547640, upload-time = "2025-04-27T12:29:32.782Z" },
+ { url = "https://files.pythonhosted.org/packages/54/96/46613131b4727f10fd2ffa6d0d6f02efcc09a0e7374eff3b5771548aa95b/pyarrow-20.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:3346babb516f4b6fd790da99b98bed9708e3f02e734c84971faccb20736848dc", size = 25781491, upload-time = "2025-04-27T12:29:38.464Z" },
+ { url = "https://files.pythonhosted.org/packages/a1/d6/0c10e0d54f6c13eb464ee9b67a68b8c71bcf2f67760ef5b6fbcddd2ab05f/pyarrow-20.0.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:75a51a5b0eef32727a247707d4755322cb970be7e935172b6a3a9f9ae98404ba", size = 30815067, upload-time = "2025-04-27T12:29:44.384Z" },
+ { url = "https://files.pythonhosted.org/packages/7e/e2/04e9874abe4094a06fd8b0cbb0f1312d8dd7d707f144c2ec1e5e8f452ffa/pyarrow-20.0.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:211d5e84cecc640c7a3ab900f930aaff5cd2702177e0d562d426fb7c4f737781", size = 32297128, upload-time = "2025-04-27T12:29:52.038Z" },
+ { url = "https://files.pythonhosted.org/packages/31/fd/c565e5dcc906a3b471a83273039cb75cb79aad4a2d4a12f76cc5ae90a4b8/pyarrow-20.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ba3cf4182828be7a896cbd232aa8dd6a31bd1f9e32776cc3796c012855e1199", size = 41334890, upload-time = "2025-04-27T12:29:59.452Z" },
+ { url = "https://files.pythonhosted.org/packages/af/a9/3bdd799e2c9b20c1ea6dc6fa8e83f29480a97711cf806e823f808c2316ac/pyarrow-20.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c3a01f313ffe27ac4126f4c2e5ea0f36a5fc6ab51f8726cf41fee4b256680bd", size = 42421775, upload-time = "2025-04-27T12:30:06.875Z" },
+ { url = "https://files.pythonhosted.org/packages/10/f7/da98ccd86354c332f593218101ae56568d5dcedb460e342000bd89c49cc1/pyarrow-20.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:a2791f69ad72addd33510fec7bb14ee06c2a448e06b649e264c094c5b5f7ce28", size = 40687231, upload-time = "2025-04-27T12:30:13.954Z" },
+ { url = "https://files.pythonhosted.org/packages/bb/1b/2168d6050e52ff1e6cefc61d600723870bf569cbf41d13db939c8cf97a16/pyarrow-20.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:4250e28a22302ce8692d3a0e8ec9d9dde54ec00d237cff4dfa9c1fbf79e472a8", size = 42295639, upload-time = "2025-04-27T12:30:21.949Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/66/2d976c0c7158fd25591c8ca55aee026e6d5745a021915a1835578707feb3/pyarrow-20.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:89e030dc58fc760e4010148e6ff164d2f44441490280ef1e97a542375e41058e", size = 42908549, upload-time = "2025-04-27T12:30:29.551Z" },
+ { url = "https://files.pythonhosted.org/packages/31/a9/dfb999c2fc6911201dcbf348247f9cc382a8990f9ab45c12eabfd7243a38/pyarrow-20.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6102b4864d77102dbbb72965618e204e550135a940c2534711d5ffa787df2a5a", size = 44557216, upload-time = "2025-04-27T12:30:36.977Z" },
+ { url = "https://files.pythonhosted.org/packages/a0/8e/9adee63dfa3911be2382fb4d92e4b2e7d82610f9d9f668493bebaa2af50f/pyarrow-20.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:96d6a0a37d9c98be08f5ed6a10831d88d52cac7b13f5287f1e0f625a0de8062b", size = 25660496, upload-time = "2025-04-27T12:30:42.809Z" },
]
[[package]]
name = "pyasn1"
-version = "0.4.8"
+version = "0.6.1"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/a4/db/fffec68299e6d7bad3d504147f9094830b704527a7fc098b721d38cc7fa7/pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba", size = 146820, upload-time = "2019-11-16T17:27:38.772Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/ba/e9/01f1a64245b89f039897cb0130016d79f77d52669aae6ee7b159a6c4c018/pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034", size = 145322, upload-time = "2024-09-10T22:41:42.55Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/62/1e/a94a8d635fa3ce4cfc7f506003548d0a2447ae76fd5ca53932970fe3053f/pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d", size = 77145, upload-time = "2019-11-16T17:27:11.07Z" },
+ { url = "https://files.pythonhosted.org/packages/c8/f1/d6a797abb14f6283c0ddff96bbdd46937f64122b8c925cab503dd37f8214/pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629", size = 83135, upload-time = "2024-09-11T16:00:36.122Z" },
]
[[package]]
@@ -3550,6 +2964,63 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/77/89/bc88a6711935ba795a679ea6ebee07e128050d6382eaa35a0a47c8032bdc/pyasn1_modules-0.4.1-py3-none-any.whl", hash = "sha256:49bfa96b45a292b711e986f222502c1c9a5e1f4e568fc30e2574a6c7d07838fd", size = 181537, upload-time = "2024-09-11T16:02:10.336Z" },
]
+[[package]]
+name = "pybase64"
+version = "1.4.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/04/14/43297a7b7f0c1bf0c00b596f754ee3ac946128c64d21047ccf9c9bbc5165/pybase64-1.4.2.tar.gz", hash = "sha256:46cdefd283ed9643315d952fe44de80dc9b9a811ce6e3ec97fd1827af97692d0", size = 137246, upload-time = "2025-07-27T13:08:57.808Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/da/fb/edaa56bbf04715efc3c36966cc0150e01d7a8336c3da182f850b7fd43d32/pybase64-1.4.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:26284ef64f142067293347bcc9d501d2b5d44b92eab9d941cb10a085fb01c666", size = 38238, upload-time = "2025-07-27T13:02:44.224Z" },
+ { url = "https://files.pythonhosted.org/packages/28/a4/ca1538e9adf08f5016b3543b0060c18aea9a6e805dd20712a197c509d90d/pybase64-1.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:52dd32fe5cbfd8af8f3f034a4a65ee61948c72e5c358bf69d59543fc0dbcf950", size = 31659, upload-time = "2025-07-27T13:02:45.445Z" },
+ { url = "https://files.pythonhosted.org/packages/0b/8f/f9b49926a60848ba98350dd648227ec524fb78340b47a450c4dbaf24b1bb/pybase64-1.4.2-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:37f133e8c96427995480bb6d396d9d49e949a3e829591845bb6a5a7f215ca177", size = 68318, upload-time = "2025-07-27T13:02:46.644Z" },
+ { url = "https://files.pythonhosted.org/packages/29/9b/6ed2dd2bc8007f33b8316d6366b0901acbdd5665b419c2893b3dd48708de/pybase64-1.4.2-cp311-cp311-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a6ee3874b0abbdd4c903d3989682a3f016fd84188622879f6f95a5dc5718d7e5", size = 71357, upload-time = "2025-07-27T13:02:47.937Z" },
+ { url = "https://files.pythonhosted.org/packages/fb/69/be9ac8127da8d8339db7129683bd2975cecb0bf40a82731e1a492577a177/pybase64-1.4.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5c69f177b1e404b22b05802127d6979acf4cb57f953c7de9472410f9c3fdece7", size = 59817, upload-time = "2025-07-27T13:02:49.163Z" },
+ { url = "https://files.pythonhosted.org/packages/f4/a2/e3e09e000b509609276ee28b71beb0b61462d4a43b3e0db0a44c8652880c/pybase64-1.4.2-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.whl", hash = "sha256:80c817e88ef2ca3cc9a285fde267690a1cb821ce0da4848c921c16f0fec56fda", size = 56639, upload-time = "2025-07-27T13:02:50.384Z" },
+ { url = "https://files.pythonhosted.org/packages/01/70/ad7eff88aa4f1be06db705812e1f01749606933bf8fe9df553bb04b703e6/pybase64-1.4.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:7a4bb6e7e45bfdaea0f2aaf022fc9a013abe6e46ccea31914a77e10f44098688", size = 59368, upload-time = "2025-07-27T13:02:51.883Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/82/0cd1b4bcd2a4da7805cfa04587be783bf9583b34ac16cadc29cf119a4fa2/pybase64-1.4.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:2710a80d41a2b41293cb0e5b84b5464f54aa3f28f7c43de88784d2d9702b8a1c", size = 59981, upload-time = "2025-07-27T13:02:53.16Z" },
+ { url = "https://files.pythonhosted.org/packages/3c/4c/8029a03468307dfaf0f9694d31830487ee43af5f8a73407004907724e8ac/pybase64-1.4.2-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:aa6122c8a81f6597e1c1116511f03ed42cf377c2100fe7debaae7ca62521095a", size = 54908, upload-time = "2025-07-27T13:02:54.363Z" },
+ { url = "https://files.pythonhosted.org/packages/a1/8b/70bd0fe659e242efd0f60895a8ce1fe88e3a4084fd1be368974c561138c9/pybase64-1.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b7e22b02505d64db308e9feeb6cb52f1d554ede5983de0befa59ac2d2ffb6a5f", size = 58650, upload-time = "2025-07-27T13:02:55.905Z" },
+ { url = "https://files.pythonhosted.org/packages/64/ca/9c1d23cbc4b9beac43386a32ad53903c816063cef3f14c10d7c3d6d49a23/pybase64-1.4.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:edfe4a3c8c4007f09591f49b46a89d287ef5e8cd6630339536fe98ff077263c2", size = 52323, upload-time = "2025-07-27T13:02:57.192Z" },
+ { url = "https://files.pythonhosted.org/packages/aa/29/a6292e9047248c8616dc53131a49da6c97a61616f80e1e36c73d7ef895fe/pybase64-1.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b79b4a53dd117ffbd03e96953f2e6bd2827bfe11afeb717ea16d9b0893603077", size = 68979, upload-time = "2025-07-27T13:02:58.594Z" },
+ { url = "https://files.pythonhosted.org/packages/c2/e0/cfec7b948e170395d8e88066e01f50e71195db9837151db10c14965d6222/pybase64-1.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:fd9afa7a61d89d170607faf22287290045757e782089f0357b8f801d228d52c3", size = 58037, upload-time = "2025-07-27T13:02:59.753Z" },
+ { url = "https://files.pythonhosted.org/packages/74/7e/0ac1850198c9c35ef631174009cee576f4d8afff3bf493ce310582976ab4/pybase64-1.4.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:5c17b092e4da677a595178d2db17a5d2fafe5c8e418d46c0c4e4cde5adb8cff3", size = 54416, upload-time = "2025-07-27T13:03:00.978Z" },
+ { url = "https://files.pythonhosted.org/packages/1b/45/b0b037f27e86c50e62d927f0bc1bde8b798dd55ab39197b116702e508d05/pybase64-1.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:120799274cf55f3f5bb8489eaa85142f26170564baafa7cf3e85541c46b6ab13", size = 56257, upload-time = "2025-07-27T13:03:02.201Z" },
+ { url = "https://files.pythonhosted.org/packages/d2/0d/5034598aac56336d88fd5aaf6f34630330643b51d399336b8c788d798fc5/pybase64-1.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:522e4e712686acec2d25de9759dda0b0618cb9f6588523528bc74715c0245c7b", size = 70889, upload-time = "2025-07-27T13:03:03.437Z" },
+ { url = "https://files.pythonhosted.org/packages/8a/3b/0645f21bb08ecf45635b624958b5f9e569069d31ecbf125dc7e0e5b83f60/pybase64-1.4.2-cp311-cp311-win32.whl", hash = "sha256:bfd828792982db8d787515535948c1e340f1819407c8832f94384c0ebeaf9d74", size = 33631, upload-time = "2025-07-27T13:03:05.194Z" },
+ { url = "https://files.pythonhosted.org/packages/8f/08/24f8103c1f19e78761026cdd9f3b3be73239bc19cf5ab6fef0e8042d0bc6/pybase64-1.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:7a9e89d40dbf833af481d1d5f1a44d173c9c4b56a7c8dba98e39a78ee87cfc52", size = 35781, upload-time = "2025-07-27T13:03:06.779Z" },
+ { url = "https://files.pythonhosted.org/packages/66/cd/832fb035a0ea7eb53d776a5cfa961849e22828f6dfdfcdb9eb43ba3c0166/pybase64-1.4.2-cp311-cp311-win_arm64.whl", hash = "sha256:ce5809fa90619b03eab1cd63fec142e6cf1d361731a9b9feacf27df76c833343", size = 30903, upload-time = "2025-07-27T13:03:07.903Z" },
+ { url = "https://files.pythonhosted.org/packages/28/6d/11ede991e800797b9f5ebd528013b34eee5652df93de61ffb24503393fa5/pybase64-1.4.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:db2c75d1388855b5a1015b65096d7dbcc708e7de3245dcbedeb872ec05a09326", size = 38326, upload-time = "2025-07-27T13:03:09.065Z" },
+ { url = "https://files.pythonhosted.org/packages/fe/84/87f1f565f42e2397e2aaa2477c86419f5173c3699881c42325c090982f0a/pybase64-1.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6b621a972a01841368fdb9dedc55fd3c6e0c7217d0505ba3b1ebe95e7ef1b493", size = 31661, upload-time = "2025-07-27T13:03:10.295Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/2a/a24c810e7a61d2cc6f73fe9ee4872a03030887fa8654150901b15f376f65/pybase64-1.4.2-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:f48c32ac6a16cbf57a5a96a073fef6ff7e3526f623cd49faa112b7f9980bafba", size = 68192, upload-time = "2025-07-27T13:03:11.467Z" },
+ { url = "https://files.pythonhosted.org/packages/ee/87/d9baf98cbfc37b8657290ad4421f3a3c36aa0eafe4872c5859cfb52f3448/pybase64-1.4.2-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ace8b23093a6bb862477080d9059b784096ab2f97541e8bfc40d42f062875149", size = 71587, upload-time = "2025-07-27T13:03:12.719Z" },
+ { url = "https://files.pythonhosted.org/packages/0b/89/3df043cc56ef3b91b7aa0c26ae822a2d7ec8da0b0fd7c309c879b0eb5988/pybase64-1.4.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1772c7532a7fb6301baea3dd3e010148dbf70cd1136a83c2f5f91bdc94822145", size = 59910, upload-time = "2025-07-27T13:03:14.266Z" },
+ { url = "https://files.pythonhosted.org/packages/75/4f/6641e9edf37aeb4d4524dc7ba2168eff8d96c90e77f6283c2be3400ab380/pybase64-1.4.2-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.whl", hash = "sha256:f86f7faddcba5cbfea475f8ab96567834c28bf09ca6c7c3d66ee445adac80d8f", size = 56701, upload-time = "2025-07-27T13:03:15.6Z" },
+ { url = "https://files.pythonhosted.org/packages/2d/7f/20d8ac1046f12420a0954a45a13033e75f98aade36eecd00c64e3549b071/pybase64-1.4.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:0b8c8e275b5294089f314814b4a50174ab90af79d6a4850f6ae11261ff6a7372", size = 59288, upload-time = "2025-07-27T13:03:16.823Z" },
+ { url = "https://files.pythonhosted.org/packages/17/ea/9c0ca570e3e50b3c6c3442e280c83b321a0464c86a9db1f982a4ff531550/pybase64-1.4.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:864d85a0470c615807ae8b97d724d068b940a2d10ac13a5f1b9e75a3ce441758", size = 60267, upload-time = "2025-07-27T13:03:18.132Z" },
+ { url = "https://files.pythonhosted.org/packages/f9/ac/46894929d71ccedebbfb0284173b0fea96bc029cd262654ba8451a7035d6/pybase64-1.4.2-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:47254d97ed2d8351e30ecfdb9e2414547f66ba73f8a09f932c9378ff75cd10c5", size = 54801, upload-time = "2025-07-27T13:03:19.669Z" },
+ { url = "https://files.pythonhosted.org/packages/6a/1e/02c95218ea964f0b2469717c2c69b48e63f4ca9f18af01a5b2a29e4c1216/pybase64-1.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:264b65ecc4f0ee73f3298ab83bbd8008f7f9578361b8df5b448f985d8c63e02a", size = 58599, upload-time = "2025-07-27T13:03:20.951Z" },
+ { url = "https://files.pythonhosted.org/packages/15/45/ccc21004930789b8fb439d43e3212a6c260ccddb2bf450c39a20db093f33/pybase64-1.4.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:fbcc2b30cd740c16c9699f596f22c7a9e643591311ae72b1e776f2d539e9dd9d", size = 52388, upload-time = "2025-07-27T13:03:23.064Z" },
+ { url = "https://files.pythonhosted.org/packages/c4/45/22e46e549710c4c237d77785b6fb1bc4c44c288a5c44237ba9daf5c34b82/pybase64-1.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:cda9f79c22d51ee4508f5a43b673565f1d26af4330c99f114e37e3186fdd3607", size = 68802, upload-time = "2025-07-27T13:03:24.673Z" },
+ { url = "https://files.pythonhosted.org/packages/55/0c/232c6261b81296e5593549b36e6e7884a5da008776d12665923446322c36/pybase64-1.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:0c91c6d2a7232e2a1cd10b3b75a8bb657defacd4295a1e5e80455df2dfc84d4f", size = 57841, upload-time = "2025-07-27T13:03:25.948Z" },
+ { url = "https://files.pythonhosted.org/packages/20/8a/b35a615ae6f04550d696bb179c414538b3b477999435fdd4ad75b76139e4/pybase64-1.4.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:a370dea7b1cee2a36a4d5445d4e09cc243816c5bc8def61f602db5a6f5438e52", size = 54320, upload-time = "2025-07-27T13:03:27.495Z" },
+ { url = "https://files.pythonhosted.org/packages/d3/a9/8bd4f9bcc53689f1b457ecefed1eaa080e4949d65a62c31a38b7253d5226/pybase64-1.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9aa4de83f02e462a6f4e066811c71d6af31b52d7484de635582d0e3ec3d6cc3e", size = 56482, upload-time = "2025-07-27T13:03:28.942Z" },
+ { url = "https://files.pythonhosted.org/packages/75/e5/4a7735b54a1191f61c3f5c2952212c85c2d6b06eb5fb3671c7603395f70c/pybase64-1.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83a1c2f9ed00fee8f064d548c8654a480741131f280e5750bb32475b7ec8ee38", size = 70959, upload-time = "2025-07-27T13:03:30.171Z" },
+ { url = "https://files.pythonhosted.org/packages/d3/67/e2b6cb32c782e12304d467418e70da0212567f42bd4d3b5eb1fdf64920ad/pybase64-1.4.2-cp312-cp312-win32.whl", hash = "sha256:a6e5688b18d558e8c6b8701cc8560836c4bbeba61d33c836b4dba56b19423716", size = 33683, upload-time = "2025-07-27T13:03:31.775Z" },
+ { url = "https://files.pythonhosted.org/packages/4f/bc/d5c277496063a09707486180f17abbdbdebbf2f5c4441b20b11d3cb7dc7c/pybase64-1.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:c995d21b8bd08aa179cd7dd4db0695c185486ecc72da1e8f6c37ec86cadb8182", size = 35817, upload-time = "2025-07-27T13:03:32.99Z" },
+ { url = "https://files.pythonhosted.org/packages/e6/69/e4be18ae685acff0ae77f75d4586590f29d2cd187bf603290cf1d635cad4/pybase64-1.4.2-cp312-cp312-win_arm64.whl", hash = "sha256:e254b9258c40509c2ea063a7784f6994988f3f26099d6e08704e3c15dfed9a55", size = 30900, upload-time = "2025-07-27T13:03:34.499Z" },
+ { url = "https://files.pythonhosted.org/packages/32/34/b67371f4fcedd5e2def29b1cf92a4311a72f590c04850f370c75297b48ce/pybase64-1.4.2-graalpy311-graalpy242_311_native-macosx_10_9_x86_64.whl", hash = "sha256:b4eed40a5f1627ee65613a6ac834a33f8ba24066656f569c852f98eb16f6ab5d", size = 38667, upload-time = "2025-07-27T13:07:25.315Z" },
+ { url = "https://files.pythonhosted.org/packages/aa/3e/e57fe09ed1c7e740d21c37023c5f7c8963b4c36380f41d10261cc76f93b4/pybase64-1.4.2-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:57885fa521e9add235af4db13e9e048d3a2934cd27d7c5efac1925e1b4d6538d", size = 32094, upload-time = "2025-07-27T13:07:28.235Z" },
+ { url = "https://files.pythonhosted.org/packages/51/34/f40d3262c3953814b9bcdcf858436bd5bc1133a698be4bcc7ed2a8c0730d/pybase64-1.4.2-graalpy311-graalpy242_311_native-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:eef9255d926c64e2fca021d3aee98023bacb98e1518e5986d6aab04102411b04", size = 43212, upload-time = "2025-07-27T13:07:31.327Z" },
+ { url = "https://files.pythonhosted.org/packages/8c/2a/5e05d25718cb8ffd68bd46553ddfd2b660893d937feda1716b8a3b21fb38/pybase64-1.4.2-graalpy311-graalpy242_311_native-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:89614ea2d2329b6708746c540e0f14d692125df99fb1203ff0de948d9e68dfc9", size = 35789, upload-time = "2025-07-27T13:07:34.026Z" },
+ { url = "https://files.pythonhosted.org/packages/d5/9d/f56c3ee6e94faaae2896ecaf666428330cb24096abf7d2427371bb2b403a/pybase64-1.4.2-graalpy311-graalpy242_311_native-win_amd64.whl", hash = "sha256:e401cecd2d7ddcd558768b2140fd4430746be4d17fb14c99eec9e40789df136d", size = 35861, upload-time = "2025-07-27T13:07:37.099Z" },
+ { url = "https://files.pythonhosted.org/packages/0e/bf/5ebaa2d9ddb5fc506633bc8b820fc27e64da964937fb30929c0367c47d00/pybase64-1.4.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0a5393be20b0705870f5a8969749af84d734c077de80dd7e9f5424a247afa85e", size = 38162, upload-time = "2025-07-27T13:07:58.364Z" },
+ { url = "https://files.pythonhosted.org/packages/25/41/795c5fd6e5571bb675bf9add8a048166dddf8951c2a903fea8557743886b/pybase64-1.4.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:448f0259a2f1a17eb086f70fe2ad9b556edba1fc5bc4e62ce6966179368ee9f8", size = 31452, upload-time = "2025-07-27T13:08:01.259Z" },
+ { url = "https://files.pythonhosted.org/packages/aa/dd/c819003b59b2832256b72ad23cbeadbd95d083ef0318d07149a58b7a88af/pybase64-1.4.2-pp311-pypy311_pp73-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:1159e70cba8e76c3d8f334bd1f8fd52a1bb7384f4c3533831b23ab2df84a6ef3", size = 40668, upload-time = "2025-07-27T13:08:04.176Z" },
+ { url = "https://files.pythonhosted.org/packages/0e/c5/38c6aba28678c4a4db49312a6b8171b93a0ffe9f21362cf4c0f325caa850/pybase64-1.4.2-pp311-pypy311_pp73-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7d943bc5dad8388971494554b97f22ae06a46cc7779ad0de3d4bfdf7d0bbea30", size = 41281, upload-time = "2025-07-27T13:08:07.395Z" },
+ { url = "https://files.pythonhosted.org/packages/e5/23/5927bd9e59714e4e8cefd1d21ccd7216048bb1c6c3e7104b1b200afdc63d/pybase64-1.4.2-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:10b99182c561d86422c5de4265fd1f8f172fb38efaed9d72c71fb31e279a7f94", size = 35433, upload-time = "2025-07-27T13:08:10.551Z" },
+ { url = "https://files.pythonhosted.org/packages/01/0f/fab7ed5bf4926523c3b39f7621cea3e0da43f539fbc2270e042f1afccb79/pybase64-1.4.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:bb082c1114f046e59fcbc4f2be13edc93b36d7b54b58605820605be948f8fdf6", size = 36131, upload-time = "2025-07-27T13:08:13.777Z" },
+]
+
[[package]]
name = "pyclipper"
version = "1.3.0.post6"
@@ -3610,7 +3081,7 @@ wheels = [
[[package]]
name = "pydantic"
-version = "2.11.7"
+version = "2.11.9"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "annotated-types" },
@@ -3618,9 +3089,9 @@ dependencies = [
{ name = "typing-extensions" },
{ name = "typing-inspection" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350, upload-time = "2025-06-14T08:33:17.137Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/ff/5d/09a551ba512d7ca404d785072700d3f6727a02f6f3c24ecfd081c7cf0aa8/pydantic-2.11.9.tar.gz", hash = "sha256:6b8ffda597a14812a7975c90b82a8a2e777d9257aba3453f973acd3c032a18e2", size = 788495, upload-time = "2025-09-13T11:26:39.325Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782, upload-time = "2025-06-14T08:33:14.905Z" },
+ { url = "https://files.pythonhosted.org/packages/3e/d3/108f2006987c58e76691d5ae5d200dd3e0f532cb4e5fa3560751c3a1feba/pydantic-2.11.9-py3-none-any.whl", hash = "sha256:c42dd626f5cfc1c6950ce6205ea58c93efa406da65f479dcb4029d5934857da2", size = 444855, upload-time = "2025-09-13T11:26:36.909Z" },
]
[[package]]
@@ -3673,15 +3144,16 @@ wheels = [
[[package]]
name = "pydantic-settings"
-version = "2.7.1"
+version = "2.12.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pydantic" },
{ name = "python-dotenv" },
+ { name = "typing-inspection" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/73/7b/c58a586cd7d9ac66d2ee4ba60ca2d241fa837c02bca9bea80a9a8c3d22a9/pydantic_settings-2.7.1.tar.gz", hash = "sha256:10c9caad35e64bfb3c2fbf70a078c0e25cc92499782e5200747f942a065dec93", size = 79920, upload-time = "2024-12-31T11:27:44.632Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/43/4b/ac7e0aae12027748076d72a8764ff1c9d82ca75a7a52622e67ed3f765c54/pydantic_settings-2.12.0.tar.gz", hash = "sha256:005538ef951e3c2a68e1c08b292b5f2e71490def8589d4221b95dab00dafcfd0", size = 194184, upload-time = "2025-11-10T14:25:47.013Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/b4/46/93416fdae86d40879714f72956ac14df9c7b76f7d41a4d68aa9f71a0028b/pydantic_settings-2.7.1-py3-none-any.whl", hash = "sha256:590be9e6e24d06db33a4262829edef682500ef008565a969c73d39d5f8bfb3fd", size = 29718, upload-time = "2024-12-31T11:27:43.201Z" },
+ { url = "https://files.pythonhosted.org/packages/c1/60/5d4751ba3f4a40a6891f24eec885f51afd78d208498268c734e256fb13c4/pydantic_settings-2.12.0-py3-none-any.whl", hash = "sha256:fddb9fd99a5b18da837b29710391e945b1e30c135477f484084ee513adb93809", size = 51880, upload-time = "2025-11-10T14:25:45.546Z" },
]
[[package]]
@@ -3693,18 +3165,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/a6/53/d78dc063216e62fc55f6b2eebb447f6a4b0a59f55c8406376f76bf959b08/pydub-0.25.1-py2.py3-none-any.whl", hash = "sha256:65617e33033874b59d87db603aa1ed450633288aefead953b30bded59cb599a6", size = 32327, upload-time = "2021-03-10T02:09:53.503Z" },
]
-[[package]]
-name = "pyee"
-version = "12.0.0"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "typing-extensions" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/d2/a7/8faaa62a488a2a1e0d56969757f087cbd2729e9bcfa508c230299f366b4c/pyee-12.0.0.tar.gz", hash = "sha256:c480603f4aa2927d4766eb41fa82793fe60a82cbfdb8d688e0d08c55a534e145", size = 29675, upload-time = "2024-08-30T19:40:43.555Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/1d/0d/95993c08c721ec68892547f2117e8f9dfbcef2ca71e098533541b4a54d5f/pyee-12.0.0-py3-none-any.whl", hash = "sha256:7b14b74320600049ccc7d0e0b1becd3b4bd0a03c745758225e31a59f4095c990", size = 14831, upload-time = "2024-08-30T19:40:42.132Z" },
-]
-
[[package]]
name = "pygments"
version = "2.19.1"
@@ -3741,53 +3201,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/e7/a3/61527d80d84e9fd4d97649322e83bd7efde8200fc07fe34469c8c2bd0d91/pymdown_extensions-10.14.2-py3-none-any.whl", hash = "sha256:f45bc5892410e54fd738ab8ccd736098b7ff0cb27fdb4bf24d0a0c6584bc90e1", size = 264459, upload-time = "2025-01-29T02:56:34.421Z" },
]
-[[package]]
-name = "pymilvus"
-version = "2.5.0"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "grpcio" },
- { name = "milvus-lite", marker = "sys_platform != 'win32'" },
- { name = "pandas" },
- { name = "protobuf" },
- { name = "python-dotenv" },
- { name = "setuptools" },
- { name = "ujson" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/f7/3d/e6b593cf456e4300e3aa58b76e55f392166c5df2ea3605666ad6200503fb/pymilvus-2.5.0.tar.gz", hash = "sha256:4da14a3bd957a4921166f9355fd1f1ac5c5e4e80b46f12f64d9c9a6dcb8cb395", size = 1238729, upload-time = "2024-11-26T08:10:27.752Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/01/f1/76af6c8e1481879f5e0c0d885ab899ab8869fd939b27ac7a0b6c3b3b4ebe/pymilvus-2.5.0-py3-none-any.whl", hash = "sha256:a0e8653d8fe78019abfda79b3404ef7423f312501e8cbd7dc728051ce8732652", size = 212848, upload-time = "2024-11-26T08:10:25.953Z" },
-]
-
-[[package]]
-name = "pymongo"
-version = "4.10.1"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "dnspython" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/1a/35/b62a3139f908c68b69aac6a6a3f8cc146869de0a7929b994600e2c587c77/pymongo-4.10.1.tar.gz", hash = "sha256:a9de02be53b6bb98efe0b9eda84ffa1ec027fcb23a2de62c4f941d9a2f2f3330", size = 1903902, upload-time = "2024-10-01T23:07:58.525Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/e4/a3/d6403ec53fa2fe922b4a5c86388ea5fada01dd51d803e17bb2a7c9cda839/pymongo-4.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:57ee6becae534e6d47848c97f6a6dff69e3cce7c70648d6049bd586764febe59", size = 889238, upload-time = "2024-10-01T23:06:36.03Z" },
- { url = "https://files.pythonhosted.org/packages/29/a2/9643450424bcf241e80bb713497ec2e3273c183d548b4eca357f75d71885/pymongo-4.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6f437a612f4d4f7aca1812311b1e84477145e950fdafe3285b687ab8c52541f3", size = 889504, upload-time = "2024-10-01T23:06:37.328Z" },
- { url = "https://files.pythonhosted.org/packages/ec/40/4759984f34415509e9111be8ee863034611affdc1e0b41016c9d53b2f1b3/pymongo-4.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a970fd3117ab40a4001c3dad333bbf3c43687d90f35287a6237149b5ccae61d", size = 1649069, upload-time = "2024-10-01T23:06:38.553Z" },
- { url = "https://files.pythonhosted.org/packages/56/0f/b6e917478a3ada81e768475516cd544982cc42cbb7d3be325182768139e1/pymongo-4.10.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7c4d0e7cd08ef9f8fbf2d15ba281ed55604368a32752e476250724c3ce36c72e", size = 1714927, upload-time = "2024-10-01T23:06:40.292Z" },
- { url = "https://files.pythonhosted.org/packages/56/c5/4237d94dfa19ebdf9a92b1071e2139c91f48908c5782e592c571c33b67ab/pymongo-4.10.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca6f700cff6833de4872a4e738f43123db34400173558b558ae079b5535857a4", size = 1683454, upload-time = "2024-10-01T23:06:42.257Z" },
- { url = "https://files.pythonhosted.org/packages/9a/16/dbffca9d4ad66f2a325c280f1177912fa23235987f7b9033e283da889b7a/pymongo-4.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cec237c305fcbeef75c0bcbe9d223d1e22a6e3ba1b53b2f0b79d3d29c742b45b", size = 1653840, upload-time = "2024-10-01T23:06:43.991Z" },
- { url = "https://files.pythonhosted.org/packages/2b/4d/21df934ef5cf8f0e587bac922a129e13d4c0346c54e9bf2371b90dd31112/pymongo-4.10.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3337804ea0394a06e916add4e5fac1c89902f1b6f33936074a12505cab4ff05", size = 1613233, upload-time = "2024-10-01T23:06:46.113Z" },
- { url = "https://files.pythonhosted.org/packages/24/07/dd9c3db30e754680606295d5574521956898005db0629411a89163cc6eee/pymongo-4.10.1-cp311-cp311-win32.whl", hash = "sha256:778ac646ce6ac1e469664062dfe9ae1f5c9961f7790682809f5ec3b8fda29d65", size = 857331, upload-time = "2024-10-01T23:06:47.812Z" },
- { url = "https://files.pythonhosted.org/packages/02/68/b71c4106d03eef2482eade440c6f5737c2a4a42f6155726009f80ea38d06/pymongo-4.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:9df4ab5594fdd208dcba81be815fa8a8a5d8dedaf3b346cbf8b61c7296246a7a", size = 876473, upload-time = "2024-10-01T23:06:49.201Z" },
- { url = "https://files.pythonhosted.org/packages/10/d1/60ad99fe3f64d45e6c71ac0e3078e88d9b64112b1bae571fc3707344d6d1/pymongo-4.10.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fbedc4617faa0edf423621bb0b3b8707836687161210d470e69a4184be9ca011", size = 943356, upload-time = "2024-10-01T23:06:50.9Z" },
- { url = "https://files.pythonhosted.org/packages/ca/9b/21d4c6b4ee9c1fa9691c68dc2a52565e0acb644b9e95148569b4736a4ebd/pymongo-4.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7bd26b2aec8ceeb95a5d948d5cc0f62b0eb6d66f3f4230705c1e3d3d2c04ec76", size = 943142, upload-time = "2024-10-01T23:06:52.146Z" },
- { url = "https://files.pythonhosted.org/packages/07/af/691b7454e219a8eb2d1641aecedd607e3a94b93650c2011ad8a8fd74ef9f/pymongo-4.10.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb104c3c2a78d9d85571c8ac90ec4f95bca9b297c6eee5ada71fabf1129e1674", size = 1909129, upload-time = "2024-10-01T23:06:53.551Z" },
- { url = "https://files.pythonhosted.org/packages/0c/74/fd75d5ad4181d6e71ce0fca32404fb71b5046ac84d9a1a2f0862262dd032/pymongo-4.10.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4924355245a9c79f77b5cda2db36e0f75ece5faf9f84d16014c0a297f6d66786", size = 1987763, upload-time = "2024-10-01T23:06:55.304Z" },
- { url = "https://files.pythonhosted.org/packages/8a/56/6d3d0ef63c6d8cb98c7c653a3a2e617675f77a95f3853851d17a7664876a/pymongo-4.10.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:11280809e5dacaef4971113f0b4ff4696ee94cfdb720019ff4fa4f9635138252", size = 1950821, upload-time = "2024-10-01T23:06:57.541Z" },
- { url = "https://files.pythonhosted.org/packages/70/ed/1603fa0c0e51444752c3fa91f16c3a97e6d92eb9fe5e553dae4f18df16f6/pymongo-4.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5d55f2a82e5eb23795f724991cac2bffbb1c0f219c0ba3bf73a835f97f1bb2e", size = 1912247, upload-time = "2024-10-01T23:06:59.023Z" },
- { url = "https://files.pythonhosted.org/packages/c1/66/e98b2308971d45667cb8179d4d66deca47336c90663a7e0527589f1038b7/pymongo-4.10.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e974ab16a60be71a8dfad4e5afccf8dd05d41c758060f5d5bda9a758605d9a5d", size = 1862230, upload-time = "2024-10-01T23:07:01.407Z" },
- { url = "https://files.pythonhosted.org/packages/6c/80/ba9b7ed212a5f8cf8ad7037ed5bbebc1c587fc09242108f153776e4a338b/pymongo-4.10.1-cp312-cp312-win32.whl", hash = "sha256:544890085d9641f271d4f7a47684450ed4a7344d6b72d5968bfae32203b1bb7c", size = 903045, upload-time = "2024-10-01T23:07:02.973Z" },
- { url = "https://files.pythonhosted.org/packages/76/8b/5afce891d78159912c43726fab32641e3f9718f14be40f978c148ea8db48/pymongo-4.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:dcc07b1277e8b4bf4d7382ca133850e323b7ab048b8353af496d050671c7ac52", size = 926686, upload-time = "2024-10-01T23:07:04.403Z" },
-]
-
[[package]]
name = "pymysql"
version = "1.1.1"
@@ -3817,11 +3230,11 @@ wheels = [
[[package]]
name = "pypdf"
-version = "4.3.1"
+version = "6.0.0"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/f0/65/2ed7c9e1d31d860f096061b3dd2d665f501e09faaa0409a3f0d719d2a16d/pypdf-4.3.1.tar.gz", hash = "sha256:b2f37fe9a3030aa97ca86067a56ba3f9d3565f9a791b305c7355d8392c30d91b", size = 293266, upload-time = "2024-07-21T19:35:20.207Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/20/ac/a300a03c3b34967c050677ccb16e7a4b65607ee5df9d51e8b6d713de4098/pypdf-6.0.0.tar.gz", hash = "sha256:282a99d2cc94a84a3a3159f0d9358c0af53f85b4d28d76ea38b96e9e5ac2a08d", size = 5033827, upload-time = "2025-08-11T14:22:02.352Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/3c/60/eccdd92dd4af3e4bea6d6a342f7588c618a15b9bec4b968af581e498bcc4/pypdf-4.3.1-py3-none-any.whl", hash = "sha256:64b31da97eda0771ef22edb1bfecd5deee4b72c3d1736b7df2689805076d6418", size = 295825, upload-time = "2024-07-21T19:35:18.126Z" },
+ { url = "https://files.pythonhosted.org/packages/2c/83/2cacc506eb322bb31b747bc06ccb82cc9aa03e19ee9c1245e538e49d52be/pypdf-6.0.0-py3-none-any.whl", hash = "sha256:56ea60100ce9f11fc3eec4f359da15e9aec3821b036c1f06d2b660d35683abb8", size = 310465, upload-time = "2025-08-11T14:22:00.481Z" },
]
[[package]]
@@ -3875,19 +3288,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/30/05/ce271016e351fddc8399e546f6e23761967ee09c8c568bbfbecb0c150171/pytest_asyncio-1.0.0-py3-none-any.whl", hash = "sha256:4f024da9f1ef945e680dc68610b52550e36590a67fd31bb3b4943979a1f90ef3", size = 15976, upload-time = "2025-05-26T04:54:39.035Z" },
]
-[[package]]
-name = "pytest-docker"
-version = "3.1.1"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "attrs" },
- { name = "pytest" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/e7/a6/543f2fb157ad228fcc04a8974aa16c989058834d8e539608814cf722f1b3/pytest-docker-3.1.1.tar.gz", hash = "sha256:2371524804a752aaa766c79b9eee8e634534afddb82597f3b573da7c5d6ffb5f", size = 12918, upload-time = "2024-02-02T09:18:11.74Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/1a/a4/69defc13bf77ee5aeb3e7b7c45393d6c7312e9c4d8b55d280a094ff76ff3/pytest_docker-3.1.1-py3-none-any.whl", hash = "sha256:fd0d48d6feac41f62acbc758319215ec9bb805c2309622afb07c27fa5c5ae362", size = 8243, upload-time = "2024-02-02T09:18:10.61Z" },
-]
-
[[package]]
name = "python-dateutil"
version = "2.9.0.post0"
@@ -3932,16 +3332,16 @@ wheels = [
[[package]]
name = "python-jose"
-version = "3.4.0"
+version = "3.5.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "ecdsa" },
{ name = "pyasn1" },
{ name = "rsa" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/8e/a0/c49687cf40cb6128ea4e0559855aff92cd5ebd1a60a31c08526818c0e51e/python-jose-3.4.0.tar.gz", hash = "sha256:9a9a40f418ced8ecaf7e3b28d69887ceaa76adad3bcaa6dae0d9e596fec1d680", size = 92145, upload-time = "2025-02-18T17:26:41.985Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/c6/77/3a1c9039db7124eb039772b935f2244fbb73fc8ee65b9acf2375da1c07bf/python_jose-3.5.0.tar.gz", hash = "sha256:fb4eaa44dbeb1c26dcc69e4bd7ec54a1cb8dd64d3b4d81ef08d90ff453f2b01b", size = 92726, upload-time = "2025-05-28T17:31:54.288Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/63/b0/2586ea6b6fd57a994ece0b56418cbe93fff0efb85e2c9eb6b0caf24a4e37/python_jose-3.4.0-py2.py3-none-any.whl", hash = "sha256:9c9f616819652d109bd889ecd1e15e9a162b9b94d682534c9c2146092945b78f", size = 34616, upload-time = "2025-02-18T17:26:40.826Z" },
+ { url = "https://files.pythonhosted.org/packages/d9/c3/0bd11992072e6a1c513b16500a5d07f91a24017c5909b02c72c62d7ad024/python_jose-3.5.0-py2.py3-none-any.whl", hash = "sha256:abd1202f23d34dfad2c3d28cb8617b90acf34132c7afd60abd0b0b7d3cb55771", size = 34624, upload-time = "2025-05-28T17:31:52.802Z" },
]
[[package]]
@@ -4004,6 +3404,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/3c/32/b4fb8585d1be0f68bde7e110dffbcf354915f77ad8c778563f0ad9655c02/python_socketio-5.13.0-py3-none-any.whl", hash = "sha256:51f68d6499f2df8524668c24bcec13ba1414117cfb3a90115c559b601ab10caf", size = 77800, upload-time = "2025-04-12T15:46:58.412Z" },
]
+[[package]]
+name = "pytokens"
+version = "0.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/4e/8d/a762be14dae1c3bf280202ba3172020b2b0b4c537f94427435f19c413b72/pytokens-0.3.0.tar.gz", hash = "sha256:2f932b14ed08de5fcf0b391ace2642f858f1394c0857202959000b68ed7a458a", size = 17644, upload-time = "2025-11-05T13:36:35.34Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/84/25/d9db8be44e205a124f6c98bc0324b2bb149b7431c53877fc6d1038dddaf5/pytokens-0.3.0-py3-none-any.whl", hash = "sha256:95b2b5eaf832e469d141a378872480ede3f251a5a5041b8ec6e581d3ac71bbf3", size = 12195, upload-time = "2025-11-05T13:36:33.183Z" },
+]
+
[[package]]
name = "pytube"
version = "15.0.0"
@@ -4024,15 +3433,15 @@ wheels = [
[[package]]
name = "pywin32"
-version = "308"
+version = "311"
source = { registry = "https://pypi.org/simple" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/eb/e2/02652007469263fe1466e98439831d65d4ca80ea1a2df29abecedf7e47b7/pywin32-308-cp311-cp311-win32.whl", hash = "sha256:5d8c8015b24a7d6855b1550d8e660d8daa09983c80e5daf89a273e5c6fb5095a", size = 5928156, upload-time = "2024-10-12T20:42:05.78Z" },
- { url = "https://files.pythonhosted.org/packages/48/ef/f4fb45e2196bc7ffe09cad0542d9aff66b0e33f6c0954b43e49c33cad7bd/pywin32-308-cp311-cp311-win_amd64.whl", hash = "sha256:575621b90f0dc2695fec346b2d6302faebd4f0f45c05ea29404cefe35d89442b", size = 6559559, upload-time = "2024-10-12T20:42:07.644Z" },
- { url = "https://files.pythonhosted.org/packages/79/ef/68bb6aa865c5c9b11a35771329e95917b5559845bd75b65549407f9fc6b4/pywin32-308-cp311-cp311-win_arm64.whl", hash = "sha256:100a5442b7332070983c4cd03f2e906a5648a5104b8a7f50175f7906efd16bb6", size = 7972495, upload-time = "2024-10-12T20:42:09.803Z" },
- { url = "https://files.pythonhosted.org/packages/00/7c/d00d6bdd96de4344e06c4afbf218bc86b54436a94c01c71a8701f613aa56/pywin32-308-cp312-cp312-win32.whl", hash = "sha256:587f3e19696f4bf96fde9d8a57cec74a57021ad5f204c9e627e15c33ff568897", size = 5939729, upload-time = "2024-10-12T20:42:12.001Z" },
- { url = "https://files.pythonhosted.org/packages/21/27/0c8811fbc3ca188f93b5354e7c286eb91f80a53afa4e11007ef661afa746/pywin32-308-cp312-cp312-win_amd64.whl", hash = "sha256:00b3e11ef09ede56c6a43c71f2d31857cf7c54b0ab6e78ac659497abd2834f47", size = 6543015, upload-time = "2024-10-12T20:42:14.044Z" },
- { url = "https://files.pythonhosted.org/packages/9d/0f/d40f8373608caed2255781a3ad9a51d03a594a1248cd632d6a298daca693/pywin32-308-cp312-cp312-win_arm64.whl", hash = "sha256:9b4de86c8d909aed15b7011182c8cab38c8850de36e6afb1f0db22b8959e3091", size = 7976033, upload-time = "2024-10-12T20:42:16.215Z" },
+ { url = "https://files.pythonhosted.org/packages/7c/af/449a6a91e5d6db51420875c54f6aff7c97a86a3b13a0b4f1a5c13b988de3/pywin32-311-cp311-cp311-win32.whl", hash = "sha256:184eb5e436dea364dcd3d2316d577d625c0351bf237c4e9a5fabbcfa5a58b151", size = 8697031, upload-time = "2025-07-14T20:13:13.266Z" },
+ { url = "https://files.pythonhosted.org/packages/51/8f/9bb81dd5bb77d22243d33c8397f09377056d5c687aa6d4042bea7fbf8364/pywin32-311-cp311-cp311-win_amd64.whl", hash = "sha256:3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503", size = 9508308, upload-time = "2025-07-14T20:13:15.147Z" },
+ { url = "https://files.pythonhosted.org/packages/44/7b/9c2ab54f74a138c491aba1b1cd0795ba61f144c711daea84a88b63dc0f6c/pywin32-311-cp311-cp311-win_arm64.whl", hash = "sha256:a733f1388e1a842abb67ffa8e7aad0e70ac519e09b0f6a784e65a136ec7cefd2", size = 8703930, upload-time = "2025-07-14T20:13:16.945Z" },
+ { url = "https://files.pythonhosted.org/packages/e7/ab/01ea1943d4eba0f850c3c61e78e8dd59757ff815ff3ccd0a84de5f541f42/pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31", size = 8706543, upload-time = "2025-07-14T20:13:20.765Z" },
+ { url = "https://files.pythonhosted.org/packages/d1/a8/a0e8d07d4d051ec7502cd58b291ec98dcc0c3fff027caad0470b72cfcc2f/pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067", size = 9495040, upload-time = "2025-07-14T20:13:22.543Z" },
+ { url = "https://files.pythonhosted.org/packages/ba/3a/2ae996277b4b50f17d61f0603efd8253cb2d79cc7ae159468007b586396d/pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852", size = 8710102, upload-time = "2025-07-14T20:13:24.682Z" },
]
[[package]]
@@ -4070,24 +3479,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338, upload-time = "2024-08-06T20:32:41.93Z" },
]
-[[package]]
-name = "qdrant-client"
-version = "1.14.3"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "grpcio" },
- { name = "httpx", extra = ["http2"] },
- { name = "numpy" },
- { name = "portalocker" },
- { name = "protobuf" },
- { name = "pydantic" },
- { name = "urllib3" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/1d/56/3f355f931c239c260b4fe3bd6433ec6c9e6185cd5ae0970fe89d0ca6daee/qdrant_client-1.14.3.tar.gz", hash = "sha256:bb899e3e065b79c04f5e47053d59176150c0a5dabc09d7f476c8ce8e52f4d281", size = 286766, upload-time = "2025-06-16T11:13:47.838Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/35/5e/8174c845707e60b60b65c58f01e40bbc1d8181b5ff6463f25df470509917/qdrant_client-1.14.3-py3-none-any.whl", hash = "sha256:66faaeae00f9b5326946851fe4ca4ddb1ad226490712e2f05142266f68dfc04d", size = 328969, upload-time = "2025-06-16T11:13:46.636Z" },
-]
-
[[package]]
name = "rank-bm25"
version = "0.2.2"
@@ -4169,6 +3560,20 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/3c/5f/fa26b9b2672cbe30e07d9a5bdf39cf16e3b80b42916757c5f92bca88e4ba/redis-5.2.1-py3-none-any.whl", hash = "sha256:ee7e1056b9aea0f04c6c2ed59452947f34c4940ee025f5dd83e6a6418b6989e4", size = 261502, upload-time = "2024-12-06T09:50:39.656Z" },
]
+[[package]]
+name = "referencing"
+version = "0.37.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "attrs" },
+ { name = "rpds-py" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" },
+]
+
[[package]]
name = "regex"
version = "2024.11.6"
@@ -4209,7 +3614,7 @@ wheels = [
[[package]]
name = "requests"
-version = "2.32.4"
+version = "2.32.5"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "certifi" },
@@ -4217,9 +3622,9 @@ dependencies = [
{ name = "idna" },
{ name = "urllib3" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258, upload-time = "2025-06-09T16:43:07.34Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" },
]
[[package]]
@@ -4247,20 +3652,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481, upload-time = "2023-05-01T04:11:28.427Z" },
]
-[[package]]
-name = "responses"
-version = "0.25.6"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "pyyaml" },
- { name = "requests" },
- { name = "urllib3" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/97/63/759996eea0f17e8dc4c9ea9c60765292d28a7750bdbee073ad55d83caa57/responses-0.25.6.tar.gz", hash = "sha256:eae7ce61a9603004e76c05691e7c389e59652d91e94b419623c12bbfb8e331d8", size = 79145, upload-time = "2025-01-13T21:04:27.895Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/92/c4/8d23584b3a3471ea6f5a18cfb035e11eeb9fa9b3112d901477c6ad10cc4e/responses-0.25.6-py3-none-any.whl", hash = "sha256:9cac8f21e1193bb150ec557875377e41ed56248aed94e4567ed644db564bacf1", size = 34730, upload-time = "2025-01-13T21:04:24.895Z" },
-]
-
[[package]]
name = "restrictedpython"
version = "8.0"
@@ -4283,6 +3674,56 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424, upload-time = "2024-11-01T16:43:55.817Z" },
]
+[[package]]
+name = "rpds-py"
+version = "0.28.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/48/dc/95f074d43452b3ef5d06276696ece4b3b5d696e7c9ad7173c54b1390cd70/rpds_py-0.28.0.tar.gz", hash = "sha256:abd4df20485a0983e2ca334a216249b6186d6e3c1627e106651943dbdb791aea", size = 27419, upload-time = "2025-10-22T22:24:29.327Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a6/34/058d0db5471c6be7bef82487ad5021ff8d1d1d27794be8730aad938649cf/rpds_py-0.28.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:03065002fd2e287725d95fbc69688e0c6daf6c6314ba38bdbaa3895418e09296", size = 362344, upload-time = "2025-10-22T22:21:39.713Z" },
+ { url = "https://files.pythonhosted.org/packages/5d/67/9503f0ec8c055a0782880f300c50a2b8e5e72eb1f94dfc2053da527444dd/rpds_py-0.28.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:28ea02215f262b6d078daec0b45344c89e161eab9526b0d898221d96fdda5f27", size = 348440, upload-time = "2025-10-22T22:21:41.056Z" },
+ { url = "https://files.pythonhosted.org/packages/68/2e/94223ee9b32332a41d75b6f94b37b4ce3e93878a556fc5f152cbd856a81f/rpds_py-0.28.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25dbade8fbf30bcc551cb352376c0ad64b067e4fc56f90e22ba70c3ce205988c", size = 379068, upload-time = "2025-10-22T22:21:42.593Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/25/54fd48f9f680cfc44e6a7f39a5fadf1d4a4a1fd0848076af4a43e79f998c/rpds_py-0.28.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c03002f54cc855860bfdc3442928ffdca9081e73b5b382ed0b9e8efe6e5e205", size = 390518, upload-time = "2025-10-22T22:21:43.998Z" },
+ { url = "https://files.pythonhosted.org/packages/1b/85/ac258c9c27f2ccb1bd5d0697e53a82ebcf8088e3186d5d2bf8498ee7ed44/rpds_py-0.28.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9699fa7990368b22032baf2b2dce1f634388e4ffc03dfefaaac79f4695edc95", size = 525319, upload-time = "2025-10-22T22:21:45.645Z" },
+ { url = "https://files.pythonhosted.org/packages/40/cb/c6734774789566d46775f193964b76627cd5f42ecf246d257ce84d1912ed/rpds_py-0.28.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9b06fe1a75e05e0713f06ea0c89ecb6452210fd60e2f1b6ddc1067b990e08d9", size = 404896, upload-time = "2025-10-22T22:21:47.544Z" },
+ { url = "https://files.pythonhosted.org/packages/1f/53/14e37ce83202c632c89b0691185dca9532288ff9d390eacae3d2ff771bae/rpds_py-0.28.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac9f83e7b326a3f9ec3ef84cda98fb0a74c7159f33e692032233046e7fd15da2", size = 382862, upload-time = "2025-10-22T22:21:49.176Z" },
+ { url = "https://files.pythonhosted.org/packages/6a/83/f3642483ca971a54d60caa4449f9d6d4dbb56a53e0072d0deff51b38af74/rpds_py-0.28.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:0d3259ea9ad8743a75a43eb7819324cdab393263c91be86e2d1901ee65c314e0", size = 398848, upload-time = "2025-10-22T22:21:51.024Z" },
+ { url = "https://files.pythonhosted.org/packages/44/09/2d9c8b2f88e399b4cfe86efdf2935feaf0394e4f14ab30c6c5945d60af7d/rpds_py-0.28.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a7548b345f66f6695943b4ef6afe33ccd3f1b638bd9afd0f730dd255c249c9e", size = 412030, upload-time = "2025-10-22T22:21:52.665Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/f5/e1cec473d4bde6df1fd3738be8e82d64dd0600868e76e92dfeaebbc2d18f/rpds_py-0.28.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c9a40040aa388b037eb39416710fbcce9443498d2eaab0b9b45ae988b53f5c67", size = 559700, upload-time = "2025-10-22T22:21:54.123Z" },
+ { url = "https://files.pythonhosted.org/packages/8d/be/73bb241c1649edbf14e98e9e78899c2c5e52bbe47cb64811f44d2cc11808/rpds_py-0.28.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8f60c7ea34e78c199acd0d3cda37a99be2c861dd2b8cf67399784f70c9f8e57d", size = 584581, upload-time = "2025-10-22T22:21:56.102Z" },
+ { url = "https://files.pythonhosted.org/packages/9c/9c/ffc6e9218cd1eb5c2c7dbd276c87cd10e8c2232c456b554169eb363381df/rpds_py-0.28.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1571ae4292649100d743b26d5f9c63503bb1fedf538a8f29a98dce2d5ba6b4e6", size = 549981, upload-time = "2025-10-22T22:21:58.253Z" },
+ { url = "https://files.pythonhosted.org/packages/5f/50/da8b6d33803a94df0149345ee33e5d91ed4d25fc6517de6a25587eae4133/rpds_py-0.28.0-cp311-cp311-win32.whl", hash = "sha256:5cfa9af45e7c1140af7321fa0bef25b386ee9faa8928c80dc3a5360971a29e8c", size = 214729, upload-time = "2025-10-22T22:21:59.625Z" },
+ { url = "https://files.pythonhosted.org/packages/12/fd/b0f48c4c320ee24c8c20df8b44acffb7353991ddf688af01eef5f93d7018/rpds_py-0.28.0-cp311-cp311-win_amd64.whl", hash = "sha256:dd8d86b5d29d1b74100982424ba53e56033dc47720a6de9ba0259cf81d7cecaa", size = 223977, upload-time = "2025-10-22T22:22:01.092Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/21/c8e77a2ac66e2ec4e21f18a04b4e9a0417ecf8e61b5eaeaa9360a91713b4/rpds_py-0.28.0-cp311-cp311-win_arm64.whl", hash = "sha256:4e27d3a5709cc2b3e013bf93679a849213c79ae0573f9b894b284b55e729e120", size = 217326, upload-time = "2025-10-22T22:22:02.944Z" },
+ { url = "https://files.pythonhosted.org/packages/b8/5c/6c3936495003875fe7b14f90ea812841a08fca50ab26bd840e924097d9c8/rpds_py-0.28.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6b4f28583a4f247ff60cd7bdda83db8c3f5b05a7a82ff20dd4b078571747708f", size = 366439, upload-time = "2025-10-22T22:22:04.525Z" },
+ { url = "https://files.pythonhosted.org/packages/56/f9/a0f1ca194c50aa29895b442771f036a25b6c41a35e4f35b1a0ea713bedae/rpds_py-0.28.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d678e91b610c29c4b3d52a2c148b641df2b4676ffe47c59f6388d58b99cdc424", size = 348170, upload-time = "2025-10-22T22:22:06.397Z" },
+ { url = "https://files.pythonhosted.org/packages/18/ea/42d243d3a586beb72c77fa5def0487daf827210069a95f36328e869599ea/rpds_py-0.28.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e819e0e37a44a78e1383bf1970076e2ccc4dc8c2bbaa2f9bd1dc987e9afff628", size = 378838, upload-time = "2025-10-22T22:22:07.932Z" },
+ { url = "https://files.pythonhosted.org/packages/e7/78/3de32e18a94791af8f33601402d9d4f39613136398658412a4e0b3047327/rpds_py-0.28.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5ee514e0f0523db5d3fb171f397c54875dbbd69760a414dccf9d4d7ad628b5bd", size = 393299, upload-time = "2025-10-22T22:22:09.435Z" },
+ { url = "https://files.pythonhosted.org/packages/13/7e/4bdb435afb18acea2eb8a25ad56b956f28de7c59f8a1d32827effa0d4514/rpds_py-0.28.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5f3fa06d27fdcee47f07a39e02862da0100cb4982508f5ead53ec533cd5fe55e", size = 518000, upload-time = "2025-10-22T22:22:11.326Z" },
+ { url = "https://files.pythonhosted.org/packages/31/d0/5f52a656875cdc60498ab035a7a0ac8f399890cc1ee73ebd567bac4e39ae/rpds_py-0.28.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:46959ef2e64f9e4a41fc89aa20dbca2b85531f9a72c21099a3360f35d10b0d5a", size = 408746, upload-time = "2025-10-22T22:22:13.143Z" },
+ { url = "https://files.pythonhosted.org/packages/3e/cd/49ce51767b879cde77e7ad9fae164ea15dce3616fe591d9ea1df51152706/rpds_py-0.28.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8455933b4bcd6e83fde3fefc987a023389c4b13f9a58c8d23e4b3f6d13f78c84", size = 386379, upload-time = "2025-10-22T22:22:14.602Z" },
+ { url = "https://files.pythonhosted.org/packages/6a/99/e4e1e1ee93a98f72fc450e36c0e4d99c35370220e815288e3ecd2ec36a2a/rpds_py-0.28.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:ad50614a02c8c2962feebe6012b52f9802deec4263946cddea37aaf28dd25a66", size = 401280, upload-time = "2025-10-22T22:22:16.063Z" },
+ { url = "https://files.pythonhosted.org/packages/61/35/e0c6a57488392a8b319d2200d03dad2b29c0db9996f5662c3b02d0b86c02/rpds_py-0.28.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e5deca01b271492553fdb6c7fd974659dce736a15bae5dad7ab8b93555bceb28", size = 412365, upload-time = "2025-10-22T22:22:17.504Z" },
+ { url = "https://files.pythonhosted.org/packages/ff/6a/841337980ea253ec797eb084665436007a1aad0faac1ba097fb906c5f69c/rpds_py-0.28.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:735f8495a13159ce6a0d533f01e8674cec0c57038c920495f87dcb20b3ddb48a", size = 559573, upload-time = "2025-10-22T22:22:19.108Z" },
+ { url = "https://files.pythonhosted.org/packages/e7/5e/64826ec58afd4c489731f8b00729c5f6afdb86f1df1df60bfede55d650bb/rpds_py-0.28.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:961ca621ff10d198bbe6ba4957decca61aa2a0c56695384c1d6b79bf61436df5", size = 583973, upload-time = "2025-10-22T22:22:20.768Z" },
+ { url = "https://files.pythonhosted.org/packages/b6/ee/44d024b4843f8386a4eeaa4c171b3d31d55f7177c415545fd1a24c249b5d/rpds_py-0.28.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2374e16cc9131022e7d9a8f8d65d261d9ba55048c78f3b6e017971a4f5e6353c", size = 553800, upload-time = "2025-10-22T22:22:22.25Z" },
+ { url = "https://files.pythonhosted.org/packages/7d/89/33e675dccff11a06d4d85dbb4d1865f878d5020cbb69b2c1e7b2d3f82562/rpds_py-0.28.0-cp312-cp312-win32.whl", hash = "sha256:d15431e334fba488b081d47f30f091e5d03c18527c325386091f31718952fe08", size = 216954, upload-time = "2025-10-22T22:22:24.105Z" },
+ { url = "https://files.pythonhosted.org/packages/af/36/45f6ebb3210887e8ee6dbf1bc710ae8400bb417ce165aaf3024b8360d999/rpds_py-0.28.0-cp312-cp312-win_amd64.whl", hash = "sha256:a410542d61fc54710f750d3764380b53bf09e8c4edbf2f9141a82aa774a04f7c", size = 227844, upload-time = "2025-10-22T22:22:25.551Z" },
+ { url = "https://files.pythonhosted.org/packages/57/91/f3fb250d7e73de71080f9a221d19bd6a1c1eb0d12a1ea26513f6c1052ad6/rpds_py-0.28.0-cp312-cp312-win_arm64.whl", hash = "sha256:1f0cfd1c69e2d14f8c892b893997fa9a60d890a0c8a603e88dca4955f26d1edd", size = 217624, upload-time = "2025-10-22T22:22:26.914Z" },
+ { url = "https://files.pythonhosted.org/packages/ae/bc/b43f2ea505f28119bd551ae75f70be0c803d2dbcd37c1b3734909e40620b/rpds_py-0.28.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f5e7101145427087e493b9c9b959da68d357c28c562792300dd21a095118ed16", size = 363913, upload-time = "2025-10-22T22:24:07.129Z" },
+ { url = "https://files.pythonhosted.org/packages/28/f2/db318195d324c89a2c57dc5195058cbadd71b20d220685c5bd1da79ee7fe/rpds_py-0.28.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:31eb671150b9c62409a888850aaa8e6533635704fe2b78335f9aaf7ff81eec4d", size = 350452, upload-time = "2025-10-22T22:24:08.754Z" },
+ { url = "https://files.pythonhosted.org/packages/ae/f2/1391c819b8573a4898cedd6b6c5ec5bc370ce59e5d6bdcebe3c9c1db4588/rpds_py-0.28.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48b55c1f64482f7d8bd39942f376bfdf2f6aec637ee8c805b5041e14eeb771db", size = 380957, upload-time = "2025-10-22T22:24:10.826Z" },
+ { url = "https://files.pythonhosted.org/packages/5a/5c/e5de68ee7eb7248fce93269833d1b329a196d736aefb1a7481d1e99d1222/rpds_py-0.28.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:24743a7b372e9a76171f6b69c01aedf927e8ac3e16c474d9fe20d552a8cb45c7", size = 391919, upload-time = "2025-10-22T22:24:12.559Z" },
+ { url = "https://files.pythonhosted.org/packages/fb/4f/2376336112cbfeb122fd435d608ad8d5041b3aed176f85a3cb32c262eb80/rpds_py-0.28.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:389c29045ee8bbb1627ea190b4976a310a295559eaf9f1464a1a6f2bf84dde78", size = 528541, upload-time = "2025-10-22T22:24:14.197Z" },
+ { url = "https://files.pythonhosted.org/packages/68/53/5ae232e795853dd20da7225c5dd13a09c0a905b1a655e92bdf8d78a99fd9/rpds_py-0.28.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23690b5827e643150cf7b49569679ec13fe9a610a15949ed48b85eb7f98f34ec", size = 405629, upload-time = "2025-10-22T22:24:16.001Z" },
+ { url = "https://files.pythonhosted.org/packages/b9/2d/351a3b852b683ca9b6b8b38ed9efb2347596973849ba6c3a0e99877c10aa/rpds_py-0.28.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f0c9266c26580e7243ad0d72fc3e01d6b33866cfab5084a6da7576bcf1c4f72", size = 384123, upload-time = "2025-10-22T22:24:17.585Z" },
+ { url = "https://files.pythonhosted.org/packages/e0/15/870804daa00202728cc91cb8e2385fa9f1f4eb49857c49cfce89e304eae6/rpds_py-0.28.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:4c6c4db5d73d179746951486df97fd25e92396be07fc29ee8ff9a8f5afbdfb27", size = 400923, upload-time = "2025-10-22T22:24:19.512Z" },
+ { url = "https://files.pythonhosted.org/packages/53/25/3706b83c125fa2a0bccceac951de3f76631f6bd0ee4d02a0ed780712ef1b/rpds_py-0.28.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a3b695a8fa799dd2cfdb4804b37096c5f6dba1ac7f48a7fbf6d0485bcd060316", size = 413767, upload-time = "2025-10-22T22:24:21.316Z" },
+ { url = "https://files.pythonhosted.org/packages/ef/f9/ce43dbe62767432273ed2584cef71fef8411bddfb64125d4c19128015018/rpds_py-0.28.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:6aa1bfce3f83baf00d9c5fcdbba93a3ab79958b4c7d7d1f55e7fe68c20e63912", size = 561530, upload-time = "2025-10-22T22:24:22.958Z" },
+ { url = "https://files.pythonhosted.org/packages/46/c9/ffe77999ed8f81e30713dd38fd9ecaa161f28ec48bb80fa1cd9118399c27/rpds_py-0.28.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:7b0f9dceb221792b3ee6acb5438eb1f02b0cb2c247796a72b016dcc92c6de829", size = 585453, upload-time = "2025-10-22T22:24:24.779Z" },
+ { url = "https://files.pythonhosted.org/packages/ed/d2/4a73b18821fd4669762c855fd1f4e80ceb66fb72d71162d14da58444a763/rpds_py-0.28.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:5d0145edba8abd3db0ab22b5300c99dc152f5c9021fab861be0f0544dc3cbc5f", size = 552199, upload-time = "2025-10-22T22:24:26.54Z" },
+]
+
[[package]]
name = "rsa"
version = "4.9"
@@ -4297,14 +3738,14 @@ wheels = [
[[package]]
name = "s3transfer"
-version = "0.10.4"
+version = "0.13.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "botocore" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/c0/0a/1cdbabf9edd0ea7747efdf6c9ab4e7061b085aa7f9bfc36bb1601563b069/s3transfer-0.10.4.tar.gz", hash = "sha256:29edc09801743c21eb5ecbc617a152df41d3c287f67b615f73e5f750583666a7", size = 145287, upload-time = "2024-11-20T21:06:05.981Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/6d/05/d52bf1e65044b4e5e27d4e63e8d1579dbdec54fce685908ae09bc3720030/s3transfer-0.13.1.tar.gz", hash = "sha256:c3fdba22ba1bd367922f27ec8032d6a1cf5f10c934fb5d68cf60fd5a23d936cf", size = 150589, upload-time = "2025-07-18T19:22:42.31Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/66/05/7957af15543b8c9799209506df4660cba7afc4cf94bfb60513827e96bed6/s3transfer-0.10.4-py3-none-any.whl", hash = "sha256:244a76a24355363a68164241438de1b72f8781664920260c48465896b712a41e", size = 83175, upload-time = "2024-11-20T21:06:03.961Z" },
+ { url = "https://files.pythonhosted.org/packages/6d/4f/d073e09df851cfa251ef7840007d04db3293a0482ce607d2b993926089be/s3transfer-0.13.1-py3-none-any.whl", hash = "sha256:a981aa7429be23fe6dfc13e80e4020057cbab622b08c0315288758d67cabc724", size = 85308, upload-time = "2025-07-18T19:22:40.947Z" },
]
[[package]]
@@ -4382,7 +3823,7 @@ wheels = [
[[package]]
name = "sentence-transformers"
-version = "4.1.0"
+version = "5.1.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "huggingface-hub" },
@@ -4394,9 +3835,9 @@ dependencies = [
{ name = "transformers" },
{ name = "typing-extensions" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/73/84/b30d1b29ff58cfdff423e36a50efd622c8e31d7039b1a0d5e72066620da1/sentence_transformers-4.1.0.tar.gz", hash = "sha256:f125ffd1c727533e0eca5d4567de72f84728de8f7482834de442fd90c2c3d50b", size = 272420, upload-time = "2025-04-15T13:46:13.732Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/21/47/7d61a19ba7e6b5f36f0ffff5bbf032a1c1913612caac611e12383069eda0/sentence_transformers-5.1.1.tar.gz", hash = "sha256:8af3f844b2ecf9a6c2dfeafc2c02938a87f61202b54329d70dfd7dfd7d17a84e", size = 374434, upload-time = "2025-09-22T11:28:27.54Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/45/2d/1151b371f28caae565ad384fdc38198f1165571870217aedda230b9d7497/sentence_transformers-4.1.0-py3-none-any.whl", hash = "sha256:382a7f6be1244a100ce40495fb7523dbe8d71b3c10b299f81e6b735092b3b8ca", size = 345695, upload-time = "2025-04-15T13:46:12.44Z" },
+ { url = "https://files.pythonhosted.org/packages/48/21/4670d03ab8587b0ab6f7d5fa02a95c3dd6b1f39d0e40e508870201f3d76c/sentence_transformers-5.1.1-py3-none-any.whl", hash = "sha256:5ed544629eafe89ca668a8910ebff96cf0a9c5254ec14b05c66c086226c892fd", size = 486574, upload-time = "2025-09-22T11:28:26.311Z" },
]
[[package]]
@@ -4485,15 +3926,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" },
]
-[[package]]
-name = "smmap"
-version = "5.0.2"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/44/cd/a040c4b3119bbe532e5b0732286f805445375489fceaec1f48306068ee3b/smmap-5.0.2.tar.gz", hash = "sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5", size = 22329, upload-time = "2025-01-02T07:14:40.909Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/04/be/d09147ad1ec7934636ad912901c5fd7667e1c858e19d355237db0d0cd5e4/smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e", size = 24303, upload-time = "2025-01-02T07:14:38.724Z" },
-]
-
[[package]]
name = "sniffio"
version = "1.3.1"
@@ -4569,6 +4001,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/aa/e4/592120713a314621c692211eba034d09becaf6bc8848fabc1dc2a54d8c16/SQLAlchemy-2.0.38-py3-none-any.whl", hash = "sha256:63178c675d4c80def39f1febd625a6333f44c0ba269edd8a468b156394b27753", size = 1896347, upload-time = "2025-02-06T22:08:29.784Z" },
]
+[[package]]
+name = "sse-starlette"
+version = "3.0.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "anyio" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/db/3c/fa6517610dc641262b77cc7bf994ecd17465812c1b0585fe33e11be758ab/sse_starlette-3.0.3.tar.gz", hash = "sha256:88cfb08747e16200ea990c8ca876b03910a23b547ab3bd764c0d8eb81019b971", size = 21943, upload-time = "2025-10-30T18:44:20.117Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/23/a0/984525d19ca5c8a6c33911a0c164b11490dd0f90ff7fd689f704f84e9a11/sse_starlette-3.0.3-py3-none-any.whl", hash = "sha256:af5bf5a6f3933df1d9c7f8539633dc8444ca6a97ab2e2a7cd3b6e431ac03a431", size = 11765, upload-time = "2025-10-30T18:44:18.834Z" },
+]
+
[[package]]
name = "starlette"
version = "0.45.3"
@@ -4596,6 +4040,24 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/df/4a/40ff289cdc106f6ec0c157c17f5cff13fac582ad0be54637b6081d64f547/starlette_compress-1.6.0-py3-none-any.whl", hash = "sha256:861bbf56df551bd33da95f0d7af102db0034f2786cd5ec3eae713d39a9c44ea6", size = 11390, upload-time = "2025-05-21T09:37:55.625Z" },
]
+[[package]]
+name = "starsessions"
+version = "2.2.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "itsdangerous" },
+ { name = "starlette" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/86/a1/dd738cd47b7a1c681cae49c4f7c88cc953b2aca4de455c2aacda6652e7ce/starsessions-2.2.1.tar.gz", hash = "sha256:ce5e4448d9bf2c76222e56cd099ad92d22313e8a4def612e22b71a122cc11da0", size = 15048, upload-time = "2024-10-23T09:01:12.343Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d2/ce/fc699345a3cdfb4425b5dc1e446f1b49702ac55907a6a4d5d806f2512dae/starsessions-2.2.1-py3-none-any.whl", hash = "sha256:8097b33d70017b2d2331307f0ea923620b5bfb847118d2e5872805d0c1c16f83", size = 14621, upload-time = "2024-10-23T09:01:10.88Z" },
+]
+
+[package.optional-dependencies]
+redis = [
+ { name = "redis" },
+]
+
[[package]]
name = "sympy"
version = "1.13.1"
@@ -4617,18 +4079,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/b6/cb/b86984bed139586d01532a587464b5805f12e397594f19f931c4c2fbfa61/tenacity-9.0.0-py3-none-any.whl", hash = "sha256:93de0c98785b27fcf659856aa9f54bfbd399e29969b0621bc7f762bd441b4539", size = 28169, upload-time = "2024-07-29T12:12:25.825Z" },
]
-[[package]]
-name = "tencentcloud-sdk-python"
-version = "3.0.1336"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "requests" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/0b/d6/4d57d25c0614cccb9d017962f3bfe20313b2c42bdfa3c4c33fa02c35906d/tencentcloud-sdk-python-3.0.1336.tar.gz", hash = "sha256:1c6a1413267030c142ba2a2e4f64ce12026157efd0f4c446efca1856dbae6f35", size = 11427085, upload-time = "2025-03-10T20:45:29.435Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/58/c7/e1877f3962966b3442218b0ccaadaa70eb1c89171f5f06eace029bd49c6d/tencentcloud_sdk_python-3.0.1336-py2.py3-none-any.whl", hash = "sha256:1c6280d427274b6f76e01220951ee49fd203c1c78d79e5ba62bfc3df6e566299", size = 12165181, upload-time = "2025-03-10T20:45:16.982Z" },
-]
-
[[package]]
name = "threadpoolctl"
version = "3.5.0"
@@ -4839,42 +4289,14 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/97/3f/c4c51c55ff8487f2e6d0e618dba917e3c3ee2caae6cf0fbb59c9b1876f2e/tzlocal-5.2-py3-none-any.whl", hash = "sha256:49816ef2fe65ea8ac19d19aa7a1ae0551c834303d5014c6d5a62e4cbda8047b8", size = 17859, upload-time = "2023-10-22T17:41:36.511Z" },
]
-[[package]]
-name = "ujson"
-version = "5.10.0"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/f0/00/3110fd566786bfa542adb7932d62035e0c0ef662a8ff6544b6643b3d6fd7/ujson-5.10.0.tar.gz", hash = "sha256:b3cd8f3c5d8c7738257f1018880444f7b7d9b66232c64649f562d7ba86ad4bc1", size = 7154885, upload-time = "2024-05-14T02:02:34.233Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/23/ec/3c551ecfe048bcb3948725251fb0214b5844a12aa60bee08d78315bb1c39/ujson-5.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a5b366812c90e69d0f379a53648be10a5db38f9d4ad212b60af00bd4048d0f00", size = 55353, upload-time = "2024-05-14T02:00:48.04Z" },
- { url = "https://files.pythonhosted.org/packages/8d/9f/4731ef0671a0653e9f5ba18db7c4596d8ecbf80c7922dd5fe4150f1aea76/ujson-5.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:502bf475781e8167f0f9d0e41cd32879d120a524b22358e7f205294224c71126", size = 51813, upload-time = "2024-05-14T02:00:49.28Z" },
- { url = "https://files.pythonhosted.org/packages/1f/2b/44d6b9c1688330bf011f9abfdb08911a9dc74f76926dde74e718d87600da/ujson-5.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b91b5d0d9d283e085e821651184a647699430705b15bf274c7896f23fe9c9d8", size = 51988, upload-time = "2024-05-14T02:00:50.484Z" },
- { url = "https://files.pythonhosted.org/packages/29/45/f5f5667427c1ec3383478092a414063ddd0dfbebbcc533538fe37068a0a3/ujson-5.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:129e39af3a6d85b9c26d5577169c21d53821d8cf68e079060602e861c6e5da1b", size = 53561, upload-time = "2024-05-14T02:00:52.146Z" },
- { url = "https://files.pythonhosted.org/packages/26/21/a0c265cda4dd225ec1be595f844661732c13560ad06378760036fc622587/ujson-5.10.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f77b74475c462cb8b88680471193064d3e715c7c6074b1c8c412cb526466efe9", size = 58497, upload-time = "2024-05-14T02:00:53.366Z" },
- { url = "https://files.pythonhosted.org/packages/28/36/8fde862094fd2342ccc427a6a8584fed294055fdee341661c78660f7aef3/ujson-5.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7ec0ca8c415e81aa4123501fee7f761abf4b7f386aad348501a26940beb1860f", size = 997877, upload-time = "2024-05-14T02:00:55.095Z" },
- { url = "https://files.pythonhosted.org/packages/90/37/9208e40d53baa6da9b6a1c719e0670c3f474c8fc7cc2f1e939ec21c1bc93/ujson-5.10.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab13a2a9e0b2865a6c6db9271f4b46af1c7476bfd51af1f64585e919b7c07fd4", size = 1140632, upload-time = "2024-05-14T02:00:57.099Z" },
- { url = "https://files.pythonhosted.org/packages/89/d5/2626c87c59802863d44d19e35ad16b7e658e4ac190b0dead17ff25460b4c/ujson-5.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:57aaf98b92d72fc70886b5a0e1a1ca52c2320377360341715dd3933a18e827b1", size = 1043513, upload-time = "2024-05-14T02:00:58.488Z" },
- { url = "https://files.pythonhosted.org/packages/2f/ee/03662ce9b3f16855770f0d70f10f0978ba6210805aa310c4eebe66d36476/ujson-5.10.0-cp311-cp311-win32.whl", hash = "sha256:2987713a490ceb27edff77fb184ed09acdc565db700ee852823c3dc3cffe455f", size = 38616, upload-time = "2024-05-14T02:01:00.463Z" },
- { url = "https://files.pythonhosted.org/packages/3e/20/952dbed5895835ea0b82e81a7be4ebb83f93b079d4d1ead93fcddb3075af/ujson-5.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:f00ea7e00447918ee0eff2422c4add4c5752b1b60e88fcb3c067d4a21049a720", size = 42071, upload-time = "2024-05-14T02:01:02.211Z" },
- { url = "https://files.pythonhosted.org/packages/e8/a6/fd3f8bbd80842267e2d06c3583279555e8354c5986c952385199d57a5b6c/ujson-5.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98ba15d8cbc481ce55695beee9f063189dce91a4b08bc1d03e7f0152cd4bbdd5", size = 55642, upload-time = "2024-05-14T02:01:04.055Z" },
- { url = "https://files.pythonhosted.org/packages/a8/47/dd03fd2b5ae727e16d5d18919b383959c6d269c7b948a380fdd879518640/ujson-5.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9d2edbf1556e4f56e50fab7d8ff993dbad7f54bac68eacdd27a8f55f433578e", size = 51807, upload-time = "2024-05-14T02:01:05.25Z" },
- { url = "https://files.pythonhosted.org/packages/25/23/079a4cc6fd7e2655a473ed9e776ddbb7144e27f04e8fc484a0fb45fe6f71/ujson-5.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6627029ae4f52d0e1a2451768c2c37c0c814ffc04f796eb36244cf16b8e57043", size = 51972, upload-time = "2024-05-14T02:01:06.458Z" },
- { url = "https://files.pythonhosted.org/packages/04/81/668707e5f2177791869b624be4c06fb2473bf97ee33296b18d1cf3092af7/ujson-5.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8ccb77b3e40b151e20519c6ae6d89bfe3f4c14e8e210d910287f778368bb3d1", size = 53686, upload-time = "2024-05-14T02:01:07.618Z" },
- { url = "https://files.pythonhosted.org/packages/bd/50/056d518a386d80aaf4505ccf3cee1c40d312a46901ed494d5711dd939bc3/ujson-5.10.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3caf9cd64abfeb11a3b661329085c5e167abbe15256b3b68cb5d914ba7396f3", size = 58591, upload-time = "2024-05-14T02:01:08.901Z" },
- { url = "https://files.pythonhosted.org/packages/fc/d6/aeaf3e2d6fb1f4cfb6bf25f454d60490ed8146ddc0600fae44bfe7eb5a72/ujson-5.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6e32abdce572e3a8c3d02c886c704a38a1b015a1fb858004e03d20ca7cecbb21", size = 997853, upload-time = "2024-05-14T02:01:10.772Z" },
- { url = "https://files.pythonhosted.org/packages/f8/d5/1f2a5d2699f447f7d990334ca96e90065ea7f99b142ce96e85f26d7e78e2/ujson-5.10.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a65b6af4d903103ee7b6f4f5b85f1bfd0c90ba4eeac6421aae436c9988aa64a2", size = 1140689, upload-time = "2024-05-14T02:01:12.214Z" },
- { url = "https://files.pythonhosted.org/packages/f2/2c/6990f4ccb41ed93744aaaa3786394bca0875503f97690622f3cafc0adfde/ujson-5.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:604a046d966457b6cdcacc5aa2ec5314f0e8c42bae52842c1e6fa02ea4bda42e", size = 1043576, upload-time = "2024-05-14T02:01:14.39Z" },
- { url = "https://files.pythonhosted.org/packages/14/f5/a2368463dbb09fbdbf6a696062d0c0f62e4ae6fa65f38f829611da2e8fdd/ujson-5.10.0-cp312-cp312-win32.whl", hash = "sha256:6dea1c8b4fc921bf78a8ff00bbd2bfe166345f5536c510671bccececb187c80e", size = 38764, upload-time = "2024-05-14T02:01:15.83Z" },
- { url = "https://files.pythonhosted.org/packages/59/2d/691f741ffd72b6c84438a93749ac57bf1a3f217ac4b0ea4fd0e96119e118/ujson-5.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:38665e7d8290188b1e0d57d584eb8110951a9591363316dd41cf8686ab1d0abc", size = 42211, upload-time = "2024-05-14T02:01:17.567Z" },
-]
-
[[package]]
name = "unstructured"
-version = "0.16.17"
+version = "0.18.15"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "backoff" },
{ name = "beautifulsoup4" },
- { name = "chardet" },
+ { name = "charset-normalizer" },
{ name = "dataclasses-json" },
{ name = "emoji" },
{ name = "filetype" },
@@ -4894,9 +4316,9 @@ dependencies = [
{ name = "unstructured-client" },
{ name = "wrapt" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/85/90/cf5cbf152d0d1ab507c14e2535d4a9442ad59308ced8c26b71d8b93ace52/unstructured-0.16.17.tar.gz", hash = "sha256:590700ed344ed27a6dce8b3ffdeec2c427bd4f057d9bcb470f8ce828cc20b314", size = 1670303, upload-time = "2025-01-29T12:53:50.37Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/6c/08/cf969b274f652e2fe48a6807b827498c7142dc749bdbd46ab24ea97a5fd5/unstructured-0.18.15.tar.gz", hash = "sha256:81d8481280a4ac5cefe74bdb6db3687e8f240d5643706f86728eac39549112b5", size = 1691102, upload-time = "2025-09-17T14:30:59.524Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/ce/b7/b0f668213b8b3d17190da161faa7eae5681627835fab76094c4697b12729/unstructured-0.16.17-py3-none-any.whl", hash = "sha256:9b55bf47ac6532f16e6ef27f5b823e037ab860f07d377784b9dc43a99a981268", size = 1755843, upload-time = "2025-01-29T12:53:47.374Z" },
+ { url = "https://files.pythonhosted.org/packages/62/24/7b8a8a9c23b209dc484b0d82905847c5f6b96a579bade367f3f3e40263f3/unstructured-0.18.15-py3-none-any.whl", hash = "sha256:f05b1defcbe8190319d30da8adddbb888f74bf8ec7f65886867d7dca41d67ad0", size = 1778900, upload-time = "2025-09-17T14:30:57.872Z" },
]
[[package]]
@@ -4937,15 +4359,15 @@ wheels = [
[[package]]
name = "uvicorn"
-version = "0.34.2"
+version = "0.37.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "click" },
{ name = "h11" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/a6/ae/9bbb19b9e1c450cf9ecaef06463e40234d98d95bf572fab11b4f19ae5ded/uvicorn-0.34.2.tar.gz", hash = "sha256:0e929828f6186353a80b58ea719861d2629d766293b6d19baf086ba31d4f3328", size = 76815, upload-time = "2025-04-19T06:02:50.101Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/71/57/1616c8274c3442d802621abf5deb230771c7a0fec9414cb6763900eb3868/uvicorn-0.37.0.tar.gz", hash = "sha256:4115c8add6d3fd536c8ee77f0e14a7fd2ebba939fed9b02583a97f80648f9e13", size = 80367, upload-time = "2025-09-23T13:33:47.486Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/b1/4b/4cef6ce21a2aaca9d852a6e84ef4f135d99fcd74fa75105e2fc0c8308acd/uvicorn-0.34.2-py3-none-any.whl", hash = "sha256:deb49af569084536d269fe0a6d67e3754f104cf03aba7c11c40f01aadf33c403", size = 62483, upload-time = "2025-04-19T06:02:48.42Z" },
+ { url = "https://files.pythonhosted.org/packages/85/cd/584a2ceb5532af99dd09e50919e3615ba99aa127e9850eafe5f31ddfdb9a/uvicorn-0.37.0-py3-none-any.whl", hash = "sha256:913b2b88672343739927ce381ff9e2ad62541f9f8289664fa1d1d3803fa2ce6c", size = 67976, upload-time = "2025-09-23T13:33:45.842Z" },
]
[package.optional-dependencies]
@@ -5083,18 +4505,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/b0/0b/c7e5d11020242984d9d37990310520ed663b942333b83a033c2f20191113/websockets-14.1-py3-none-any.whl", hash = "sha256:4d4fc827a20abe6d544a119896f6b78ee13fe81cbfef416f3f2ddf09a03f0e2e", size = 156277, upload-time = "2024-11-13T07:11:27.848Z" },
]
-[[package]]
-name = "werkzeug"
-version = "3.1.3"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "markupsafe" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/9f/69/83029f1f6300c5fb2471d621ab06f6ec6b3324685a2ce0f9777fd4a8b71e/werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746", size = 806925, upload-time = "2024-11-08T15:52:18.093Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/52/24/ab44c871b0f07f491e5d2ad12c9bd7358e527510618cb1b803a88e986db1/werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e", size = 224498, upload-time = "2024-11-08T15:52:16.132Z" },
-]
-
[[package]]
name = "win32-setctime"
version = "1.2.0"
@@ -5165,53 +4575,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/a7/ea/53d1fe468e63e092cf16e2c18d16f50c29851242f9dd12d6a66e0d7f0d02/XlsxWriter-3.2.0-py3-none-any.whl", hash = "sha256:ecfd5405b3e0e228219bcaf24c2ca0915e012ca9464a14048021d21a995d490e", size = 159925, upload-time = "2024-02-18T23:11:21.559Z" },
]
-[[package]]
-name = "xmltodict"
-version = "0.14.2"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/50/05/51dcca9a9bf5e1bce52582683ce50980bcadbc4fa5143b9f2b19ab99958f/xmltodict-0.14.2.tar.gz", hash = "sha256:201e7c28bb210e374999d1dde6382923ab0ed1a8a5faeece48ab525b7810a553", size = 51942, upload-time = "2024-10-16T06:10:29.683Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/d6/45/fc303eb433e8a2a271739c98e953728422fa61a3c1f36077a49e395c972e/xmltodict-0.14.2-py2.py3-none-any.whl", hash = "sha256:20cc7d723ed729276e808f26fb6b3599f786cbc37e06c65e192ba77c40f20aac", size = 9981, upload-time = "2024-10-16T06:10:27.649Z" },
-]
-
-[[package]]
-name = "xxhash"
-version = "3.5.0"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/00/5e/d6e5258d69df8b4ed8c83b6664f2b47d30d2dec551a29ad72a6c69eafd31/xxhash-3.5.0.tar.gz", hash = "sha256:84f2caddf951c9cbf8dc2e22a89d4ccf5d86391ac6418fe81e3c67d0cf60b45f", size = 84241, upload-time = "2024-08-17T09:20:38.972Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/b8/c7/afed0f131fbda960ff15eee7f304fa0eeb2d58770fade99897984852ef23/xxhash-3.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:02c2e816896dc6f85922ced60097bcf6f008dedfc5073dcba32f9c8dd786f3c1", size = 31969, upload-time = "2024-08-17T09:18:00.852Z" },
- { url = "https://files.pythonhosted.org/packages/8c/0c/7c3bc6d87e5235672fcc2fb42fd5ad79fe1033925f71bf549ee068c7d1ca/xxhash-3.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6027dcd885e21581e46d3c7f682cfb2b870942feeed58a21c29583512c3f09f8", size = 30800, upload-time = "2024-08-17T09:18:01.863Z" },
- { url = "https://files.pythonhosted.org/packages/04/9e/01067981d98069eec1c20201f8c145367698e9056f8bc295346e4ea32dd1/xxhash-3.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1308fa542bbdbf2fa85e9e66b1077eea3a88bef38ee8a06270b4298a7a62a166", size = 221566, upload-time = "2024-08-17T09:18:03.461Z" },
- { url = "https://files.pythonhosted.org/packages/d4/09/d4996de4059c3ce5342b6e1e6a77c9d6c91acce31f6ed979891872dd162b/xxhash-3.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c28b2fdcee797e1c1961cd3bcd3d545cab22ad202c846235197935e1df2f8ef7", size = 201214, upload-time = "2024-08-17T09:18:05.616Z" },
- { url = "https://files.pythonhosted.org/packages/62/f5/6d2dc9f8d55a7ce0f5e7bfef916e67536f01b85d32a9fbf137d4cadbee38/xxhash-3.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:924361811732ddad75ff23e90efd9ccfda4f664132feecb90895bade6a1b4623", size = 429433, upload-time = "2024-08-17T09:18:06.957Z" },
- { url = "https://files.pythonhosted.org/packages/d9/72/9256303f10e41ab004799a4aa74b80b3c5977d6383ae4550548b24bd1971/xxhash-3.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89997aa1c4b6a5b1e5b588979d1da048a3c6f15e55c11d117a56b75c84531f5a", size = 194822, upload-time = "2024-08-17T09:18:08.331Z" },
- { url = "https://files.pythonhosted.org/packages/34/92/1a3a29acd08248a34b0e6a94f4e0ed9b8379a4ff471f1668e4dce7bdbaa8/xxhash-3.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:685c4f4e8c59837de103344eb1c8a3851f670309eb5c361f746805c5471b8c88", size = 208538, upload-time = "2024-08-17T09:18:10.332Z" },
- { url = "https://files.pythonhosted.org/packages/53/ad/7fa1a109663366de42f724a1cdb8e796a260dbac45047bce153bc1e18abf/xxhash-3.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dbd2ecfbfee70bc1a4acb7461fa6af7748ec2ab08ac0fa298f281c51518f982c", size = 216953, upload-time = "2024-08-17T09:18:11.707Z" },
- { url = "https://files.pythonhosted.org/packages/35/02/137300e24203bf2b2a49b48ce898ecce6fd01789c0fcd9c686c0a002d129/xxhash-3.5.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:25b5a51dc3dfb20a10833c8eee25903fd2e14059e9afcd329c9da20609a307b2", size = 203594, upload-time = "2024-08-17T09:18:13.799Z" },
- { url = "https://files.pythonhosted.org/packages/23/03/aeceb273933d7eee248c4322b98b8e971f06cc3880e5f7602c94e5578af5/xxhash-3.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a8fb786fb754ef6ff8c120cb96629fb518f8eb5a61a16aac3a979a9dbd40a084", size = 210971, upload-time = "2024-08-17T09:18:15.824Z" },
- { url = "https://files.pythonhosted.org/packages/e3/64/ed82ec09489474cbb35c716b189ddc1521d8b3de12b1b5ab41ce7f70253c/xxhash-3.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:a905ad00ad1e1c34fe4e9d7c1d949ab09c6fa90c919860c1534ff479f40fd12d", size = 415050, upload-time = "2024-08-17T09:18:17.142Z" },
- { url = "https://files.pythonhosted.org/packages/71/43/6db4c02dcb488ad4e03bc86d70506c3d40a384ee73c9b5c93338eb1f3c23/xxhash-3.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:963be41bcd49f53af6d795f65c0da9b4cc518c0dd9c47145c98f61cb464f4839", size = 192216, upload-time = "2024-08-17T09:18:18.779Z" },
- { url = "https://files.pythonhosted.org/packages/22/6d/db4abec29e7a567455344433d095fdb39c97db6955bb4a2c432e486b4d28/xxhash-3.5.0-cp311-cp311-win32.whl", hash = "sha256:109b436096d0a2dd039c355fa3414160ec4d843dfecc64a14077332a00aeb7da", size = 30120, upload-time = "2024-08-17T09:18:20.009Z" },
- { url = "https://files.pythonhosted.org/packages/52/1c/fa3b61c0cf03e1da4767213672efe186b1dfa4fc901a4a694fb184a513d1/xxhash-3.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:b702f806693201ad6c0a05ddbbe4c8f359626d0b3305f766077d51388a6bac58", size = 30003, upload-time = "2024-08-17T09:18:21.052Z" },
- { url = "https://files.pythonhosted.org/packages/6b/8e/9e6fc572acf6e1cc7ccb01973c213f895cb8668a9d4c2b58a99350da14b7/xxhash-3.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:c4dcb4120d0cc3cc448624147dba64e9021b278c63e34a38789b688fd0da9bf3", size = 26777, upload-time = "2024-08-17T09:18:22.809Z" },
- { url = "https://files.pythonhosted.org/packages/07/0e/1bfce2502c57d7e2e787600b31c83535af83746885aa1a5f153d8c8059d6/xxhash-3.5.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:14470ace8bd3b5d51318782cd94e6f94431974f16cb3b8dc15d52f3b69df8e00", size = 31969, upload-time = "2024-08-17T09:18:24.025Z" },
- { url = "https://files.pythonhosted.org/packages/3f/d6/8ca450d6fe5b71ce521b4e5db69622383d039e2b253e9b2f24f93265b52c/xxhash-3.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:59aa1203de1cb96dbeab595ded0ad0c0056bb2245ae11fac11c0ceea861382b9", size = 30787, upload-time = "2024-08-17T09:18:25.318Z" },
- { url = "https://files.pythonhosted.org/packages/5b/84/de7c89bc6ef63d750159086a6ada6416cc4349eab23f76ab870407178b93/xxhash-3.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08424f6648526076e28fae6ea2806c0a7d504b9ef05ae61d196d571e5c879c84", size = 220959, upload-time = "2024-08-17T09:18:26.518Z" },
- { url = "https://files.pythonhosted.org/packages/fe/86/51258d3e8a8545ff26468c977101964c14d56a8a37f5835bc0082426c672/xxhash-3.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:61a1ff00674879725b194695e17f23d3248998b843eb5e933007ca743310f793", size = 200006, upload-time = "2024-08-17T09:18:27.905Z" },
- { url = "https://files.pythonhosted.org/packages/02/0a/96973bd325412feccf23cf3680fd2246aebf4b789122f938d5557c54a6b2/xxhash-3.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2f2c61bee5844d41c3eb015ac652a0229e901074951ae48581d58bfb2ba01be", size = 428326, upload-time = "2024-08-17T09:18:29.335Z" },
- { url = "https://files.pythonhosted.org/packages/11/a7/81dba5010f7e733de88af9555725146fc133be97ce36533867f4c7e75066/xxhash-3.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d32a592cac88d18cc09a89172e1c32d7f2a6e516c3dfde1b9adb90ab5df54a6", size = 194380, upload-time = "2024-08-17T09:18:30.706Z" },
- { url = "https://files.pythonhosted.org/packages/fb/7d/f29006ab398a173f4501c0e4977ba288f1c621d878ec217b4ff516810c04/xxhash-3.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70dabf941dede727cca579e8c205e61121afc9b28516752fd65724be1355cc90", size = 207934, upload-time = "2024-08-17T09:18:32.133Z" },
- { url = "https://files.pythonhosted.org/packages/8a/6e/6e88b8f24612510e73d4d70d9b0c7dff62a2e78451b9f0d042a5462c8d03/xxhash-3.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e5d0ddaca65ecca9c10dcf01730165fd858533d0be84c75c327487c37a906a27", size = 216301, upload-time = "2024-08-17T09:18:33.474Z" },
- { url = "https://files.pythonhosted.org/packages/af/51/7862f4fa4b75a25c3b4163c8a873f070532fe5f2d3f9b3fc869c8337a398/xxhash-3.5.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e5b5e16c5a480fe5f59f56c30abdeba09ffd75da8d13f6b9b6fd224d0b4d0a2", size = 203351, upload-time = "2024-08-17T09:18:34.889Z" },
- { url = "https://files.pythonhosted.org/packages/22/61/8d6a40f288f791cf79ed5bb113159abf0c81d6efb86e734334f698eb4c59/xxhash-3.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:149b7914451eb154b3dfaa721315117ea1dac2cc55a01bfbd4df7c68c5dd683d", size = 210294, upload-time = "2024-08-17T09:18:36.355Z" },
- { url = "https://files.pythonhosted.org/packages/17/02/215c4698955762d45a8158117190261b2dbefe9ae7e5b906768c09d8bc74/xxhash-3.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:eade977f5c96c677035ff39c56ac74d851b1cca7d607ab3d8f23c6b859379cab", size = 414674, upload-time = "2024-08-17T09:18:38.536Z" },
- { url = "https://files.pythonhosted.org/packages/31/5c/b7a8db8a3237cff3d535261325d95de509f6a8ae439a5a7a4ffcff478189/xxhash-3.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fa9f547bd98f5553d03160967866a71056a60960be00356a15ecc44efb40ba8e", size = 192022, upload-time = "2024-08-17T09:18:40.138Z" },
- { url = "https://files.pythonhosted.org/packages/78/e3/dd76659b2811b3fd06892a8beb850e1996b63e9235af5a86ea348f053e9e/xxhash-3.5.0-cp312-cp312-win32.whl", hash = "sha256:f7b58d1fd3551b8c80a971199543379be1cee3d0d409e1f6d8b01c1a2eebf1f8", size = 30170, upload-time = "2024-08-17T09:18:42.163Z" },
- { url = "https://files.pythonhosted.org/packages/d9/6b/1c443fe6cfeb4ad1dcf231cdec96eb94fb43d6498b4469ed8b51f8b59a37/xxhash-3.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:fa0cafd3a2af231b4e113fba24a65d7922af91aeb23774a8b78228e6cd785e3e", size = 30040, upload-time = "2024-08-17T09:18:43.699Z" },
- { url = "https://files.pythonhosted.org/packages/0f/eb/04405305f290173acc0350eba6d2f1a794b57925df0398861a20fbafa415/xxhash-3.5.0-cp312-cp312-win_arm64.whl", hash = "sha256:586886c7e89cb9828bcd8a5686b12e161368e0064d040e225e72607b43858ba2", size = 26796, upload-time = "2024-08-17T09:18:45.29Z" },
-]
-
[[package]]
name = "yarl"
version = "1.18.3"
@@ -5260,15 +4623,15 @@ wheels = [
[[package]]
name = "youtube-transcript-api"
-version = "1.1.0"
+version = "1.2.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "defusedxml" },
{ name = "requests" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/36/dd/10d413b20a2d14fa483853d0f6d920a0a0a6887d7c60167e4641733f99fb/youtube_transcript_api-1.1.0.tar.gz", hash = "sha256:786d9e64bd7fffee0dbc1471a61a798cebdc379b9cf8f7661d3664e831fcc1a5", size = 470144, upload-time = "2025-06-11T22:30:44.048Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/8f/f8/5e12d3d0c7001c3b3078697b9918241022bdb1ae12715e9debb00a83e16e/youtube_transcript_api-1.2.2.tar.gz", hash = "sha256:5f67cfaff3621d969778817a3d7b2172c16784855f45fcaed4f0529632e2fef4", size = 469634, upload-time = "2025-08-04T12:22:52.158Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/b3/69/63f1b9f96a9d3b6bd35288fe27f987c41bd157e47b3d07ca025549e3f8e6/youtube_transcript_api-1.1.0-py3-none-any.whl", hash = "sha256:876ac42b1e3f8cc99b81d8fd810bd74ed07511e51dff5db50e714e3156ad3595", size = 485739, upload-time = "2025-06-11T22:30:40.515Z" },
+ { url = "https://files.pythonhosted.org/packages/41/92/3d1a580f0efcad926f45876cf6cb92b2c260e84ae75dae5463bbf38f92e7/youtube_transcript_api-1.2.2-py3-none-any.whl", hash = "sha256:feca8c7f7c9d65188ef6377fc0e01cf466e6b68f1b3e648019646ab342f994d2", size = 485047, upload-time = "2025-08-04T12:22:50.836Z" },
]
[[package]]
@@ -5321,4 +4684,4 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/f2/61/ac78a1263bc83a5cf29e7458b77a568eda5a8f81980691bbc6eb6a0d45cc/zstandard-0.23.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a8fffdbd9d1408006baaf02f1068d7dd1f016c6bcb7538682622c556e7b68e35", size = 5191313, upload-time = "2024-07-15T00:16:09.758Z" },
{ url = "https://files.pythonhosted.org/packages/e7/54/967c478314e16af5baf849b6ee9d6ea724ae5b100eb506011f045d3d4e16/zstandard-0.23.0-cp312-cp312-win32.whl", hash = "sha256:dc1d33abb8a0d754ea4763bad944fd965d3d95b5baef6b121c0c9013eaf1907d", size = 430877, upload-time = "2024-07-15T00:16:11.758Z" },
{ url = "https://files.pythonhosted.org/packages/75/37/872d74bd7739639c4553bf94c84af7d54d8211b626b352bc57f0fd8d1e3f/zstandard-0.23.0-cp312-cp312-win_amd64.whl", hash = "sha256:64585e1dba664dc67c7cdabd56c1e5685233fbb1fc1966cfba2a340ec0dfff7b", size = 495595, upload-time = "2024-07-15T00:16:13.731Z" },
-]
\ No newline at end of file
+]
diff --git a/vite.config.ts b/vite.config.ts
index df802c081cb4..22eaec706f50 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -3,6 +3,7 @@ import { defineConfig } from 'vite';
import { viteStaticCopy } from 'vite-plugin-static-copy';
+// @ts-ignore
export default defineConfig({
plugins: [
sveltekit(),
@@ -26,6 +27,30 @@ export default defineConfig({
worker: {
format: 'es'
},
+ server: {
+ port: 5173,
+ proxy: {
+ '^/kael/api/': {
+ target: 'http://localhost:8083',
+ changeOrigin: true
+ // 如果后端实际上是 /api 而不是 /kael/api,添加:
+ // rewrite: p => p.replace(/^\/kael\/api\//, '/api/')
+ },
+ '/kael/openai': {
+ target: 'http://localhost:8083',
+ changeOrigin: true
+ },
+ '/kael/ollama': {
+ target: 'http://localhost:8083',
+ changeOrigin: true
+ },
+ '/kael/ws': {
+ target: 'http://localhost:8083',
+ ws: true,
+ changeOrigin: true
+ }
+ }
+ },
esbuild: {
pure: process.env.ENV === 'dev' ? [] : ['console.log', 'console.debug', 'console.error']
}