AutoGPT

Форк
0
/
cli.py 
933 строки · 32.3 Кб
1
"""
2
This is a minimal file intended to be run by users to help them manage the autogpt projects.
3

4
If you want to contribute, please use only libraries that come as part of Python.
5
To ensure efficiency, add the imports to the functions so only what is needed is imported.
6
"""
7
try:
8
    import click
9
    import github
10
except ImportError:
11
    import os
12

13
    os.system("pip3 install click")
14
    os.system("pip3 install PyGithub")
15
    import click
16

17

18
@click.group()
19
def cli():
20
    pass
21

22

23
@cli.command()
24
def setup():
25
    """Installs dependencies needed for your system. Works with Linux, MacOS and Windows WSL."""
26
    import os
27
    import subprocess
28

29
    click.echo(
30
        click.style(
31
            """
32
       d8888          888             .d8888b.  8888888b. 88888888888 
33
      d88888          888            d88P  Y88b 888   Y88b    888     
34
     d88P888          888            888    888 888    888    888     
35
    d88P 888 888  888 888888 .d88b.  888        888   d88P    888     
36
   d88P  888 888  888 888   d88""88b 888  88888 8888888P"     888     
37
  d88P   888 888  888 888   888  888 888    888 888           888     
38
 d8888888888 Y88b 888 Y88b. Y88..88P Y88b  d88P 888           888     
39
d88P     888  "Y88888  "Y888 "Y88P"   "Y8888P88 888           888     
40
                                                                                                                                       
41
""",
42
            fg="green",
43
        )
44
    )
45

46
    script_dir = os.path.dirname(os.path.realpath(__file__))
47
    setup_script = os.path.join(script_dir, "setup.sh")
48
    install_error = False
49
    if os.path.exists(setup_script):
50
        click.echo(click.style("🚀 Setup initiated...\n", fg="green"))
51
        try:
52
            subprocess.check_call([setup_script], cwd=script_dir)
53
        except subprocess.CalledProcessError:
54
            click.echo(
55
                click.style("❌ There was an issue with the installation.", fg="red")
56
            )
57
            install_error = True
58
    else:
59
        click.echo(
60
            click.style(
61
                "❌ Error: setup.sh does not exist in the current directory.", fg="red"
62
            )
63
        )
64
        install_error = True
65

66
    try:
67
        # Check if git user is configured
68
        user_name = (
69
            subprocess.check_output(["git", "config", "user.name"])
70
            .decode("utf-8")
71
            .strip()
72
        )
73
        user_email = (
74
            subprocess.check_output(["git", "config", "user.email"])
75
            .decode("utf-8")
76
            .strip()
77
        )
78

79
        if user_name and user_email:
80
            click.echo(
81
                click.style(
82
                    f"✅ Git is configured with name '{user_name}' and email '{user_email}'",
83
                    fg="green",
84
                )
85
            )
86
        else:
87
            raise subprocess.CalledProcessError(
88
                returncode=1, cmd="git config user.name or user.email"
89
            )
90

91
    except subprocess.CalledProcessError:
92
        # If the GitHub account is not configured, print instructions on how to set it up
93
        click.echo(click.style("⚠️ Git user is not configured.", fg="red"))
94
        click.echo(
95
            click.style(
96
                "To configure Git with your user info, use the following commands:",
97
                fg="red",
98
            )
99
        )
100
        click.echo(
101
            click.style('  git config --global user.name "Your (user)name"', fg="red")
102
        )
103
        click.echo(
104
            click.style('  git config --global user.email "Your email"', fg="red")
105
        )
106
        install_error = True
107

108
    print_access_token_instructions = False
109

110
    # Check for the existence of the .github_access_token file
111
    if os.path.exists(".github_access_token"):
112
        with open(".github_access_token", "r") as file:
113
            github_access_token = file.read().strip()
114
            if github_access_token:
115
                click.echo(
116
                    click.style(
117
                        "✅ GitHub access token loaded successfully.", fg="green"
118
                    )
119
                )
120
                # Check if the token has the required permissions
