@openhands/extensions 0.32.0 → 0.32.1

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.
@@ -98,7 +98,7 @@
98
98
  }
99
99
  },
100
100
  "bundle": {
101
- "version": "1.2.3",
101
+ "version": "1.2.4",
102
102
  "entrypoint": "python3 worker.py",
103
103
  "timeout": 300,
104
104
  "files": {
@@ -117,5 +117,5 @@
117
117
  },
118
118
  "message": "Configure the repositories, labels, branch prefix, pull request mode, agent profile, and schedule."
119
119
  },
120
- "version": "1.2.2"
120
+ "version": "1.2.3"
121
121
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "github-issue-triage",
3
- "version": "1.3.3",
3
+ "version": "1.3.4",
4
4
  "name": "GitHub issue triage",
5
5
  "category": "Project management",
6
6
  "description": "Prioritize open issues and establish acceptance criteria before marking them ready for development.",
@@ -54,7 +54,7 @@
54
54
  }
55
55
  },
56
56
  "bundle": {
57
- "version": "1.4.1",
57
+ "version": "1.4.2",
58
58
  "entrypoint": "python3 worker.py",
59
59
  "timeout": 300,
60
60
  "files": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "github-pr-reviewer",
3
- "version": "1.11.1",
3
+ "version": "1.11.2",
4
4
  "name": "GitHub code review",
5
5
  "category": "Code review",
6
6
  "description": "Review requested pull-request heads, resume an outstanding reviewer request on a schedule once its checks are green, classify all open non-draft pull requests that nobody requested and review eligible green heads, drain the backlog oldest-first under a small per-scan new-conversation bound, record exact-head decisions, stop early on out-of-scope changes, and optionally request a code-aware human maintainer after approval or a maintainer-decision scope stop only when a successfully fetched same-repository closing issue has priority:medium or priority:high.",
@@ -135,7 +135,7 @@
135
135
  }
136
136
  },
