refactor: clean up legacy code, rename hopper to entity_extractor, and add third-party notices

- Add NOTICE file and README license references for mobile-use and finalrun-agent
- Add derivative attribution headers to 17 files derived from mobile-use
- Rename hopper agent to entity_extractor across prompts, tools, and configs
- Remove obsolete adb_tunnel, ApiBaseUrl, and legacy CLI utility scripts
- Replace legacy examples with native Artemis diagnostic and workflow examples
- Update unit and tool tests to validate entity_extractor and SDK builders
This commit is contained in:
somew1nd committed 2026-09-11 16:19:42 -07:00
1 parent 0860788192
commit 54fcef9887
83 files changed
+1996 -3660

No files matched your search

+2 -2
View File
@@ -83,6 +83,7 @@ from artemis.config.constants import (
ENV_ARTEMIS_TRACES_DIR,
ENV_ARTEMIS_USE_FILE_API,
ENV_ARTEMIS_USE_USER_DIR,
ENV_OPENROUTER_API_KEY,
ENV_OPEN_ROUTER_API_KEY,
ENV_OPENAI_API_KEY,
ENV_OPENAI_BASE_URL,
@@ -100,7 +101,6 @@ from artemis.config.constants import (
LLMUtilsNodeWithFallback,
)
from artemis.config.llm import (
CyFunctionDetector,
LLM,
LLMConfig,
LLMConfigUtils,
@@ -196,7 +196,6 @@ __all__ = [
"get_ls_address_file",
"is_frozen_bundle",
# LLM Config & Models
"CyFunctionDetector",
"LLM",
"LLMWithFallback",
"LLMConfigUtils",
@@ -296,6 +295,7 @@ __all__ = [
"ENV_OPENAI_API_KEY",
"ENV_OPENAI_BASE_URL",
"ENV_ANTHROPIC_API_KEY",
"ENV_OPENROUTER_API_KEY",
"ENV_OPEN_ROUTER_API_KEY",
"ENV_XAI_API_KEY",
"ENV_ARTEMIS_EXPLORER_VERSION",
+2 -1
View File
@@ -62,6 +62,7 @@ ENV_API_KEY = "API_KEY"
ENV_OPENAI_API_KEY = "OPENAI_API_KEY"
ENV_OPENAI_BASE_URL = "OPENAI_BASE_URL"
ENV_ANTHROPIC_API_KEY = "ANTHROPIC_API_KEY"
ENV_OPENROUTER_API_KEY = "OPENROUTER_API_KEY"
ENV_OPEN_ROUTER_API_KEY = "OPEN_ROUTER_API_KEY"
ENV_XAI_API_KEY = "XAI_API_KEY"
@@ -125,7 +126,7 @@ ExplorerVersion = Literal["flash", "pro", "ultra"]
LLMUtilsNode = Literal[
"outputter",
"hopper",
"entity_extractor",
"video_analyzer",
"object_detector",
]
+7 -30
View File
@@ -48,30 +48,11 @@ def validate_vertex_ai_credentials() -> None:
)
class _CyFunctionDetectorMeta(type):
def __instancecheck__(self, instance):
name = type(instance).__name__
return (
name
in (
"cyfunction",
"cython_function_or_method",
"builtin_function_or_method",
)
or "cyfunction" in name.lower()
)
class CyFunctionDetector(metaclass=_CyFunctionDetectorMeta):
"""Utility type detector for Cython and C-extension functions in Pydantic."""
pass
class LLM(BaseModel):
"""Base model representing an LLM model provider and runtime parameters."""
model_config = {"ignored_types": (CyFunctionDetector,)}
provider: LLMProvider
model: str
temperature: float | None = None
@@ -95,8 +76,8 @@ class LLM(BaseModel):
if not (settings.ANTHROPIC_API_KEY or os.environ.get("ANTHROPIC_API_KEY")):
raise Exception(f"{name} requires ANTHROPIC_API_KEY in .env")
elif self.provider == "openrouter":
if not settings.OPEN_ROUTER_API_KEY:
raise Exception(f"{name} requires OPEN_ROUTER_API_KEY in .env")
if not (settings.OPENROUTER_API_KEY or settings.OPEN_ROUTER_API_KEY):
raise Exception(f"{name} requires OPENROUTER_API_KEY in .env")
elif self.provider == "xai":
if not settings.XAI_API_KEY:
raise Exception(f"{name} requires XAI_API_KEY in .env")
@@ -133,18 +114,14 @@ def lightweight_judge_default() -> "LLMWithFallback":
class LLMConfigUtils(BaseModel):
"""Configuration container for auxiliary utility agents/nodes."""
model_config = {"ignored_types": (CyFunctionDetector,)}
outputter: LLMWithFallback
hopper: LLMWithFallback
entity_extractor: LLMWithFallback
video_analyzer: LLMWithFallback | None = None
object_detector: LLMWithFallback | None = None
class LLMConfig(BaseModel):
"""Comprehensive LLM configuration mapping every node to primary/fallback models."""
model_config = {"ignored_types": (CyFunctionDetector,)}
planner: LLMWithFallback
utils: LLMConfigUtils
summarizer: LLMWithFallback
@@ -167,7 +144,7 @@ class LLMConfig(BaseModel):
"""Validate credentials across all configured agent nodes."""
self.planner.validate_provider("Planner")
self.utils.outputter.validate_provider("Outputter")
self.utils.hopper.validate_provider("Hopper")
self.utils.entity_extractor.validate_provider("EntityExtractor")
if self.utils.video_analyzer:
self.utils.video_analyzer.validate_provider("VideoAnalyzer")
if self.utils.object_detector:
@@ -196,7 +173,7 @@ class LLMConfig(BaseModel):
return f"""
📃 Planner: {self.planner}
🧩 Utils:
🔽 Hopper: {self.utils.hopper}
🔍 Entity Extractor: {self.utils.entity_extractor}
📝 Outputter: {self.utils.outputter}
🎬 Video Analyzer: {self.utils.video_analyzer or "Not configured"}
👁️ Object Detector: {self.utils.object_detector or "Not configured"}
@@ -219,7 +196,7 @@ class LLMConfig(BaseModel):
def get_utils(self, item: LLMUtilsNode) -> LLMWithFallback:
"""Retrieve model configuration for a specific utility node."""
value = getattr(self.utils, item)
value = getattr(self.utils, item, None)
if value is None:
raise ValueError(
f"Utils '{item}' is not configured. Please add it to your LLM "
@@ -264,7 +241,7 @@ def _expand_default_into_nodes(config_dict: dict) -> dict:
all_utils_nodes = [
"outputter",
"hopper",
"entity_extractor",
"video_analyzer",
"object_detector",
]
-3
View File
@@ -26,7 +26,6 @@ from artemis.config.constants import (
ENV_EVENTS_OUTPUT_PATH,
ENV_RESULTS_OUTPUT_PATH,
)
from artemis.config.llm import CyFunctionDetector
from artemis.utils.logger import get_logger
logger = get_logger(__name__)
@@ -34,8 +33,6 @@ logger = get_logger(__name__)
class OutputConfig(BaseModel):
"""Configuration for structured output formatting and schemas."""
model_config = {"ignored_types": (CyFunctionDetector,)}
structured_output: Annotated[
type[BaseModel] | dict | None,
Field(
+19 -5
View File
@@ -18,7 +18,7 @@ import os
from pathlib import Path
from dotenv import load_dotenv
from pydantic import Field, SecretStr, model_validator
from pydantic import AliasChoices, Field, SecretStr, model_validator
from pydantic_settings import BaseSettings
from artemis.config.constants import (
@@ -32,6 +32,7 @@ from artemis.config.constants import (
ENV_GEMINI_API_KEY,
ENV_GOOGLE_API_KEY,
ENV_OCR_API_KEY,
ENV_OPENROUTER_API_KEY,
ENV_OPEN_ROUTER_API_KEY,
ENV_OPENAI_API_KEY,
ENV_VISION_API_KEY,
@@ -99,6 +100,10 @@ class Settings(BaseSettings):
GCP_API_KEY: SecretStr | None = None
ANTHROPIC_API_KEY: SecretStr | None = None
XAI_API_KEY: SecretStr | None = None
OPENROUTER_API_KEY: SecretStr | None = Field(
default=None,
validation_alias=AliasChoices("OPENROUTER_API_KEY", "OPEN_ROUTER_API_KEY"),
)
OPEN_ROUTER_API_KEY: SecretStr | None = None
# Google Cloud Vision OCR Authentication
@@ -163,6 +168,7 @@ class Settings(BaseSettings):
"GCP_API_KEY",
"ANTHROPIC_API_KEY",
"XAI_API_KEY",
"OPENROUTER_API_KEY",
"OPEN_ROUTER_API_KEY",
"OCR_API_KEY",
"VISION_API_KEY",
@@ -172,6 +178,12 @@ class Settings(BaseSettings):
if val and is_placeholder_key(val):
setattr(self, attr, None)
# Synchronize OpenRouter keys
if not self.OPENROUTER_API_KEY and self.OPEN_ROUTER_API_KEY:
self.OPENROUTER_API_KEY = self.OPEN_ROUTER_API_KEY
elif not self.OPEN_ROUTER_API_KEY and self.OPENROUTER_API_KEY:
self.OPEN_ROUTER_API_KEY = self.OPENROUTER_API_KEY
if not self.GOOGLE_API_KEY:
if self.GEMINI_API_KEY:
self.GOOGLE_API_KEY = self.GEMINI_API_KEY
@@ -204,8 +216,8 @@ class Settings(BaseSettings):
key = self.OPENAI_API_KEY
elif provider_lower in ("anthropic", "claude"):
key = self.ANTHROPIC_API_KEY
elif provider_lower == "openrouter":
key = self.OPEN_ROUTER_API_KEY
elif provider_lower in ("openrouter", "open_router"):
key = self.OPENROUTER_API_KEY or self.OPEN_ROUTER_API_KEY
elif provider_lower in ("xai", "grok"):
key = self.XAI_API_KEY
@@ -243,9 +255,11 @@ class Settings(BaseSettings):
self.ANTHROPIC_API_KEY = secret
env_key_name = ENV_ANTHROPIC_API_KEY
os.environ[ENV_ANTHROPIC_API_KEY] = key
elif provider_lower == "openrouter":
elif provider_lower in ("openrouter", "open_router"):
self.OPENROUTER_API_KEY = secret
self.OPEN_ROUTER_API_KEY = secret
env_key_name = ENV_OPEN_ROUTER_API_KEY
env_key_name = ENV_OPENROUTER_API_KEY
os.environ[ENV_OPENROUTER_API_KEY] = key
os.environ[ENV_OPEN_ROUTER_API_KEY] = key
elif provider_lower == "xai":
self.XAI_API_KEY = secret