Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
from pydantic import SecretStr

from openhands.sdk import LLM, Agent, AgentContext, Conversation
from openhands.sdk.context.skills import (
from openhands.sdk.skills import (
discover_skill_resources,
load_skills_from_dir,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
load_all_skills,
sync_public_skills,
)
from openhands.sdk.context.skills.skill import DEFAULT_MARKETPLACE_PATH
from openhands.sdk.skills.skill import DEFAULT_MARKETPLACE_PATH


skills_router = APIRouter(prefix="/skills", tags=["Skills"])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,21 @@
from dataclasses import dataclass
from pathlib import Path

from openhands.sdk.context.skills import (
from openhands.sdk.logger import get_logger
from openhands.sdk.skills import (
Skill,
load_available_skills,
)
from openhands.sdk.context.skills.skill import (
from openhands.sdk.skills.skill import (
DEFAULT_MARKETPLACE_PATH,
PUBLIC_SKILLS_BRANCH,
PUBLIC_SKILLS_REPO,
load_skills_from_dir,
)
from openhands.sdk.context.skills.utils import (
from openhands.sdk.skills.utils import (
get_skills_cache_dir,
update_skills_repository,
)
from openhands.sdk.logger import get_logger
from openhands.sdk.utils import sanitized_env


Expand Down
12 changes: 6 additions & 6 deletions openhands-sdk/openhands/sdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,7 @@
AgentBase,
)
from openhands.sdk.banner import _print_banner
from openhands.sdk.context import (
AgentContext,
load_project_skills,
load_skills_from_dir,
load_user_skills,
)
from openhands.sdk.context import AgentContext
from openhands.sdk.context.condenser import (
LLMSummarizingCondenser,
)
Expand Down Expand Up @@ -65,6 +60,11 @@
SettingsSectionMetadata,
field_meta,
)
from openhands.sdk.skills import (
load_project_skills,
load_skills_from_dir,
load_user_skills,
)
from openhands.sdk.subagent import (
agent_definition_to_factory,
load_agents_from_dir,
Expand Down
4 changes: 3 additions & 1 deletion openhands-sdk/openhands/sdk/context/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from openhands.sdk.context.agent_context import AgentContext
from openhands.sdk.context.prompts import render_template
from openhands.sdk.context.skills import (

# Import from canonical location (openhands.sdk.skills)
from openhands.sdk.skills import (
BaseTrigger,
KeywordTrigger,
Skill,
Expand Down
12 changes: 6 additions & 6 deletions openhands-sdk/openhands/sdk/context/agent_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@
from pydantic import BaseModel, Field, field_validator, model_validator

from openhands.sdk.context.prompts import render_template
from openhands.sdk.context.skills import (
from openhands.sdk.llm import Message, TextContent
from openhands.sdk.llm.utils.model_prompt_spec import get_model_prompt_spec
from openhands.sdk.logger import get_logger
from openhands.sdk.secret import SecretSource, SecretValue
from openhands.sdk.skills import (
Skill,
SkillKnowledge,
load_available_skills,
to_prompt,
)
from openhands.sdk.context.skills.skill import DEFAULT_MARKETPLACE_PATH
from openhands.sdk.llm import Message, TextContent
from openhands.sdk.llm.utils.model_prompt_spec import get_model_prompt_spec
from openhands.sdk.logger import get_logger
from openhands.sdk.secret import SecretSource, SecretValue
from openhands.sdk.skills.skill import DEFAULT_MARKETPLACE_PATH


logger = get_logger(__name__)
Expand Down
140 changes: 111 additions & 29 deletions openhands-sdk/openhands/sdk/context/skills/__init__.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,124 @@
from openhands.sdk.context.skills.exceptions import SkillValidationError
from openhands.sdk.context.skills.skill import (
Skill,
SkillResources,
load_available_skills,
load_project_skills,
load_public_skills,
load_skills_from_dir,
load_user_skills,
to_prompt,
)
from openhands.sdk.context.skills.trigger import (
BaseTrigger,
KeywordTrigger,
TaskTrigger,
)
from openhands.sdk.context.skills.types import SkillKnowledge
from openhands.sdk.context.skills.utils import (
RESOURCE_DIRECTORIES,
discover_skill_resources,
validate_skill_name,
)
"""Deprecated: Use openhands.sdk.skills instead.

This module is deprecated and will be removed in a future version.
All skill-related imports should come from `openhands.sdk.skills`.

Migration guide:
# Old (deprecated):
from openhands.sdk.context.skills import Skill, load_skills_from_dir

# New:
from openhands.sdk.skills import Skill, load_skills_from_dir
"""

from openhands.sdk.utils.deprecation import warn_deprecated


def __getattr__(name: str):
"""Lazily import from openhands.sdk.skills with deprecation warning."""
# Import the canonical module
from openhands.sdk import skills as _skills

# List of valid exports that we re-export with deprecation warning
_VALID_EXPORTS = {
# Exceptions
"SkillError",
"SkillValidationError",
# Core skill model and loading
"Skill",
"SkillInfo",
"SkillResources",
"load_skills_from_dir",
"load_project_skills",
"load_user_skills",
"load_public_skills",
"load_available_skills",
"to_prompt",
# Triggers
"BaseTrigger",
"KeywordTrigger",
"TaskTrigger",
# Types
"SkillKnowledge",
"InputMetadata",
"SkillResponse",
"SkillContentResponse",
# Utilities
"discover_skill_resources",
"RESOURCE_DIRECTORIES",
"validate_skill_name",
}

if name in _VALID_EXPORTS:
warn_deprecated(
f"Importing '{name}' from 'openhands.sdk.context.skills'",
deprecated_in="1.16.0",
removed_in="1.20.0",
details=f"Use 'from openhands.sdk.skills import {name}' instead.",
stacklevel=3,
)
return getattr(_skills, name)

raise AttributeError(f"module {__name__!r} has no attribute {name!r}")


def __dir__():
"""List available attributes for tab-completion."""
return [
# Exceptions
"SkillError",
"SkillValidationError",
# Core skill model and loading
"Skill",
"SkillInfo",
"SkillResources",
"load_skills_from_dir",
"load_project_skills",
"load_user_skills",
"load_public_skills",
"load_available_skills",
"to_prompt",
# Triggers
"BaseTrigger",
"KeywordTrigger",
"TaskTrigger",
# Types
"SkillKnowledge",
"InputMetadata",
"SkillResponse",
"SkillContentResponse",
# Utilities
"discover_skill_resources",
"RESOURCE_DIRECTORIES",
"validate_skill_name",
]


__all__ = [
# Exceptions
"SkillError",
"SkillValidationError",
# Core skill model and loading
"Skill",
"SkillInfo",
"SkillResources",
"load_skills_from_dir",
"load_project_skills",
"load_user_skills",
"load_public_skills",
"load_available_skills",
"to_prompt",
# Triggers
"BaseTrigger",
"KeywordTrigger",
"TaskTrigger",
# Types
"SkillKnowledge",
"load_available_skills",
"load_skills_from_dir",
"load_user_skills",
"load_project_skills",
"load_public_skills",
"SkillValidationError",
"InputMetadata",
"SkillResponse",
"SkillContentResponse",
# Utilities
"discover_skill_resources",
"RESOURCE_DIRECTORIES",
"to_prompt",
"validate_skill_name",
]
12 changes: 6 additions & 6 deletions openhands-sdk/openhands/sdk/plugin/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@

from pydantic import BaseModel, Field

from openhands.sdk.context.skills import Skill
from openhands.sdk.context.skills.utils import (
discover_skill_resources,
find_skill_md,
load_mcp_config,
)
from openhands.sdk.hooks import HookConfig
from openhands.sdk.logger import get_logger
from openhands.sdk.plugin.fetch import fetch_plugin
Expand All @@ -22,6 +16,12 @@
PluginAuthor,
PluginManifest,
)
from openhands.sdk.skills.skill import Skill
from openhands.sdk.skills.utils import (
discover_skill_resources,
find_skill_md,
load_mcp_config,
)
from openhands.sdk.subagent.schema import AgentDefinition


Expand Down
6 changes: 3 additions & 3 deletions openhands-sdk/openhands/sdk/plugin/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ def to_plugin_source(self) -> PluginSource:


if TYPE_CHECKING:
from openhands.sdk.context.skills import Skill
from openhands.sdk.skills.skill import Skill


class PluginAuthor(BaseModel):
Expand Down Expand Up @@ -335,8 +335,8 @@ def to_skill(self, plugin_name: str) -> Skill:
- Trigger keyword: "/city-weather:now"
- When user types "/city-weather:now Tokyo", the skill activates
"""
from openhands.sdk.context.skills import Skill
from openhands.sdk.context.skills.trigger import KeywordTrigger
from openhands.sdk.skills.skill import Skill
from openhands.sdk.skills.trigger import KeywordTrigger

# Build the trigger keyword in Claude Code namespace format
trigger_keyword = f"/{plugin_name}:{self.name}"
Expand Down
Loading
Loading