agentr 0.1.7__py3-none-any.whl → 0.1.8__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.
agentr/application.py CHANGED
@@ -35,8 +35,8 @@ class APIApplication(Application):
35
35
  response.raise_for_status()
36
36
  return response
37
37
  except NotAuthorizedError as e:
38
- logger.warning(f"Reddit authorization needed: {e.message}")
39
- return e.message
38
+ logger.warning(f"Authorization needed: {e.message}")
39
+ raise e
40
40
  except Exception as e:
41
41
  logger.error(f"Error getting {url}: {e}")
42
42
  raise e
@@ -49,8 +49,8 @@ class APIApplication(Application):
49
49
  response.raise_for_status()
50
50
  return response
51
51
  except NotAuthorizedError as e:
52
- logger.warning(f"Reddit authorization needed: {e.message}")
53
- return e.message
52
+ logger.warning(f"Authorization needed: {e.message}")
53
+ raise e
54
54
  except httpx.HTTPStatusError as e:
55
55
  if e.response.status_code == 429:
56
56
  return e.response.text or "Rate limit exceeded. Please try again later."
@@ -67,8 +67,8 @@ class APIApplication(Application):
67
67
  response.raise_for_status()
68
68
  return response
69
69
  except NotAuthorizedError as e:
70
- logger.warning(f"Reddit authorization needed: {e.message}")
71
- return e.message
70
+ logger.warning(f"Authorization needed: {e.message}")
71
+ raise e
72
72
  except Exception as e:
73
73
  logger.error(f"Error posting {url}: {e}")
74
74
  raise e
@@ -80,10 +80,11 @@ class APIApplication(Application):
80
80
  response.raise_for_status()
81
81
  return response
82
82
  except NotAuthorizedError as e:
83
- logger.warning(f"Reddit authorization needed: {e.message}")
84
- return e.message
83
+ logger.warning(f"Authorization needed: {e.message}")
84
+ raise e
85
85
  except Exception as e:
86
86
  logger.error(f"Error posting {url}: {e}")
87
+ raise e
87
88
 
88
89
  def validate(self):
89
90
  pass
@@ -1,7 +1,6 @@
1
1
  from agentr.integration import Integration
2
2
  from agentr.application import APIApplication
3
3
  from loguru import logger
4
- from agentr.exceptions import NotAuthorizedError
5
4
 
6
5
  class GithubApp(APIApplication):
7
6
  def __init__(self, integration: Integration) -> None:
@@ -12,10 +11,6 @@ class GithubApp(APIApplication):
12
11
  if not self.integration:
13
12
  raise ValueError("Integration not configured")
14
13
  credentials = self.integration.get_credentials()
15
- if not credentials:
16
- logger.warning("No credentials found")
17
- action = self.integration.authorize()
18
- raise NotAuthorizedError(action)
19
14
  if "headers" in credentials:
20
15
  return credentials["headers"]