121
                import requests
122

123
                headers = {"Authorization": f"token {github_access_token}"}
124
                response = requests.get("https://api.github.com/user", headers=headers)
125
                if response.status_code == 200:
126
                    scopes = response.headers.get("X-OAuth-Scopes")
127
                    if "public_repo" in scopes or "repo" in scopes:
128
                        click.echo(
129
                            click.style(
130
                                "✅ GitHub access token has the required permissions.",
131
                                fg="green",
132
                            )
133
                        )
134
                    else:
135
                        install_error = True
136
                        click.echo(
137
                            click.style(
138
                                "❌ GitHub access token does not have the required permissions. Please ensure it has 'public_repo' or 'repo' scope.",
139
                                fg="red",
140
                            )
141
                        )
142
                else:
143
                    install_error = True
144
                    click.echo(
145
                        click.style(
146
                            "❌ Failed to validate GitHub access token. Please ensure it is correct.",
147
                            fg="red",
148
                        )
149
                    )
150
            else:
151
                install_error = True
152
                click.echo(
153
                    click.style(
154
                        "❌ GitHub access token file is empty. Please follow the instructions below to set up your GitHub access token.",
155
                        fg="red",
156
                    )
157
                )
158
                print_access_token_instructions = True
159
    else:
160
        # Create the .github_access_token file if it doesn't exist
161
        with open(".github_access_token", "w") as file:
162
            file.write("")
163
        install_error = True
164
        print_access_token_instructions = True
165

166
    if print_access_token_instructions:
167
        # Instructions to set up GitHub access token
168
        click.echo(
169
            click.style(
170
                "💡 To configure your GitHub access token, follow these steps:", fg="red"
171
            )
172
        )
173
        click.echo(
174
            click.style("\t1. Ensure you are logged into your GitHub account", fg="red")
175
        )
176
        click.echo(
177
            click.style("\t2. Navigate to https://github.com/settings/tokens", fg="red")
178
        )
179
        click.echo(click.style("\t3. Click on 'Generate new token'.", fg="red"))
180
        click.echo(
181
            click.style("\t4. Click on 'Generate new token (classic)'.", fg="red")
182
        )
183
        click.echo(
184
            click.style(
185
                "\t5. Fill out the form to generate a new token. Ensure you select the 'repo' scope.",
186
                fg="red",
187
            )
188
        )
189
        click.echo(
190
            click.style(
191
                "\t6. Open the '.github_access_token' file in the same directory as this script and paste the token into this file.",
192
                fg="red",
193
            )
194
        )
195
        click.echo(
196
            click.style("\t7. Save the file and run the setup command again.", fg="red")
197
        )
198

199
    if install_error:
200
        click.echo(
201
            click.style(
202
                "\n\n🔴 If you need help, please raise a ticket on GitHub at https://github.com/Significant-Gravitas/AutoGPT/issues\n\n",
203
                fg="magenta",
204
                bold=True,
205
            )
206
        )
207

208

209
@cli.group()
210
def agent():
211
    """Commands to create, start and stop agents"""
212
    pass
213

214

215
@agent.command()
216
@click.argument("agent_name")
217
def create(agent_name):
218
    """Create's a new agent with the agent name provided"""
219
    import os
220
    import re
221
    import shutil
222

223
    if not re.match(r"\w*$", agent_name):
224
        click.echo(
225
            click.style(
226
                f"😞 Agent name '{agent_name}' is not valid. It should not contain spaces or special characters other than -_",
227
                fg="red",
228
            )
229
        )
230
        return
231
    try:
232
        new_agent_dir = f"./autogpts/{agent_name}"
233
        new_agent_name = f"{agent_name.lower()}.json"
234

235
        existing_arena_files = [name.lower() for name in os.listdir("./arena/")]
236

237
        if (
238
            not os.path.exists(new_agent_dir)
239
            and not new_agent_name in existing_arena_files
240
        ):
241
            shutil.copytree("./autogpts/forge", new_agent_dir)
