chore: import upstream snapshot with attribution
K8s Workspace Integration Tests / k8s-workspace-tests (push) Has been cancelled
Pre-commit / run (ubuntu-latest) (push) Has been cancelled
Python Unittest Coverage / test (macos-15, 3.11) (push) Has been cancelled
Python Unittest Coverage / test (ubuntu-latest, 3.11) (push) Has been cancelled
Python Unittest Coverage / test (windows-latest, 3.11) (push) Has been cancelled
Web UI / check (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:39:27 +08:00
commit c3bf08ac8d
755 changed files with 172616 additions and 0 deletions
+67
View File
@@ -0,0 +1,67 @@
name: Bug Report
description: Report a bug to help us improve AgentScope.
title: "[Bug]: "
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
**<u>AgentScope is an open-source project. To involve a broader community, we recommend asking your questions in English.</u>**
- type: checkboxes
id: prerequisites
attributes:
label: Prerequisites
description: Please confirm the following before submitting.
options:
- label: I have searched the existing [issues](https://github.com/agentscope-ai/agentscope/issues) and [discussions](https://github.com/agentscope-ai/agentscope/discussions), and this is not a duplicate.
required: true
- label: This is a bug, not a usage question. (For questions, please use [Discussions](https://github.com/agentscope-ai/agentscope/discussions/new?category=general) instead.)
required: true
- type: textarea
id: description
attributes:
label: Background / Description
description: A clear and concise description of the bug, including what you were trying to do and the expected behavior.
placeholder: What were you trying to do, what did you expect, and what actually happened?
validations:
required: true
- type: textarea
id: error
attributes:
label: Error Messages
description: Detailed error messages, stack traces, or logs.
render: shell
validations:
required: true
- type: textarea
id: reproduce
attributes:
label: Steps to Reproduce
description: Provide a minimal reproducible example (code + commands) so we can reproduce the bug.
placeholder: |
1. Code:
```python
...
```
2. Run: `python ...`
3. See error
validations:
required: true
- type: textarea
id: environment
attributes:
label: Environment
description: Run `import agentscope; print(agentscope.__version__)` to get the AgentScope version.
value: |
- AgentScope Version:
- Python Version:
- OS:
validations:
required: true
+8
View File
@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Feature Request / Idea
url: https://github.com/agentscope-ai/agentscope/discussions/new?category=ideas
about: Suggest a new feature or share an idea. Maintainers will turn accepted proposals into roadmap issues.
- name: Question / Usage Help
url: https://github.com/agentscope-ai/agentscope/discussions/new?category=general
about: Ask a usage question or start a general discussion. Please do NOT open an issue for questions.
+25
View File
@@ -0,0 +1,25 @@
## PR Title Format
Please ensure your PR title follows the Conventional Commits format:
- Format: `<type>(<scope>): <description>`
- Example: `feat(memory): add redis cache support`
- Allowed types: `feat`, `fix`, `docs`, `ci`, `refactor`, `test`, `chore`, `perf`, `style`, `build`, `revert`
- Description should start with a lowercase letter
## AgentScope Version
[The version of AgentScope you are working on, e.g. `import agentscope; print(agentscope.__version__)`]
## Description
[Please describe the background, purpose, changes made, and how to test this PR]
## Checklist
Please check the following items before code is ready to be reviewed.
- [ ] An issue has been created for this PR
- [ ] I have read the [CONTRIBUTING.md](https://github.com/agentscope-ai/agentscope/blob/main/CONTRIBUTING.md)
- [ ] Docstrings are in Google style
- [ ] Related documentation has been updated (e.g. links, examples, etc.) in [documentation repository](https://github.com/agentscope-ai/docs)
- [ ] Code is ready for review
+97
View File
@@ -0,0 +1,97 @@
# AgentScope Code Review Guide
You should conduct a strict code review. Each requirement is labeled with priority:
- **[MUST]** must be satisfied or PR will be rejected
- **[SHOULD]** strongly recommended
- **[MAY]** optional suggestion
## 1. Code Quality
### [MUST] Lazy Loading
- **Third-party library** dependencies should be imported at the point of use, avoid centralized imports at file top
- The `Third-party library` refers to libraries not included in the `dependencies` variable in `pyproject.toml`.
- For base class imports, use factory pattern:
```python
def get_xxx_cls() -> "MyClass":
from xxx import BaseClass
class MyClass(BaseClass): ...
return MyClass
```
### [SHOULD] Code Conciseness
After understanding the code intent, check if it can be optimized:
- Avoid unnecessary temporary variables
- Merge duplicate code blocks
- Prioritize reusing existing utility functions
### [MUST] Encapsulation Standards
- All Python files under `src/agentscope` should be named with `_` prefix, and exposure controlled through `__init__.py`
- Classes and functions used internally by the framework that don't need to be exposed to users must be named with `_` prefix
## 2. [MUST] Code Security
- Prohibit hardcoding API keys/tokens/passwords
- Use environment variables or configuration files for management
- Check for debug information and temporary credentials
- Check for injection attack risks (SQL/command/code injection, etc.)
## 3. [MUST] Testing & Dependencies
- New features must include unit tests
- New dependencies need to be added to the corresponding section in `pyproject.toml`
- Dependencies for non-core scenarios should not be added to the minimal dependency list
- Test assertions MUST compare the entire data structure rather than asserting individual fields, so reviewers can quickly understand the test intent. For random or non-deterministic fields, use `AnyString` and `AnyValue` from `tests/utils.py` for matching
## 4. Code Standards
### [MUST] Comment Standards
- **Use English**
- All classes/methods must have complete docstrings, strictly following the template:
```python
def func(a: str, b: int | None = None) -> str:
"""{description}
Args:
a (`str`):
The argument a
b (`int | None`, optional):
The argument b
Returns:
`str`:
The return str
"""
```
- Use reStructuredText syntax for special content:
```python
class MyClass:
"""xxx
`Example link <https://xxx>`_
.. note:: Example note
.. tip:: Example tip
.. important:: Example important info
.. code-block:: python
def hello_world():
print("Hello world!")
"""
```
### [MUST] Pre-commit Checks
- **Strict review**: In most cases, code should be modified rather than skipping checks
- **File-level check skipping is prohibited**
- Only allowed skip: agent class system prompt parameters (to avoid `\n` formatting issues)
---
## 5. Git Standards
### [MUST] PR Title
- Follow Conventional Commits
- Must use prefixes: `feat/fix/docs/ci/refactor/test`, etc.
- Format: `feat(scope): description`
- Example: `feat(memory): add redis cache support`
+152
View File
@@ -0,0 +1,152 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Script to automatically update NEWS section in README files.
Reads the first 10 news items from docs/NEWS.md and updates README.md and
README_zh.md.
"""
from pathlib import Path
def read_news_items(news_file: Path, max_items: int = 10) -> list[str]:
"""
Read news items from NEWS.md file.
Args:
news_file (`Path`):
Path to the NEWS.md file
max_items (`int`, optional):
Maximum number of items to read
Returns:
`list[str]`:
List of news items
"""
with open(news_file, "r", encoding="utf-8") as f:
content = f.read()
# Split by lines that start with "- **["
lines = content.strip().split("\n")
news_items = []
for line in lines:
if line.strip().startswith("- **["):
news_items.append(line)
if len(news_items) >= max_items:
break
return news_items
def update_readme(
readme_file: Path,
news_items: list[str],
) -> None:
"""
Update the NEWS section in README file using HTML comment markers.
Args:
readme_file (`Path`):
Path to the README file
news_items (`list[str]`):
List of news items to insert
"""
with open(readme_file, "r", encoding="utf-8") as f:
content = f.read()
# Use HTML comment markers to identify the NEWS section
begin_marker = "<!-- BEGIN NEWS -->"
end_marker = "<!-- END NEWS -->"
if begin_marker not in content or end_marker not in content:
print(f"⚠️ NEWS markers not found in {readme_file.name}")
print(
f" Please add '{begin_marker}' and '{end_marker}' to mark the "
f"NEWS section",
)
return
# Find positions of markers
begin_pos = content.find(begin_marker)
end_pos = content.find(end_marker)
if begin_pos == -1 or end_pos == -1 or begin_pos >= end_pos:
print(f"❌ Invalid NEWS markers in {readme_file.name}")
return
# Create new NEWS content
news_content = "\n".join(news_items)
# Replace content between markers
new_content = (
content[: begin_pos + len(begin_marker)]
+ "\n"
+ news_content
+ "\n"
+ content[end_pos:]
)
with open(readme_file, "w", encoding="utf-8") as f:
f.write(new_content)
print(f"✅ Updated {readme_file.name}")
def main() -> None:
"""Main function to update NEWS in README files."""
# Define paths
repo_root = Path(__file__).parent.parent.parent
news_file_en = repo_root / "docs" / "NEWS.md"
news_file_zh = repo_root / "docs" / "NEWS_zh.md"
readme_en = repo_root / "README.md"
readme_zh = repo_root / "README_zh.md"
# Update English README from NEWS.md
if news_file_en.exists():
print(f"📖 Reading news items from {news_file_en}")
news_items_en = read_news_items(news_file_en, max_items=10)
print(f"📰 Found {len(news_items_en)} English news items")
if news_items_en and readme_en.exists():
print(f"📝 Updating {readme_en.name}...")
update_readme(readme_en, news_items_en)
elif not news_items_en:
print("⚠️ No English news items found")
else:
print(f"⚠️ {readme_en} not found")
else:
print(f"❌ NEWS.md not found at {news_file_en}")
# Update Chinese README from NEWS_zh.md
if news_file_zh.exists() and news_file_zh.stat().st_size > 0:
print(f"📖 Reading news items from {news_file_zh}")
news_items_zh = read_news_items(news_file_zh, max_items=10)
print(f"📰 Found {len(news_items_zh)} Chinese news items")
if news_items_zh and readme_zh.exists():
print(f"📝 Updating {readme_zh.name}...")
update_readme(readme_zh, news_items_zh)
elif not news_items_zh:
print("⚠️ No Chinese news items found")
else:
print(f"⚠️ {readme_zh} not found")
else:
print(
f"⚠️ NEWS_zh.md not found or empty at {news_file_zh}, "
f"using English news for Chinese README",
)
# Fallback: use English news for Chinese README if NEWS_zh.md
# doesn't exist
if news_file_en.exists() and readme_zh.exists():
print(f"📖 Reading news items from {news_file_en} (fallback)")
news_items = read_news_items(news_file_en, max_items=10)
if news_items:
print(f"📝 Updating {readme_zh.name} with English news...")
update_readme(readme_zh, news_items)
print("✨ All done!")
if __name__ == "__main__":
main()
+63
View File
@@ -0,0 +1,63 @@
# ─────────────────────────────────────────────────────────────────────────────
# Template: copy this file to the MONITORED repo at
# .github/workflows/github-monitor.yml
#
# Required secrets in the monitored repo:
# - STORAGE_REPO_TOKEN Fine-grained PAT with Contents: Read & Write on
# the storage repo (e.g. DavdGao/agentscope-monitor).
# - DINGTALK_WEBHOOK Dingtalk bot webhook URL.
# - DINGTALK_SECRET (optional) Dingtalk bot signing secret.
# ─────────────────────────────────────────────────────────────────────────────
name: GitHub Monitor
on:
issues:
types: [opened, closed, reopened]
issue_comment:
types: [created]
pull_request_target:
# synchronize is silent (stored only) — see SILENT_REALTIME_EVENTS in scripts/config.py.
# It's needed for the daily "PRs with new commits to re-review" section.
types: [opened, closed, reopened, synchronize, review_requested]
pull_request_review:
types: [submitted]
pull_request_review_comment:
types: [created]
discussion:
types: [created, answered]
discussion_comment:
types: [created]
permissions:
contents: read
jobs:
notify:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout storage repo (notification scripts)
uses: actions/checkout@v4
with:
repository: DavdGao/agentscope-monitor
token: ${{ secrets.STORAGE_REPO_TOKEN }}
- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: pip
- run: pip install -r requirements.txt
- name: Send notification
env:
EVENT_NAME: ${{ github.event_name }}
EVENT_PAYLOAD: ${{ toJson(github.event) }}
REPO_NAME: ${{ github.repository }}
RUN_ID: ${{ github.run_id }}
RUN_ATTEMPT: ${{ github.run_attempt }}
STORAGE_REPO: DavdGao/agentscope-monitor
STORAGE_REPO_TOKEN: ${{ secrets.STORAGE_REPO_TOKEN }}
DINGTALK_WEBHOOK: ${{ secrets.DINGTALK_WEBHOOK }}
DINGTALK_SECRET: ${{ secrets.DINGTALK_SECRET }}
run: python -m scripts.notify
+81
View File
@@ -0,0 +1,81 @@
name: K8s Workspace Integration Tests
# Runs the K8sWorkspace integration suite against a kind cluster.
# The regular `unittest.yml` job also imports this test file, but every
# test inside is guarded by `skipUnless(_KIND_AVAILABLE, ...)`, so it is
# a no-op there. This workflow is where the tests actually execute.
on:
push:
paths:
- "src/agentscope/workspace/**"
- "tests/workspace_k8s_test.py"
- "tests/docker/k8s_workspace_test.Dockerfile"
- ".github/workflows/k8s-workspace.yml"
pull_request:
paths:
- "src/agentscope/workspace/**"
- "tests/workspace_k8s_test.py"
- "tests/docker/k8s_workspace_test.Dockerfile"
- ".github/workflows/k8s-workspace.yml"
jobs:
k8s-workspace-tests:
if: false == contains(github.event.pull_request.title, 'WIP')
# Ubuntu only: kind requires linux + docker; the test module's
# skipUnless would skip everything on Windows/macOS anyway.
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
python-version: '3.11'
- name: Create kind cluster
uses: helm/kind-action@v1
with:
cluster_name: agentscope-test
wait: 120s
- name: Build K8s workspace test image
run: |
docker build \
-f tests/docker/k8s_workspace_test.Dockerfile \
-t agentscope-k8s-test:ci .
- name: Load image into kind
run: kind load docker-image agentscope-k8s-test:ci --name agentscope-test
- name: Create test namespace
run: kubectl create namespace agentscope
- name: Install project
run: |
uv pip install -q -e .[dev]
uv pip install pytest
- name: Run K8s workspace tests
env:
K8S_TEST_IMAGE: agentscope-k8s-test:ci
K8S_TEST_NAMESPACE: agentscope
run: pytest tests/workspace_k8s_test.py -v
- name: Dump cluster diagnostics on failure
if: failure()
run: |
echo "── pods ──"
kubectl get pods -A -o wide || true
echo "── pvcs ──"
kubectl get pvc -A || true
echo "── events ──"
kubectl get events -A --sort-by=.lastTimestamp | tail -n 50 || true
echo "── describe agentscope pods ──"
for p in $(kubectl -n agentscope get pods -o name 2>/dev/null); do
echo "── $p ──"
kubectl -n agentscope describe "$p" || true
kubectl -n agentscope logs "$p" --all-containers=true --tail=200 || true
done
+49
View File
@@ -0,0 +1,49 @@
name: PR Title Check
on:
pull_request:
branches:
- main
types: [opened, edited, synchronize, reopened]
jobs:
check-pr-title:
runs-on: ubuntu-latest
steps:
- name: Check PR Title Format
uses: amannn/action-semantic-pull-request@v6.1.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
# Configure allowed types based on your requirements
types: |
feat
fix
docs
ci
refactor
test
chore
perf
style
build
revert
# Require a scope (the part in parentheses)
requireScope: false
# Scope pattern: only lowercase letters, numbers, hyphens, and underscores allowed
scopePattern: ^[a-z0-9_-]+$
scopePatternError: |
The scope (text in parentheses) must contain only lowercase letters, numbers, hyphens, and underscores.
Example: "feat(memory): add redis cache support"
Invalid: "feat(Memory): ..." or "feat(MEMORY): ..."
# Subject (description) must not be empty and must be lowercase
subjectPattern: ^(?![A-Z]).+$
subjectPatternError: |
The subject (description after colon) must start with a lowercase letter.
Example: "feat(memory): add redis cache support"
# Validate the entire PR title against the Conventional Commits spec
validateSingleCommit: false
# Ignore merge commits
ignoreLabels: |
ignore-semantic-pull-request
+35
View File
@@ -0,0 +1,35 @@
name: Pre-commit
on: [push, pull_request]
jobs:
run:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: True
matrix:
os: [ubuntu-latest]
env:
OS: ${{ matrix.os }}
PYTHON: '3.11'
steps:
- uses: actions/checkout@master
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
python-version: '3.11'
- name: Install AgentScope
run: |
uv pip install -q -e .[dev]
- name: Install pre-commit
run: |
pre-commit install
- name: Pre-commit starts
run: |
pre-commit run --all-files > pre-commit.log 2>&1 || true
cat pre-commit.log
if grep -q Failed pre-commit.log; then
echo -e "\e[41m [**FAIL**] Please install pre-commit and format your code first. \e[0m"
exit 1
fi
echo -e "\e[46m ********************************Passed******************************** \e[0m"
+43
View File
@@ -0,0 +1,43 @@
# This workflow will upload a Python Package using Twine when a release is created
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
name: Publish PyPi Package
on:
workflow_dispatch:
release:
types: [published]
permissions:
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
uv pip install build
- name: Build package
run: python -m build
- name: Test installation
run: |
uv pip install dist/*.whl
python -c "import agentscope; print(agentscope.__version__)"
- name: Publish package
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
+35
View File
@@ -0,0 +1,35 @@
# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time.
#
# You can adjust the behavior by modifying this file.
# For more information, see:
# https://github.com/actions/stale
name: Mark stale issues and pull requests
on:
schedule:
- cron: '30 9 * * *'
jobs:
stale:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v10
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is marked as stale because there has been no activity for 60 days. Remove stale label or add new comments or this issue will be closed in 90 day.'
close-issue-message: 'Close this stale issue.'
stale-issue-label: 'stale-issue'
exempt-issue-labels: 'RoadMap,Roadmap'
days-before-stale: 60
days-before-close: 30
stale-pr-message: 'This PR is marked as stale because there has been no activity for 60 days. Remove stale label or add new comments or this PR will be closed in 30 days.'
close-pr-message: 'Close this stale PR.'
stale-pr-label: 'stale-pr'
days-before-pr-stale: 60
days-before-pr-close: 30
+32
View File
@@ -0,0 +1,32 @@
name: Python Unittest Coverage
on: [push, pull_request]
jobs:
test:
if: false == contains(github.event.pull_request.title, 'WIP')
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-15]
python-version: ['3.11']
env:
OS: ${{ matrix.os }}
steps:
- uses: actions/checkout@master
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install Dev Dependencies
run: |
uv pip install -q -e .[dev]
uv pip install coverage pytest
- name: Run tests with coverage
env:
GRPC_VERBOSITY: ERROR
run: |
coverage run -m pytest tests
- name: Generate coverage report
run: |
coverage report -m
+39
View File
@@ -0,0 +1,39 @@
name: Update NEWS in README
on:
push:
paths:
- 'docs/NEWS.md'
- 'docs/NEWS_zh.md'
branches-ignore:
- 'main'
# Prevent concurrent runs that modify README files
concurrency:
group: readme-updates-${{ github.ref }}
cancel-in-progress: false
jobs:
updateNews:
name: NEWS Updater
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.10'
- name: Update NEWS in README files
run: python .github/scripts/update_news.py
- name: Commit changes
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add README.md README_zh.md
git diff --staged --quiet || git commit -m "docs: auto-sync NEWS section to README files"
git push
+46
View File
@@ -0,0 +1,46 @@
name: Web UI
on:
push:
branches:
- main
paths:
- ".github/workflows/web-ui.yml"
- "examples/web_ui/**"
pull_request:
branches:
- main
paths:
- ".github/workflows/web-ui.yml"
- "examples/web_ui/**"
jobs:
check:
if: github.event_name != 'pull_request' || false == contains(github.event.pull_request.title, 'WIP')
runs-on: ubuntu-latest
defaults:
run:
working-directory: examples/web_ui
steps:
- uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
cache-dependency-path: examples/web_ui/pnpm-lock.yaml
- name: Install dependencies
run: pnpm install --no-frozen-lockfile
- name: Check formatting
run: pnpm format:check
- name: Build
run: pnpm build