diff --git a/.agent-store-config.yaml b/.agent-store-config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d5d24ee57f9d537f834de0ec2e2636ebfcd62dc7 --- /dev/null +++ b/.agent-store-config.yaml @@ -0,0 +1,8 @@ +role: + name: SoftwareCompany + module: metagpt.roles.software_company + skills: + - name: WritePRD + - name: WriteDesign + - name: WriteTasks + - name: WriteCode diff --git a/.agent-store-config.yaml.example b/.agent-store-config.yaml.example new file mode 100644 index 0000000000000000000000000000000000000000..d12cc6999ee0a0665fae8a9f25a1e44443a3f1b7 --- /dev/null +++ b/.agent-store-config.yaml.example @@ -0,0 +1,9 @@ +role: + name: Teacher # Referenced the `Teacher` in `metagpt/roles/teacher.py`. + module: metagpt.roles.teacher # Referenced `metagpt/roles/teacher.py`. + skills: # Refer to the skill `name` of the published skill in `.well-known/skills.yaml`. + - name: text_to_speech + description: Text-to-speech + - name: text_to_image + description: Create a drawing based on the text. + diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000000000000000000000000000000000..2968dd34dcdc908cb1353345faa78b10192b378a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +workspace +tmp +build +workspace +dist +data +geckodriver.log diff --git a/.gitattributes b/.gitattributes index a6344aac8c09253b3b630fb776ae94478aa0275b..b5a1f82da84717ad2d14744b6b0340917c0bfc78 100644 --- a/.gitattributes +++ b/.gitattributes @@ -33,3 +33,10 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text *.zip filter=lfs diff=lfs merge=lfs -text *.zst filter=lfs diff=lfs merge=lfs -text *tfevents* filter=lfs diff=lfs merge=lfs -text +metagpt/static/assets/example-1902a4ef.png filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.mp4 filter=lfs diff=lfs merge=lfs -text +*.svg filter=lfs diff=lfs merge=lfs -text +*.jpg filter=lfs diff=lfs merge=lfs -text +*.ico filter=lfs diff=lfs merge=lfs -text +*.html linguist-detectable=false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..1a9741e913631b2f5130c0def373fd9895f068b4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,171 @@ +### Python template + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python scripts from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# report +allure-report +allure-results + +# idea +.idea +.DS_Store +.vscode + + +*.txt +docs/scripts/set_env.sh +key.yaml +output.json +data +data/output_add.json +data.ms +examples/nb/ +.chroma +*~$* +workspace/* +*.mmd +tmp +output.wav +*.bak + +# output folder +output +tmp.png + diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b1892a70907df3da64bffcc2c314f20313971e0a --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,27 @@ +default_stages: [ commit ] + +# Install +# 1. pip install pre-commit +# 2. pre-commit install(the first time you download the repo, it will be cached for future use) +repos: + - repo: https://github.com/pycqa/isort + rev: 5.11.5 + hooks: + - id: isort + args: ['--profile', 'black'] + exclude: >- + (?x)^( + .*__init__\.py$ + ) + + - repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.0.284 + hooks: + - id: ruff + + - repo: https://github.com/psf/black + rev: 23.3.0 + hooks: + - id: black + args: ['--line-length', '120'] \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..9cf4b42892d60c51fa8e8e989314626765173fb0 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,32 @@ +# Use a base image with Python3.9 and Nodejs20 slim version +FROM nikolaik/python-nodejs:python3.9-nodejs20-slim + +USER root + +# Install Debian software needed by MetaGPT and clean up in one RUN command to reduce image size +RUN apt update &&\ + apt install -y libgomp1 git chromium fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 --no-install-recommends &&\ + apt clean && rm -rf /var/lib/apt/lists/* + +# Install Mermaid CLI globally +ENV CHROME_BIN="/usr/bin/chromium" \ + PUPPETEER_CONFIG="/app/metagpt/config/puppeteer-config.json"\ + PUPPETEER_SKIP_CHROMIUM_DOWNLOAD="true" +RUN npm install -g @mermaid-js/mermaid-cli &&\ + npm cache clean --force + +# Install Python dependencies and install MetaGPT +COPY requirements.txt requirements.txt + +RUN pip install --no-cache-dir -r requirements.txt + +COPY . /app/metagpt +WORKDIR /app/metagpt +RUN mkdir logs &&\ + chmod -R 777 /app/metagpt/logs/ &&\ + mkdir workspace &&\ + chmod -R 777 /app/metagpt/workspace/ &&\ + python -m pip install -e. + + +CMD ["python", "metagpt/web/app.py"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..5b0c000cde3e4987e655f4cb50cb8b794de3be31 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) Chenglin Wu + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md index 2cfdcf8d479a43e73ef79232203aeb267eec0332..33256c1f0aefff7fa006c683f57a398b230fcca3 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,148 @@ --- -title: MG -emoji: 📉 -colorFrom: red -colorTo: yellow +title: MetaGPT +emoji: 🐼 +colorFrom: green +colorTo: blue sdk: docker +app_file: app.py pinned: false -license: mit --- -Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference +# MetaGPT: The Multi-Agent Framework + +
+ ++Assign different roles to GPTs to form a collaborative software entity for complex tasks. +
+ + + + + +1. MetaGPT takes a **one line requirement** as input and outputs **user stories / competitive analysis / requirements / data structures / APIs / documents, etc.** +2. Internally, MetaGPT includes **product managers / architects / project managers / engineers.** It provides the entire process of a **software company along with carefully orchestrated SOPs.** + 1. `Code = SOP(Team)` is the core philosophy. We materialize SOP and apply it to teams composed of LLMs. + + + +Software Company Multi-Role Schematic (Gradually Implementing)
+ + + +## Install + +### Pip installation + +```bash +# Step 1: Ensure that Python 3.9+ is installed on your system. You can check this by using: +# You can use conda to initialize a new python env +# conda create -n metagpt python=3.9 +# conda activate metagpt +python3 --version + +# Step 2: Clone the repository to your local machine for latest version, and install it. +git clone https://github.com/geekan/MetaGPT.git +cd MetaGPT +pip3 install -e. # or pip3 install metagpt # for stable version + +# Step 3: run the startup.py +# setup your OPENAI_API_KEY in key.yaml copy from config.yaml +python3 startup.py "Write a cli snake game" + +# Step 4 [Optional]: If you want to save the artifacts like diagrams such as quadrant chart, system designs, sequence flow in the workspace, you can execute the step before Step 3. By default, the framework is compatible, and the entire process can be run completely without executing this step. +# If executing, ensure that NPM is installed on your system. Then install mermaid-js. (If you don't have npm in your computer, please go to the Node.js official website to install Node.js https://nodejs.org/ and then you will have npm tool in your computer.) +npm --version +sudo npm install -g @mermaid-js/mermaid-cli +``` + +detail installation please refer to [cli_install](https://docs.deepwisdom.ai/guide/get_started/installation.html#install-stable-version) + +### Docker installation +> Note: In the Windows, you need to replace "/opt/metagpt" with a directory that Docker has permission to create, such as "D:\Users\x\metagpt" + +```bash +# Step 1: Download metagpt official image and prepare config.yaml +docker pull metagpt/metagpt:latest +mkdir -p /opt/metagpt/{config,workspace} +docker run --rm metagpt/metagpt:latest cat /app/metagpt/config/config.yaml > /opt/metagpt/config/key.yaml +vim /opt/metagpt/config/key.yaml # Change the config + +# Step 2: Run metagpt demo with container +docker run --rm \ + --privileged \ + -v /opt/metagpt/config/key.yaml:/app/metagpt/config/key.yaml \ + -v /opt/metagpt/workspace:/app/metagpt/workspace \ + metagpt/metagpt:latest \ + python startup.py "Write a cli snake game" +``` + +detail installation please refer to [docker_install](https://docs.deepwisdom.ai/guide/get_started/installation.html#install-with-docker) + +### QuickStart & Demo Video +- Try it on [MetaGPT Huggingface Space](https://huggingface.co/spaces/deepwisdom/MetaGPT) +- [Matthew Berman: How To Install MetaGPT - Build A Startup With One Prompt!!](https://youtu.be/uT75J_KG_aY) +- [Official Demo Video](https://github.com/geekan/MetaGPT/assets/2707039/5e8c1062-8c35-440f-bb20-2b0320f8d27d) + +https://github.com/geekan/MetaGPT/assets/34952977/34345016-5d13-489d-b9f9-b82ace413419 + +## Tutorial + +- 🗒 [Online Document](https://docs.deepwisdom.ai/) +- 💻 [Usage](https://docs.deepwisdom.ai/guide/get_started/quickstart.html) +- 🔎 [What can MetaGPT do?](https://docs.deepwisdom.ai/guide/get_started/introduction.html) +- 🛠 How to build your own agents? + - [MetaGPT Usage & Development Guide | Agent 101](https://docs.deepwisdom.ai/guide/tutorials/agent_101.html) + - [MetaGPT Usage & Development Guide | MultiAgent 101](https://docs.deepwisdom.ai/guide/tutorials/multi_agent_101.html) +- 🧑💻 Contribution + - [Develop Roadmap](docs/ROADMAP.md) +- 🔖 Use Cases + - [Debate](https://docs.deepwisdom.ai/guide/use_cases/multi_agent/debate.html) + - [Researcher](https://docs.deepwisdom.ai/guide/use_cases/agent/researcher.html) + - [Recepit Assistant](https://docs.deepwisdom.ai/guide/use_cases/agent/receipt_assistant.html) +- ❓ [FAQs](https://docs.deepwisdom.ai/guide/faq.html) + +## Support + +### Discard Join US +📢 Join Our [Discord Channel](https://discord.gg/ZRHeExS6xv)! + +Looking forward to seeing you there! 🎉 + +### Contact Information + +If you have any questions or feedback about this project, please feel free to contact us. We highly appreciate your suggestions! + +- **Email:** alexanderwu@fuzhi.ai +- **GitHub Issues:** For more technical inquiries, you can also create a new issue in our [GitHub repository](https://github.com/geekan/metagpt/issues). + +We will respond to all questions within 2-3 business days. + +## Citation + +For now, cite the [arXiv paper](https://arxiv.org/abs/2308.00352): + +```bibtex +@misc{hong2023metagpt, + title={MetaGPT: Meta Programming for A Multi-Agent Collaborative Framework}, + author={Sirui Hong and Mingchen Zhuge and Jonathan Chen and Xiawu Zheng and Yuheng Cheng and Ceyao Zhang and Jinlin Wang and Zili Wang and Steven Ka Shing Yau and Zijuan Lin and Liyang Zhou and Chenyu Ran and Lingfeng Xiao and Chenglin Wu and Jürgen Schmidhuber}, + year={2023}, + eprint={2308.00352}, + archivePrefix={arXiv}, + primaryClass={cs.AI} +} +``` diff --git a/agent/roles/__init__.py b/agent/roles/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..faa18be5bbf7d6e25d05b85f3c2126e1c0d0bd32 --- /dev/null +++ b/agent/roles/__init__.py @@ -0,0 +1,2 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- diff --git a/agent/roles/software_company.py b/agent/roles/software_company.py new file mode 100644 index 0000000000000000000000000000000000000000..8624b8b110bd89aaefca52aee6974830173aa3ff --- /dev/null +++ b/agent/roles/software_company.py @@ -0,0 +1,313 @@ +import json +import os +from pathlib import Path + +import aiofiles +from aiobotocore.session import get_session +from mdutils.mdutils import MdUtils +from metagpt.actions import Action, WriteCodeReview +from metagpt.actions.design_api import WriteDesign +from metagpt.actions.prepare_documents import PrepareDocuments +from metagpt.actions.project_management import WriteTasks +from metagpt.actions.summarize_code import SummarizeCode +from metagpt.actions.write_code import WriteCode +from metagpt.actions.write_prd import WritePRD +from metagpt.config import CONFIG +from metagpt.const import ( + CODE_SUMMARIES_FILE_REPO, + COMPETITIVE_ANALYSIS_FILE_REPO, + DATA_API_DESIGN_FILE_REPO, + DOCS_FILE_REPO, + PRDS_FILE_REPO, + REQUIREMENT_FILENAME, + SEQ_FLOW_FILE_REPO, + SYSTEM_DESIGN_FILE_REPO, + TASK_FILE_REPO, +) +from metagpt.environment import Environment +from metagpt.roles import Architect, Engineer, ProductManager, ProjectManager, Role +from metagpt.schema import Message, MessageQueue +from metagpt.team import Team +from metagpt.utils.common import any_to_str, is_subscribed +from metagpt.utils.file_repository import FileRepository +from pydantic import Field +from zipstream import AioZipStream + + +class RoleRun(Action): + role: Role + desc: str # f"{role.profile} {role.todo}" + + +class SoftwareCompanyEnv(Environment): + buf: MessageQueue = Field(default_factory=MessageQueue) + peek_buf: MessageQueue = Field(default_factory=MessageQueue) + + def publish_message(self, message: Message, peekable: bool = True) -> bool: + self.buf.push(msg=message) + if peekable: + self.peek_buf.push(msg=message) + return True + + def peek_messages(self): + return self.peek_buf.pop_all() + + def get_message(self): + return self.buf.pop() + + +class SoftwareCompany(Role): + """封装软件公司成角色,以快速接入agent store。""" + + company: Team = Field(default_factory=Team) + + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.company.env = SoftwareCompanyEnv() + self.company.hire([ProductManager(), Architect(), ProjectManager(), Engineer(n_borg=5)]) + + async def _think(self) -> bool: + """软件公司运行需要4轮 + + BOSS -> ProductManager -> Architect -> ProjectManager -> Engineer + BossRequirement -> WritePRD -> WriteDesign -> WriteTasks -> WriteCode + """ + while msg := self.company.env.get_message(): + for role in self.company.env.roles.values(): + if not is_subscribed(message=msg, tags=role.subscription) or not role.is_watch(caused_by=msg.cause_by): + continue + role.put_message(message=msg) + self.rc.todo = RoleRun(role=role, desc=f"{role.profile} {role.todo}") + return True + self.rc.todo = None + return False + + async def _act(self) -> Message: + await self.company.run(1, auto_archive=False) + msgs = self.company.env.peek_messages() + mappings = { + any_to_str(PrepareDocuments): self.format_requirements, + any_to_str(WritePRD): self.format_prd, + any_to_str(WriteDesign): self.format_system_design, + any_to_str(WriteTasks): self.format_task, + any_to_str(WriteCode): self.format_code, + any_to_str(WriteCodeReview): self.format_code, + any_to_str(SummarizeCode): self.format_summarize_code, + } + for msg in msgs: + func = mappings.get(msg.cause_by) + if not func: + continue + output = await func(msg) + return output + + async def format_requirements(self, msg: Message): + mdfile = MdUtils("") + doc = await FileRepository.get_file(filename=REQUIREMENT_FILENAME, relative_path=DOCS_FILE_REPO) + mdfile.new_header(2, "New Requirements", add_table_of_contents="n") + mdfile.new_paragraph(text=doc.content) + return Message(mdfile.get_md_text(), cause_by=msg.cause_by, role=msg.role) + + async def format_summarize_code(self, msg: Message): + mdfile = MdUtils("") + docs = await FileRepository.get_all_files(relative_path=CODE_SUMMARIES_FILE_REPO) + if not docs: + mdfile.new_header(2, "Code Summaries", add_table_of_contents="n") + mdfile.new_paragraph(text="Pass.") + return Message(mdfile.get_md_text(), cause_by=msg.cause_by, role=msg.role) + + ix = 0 + for doc in docs: + if ix > 0: + mdfile.new_line("---") + ix += 1 + mdfile.new_header(1, "RID:" + str(Path(doc.filename).with_suffix("")), add_table_of_contents="n") + data = json.loads(doc.content) + mdfile.new_header(2, "File names", add_table_of_contents="n") + mdfile.new_list(data.get("codes_filenames", [])) + + mdfile.new_header(2, "Summary", add_table_of_contents="n") + mdfile.insert_code(data.get("reason", ""), "json") + return Message(mdfile.get_md_text(), cause_by=msg.cause_by, role=msg.role) + + async def format_prd(self, prd: Message): + mdfile = MdUtils("") + docs = await FileRepository.get_all_files(relative_path=PRDS_FILE_REPO) + ix = 0 + for doc in docs: + filename = Path(doc.filename) + if ix > 0: + mdfile.new_line("---") + ix += 1 + mdfile.new_header(1, "RID:" + str(filename.with_suffix("")), add_table_of_contents="n") + + data = json.loads(doc.content) + for title, content in data.items(): + if title == "Competitive Analysis": + mdfile.new_header(2, title, add_table_of_contents="n") + if all(i.count(":") == 1 for i in content): + mdfile.new_table( + 2, + len(content) + 1, + ["Competitor", "Description", *(i for j in content for i in j.split(":"))], + ) + else: + mdfile.new_list(content, marked_with="1") + elif title == "Competitive Quadrant Chart": + mdfile.new_header(2, title, add_table_of_contents="n") + competitive_analysis_path = ( + CONFIG.git_repo.workdir / COMPETITIVE_ANALYSIS_FILE_REPO / filename.with_suffix(".png") + ) + if not await self._add_s3_url(md_file=mdfile, title=title, pathname=competitive_analysis_path): + mdfile.insert_code(content, "mermaid") + elif title == "Requirement Pool": + mdfile.new_header(2, title, add_table_of_contents="n") + mdfile.new_table( + 2, len(content) + 1, ["Task Description", "Priority", *(i for j in content for i in j)] + ) + elif isinstance(content, list): + mdfile.new_header(2, title, add_table_of_contents="n") + mdfile.new_list(content, marked_with="1") + else: + mdfile.new_header(2, title, add_table_of_contents="n") + mdfile.new_paragraph(content) + return Message(mdfile.get_md_text(), cause_by=prd.cause_by, role=prd.role) + + async def format_system_design(self, design: Message): + mdfile = MdUtils("") + docs = await FileRepository.get_all_files(relative_path=SYSTEM_DESIGN_FILE_REPO) + ix = 0 + for doc in docs: + filename = Path(doc.filename) + if ix > 0: + mdfile.new_line("---") + ix += 1 + mdfile.new_header(1, "RID:" + str(filename.with_suffix("")), add_table_of_contents="n") + + data = json.loads(doc.content) + for title, content in data.items(): + if title == "Project name": + mdfile.new_header(2, title, add_table_of_contents="n") + mdfile.insert_code(content, "python") + elif title == "Data structures and interfaces": + mdfile.new_header(2, title, add_table_of_contents="n") + data_api_design_path = ( + CONFIG.git_repo.workdir / DATA_API_DESIGN_FILE_REPO / filename.with_suffix(".png") + ) + if not await self._add_s3_url(md_file=mdfile, title=title, pathname=data_api_design_path): + mdfile.insert_code(content, "mermaid") + elif title == "Program call flow": + mdfile.new_header(2, title, add_table_of_contents="n") + seq_flow_path = CONFIG.git_repo.workdir / SEQ_FLOW_FILE_REPO / filename.with_suffix(".png") + if not await self._add_s3_url(md_file=mdfile, title=title, pathname=seq_flow_path): + mdfile.insert_code(content, "mermaid") + elif isinstance(content, list): + mdfile.new_header(2, title, add_table_of_contents="n") + mdfile.new_list(content, marked_with="1") + else: + mdfile.new_header(2, title, add_table_of_contents="n") + mdfile.new_paragraph(content) + return Message(mdfile.get_md_text(), cause_by=design.cause_by, role=design.role) + + async def format_task(self, task: Message): + mdfile = MdUtils("") + docs = await FileRepository.get_all_files(relative_path=TASK_FILE_REPO) + ix = 0 + for doc in docs: + filename = Path(doc.filename) + if ix > 0: + mdfile.new_line("---") + ix += 1 + mdfile.new_header(1, "RID:" + str(filename.with_suffix("")), add_table_of_contents="n") + + data = json.loads(doc.content) + for title, content in data.items(): + if title in { + "Required Python third-party packages", + "Required Other language third-party packages", + "Task list", + }: + mdfile.new_header(2, title, add_table_of_contents="n") + mdfile.new_list(content) + elif title == "Full API spec": + mdfile.new_header(2, title, add_table_of_contents="n") + mdfile.insert_code(content, "text") + elif title == "Logic Analysis": + mdfile.new_header(2, title, add_table_of_contents="n") + mdfile.new_table( + 2, len(content) + 1, ["Filename", "Class/Function Name", *(i for j in content for i in j)] + ) + elif title == "Shared Knowledge": + mdfile.new_header(2, title=title, add_table_of_contents="n") + mdfile.insert_code(content, "text") + elif isinstance(content, list): + mdfile.new_header(2, title, add_table_of_contents="n") + mdfile.new_list(content, marked_with="1") + else: + mdfile.new_header(2, title=title, add_table_of_contents="n") + mdfile.new_paragraph(text=content) + return Message(mdfile.get_md_text(), cause_by=task.cause_by, role=task.role) + + async def format_code(self, code: Message): + mdfile = MdUtils("") + docs = await FileRepository.get_all_files(relative_path=CONFIG.src_workspace) + code_block_types = { + ".py": "python", + ".yaml": "yaml", + ".yml": "yaml", + ".json": "json", + ".js": "javascript", + ".sql": "sql", + } + for doc in docs: + mdfile.new_header(2, doc.filename, add_table_of_contents="n") + suffix = doc.filename.rsplit(".", maxsplit=1)[-1] + mdfile.insert_code(doc.content, code_block_types.get(suffix, "text")) + url = await self.upload() + mdfile.new_header(2, "Project Packaging Complete", add_table_of_contents="n") + mdfile.new_paragraph( + "We are thrilled to inform you that our project has been successfully packaged " + "and is ready for download and use. You can download the packaged project through" + f" the following link:\n[Project Download Link]({url})" + ) + return Message(mdfile.get_md_text(), cause_by=code.cause_by, role=code.role) + + async def upload_file_to_s3(self, filepath: str, key: str): + async with aiofiles.open(filepath, "rb") as f: + content = await f.read() + return await self.upload_to_s3(content, key) + + async def upload_to_s3(self, content: bytes, key: str): + session = get_session() + async with session.create_client( + "s3", + aws_secret_access_key=os.getenv("S3_SECRET_KEY"), + aws_access_key_id=os.getenv("S3_ACCESS_KEY"), + endpoint_url=os.getenv("S3_ENDPOINT_URL"), + use_ssl=os.getenv("S3_SECURE"), + ) as client: + # upload object to amazon s3 + bucket = os.getenv("S3_BUCKET") + await client.put_object(Bucket=bucket, Key=key, Body=content) + return f"{os.getenv('S3_ENDPOINT_URL')}/{bucket}/{key}" + + async def upload(self): + files = [] + all_filenames = CONFIG.git_repo.get_files(relative_path=".") + for filename in all_filenames: + full_path = CONFIG.git_repo.workdir / filename + files.append({"file": str(full_path), "name": str(filename)}) + # aiozipstream + chunks = [] + async for chunk in AioZipStream(files, chunksize=32768).stream(): + chunks.append(chunk) + key = f"{CONFIG.workspace_path.name}/metagpt-{CONFIG.git_repo.workdir.name}.zip" + return await self.upload_to_s3(b"".join(chunks), key) + + async def _add_s3_url(self, md_file: MdUtils, title: str, pathname: Path) -> bool: + if pathname.exists(): + key = pathname.relative_to(CONFIG.workspace_path.parent) + url = await self.upload_file_to_s3(filepath=str(pathname), key=str(key)) + md_file.new_line(md_file.new_inline_image(title, url)) + return True + return False diff --git a/agent/static/cy_aps/assets/__commonjsHelpers__-042e6b4d.js b/agent/static/cy_aps/assets/__commonjsHelpers__-042e6b4d.js new file mode 100644 index 0000000000000000000000000000000000000000..0477d759fd6dcc2507749d991bedf1409961338e --- /dev/null +++ b/agent/static/cy_aps/assets/__commonjsHelpers__-042e6b4d.js @@ -0,0 +1 @@ +var f=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function l(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function a(e){if(e.__esModule)return e;var r=e.default;if(typeof r=="function"){var o=function n(){if(this instanceof n){var t=[null];t.push.apply(t,arguments);var u=Function.bind.apply(r,t);return new u}return r.apply(this,arguments)};o.prototype=r.prototype}else o={};return Object.defineProperty(o,"__esModule",{value:!0}),Object.keys(e).forEach(function(n){var t=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(o,n,t.get?t:{enumerable:!0,get:function(){return e[n]}})}),o}export{a,f as c,l as g}; diff --git a/agent/static/cy_aps/assets/bigTexCard-be1474a9.svg b/agent/static/cy_aps/assets/bigTexCard-be1474a9.svg new file mode 100644 index 0000000000000000000000000000000000000000..f00f2c42fb87cc34618eccaf45b41cbeee0292c6 --- /dev/null +++ b/agent/static/cy_aps/assets/bigTexCard-be1474a9.svg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:be1474a92e5ee1a0faf5a29a95da64ccbde62d6b4bb0722eb1151cffa2d8f25d +size 2768 diff --git a/agent/static/cy_aps/assets/blacklogo-ead63efd.svg b/agent/static/cy_aps/assets/blacklogo-ead63efd.svg new file mode 100644 index 0000000000000000000000000000000000000000..d0961d150a463fbae07d10e6ce1be37d0e2d93aa --- /dev/null +++ b/agent/static/cy_aps/assets/blacklogo-ead63efd.svg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ead63efd7a6e23d6c998b696fb78e8dda7039b5a54695f77005eb9ec4083f3e9 +size 5323 diff --git a/agent/static/cy_aps/assets/btn0-e612db37.png b/agent/static/cy_aps/assets/btn0-e612db37.png new file mode 100644 index 0000000000000000000000000000000000000000..5265c1224828ed6ae9343946207887f972f50d0a --- /dev/null +++ b/agent/static/cy_aps/assets/btn0-e612db37.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e612db371f4bf5fb40ce44b4bf4b77364422924f762b898d9e250074b0423306 +size 4786 diff --git a/agent/static/cy_aps/assets/btn1-25da2f4c.png b/agent/static/cy_aps/assets/btn1-25da2f4c.png new file mode 100644 index 0000000000000000000000000000000000000000..a055fbe720fce7e11924c33472abf886e35388d4 --- /dev/null +++ b/agent/static/cy_aps/assets/btn1-25da2f4c.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:25da2f4cf7929a1b056c2870bf0892200d4fed7e37ef8e5181c398fc705088ef +size 6625 diff --git a/agent/static/cy_aps/assets/btn2-d21834a1.png b/agent/static/cy_aps/assets/btn2-d21834a1.png new file mode 100644 index 0000000000000000000000000000000000000000..427a59480160b287bd2d4a83811ce39bc9ac1ee4 --- /dev/null +++ b/agent/static/cy_aps/assets/btn2-d21834a1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d21834a1bb77e4dc8bbbd69cf8b124e97bebc779cb9866b6f8ea9ee64434aca2 +size 5214 diff --git a/agent/static/cy_aps/assets/btn3-cf765453.png b/agent/static/cy_aps/assets/btn3-cf765453.png new file mode 100644 index 0000000000000000000000000000000000000000..ff5c14b8801cdaa0ef937cfd47c334594b8cb9f7 --- /dev/null +++ b/agent/static/cy_aps/assets/btn3-cf765453.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cf7654533e5892036a7c9d6671da5a7380fcdc8afa215ecf7fa449d8d50b10ba +size 6107 diff --git a/agent/static/cy_aps/assets/contributors-753a72cb.png b/agent/static/cy_aps/assets/contributors-753a72cb.png new file mode 100644 index 0000000000000000000000000000000000000000..bf6c1312a5a1c9e13b07f9e87eb9060e57a687fb --- /dev/null +++ b/agent/static/cy_aps/assets/contributors-753a72cb.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:753a72cb5284ad76c7176475e3e86f233ffd0dd81610dd39079a6d2c840cb5fe +size 121538 diff --git a/agent/static/cy_aps/assets/example-c23c1e5e.mp4 b/agent/static/cy_aps/assets/example-c23c1e5e.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..61d3d1ea7ce9fa5c48dcd53f7b97df7dbbf0e93a --- /dev/null +++ b/agent/static/cy_aps/assets/example-c23c1e5e.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c23c1e5e721d05c000d3cae32e33c3883b7736b9e059a674dc6a2093c24ba4fd +size 14430374 diff --git a/agent/static/cy_aps/assets/example-ce12f6a4.png b/agent/static/cy_aps/assets/example-ce12f6a4.png new file mode 100644 index 0000000000000000000000000000000000000000..0e945385fa7e041e491fef988fda7be3a88945b9 --- /dev/null +++ b/agent/static/cy_aps/assets/example-ce12f6a4.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ce12f6a4685ccbfe96416f527892afad06b17e2627e79a203c9433d0340990f7 +size 87383 diff --git a/agent/static/cy_aps/assets/favicon-beef0aa9.ico b/agent/static/cy_aps/assets/favicon-beef0aa9.ico new file mode 100644 index 0000000000000000000000000000000000000000..d5bdec783b33094924ce56292efa40b29fe6b9d1 --- /dev/null +++ b/agent/static/cy_aps/assets/favicon-beef0aa9.ico @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:beef0aa93bd461d89fe8d5613ca9328b3173a6747a860891f968e940554cdd8b +size 16958 diff --git a/agent/static/cy_aps/assets/home-0791050d.js b/agent/static/cy_aps/assets/home-0791050d.js new file mode 100644 index 0000000000000000000000000000000000000000..58334e1cc48d5e9a2bc969c1bafb27a9a307c470 --- /dev/null +++ b/agent/static/cy_aps/assets/home-0791050d.js @@ -0,0 +1,335 @@ +var Fw=Object.defineProperty;var Bw=(t,e,n)=>e in t?Fw(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var Mi=(t,e,n)=>(Bw(t,typeof e!="symbol"?e+"":e,n),n);import{d as be,x as yt,c as le,f as V,h as ae,l as F,n as It,k as Bt,r as ee,o as kn,w as Zt,v as ue,$ as q,j as oi,p as ot,q as dt,a2 as wr,a3 as Zi,a4 as Ji,t as St,F as st,U as Ks,R as $i,H as bm,G as Kn,i as Ft,B as ni,g as $m,K as Pn,a5 as j,J as Gw,A as Qs,a6 as Yw,I as OC,a7 as Hm,Q as si,T as Hi,z as zm,L as Xs,b as Ya,a8 as Vm,P as yn,s as Ge,u as $e,M as ji,a9 as qw,y as AC,D as Ps,aa as $w,_ as Hw,a as zw,ab as Vw,N as Ww,ac as Kw}from"./vue-e0bc46a9.js";import{_ as Un,j as Fn,k as Bn,m as Qw,o as Ht,e as Rt,M as yC,n as IC,p as Ka,q as Xw,r as Zw,O as gs,s as Jw,D as DC,u as jw,v as eM,A as tM,T as nM,B as hm,g as xC,w as rM,L as Gf,x as iM,y as aM,z as oM,E as sM,G as lM,S as cM,H as uM}from"./vendor-4cd7d240.js";import{C as Wm,U as dM,t as Km}from"./index-5df855a0.js";import{c as La,a as _M,g as Qm}from"./__commonjsHelpers__-042e6b4d.js";const pM="https://public-frontend-1300249583.cos-website.ap-nanjing.myqcloud.com/cy_aps/assets/bigTexCard-be1474a9.svg",mM="https://public-frontend-1300249583.cos-website.ap-nanjing.myqcloud.com/cy_aps/assets/example-ce12f6a4.png",gM="https://public-frontend-1300249583.cos-website.ap-nanjing.myqcloud.com/cy_aps/assets/example-c23c1e5e.mp4",EM=["xlink:href"],ea=be({__name:"Icon",props:{iconId:{},fill:{},size:{},disabled:{type:Boolean}},setup(t){const e=t,n=yt(e,"iconId"),i=yt(e,"fill"),o=le(()=>n.value.split("-").filter(l=>l).map(l=>l[0].toUpperCase()+l.slice(1)).join("")),s=le(()=>`width: ${e.size}px;height:${e.size}px;fill:${i.value}`);return(l,c)=>(V(),ae("svg",{class:It([o.value,n.value,"IconCommon",l.disabled?"iconDisabled":""]),style:Bt(s.value),"aria-hidden":"true"},[F("use",{"xlink:href":`#${n.value}`},null,8,EM)],6))}});const fM="https://public-frontend-1300249583.cos-website.ap-nanjing.myqcloud.com/cy_aps/assets/wechat-4dad209c.png",SM=be({name:"IconDownload",props:{size:{type:[Number,String]},strokeWidth:{type:Number,default:4},strokeLinecap:{type:String,default:"butt",validator:t=>["butt","round","square"].includes(t)},strokeLinejoin:{type:String,default:"miter",validator:t=>["arcs","bevel","miter","miter-clip","round"].includes(t)},rotate:Number,spin:Boolean},emits:{click:t=>!0},setup(t,{emit:e}){const n=Fn("icon"),i=le(()=>[n,`${n}-download`,{[`${n}-spin`]:t.spin}]),o=le(()=>{const l={};return t.size&&(l.fontSize=Bn(t.size)?`${t.size}px`:t.size),t.rotate&&(l.transform=`rotate(${t.rotate}deg)`),l});return{cls:i,innerStyle:o,onClick:l=>{e("click",l)}}}}),bM=["stroke-width","stroke-linecap","stroke-linejoin"],hM=F("path",{d:"m33.072 22.071-9.07 9.071-9.072-9.07M24 5v26m16 4v6H8v-6"},null,-1),TM=[hM];function vM(t,e,n,i,o,s){return V(),ae("svg",{viewBox:"0 0 48 48",fill:"none",xmlns:"http://www.w3.org/2000/svg",stroke:"currentColor",class:It(t.cls),style:Bt(t.innerStyle),"stroke-width":t.strokeWidth,"stroke-linecap":t.strokeLinecap,"stroke-linejoin":t.strokeLinejoin,onClick:e[0]||(e[0]=(...l)=>t.onClick&&t.onClick(...l))},TM,14,bM)}var Jc=Un(SM,[["render",vM]]);const CM=Object.assign(Jc,{install:(t,e)=>{var n;const i=(n=e==null?void 0:e.iconPrefix)!=null?n:"";t.component(i+Jc.name,Jc)}}),RM=be({name:"IconScan",props:{size:{type:[Number,String]},strokeWidth:{type:Number,default:4},strokeLinecap:{type:String,default:"butt",validator:t=>["butt","round","square"].includes(t)},strokeLinejoin:{type:String,default:"miter",validator:t=>["arcs","bevel","miter","miter-clip","round"].includes(t)},rotate:Number,spin:Boolean},emits:{click:t=>!0},setup(t,{emit:e}){const n=Fn("icon"),i=le(()=>[n,`${n}-scan`,{[`${n}-spin`]:t.spin}]),o=le(()=>{const l={};return t.size&&(l.fontSize=Bn(t.size)?`${t.size}px`:t.size),t.rotate&&(l.transform=`rotate(${t.rotate}deg)`),l});return{cls:i,innerStyle:o,onClick:l=>{e("click",l)}}}}),NM=["stroke-width","stroke-linecap","stroke-linejoin"],OM=F("path",{d:"M7 17V7h10m24 10V7H31m10 24v10H31M7 31v10h10M5 24h38"},null,-1),AM=[OM];function yM(t,e,n,i,o,s){return V(),ae("svg",{viewBox:"0 0 48 48",fill:"none",xmlns:"http://www.w3.org/2000/svg",stroke:"currentColor",class:It(t.cls),style:Bt(t.innerStyle),"stroke-width":t.strokeWidth,"stroke-linecap":t.strokeLinecap,"stroke-linejoin":t.strokeLinejoin,onClick:e[0]||(e[0]=(...l)=>t.onClick&&t.onClick(...l))},AM,14,NM)}var jc=Un(RM,[["render",yM]]);const IM=Object.assign(jc,{install:(t,e)=>{var n;const i=(n=e==null?void 0:e.iconPrefix)!=null?n:"";t.component(i+jc.name,jc)}}),DM=be({name:"IconSync",props:{size:{type:[Number,String]},strokeWidth:{type:Number,default:4},strokeLinecap:{type:String,default:"butt",validator:t=>["butt","round","square"].includes(t)},strokeLinejoin:{type:String,default:"miter",validator:t=>["arcs","bevel","miter","miter-clip","round"].includes(t)},rotate:Number,spin:Boolean},emits:{click:t=>!0},setup(t,{emit:e}){const n=Fn("icon"),i=le(()=>[n,`${n}-sync`,{[`${n}-spin`]:t.spin}]),o=le(()=>{const l={};return t.size&&(l.fontSize=Bn(t.size)?`${t.size}px`:t.size),t.rotate&&(l.transform=`rotate(${t.rotate}deg)`),l});return{cls:i,innerStyle:o,onClick:l=>{e("click",l)}}}}),xM=["stroke-width","stroke-linecap","stroke-linejoin"],wM=F("path",{d:"M11.98 11.703c-6.64 6.64-6.64 17.403 0 24.042a16.922 16.922 0 0 0 8.942 4.7M34.603 37.156l1.414-1.415c6.64-6.639 6.64-17.402 0-24.041A16.922 16.922 0 0 0 27.075 7M14.81 11.982l-1.414-1.414-1.414-1.414h2.829v2.828ZM33.192 36.02l1.414 1.414 1.414 1.415h-2.828V36.02Z"},null,-1),MM=[wM];function LM(t,e,n,i,o,s){return V(),ae("svg",{viewBox:"0 0 48 48",fill:"none",xmlns:"http://www.w3.org/2000/svg",stroke:"currentColor",class:It(t.cls),style:Bt(t.innerStyle),"stroke-width":t.strokeWidth,"stroke-linecap":t.strokeLinecap,"stroke-linejoin":t.strokeLinejoin,onClick:e[0]||(e[0]=(...l)=>t.onClick&&t.onClick(...l))},MM,14,xM)}var eu=Un(DM,[["render",LM]]);const Es=Object.assign(eu,{install:(t,e)=>{var n;const i=(n=e==null?void 0:e.iconPrefix)!=null?n:"";t.component(i+eu.name,eu)}}),PM=be({name:"IconVoice",props:{size:{type:[Number,String]},strokeWidth:{type:Number,default:4},strokeLinecap:{type:String,default:"butt",validator:t=>["butt","round","square"].includes(t)},strokeLinejoin:{type:String,default:"miter",validator:t=>["arcs","bevel","miter","miter-clip","round"].includes(t)},rotate:Number,spin:Boolean},emits:{click:t=>!0},setup(t,{emit:e}){const n=Fn("icon"),i=le(()=>[n,`${n}-voice`,{[`${n}-spin`]:t.spin}]),o=le(()=>{const l={};return t.size&&(l.fontSize=Bn(t.size)?`${t.size}px`:t.size),t.rotate&&(l.transform=`rotate(${t.rotate}deg)`),l});return{cls:i,innerStyle:o,onClick:l=>{e("click",l)}}}}),kM=["stroke-width","stroke-linecap","stroke-linejoin"],UM=F("path",{d:"M41 21v1c0 8.837-7.163 16-16 16h-2c-8.837 0-16-7.163-16-16v-1m17 17v6m0-14a9 9 0 0 1-9-9v-6a9 9 0 1 1 18 0v6a9 9 0 0 1-9 9Z"},null,-1),FM=[UM];function BM(t,e,n,i,o,s){return V(),ae("svg",{viewBox:"0 0 48 48",fill:"none",xmlns:"http://www.w3.org/2000/svg",stroke:"currentColor",class:It(t.cls),style:Bt(t.innerStyle),"stroke-width":t.strokeWidth,"stroke-linecap":t.strokeLinecap,"stroke-linejoin":t.strokeLinejoin,onClick:e[0]||(e[0]=(...l)=>t.onClick&&t.onClick(...l))},FM,14,kM)}var tu=Un(PM,[["render",BM]]);const GM=Object.assign(tu,{install:(t,e)=>{var n;const i=(n=e==null?void 0:e.iconPrefix)!=null?n:"";t.component(i+tu.name,tu)}}),YM=be({name:"IconPauseCircleFill",props:{size:{type:[Number,String]},strokeWidth:{type:Number,default:4},strokeLinecap:{type:String,default:"butt",validator:t=>["butt","round","square"].includes(t)},strokeLinejoin:{type:String,default:"miter",validator:t=>["arcs","bevel","miter","miter-clip","round"].includes(t)},rotate:Number,spin:Boolean},emits:{click:t=>!0},setup(t,{emit:e}){const n=Fn("icon"),i=le(()=>[n,`${n}-pause-circle-fill`,{[`${n}-spin`]:t.spin}]),o=le(()=>{const l={};return t.size&&(l.fontSize=Bn(t.size)?`${t.size}px`:t.size),t.rotate&&(l.transform=`rotate(${t.rotate}deg)`),l});return{cls:i,innerStyle:o,onClick:l=>{e("click",l)}}}}),qM=["stroke-width","stroke-linecap","stroke-linejoin"],$M=F("path",{"fill-rule":"evenodd","clip-rule":"evenodd",d:"M24 44c11.046 0 20-8.954 20-20S35.046 4 24 4 4 12.954 4 24s8.954 20 20 20Zm-6-27a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V18a1 1 0 0 0-1-1h-3Zm9 0a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V18a1 1 0 0 0-1-1h-3Z",fill:"currentColor",stroke:"none"},null,-1),HM=[$M];function zM(t,e,n,i,o,s){return V(),ae("svg",{viewBox:"0 0 48 48",fill:"none",xmlns:"http://www.w3.org/2000/svg",stroke:"currentColor",class:It(t.cls),style:Bt(t.innerStyle),"stroke-width":t.strokeWidth,"stroke-linecap":t.strokeLinecap,"stroke-linejoin":t.strokeLinejoin,onClick:e[0]||(e[0]=(...l)=>t.onClick&&t.onClick(...l))},HM,14,qM)}var nu=Un(YM,[["render",zM]]);const VM=Object.assign(nu,{install:(t,e)=>{var n;const i=(n=e==null?void 0:e.iconPrefix)!=null?n:"";t.component(i+nu.name,nu)}}),WM=be({name:"IconPlayCircleFill",props:{size:{type:[Number,String]},strokeWidth:{type:Number,default:4},strokeLinecap:{type:String,default:"butt",validator:t=>["butt","round","square"].includes(t)},strokeLinejoin:{type:String,default:"miter",validator:t=>["arcs","bevel","miter","miter-clip","round"].includes(t)},rotate:Number,spin:Boolean},emits:{click:t=>!0},setup(t,{emit:e}){const n=Fn("icon"),i=le(()=>[n,`${n}-play-circle-fill`,{[`${n}-spin`]:t.spin}]),o=le(()=>{const l={};return t.size&&(l.fontSize=Bn(t.size)?`${t.size}px`:t.size),t.rotate&&(l.transform=`rotate(${t.rotate}deg)`),l});return{cls:i,innerStyle:o,onClick:l=>{e("click",l)}}}}),KM=["stroke-width","stroke-linecap","stroke-linejoin"],QM=F("path",{"fill-rule":"evenodd","clip-rule":"evenodd",d:"M44 24c0 11.046-8.954 20-20 20S4 35.046 4 24 12.954 4 24 4s20 8.954 20 20Zm-23.662-7.783C19.302 15.605 18 16.36 18 17.575v12.85c0 1.214 1.302 1.97 2.338 1.358l10.89-6.425c1.03-.607 1.03-2.11 0-2.716l-10.89-6.425Z",fill:"currentColor",stroke:"none"},null,-1),XM=[QM];function ZM(t,e,n,i,o,s){return V(),ae("svg",{viewBox:"0 0 48 48",fill:"none",xmlns:"http://www.w3.org/2000/svg",stroke:"currentColor",class:It(t.cls),style:Bt(t.innerStyle),"stroke-width":t.strokeWidth,"stroke-linecap":t.strokeLinecap,"stroke-linejoin":t.strokeLinejoin,onClick:e[0]||(e[0]=(...l)=>t.onClick&&t.onClick(...l))},XM,14,KM)}var ru=Un(WM,[["render",ZM]]);const JM=Object.assign(ru,{install:(t,e)=>{var n;const i=(n=e==null?void 0:e.iconPrefix)!=null?n:"";t.component(i+ru.name,ru)}}),jM=be({name:"IconRecordStop",props:{size:{type:[Number,String]},strokeWidth:{type:Number,default:4},strokeLinecap:{type:String,default:"butt",validator:t=>["butt","round","square"].includes(t)},strokeLinejoin:{type:String,default:"miter",validator:t=>["arcs","bevel","miter","miter-clip","round"].includes(t)},rotate:Number,spin:Boolean},emits:{click:t=>!0},setup(t,{emit:e}){const n=Fn("icon"),i=le(()=>[n,`${n}-record-stop`,{[`${n}-spin`]:t.spin}]),o=le(()=>{const l={};return t.size&&(l.fontSize=Bn(t.size)?`${t.size}px`:t.size),t.rotate&&(l.transform=`rotate(${t.rotate}deg)`),l});return{cls:i,innerStyle:o,onClick:l=>{e("click",l)}}}}),eL=["stroke-width","stroke-linecap","stroke-linejoin"],tL=F("path",{"clip-rule":"evenodd",d:"M24 6c9.941 0 18 8.059 18 18s-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6Z"},null,-1),nL=F("path",{d:"M19 20a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1h-8a1 1 0 0 1-1-1v-8Z",fill:"currentColor",stroke:"none"},null,-1),rL=F("path",{d:"M19 20a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1h-8a1 1 0 0 1-1-1v-8Z"},null,-1),iL=[tL,nL,rL];function aL(t,e,n,i,o,s){return V(),ae("svg",{viewBox:"0 0 48 48",fill:"none",xmlns:"http://www.w3.org/2000/svg",stroke:"currentColor",class:It(t.cls),style:Bt(t.innerStyle),"stroke-width":t.strokeWidth,"stroke-linecap":t.strokeLinecap,"stroke-linejoin":t.strokeLinejoin,onClick:e[0]||(e[0]=(...l)=>t.onClick&&t.onClick(...l))},iL,14,eL)}var iu=Un(jM,[["render",aL]]);const oL=Object.assign(iu,{install:(t,e)=>{var n;const i=(n=e==null?void 0:e.iconPrefix)!=null?n:"";t.component(i+iu.name,iu)}}),sL=be({name:"IconBook",props:{size:{type:[Number,String]},strokeWidth:{type:Number,default:4},strokeLinecap:{type:String,default:"butt",validator:t=>["butt","round","square"].includes(t)},strokeLinejoin:{type:String,default:"miter",validator:t=>["arcs","bevel","miter","miter-clip","round"].includes(t)},rotate:Number,spin:Boolean},emits:{click:t=>!0},setup(t,{emit:e}){const n=Fn("icon"),i=le(()=>[n,`${n}-book`,{[`${n}-spin`]:t.spin}]),o=le(()=>{const l={};return t.size&&(l.fontSize=Bn(t.size)?`${t.size}px`:t.size),t.rotate&&(l.transform=`rotate(${t.rotate}deg)`),l});return{cls:i,innerStyle:o,onClick:l=>{e("click",l)}}}}),lL=["stroke-width","stroke-linecap","stroke-linejoin"],cL=F("path",{d:"M24 13 7 7v28l17 6 17-6V7l-17 6Zm0 0v27.5M29 18l7-2.5M29 25l7-2.5M29 32l7-2.5M19 18l-7-2.5m7 9.5-7-2.5m7 9.5-7-2.5"},null,-1),uL=[cL];function dL(t,e,n,i,o,s){return V(),ae("svg",{viewBox:"0 0 48 48",fill:"none",xmlns:"http://www.w3.org/2000/svg",stroke:"currentColor",class:It(t.cls),style:Bt(t.innerStyle),"stroke-width":t.strokeWidth,"stroke-linecap":t.strokeLinecap,"stroke-linejoin":t.strokeLinejoin,onClick:e[0]||(e[0]=(...l)=>t.onClick&&t.onClick(...l))},uL,14,lL)}var au=Un(sL,[["render",dL]]);const _L=Object.assign(au,{install:(t,e)=>{var n;const i=(n=e==null?void 0:e.iconPrefix)!=null?n:"";t.component(i+au.name,au)}}),pL=be({name:"IconImage",props:{size:{type:[Number,String]},strokeWidth:{type:Number,default:4},strokeLinecap:{type:String,default:"butt",validator:t=>["butt","round","square"].includes(t)},strokeLinejoin:{type:String,default:"miter",validator:t=>["arcs","bevel","miter","miter-clip","round"].includes(t)},rotate:Number,spin:Boolean},emits:{click:t=>!0},setup(t,{emit:e}){const n=Fn("icon"),i=le(()=>[n,`${n}-image`,{[`${n}-spin`]:t.spin}]),o=le(()=>{const l={};return t.size&&(l.fontSize=Bn(t.size)?`${t.size}px`:t.size),t.rotate&&(l.transform=`rotate(${t.rotate}deg)`),l});return{cls:i,innerStyle:o,onClick:l=>{e("click",l)}}}}),mL=["stroke-width","stroke-linecap","stroke-linejoin"],gL=F("path",{d:"m24 33 9-9v9h-9Zm0 0-3.5-4.5L17 33h7Zm15 8H9a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h30a2 2 0 0 1 2 2v30a2 2 0 0 1-2 2ZM15 15h2v2h-2v-2Z"},null,-1),EL=F("path",{d:"M33 33v-9l-9 9h9ZM23.5 33l-3-4-3 4h6ZM15 15h2v2h-2z",fill:"currentColor",stroke:"none"},null,-1),fL=[gL,EL];function SL(t,e,n,i,o,s){return V(),ae("svg",{viewBox:"0 0 48 48",fill:"none",xmlns:"http://www.w3.org/2000/svg",stroke:"currentColor",class:It(t.cls),style:Bt(t.innerStyle),"stroke-width":t.strokeWidth,"stroke-linecap":t.strokeLinecap,"stroke-linejoin":t.strokeLinejoin,onClick:e[0]||(e[0]=(...l)=>t.onClick&&t.onClick(...l))},fL,14,mL)}var ou=Un(pL,[["render",SL]]);const bL=Object.assign(ou,{install:(t,e)=>{var n;const i=(n=e==null?void 0:e.iconPrefix)!=null?n:"";t.component(i+ou.name,ou)}}),hL=be({name:"IconNav",props:{size:{type:[Number,String]},strokeWidth:{type:Number,default:4},strokeLinecap:{type:String,default:"butt",validator:t=>["butt","round","square"].includes(t)},strokeLinejoin:{type:String,default:"miter",validator:t=>["arcs","bevel","miter","miter-clip","round"].includes(t)},rotate:Number,spin:Boolean},emits:{click:t=>!0},setup(t,{emit:e}){const n=Fn("icon"),i=le(()=>[n,`${n}-nav`,{[`${n}-spin`]:t.spin}]),o=le(()=>{const l={};return t.size&&(l.fontSize=Bn(t.size)?`${t.size}px`:t.size),t.rotate&&(l.transform=`rotate(${t.rotate}deg)`),l});return{cls:i,innerStyle:o,onClick:l=>{e("click",l)}}}}),TL=["stroke-width","stroke-linecap","stroke-linejoin"],vL=F("path",{d:"M6 19h10m0 0h26m-26 0V9m0 10v10m0 0v10m0-10H6m10 0h26M6 9h36v30H6V9Z"},null,-1),CL=[vL];function RL(t,e,n,i,o,s){return V(),ae("svg",{viewBox:"0 0 48 48",fill:"none",xmlns:"http://www.w3.org/2000/svg",stroke:"currentColor",class:It(t.cls),style:Bt(t.innerStyle),"stroke-width":t.strokeWidth,"stroke-linecap":t.strokeLinecap,"stroke-linejoin":t.strokeLinejoin,onClick:e[0]||(e[0]=(...l)=>t.onClick&&t.onClick(...l))},CL,14,TL)}var su=Un(hL,[["render",RL]]);const NL=Object.assign(su,{install:(t,e)=>{var n;const i=(n=e==null?void 0:e.iconPrefix)!=null?n:"";t.component(i+su.name,su)}}),OL=be({name:"IconPublic",props:{size:{type:[Number,String]},strokeWidth:{type:Number,default:4},strokeLinecap:{type:String,default:"butt",validator:t=>["butt","round","square"].includes(t)},strokeLinejoin:{type:String,default:"miter",validator:t=>["arcs","bevel","miter","miter-clip","round"].includes(t)},rotate:Number,spin:Boolean},emits:{click:t=>!0},setup(t,{emit:e}){const n=Fn("icon"),i=le(()=>[n,`${n}-public`,{[`${n}-spin`]:t.spin}]),o=le(()=>{const l={};return t.size&&(l.fontSize=Bn(t.size)?`${t.size}px`:t.size),t.rotate&&(l.transform=`rotate(${t.rotate}deg)`),l});return{cls:i,innerStyle:o,onClick:l=>{e("click",l)}}}}),AL=["stroke-width","stroke-linecap","stroke-linejoin"],yL=F("path",{d:"M15 21.5 6.704 19M15 21.5l4.683 5.152a1 1 0 0 1 .25.814L18 40.976l10.918-16.117a1 1 0 0 0-.298-1.409L21.5 19 15 21.5Zm0 0 6.062-6.995a1 1 0 0 0 .138-1.103L18 7.024M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6s18 8.059 18 18Z"},null,-1),IL=[yL];function DL(t,e,n,i,o,s){return V(),ae("svg",{viewBox:"0 0 48 48",fill:"none",xmlns:"http://www.w3.org/2000/svg",stroke:"currentColor",class:It(t.cls),style:Bt(t.innerStyle),"stroke-width":t.strokeWidth,"stroke-linecap":t.strokeLinecap,"stroke-linejoin":t.strokeLinejoin,onClick:e[0]||(e[0]=(...l)=>t.onClick&&t.onClick(...l))},IL,14,AL)}var lu=Un(OL,[["render",DL]]);const xL=Object.assign(lu,{install:(t,e)=>{var n;const i=(n=e==null?void 0:e.iconPrefix)!=null?n:"";t.component(i+lu.name,lu)}}),wL={class:"header"},ML={class:"content"},LL=be({__name:"modal",props:{visible:{type:Boolean}},emits:["update:visible","close"],setup(t,{emit:e}){const n=t,i=ee(null),o=()=>{e("update:visible",!1),e("close")};return kn(()=>{Zt(()=>n.visible,s=>{var l,c;s?(l=i.value)==null||l.showModal():(c=i.value)==null||c.close()},{immediate:!0})}),(s,l)=>(V(),ae("dialog",{ref_key:"dialogRef",ref:i,class:"customDialog"},[F("div",wL,[ue(q(Qw),{style:{cursor:"pointer"},size:24,onClick:o})]),F("div",ML,[oi(s.$slots,"default",{},void 0,!0)])],512))}});const Dt=(t,e)=>{const n=t.__vccOpts||t;for(const[i,o]of e)n[i]=o;return n},wC=Dt(LL,[["__scopeId","data-v-6fddb6c7"]]),Zs=t=>(Zi("data-v-e442bd8c"),t=t(),Ji(),t),PL={class:"wechatModal"},kL={class:"title"},UL=Zs(()=>F("div",{class:"titleText"},"WeChat",-1)),FL=Zs(()=>F("div",{class:"desc"}," Add the MetaGPT WeChat assistant to get the latest MetaGPT updates. Join the MetaGPT community for more high-quality technical and product discussions. ",-1)),BL={class:"qrCode"},GL=Zs(()=>F("img",{style:{width:"100%"},src:fM,alt:""},null,-1)),YL={class:"scanText"},qL=Zs(()=>F("span",null,"Scan on WeChat to add.",-1)),$L=be({__name:"wechatModal",props:{visible:{type:Boolean}},emits:["update:visible"],setup(t,{emit:e}){const i=yt(t,"visible"),o=()=>{e("update:visible",!1)};return(s,l)=>(V(),ot(wC,{visible:q(i),"onUpdate:visible":l[0]||(l[0]=c=>wr(i)?i.value=c:null),style:{width:"527px"},onClose:o},{default:dt(()=>[F("div",PL,[F("div",kL,[ue(ea,{size:28,fill:"#28C445","icon-id":"icon-wechat2"}),UL]),FL,F("div",BL,[GL,F("span",YL,[ue(q(IM),{size:16}),qL])])])]),_:1},8,["visible"]))}});const HL=Dt($L,[["__scopeId","data-v-e442bd8c"]]),zL="https://public-frontend-1300249583.cos-website.ap-nanjing.myqcloud.com/cy_aps/assets/blacklogo-ead63efd.svg",VL={},WL={style:{width:"32px","vertical-align":"middle"},src:zL};function KL(t,e){return V(),ae("img",WL)}const QL=Dt(VL,[["render",KL]]);let ks=[];const MC=new WeakMap;function XL(){ks.forEach(t=>t(...MC.get(t))),ks=[]}function LC(t,...e){MC.set(t,e),!ks.includes(t)&&ks.push(t)===1&&requestAnimationFrame(XL)}function Us(t){return t.composedPath()[0]||null}const Yf={black:"#000",silver:"#C0C0C0",gray:"#808080",white:"#FFF",maroon:"#800000",red:"#F00",purple:"#800080",fuchsia:"#F0F",green:"#008000",lime:"#0F0",olive:"#808000",yellow:"#FF0",navy:"#000080",blue:"#00F",teal:"#008080",aqua:"#0FF",transparent:"#0000"},ta="^\\s*",na="\\s*$",Xr="\\s*((\\.\\d+)|(\\d+(\\.\\d*)?))\\s*",Zr="([0-9A-Fa-f])",Jr="([0-9A-Fa-f]{2})",ZL=new RegExp(`${ta}rgb\\s*\\(${Xr},${Xr},${Xr}\\)${na}`),JL=new RegExp(`${ta}rgba\\s*\\(${Xr},${Xr},${Xr},${Xr}\\)${na}`),jL=new RegExp(`${ta}#${Zr}${Zr}${Zr}${na}`),e0=new RegExp(`${ta}#${Jr}${Jr}${Jr}${na}`),t0=new RegExp(`${ta}#${Zr}${Zr}${Zr}${Zr}${na}`),n0=new RegExp(`${ta}#${Jr}${Jr}${Jr}${Jr}${na}`);function sn(t){return parseInt(t,16)}function Ki(t){try{let e;if(e=e0.exec(t))return[sn(e[1]),sn(e[2]),sn(e[3]),1];if(e=ZL.exec(t))return[Qt(e[1]),Qt(e[5]),Qt(e[9]),1];if(e=JL.exec(t))return[Qt(e[1]),Qt(e[5]),Qt(e[9]),qa(e[13])];if(e=jL.exec(t))return[sn(e[1]+e[1]),sn(e[2]+e[2]),sn(e[3]+e[3]),1];if(e=n0.exec(t))return[sn(e[1]),sn(e[2]),sn(e[3]),qa(sn(e[4])/255)];if(e=t0.exec(t))return[sn(e[1]+e[1]),sn(e[2]+e[2]),sn(e[3]+e[3]),qa(sn(e[4]+e[4])/255)];if(t in Yf)return Ki(Yf[t]);throw new Error(`[seemly/rgba]: Invalid color value ${t}.`)}catch(e){throw e}}function r0(t){return t>1?1:t<0?0:t}function i0(t,e,n,i){return`rgba(${Qt(t)}, ${Qt(e)}, ${Qt(n)}, ${r0(i)})`}function cu(t,e,n,i,o){return Qt((t*e*(1-i)+n*i)/o)}function PC(t,e){Array.isArray(t)||(t=Ki(t)),Array.isArray(e)||(e=Ki(e));const n=t[3],i=e[3],o=qa(n+i-n*i);return i0(cu(t[0],n,e[0],i,o),cu(t[1],n,e[1],i,o),cu(t[2],n,e[2],i,o),o)}function fs(t,e){const[n,i,o,s=1]=Array.isArray(t)?t:Ki(t),{lightness:l=1,alpha:c=1}=e;return a0([n*l,i*l,o*l,s*c])}function qa(t){const e=Math.round(Number(t)*100)/100;return e>1?1:e<0?0:e}function Qt(t){const e=Math.round(Number(t));return e>255?255:e<0?0:e}function a0(t){const[e,n,i]=t;return 3 in t?`rgba(${Qt(e)}, ${Qt(n)}, ${Qt(i)}, ${qa(t[3])})`:`rgba(${Qt(e)}, ${Qt(n)}, ${Qt(i)}, 1)`}function kC(t=8){return Math.random().toString(16).slice(2,2+t)}function o0(t,e=[],n){const i={};return e.forEach(o=>{i[o]=t[o]}),Object.assign(i,n)}function Tm(t,e=!0,n=[]){return t.forEach(i=>{if(i!==null){if(typeof i!="object"){(typeof i=="string"||typeof i=="number")&&n.push(St(String(i)));return}if(Array.isArray(i)){Tm(i,e,n);return}if(i.type===st){if(i.children===null)return;Array.isArray(i.children)&&Tm(i.children,e,n)}else i.type!==Ks&&n.push(i)}}),n}function Ga(t,...e){if(Array.isArray(t))t.forEach(n=>Ga(n,...e));else return t(...e)}function qf(t,e){console.error(`[naive/${t}]: ${e}`)}function s0(t,e){throw new Error(`[naive/${t}]: ${e}`)}function $f(t,e="default",n=void 0){const i=t[e];if(!i)return qf("getFirstSlotVNode",`slot[${e}] is empty`),null;const o=Tm(i(n));return o.length===1?o[0]:(qf("getFirstSlotVNode",`slot[${e}] should have exactly one child`),null)}function Xm(t){return t.some(e=>$i(e)?!(e.type===Ks||e.type===st&&!Xm(e.children)):!0)?t:null}function uu(t,e){const n=t&&Xm(t());return e(n||null)}function Hf(t){return!(t&&Xm(t()))}const zf=be({render(){var t,e;return(e=(t=this.$slots).default)===null||e===void 0?void 0:e.call(t)}}),l0=/^(\d|\.)+$/,Vf=/(\d|\.)+/;function du(t,{c:e=1,offset:n=0,attachPx:i=!0}={}){if(typeof t=="number"){const o=(t+n)*e;return o===0?"0":`${o}px`}else if(typeof t=="string")if(l0.test(t)){const o=(Number(t)+n)*e;return i?o===0?"0":`${o}px`:`${o}`}else{const o=Vf.exec(t);return o?t.replace(Vf,String((Number(o[0])+n)*e)):t}return t}function c0(t){let e=0;for(let n=0;n"+ci(t[e].content)+`
+`};Zn.fence=function(t,e,n,i,o){var s=t[e],l=s.info?Tve(s.info).trim():"",c="",d="",_,p,g,E,f;return l&&(g=l.split(/(\s+)/g),c=g[0],d=g.slice(2).join("")),n.highlight?_=n.highlight(s.content,c,d)||ci(s.content):_=ci(s.content),_.indexOf(""+_+`
+`):""+_+`
+`};Zn.image=function(t,e,n,i,o){var s=t[e];return s.attrs[s.attrIndex("alt")][1]=o.renderInlineAsText(s.children,n,i),o.renderToken(t,e,n)};Zn.hardbreak=function(t,e,n){return n.xhtmlOut?`