mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-28 23:11:37 +08:00
Compare commits
1 Commits
opencode-p
...
feat/devex
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2934036fe |
18
.editorconfig
Normal file
18
.editorconfig
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.{yml,yaml,json,toml}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[Makefile]
|
||||||
|
indent_style = tab
|
||||||
37
.github/workflows/tests.yml
vendored
37
.github/workflows/tests.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: Tests
|
name: CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@@ -6,37 +6,38 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
|
|
||||||
# Cancel in-progress runs for the same PR/branch
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: tests-${{ github.ref }}
|
group: ci-${{ github.ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 3
|
||||||
|
continue-on-error: true
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: astral-sh/setup-uv@v5
|
||||||
|
- run: uvx ruff check run_agent.py model_tools.py toolsets.py cli.py hermes_state.py batch_runner.py tools/ hermes_cli/ gateway/ agent/ cron/
|
||||||
|
- run: uvx ruff format --check run_agent.py model_tools.py toolsets.py cli.py hermes_state.py batch_runner.py tools/ hermes_cli/ gateway/ agent/ cron/
|
||||||
|
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- uses: actions/checkout@v4
|
||||||
uses: actions/checkout@v4
|
- uses: astral-sh/setup-uv@v5
|
||||||
|
with:
|
||||||
- name: Install uv
|
enable-cache: true
|
||||||
uses: astral-sh/setup-uv@v5
|
- run: uv python install 3.11
|
||||||
|
- run: |
|
||||||
- name: Set up Python 3.11
|
|
||||||
run: uv python install 3.11
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
uv venv .venv --python 3.11
|
uv venv .venv --python 3.11
|
||||||
source .venv/bin/activate
|
source .venv/bin/activate
|
||||||
uv pip install -e ".[all,dev]"
|
uv pip install -e ".[all,dev]"
|
||||||
|
- run: |
|
||||||
- name: Run tests
|
|
||||||
run: |
|
|
||||||
source .venv/bin/activate
|
source .venv/bin/activate
|
||||||
python -m pytest tests/ -q --ignore=tests/integration --tb=short -n auto
|
python -m pytest tests/ -q --ignore=tests/integration --tb=short -n auto
|
||||||
env:
|
env:
|
||||||
# Ensure tests don't accidentally call real APIs
|
|
||||||
OPENROUTER_API_KEY: ""
|
OPENROUTER_API_KEY: ""
|
||||||
OPENAI_API_KEY: ""
|
OPENAI_API_KEY: ""
|
||||||
NOUS_API_KEY: ""
|
NOUS_API_KEY: ""
|
||||||
|
|||||||
18
.pre-commit-config.yaml
Normal file
18
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
repos:
|
||||||
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
|
rev: v0.11.12
|
||||||
|
hooks:
|
||||||
|
- id: ruff
|
||||||
|
args: [--fix]
|
||||||
|
- id: ruff-format
|
||||||
|
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v5.0.0
|
||||||
|
hooks:
|
||||||
|
- id: trailing-whitespace
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: check-merge-conflict
|
||||||
|
- id: check-yaml
|
||||||
|
args: [--allow-multiple-documents]
|
||||||
|
- id: check-added-large-files
|
||||||
|
args: [--maxkb=500]
|
||||||
69
Makefile
Normal file
69
Makefile
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
.DEFAULT_GOAL := help
|
||||||
|
SHELL := /bin/bash
|
||||||
|
VENV := .venv
|
||||||
|
UV := uv
|
||||||
|
|
||||||
|
SRC := run_agent.py model_tools.py toolsets.py cli.py hermes_state.py batch_runner.py \
|
||||||
|
tools/ hermes_cli/ gateway/ agent/ cron/
|
||||||
|
|
||||||
|
# ─── Setup ──────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
.PHONY: setup sync clean
|
||||||
|
|
||||||
|
setup: ## Full dev setup (venv + deps + pre-commit)
|
||||||
|
$(UV) venv $(VENV) --python 3.11
|
||||||
|
. $(VENV)/bin/activate && $(UV) pip install -e ".[all,dev]"
|
||||||
|
. $(VENV)/bin/activate && $(UV) pip install -e "./mini-swe-agent"
|
||||||
|
. $(VENV)/bin/activate && pre-commit install
|
||||||
|
@echo "\n✅ Setup complete. Run: source $(VENV)/bin/activate"
|
||||||
|
|
||||||
|
sync: ## Reinstall deps into existing venv
|
||||||
|
. $(VENV)/bin/activate && $(UV) pip install -e ".[all,dev]"
|
||||||
|
|
||||||
|
clean: ## Remove build artifacts and caches
|
||||||
|
rm -rf .ruff_cache .mypy_cache .pytest_cache dist build *.egg-info
|
||||||
|
find . -type d -name __pycache__ -not -path "./.venv/*" -exec rm -rf {} +
|
||||||
|
|
||||||
|
# ─── Quality ────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
.PHONY: lint fmt check
|
||||||
|
|
||||||
|
lint: ## Check lint + formatting (no changes)
|
||||||
|
. $(VENV)/bin/activate && ruff check $(SRC)
|
||||||
|
. $(VENV)/bin/activate && ruff format --check $(SRC)
|
||||||
|
|
||||||
|
fmt: ## Auto-fix lint + format
|
||||||
|
. $(VENV)/bin/activate && ruff format $(SRC)
|
||||||
|
. $(VENV)/bin/activate && ruff check --fix $(SRC)
|
||||||
|
|
||||||
|
check: lint test ## Lint + test (mirrors CI)
|
||||||
|
|
||||||
|
# ─── Test ───────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
.PHONY: test test-fast test-watch
|
||||||
|
|
||||||
|
test: ## Run full test suite
|
||||||
|
. $(VENV)/bin/activate && python -m pytest tests/ -q --ignore=tests/integration --tb=short
|
||||||
|
|
||||||
|
test-fast: ## Run tests with fail-fast
|
||||||
|
. $(VENV)/bin/activate && python -m pytest tests/ -q --ignore=tests/integration --tb=short -x
|
||||||
|
|
||||||
|
test-watch: ## Rerun tests on file changes
|
||||||
|
. $(VENV)/bin/activate && python -m watchfiles "python -m pytest tests/ -q --ignore=tests/integration --tb=short -x" $(SRC) tests/
|
||||||
|
|
||||||
|
# ─── Dev Servers ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
.PHONY: dev-cli dev-gateway
|
||||||
|
|
||||||
|
dev-cli: ## Auto-restart CLI on file changes
|
||||||
|
. $(VENV)/bin/activate && python -m watchfiles "python -m hermes_cli.main" $(SRC)
|
||||||
|
|
||||||
|
dev-gateway: ## Auto-restart gateway on file changes
|
||||||
|
. $(VENV)/bin/activate && python -m watchfiles "python -m gateway.run" $(SRC)
|
||||||
|
|
||||||
|
# ─── Misc ───────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
.PHONY: help
|
||||||
|
|
||||||
|
help: ## Show this help
|
||||||
|
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}'
|
||||||
@@ -40,7 +40,7 @@ dependencies = [
|
|||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
modal = ["swe-rex[modal]>=1.4.0"]
|
modal = ["swe-rex[modal]>=1.4.0"]
|
||||||
daytona = ["daytona>=0.148.0"]
|
daytona = ["daytona>=0.148.0"]
|
||||||
dev = ["pytest", "pytest-asyncio", "pytest-xdist", "mcp>=1.2.0"]
|
dev = ["pytest", "pytest-asyncio", "pytest-xdist", "mcp>=1.2.0", "ruff", "pre-commit", "watchfiles"]
|
||||||
messaging = ["python-telegram-bot>=20.0", "discord.py>=2.0", "aiohttp>=3.9.0", "slack-bolt>=1.18.0", "slack-sdk>=3.27.0"]
|
messaging = ["python-telegram-bot>=20.0", "discord.py>=2.0", "aiohttp>=3.9.0", "slack-bolt>=1.18.0", "slack-sdk>=3.27.0"]
|
||||||
cron = ["croniter"]
|
cron = ["croniter"]
|
||||||
slack = ["slack-bolt>=1.18.0", "slack-sdk>=3.27.0"]
|
slack = ["slack-bolt>=1.18.0", "slack-sdk>=3.27.0"]
|
||||||
@@ -79,6 +79,38 @@ py-modules = ["run_agent", "model_tools", "toolsets", "batch_runner", "trajector
|
|||||||
[tool.setuptools.packages.find]
|
[tool.setuptools.packages.find]
|
||||||
include = ["tools", "hermes_cli", "gateway", "cron", "honcho_integration"]
|
include = ["tools", "hermes_cli", "gateway", "cron", "honcho_integration"]
|
||||||
|
|
||||||
|
[tool.ruff]
|
||||||
|
target-version = "py311"
|
||||||
|
line-length = 120
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
select = ["E", "F", "W", "I", "UP", "B", "SIM"]
|
||||||
|
ignore = [
|
||||||
|
"E402", # late imports — intentional throughout codebase
|
||||||
|
"E501", # line too long — handled by formatter where it can
|
||||||
|
"E731", # lambda assignments — used in registry pattern
|
||||||
|
"E741", # ambiguous variable name
|
||||||
|
"F811", # redefined unused — intentional overrides
|
||||||
|
"F841", # unused variable
|
||||||
|
"B007", # unused loop variable
|
||||||
|
"B904", # raise from
|
||||||
|
"B905", # zip strict
|
||||||
|
"B027", # empty method without abstract decorator
|
||||||
|
"SIM102", # collapsible if
|
||||||
|
"SIM103", # needless bool
|
||||||
|
"SIM105", # suppressible exception
|
||||||
|
"SIM108", # ternary
|
||||||
|
"SIM110", # reimplemented builtin
|
||||||
|
"SIM112", # uncapitalized env var
|
||||||
|
"SIM115", # open file with context handler
|
||||||
|
"SIM117", # multiple with statements
|
||||||
|
"SIM118", # in-dict-keys
|
||||||
|
"SIM212", # if-expr twisted arms
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.ruff.lint.isort]
|
||||||
|
known-first-party = ["tools", "hermes_cli", "gateway", "agent", "cron"]
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
testpaths = ["tests"]
|
testpaths = ["tests"]
|
||||||
markers = [
|
markers = [
|
||||||
|
|||||||
Reference in New Issue
Block a user