242
            click.echo(
243
                click.style(
244
                    f"🎉 New agent '{agent_name}' created. The code for your new agent is in: autogpts/{agent_name}",
245
                    fg="green",
246
                )
247
            )
248
        else:
249
            click.echo(
250
                click.style(
251
                    f"😞 Agent '{agent_name}' already exists. Enter a different name for your agent, the name needs to be unique regardless of case",
252
                    fg="red",
253
                )
254
            )
255
    except Exception as e:
256
        click.echo(click.style(f"😢 An error occurred: {e}", fg="red"))
257

258

259
@agent.command()
260
@click.argument("agent_name")
261
@click.option(
262
    "--no-setup",
263
    is_flag=True,
264
    help="Disables running the setup script before starting the agent",
265
)
266
def start(agent_name, no_setup):
267
    """Start agent command"""
268
    import os
269
    import subprocess
270

271
    script_dir = os.path.dirname(os.path.realpath(__file__))
272
    agent_dir = os.path.join(script_dir, f"autogpts/{agent_name}")
273
    run_command = os.path.join(agent_dir, "run")
274
    run_bench_command = os.path.join(agent_dir, "run_benchmark")
275
    if (
276
        os.path.exists(agent_dir)
277
        and os.path.isfile(run_command)
278
        and os.path.isfile(run_bench_command)
279
    ):
280
        os.chdir(agent_dir)
281
        if not no_setup:
282
            click.echo(f"⌛ Running setup for agent '{agent_name}'...")
283
            setup_process = subprocess.Popen(["./setup"], cwd=agent_dir)
284
            setup_process.wait()
285
            click.echo()
286

287
        subprocess.Popen(["./run_benchmark", "serve"], cwd=agent_dir)
288
        click.echo("⌛ (Re)starting benchmark server...")
289
        wait_until_conn_ready(8080)
290
        click.echo()
291

292
        subprocess.Popen(["./run"], cwd=agent_dir)
293
        click.echo(f"⌛ (Re)starting agent '{agent_name}'...")
294
        wait_until_conn_ready(8000)
295
        click.echo("✅ Agent application started and available on port 8000")
296
    elif not os.path.exists(agent_dir):
297
        click.echo(
298
            click.style(
299
                f"😞 Agent '{agent_name}' does not exist. Please create the agent first.",
300
                fg="red",
301
            )
302
        )
303
    else:
304
        click.echo(
305
            click.style(
306
                f"😞 Run command does not exist in the agent '{agent_name}' directory.",
307
                fg="red",
308
            )
309
        )
310

311

312
@agent.command()
313
def stop():
314
    """Stop agent command"""
315
    import os
316
    import signal
317
    import subprocess
318

319
    try:
320
        pids = subprocess.check_output(["lsof", "-t", "-i", ":8000"]).split()
321
        if isinstance(pids, int):
322
            os.kill(int(pids), signal.SIGTERM)
323
        else:
324
            for pid in pids:
325
                os.kill(int(pid), signal.SIGTERM)
326
    except subprocess.CalledProcessError:
327
        click.echo("No process is running on port 8000")
328

329
    try:
330
        pids = int(subprocess.check_output(["lsof", "-t", "-i", ":8080"]))
331
        if isinstance(pids, int):
332
            os.kill(int(pids), signal.SIGTERM)
333
        else:
334
            for pid in pids:
335
                os.kill(int(pid), signal.SIGTERM)
336
    except subprocess.CalledProcessError:
337
        click.echo("No process is running on port 8080")
338

339

340
@agent.command()
341
def list():
342
    """List agents command"""
343
    import os
344

345
    try:
346
        agents_dir = "./autogpts"
347
        agents_list = [
348
            d
349
            for d in os.listdir(agents_dir)
350
            if os.path.isdir(os.path.join(agents_dir, d))
351
        ]
352
        if agents_list:
353
            click.echo(click.style("Available agents: 🤖", fg="green"))
354
            for agent in agents_list:
355
                click.echo(click.style(f"\t🐙 {agent}", fg="blue"))
356
        else:
357
            click.echo(click.style("No agents found 😞", fg="red"))
