Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
Henri Bonamy commited on
Commit ·
8406ff4
1
Parent(s): 296641b
Added tool to go from draft to open PR, enabling merging + minor improvements
Browse files- agent/tools/hf_repo_git_tool.py +67 -13
agent/tools/hf_repo_git_tool.py
CHANGED
|
@@ -16,7 +16,7 @@ OperationType = Literal[
|
|
| 16 |
"create_branch", "delete_branch",
|
| 17 |
"create_tag", "delete_tag",
|
| 18 |
"list_refs",
|
| 19 |
-
"create_pr", "list_prs", "get_pr", "merge_pr", "close_pr", "comment_pr",
|
| 20 |
"create_repo", "update_repo",
|
| 21 |
]
|
| 22 |
|
|
@@ -59,6 +59,7 @@ class HfRepoGitTool:
|
|
| 59 |
"merge_pr": self._merge_pr,
|
| 60 |
"close_pr": self._close_pr,
|
| 61 |
"comment_pr": self._comment_pr,
|
|
|
|
| 62 |
"create_repo": self._create_repo,
|
| 63 |
"update_repo": self._update_repo,
|
| 64 |
}
|
|
@@ -88,9 +89,10 @@ class HfRepoGitTool:
|
|
| 88 |
- `list_refs`: `{"operation": "list_refs", "repo_id": "..."}`
|
| 89 |
|
| 90 |
**PRs:**
|
| 91 |
-
- `create_pr`: `{"operation": "create_pr", "repo_id": "...", "title": "..."}`
|
| 92 |
-
- `list_prs`: `{"operation": "list_prs", "repo_id": "..."}`
|
| 93 |
-
- `get_pr`: `{"operation": "get_pr", "repo_id": "...", "pr_num": 1}`
|
|
|
|
| 94 |
- `merge_pr`: `{"operation": "merge_pr", "repo_id": "...", "pr_num": 1}`
|
| 95 |
- `close_pr`: `{"operation": "close_pr", "repo_id": "...", "pr_num": 1}`
|
| 96 |
- `comment_pr`: `{"operation": "comment_pr", "repo_id": "...", "pr_num": 1, "comment": "..."}`
|
|
@@ -268,7 +270,7 @@ class HfRepoGitTool:
|
|
| 268 |
|
| 269 |
url = f"{_build_repo_url(repo_id, repo_type)}/discussions/{result.num}"
|
| 270 |
return {
|
| 271 |
-
"formatted": f"**PR #{result.num} created:** {title}\n{url}\n\nAdd commits via upload with revision=\"refs/pr/{result.num}\"",
|
| 272 |
"totalResults": 1,
|
| 273 |
"resultsShared": 1,
|
| 274 |
}
|
|
@@ -296,9 +298,16 @@ class HfRepoGitTool:
|
|
| 296 |
lines = [f"**{repo_id}** - {len(discussions)} discussions", f"{url}/discussions", ""]
|
| 297 |
|
| 298 |
for d in discussions[:20]:
|
| 299 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 300 |
type_label = "PR" if d.is_pull_request else "D"
|
| 301 |
-
lines.append(f"{
|
| 302 |
|
| 303 |
return {"formatted": "\n".join(lines), "totalResults": len(discussions), "resultsShared": min(20, len(discussions))}
|
| 304 |
|
|
@@ -322,7 +331,13 @@ class HfRepoGitTool:
|
|
| 322 |
)
|
| 323 |
|
| 324 |
url = f"{_build_repo_url(repo_id, repo_type)}/discussions/{pr_num}"
|
| 325 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 326 |
type_label = "Pull Request" if pr.is_pull_request else "Discussion"
|
| 327 |
|
| 328 |
lines = [
|
|
@@ -333,7 +348,10 @@ class HfRepoGitTool:
|
|
| 333 |
]
|
| 334 |
|
| 335 |
if pr.is_pull_request:
|
| 336 |
-
|
|
|
|
|
|
|
|
|
|
| 337 |
|
| 338 |
return {"formatted": "\n".join(lines), "totalResults": 1, "resultsShared": 1}
|
| 339 |
|
|
@@ -411,6 +429,34 @@ class HfRepoGitTool:
|
|
| 411 |
url = f"{_build_repo_url(repo_id, repo_type)}/discussions/{pr_num}"
|
| 412 |
return {"formatted": f"**Comment added to #{pr_num}**\n{url}", "totalResults": 1, "resultsShared": 1}
|
| 413 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 414 |
# =========================================================================
|
| 415 |
# REPO MANAGEMENT
|
| 416 |
# =========================================================================
|
|
@@ -490,7 +536,7 @@ HF_REPO_GIT_TOOL_SPEC = {
|
|
| 490 |
"## Operations\n"
|
| 491 |
"**Branches:** create_branch, delete_branch, list_refs\n"
|
| 492 |
"**Tags:** create_tag, delete_tag\n"
|
| 493 |
-
"**PRs:** create_pr, list_prs, get_pr, merge_pr, close_pr, comment_pr\n"
|
| 494 |
"**Repo:** create_repo, update_repo\n\n"
|
| 495 |
"## Use when\n"
|
| 496 |
"- Creating feature branches for experiments\n"
|
|
@@ -504,14 +550,17 @@ HF_REPO_GIT_TOOL_SPEC = {
|
|
| 504 |
'{"operation": "create_branch", "repo_id": "my-model", "branch": "experiment-v2"}\n'
|
| 505 |
'{"operation": "create_tag", "repo_id": "my-model", "tag": "v1.0", "revision": "main"}\n'
|
| 506 |
'{"operation": "create_pr", "repo_id": "org/model", "title": "Fix tokenizer config"}\n'
|
|
|
|
| 507 |
'{"operation": "merge_pr", "repo_id": "my-model", "pr_num": 3}\n'
|
| 508 |
'{"operation": "create_repo", "repo_id": "my-new-model", "private": true}\n'
|
| 509 |
'{"operation": "update_repo", "repo_id": "my-model", "gated": "auto"}\n\n'
|
| 510 |
"## PR Workflow\n"
|
| 511 |
-
"1. create_pr → creates
|
| 512 |
"2. Upload files with revision='refs/pr/N' to add commits\n"
|
| 513 |
-
"3.
|
|
|
|
| 514 |
"## Notes\n"
|
|
|
|
| 515 |
"- delete_branch, delete_tag, merge_pr, create_repo, update_repo require approval\n"
|
| 516 |
"- For spaces, create_repo needs space_sdk (gradio/streamlit/docker/static)\n"
|
| 517 |
"- gated options: 'auto' (instant), 'manual' (review), false (open)\n"
|
|
@@ -524,7 +573,7 @@ HF_REPO_GIT_TOOL_SPEC = {
|
|
| 524 |
"enum": [
|
| 525 |
"create_branch", "delete_branch",
|
| 526 |
"create_tag", "delete_tag", "list_refs",
|
| 527 |
-
"create_pr", "list_prs", "get_pr", "merge_pr", "close_pr", "comment_pr",
|
| 528 |
"create_repo", "update_repo",
|
| 529 |
],
|
| 530 |
"description": "Operation to execute",
|
|
@@ -579,6 +628,11 @@ HF_REPO_GIT_TOOL_SPEC = {
|
|
| 579 |
"enum": ["open", "closed", "all"],
|
| 580 |
"description": "Filter PRs by status (list_prs)",
|
| 581 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 582 |
"private": {
|
| 583 |
"type": "boolean",
|
| 584 |
"description": "Make repo private (create_repo, update_repo)",
|
|
|
|
| 16 |
"create_branch", "delete_branch",
|
| 17 |
"create_tag", "delete_tag",
|
| 18 |
"list_refs",
|
| 19 |
+
"create_pr", "list_prs", "get_pr", "merge_pr", "close_pr", "comment_pr", "change_pr_status",
|
| 20 |
"create_repo", "update_repo",
|
| 21 |
]
|
| 22 |
|
|
|
|
| 59 |
"merge_pr": self._merge_pr,
|
| 60 |
"close_pr": self._close_pr,
|
| 61 |
"comment_pr": self._comment_pr,
|
| 62 |
+
"change_pr_status": self._change_pr_status,
|
| 63 |
"create_repo": self._create_repo,
|
| 64 |
"update_repo": self._update_repo,
|
| 65 |
}
|
|
|
|
| 89 |
- `list_refs`: `{"operation": "list_refs", "repo_id": "..."}`
|
| 90 |
|
| 91 |
**PRs:**
|
| 92 |
+
- `create_pr`: `{"operation": "create_pr", "repo_id": "...", "title": "..."}` (creates draft PR)
|
| 93 |
+
- `list_prs`: `{"operation": "list_prs", "repo_id": "..."}` (shows status: draft/open/merged/closed)
|
| 94 |
+
- `get_pr`: `{"operation": "get_pr", "repo_id": "...", "pr_num": 1}` (shows status)
|
| 95 |
+
- `change_pr_status`: `{"operation": "change_pr_status", "repo_id": "...", "pr_num": 1, "new_status": "open"}` (change draft to open)
|
| 96 |
- `merge_pr`: `{"operation": "merge_pr", "repo_id": "...", "pr_num": 1}`
|
| 97 |
- `close_pr`: `{"operation": "close_pr", "repo_id": "...", "pr_num": 1}`
|
| 98 |
- `comment_pr`: `{"operation": "comment_pr", "repo_id": "...", "pr_num": 1, "comment": "..."}`
|
|
|
|
| 270 |
|
| 271 |
url = f"{_build_repo_url(repo_id, repo_type)}/discussions/{result.num}"
|
| 272 |
return {
|
| 273 |
+
"formatted": f"**Draft PR #{result.num} created:** {title}\n{url}\n\nAdd commits via upload with revision=\"refs/pr/{result.num}\"",
|
| 274 |
"totalResults": 1,
|
| 275 |
"resultsShared": 1,
|
| 276 |
}
|
|
|
|
| 298 |
lines = [f"**{repo_id}** - {len(discussions)} discussions", f"{url}/discussions", ""]
|
| 299 |
|
| 300 |
for d in discussions[:20]:
|
| 301 |
+
if d.status == "draft":
|
| 302 |
+
status_label = "[DRAFT]"
|
| 303 |
+
elif d.status == "open":
|
| 304 |
+
status_label = "[OPEN]"
|
| 305 |
+
elif d.status == "merged":
|
| 306 |
+
status_label = "[MERGED]"
|
| 307 |
+
else:
|
| 308 |
+
status_label = "[CLOSED]"
|
| 309 |
type_label = "PR" if d.is_pull_request else "D"
|
| 310 |
+
lines.append(f"{status_label} #{d.num} [{type_label}] {d.title}")
|
| 311 |
|
| 312 |
return {"formatted": "\n".join(lines), "totalResults": len(discussions), "resultsShared": min(20, len(discussions))}
|
| 313 |
|
|
|
|
| 331 |
)
|
| 332 |
|
| 333 |
url = f"{_build_repo_url(repo_id, repo_type)}/discussions/{pr_num}"
|
| 334 |
+
status_map = {
|
| 335 |
+
"draft": "Draft",
|
| 336 |
+
"open": "Open",
|
| 337 |
+
"merged": "Merged",
|
| 338 |
+
"closed": "Closed"
|
| 339 |
+
}
|
| 340 |
+
status = status_map.get(pr.status, pr.status.capitalize())
|
| 341 |
type_label = "Pull Request" if pr.is_pull_request else "Discussion"
|
| 342 |
|
| 343 |
lines = [
|
|
|
|
| 348 |
]
|
| 349 |
|
| 350 |
if pr.is_pull_request:
|
| 351 |
+
if pr.status == "draft":
|
| 352 |
+
lines.append(f"\nTo add commits: upload with revision=\"refs/pr/{pr_num}\"")
|
| 353 |
+
elif pr.status == "open":
|
| 354 |
+
lines.append(f"\nTo add commits: upload with revision=\"refs/pr/{pr_num}\"")
|
| 355 |
|
| 356 |
return {"formatted": "\n".join(lines), "totalResults": 1, "resultsShared": 1}
|
| 357 |
|
|
|
|
| 429 |
url = f"{_build_repo_url(repo_id, repo_type)}/discussions/{pr_num}"
|
| 430 |
return {"formatted": f"**Comment added to #{pr_num}**\n{url}", "totalResults": 1, "resultsShared": 1}
|
| 431 |
|
| 432 |
+
async def _change_pr_status(self, args: Dict[str, Any]) -> ToolResult:
|
| 433 |
+
"""Change PR/discussion status (mainly to convert draft to open)."""
|
| 434 |
+
repo_id = args.get("repo_id")
|
| 435 |
+
pr_num = args.get("pr_num")
|
| 436 |
+
new_status = args.get("new_status")
|
| 437 |
+
|
| 438 |
+
if not repo_id:
|
| 439 |
+
return self._error("repo_id is required")
|
| 440 |
+
if not pr_num:
|
| 441 |
+
return self._error("pr_num is required")
|
| 442 |
+
if not new_status:
|
| 443 |
+
return self._error("new_status is required (open or closed)")
|
| 444 |
+
|
| 445 |
+
repo_type = args.get("repo_type", "model")
|
| 446 |
+
comment = args.get("comment", "")
|
| 447 |
+
|
| 448 |
+
await _async_call(
|
| 449 |
+
self.api.change_discussion_status,
|
| 450 |
+
repo_id=repo_id,
|
| 451 |
+
discussion_num=int(pr_num),
|
| 452 |
+
new_status=new_status,
|
| 453 |
+
comment=comment,
|
| 454 |
+
repo_type=repo_type,
|
| 455 |
+
)
|
| 456 |
+
|
| 457 |
+
url = f"{_build_repo_url(repo_id, repo_type)}/discussions/{pr_num}"
|
| 458 |
+
return {"formatted": f"**PR #{pr_num} status changed to {new_status}**\n{url}", "totalResults": 1, "resultsShared": 1}
|
| 459 |
+
|
| 460 |
# =========================================================================
|
| 461 |
# REPO MANAGEMENT
|
| 462 |
# =========================================================================
|
|
|
|
| 536 |
"## Operations\n"
|
| 537 |
"**Branches:** create_branch, delete_branch, list_refs\n"
|
| 538 |
"**Tags:** create_tag, delete_tag\n"
|
| 539 |
+
"**PRs:** create_pr, list_prs, get_pr, merge_pr, close_pr, comment_pr, change_pr_status\n"
|
| 540 |
"**Repo:** create_repo, update_repo\n\n"
|
| 541 |
"## Use when\n"
|
| 542 |
"- Creating feature branches for experiments\n"
|
|
|
|
| 550 |
'{"operation": "create_branch", "repo_id": "my-model", "branch": "experiment-v2"}\n'
|
| 551 |
'{"operation": "create_tag", "repo_id": "my-model", "tag": "v1.0", "revision": "main"}\n'
|
| 552 |
'{"operation": "create_pr", "repo_id": "org/model", "title": "Fix tokenizer config"}\n'
|
| 553 |
+
'{"operation": "change_pr_status", "repo_id": "my-model", "pr_num": 1, "new_status": "open"}\n'
|
| 554 |
'{"operation": "merge_pr", "repo_id": "my-model", "pr_num": 3}\n'
|
| 555 |
'{"operation": "create_repo", "repo_id": "my-new-model", "private": true}\n'
|
| 556 |
'{"operation": "update_repo", "repo_id": "my-model", "gated": "auto"}\n\n'
|
| 557 |
"## PR Workflow\n"
|
| 558 |
+
"1. create_pr → creates draft PR (empty by default)\n"
|
| 559 |
"2. Upload files with revision='refs/pr/N' to add commits\n"
|
| 560 |
+
"3. change_pr_status with new_status='open' to publish (convert draft to open)\n"
|
| 561 |
+
"4. merge_pr when ready\n\n"
|
| 562 |
"## Notes\n"
|
| 563 |
+
"- PR status: draft (default), open, merged, closed\n"
|
| 564 |
"- delete_branch, delete_tag, merge_pr, create_repo, update_repo require approval\n"
|
| 565 |
"- For spaces, create_repo needs space_sdk (gradio/streamlit/docker/static)\n"
|
| 566 |
"- gated options: 'auto' (instant), 'manual' (review), false (open)\n"
|
|
|
|
| 573 |
"enum": [
|
| 574 |
"create_branch", "delete_branch",
|
| 575 |
"create_tag", "delete_tag", "list_refs",
|
| 576 |
+
"create_pr", "list_prs", "get_pr", "merge_pr", "close_pr", "comment_pr", "change_pr_status",
|
| 577 |
"create_repo", "update_repo",
|
| 578 |
],
|
| 579 |
"description": "Operation to execute",
|
|
|
|
| 628 |
"enum": ["open", "closed", "all"],
|
| 629 |
"description": "Filter PRs by status (list_prs)",
|
| 630 |
},
|
| 631 |
+
"new_status": {
|
| 632 |
+
"type": "string",
|
| 633 |
+
"enum": ["open", "closed"],
|
| 634 |
+
"description": "New status for PR/discussion (change_pr_status)",
|
| 635 |
+
},
|
| 636 |
"private": {
|
| 637 |
"type": "boolean",
|
| 638 |
"description": "Make repo private (create_repo, update_repo)",
|