mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-02 21:19:12 +00:00
Require explicit switch to enable operator locally for now
Operator is still early in development. To enable it: - Set KHOJ_OPERATOR_ENABLE environment variable to true - Run any one of the commands below: - `pip install khoj[local]' - `pip install khoj[dev]' - `pip install playwright'
This commit is contained in:
@@ -93,7 +93,6 @@ 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",
|
||||||
"playwright >= 1.49.0",
|
|
||||||
]
|
]
|
||||||
dynamic = ["version"]
|
dynamic = ["version"]
|
||||||
|
|
||||||
@@ -114,6 +113,7 @@ prod = [
|
|||||||
]
|
]
|
||||||
local = [
|
local = [
|
||||||
"pgserver == 0.1.4",
|
"pgserver == 0.1.4",
|
||||||
|
"playwright >= 1.49.0",
|
||||||
]
|
]
|
||||||
dev = [
|
dev = [
|
||||||
"khoj[prod,local]",
|
"khoj[prod,local]",
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ import logging
|
|||||||
import os
|
import os
|
||||||
from typing import Optional, Set
|
from typing import Optional, Set
|
||||||
|
|
||||||
from playwright.async_api import Browser, Page, Playwright, async_playwright
|
|
||||||
|
|
||||||
from khoj.processor.operator.operator_actions import OperatorAction
|
from khoj.processor.operator.operator_actions import OperatorAction
|
||||||
from khoj.processor.operator.operator_environment_base import (
|
from khoj.processor.operator.operator_environment_base import (
|
||||||
Environment,
|
Environment,
|
||||||
@@ -16,6 +14,13 @@ from khoj.utils.helpers import convert_image_to_webp
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
try:
|
||||||
|
from playwright.async_api import Browser, Page, Playwright, async_playwright
|
||||||
|
except ImportError:
|
||||||
|
logger.debug(
|
||||||
|
"Playwright not found. To use browser operator, run 'pip install playwright' and 'playwright install' first."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# --- Concrete BrowserEnvironment ---
|
# --- Concrete BrowserEnvironment ---
|
||||||
class BrowserEnvironment(Environment):
|
class BrowserEnvironment(Environment):
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ from khoj.utils.helpers import (
|
|||||||
get_country_name_from_timezone,
|
get_country_name_from_timezone,
|
||||||
get_device,
|
get_device,
|
||||||
is_none_or_empty,
|
is_none_or_empty,
|
||||||
|
is_operator_enabled,
|
||||||
)
|
)
|
||||||
from khoj.utils.rawconfig import (
|
from khoj.utils.rawconfig import (
|
||||||
ChatRequestBody,
|
ChatRequestBody,
|
||||||
@@ -570,6 +571,8 @@ async def chat_options(
|
|||||||
) -> Response:
|
) -> Response:
|
||||||
cmd_options = {}
|
cmd_options = {}
|
||||||
for cmd in ConversationCommand:
|
for cmd in ConversationCommand:
|
||||||
|
if cmd == ConversationCommand.Operator and not is_operator_enabled():
|
||||||
|
continue
|
||||||
if cmd in command_descriptions:
|
if cmd in command_descriptions:
|
||||||
cmd_options[cmd.value] = command_descriptions[cmd]
|
cmd_options[cmd.value] = command_descriptions[cmd]
|
||||||
|
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ from khoj.utils.helpers import (
|
|||||||
get_file_type,
|
get_file_type,
|
||||||
in_debug_mode,
|
in_debug_mode,
|
||||||
is_none_or_empty,
|
is_none_or_empty,
|
||||||
|
is_operator_enabled,
|
||||||
is_valid_url,
|
is_valid_url,
|
||||||
log_telemetry,
|
log_telemetry,
|
||||||
mode_descriptions_for_llm,
|
mode_descriptions_for_llm,
|
||||||
@@ -253,7 +254,7 @@ def get_conversation_command(query: str) -> ConversationCommand:
|
|||||||
return ConversationCommand.Code
|
return ConversationCommand.Code
|
||||||
elif query.startswith("/research"):
|
elif query.startswith("/research"):
|
||||||
return ConversationCommand.Research
|
return ConversationCommand.Research
|
||||||
elif query.startswith("/operator"):
|
elif query.startswith("/operator") and is_operator_enabled():
|
||||||
return ConversationCommand.Operator
|
return ConversationCommand.Operator
|
||||||
else:
|
else:
|
||||||
return ConversationCommand.Default
|
return ConversationCommand.Default
|
||||||
@@ -364,6 +365,8 @@ async def aget_data_sources_and_output_format(
|
|||||||
# Skip showing Notes tool as an option if user has no entries
|
# Skip showing Notes tool as an option if user has no entries
|
||||||
if source == ConversationCommand.Notes and not user_has_entries:
|
if source == ConversationCommand.Notes and not user_has_entries:
|
||||||
continue
|
continue
|
||||||
|
if source == ConversationCommand.Operator and not is_operator_enabled():
|
||||||
|
continue
|
||||||
source_options[source.value] = description
|
source_options[source.value] = description
|
||||||
if len(agent_sources) == 0 or source.value in agent_sources:
|
if len(agent_sources) == 0 or source.value in agent_sources:
|
||||||
source_options_str += f'- "{source.value}": "{description}"\n'
|
source_options_str += f'- "{source.value}": "{description}"\n'
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ from khoj.routers.helpers import (
|
|||||||
from khoj.utils.helpers import (
|
from khoj.utils.helpers import (
|
||||||
ConversationCommand,
|
ConversationCommand,
|
||||||
is_none_or_empty,
|
is_none_or_empty,
|
||||||
|
is_operator_enabled,
|
||||||
timer,
|
timer,
|
||||||
tool_description_for_research_llm,
|
tool_description_for_research_llm,
|
||||||
truncate_code_context,
|
truncate_code_context,
|
||||||
@@ -99,6 +100,9 @@ async def apick_next_tool(
|
|||||||
agent_tools = agent.input_tools if agent else []
|
agent_tools = agent.input_tools if agent else []
|
||||||
user_has_entries = await EntryAdapters.auser_has_entries(user)
|
user_has_entries = await EntryAdapters.auser_has_entries(user)
|
||||||
for tool, description in tool_description_for_research_llm.items():
|
for tool, description in tool_description_for_research_llm.items():
|
||||||
|
# Skip showing operator tool as an option if not enabled
|
||||||
|
if tool == ConversationCommand.Operator and not is_operator_enabled():
|
||||||
|
continue
|
||||||
# Skip showing Notes tool as an option if user has no entries
|
# Skip showing Notes tool as an option if user has no entries
|
||||||
if tool == ConversationCommand.Notes:
|
if tool == ConversationCommand.Notes:
|
||||||
if not user_has_entries:
|
if not user_has_entries:
|
||||||
|
|||||||
@@ -490,6 +490,18 @@ def is_promptrace_enabled():
|
|||||||
return not is_none_or_empty(os.getenv("PROMPTRACE_DIR"))
|
return not is_none_or_empty(os.getenv("PROMPTRACE_DIR"))
|
||||||
|
|
||||||
|
|
||||||
|
def is_operator_enabled():
|
||||||
|
"""Check if Khoj can operate GUI applications.
|
||||||
|
Set KHOJ_OPERATOR_ENABLED env var to true and install playwright to enable it."""
|
||||||
|
try:
|
||||||
|
import playwright
|
||||||
|
|
||||||
|
is_playwright_installed = True
|
||||||
|
except ImportError:
|
||||||
|
is_playwright_installed = False
|
||||||
|
return is_env_var_true("KHOJ_OPERATOR_ENABLED") and is_playwright_installed
|
||||||
|
|
||||||
|
|
||||||
def is_valid_url(url: str) -> bool:
|
def is_valid_url(url: str) -> bool:
|
||||||
"""Check if a string is a valid URL"""
|
"""Check if a string is a valid URL"""
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user