358
    except FileNotFoundError:
359
        click.echo(click.style("The autogpts directory does not exist 😢", fg="red"))
360
    except Exception as e:
361
        click.echo(click.style(f"An error occurred: {e} 😢", fg="red"))
362

363

364
@cli.group()
365
def benchmark():
366
    """Commands to start the benchmark and list tests and categories"""
367
    pass
368

369

370
@benchmark.command(
371
    context_settings=dict(
372
        ignore_unknown_options=True,
373
    )
374
)
375
@click.argument("agent_name")
376
@click.argument("subprocess_args", nargs=-1, type=click.UNPROCESSED)
377
def start(agent_name, subprocess_args):
378
    """Starts the benchmark command"""
379
    import os
380
    import subprocess
381

382
    script_dir = os.path.dirname(os.path.realpath(__file__))
383
    agent_dir = os.path.join(script_dir, f"autogpts/{agent_name}")
384
    benchmark_script = os.path.join(agent_dir, "run_benchmark")
385
    if os.path.exists(agent_dir) and os.path.isfile(benchmark_script):
386
        os.chdir(agent_dir)
387
        subprocess.Popen([benchmark_script, *subprocess_args], cwd=agent_dir)
388
        click.echo(
389
            click.style(
390
                f"🚀 Running benchmark for '{agent_name}' with subprocess arguments: {' '.join(subprocess_args)}",
391
                fg="green",
392
            )
393
        )
394
    else:
395
        click.echo(
396
            click.style(
397
                f"😞 Agent '{agent_name}' does not exist. Please create the agent first.",
398
                fg="red",
399
            )
400
        )
401

402

403
@benchmark.group(name="categories")
404
def benchmark_categories():
405
    """Benchmark categories group command"""
406
    pass
407

408

409
@benchmark_categories.command(name="list")
410
def benchmark_categories_list():
411
    """List benchmark categories command"""
412
    import glob
413
    import json
414
    import os
415

416
    categories = set()
417

418
    # Get the directory of this file
419
    this_dir = os.path.dirname(os.path.abspath(__file__))
420

421
    glob_path = os.path.join(
422
        this_dir, "./benchmark/agbenchmark/challenges/**/[!deprecated]*/data.json"
423
    )
424
    # Use it as the base for the glob pattern, excluding 'deprecated' directory
425
    for data_file in glob.glob(glob_path, recursive=True):
426
        if "deprecated" not in data_file:
427
            with open(data_file, "r") as f:
428
                try:
429
                    data = json.load(f)
430
                    categories.update(data.get("category", []))
431
                except json.JSONDecodeError:
432
                    print(f"Error: {data_file} is not a valid JSON file.")
433
                    continue
434
                except IOError:
435
                    print(f"IOError: file could not be read: {data_file}")
436
                    continue
437

438
    if categories:
439
        click.echo(click.style("Available categories: 📚", fg="green"))
440
        for category in categories:
441
            click.echo(click.style(f"\t📖 {category}", fg="blue"))
442
    else:
443
        click.echo(click.style("No categories found 😞", fg="red"))
444

445

446
@benchmark.group(name="tests")
447
def benchmark_tests():
448
    """Benchmark tests group command"""
449
    pass
450

451

452
@benchmark_tests.command(name="list")
453
def benchmark_tests_list():
454
    """List benchmark tests command"""
455
    import glob
456
    import json
457
    import os
458
    import re
459

460
    tests = {}
461

462
    # Get the directory of this file
463
    this_dir = os.path.dirname(os.path.abspath(__file__))
464

465
    glob_path = os.path.join(
466
        this_dir, "./benchmark/agbenchmark/challenges/**/[!deprecated]*/data.json"
467
    )
468
    # Use it as the base for the glob pattern, excluding 'deprecated' directory
469
    for data_file in glob.glob(glob_path, recursive=True):
470
        if "deprecated" not in data_file:
471
            with open(data_file, "r") as f:
472
                try:
473
                    data = json.load(f)
474
                    category = data.get("category", [])
475
                    test_name = data.get("name", "")
