openhands 1.0.3__py3-none-any.whl → 1.0.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of openhands might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openhands
3
- Version: 1.0.3
3
+ Version: 1.0.4
4
4
  Summary: OpenHands CLI - Terminal User Interface for OpenHands AI Agent
5
5
  Author-email: OpenHands Team <contact@all-hands.dev>
6
6
  License: MIT
@@ -1,10 +1,10 @@
1
1
  openhands_cli/__init__.py,sha256=AqdjE-Up0uBSDyHvNjF0zWHNmA4ps-lsQWFpUWCWNEc,187
2
- openhands_cli/agent_chat.py,sha256=FZ1NC31xJPXqyFGUtS-JqDI_HVP5155xEz59AHp3DIw,6224
3
- openhands_cli/gui_launcher.py,sha256=7gxcem7y7WcqllZWO6B6RtM_5WPOKvRAauByS1y1U6I,7192
2
+ openhands_cli/agent_chat.py,sha256=Jl6khJ-A8i0vQN_81fD28c0Kw_YSDyir7CPmv8dKi_g,7032
3
+ openhands_cli/gui_launcher.py,sha256=FtebC7ZXYvhqRzl-CXyacPes91D3OUInwZssC-LmcDw,7192
4
4
  openhands_cli/locations.py,sha256=zG5OnpJiX0kQ1fprEsOSi_cNqydEvxunPBCTpNrVaJ0,438
5
5
  openhands_cli/pt_style.py,sha256=ITu26EC-uMJdBdB5AGtB-3kdFqZvht7gGhoPJ__O0GY,1263
6
6
  openhands_cli/runner.py,sha256=10dloNBwPHcVNfLEXgqfJgUZ6-HJyL5-xtlAQTR-9wA,6158
7
- openhands_cli/setup.py,sha256=HWb2_6N6qgXvhIzh7jLecS7HA5EEcp7b3VroDxGiGz0,3799
7
+ openhands_cli/setup.py,sha256=iamKPQI24FrPiOJx8dSOFIgPXPLDjbc9V4cVsLqsRFA,3024
8
8
  openhands_cli/simple_main.py,sha256=7MmX8DgSvlFURzYsNqcE2vQ2MtdYTr-V88JlBmJlWvo,1697
9
9
  openhands_cli/utils.py,sha256=SwrKvw9HDTExC7kjf4yFE4FkbaRTP7AQzYVhIi99zkA,2018
10
10
  openhands_cli/argparsers/main_parser.py,sha256=ceYNnktzp4xMwrsvQZl0Py6uG3atUgBsPFfqM7Cig9k,1677
@@ -25,7 +25,7 @@ openhands_cli/user_actions/exit_session.py,sha256=3u1CqWeYAEYfZi9BFh_dUwvy9aXXuv
25
25
  openhands_cli/user_actions/settings_action.py,sha256=QqWj37CAlrkV6FW9SEmmwsvKzdGyUYv4DlGjUweKsmg,5707
26
26
  openhands_cli/user_actions/types.py,sha256=zMHoJqxmtbxAIq6O3RC-XoGzgbZzWZvRFNMOGW4MViQ,407
27
27
  openhands_cli/user_actions/utils.py,sha256=qPTgP_1shnWgA7itrzTyfEGb_meXO-zq98JzFMUqCx4,6362
28
- openhands-1.0.3.dist-info/METADATA,sha256=rZJBpMT6qTrLX9bsGmFWKaJ3xft8KUMOsEcjrmjRBHA,1382
29
- openhands-1.0.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
30
- openhands-1.0.3.dist-info/entry_points.txt,sha256=CltyhTfx4lPndNPQXrZZDj5LmXrYXykVyIqoedPXsas,61
31
- openhands-1.0.3.dist-info/RECORD,,
28
+ openhands-1.0.4.dist-info/METADATA,sha256=kipycmHaOr210M3Rn09STPD27Sv4lEXnxDx849xXrzQ,1382
29
+ openhands-1.0.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
30
+ openhands-1.0.4.dist-info/entry_points.txt,sha256=CltyhTfx4lPndNPQXrZZDj5LmXrYXykVyIqoedPXsas,61
31
+ openhands-1.0.4.dist-info/RECORD,,
@@ -6,6 +6,7 @@ Provides a conversation interface with an AI agent using OpenHands patterns.
6
6
 
7
7
  import sys
8
8
  from datetime import datetime
9
+ import uuid
9
10
 
