Skip to content

Commit 541e888

Browse files
Unify skills modules: move context/skills to sdk/skills (#2774)
Co-authored-by: openhands <openhands@all-hands.dev>
1 parent e220bda commit 541e888

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+342
-157
lines changed

examples/05_skills_and_plugins/01_loading_agentskills/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
from pydantic import SecretStr
2828

2929
from openhands.sdk import LLM, Agent, AgentContext, Conversation
30-
from openhands.sdk.context.skills import (
30+
from openhands.sdk.skills import (
3131
discover_skill_resources,
3232
load_skills_from_dir,
3333
)

openhands-agent-server/openhands/agent_server/skills_router.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
load_all_skills,
1515
sync_public_skills,
1616
)
17-
from openhands.sdk.context.skills.skill import DEFAULT_MARKETPLACE_PATH
17+
from openhands.sdk.skills.skill import DEFAULT_MARKETPLACE_PATH
1818

1919

2020
skills_router = APIRouter(prefix="/skills", tags=["Skills"])

openhands-agent-server/openhands/agent_server/skills_service.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,21 @@
2020
from dataclasses import dataclass
2121
from pathlib import Path
2222

23-
from openhands.sdk.context.skills import (
23+
from openhands.sdk.logger import get_logger
24+
from openhands.sdk.skills import (
2425
Skill,
2526
load_available_skills,
2627
)
27-
from openhands.sdk.context.skills.skill import (
28+
from openhands.sdk.skills.skill import (
2829
DEFAULT_MARKETPLACE_PATH,
2930
PUBLIC_SKILLS_BRANCH,
3031
PUBLIC_SKILLS_REPO,
3132
load_skills_from_dir,
3233
)
33-
from openhands.sdk.context.skills.utils import (
34+
from openhands.sdk.skills.utils import (
3435
get_skills_cache_dir,
3536
update_skills_repository,
3637
)
37-
from openhands.sdk.logger import get_logger
3838
from openhands.sdk.utils import sanitized_env
3939

4040

openhands-sdk/openhands/sdk/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,7 @@
55
AgentBase,
66
)
77
from openhands.sdk.banner import _print_banner
8-
from openhands.sdk.context import (
9-
AgentContext,
10-
load_project_skills,
11-
load_skills_from_dir,
12-
load_user_skills,
13-
)
8+
from openhands.sdk.context import AgentContext
149
from openhands.sdk.context.condenser import (
1510
LLMSummarizingCondenser,
1611
)
@@ -65,6 +60,11 @@
6560
SettingsSectionMetadata,
6661
field_meta,
6762
)
63+
from openhands.sdk.skills import (
64+
load_project_skills,
65+
load_skills_from_dir,
66+
load_user_skills,
67+
)
6868
from openhands.sdk.subagent import (
6969
agent_definition_to_factory,
7070
load_agents_from_dir,

openhands-sdk/openhands/sdk/context/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from openhands.sdk.context.agent_context import AgentContext
22
from openhands.sdk.context.prompts import render_template
3-
from openhands.sdk.context.skills import (
3+
4+
# Import from canonical location (openhands.sdk.skills)
5+
from openhands.sdk.skills import (
46
BaseTrigger,
57
KeywordTrigger,
68
Skill,

openhands-sdk/openhands/sdk/context/agent_context.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@
77
from pydantic import BaseModel, Field, field_validator, model_validator
88

99
from openhands.sdk.context.prompts import render_template
10-
from openhands.sdk.context.skills import (
10+
from openhands.sdk.llm import Message, TextContent
11+
from openhands.sdk.llm.utils.model_prompt_spec import get_model_prompt_spec
12+
from openhands.sdk.logger import get_logger
13+
from openhands.sdk.secret import SecretSource, SecretValue
14+
from openhands.sdk.skills import (
1115
Skill,
1216
SkillKnowledge,
1317
load_available_skills,
1418
to_prompt,
1519
)
16-
from openhands.sdk.context.skills.skill import DEFAULT_MARKETPLACE_PATH
17-
from openhands.sdk.llm import Message, TextContent
18-
from openhands.sdk.llm.utils.model_prompt_spec import get_model_prompt_spec
19-
from openhands.sdk.logger import get_logger
20-
from openhands.sdk.secret import SecretSource, SecretValue
20+
from openhands.sdk.skills.skill import DEFAULT_MARKETPLACE_PATH
2121

2222

2323
logger = get_logger(__name__)
Lines changed: 111 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,124 @@
1-
from openhands.sdk.context.skills.exceptions import SkillValidationError
2-
from openhands.sdk.context.skills.skill import (
3-
Skill,
4-
SkillResources,
5-
load_available_skills,
6-
load_project_skills,
7-
load_public_skills,
8-
load_skills_from_dir,
9-
load_user_skills,
10-
to_prompt,
11-
)
12-
from openhands.sdk.context.skills.trigger import (
13-
BaseTrigger,
14-
KeywordTrigger,
15-
TaskTrigger,
16-
)
17-
from openhands.sdk.context.skills.types import SkillKnowledge
18-
from openhands.sdk.context.skills.utils import (
19-
RESOURCE_DIRECTORIES,
20-
discover_skill_resources,
21-
validate_skill_name,
22-
)
1+
"""Deprecated: Use openhands.sdk.skills instead.
2+
3+
This module is deprecated and will be removed in a future version.
4+
All skill-related imports should come from `openhands.sdk.skills`.
5+
6+
Migration guide:
7+
# Old (deprecated):
8+
from openhands.sdk.context.skills import Skill, load_skills_from_dir
9+
10+
# New:
11+
from openhands.sdk.skills import Skill, load_skills_from_dir
12+
"""
13+
14+
from openhands.sdk.utils.deprecation import warn_deprecated
15+
16+
17+
def __getattr__(name: str):
18+
"""Lazily import from openhands.sdk.skills with deprecation warning."""
19+
# Import the canonical module
20+
from openhands.sdk import skills as _skills
21+
22+
# List of valid exports that we re-export with deprecation warning
23+
_VALID_EXPORTS = {
24+
# Exceptions
25+
"SkillError",
26+
"SkillValidationError",
27+
# Core skill model and loading
28+
"Skill",
29+
"SkillInfo",
30+
"SkillResources",
31+
"load_skills_from_dir",
32+
"load_project_skills",
33+
"load_user_skills",
34+
"load_public_skills",
35+
"load_available_skills",
36+
"to_prompt",
37+
# Triggers
38+
"BaseTrigger",
39+
"KeywordTrigger",
40+
"TaskTrigger",
41+
# Types
42+
"SkillKnowledge",
43+
"InputMetadata",
44+
"SkillResponse",
45+
"SkillContentResponse",
46+
# Utilities
47+
"discover_skill_resources",
48+
"RESOURCE_DIRECTORIES",
49+
"validate_skill_name",
50+
}
51+
52+
if name in _VALID_EXPORTS:
53+
warn_deprecated(
54+
f"Importing '{name}' from 'openhands.sdk.context.skills'",
55+
deprecated_in="1.16.0",
56+
removed_in="1.20.0",
57+
details=f"Use 'from openhands.sdk.skills import {name}' instead.",
58+
stacklevel=3,
59+
)
60+
return getattr(_skills, name)
61+
62+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
63+
64+
65+
def __dir__():
66+
"""List available attributes for tab-completion."""
67+
return [
68+
# Exceptions
69+
"SkillError",
70+
"SkillValidationError",
71+
# Core skill model and loading
72+
"Skill",
73+
"SkillInfo",
74+
"SkillResources",
75+
"load_skills_from_dir",
76+
"load_project_skills",
77+
"load_user_skills",
78+
"load_public_skills",
79+
"load_available_skills",
80+
"to_prompt",
81+
# Triggers
82+
"BaseTrigger",
83+
"KeywordTrigger",
84+
"TaskTrigger",
85+
# Types
86+
"SkillKnowledge",
87+
"InputMetadata",
88+
"SkillResponse",
89+
"SkillContentResponse",
90+
# Utilities
91+
"discover_skill_resources",
92+
"RESOURCE_DIRECTORIES",
93+
"validate_skill_name",
94+
]
2395

2496

2597
__all__ = [
98+
# Exceptions
99+
"SkillError",
100+
"SkillValidationError",
101+
# Core skill model and loading
26102
"Skill",
103+
"SkillInfo",
27104
"SkillResources",
105+
"load_skills_from_dir",
106+
"load_project_skills",
107+
"load_user_skills",
108+
"load_public_skills",
109+
"load_available_skills",
110+
"to_prompt",
111+
# Triggers
28112
"BaseTrigger",
29113
"KeywordTrigger",
30114
"TaskTrigger",
115+
# Types
31116
"SkillKnowledge",
32-
"load_available_skills",
33-
"load_skills_from_dir",
34-
"load_user_skills",
35-
"load_project_skills",
36-
"load_public_skills",
37-
"SkillValidationError",
117+
"InputMetadata",
118+
"SkillResponse",
119+
"SkillContentResponse",
120+
# Utilities
38121
"discover_skill_resources",
39122
"RESOURCE_DIRECTORIES",
40-
"to_prompt",
41123
"validate_skill_name",
42124
]

openhands-sdk/openhands/sdk/plugin/plugin.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,6 @@
88

99
from pydantic import BaseModel, Field
1010

11-
from openhands.sdk.context.skills import Skill
12-
from openhands.sdk.context.skills.utils import (
13-
discover_skill_resources,
14-
find_skill_md,
15-
load_mcp_config,
16-
)
1711
from openhands.sdk.hooks import HookConfig
1812
from openhands.sdk.logger import get_logger
1913
from openhands.sdk.plugin.fetch import fetch_plugin
@@ -22,6 +16,12 @@
2216
PluginAuthor,
2317
PluginManifest,
2418
)
19+
from openhands.sdk.skills.skill import Skill
20+
from openhands.sdk.skills.utils import (
21+
discover_skill_resources,
22+
find_skill_md,
23+
load_mcp_config,
24+
)
2525
from openhands.sdk.subagent.schema import AgentDefinition
2626

2727

openhands-sdk/openhands/sdk/plugin/types.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ def to_plugin_source(self) -> PluginSource:
188188

189189

190190
if TYPE_CHECKING:
191-
from openhands.sdk.context.skills import Skill
191+
from openhands.sdk.skills.skill import Skill
192192

193193

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

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

0 commit comments

Comments
 (0)