476
                    if category and test_name:
477
                        if category[0] not in tests:
478
                            tests[category[0]] = []
479
                        tests[category[0]].append(test_name)
480
                except json.JSONDecodeError:
481
                    print(f"Error: {data_file} is not a valid JSON file.")
482
                    continue
483
                except IOError:
484
                    print(f"IOError: file could not be read: {data_file}")
485
                    continue
486

487
    if tests:
488
        click.echo(click.style("Available tests: 📚", fg="green"))
489
        for category, test_list in tests.items():
490
            click.echo(click.style(f"\t📖 {category}", fg="blue"))
491
            for test in sorted(test_list):
492
                test_name = (
493
                    " ".join(word for word in re.split("([A-Z][a-z]*)", test) if word)
494
                    .replace("_", "")
495
                    .replace("C L I", "CLI")
496
                    .replace("  ", " ")
497
                )
498
                test_name_padded = f"{test_name:<40}"
499
                click.echo(click.style(f"\t\t🔬 {test_name_padded} - {test}", fg="cyan"))
500
    else:
501
        click.echo(click.style("No tests found 😞", fg="red"))
502

503

504
@benchmark_tests.command(name="details")
505
@click.argument("test_name")
506
def benchmark_tests_details(test_name):
507
    """Benchmark test details command"""
508
    import glob
509
    import json
510
    import os
511

512
    # Get the directory of this file
513
    this_dir = os.path.dirname(os.path.abspath(__file__))
514

515
    glob_path = os.path.join(
516
        this_dir, "./benchmark/agbenchmark/challenges/**/[!deprecated]*/data.json"
517
    )
518
    # Use it as the base for the glob pattern, excluding 'deprecated' directory
519
    for data_file in glob.glob(glob_path, recursive=True):
520
        with open(data_file, "r") as f:
521
            try:
522
                data = json.load(f)
523
                if data.get("name") == test_name:
524
                    click.echo(
525
                        click.style(
526
                            f"\n{data.get('name')}\n{'-'*len(data.get('name'))}\n",
527
                            fg="blue",
528
                        )
529
                    )
530
                    click.echo(
531
                        click.style(
532
                            f"\tCategory:  {', '.join(data.get('category'))}",
533
                            fg="green",
534
                        )
535
                    )
536
                    click.echo(click.style(f"\tTask:  {data.get('task')}", fg="green"))
537
                    click.echo(
538
                        click.style(
539
                            f"\tDependencies:  {', '.join(data.get('dependencies')) if data.get('dependencies') else 'None'}",
540
                            fg="green",
541
                        )
542
                    )
543
                    click.echo(
544
                        click.style(f"\tCutoff:  {data.get('cutoff')}\n", fg="green")
545
                    )
546
                    click.echo(
547
                        click.style("\tTest Conditions\n\t-------", fg="magenta")
548
                    )
549
                    click.echo(
550
                        click.style(
551
                            f"\t\tAnswer: {data.get('ground').get('answer')}",
552
                            fg="magenta",
553
                        )
554
                    )
555
                    click.echo(
556
                        click.style(
557
                            f"\t\tShould Contain: {', '.join(data.get('ground').get('should_contain'))}",
558
                            fg="magenta",
559
                        )
560
                    )
561
                    click.echo(
562
                        click.style(
563
                            f"\t\tShould Not Contain: {', '.join(data.get('ground').get('should_not_contain'))}",
564
                            fg="magenta",
565
                        )
566
                    )
567
                    click.echo(
568
                        click.style(
569
                            f"\t\tFiles: {', '.join(data.get('ground').get('files'))}",
570
                            fg="magenta",
571
                        )
572
                    )
573
                    click.echo(
574
                        click.style(
575
                            f"\t\tEval: {data.get('ground').get('eval').get('type')}\n",
576
                            fg="magenta",
577
                        )
578
                    )
579
                    click.echo(click.style("\tInfo\n\t-------", fg="yellow"))
580
                    click.echo(
581
                        click.style(
582
                            f"\t\tDifficulty: {data.get('info').get('difficulty')}",
583
                            fg="yellow",
584
                        )
585
                    )