10
11
  from openhands.sdk import (
11
12
  Message,
@@ -16,7 +17,11 @@ from prompt_toolkit import print_formatted_text
16
17
  from prompt_toolkit.formatted_text import HTML
17
18
 
18
19
  from openhands_cli.runner import ConversationRunner
19
- from openhands_cli.setup import MissingAgentSpec, setup_conversation, start_fresh_conversation
20
+ from openhands_cli.setup import (
21
+ MissingAgentSpec,
22
+ setup_conversation,
23
+ verify_agent_exists_or_setup_agent
24
+ )
20
25
  from openhands_cli.tui.settings.mcp_screen import MCPScreen
21
26
  from openhands_cli.tui.settings.settings_screen import SettingsScreen
22
27
  from openhands_cli.tui.status import display_status
@@ -65,21 +70,33 @@ def run_cli_entry(resume_conversation_id: str | None = None) -> None:
65
70
  EOFError: If EOF is encountered
66
71
  """
67
72
 
73
+ conversation_id = uuid.uuid4()
74
+ if resume_conversation_id:
75
+ try:
76
+ conversation_id = uuid.UUID(resume_conversation_id)
77
+ except ValueError as e:
78
+ print_formatted_text(
79
+ HTML(
80
+ f"<yellow>Warning: '{resume_conversation_id}' is not a valid UUID.</yellow>"
81
+ )
82
+ )
83
+ return
84
+
68
85
  try:
69
- conversation = start_fresh_conversation(resume_conversation_id)
86
+ initialized_agent = verify_agent_exists_or_setup_agent()
70
87
  except MissingAgentSpec:
71
88
  print_formatted_text(HTML('\n<yellow>Setup is required to use OpenHands CLI.</yellow>'))
72
89
  print_formatted_text(HTML('\n<yellow>Goodbye! 👋</yellow>'))
73
90
  return
74
91
 
75
92
 
76
- display_welcome(conversation.id, bool(resume_conversation_id))
93
+ display_welcome(conversation_id, bool(resume_conversation_id))
77
94
 
78
95
  # Track session start time for uptime calculation
79
96
  session_start_time = datetime.now()
80
97
 
81
98
  # Create conversation runner to handle state machine logic
82
- runner = ConversationRunner(conversation)
99
+ runner = None
83
100
  session = get_session_prompter()
84
101
 
85
102
  # Main chat loop
@@ -106,7 +123,7 @@ def run_cli_entry(resume_conversation_id: str | None = None) -> None:
106
123
  exit_confirmation = exit_session_confirmation()
107
124
  if exit_confirmation == UserConfirmation.ACCEPT:
108
125
  print_formatted_text(HTML('\n<yellow>Goodbye! 👋</yellow>'))
109
- _print_exit_hint(conversation.id)
126
+ _print_exit_hint(conversation_id)
110
127
  break
111
128
 
112
129
  elif command == '/settings':
@@ -116,19 +133,19 @@ def run_cli_entry(resume_conversation_id: str | None = None) -> None:
116
133
 
117
134
  elif command == '/mcp':
118
135
  mcp_screen = MCPScreen()
119
- mcp_screen.display_mcp_info(conversation.agent)
136
+ mcp_screen.display_mcp_info(initialized_agent)
120
137
  continue
121
138
 
122
139
  elif command == '/clear':
123
- display_welcome(conversation.id)
140
+ display_welcome(conversation_id)
124
141
  continue
125
142
 
126
143
  elif command == '/new':
127
144
  try:
128
145
  # Start a fresh conversation (no resume ID = new conversation)
129
- conversation = setup_conversation()
146
+ conversation = setup_conversation(conversation_id)
130
147
  runner = ConversationRunner(conversation)
131
- display_welcome(conversation.id, resume=False)
148
+ display_welcome(conversation_id, resume=False)
132
149
  print_formatted_text(
133
150
  HTML('<green>✓ Started fresh conversation</green>')
134
151
  )
@@ -158,6 +175,13 @@ def run_cli_entry(resume_conversation_id: str | None = None) -> None:
158
175
  continue
159
176
 
160
177
  elif command == '/resume':
178
+ if not runner:
179
+ print_formatted_text(
180
+ HTML('<yellow>No active conversation running...</yellow>')
181
+ )
182
+ continue
183
+
184
+ conversation = runner.conversation
161
185
  if not (
162
186
  conversation.state.agent_status == AgentExecutionStatus.PAUSED
163
187
  or conversation.state.agent_status
@@ -171,6 +195,9 @@ def run_cli_entry(resume_conversation_id: str | None = None) -> None:
171
195
  # Resume without new message
172
196
  message = None
173
197
 
198
+ if not runner:
199
+ conversation = setup_conversation(conversation_id)
200
+ runner = ConversationRunner(conversation)
174
201
  runner.process_message(message)
175
202
 
176
203
  print() # Add spacing
@@ -179,7 +206,7 @@ def run_cli_entry(resume_conversation_id: str | None = None) -> None:
179
206
  exit_confirmation = exit_session_confirmation()
180
207
  if exit_confirmation == UserConfirmation.ACCEPT:
181
208
  print_formatted_text(HTML('\n<yellow>Goodbye! 👋</yellow>'))
182
- _print_exit_hint(conversation.id)
209
+ _print_exit_hint(conversation_id)
183
210
  break
184
211
 
185
212
  # Clean up terminal state
@@ -104,8 +104,8 @@ def launch_gui_server(mount_cwd: bool = False, gpu: bool = False) -> None:
104
104
 
105
105
  # Get the current version for the Docker image
106
106
  version = get_openhands_version()
107
- runtime_image = f'docker.all-hands.dev/openhands/runtime:{version}-nikolaik'
108
- app_image = f'docker.all-hands.dev/openhands/openhands:{version}'
107
+ runtime_image = f'docker.openhands.dev/openhands/runtime:{version}-nikolaik'
108
+ app_image = f'docker.openhands.dev/openhands/openhands:{version}'
109
109
 
110
110
  print_formatted_text(HTML('<grey>Pulling required Docker images...</grey>'))
111
111
 
openhands_cli/setup.py CHANGED
@@ -2,7 +2,7 @@ import uuid
2
2
 
3
3
  from prompt_toolkit import HTML, print_formatted_text
4
4
 
5
- from openhands.sdk import BaseConversation, Conversation, Workspace, register_tool
5
+ from openhands.sdk import Agent, BaseConversation, Conversation, Workspace, register_tool
6
6
  from openhands.tools.execute_bash import BashTool
7
7
  from openhands.tools.file_editor import FileEditorTool
8
8
  from openhands.tools.task_tracker import TaskTrackerTool
@@ -26,8 +26,38 @@ class MissingAgentSpec(Exception):
26
26
  pass
27
27
 
28
28
 
29
- def setup_conversation(
29
+
30
+ def load_agent_specs(
30
31
  conversation_id: str | None = None,
32
+ ) -> Agent:
33
+ agent_store = AgentStore()
34
+ agent = agent_store.load(session_id=conversation_id)
35
+ if not agent:
36
+ raise MissingAgentSpec(
37
+ 'Agent specification not found. Please configure your agent settings.'
38
+ )
39
+ return agent
40
+
41
+
42
+ def verify_agent_exists_or_setup_agent() -> Agent:
43
+ """Verify agent specs exists by attempting to load it.
44
+
45
+ """
46
+ settings_screen = SettingsScreen()
47
+ try:
48
+ agent = load_agent_specs()
49
+ return agent
50
+ except MissingAgentSpec:
51
+ # For first-time users, show the full settings flow with choice between basic/advanced
52
+ settings_screen.configure_settings(first_time=True)
53
+
54
+
55
+ # Try once again after settings setup attempt
56
+ return load_agent_specs()
57
+
58
+
59
+ def setup_conversation(
60
+ conversation_id: uuid,
31
61
  include_security_analyzer: bool = True
32
62
  ) -> BaseConversation:
33
63
  """
@@ -40,28 +70,8 @@ def setup_conversation(
40
70
  MissingAgentSpec: If agent specification is not found or invalid.
41
71
  """
42
72
 
43
- # Use provided conversation_id or generate a random one
44
- if conversation_id is None:
45
- conversation_id = uuid.uuid4()
46
- elif isinstance(conversation_id, str):
47
- try:
48
- conversation_id = uuid.UUID(conversation_id)
49
- except ValueError as e:
50
- print_formatted_text(
51
- HTML(
52
- f"<yellow>Warning: '{conversation_id}' is not a valid UUID.</yellow>"
53
- )
54
- )
55
- raise e
56
-
57
73
  with LoadingContext('Initializing OpenHands agent...'):
58
- agent_store = AgentStore()
59
- agent = agent_store.load(session_id=str(conversation_id))
60
- if not agent:
61
- raise MissingAgentSpec(
62
- 'Agent specification not found. Please configure your agent settings.'
63
- )
64
-
74
+ agent = load_agent_specs(str(conversation_id))
65
75
 
66
76
  if not include_security_analyzer:
67
77
  # Remove security analyzer from agent spec
@@ -86,31 +96,3 @@ def setup_conversation(
86
96
  )
87
97
  return conversation
88
98
 
89
-
90
-
91
- def start_fresh_conversation(
92
- resume_conversation_id: str | None = None
93
- ) -> BaseConversation:
94
- """Start a fresh conversation by creating a new conversation instance.
95
-
96
- Handles the complete conversation setup process including settings screen
97
- if agent configuration is missing.
98
-
99
- Args:
100
- resume_conversation_id: Optional conversation ID to resume
101
-
102
- Returns:
103
- BaseConversation: A new conversation instance
104
- """
105
- conversation = None
106
- settings_screen = SettingsScreen()
107
- try:
108
- conversation = setup_conversation(resume_conversation_id)
109
- return conversation
110
- except MissingAgentSpec:
111
- # For first-time users, show the full settings flow with choice between basic/advanced
112
- settings_screen.configure_settings(first_time=True)
113
-
114
-
115
- # Try once again after settings setup attempt
116
- return setup_conversation(resume_conversation_id)