21
16
  return {
@@ -55,35 +50,24 @@ class GithubApp(APIApplication):
55
50
  Returns:
56
51
  A formatted list of recent commits
57
52
  """
58
- try:
59
- repo_full_name = repo_full_name.strip()
60
- url = f"{self.base_api_url}/{repo_full_name}/commits"
61
- response = self._get(url)
53
+ repo_full_name = repo_full_name.strip()
54
+ url = f"{self.base_api_url}/{repo_full_name}/commits"
55
+ response = self._get(url)
56
+ response.raise_for_status()
57
+
58
+ commits = response.json()
59
+ if not commits:
60
+ return f"No commits found for repository {repo_full_name}"
61
+
62
+ result = f"Recent commits for {repo_full_name}:\n\n"
63
+ for commit in commits[:12]: # Limit to 12 commits
64
+ sha = commit.get("sha", "")[:7]
65
+ message = commit.get("commit", {}).get("message", "").split('\n')[0]
66
+ author = commit.get("commit", {}).get("author", {}).get("name", "Unknown")
62
67
 
63
- if response.status_code == 200:
64
- commits = response.json()
65
- if not commits:
66
- return f"No commits found for repository {repo_full_name}"
67
-
68
- result = f"Recent commits for {repo_full_name}:\n\n"
69
- for commit in commits[:12]: # Limit to 12 commits
70
- sha = commit.get("sha", "")[:7]
71
- message = commit.get("commit", {}).get("message", "").split('\n')[0]
72
- author = commit.get("commit", {}).get("author", {}).get("name", "Unknown")
73
-
74
- result += f"- {sha}: {message} (by {author})\n"
75
-
76
- return result
77
- elif response.status_code == 404:
78
- return f"Repository {repo_full_name} not found"
79
- else:
80
- logger.error(response.text)
81
- return f"Error retrieving commits: {response.status_code} - {response.text}"
82
- except NotAuthorizedError as e:
83
- return e.message
84
- except Exception as e:
85
- logger.error(e)
86
- return f"Error retrieving commits: {str(e)}"
68
+ result += f"- {sha}: {message} (by {author})\n"
69
+
70
+ return result
87
71
 
88
72
  def list_branches(self, repo_full_name: str) -> str:
89
73
  """List branches for a GitHub repository
@@ -94,32 +78,21 @@ class GithubApp(APIApplication):
94
78
  Returns:
95
79
  A formatted list of branches
96
80
  """
97
- try:
98
- repo_full_name = repo_full_name.strip()
99
- url = f"{self.base_api_url}/{repo_full_name}/branches"
100
- response = self._get(url)
101
-
102
- if response.status_code == 200:
103
- branches = response.json()
104
- if not branches:
105
- return f"No branches found for repository {repo_full_name}"
106
-
107
- result = f"Branches for {repo_full_name}:\n\n"
108
- for branch in branches:
109
- branch_name = branch.get("name", "Unknown")
110
- result += f"- {branch_name}\n"
111
-
112
- return result
113
- elif response.status_code == 404:
114
- return f"Repository {repo_full_name} not found"
115
- else:
116
- logger.error(response.text)
117
- return f"Error retrieving branches: {response.status_code} - {response.text}"
118
- except NotAuthorizedError as e:
119
- return e.message
120
- except Exception as e:
121
- logger.error(e)
122
- return f"Error retrieving branches: {str(e)}"
81
+ repo_full_name = repo_full_name.strip()
82
+ url = f"{self.base_api_url}/{repo_full_name}/branches"
83
+ response = self._get(url)
84
+ response.raise_for_status()
85
+
86
+ branches = response.json()
87
+ if not branches:
88
+ return f"No branches found for repository {repo_full_name}"
89
+
90
+ result = f"Branches for {repo_full_name}:\n\n"
91
+ for branch in branches:
92
+ branch_name = branch.get("name", "Unknown")
93
+ result += f"- {branch_name}\n"
94
+
95
+ return result
123
96
 
124
97
  def list_pull_requests(self, repo_full_name: str, state: str = "open") -> str:
125
98
  """List pull requests for a GitHub repository
@@ -131,37 +104,26 @@ class GithubApp(APIApplication):
131
104
  Returns:
132
105
  A formatted list of pull requests
133
106
  """
134
- try:
135
- repo_full_name = repo_full_name.strip()
136
- url = f"{self.base_api_url}/{repo_full_name}/pulls"
137
- params = {"state": state}
138
- response = self._get(url, params=params)
107
+ repo_full_name = repo_full_name.strip()
108
+ url = f"{self.base_api_url}/{repo_full_name}/pulls"
109
+ params = {"state": state}
110
+ response = self._get(url, params=params)
111
+ response.raise_for_status()
112
+
113
+ pull_requests = response.json()
114
+ if not pull_requests:
115
+ return f"No pull requests found for repository {repo_full_name} with state '{state}'"
116
+
117
+ result = f"Pull requests for {repo_full_name} (State: {state}):\n\n"
118
+ for pr in pull_requests:
119
+ pr_title = pr.get("title", "No Title")
120
+ pr_number = pr.get("number", "Unknown")
121
+ pr_state = pr.get("state", "Unknown")
122
+ pr_user = pr.get("user", {}).get("login", "Unknown")
139
123
 
140
- if response.status_code == 200:
141
- pull_requests = response.json()
142
- if not pull_requests:
143
- return f"No pull requests found for repository {repo_full_name} with state '{state}'"
144
-
145
- result = f"Pull requests for {repo_full_name} (State: {state}):\n\n"
146
- for pr in pull_requests:
147
- pr_title = pr.get("title", "No Title")
148
- pr_number = pr.get("number", "Unknown")
149
- pr_state = pr.get("state", "Unknown")
150
- pr_user = pr.get("user", {}).get("login", "Unknown")
151
-
152
- result += f"- PR #{pr_number}: {pr_title} (by {pr_user}, Status: {pr_state})\n"
153
-
154
- return result
155
- elif response.status_code == 404:
156
- return f"Repository {repo_full_name} not found"
157
- else:
158
- logger.error(response.text)
159
- return f"Error retrieving pull requests: {response.status_code} - {response.text}"
160
- except NotAuthorizedError as e:
161
- return e.message
162
- except Exception as e:
163
- logger.error(e)
164
- return f"Error retrieving pull requests: {str(e)}"
124
+ result += f"- PR #{pr_number}: {pr_title} (by {pr_user}, Status: {pr_state})\n"
125
+
126
+ return result
165
127
 
166
128
  def list_issues(self, repo_full_name: str, per_page: int = 30, page: int = 1) -> str:
167
129
  """List issues for a GitHub repository
@@ -174,40 +136,29 @@ class GithubApp(APIApplication):
174
136
  Returns:
175
137
  A formatted list of issues
176
138
  """
177
- try:
178
- repo_full_name = repo_full_name.strip()
179
- url = f"{self.base_api_url}/{repo_full_name}/issues/events"
180
- params = {
181
- "per_page": per_page,
182
- "page": page
183
- }
184
- response = self._get(url, params=params)
139
+ repo_full_name = repo_full_name.strip()
140
+ url = f"{self.base_api_url}/{repo_full_name}/issues/events"
141
+ params = {
142
+ "per_page": per_page,
143
+ "page": page
144
+ }
145
+ response = self._get(url, params=params)
146
+ response.raise_for_status()
147
+
148
+ issues = response.json()
149
+ if not issues:
150
+ return f"No issues found for repository {repo_full_name}"
151
+
152
+ result = f"Issues for {repo_full_name} (Page {page}):\n\n"
153
+ for issue in issues:
154
+ issue_title = issue.get("issue", {}).get("title", "No Title")
155
+ issue_number = issue.get("issue", {}).get("number", "Unknown")
156
+ issue_state = issue.get("issue", {}).get("state", "Unknown")
157
+ issue_user = issue.get("issue", {}).get("user", {}).get("login", "Unknown")
185
158
 
186
- if response.status_code == 200:
187
- issues = response.json()
188
- if not issues:
189
- return f"No issues found for repository {repo_full_name}"
190
-
191
- result = f"Issues for {repo_full_name} (Page {page}):\n\n"
192
- for issue in issues:
193
- issue_title = issue.get("issue", {}).get("title", "No Title")
194
- issue_number = issue.get("issue", {}).get("number", "Unknown")
195
- issue_state = issue.get("issue", {}).get("state", "Unknown")
196
- issue_user = issue.get("issue", {}).get("user", {}).get("login", "Unknown")
197
-
198
- result += f"- Issue #{issue_number}: {issue_title} (by {issue_user}, Status: {issue_state})\n"
199
-
200
- return result
201
- elif response.status_code == 404:
202
- return f"Repository {repo_full_name} not found"
203
- else:
204
- logger.error(response.text)
205
- return f"Error retrieving issues: {response.status_code} - {response.text}"
206
- except NotAuthorizedError as e:
207
- return e.message
208
- except Exception as e:
209
- logger.error(e)
210
- return f"Error retrieving issues: {str(e)}"
159
+ result += f"- Issue #{issue_number}: {issue_title} (by {issue_user}, Status: {issue_state})\n"
160
+
161
+ return result
211
162
 
212
163
  def get_pull_request(self, repo_full_name: str, pull_number: int) -> str:
213
164
  """Get a specific pull request for a GitHub repository
@@ -219,37 +170,26 @@ class GithubApp(APIApplication):
219
170
  Returns:
220
171
  A formatted string with pull request details
221
172
  """
222
- try:
223
- repo_full_name = repo_full_name.strip()
224
- url = f"{self.base_api_url}/{repo_full_name}/pulls/{pull_number}"
225
- response = self._get(url)
226
-
227
- if response.status_code == 200:
228
- pr = response.json()
229
- pr_title = pr.get("title", "No Title")
230
- pr_number = pr.get("number", "Unknown")
231
- pr_state = pr.get("state", "Unknown")
232
- pr_user = pr.get("user", {}).get("login", "Unknown")
233
- pr_body = pr.get("body", "No description provided.")
234
-
235
- result = (
236
- f"Pull Request #{pr_number}: {pr_title}\n"
237
- f"Created by: {pr_user}\n"
238
- f"Status: {pr_state}\n"
239
- f"Description: {pr_body}\n"
240
- )
241
-
242
- return result
243
- elif response.status_code == 404:
244
- return f"Pull request #{pull_number} not found in repository {repo_full_name}"
245
- else:
246
- logger.error(response.text)
247
- return f"Error retrieving pull request: {response.status_code} - {response.text}"
248
- except NotAuthorizedError as e:
249
- return e.message
250
- except Exception as e:
251
- logger.error(e)
252
- return f"Error retrieving pull request: {str(e)}"
173
+ repo_full_name = repo_full_name.strip()
174
+ url = f"{self.base_api_url}/{repo_full_name}/pulls/{pull_number}"
175
+ response = self._get(url)
176
+ response.raise_for_status()
177
+
178
+ pr = response.json()
179
+ pr_title = pr.get("title", "No Title")
180
+ pr_number = pr.get("number", "Unknown")
181
+ pr_state = pr.get("state", "Unknown")
182
+ pr_user = pr.get("user", {}).get("login", "Unknown")
183
+ pr_body = pr.get("body", "No description provided.")
184
+
185
+ result = (
186
+ f"Pull Request #{pr_number}: {pr_title}\n"
187
+ f"Created by: {pr_user}\n"
188
+ f"Status: {pr_state}\n"
189
+ f"Description: {pr_body}\n"
190
+ )
191
+
192
+ return result
253
193
 
254
194
  def create_pull_request(self, repo_full_name: str, title: str, head: str, base: str, body: str = "",
255
195
  maintainer_can_modify: bool = True, draft: bool = False) -> str:
@@ -267,38 +207,29 @@ class GithubApp(APIApplication):
267
207
  Returns:
268
208
  A confirmation message with the new pull request details
269
209
  """
270
- try:
271
- repo_full_name = repo_full_name.strip()
272
- url = f"{self.base_api_url}/{repo_full_name}/pulls"
273
-
274
- pull_request_data = {
275
- "title": title,
276
- "head": head,
277
- "base": base,
278
- "body": body,
279
- "maintainer_can_modify": maintainer_can_modify,
280
- "draft": draft
281
- }
282
-
283
- response = self._post(url, pull_request_data)
284
-
285
- if response.status_code in [200, 201]:
286
- pr = response.json()
287
- pr_number = pr.get("number", "Unknown")
288
- pr_url = pr.get("html_url", "")
289
-
290
- return f"Successfully created pull request #{pr_number}:\n" \
291
- f"Title: {title}\n" \
292
- f"From: {head} → To: {base}\n" \
293
- f"URL: {pr_url}"
294
- else:
295
- logger.error(response.text)
296
- return f"Error creating pull request: {response.status_code} - {response.text}"
297
- except NotAuthorizedError as e:
298
- return e.message
299
- except Exception as e:
300
- logger.error(e)
301
- return f"Error creating pull request: {str(e)}"
210
+ repo_full_name = repo_full_name.strip()
211
+ url = f"{self.base_api_url}/{repo_full_name}/pulls"
212
+
213
+ pull_request_data = {
214
+ "title": title,
215
+ "head": head,
216
+ "base": base,
217
+ "body": body,
218
+ "maintainer_can_modify": maintainer_can_modify,
219
+ "draft": draft
220
+ }
221
+
222
+ response = self._post(url, pull_request_data)
223
+ response.raise_for_status()
224
+
225
+ pr = response.json()
226
+ pr_number = pr.get("number", "Unknown")
227
+ pr_url = pr.get("html_url", "")
228
+
229
+ return f"Successfully created pull request #{pr_number}:\n" \
230
+ f"Title: {title}\n" \
231
+ f"From: {head} → To: {base}\n" \
232
+ f"URL: {pr_url}"
302
233
 
303
234
  def create_issue(self, repo_full_name: str, title: str, body: str = "", labels = None) -> str:
304
235
  """Create a new issue in a GitHub repository
@@ -315,40 +246,31 @@ class GithubApp(APIApplication):
315
246
  Returns:
316
247
  A confirmation message with the new issue details
317
248
  """
318
- try:
319
- repo_full_name = repo_full_name.strip()
320
- url = f"{self.base_api_url}/{repo_full_name}/issues"
321
-
322
- issue_data = {
323
- "title": title,
324
- "body": body
325
- }
326
-
327
- if labels:
328
- if isinstance(labels, str):
329
- labels_list = [label.strip() for label in labels.split(",") if label.strip()]
330
- issue_data["labels"] = labels_list
331
- else:
332
- issue_data["labels"] = labels
333
-
334
- response = self._post(url, issue_data)
335
-
336
- if response.status_code in [200, 201]:
337
- issue = response.json()
338
- issue_number = issue.get("number", "Unknown")
339
- issue_url = issue.get("html_url", "")
340
-
341
- return f"Successfully created issue #{issue_number}:\n" \
342
- f"Title: {title}\n" \
343
- f"URL: {issue_url}"
249
+ repo_full_name = repo_full_name.strip()
250
+ url = f"{self.base_api_url}/{repo_full_name}/issues"
251
+
252
+ issue_data = {
253
+ "title": title,
254
+ "body": body
255
+ }
256
+
257
+ if labels:
258
+ if isinstance(labels, str):
259
+ labels_list = [label.strip() for label in labels.split(",") if label.strip()]
260
+ issue_data["labels"] = labels_list
344
261
  else:
345
- logger.error(response.text)
346
- return f"Error creating issue: {response.status_code} - {response.text}"
347
- except NotAuthorizedError as e:
348
- return e.message
349
- except Exception as e:
350
- logger.error(e)
351
- return f"Error creating issue: {str(e)}"
262
+ issue_data["labels"] = labels
263
+
264
+ response = self._post(url, issue_data)
265
+ response.raise_for_status()
266
+
267
+ issue = response.json()
268
+ issue_number = issue.get("number", "Unknown")
269
+ issue_url = issue.get("html_url", "")
270
+
271
+ return f"Successfully created issue #{issue_number}:\n" \
272
+ f"Title: {title}\n" \
273
+ f"URL: {issue_url}"
352
274
 
353
275
  def list_repo_activities(self, repo_full_name: str, direction: str = "desc", per_page: int = 30) -> str:
354
276
  """List activities for a GitHub repository
@@ -361,46 +283,35 @@ class GithubApp(APIApplication):
361
283
  Returns:
362
284
  A formatted list of repository activities
363
285
  """
364
- try:
365
- repo_full_name = repo_full_name.strip()
366
- url = f"{self.base_api_url}/{repo_full_name}/activity"
367
-
368
- # Build query parameters
369
- params = {
370
- "direction": direction,
371
- "per_page": per_page
372
- }
373
-
374
- response = self._get(url, params=params)
286
+ repo_full_name = repo_full_name.strip()
287
+ url = f"{self.base_api_url}/{repo_full_name}/activity"
288
+
289
+ # Build query parameters
290
+ params = {
291
+ "direction": direction,
292
+ "per_page": per_page
293
+ }
294
+
295
+ response = self._get(url, params=params)
296
+ response.raise_for_status()
297
+
298
+ activities = response.json()
299
+ if not activities:
300
+ return f"No activities found for repository {repo_full_name}"
301
+
302
+ result = f"Repository activities for {repo_full_name}:\n\n"
303
+
304
+ for activity in activities:
305
+ # Extract common fields
306
+ timestamp = activity.get("timestamp", "Unknown time")
307
+ actor_name = "Unknown user"
308
+ if "actor" in activity and activity["actor"]:
309
+ actor_name = activity["actor"].get("login", "Unknown user")
375
310
 
376
- if response.status_code == 200:
377
- activities = response.json()
378
- if not activities:
379
- return f"No activities found for repository {repo_full_name}"
380
-
381
- result = f"Repository activities for {repo_full_name}:\n\n"
382
-
383
- for activity in activities:
384
- # Extract common fields
385
- timestamp = activity.get("timestamp", "Unknown time")
386
- actor_name = "Unknown user"
387
- if "actor" in activity and activity["actor"]:
388
- actor_name = activity["actor"].get("login", "Unknown user")
389
-
390
- # Create a simple description of the activity
391
- result += f"- {actor_name} performed an activity at {timestamp}\n"
392
-
393
- return result
394
- elif response.status_code == 404:
395
- return f"Repository {repo_full_name} not found"
396
- else:
397
- logger.error(response.text)
398
- return f"Error retrieving activities: {response.status_code} - {response.text}"
399
- except NotAuthorizedError as e:
400
- return e.message
401
- except Exception as e:
402
- logger.error(e)
403
- return f"Error retrieving activities: {str(e)}"
311
+ # Create a simple description of the activity
312
+ result += f"- {actor_name} performed an activity at {timestamp}\n"
313
+
314
+ return result
404
315
 
405
316
  def list_tools(self):
406
317
  return [self.star_repository, self.list_commits, self.list_branches,