586
                    click.echo(
587
                        click.style(
588
                            f"\t\tDescription: {data.get('info').get('description')}",
589
                            fg="yellow",
590
                        )
591
                    )
592
                    click.echo(
593
                        click.style(
594
                            f"\t\tSide Effects: {', '.join(data.get('info').get('side_effects'))}",
595
                            fg="yellow",
596
                        )
597
                    )
598
                    break
599

600
            except json.JSONDecodeError:
601
                print(f"Error: {data_file} is not a valid JSON file.")
602
                continue
603
            except IOError:
604
                print(f"IOError: file could not be read: {data_file}")
605
                continue
606

607

608
@cli.group()
609
def arena():
610
    """Commands to enter the arena"""
611
    pass
612

613

614
@arena.command()
615
@click.argument("agent_name")
616
@click.option("--branch", default="master", help="Branch to use instead of master")
617
def enter(agent_name, branch):
618
    import json
619
    import os
620
    import subprocess
621
    from datetime import datetime
622

623
    from github import Github
624

625
    # Check if the agent_name directory exists in the autogpts directory
626
    agent_dir = f"./autogpts/{agent_name}"
627
    if not os.path.exists(agent_dir):
628
        click.echo(
629
            click.style(
630
                f"❌ The directory for agent '{agent_name}' does not exist in the autogpts directory.",
631
                fg="red",
632
            )
633
        )
634
        click.echo(
635
            click.style(
636
                f"🚀 Run './run agent create {agent_name}' to create the agent.",
637
                fg="yellow",
638
            )
639
        )
640

641
        return
642
    else:
643
        # Check if the agent has already entered the arena
644
        try:
645
            subprocess.check_output(
646
                [
647
                    "git",
648
                    "rev-parse",
649
                    "--verify",
650
                    "--quiet",
651
                    f"arena_submission_{agent_name}",
652
                ]
653
            )
654
        except subprocess.CalledProcessError:
655
            pass
656
        else:
657
            click.echo(
658
                click.style(
659
                    f"⚠️  The agent '{agent_name}' has already entered the arena. To update your submission, follow these steps:",
660
                    fg="yellow",
661
                )
662
            )
663
            click.echo(
664
                click.style(
665
                    f"1. Get the git hash of your submission by running 'git rev-parse HEAD' on the branch you want to submit to the arena.",
666
                    fg="yellow",
667
                )
668
            )
669
            click.echo(
670
                click.style(
671
                    f"2. Change the branch to 'arena_submission_{agent_name}' by running 'git checkout arena_submission_{agent_name}'.",
672
                    fg="yellow",
673
                )
674
            )
675
            click.echo(
676
                click.style(
677
                    f"3. Modify the 'arena/{agent_name}.json' to include the new commit hash of your submission (the hash you got from step 1) and an up-to-date timestamp by running './run arena update {agent_name} hash --branch x'.",
678
                    fg="yellow",
679
                )
680
            )
681
            click.echo(
682
                click.style(
683
                    f"Note: The '--branch' option is only needed if you want to change the branch that will be used.",
684
                    fg="yellow",
685
                )
686
            )
687
            return
688

689
    # Check if there are staged changes
690
    staged_changes = [
691
        line
692
        for line in subprocess.check_output(["git", "status", "--porcelain"])
693
        .decode("utf-8")
694
        .split("\n")
695
        if line and line[0] in ("A", "M", "D", "R", "C")
696
    ]
697
    if staged_changes:
698
        click.echo(
699
            click.style(
700
                f"❌ There are staged changes. Please commit or stash them and run the command again.",
701
                fg="red",
702
            )
703
        )
704
        return
705

706
    try:
707
        # Load GitHub access token from file
708
        with open(".github_access_token", "r") as file:
709
            github_access_token = file.read().strip()
710

711
        # Get GitHub repository URL
712
        github_repo_url = (
713
            subprocess.check_output(["git", "config", "--get", "remote.origin.url"])
714
            .decode("utf-8")
715
            .strip()
716
        )
