Skip to content

Commit f233b21

Browse files
Restructure agent-sdk repository into UV workspace with simplified structure (#33)
Co-authored-by: openhands <openhands@all-hands.dev>
1 parent 7da40fb commit f233b21

Some content is hidden

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

63 files changed

+265
-209
lines changed

.github/workflows/tests.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,16 @@ jobs:
2828
run: uv sync --frozen --group dev
2929

3030
- name: Run tests with coverage
31-
run: CI=true uv run pytest -vvxss --basetemp="${{ runner.temp }}/pytest" -o tmp_path_retention=none -o tmp_path_retention_count=0 --cov=openhands --cov-report=term-missing tests/
31+
run: |
32+
CI=true uv run pytest \
33+
-vvxss \
34+
--basetemp="${{ runner.temp }}/pytest" \
35+
-o tmp_path_retention=none \
36+
-o tmp_path_retention_count=0 \
37+
--cov=openhands/core \
38+
--cov=openhands/tools \
39+
--cov-report=term-missing \
40+
openhands/core/tests openhands/tools/tests tests
3241
3342
- name: Build coverage XML (separate step, lower mem)
3443
if: always()

examples/hello_world.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
Tool,
1414
get_logger,
1515
)
16-
from openhands.core.runtime.tools import (
16+
from openhands.tools import (
1717
BashExecutor,
1818
FileEditorExecutor,
1919
execute_bash_tool,

openhands/__init__.py

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1 @@
1-
"""OpenHands package."""
2-
3-
import os
4-
from importlib.metadata import PackageNotFoundError, version
5-
from pathlib import Path
6-
7-
8-
__package_name__ = "openhands-sdk"
9-
10-
11-
def get_version():
12-
# Try getting the version from pyproject.toml
13-
try:
14-
root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
15-
candidate_paths = [
16-
Path(root_dir) / "pyproject.toml",
17-
Path(root_dir) / "openhands" / "pyproject.toml",
18-
]
19-
for file_path in candidate_paths:
20-
if file_path.is_file():
21-
with open(file_path, "r") as f:
22-
for line in f:
23-
if line.strip().startswith("version ="):
24-
return line.split("=", 1)[1].strip().strip('"').strip("'")
25-
except FileNotFoundError:
26-
pass
27-
28-
try:
29-
return version(__package_name__)
30-
except (ImportError, PackageNotFoundError):
31-
pass
32-
return "unknown"
33-
34-
35-
try:
36-
__version__ = get_version()
37-
except Exception:
38-
__version__ = "unknown"
1+
__path__ = __import__('pkgutil').extend_path(__path__, __name__)

openhands/core/__init__.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
1+
from importlib.metadata import PackageNotFoundError, version
2+
13
from .agenthub import AgentBase, CodeActAgent
24
from .config import LLMConfig, MCPConfig, OpenHandsConfig
35
from .conversation import Conversation
46
from .llm import LLM, ImageContent, Message, TextContent
57
from .logger import get_logger
6-
from .runtime import ActionBase, ObservationBase, Tool
8+
from .tool import ActionBase, ObservationBase, Tool
9+
710

11+
try:
12+
__version__ = version("openhands-core")
13+
except PackageNotFoundError:
14+
__version__ = "0.0.0" # fallback for editable/unbuilt environments
815

916
__all__ = [
1017
"LLM",
@@ -21,4 +28,5 @@
2128
"MCPConfig",
2229
"get_logger",
2330
"Conversation",
31+
"__version__",
2432
]

openhands/core/agenthub/agent.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from openhands.core.llm import LLM
55
from openhands.core.llm.message import Message
66
from openhands.core.logger import get_logger
7-
from openhands.core.runtime import ActionBase, ObservationBase, Tool
7+
from openhands.core.tool import ActionBase, ObservationBase, Tool
88

99

1010
logger = get_logger(__name__)

openhands/core/agenthub/codeact_agent/codeact_agent.py

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,53 @@
88
Message as LiteLLMMessage,
99
ModelResponse,
1010
)
11+
from pydantic import Field
1112

1213
from openhands.core.agenthub.agent import AgentBase
1314
from openhands.core.agenthub.history import AgentHistory
1415
from openhands.core.context.env_context import EnvContext
1516
from openhands.core.context.prompt import PromptManager
1617
from openhands.core.llm import LLM, Message, TextContent, get_llm_metadata
1718
from openhands.core.logger import get_logger
18-
from openhands.core.runtime import ActionBase, ObservationBase, Tool
19-
from openhands.core.runtime.tools import FinishAction, finish_tool
19+
from openhands.core.tool import ActionBase, ObservationBase, Tool, ToolAnnotations
2020

2121

2222
logger = get_logger(__name__)
2323

24+
"""Finish tool implementation."""
25+
26+
27+
class FinishAction(ActionBase):
28+
message: str = Field(description="Final message to send to the user.")
29+
30+
31+
TOOL_DESCRIPTION = """Signals the completion of the current task or conversation.
32+
33+
Use this tool when:
34+
- You have successfully completed the user's requested task
35+
- You cannot proceed further due to technical limitations or missing information
36+
37+
The message should include:
38+
- A clear summary of actions taken and their results
39+
- Any next steps for the user
40+
- Explanation if you're unable to complete the task
41+
- Any follow-up questions if more information is needed
42+
"""
43+
44+
45+
finish_tool = Tool(
46+
name="finish",
47+
input_schema=FinishAction,
48+
description=TOOL_DESCRIPTION,
49+
annotations=ToolAnnotations(
50+
title="finish",
51+
readOnlyHint=True,
52+
destructiveHint=False,
53+
idempotentHint=True,
54+
openWorldHint=False,
55+
),
56+
)
57+
2458

2559
class CodeActAgent(AgentBase):
2660
def __init__(

openhands/core/conversation/conversation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from openhands.core.agenthub.agent import AgentBase
1010
from openhands.core.llm import Message, TextContent
11-
from openhands.core.runtime import ActionBase, ObservationBase
11+
from openhands.core.tool import ActionBase, ObservationBase
1212

1313

1414
OnEvent = Callable[[Message | ActionBase | ObservationBase], None]

openhands/core/llm/metadata.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,28 @@
11
import os
22

3-
import openhands
4-
53

64
def get_llm_metadata(
75
model_name: str,
86
agent_name: str,
97
session_id: str | None = None,
108
user_id: str | None = None,
119
) -> dict:
10+
import openhands.core
11+
openhands_tools_version: str = "n/a"
12+
try:
13+
import openhands.tools
14+
openhands_tools_version = openhands.tools.__version__
15+
except ModuleNotFoundError:
16+
pass
17+
1218
metadata = {
13-
"trace_version": openhands.__version__,
19+
"trace_version": openhands.core.__version__,
1420
"tags": [
1521
f"model:{model_name}",
1622
f"agent:{agent_name}",
1723
f"web_host:{os.environ.get('WEB_HOST', 'unspecified')}",
18-
f"openhands_version:{openhands.__version__}",
24+
f"openhands_version:{openhands.core.__version__}",
25+
f"openhands_tools_version:{openhands_tools_version}",
1926
],
2027
}
2128
if session_id is not None:

openhands/core/pyproject.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[project]
2+
name = "openhands-sdk"
3+
version = "1.0.0"
4+
description = "OpenHands SDK - Core functionality for building AI agents"
5+
6+
requires-python = ">=3.12"
7+
dependencies = [
8+
"fastmcp>=2.11.3",
9+
"litellm>=1.75.9",
10+
"pydantic>=2.11.7",
11+
"python-frontmatter>=1.1.0",
12+
"tenacity>=9.1.2",
13+
]
14+
15+
[build-system]
16+
requires = ["hatchling"]
17+
build-backend = "hatchling.build"
18+
19+
[tool.hatch.build.targets.wheel]
20+
packages = ["openhands"]

openhands/core/runtime/tools/finish/__init__.py

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)