137
137
  "bundle": {
138
- "version": "1.11.1",
138
+ "version": "1.11.2",
139
139
  "entrypoint": "python3 worker.py",
140
140
  "timeout": 300,
141
141
  "files": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openhands/extensions",
3
- "version": "0.32.0",
3
+ "version": "0.32.1",
4
4
  "description": "Public OpenHands extension catalogs for skills, plugins, integrations, and automation templates.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -104,16 +104,16 @@ class CloudConversations:
104
104
  return found[0] if found else None
105
105
 
106
106
  def start(self, conversation_id, profile_id, title: str, prompt: str) -> None:
107
- self._request(
108
- "POST",
109
- "/api/v1/app-conversations",
110
- {
111
- "conversation_id": str(conversation_id),
112
- "agent_profile_id": str(profile_id),
113
- "title": title,
114
- "initial_message": _user_message(prompt),
115
- },
116
- )
107
+ body = {
108
+ "conversation_id": str(conversation_id),
109
+ "title": title,
110
+ "initial_message": _user_message(prompt),
111
+ }
112
+ if profile_id is not None:
113
+ # Without one the API launches the member's active profile, or the
114
+ # default settings when none is active.
115
+ body["agent_profile_id"] = str(profile_id)
116
+ self._request("POST", "/api/v1/app-conversations", body)
117
117
 
118
118
  def agent_profiles(self) -> list[dict]:
119
119
  listing = self._request("GET", "/api/agent-profiles")
@@ -177,7 +177,10 @@ class AgentConversationDispatcher:
177
177
  # local Agent Canvas; elsewhere conversations go through the OpenHands API.
178
178
  self.agent_url = os.environ.get("AGENT_SERVER_URL")
179
179
  self.api_key = os.environ["SESSION_API_KEY"]
180
- self.profile_id = UUID(os.environ["AUTOMATION_AGENT_PROFILE_ID"])
180
+ # The automation service sets the variable only when the automation
181
+ # names an agent profile; a run without one launches the default.
182
+ profile_id = os.environ.get("AUTOMATION_AGENT_PROFILE_ID")
183
+ self.profile_id = UUID(profile_id) if profile_id else None
181
184
  payload = json.loads(os.environ["AUTOMATION_EVENT_PAYLOAD"])
182
185
  self.automation_id = str(payload["automation_id"])
183
186
  self._cloud = None if self.agent_url else CloudConversations()
@@ -187,6 +190,18 @@ class AgentConversationDispatcher:
187
190
  def __enter__(self):
188
191
  if self._cloud:
189
192
  return self
193
+ if self.profile_id is None:
194
+ # The Agent Server starts a conversation from a profile, and always
195
+ # has an active one: its listing seeds `default` when the store is
196
+ # empty.
197
+ listing = self._agent_server_get("/api/agent-profiles")
198
+ active = (listing or {}).get("active_agent_profile_id")
199
+ if not active:
200
+ raise RuntimeError(
201
+ "No agent profile is selected and the Agent Server has "
202
+ "none active"
203
+ )
204
+ self.profile_id = UUID(active)
190
205
  _register_tools()
191
206
  self._workspace = RemoteWorkspace(
192
207
  host=self.agent_url,
package/pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "openhands-extensions"
3
- version = "0.32.0"
3
+ version = "0.32.1"
4
4
  description = "OpenHands extensions, plugins, and skills (Python bindings for the integration catalog)"
5
5
  requires-python = ">=3.12"
6
6
  dependencies = [
@@ -18,7 +18,7 @@ from importlib.metadata import PackageNotFoundError, version
18
18
  #: Kept in lock-step with pyproject.toml/package.json by the version test.
19
19
  #: release-please only rewrites a semver found on the annotated line itself, so
20
20
  #: the annotation must stay on the assignment; on its own line it is a no-op.
21
- _FALLBACK_VERSION = "0.32.0" # x-release-please-version
21
+ _FALLBACK_VERSION = "0.32.1" # x-release-please-version
22
22
 
23
23
  try:
24
24
  __version__: str = version("openhands-extensions")
@@ -104,16 +104,16 @@ class CloudConversations:
104
104
  return found[0] if found else None
105
105
 
106
106
  def start(self, conversation_id, profile_id, title: str, prompt: str) -> None:
107
- self._request(
108
- "POST",
109
- "/api/v1/app-conversations",
110
- {
111
- "conversation_id": str(conversation_id),
112
- "agent_profile_id": str(profile_id),
113
- "title": title,
114
- "initial_message": _user_message(prompt),
115
- },
116
- )
107
+ body = {
108
+ "conversation_id": str(conversation_id),
109
+ "title": title,
110
+ "initial_message": _user_message(prompt),
111
+ }
112
+ if profile_id is not None:
113
+ # Without one the API launches the member's active profile, or the
114
+ # default settings when none is active.
115
+ body["agent_profile_id"] = str(profile_id)
116
+ self._request("POST", "/api/v1/app-conversations", body)
117
117
 
118
118
  def agent_profiles(self) -> list[dict]:
119
119
  listing = self._request("GET", "/api/agent-profiles")
@@ -177,7 +177,10 @@ class AgentConversationDispatcher:
177
177
  # local Agent Canvas; elsewhere conversations go through the OpenHands API.
178
178
  self.agent_url = os.environ.get("AGENT_SERVER_URL")
179
179
  self.api_key = os.environ["SESSION_API_KEY"]
180
- self.profile_id = UUID(os.environ["AUTOMATION_AGENT_PROFILE_ID"])
180
+ # The automation service sets the variable only when the automation
181
+ # names an agent profile; a run without one launches the default.
182
+ profile_id = os.environ.get("AUTOMATION_AGENT_PROFILE_ID")
183
+ self.profile_id = UUID(profile_id) if profile_id else None
181
184
  payload = json.loads(os.environ["AUTOMATION_EVENT_PAYLOAD"])
182
185
  self.automation_id = str(payload["automation_id"])
183
186
  self._cloud = None if self.agent_url else CloudConversations()
@@ -187,6 +190,18 @@ class AgentConversationDispatcher:
187
190
  def __enter__(self):
188
191
  if self._cloud:
189
192
  return self
193
+ if self.profile_id is None:
194
+ # The Agent Server starts a conversation from a profile, and always
195
+ # has an active one: its listing seeds `default` when the store is
196
+ # empty.
197
+ listing = self._agent_server_get("/api/agent-profiles")
198
+ active = (listing or {}).get("active_agent_profile_id")
199
+ if not active:
200
+ raise RuntimeError(
201
+ "No agent profile is selected and the Agent Server has "
202
+ "none active"
203
+ )
204
+ self.profile_id = UUID(active)
190
205
  _register_tools()
191
206
  self._workspace = RemoteWorkspace(
192
207
  host=self.agent_url,
@@ -104,16 +104,16 @@ class CloudConversations:
104
104
  return found[0] if found else None
105
105
 
106
106
  def start(self, conversation_id, profile_id, title: str, prompt: str) -> None:
107
- self._request(
108
- "POST",
109
- "/api/v1/app-conversations",
110
- {
111
- "conversation_id": str(conversation_id),
112
- "agent_profile_id": str(profile_id),
113
- "title": title,
114
- "initial_message": _user_message(prompt),
115
- },
116
- )
107
+ body = {
108
+ "conversation_id": str(conversation_id),
109
+ "title": title,
110
+ "initial_message": _user_message(prompt),
111
+ }
112
+ if profile_id is not None:
113
+ # Without one the API launches the member's active profile, or the
114
+ # default settings when none is active.
115
+ body["agent_profile_id"] = str(profile_id)
116
+ self._request("POST", "/api/v1/app-conversations", body)
117
117
 
118
118
  def agent_profiles(self) -> list[dict]:
119
119
  listing = self._request("GET", "/api/agent-profiles")
@@ -177,7 +177,10 @@ class AgentConversationDispatcher:
177
177
  # local Agent Canvas; elsewhere conversations go through the OpenHands API.
178
178
  self.agent_url = os.environ.get("AGENT_SERVER_URL")
179
179
  self.api_key = os.environ["SESSION_API_KEY"]
180
- self.profile_id = UUID(os.environ["AUTOMATION_AGENT_PROFILE_ID"])
180
+ # The automation service sets the variable only when the automation
181
+ # names an agent profile; a run without one launches the default.
182
+ profile_id = os.environ.get("AUTOMATION_AGENT_PROFILE_ID")
183
+ self.profile_id = UUID(profile_id) if profile_id else None
181
184
  payload = json.loads(os.environ["AUTOMATION_EVENT_PAYLOAD"])
182
185
  self.automation_id = str(payload["automation_id"])
183
186
  self._cloud = None if self.agent_url else CloudConversations()
@@ -187,6 +190,18 @@ class AgentConversationDispatcher:
187
190
  def __enter__(self):
188
191
  if self._cloud:
189
192
  return self
193
+ if self.profile_id is None:
194
+ # The Agent Server starts a conversation from a profile, and always
195
+ # has an active one: its listing seeds `default` when the store is
196
+ # empty.
197
+ listing = self._agent_server_get("/api/agent-profiles")
198
+ active = (listing or {}).get("active_agent_profile_id")
199
+ if not active:
200
+ raise RuntimeError(
201
+ "No agent profile is selected and the Agent Server has "
202
+ "none active"
203
+ )
204
+ self.profile_id = UUID(active)
190
205
  _register_tools()
191
206
  self._workspace = RemoteWorkspace(
192
207
  host=self.agent_url,
@@ -104,16 +104,16 @@ class CloudConversations:
104
104
  return found[0] if found else None
105
105
 
106
106
  def start(self, conversation_id, profile_id, title: str, prompt: str) -> None:
107
- self._request(
108
- "POST",
109
- "/api/v1/app-conversations",
110
- {
111
- "conversation_id": str(conversation_id),
112
- "agent_profile_id": str(profile_id),
113
- "title": title,
114
- "initial_message": _user_message(prompt),
115
- },
116
- )
107
+ body = {
108
+ "conversation_id": str(conversation_id),
109
+ "title": title,
110
+ "initial_message": _user_message(prompt),
111
+ }
112
+ if profile_id is not None:
113
+ # Without one the API launches the member's active profile, or the
114
+ # default settings when none is active.
115
+ body["agent_profile_id"] = str(profile_id)
116
+ self._request("POST", "/api/v1/app-conversations", body)
117
117
 
118
118
  def agent_profiles(self) -> list[dict]:
119
119
  listing = self._request("GET", "/api/agent-profiles")
@@ -177,7 +177,10 @@ class AgentConversationDispatcher:
177
177
  # local Agent Canvas; elsewhere conversations go through the OpenHands API.
178
178
  self.agent_url = os.environ.get("AGENT_SERVER_URL")
179
179
  self.api_key = os.environ["SESSION_API_KEY"]
180
- self.profile_id = UUID(os.environ["AUTOMATION_AGENT_PROFILE_ID"])
180
+ # The automation service sets the variable only when the automation
181
+ # names an agent profile; a run without one launches the default.
182
+ profile_id = os.environ.get("AUTOMATION_AGENT_PROFILE_ID")
183
+ self.profile_id = UUID(profile_id) if profile_id else None
181
184
  payload = json.loads(os.environ["AUTOMATION_EVENT_PAYLOAD"])
182
185
  self.automation_id = str(payload["automation_id"])
183
186
  self._cloud = None if self.agent_url else CloudConversations()
@@ -187,6 +190,18 @@ class AgentConversationDispatcher:
187
190
  def __enter__(self):
188
191
  if self._cloud:
189
192
  return self
193
+ if self.profile_id is None:
194
+ # The Agent Server starts a conversation from a profile, and always
195
+ # has an active one: its listing seeds `default` when the store is
196
+ # empty.
197
+ listing = self._agent_server_get("/api/agent-profiles")
198
+ active = (listing or {}).get("active_agent_profile_id")
199
+ if not active:
200
+ raise RuntimeError(
201
+ "No agent profile is selected and the Agent Server has "
202
+ "none active"
203
+ )
204
+ self.profile_id = UUID(active)
190
205
  _register_tools()
191
206
  self._workspace = RemoteWorkspace(
192
207
  host=self.agent_url,
@@ -104,16 +104,16 @@ class CloudConversations:
104
104
  return found[0] if found else None
105
105
 
106
106
  def start(self, conversation_id, profile_id, title: str, prompt: str) -> None:
107
- self._request(
108
- "POST",
109
- "/api/v1/app-conversations",
110
- {
111
- "conversation_id": str(conversation_id),
112
- "agent_profile_id": str(profile_id),
113
- "title": title,
114
- "initial_message": _user_message(prompt),
115
- },
116
- )
107
+ body = {
108
+ "conversation_id": str(conversation_id),
109
+ "title": title,
110
+ "initial_message": _user_message(prompt),
111
+ }
112
+ if profile_id is not None:
113
+ # Without one the API launches the member's active profile, or the
114
+ # default settings when none is active.
115
+ body["agent_profile_id"] = str(profile_id)
116
+ self._request("POST", "/api/v1/app-conversations", body)
117
117
 
118
118
  def agent_profiles(self) -> list[dict]:
119
119
  listing = self._request("GET", "/api/agent-profiles")
@@ -177,7 +177,10 @@ class AgentConversationDispatcher:
177
177
  # local Agent Canvas; elsewhere conversations go through the OpenHands API.
178
178
  self.agent_url = os.environ.get("AGENT_SERVER_URL")
179
179
  self.api_key = os.environ["SESSION_API_KEY"]
180
- self.profile_id = UUID(os.environ["AUTOMATION_AGENT_PROFILE_ID"])
180
+ # The automation service sets the variable only when the automation
181
+ # names an agent profile; a run without one launches the default.
182
+ profile_id = os.environ.get("AUTOMATION_AGENT_PROFILE_ID")
183
+ self.profile_id = UUID(profile_id) if profile_id else None
181
184
  payload = json.loads(os.environ["AUTOMATION_EVENT_PAYLOAD"])
182
185
  self.automation_id = str(payload["automation_id"])
183
186
  self._cloud = None if self.agent_url else CloudConversations()
@@ -187,6 +190,18 @@ class AgentConversationDispatcher:
187
190
  def __enter__(self):
188
191
  if self._cloud:
189
192
  return self
193
+ if self.profile_id is None:
194
+ # The Agent Server starts a conversation from a profile, and always
195
+ # has an active one: its listing seeds `default` when the store is
196
+ # empty.
197
+ listing = self._agent_server_get("/api/agent-profiles")
198
+ active = (listing or {}).get("active_agent_profile_id")
199
+ if not active:
200
+ raise RuntimeError(
201
+ "No agent profile is selected and the Agent Server has "
202
+ "none active"
203
+ )
204
+ self.profile_id = UUID(active)
190
205
  _register_tools()
191
206
  self._workspace = RemoteWorkspace(
192
207
  host=self.agent_url,
@@ -68,7 +68,7 @@
68
68
  "timeout": 300,
69
69
  "template": {
70
70
  "id": "github-pr-reviewer",
71
- "version": "1.11.1",
71
+ "version": "1.11.2",
72
72
  "config": {
73
73
  "repos": [
74
74
  "OpenHands/agent-server-gui"
@@ -108,7 +108,7 @@
108
108
  "timeout": 300,
109
109
  "template": {
110
110
  "id": "github-pr-reviewer",
111
- "version": "1.11.1",
111
+ "version": "1.11.2",
112
112
  "config": {
113
113
  "repos": [
114
114
  "OpenHands/agent-server-gui"
@@ -213,7 +213,7 @@
213
213
  "timeout": 300,
214
214
  "template": {
215
215
  "id": "github-pr-reviewer",
216
- "version": "1.11.1",
216
+ "version": "1.11.2",
217
217
  "config": {
218
218
  "repos": [
219
219
  "OpenHands/agent-server-gui",
@@ -254,7 +254,7 @@
254
254
  "timeout": 300,
255
255
  "template": {
256
256
  "id": "github-pr-reviewer",
257
- "version": "1.11.1",
257
+ "version": "1.11.2",
258
258
  "config": {
259
259
  "repos": [
260
260
  "OpenHands/agent-server-gui",
@@ -296,7 +296,7 @@
296
296
  "preset_metadata": {
297
297
  "template": {
298
298
  "id": "github-pr-reviewer",
299
- "version": "1.11.1",
299
+ "version": "1.11.2",
300
300
  "config": {
301
301
  "repos": [
302
302
  "OpenHands/agent-server-gui",
@@ -351,7 +351,7 @@
351
351
  "timeout": 300,
352
352
  "template": {
353
353
  "id": "github-pr-reviewer",
354
- "version": "1.11.1",
354
+ "version": "1.11.2",
355
355
  "config": {
356
356
  "repos": [
357
357
  "OpenHands/agent-server-gui"
@@ -444,7 +444,7 @@
444
444
  "timeout": 300,
445
445
  "template": {
446
446
  "id": "github-pr-reviewer",
447
- "version": "1.11.1",
447
+ "version": "1.11.2",
448
448
  "config": {
449
449
  "repos": [
450
450
  "OpenHands/agent-server-gui"
@@ -540,7 +540,7 @@
540
540
  "timeout": 300,
541
541
  "template": {
542
542
  "id": "github-pr-reviewer",
543
- "version": "1.11.1",
543
+ "version": "1.11.2",
544
544
  "config": {
545
545
  "repos": [
546
546
  "OpenHands/agent-server-gui"
@@ -616,7 +616,7 @@
616
616
  "timeout": 300,
617
617
  "template": {
618
618
  "id": "github-pr-reviewer",
619
- "version": "1.11.1",
619
+ "version": "1.11.2",
620
620
  "config": {
621
621
  "repos": [
622
622
  "OpenHands/automation"