717

718
        if github_repo_url.startswith("git@"):
719
            github_repo_url = (
720
                github_repo_url.replace(":", "/")
721
                .replace("git@", "https://")
722
                .replace(".git", "")
723
            )
724

725
        # If --branch is passed, use it instead of master
726
        if branch:
727
            branch_to_use = branch
728
        else:
729
            branch_to_use = "master"
730

731
        # Get the commit hash of HEAD of the branch_to_use
732
        commit_hash_to_benchmark = (
733
            subprocess.check_output(["git", "rev-parse", branch_to_use])
734
            .decode("utf-8")
735
            .strip()
736
        )
737

738
        arena_submission_branch = f"arena_submission_{agent_name}"
739
        # Create a new branch called arena_submission_{agent_name}
740
        subprocess.check_call(["git", "checkout", "-b", arena_submission_branch])
741
        # Create a dictionary with the necessary fields
742
        data = {
743
            "github_repo_url": github_repo_url,
744
            "timestamp": datetime.utcnow().isoformat(),
745
            "commit_hash_to_benchmark": commit_hash_to_benchmark,
746
        }
747

748
        # If --branch was passed, add branch_to_benchmark to the JSON file
749
        if branch:
750
            data["branch_to_benchmark"] = branch
751

752
        # Create agent directory if it does not exist
753
        subprocess.check_call(["mkdir", "-p", "arena"])
754

755
        # Create a JSON file with the data
756
        with open(f"arena/{agent_name}.json", "w") as json_file:
757
            json.dump(data, json_file, indent=4)
758

759
        # Create a commit with the specified message
760
        subprocess.check_call(["git", "add", f"arena/{agent_name}.json"])
761
        subprocess.check_call(
762
            ["git", "commit", "-m", f"{agent_name} entering the arena"]
763
        )
764

765
        # Push the commit
766
        subprocess.check_call(["git", "push", "origin", arena_submission_branch])
767

768
        # Create a PR into the parent repository
769
        g = Github(github_access_token)
770
        repo_name = github_repo_url.replace("https://github.com/", "")
771
        repo = g.get_repo(repo_name)
772
        parent_repo = repo.parent
773
        if parent_repo:
774
            pr_message = f"""
775
### 🌟 Welcome to the AutoGPT Arena Hacks Hackathon! 🌟
776

777
Hey there amazing builders! We're thrilled to have you join this exciting journey. Before you dive deep into building, we'd love to know more about you and the awesome project you are envisioning. Fill out the template below to kickstart your hackathon journey. May the best agent win! 🏆
778

779
#### 🤖 Team Introduction
780

781
- **Agent Name:** {agent_name}
782
- **Team Members:** (Who are the amazing minds behind this team? Do list everyone along with their roles!)
783
- **Repository Link:** [{github_repo_url.replace('https://github.com/', '')}]({github_repo_url})
784

785
#### 🌟 Project Vision
786

787
- **Starting Point:** (Are you building from scratch or starting with an existing agent? Do tell!)
788
- **Preliminary Ideas:** (Share your initial ideas and what kind of project you are aiming to build. We are all ears!)
789
  
790
#### 🏆 Prize Category
791

792
- **Target Prize:** (Which prize caught your eye? Which one are you aiming for?)
793
- **Why this Prize:** (We'd love to know why this prize feels like the right fit for your team!)
794

795
#### 🎬 Introduction Video
796

797
- **Video Link:** (If you'd like, share a short video where you introduce your team and talk about your project. We'd love to see your enthusiastic faces!)
798

799
#### 📝 Notes and Compliance
800

801
- **Additional Notes:** (Any other things you want to share? We're here to listen!)
802
- **Compliance with Hackathon Rules:** (Just a gentle reminder to stick to the rules outlined for the hackathon)
803

804
#### ✅ Checklist
805

806
- [ ] We have read and are aligned with the [Hackathon Rules](https://lablab.ai/event/autogpt-arena-hacks).
807
- [ ] We confirm that our project will be open-source and adhere to the MIT License.
808
- [ ] Our lablab.ai registration email matches our OpenAI account to claim the bonus credits (if applicable).
809
"""
810
            head = f"{repo.owner.login}:{arena_submission_branch}"
