mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-09 13:25:11 +00:00
Support using MCP tools in research mode
- Server admin can add MCP servers via the admin panel - Enabled MCP server tools are exposed to the research agent for use - Use MCP library to standardize interactions with mcp servers - Support SSE or Stdio as transport to interact with mcp servers - Reuse session established to MCP servers across research iterations
This commit is contained in:
@@ -93,6 +93,7 @@ dependencies = [
|
|||||||
"resend == 1.0.1",
|
"resend == 1.0.1",
|
||||||
"email-validator == 2.2.0",
|
"email-validator == 2.2.0",
|
||||||
"e2b-code-interpreter ~= 1.0.0",
|
"e2b-code-interpreter ~= 1.0.0",
|
||||||
|
"mcp >= 1.12.4",
|
||||||
]
|
]
|
||||||
dynamic = ["version"]
|
dynamic = ["version"]
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ from khoj.database.models import (
|
|||||||
GoogleUser,
|
GoogleUser,
|
||||||
KhojApiUser,
|
KhojApiUser,
|
||||||
KhojUser,
|
KhojUser,
|
||||||
|
McpServer,
|
||||||
NotionConfig,
|
NotionConfig,
|
||||||
PriceTier,
|
PriceTier,
|
||||||
ProcessLock,
|
ProcessLock,
|
||||||
@@ -2127,3 +2128,15 @@ class AutomationAdapters:
|
|||||||
|
|
||||||
automation.remove()
|
automation.remove()
|
||||||
return automation_metadata
|
return automation_metadata
|
||||||
|
|
||||||
|
|
||||||
|
class McpServerAdapters:
|
||||||
|
@staticmethod
|
||||||
|
async def aget_all_mcp_servers() -> List[McpServer]:
|
||||||
|
"""Asynchronously retrieve all McpServer objects from the database."""
|
||||||
|
servers: List[McpServer] = []
|
||||||
|
try:
|
||||||
|
servers = [server async for server in McpServer.objects.all()]
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error retrieving MCP servers: {e}", exc_info=True)
|
||||||
|
return servers
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ from khoj.database.models import (
|
|||||||
Entry,
|
Entry,
|
||||||
GithubConfig,
|
GithubConfig,
|
||||||
KhojUser,
|
KhojUser,
|
||||||
|
McpServer,
|
||||||
NotionConfig,
|
NotionConfig,
|
||||||
ProcessLock,
|
ProcessLock,
|
||||||
RateLimitRecord,
|
RateLimitRecord,
|
||||||
@@ -183,6 +184,16 @@ admin.site.register(UserRequests, unfold_admin.ModelAdmin)
|
|||||||
admin.site.register(RateLimitRecord, unfold_admin.ModelAdmin)
|
admin.site.register(RateLimitRecord, unfold_admin.ModelAdmin)
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(McpServer)
|
||||||
|
class McpServerAdmin(unfold_admin.ModelAdmin):
|
||||||
|
list_display = (
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"path",
|
||||||
|
)
|
||||||
|
search_fields = ("id", "name", "path")
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Agent)
|
@admin.register(Agent)
|
||||||
class AgentAdmin(unfold_admin.ModelAdmin):
|
class AgentAdmin(unfold_admin.ModelAdmin):
|
||||||
list_display = (
|
list_display = (
|
||||||
|
|||||||
26
src/khoj/database/migrations/0096_mcpserver.py
Normal file
26
src/khoj/database/migrations/0096_mcpserver.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# Generated by Django 5.1.14 on 2025-11-13 20:58
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("database", "0095_alter_webscraper_type"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="McpServer",
|
||||||
|
fields=[
|
||||||
|
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
|
||||||
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||||
|
("updated_at", models.DateTimeField(auto_now=True)),
|
||||||
|
("name", models.CharField(max_length=50, unique=True)),
|
||||||
|
("path", models.CharField(max_length=200, unique=True)),
|
||||||
|
("api_key", models.CharField(blank=True, max_length=4000, null=True)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"abstract": False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -806,3 +806,12 @@ class DataStore(DbBaseModel):
|
|||||||
value = models.JSONField(default=dict)
|
value = models.JSONField(default=dict)
|
||||||
private = models.BooleanField(default=False)
|
private = models.BooleanField(default=False)
|
||||||
owner = models.ForeignKey(KhojUser, on_delete=models.CASCADE, default=None, null=True, blank=True)
|
owner = models.ForeignKey(KhojUser, on_delete=models.CASCADE, default=None, null=True, blank=True)
|
||||||
|
|
||||||
|
|
||||||
|
class McpServer(DbBaseModel):
|
||||||
|
name = models.CharField(max_length=50, unique=True)
|
||||||
|
path = models.CharField(max_length=200, unique=True)
|
||||||
|
api_key = models.CharField(max_length=4000, blank=True, null=True)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|||||||
124
src/khoj/processor/tools/mcp.py
Normal file
124
src/khoj/processor/tools/mcp.py
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
import logging
|
||||||
|
from contextlib import AsyncExitStack
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from mcp import ClientSession, StdioServerParameters
|
||||||
|
from mcp.client.sse import sse_client
|
||||||
|
from mcp.client.stdio import stdio_client
|
||||||
|
from mcp.types import AudioContent, ImageContent, TextContent
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class MCPClient:
|
||||||
|
"""
|
||||||
|
A client for interacting with MCP servers.
|
||||||
|
Establishes a session with the server and provides methods to get and run tools.
|
||||||
|
Supports both stdio and sse communication methods.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, name: str, path: str, api_key: Optional[str] = None):
|
||||||
|
self.name = name
|
||||||
|
self.path = path
|
||||||
|
self.api_key = api_key
|
||||||
|
self.session: Optional[ClientSession] = None
|
||||||
|
self.exit_stack = AsyncExitStack()
|
||||||
|
|
||||||
|
async def connect(self):
|
||||||
|
"""
|
||||||
|
Connect to the MCP server based on the specified path.
|
||||||
|
Uses stdio for local scripts and SSE for remote servers.
|
||||||
|
"""
|
||||||
|
if self.path.startswith("http://") or self.path.startswith("https://"):
|
||||||
|
# Path is a URL, so use SSE to connect to the server
|
||||||
|
await self._connect_to_sse_server()
|
||||||
|
else:
|
||||||
|
# Path is a script, so use stdio to connect to the server
|
||||||
|
await self._connect_to_stdio_server()
|
||||||
|
|
||||||
|
async def get_tools(self):
|
||||||
|
"""
|
||||||
|
Retrieve the list of tools available on the MCP server.
|
||||||
|
"""
|
||||||
|
# Ensure connection is established
|
||||||
|
if not self.session:
|
||||||
|
await self.connect()
|
||||||
|
|
||||||
|
tools_response = await self.session.list_tools()
|
||||||
|
return tools_response.tools
|
||||||
|
|
||||||
|
async def run_tool(self, tool_name: str, input_data: dict):
|
||||||
|
"""
|
||||||
|
Run a specified tool on the MCP server with the given input data.
|
||||||
|
"""
|
||||||
|
# Ensure connection is established
|
||||||
|
if not self.session:
|
||||||
|
await self.connect()
|
||||||
|
|
||||||
|
result = await self.session.call_tool(tool_name, input_data)
|
||||||
|
|
||||||
|
# Process result content based on its type
|
||||||
|
if len(result.content) > 0 and isinstance(result.content[0], TextContent):
|
||||||
|
return [item.text for item in result.content]
|
||||||
|
elif len(result.content) > 0 and isinstance(result.content[0], AudioContent):
|
||||||
|
return [{"data": item.data, "format": item.mimeType} for item in result.content]
|
||||||
|
elif len(result.content) > 0 and isinstance(result.content[0], ImageContent):
|
||||||
|
return [{"data": item.data, "format": item.mimeType} for item in result.content]
|
||||||
|
return result.content
|
||||||
|
|
||||||
|
async def _connect_to_sse_server(self):
|
||||||
|
"""
|
||||||
|
Connect to the MCP server using Server-Sent Events (SSE).
|
||||||
|
"""
|
||||||
|
self._streams_context = sse_client(url=self.path)
|
||||||
|
streams = await self._streams_context.__aenter__()
|
||||||
|
|
||||||
|
self._session_context = ClientSession(*streams)
|
||||||
|
self.session = await self._session_context.__aenter__()
|
||||||
|
|
||||||
|
# Initialize
|
||||||
|
await self.session.initialize()
|
||||||
|
|
||||||
|
async def _connect_to_stdio_server(self):
|
||||||
|
"""
|
||||||
|
Connect to the MCP server using stdio communication.
|
||||||
|
"""
|
||||||
|
is_python = False
|
||||||
|
is_javascript = False
|
||||||
|
command = None
|
||||||
|
args = [self.path]
|
||||||
|
|
||||||
|
# Determine if the server is a file path or npm package
|
||||||
|
if self.path.startswith("@") or "/" not in self.path:
|
||||||
|
# Assume it's an npm package
|
||||||
|
is_javascript = True
|
||||||
|
command = "npx"
|
||||||
|
else:
|
||||||
|
# It's a file path
|
||||||
|
is_python = self.path.endswith(".py")
|
||||||
|
is_javascript = self.path.endswith(".js")
|
||||||
|
if not (is_python or is_javascript):
|
||||||
|
raise ValueError("Server script must be a .py, .js file or npm package.")
|
||||||
|
|
||||||
|
command = "python" if is_python else "node"
|
||||||
|
|
||||||
|
server_params = StdioServerParameters(command=command, args=args, env=None)
|
||||||
|
|
||||||
|
logger.debug(f"Connecting to stdio MCP server with command: {command} and args: {args}")
|
||||||
|
|
||||||
|
# Start the server
|
||||||
|
stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params))
|
||||||
|
self.stdio, self.writer = stdio_transport
|
||||||
|
self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.writer))
|
||||||
|
|
||||||
|
await self.session.initialize()
|
||||||
|
|
||||||
|
async def close(self):
|
||||||
|
"""
|
||||||
|
Close the MCP client session and clean up resources.
|
||||||
|
"""
|
||||||
|
await self.exit_stack.aclose()
|
||||||
|
if hasattr(self, "_session_context") and self._session_context:
|
||||||
|
await self._session_context.__aexit__(None, None, None)
|
||||||
|
if hasattr(self, "_streams_context") and self._streams_context:
|
||||||
|
await self._streams_context.__aexit__(None, None, None)
|
||||||
@@ -7,7 +7,7 @@ from typing import Callable, Dict, List, Optional
|
|||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from khoj.database.adapters import AgentAdapters, EntryAdapters
|
from khoj.database.adapters import AgentAdapters, EntryAdapters, McpServerAdapters
|
||||||
from khoj.database.models import Agent, ChatMessageModel, KhojUser
|
from khoj.database.models import Agent, ChatMessageModel, KhojUser
|
||||||
from khoj.processor.conversation import prompts
|
from khoj.processor.conversation import prompts
|
||||||
from khoj.processor.conversation.utils import (
|
from khoj.processor.conversation.utils import (
|
||||||
@@ -19,6 +19,7 @@ from khoj.processor.conversation.utils import (
|
|||||||
load_complex_json,
|
load_complex_json,
|
||||||
)
|
)
|
||||||
from khoj.processor.operator import operate_environment
|
from khoj.processor.operator import operate_environment
|
||||||
|
from khoj.processor.tools.mcp import MCPClient
|
||||||
from khoj.processor.tools.online_search import read_webpages_content, search_online
|
from khoj.processor.tools.online_search import read_webpages_content, search_online
|
||||||
from khoj.processor.tools.run_code import run_code
|
from khoj.processor.tools.run_code import run_code
|
||||||
from khoj.routers.helpers import (
|
from khoj.routers.helpers import (
|
||||||
@@ -61,6 +62,7 @@ async def apick_next_tool(
|
|||||||
max_document_searches: int = 7,
|
max_document_searches: int = 7,
|
||||||
max_online_searches: int = 3,
|
max_online_searches: int = 3,
|
||||||
max_webpages_to_read: int = 3,
|
max_webpages_to_read: int = 3,
|
||||||
|
mcp_clients: List[MCPClient] = [],
|
||||||
send_status_func: Optional[Callable] = None,
|
send_status_func: Optional[Callable] = None,
|
||||||
tracer: dict = {},
|
tracer: dict = {},
|
||||||
):
|
):
|
||||||
@@ -144,6 +146,23 @@ async def apick_next_tool(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Get MCP tools
|
||||||
|
for mcp_client in mcp_clients:
|
||||||
|
try:
|
||||||
|
mcp_tools = await mcp_client.get_tools()
|
||||||
|
for mcp_tool in mcp_tools:
|
||||||
|
qualified_tool_name = f"{mcp_client.name}/{mcp_tool.name}"
|
||||||
|
tool_options_str += f'- "{qualified_tool_name}": "{mcp_tool.description}"\n'
|
||||||
|
tools.append(
|
||||||
|
ToolDefinition(
|
||||||
|
name=qualified_tool_name,
|
||||||
|
description=mcp_tool.description,
|
||||||
|
schema=mcp_tool.inputSchema,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f'Failed to get tools from MCP server "{mcp_client.name}", so skipping: {e}.')
|
||||||
|
|
||||||
today = datetime.today()
|
today = datetime.today()
|
||||||
location_data = f"{location}" if location else "Unknown"
|
location_data = f"{location}" if location else "Unknown"
|
||||||
agent_chat_model = AgentAdapters.get_agent_chat_model(agent, user) if agent else None
|
agent_chat_model = AgentAdapters.get_agent_chat_model(agent, user) if agent else None
|
||||||
@@ -240,6 +259,10 @@ async def research(
|
|||||||
current_iteration = 0
|
current_iteration = 0
|
||||||
MAX_ITERATIONS = int(os.getenv("KHOJ_RESEARCH_ITERATIONS", 5))
|
MAX_ITERATIONS = int(os.getenv("KHOJ_RESEARCH_ITERATIONS", 5))
|
||||||
|
|
||||||
|
# Construct MCP clients
|
||||||
|
mcp_servers = await McpServerAdapters.aget_all_mcp_servers()
|
||||||
|
mcp_clients = [MCPClient(server.name, server.path, server.api_key) for server in mcp_servers]
|
||||||
|
|
||||||
# Incorporate previous partial research into current research chat history
|
# Incorporate previous partial research into current research chat history
|
||||||
research_conversation_history = [chat for chat in deepcopy(conversation_history) if chat.message]
|
research_conversation_history = [chat for chat in deepcopy(conversation_history) if chat.message]
|
||||||
if current_iteration := len(previous_iterations) > 0:
|
if current_iteration := len(previous_iterations) > 0:
|
||||||
@@ -277,6 +300,7 @@ async def research(
|
|||||||
code_results: Dict = dict()
|
code_results: Dict = dict()
|
||||||
document_results: List[Dict[str, str]] = []
|
document_results: List[Dict[str, str]] = []
|
||||||
operator_results: OperatorRun = None
|
operator_results: OperatorRun = None
|
||||||
|
mcp_results: List = []
|
||||||
this_iteration = ResearchIteration(query=query)
|
this_iteration = ResearchIteration(query=query)
|
||||||
|
|
||||||
async for result in apick_next_tool(
|
async for result in apick_next_tool(
|
||||||
@@ -293,6 +317,7 @@ async def research(
|
|||||||
max_document_searches=max_document_searches,
|
max_document_searches=max_document_searches,
|
||||||
max_online_searches=max_online_searches,
|
max_online_searches=max_online_searches,
|
||||||
max_webpages_to_read=max_webpages_to_read,
|
max_webpages_to_read=max_webpages_to_read,
|
||||||
|
mcp_clients=mcp_clients,
|
||||||
send_status_func=send_status_func,
|
send_status_func=send_status_func,
|
||||||
tracer=tracer,
|
tracer=tracer,
|
||||||
):
|
):
|
||||||
@@ -540,13 +565,41 @@ async def research(
|
|||||||
this_iteration.warning = f"Error searching with regex: {e}"
|
this_iteration.warning = f"Error searching with regex: {e}"
|
||||||
logger.error(this_iteration.warning, exc_info=True)
|
logger.error(this_iteration.warning, exc_info=True)
|
||||||
|
|
||||||
|
elif "/" in this_iteration.query.name:
|
||||||
|
try:
|
||||||
|
# Identify MCP client to use
|
||||||
|
server_name, tool_name = this_iteration.query.name.split("/", 1)
|
||||||
|
mcp_client = next((client for client in mcp_clients if client.name == server_name), None)
|
||||||
|
if not mcp_client:
|
||||||
|
raise ValueError(f"Could not find MCP server with name {server_name}")
|
||||||
|
|
||||||
|
# Invoke tool on the identified MCP server
|
||||||
|
mcp_results = await mcp_client.run_tool(tool_name, this_iteration.query.args)
|
||||||
|
|
||||||
|
# Record tool result in context
|
||||||
|
if this_iteration.context is None:
|
||||||
|
this_iteration.context = []
|
||||||
|
this_iteration.context += mcp_results
|
||||||
|
async for result in send_status_func(f"**Used MCP Tool**: {tool_name} on {mcp_client.name}"):
|
||||||
|
yield result
|
||||||
|
except Exception as e:
|
||||||
|
this_iteration.warning = f"Error using MCP tool: {e}"
|
||||||
|
logger.error(this_iteration.warning, exc_info=True)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# No valid tools. This is our exit condition.
|
# No valid tools. This is our exit condition.
|
||||||
current_iteration = MAX_ITERATIONS
|
current_iteration = MAX_ITERATIONS
|
||||||
|
|
||||||
current_iteration += 1
|
current_iteration += 1
|
||||||
|
|
||||||
if document_results or online_results or code_results or operator_results or this_iteration.warning:
|
if (
|
||||||
|
document_results
|
||||||
|
or online_results
|
||||||
|
or code_results
|
||||||
|
or operator_results
|
||||||
|
or mcp_results
|
||||||
|
or this_iteration.warning
|
||||||
|
):
|
||||||
results_data = f"\n<iteration_{current_iteration}_results>"
|
results_data = f"\n<iteration_{current_iteration}_results>"
|
||||||
if document_results:
|
if document_results:
|
||||||
results_data += f"\n<document_references>\n{yaml.dump(document_results, allow_unicode=True, sort_keys=False, default_flow_style=False)}\n</document_references>"
|
results_data += f"\n<document_references>\n{yaml.dump(document_results, allow_unicode=True, sort_keys=False, default_flow_style=False)}\n</document_references>"
|
||||||
@@ -558,6 +611,8 @@ async def research(
|
|||||||
results_data += (
|
results_data += (
|
||||||
f"\n<browser_operator_results>\n{operator_results.response}\n</browser_operator_results>"
|
f"\n<browser_operator_results>\n{operator_results.response}\n</browser_operator_results>"
|
||||||
)
|
)
|
||||||
|
if mcp_results:
|
||||||
|
results_data += f"\n<mcp_tool_results>\n{yaml.dump(mcp_results, allow_unicode=True, sort_keys=False, default_flow_style=False)}\n</mcp_tool_results>"
|
||||||
if this_iteration.warning:
|
if this_iteration.warning:
|
||||||
results_data += f"\n<warning>\n{this_iteration.warning}\n</warning>"
|
results_data += f"\n<warning>\n{this_iteration.warning}\n</warning>"
|
||||||
results_data += f"\n</iteration_{current_iteration}_results>"
|
results_data += f"\n</iteration_{current_iteration}_results>"
|
||||||
@@ -568,3 +623,7 @@ async def research(
|
|||||||
this_iteration.summarizedResult = this_iteration.summarizedResult or "Failed to get results."
|
this_iteration.summarizedResult = this_iteration.summarizedResult or "Failed to get results."
|
||||||
previous_iterations.append(this_iteration)
|
previous_iterations.append(this_iteration)
|
||||||
yield this_iteration
|
yield this_iteration
|
||||||
|
|
||||||
|
# Close MCP client connections
|
||||||
|
for mcp_client in mcp_clients:
|
||||||
|
await mcp_client.close()
|
||||||
|
|||||||
157
uv.lock
generated
157
uv.lock
generated
@@ -1162,6 +1162,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" },
|
{ 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]]
|
[[package]]
|
||||||
name = "khoj"
|
name = "khoj"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
@@ -1197,6 +1224,7 @@ dependencies = [
|
|||||||
{ name = "magika" },
|
{ name = "magika" },
|
||||||
{ name = "markdown-it-py" },
|
{ name = "markdown-it-py" },
|
||||||
{ name = "markdownify" },
|
{ name = "markdownify" },
|
||||||
|
{ name = "mcp" },
|
||||||
{ name = "openai" },
|
{ name = "openai" },
|
||||||
{ name = "openai-whisper" },
|
{ name = "openai-whisper" },
|
||||||
{ name = "pgvector" },
|
{ name = "pgvector" },
|
||||||
@@ -1296,6 +1324,7 @@ requires-dist = [
|
|||||||
{ name = "magika", specifier = "~=0.5.1" },
|
{ name = "magika", specifier = "~=0.5.1" },
|
||||||
{ name = "markdown-it-py", specifier = "~=3.0.0" },
|
{ name = "markdown-it-py", specifier = "~=3.0.0" },
|
||||||
{ name = "markdownify", specifier = "~=0.11.6" },
|
{ name = "markdownify", specifier = "~=0.11.6" },
|
||||||
|
{ name = "mcp", specifier = ">=1.12.4" },
|
||||||
{ name = "mypy", marker = "extra == 'dev'", specifier = ">=1.0.1" },
|
{ name = "mypy", marker = "extra == 'dev'", specifier = ">=1.0.1" },
|
||||||
{ name = "openai", specifier = ">=2.0.0,<3.0.0" },
|
{ name = "openai", specifier = ">=2.0.0,<3.0.0" },
|
||||||
{ name = "openai-whisper", specifier = ">=20231117" },
|
{ name = "openai-whisper", specifier = ">=20231117" },
|
||||||
@@ -1577,6 +1606,28 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/34/75/51952c7b2d3873b44a0028b1bd26a25078c18f92f256608e8d1dc61b39fd/marshmallow-3.26.1-py3-none-any.whl", hash = "sha256:3350409f20a70a7e4e11a27661187b77cdcaeb20abca41c1454fe33636bea09c", size = 50878, upload-time = "2025-02-03T15:32:22.295Z" },
|
{ url = "https://files.pythonhosted.org/packages/34/75/51952c7b2d3873b44a0028b1bd26a25078c18f92f256608e8d1dc61b39fd/marshmallow-3.26.1-py3-none-any.whl", hash = "sha256:3350409f20a70a7e4e11a27661187b77cdcaeb20abca41c1454fe33636bea09c", size = 50878, upload-time = "2025-02-03T15:32:22.295Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mcp"
|
||||||
|
version = "1.12.4"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
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/31/88/f6cb7e7c260cd4b4ce375f2b1614b33ce401f63af0f49f7141a2e9bf0a45/mcp-1.12.4.tar.gz", hash = "sha256:0765585e9a3a5916a3c3ab8659330e493adc7bd8b2ca6120c2d7a0c43e034ca5", size = 431148, upload-time = "2025-08-07T20:31:18.082Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ad/68/316cbc54b7163fa22571dcf42c9cc46562aae0a021b974e0a8141e897200/mcp-1.12.4-py3-none-any.whl", hash = "sha256:7aa884648969fab8e78b89399d59a683202972e12e6bc9a1c88ce7eda7743789", size = 160145, upload-time = "2025-08-07T20:31:15.69Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mdurl"
|
name = "mdurl"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
@@ -2780,6 +2831,22 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/11/c3/005fcca25ce078d2cc29fd559379817424e94885510568bc1bc53d7d5846/pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725", size = 508002, upload-time = "2024-09-11T02:24:45.8Z" },
|
{ url = "https://files.pythonhosted.org/packages/11/c3/005fcca25ce078d2cc29fd559379817424e94885510568bc1bc53d7d5846/pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725", size = 508002, upload-time = "2024-09-11T02:24:45.8Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pywin32"
|
||||||
|
version = "311"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7b/40/44efbb0dfbd33aca6a6483191dae0716070ed99e2ecb0c53683f400a0b4f/pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3", size = 8760432, upload-time = "2025-07-14T20:13:05.9Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5e/bf/360243b1e953bd254a82f12653974be395ba880e7ec23e3731d9f73921cc/pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b", size = 9590103, upload-time = "2025-07-14T20:13:07.698Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/57/38/d290720e6f138086fb3d5ffe0b6caa019a791dd57866940c82e4eeaf2012/pywin32-311-cp310-cp310-win_arm64.whl", hash = "sha256:0502d1facf1fed4839a9a51ccbcc63d952cf318f78ffc00a7e78528ac27d7a2b", size = 8778557, upload-time = "2025-07-14T20:13:11.11Z" },
|
||||||
|
{ 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]]
|
[[package]]
|
||||||
name = "pyyaml"
|
name = "pyyaml"
|
||||||
version = "6.0.2"
|
version = "6.0.2"
|
||||||
@@ -2834,6 +2901,20 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/ba/12/1e5497183bdbe782dbb91bad1d0d2297dba4d2831b2652657f7517bfc6df/rapidocr_onnxruntime-1.4.4-py3-none-any.whl", hash = "sha256:971d7d5f223a7a808662229df1ef69893809d8457d834e6373d3854bc1782cbf", size = 14915192, upload-time = "2025-01-17T01:48:25.104Z" },
|
{ url = "https://files.pythonhosted.org/packages/ba/12/1e5497183bdbe782dbb91bad1d0d2297dba4d2831b2652657f7517bfc6df/rapidocr_onnxruntime-1.4.4-py3-none-any.whl", hash = "sha256:971d7d5f223a7a808662229df1ef69893809d8457d834e6373d3854bc1782cbf", size = 14915192, upload-time = "2025-01-17T01:48:25.104Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[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]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "2024.11.6"
|
version = "2024.11.6"
|
||||||
@@ -2942,6 +3023,70 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/0d/9b/63f4c7ebc259242c89b3acafdb37b41d1185c07ff0011164674e9076b491/rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0", size = 243229, upload-time = "2025-03-30T14:15:12.283Z" },
|
{ url = "https://files.pythonhosted.org/packages/0d/9b/63f4c7ebc259242c89b3acafdb37b41d1185c07ff0011164674e9076b491/rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0", size = 243229, upload-time = "2025-03-30T14:15:12.283Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[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/82/f8/13bb772dc7cbf2c3c5b816febc34fa0cb2c64a08e0569869585684ce6631/rpds_py-0.28.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:7b6013db815417eeb56b2d9d7324e64fcd4fa289caeee6e7a78b2e11fc9b438a", size = 362820, upload-time = "2025-10-22T22:21:15.074Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/84/91/6acce964aab32469c3dbe792cb041a752d64739c534e9c493c701ef0c032/rpds_py-0.28.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1a4c6b05c685c0c03f80dabaeb73e74218c49deea965ca63f76a752807397207", size = 348499, upload-time = "2025-10-22T22:21:17.658Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f1/93/c05bb1f4f5e0234db7c4917cb8dd5e2e0a9a7b26dc74b1b7bee3c9cfd477/rpds_py-0.28.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4794c6c3fbe8f9ac87699b131a1f26e7b4abcf6d828da46a3a52648c7930eba", size = 379356, upload-time = "2025-10-22T22:21:19.847Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5c/37/e292da436f0773e319753c567263427cdf6c645d30b44f09463ff8216cda/rpds_py-0.28.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2e8456b6ee5527112ff2354dd9087b030e3429e43a74f480d4a5ca79d269fd85", size = 390151, upload-time = "2025-10-22T22:21:21.569Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/76/87/a4e3267131616e8faf10486dc00eaedf09bd61c87f01e5ef98e782ee06c9/rpds_py-0.28.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:beb880a9ca0a117415f241f66d56025c02037f7c4efc6fe59b5b8454f1eaa50d", size = 524831, upload-time = "2025-10-22T22:21:23.394Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e1/c8/4a4ca76f0befae9515da3fad11038f0fce44f6bb60b21fe9d9364dd51fb0/rpds_py-0.28.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6897bebb118c44b38c9cb62a178e09f1593c949391b9a1a6fe777ccab5934ee7", size = 404687, upload-time = "2025-10-22T22:21:25.201Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6a/65/118afe854424456beafbbebc6b34dcf6d72eae3a08b4632bc4220f8240d9/rpds_py-0.28.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1b553dd06e875249fd43efd727785efb57a53180e0fde321468222eabbeaafa", size = 382683, upload-time = "2025-10-22T22:21:26.536Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f7/bc/0625064041fb3a0c77ecc8878c0e8341b0ae27ad0f00cf8f2b57337a1e63/rpds_py-0.28.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:f0b2044fdddeea5b05df832e50d2a06fe61023acb44d76978e1b060206a8a476", size = 398927, upload-time = "2025-10-22T22:21:27.864Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5d/1a/fed7cf2f1ee8a5e4778f2054153f2cfcf517748875e2f5b21cf8907cd77d/rpds_py-0.28.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05cf1e74900e8da73fa08cc76c74a03345e5a3e37691d07cfe2092d7d8e27b04", size = 411590, upload-time = "2025-10-22T22:21:29.474Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c1/64/a8e0f67fa374a6c472dbb0afdaf1ef744724f165abb6899f20e2f1563137/rpds_py-0.28.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:efd489fec7c311dae25e94fe7eeda4b3d06be71c68f2cf2e8ef990ffcd2cd7e8", size = 559843, upload-time = "2025-10-22T22:21:30.917Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a9/ea/e10353f6d7c105be09b8135b72787a65919971ae0330ad97d87e4e199880/rpds_py-0.28.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:ada7754a10faacd4f26067e62de52d6af93b6d9542f0df73c57b9771eb3ba9c4", size = 584188, upload-time = "2025-10-22T22:21:32.827Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/18/b0/a19743e0763caf0c89f6fc6ba6fbd9a353b24ffb4256a492420c5517da5a/rpds_py-0.28.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c2a34fd26588949e1e7977cfcbb17a9a42c948c100cab890c6d8d823f0586457", size = 550052, upload-time = "2025-10-22T22:21:34.702Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/de/bc/ec2c004f6c7d6ab1e25dae875cdb1aee087c3ebed5b73712ed3000e3851a/rpds_py-0.28.0-cp310-cp310-win32.whl", hash = "sha256:f9174471d6920cbc5e82a7822de8dfd4dcea86eb828b04fc8c6519a77b0ee51e", size = 215110, upload-time = "2025-10-22T22:21:36.645Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6c/de/4ce8abf59674e17187023933547d2018363e8fc76ada4f1d4d22871ccb6e/rpds_py-0.28.0-cp310-cp310-win_amd64.whl", hash = "sha256:6e32dd207e2c4f8475257a3540ab8a93eff997abfa0a3fdb287cae0d6cd874b8", size = 223850, upload-time = "2025-10-22T22:21:38.006Z" },
|
||||||
|
{ 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]]
|
[[package]]
|
||||||
name = "rsa"
|
name = "rsa"
|
||||||
version = "4.9.1"
|
version = "4.9.1"
|
||||||
@@ -3233,6 +3378,18 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/a9/5c/bfd6bd0bf979426d405cc6e71eceb8701b148b16c21d2dc3c261efc61c7b/sqlparse-0.5.3-py3-none-any.whl", hash = "sha256:cf2196ed3418f3ba5de6af7e82c694a9fbdbfecccdfc72e281548517081f16ca", size = 44415, upload-time = "2024-12-10T12:05:27.824Z" },
|
{ url = "https://files.pythonhosted.org/packages/a9/5c/bfd6bd0bf979426d405cc6e71eceb8701b148b16c21d2dc3c261efc61c7b/sqlparse-0.5.3-py3-none-any.whl", hash = "sha256:cf2196ed3418f3ba5de6af7e82c694a9fbdbfecccdfc72e281548517081f16ca", size = 44415, upload-time = "2024-12-10T12:05:27.824Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[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]]
|
[[package]]
|
||||||
name = "starlette"
|
name = "starlette"
|
||||||
version = "0.46.2"
|
version = "0.46.2"
|
||||||
|
|||||||
Reference in New Issue
Block a user