811
            pr = parent_repo.create_pull(
812
                title=f"{agent_name} entering the arena",
813
                body=pr_message,
814
                head=head,
815
                base=branch_to_use,
816
            )
817
            click.echo(
818
                click.style(
819
                    f"🚀 {agent_name} has entered the arena! Please edit your PR description at the following URL: {pr.html_url}",
820
                    fg="green",
821
                )
822
            )
823
        else:
824
            click.echo(
825
                click.style(
826
                    "❌ This repository does not have a parent repository to sync with.",
827
                    fg="red",
828
                )
829
            )
830
            return
831

832
        # Switch back to the master branch
833
        subprocess.check_call(["git", "checkout", branch_to_use])
834

835
    except Exception as e:
836
        click.echo(click.style(f"❌ An error occurred: {e}", fg="red"))
837
        # Switch back to the master branch
838
        subprocess.check_call(["git", "checkout", branch_to_use])
839

840

841
@arena.command()
842
@click.argument("agent_name")
843
@click.argument("hash")
844
@click.option("--branch", default=None, help="Branch to use instead of current branch")
845
def update(agent_name, hash, branch):
846
    import json
847
    import os
848
    import subprocess
849
    from datetime import datetime
850

851
    # Check if the agent_name.json file exists in the arena directory
852
    agent_json_file = f"./arena/{agent_name}.json"
853
    # Check if they are on the correct branch
854
    current_branch = (
855
        subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"])
856
        .decode("utf-8")
857
        .strip()
858
    )
859
    correct_branch = f"arena_submission_{agent_name}"
860
    if current_branch != correct_branch:
861
        click.echo(
862
            click.style(
863
                f"❌ You are not on the correct branch. Please switch to the '{correct_branch}' branch.",
864
                fg="red",
865
            )
866
        )
867
        return
868

869
    if not os.path.exists(agent_json_file):
870
        click.echo(
871
            click.style(
872
                f"❌ The file for agent '{agent_name}' does not exist in the arena directory.",
873
                fg="red",
874
            )
875
        )
876
        click.echo(
877
            click.style(
878
                f"⚠️ You need to enter the arena first. Run './run arena enter {agent_name}'",
879
                fg="yellow",
880
            )
881
        )
882
        return
883
    else:
884
        # Load the existing data
885
        with open(agent_json_file, "r") as json_file:
886
            data = json.load(json_file)
887

888
        # Update the commit hash and timestamp
889
        data["commit_hash_to_benchmark"] = hash
890
        data["timestamp"] = datetime.utcnow().isoformat()
891

892
        # If --branch was passed, update the branch_to_benchmark in the JSON file
893
        if branch:
894
            data["branch_to_benchmark"] = branch
895

896
        # Write the updated data back to the JSON file
897
        with open(agent_json_file, "w") as json_file:
898
            json.dump(data, json_file, indent=4)
899

900
        click.echo(
901
            click.style(
902
                f"🚀 The file for agent '{agent_name}' has been updated in the arena directory.",
903
                fg="green",
904
            )
905
        )
906

907

908
def wait_until_conn_ready(port: int = 8000, timeout: int = 30):
909
    """
910
    Polls localhost:{port} until it is available for connections
911

912
    Params:
913
        port: The port for which to wait until it opens
914
        timeout: Timeout in seconds; maximum amount of time to wait
915

916
    Raises:
917
        TimeoutError: If the timeout (seconds) expires before the port opens
918
    """
919
    import socket
920
    import time
921

922
    start = time.time()
923
    while True:
924
        time.sleep(0.5)
925
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
926
            if s.connect_ex(("localhost", port)) == 0:
927
                break
928
        if time.time() > start + timeout:
929
            raise TimeoutError(f"Port {port} did not open within {timeout} seconds")
930

931

932
if __name__ == "__main__":
933
    cli()
934

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.