smythe 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- smythe-0.2.0/.github/ISSUE_TEMPLATE/bug_report.md +45 -0
- smythe-0.2.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
- smythe-0.2.0/.github/ISSUE_TEMPLATE/feature_request.md +36 -0
- smythe-0.2.0/.github/ISSUE_TEMPLATE/release-checklist.md +34 -0
- smythe-0.2.0/.github/PULL_REQUEST_TEMPLATE.md +45 -0
- smythe-0.2.0/.github/workflows/ci.yml +49 -0
- smythe-0.2.0/.github/workflows/publish.yml +44 -0
- smythe-0.2.0/.gitignore +31 -0
- smythe-0.2.0/CHANGELOG.md +198 -0
- smythe-0.2.0/CODE_OF_CONDUCT.md +135 -0
- smythe-0.2.0/CONTRIBUTING.md +93 -0
- smythe-0.2.0/LICENSE +21 -0
- smythe-0.2.0/PKG-INFO +529 -0
- smythe-0.2.0/RELEASING.md +46 -0
- smythe-0.2.0/ROADMAP.md +42 -0
- smythe-0.2.0/Readme.md +483 -0
- smythe-0.2.0/SECURITY.md +72 -0
- smythe-0.2.0/docs/checkpoint-format.md +79 -0
- smythe-0.2.0/docs/mcp.md +69 -0
- smythe-0.2.0/examples/01_pipeline.yaml +29 -0
- smythe-0.2.0/examples/01_quickstart_yaml.py +25 -0
- smythe-0.2.0/examples/02_dynamic_planning.py +35 -0
- smythe-0.2.0/examples/03_parallel_budget.py +44 -0
- smythe-0.2.0/examples/04_resume_after_crash.py +72 -0
- smythe-0.2.0/examples/05_mcp_filesystem.py +107 -0
- smythe-0.2.0/examples/06_mcp_github.py +78 -0
- smythe-0.2.0/examples/07_mcp_saas.py +78 -0
- smythe-0.2.0/examples/README.md +18 -0
- smythe-0.2.0/examples/_providers.py +88 -0
- smythe-0.2.0/examples/mcp_file_server.py +37 -0
- smythe-0.2.0/plans/01-bug-fixes.md +271 -0
- smythe-0.2.0/plans/02-everything-else.md +357 -0
- smythe-0.2.0/plans/03-openclaw-agentskills-prd.md +279 -0
- smythe-0.2.0/plans/04-mcp-tool-support.md +241 -0
- smythe-0.2.0/pyproject.toml +66 -0
- smythe-0.2.0/smythe/__init__.py +83 -0
- smythe-0.2.0/smythe/agent.py +47 -0
- smythe-0.2.0/smythe/async_executor.py +148 -0
- smythe-0.2.0/smythe/budget.py +115 -0
- smythe-0.2.0/smythe/checkpoint.py +267 -0
- smythe-0.2.0/smythe/constrained_planner.py +189 -0
- smythe-0.2.0/smythe/constrained_prompts.py +63 -0
- smythe-0.2.0/smythe/executor.py +98 -0
- smythe-0.2.0/smythe/executor_base.py +163 -0
- smythe-0.2.0/smythe/graph.py +329 -0
- smythe-0.2.0/smythe/loader.py +171 -0
- smythe-0.2.0/smythe/mcp.py +338 -0
- smythe-0.2.0/smythe/memory.py +144 -0
- smythe-0.2.0/smythe/openclaw_adapter.py +61 -0
- smythe-0.2.0/smythe/planner.py +171 -0
- smythe-0.2.0/smythe/prompts.py +167 -0
- smythe-0.2.0/smythe/provider.py +496 -0
- smythe-0.2.0/smythe/registry.py +164 -0
- smythe-0.2.0/smythe/router.py +101 -0
- smythe-0.2.0/smythe/skills.py +70 -0
- smythe-0.2.0/smythe/swarm.py +490 -0
- smythe-0.2.0/smythe/synthesizer.py +187 -0
- smythe-0.2.0/smythe/task.py +25 -0
- smythe-0.2.0/smythe/tools.py +166 -0
- smythe-0.2.0/smythe/tracer.py +105 -0
- smythe-0.2.0/tests/__init__.py +0 -0
- smythe-0.2.0/tests/helpers.py +114 -0
- smythe-0.2.0/tests/mcp_test_server.py +35 -0
- smythe-0.2.0/tests/test_agent.py +83 -0
- smythe-0.2.0/tests/test_async_executor.py +359 -0
- smythe-0.2.0/tests/test_budget.py +193 -0
- smythe-0.2.0/tests/test_checkpoint.py +277 -0
- smythe-0.2.0/tests/test_constrained_planner.py +212 -0
- smythe-0.2.0/tests/test_examples_smoke.py +51 -0
- smythe-0.2.0/tests/test_executor.py +160 -0
- smythe-0.2.0/tests/test_executor_base.py +62 -0
- smythe-0.2.0/tests/test_graph.py +203 -0
- smythe-0.2.0/tests/test_graph_export.py +65 -0
- smythe-0.2.0/tests/test_integration.py +133 -0
- smythe-0.2.0/tests/test_llm_planner.py +334 -0
- smythe-0.2.0/tests/test_loader.py +321 -0
- smythe-0.2.0/tests/test_mcp.py +342 -0
- smythe-0.2.0/tests/test_memory.py +154 -0
- smythe-0.2.0/tests/test_offline_provider.py +51 -0
- smythe-0.2.0/tests/test_openclaw_adapter.py +89 -0
- smythe-0.2.0/tests/test_planner.py +67 -0
- smythe-0.2.0/tests/test_planner_inventory.py +120 -0
- smythe-0.2.0/tests/test_provider.py +505 -0
- smythe-0.2.0/tests/test_registry.py +130 -0
- smythe-0.2.0/tests/test_router.py +127 -0
- smythe-0.2.0/tests/test_skills.py +80 -0
- smythe-0.2.0/tests/test_skills_registry.py +219 -0
- smythe-0.2.0/tests/test_swarm.py +308 -0
- smythe-0.2.0/tests/test_synthesizer.py +214 -0
- smythe-0.2.0/tests/test_task.py +35 -0
- smythe-0.2.0/tests/test_tool_loop.py +249 -0
- smythe-0.2.0/tests/test_tools.py +111 -0
- smythe-0.2.0/tests/test_tracer.py +118 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Report incorrect or unexpected behavior
|
|
4
|
+
title: "[bug] "
|
|
5
|
+
labels: bug
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
A clear, one-paragraph description of the bug.
|
|
12
|
+
|
|
13
|
+
## Reproduction
|
|
14
|
+
|
|
15
|
+
Minimal code that reproduces the issue. A failing test against the smythe
|
|
16
|
+
test suite is ideal.
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
# Smallest possible repro
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Expected behavior
|
|
23
|
+
|
|
24
|
+
What you expected to happen.
|
|
25
|
+
|
|
26
|
+
## Actual behavior
|
|
27
|
+
|
|
28
|
+
What actually happened. Include the full traceback if there is one.
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
# Paste traceback here
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Environment
|
|
35
|
+
|
|
36
|
+
- smythe version (or commit SHA if installed from source):
|
|
37
|
+
- Python version (`python --version`):
|
|
38
|
+
- OS:
|
|
39
|
+
- Provider extras installed (anthropic / openai / gemini / openclaw / none):
|
|
40
|
+
- Model name (e.g. `claude-mythos`, `gpt-4o`, `gemini-3-pro`):
|
|
41
|
+
|
|
42
|
+
## Additional context
|
|
43
|
+
|
|
44
|
+
Anything else that might help — relevant logs, configuration snippets,
|
|
45
|
+
related issues, hypotheses.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
about: Propose a new capability or enhancement
|
|
4
|
+
title: "[feature] "
|
|
5
|
+
labels: enhancement
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Problem
|
|
10
|
+
|
|
11
|
+
What problem are you trying to solve? What use case is currently awkward
|
|
12
|
+
or impossible?
|
|
13
|
+
|
|
14
|
+
## Proposed solution
|
|
15
|
+
|
|
16
|
+
What you'd like to see. Sketch the API or behavior if you have one in mind.
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
# Optional: sketch of the proposed API
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Alternatives considered
|
|
23
|
+
|
|
24
|
+
Other approaches you thought about, and why this one is preferred.
|
|
25
|
+
|
|
26
|
+
## Scope and breaking changes
|
|
27
|
+
|
|
28
|
+
- Does this change the public API? If so, how?
|
|
29
|
+
- Are there backward-compatible incremental steps?
|
|
30
|
+
- Roughly how big is this — a single function, a new module, or a multi-sprint
|
|
31
|
+
initiative?
|
|
32
|
+
|
|
33
|
+
## Additional context
|
|
34
|
+
|
|
35
|
+
Links to relevant issues, prior art in other frameworks (LangGraph, CrewAI,
|
|
36
|
+
AutoGen, etc.), or specs.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Release checklist
|
|
3
|
+
about: Steps for cutting a release to PyPI
|
|
4
|
+
title: "Release vX.Y.Z"
|
|
5
|
+
labels: roadmap
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Release Checklist
|
|
9
|
+
|
|
10
|
+
## Preflight
|
|
11
|
+
|
|
12
|
+
- [ ] `pyproject.toml` version has been bumped (PyPI never allows re-uploading a version).
|
|
13
|
+
- [ ] `smythe/__init__.py` `__version__` matches.
|
|
14
|
+
- [ ] `CHANGELOG.md` has a section for this version.
|
|
15
|
+
- [ ] README install instructions mention `pip install smythe`.
|
|
16
|
+
- [ ] Tests pass locally.
|
|
17
|
+
- [ ] Build passes locally with `python -m build`.
|
|
18
|
+
- [ ] Package validates with `python -m twine check dist/*`.
|
|
19
|
+
- [ ] Built wheel installs and imports in a fresh venv.
|
|
20
|
+
|
|
21
|
+
## GitHub
|
|
22
|
+
|
|
23
|
+
- [ ] `.github/workflows/publish.yml` exists on the default branch.
|
|
24
|
+
- [ ] GitHub environment `pypi` exists (Settings → Environments).
|
|
25
|
+
- [ ] Release notes are drafted.
|
|
26
|
+
- [ ] Git tag matches the package version, e.g. `v0.2.0`.
|
|
27
|
+
|
|
28
|
+
## PyPI
|
|
29
|
+
|
|
30
|
+
- [ ] Pending/trusted publisher exists for `petehottelet/smythe`.
|
|
31
|
+
- [ ] Publisher workflow is `publish.yml`.
|
|
32
|
+
- [ ] Publisher environment is `pypi`.
|
|
33
|
+
- [ ] Release workflow publishes successfully.
|
|
34
|
+
- [ ] `pip install smythe` works from a clean venv after release.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<!-- Thanks for contributing to smythe! Please fill out the sections below. -->
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
What does this PR change, and why? One or two sentences focused on the "why"
|
|
6
|
+
rather than the "what".
|
|
7
|
+
|
|
8
|
+
## Linked issue
|
|
9
|
+
|
|
10
|
+
Closes #<issue-number> <!-- or "Refs #..." if not closing -->
|
|
11
|
+
|
|
12
|
+
## Type of change
|
|
13
|
+
|
|
14
|
+
- [ ] Bug fix (non-breaking)
|
|
15
|
+
- [ ] New feature (non-breaking)
|
|
16
|
+
- [ ] Breaking change (API or behavior change — call out the migration path)
|
|
17
|
+
- [ ] Documentation only
|
|
18
|
+
- [ ] Test / CI / tooling only
|
|
19
|
+
|
|
20
|
+
## Testing
|
|
21
|
+
|
|
22
|
+
How did you verify this change?
|
|
23
|
+
|
|
24
|
+
- [ ] Added new tests covering this change
|
|
25
|
+
- [ ] Existing tests cover this change
|
|
26
|
+
- [ ] Manually exercised — describe how:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
# Paste relevant test output, or describe the manual run
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Checklist
|
|
33
|
+
|
|
34
|
+
- [ ] `ruff check smythe/ tests/` passes locally
|
|
35
|
+
- [ ] `pytest tests/` passes locally on at least one supported Python version
|
|
36
|
+
- [ ] [CHANGELOG.md](../CHANGELOG.md) updated under `[Unreleased]` for any
|
|
37
|
+
user-facing change
|
|
38
|
+
- [ ] Public API additions/changes are documented in docstrings and
|
|
39
|
+
[Readme.md](../Readme.md) where appropriate
|
|
40
|
+
- [ ] No "created with X" attribution in commit messages
|
|
41
|
+
- [ ] No emojis in code or commit messages (unless explicitly requested)
|
|
42
|
+
|
|
43
|
+
## Breaking changes
|
|
44
|
+
|
|
45
|
+
If this is a breaking change, describe the migration path users should follow.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
lint:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- uses: actions/setup-python@v5
|
|
15
|
+
with:
|
|
16
|
+
python-version: "3.11"
|
|
17
|
+
- run: pip install ruff
|
|
18
|
+
- run: ruff check smythe/ tests/
|
|
19
|
+
|
|
20
|
+
test:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
strategy:
|
|
23
|
+
matrix:
|
|
24
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
25
|
+
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v4
|
|
28
|
+
|
|
29
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
30
|
+
uses: actions/setup-python@v5
|
|
31
|
+
with:
|
|
32
|
+
python-version: ${{ matrix.python-version }}
|
|
33
|
+
|
|
34
|
+
- name: Install dependencies
|
|
35
|
+
run: |
|
|
36
|
+
python -m pip install --upgrade pip
|
|
37
|
+
pip install -e .
|
|
38
|
+
pip install pytest pytest-asyncio pytest-cov
|
|
39
|
+
|
|
40
|
+
- name: Run tests
|
|
41
|
+
run: python -m pytest tests/ -v --cov=smythe --cov-report=term --cov-report=xml
|
|
42
|
+
|
|
43
|
+
- name: Upload coverage report (artifact)
|
|
44
|
+
if: matrix.python-version == '3.11'
|
|
45
|
+
uses: actions/upload-artifact@v4
|
|
46
|
+
with:
|
|
47
|
+
name: coverage-xml
|
|
48
|
+
path: coverage.xml
|
|
49
|
+
if-no-files-found: warn
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# Trusted publishing: PyPI's pending publisher is configured to trust
|
|
4
|
+
# exactly this workflow filename (publish.yml) and the `pypi` GitHub
|
|
5
|
+
# environment. No API token — GitHub OIDC via id-token: write.
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
release:
|
|
9
|
+
types: [published]
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
publish:
|
|
17
|
+
name: Build and publish to PyPI
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
environment: pypi
|
|
20
|
+
|
|
21
|
+
permissions:
|
|
22
|
+
id-token: write
|
|
23
|
+
contents: read
|
|
24
|
+
|
|
25
|
+
steps:
|
|
26
|
+
- name: Check out repository
|
|
27
|
+
uses: actions/checkout@v4
|
|
28
|
+
|
|
29
|
+
- name: Set up Python
|
|
30
|
+
uses: actions/setup-python@v5
|
|
31
|
+
with:
|
|
32
|
+
python-version: "3.11"
|
|
33
|
+
|
|
34
|
+
- name: Install build tools
|
|
35
|
+
run: python -m pip install --upgrade pip build twine
|
|
36
|
+
|
|
37
|
+
- name: Build package
|
|
38
|
+
run: python -m build
|
|
39
|
+
|
|
40
|
+
- name: Check package
|
|
41
|
+
run: python -m twine check dist/*
|
|
42
|
+
|
|
43
|
+
- name: Publish package to PyPI
|
|
44
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
smythe-0.2.0/.gitignore
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*$py.class
|
|
4
|
+
*.so
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
*.egg-info/
|
|
8
|
+
*.egg
|
|
9
|
+
.eggs/
|
|
10
|
+
*.whl
|
|
11
|
+
.venv/
|
|
12
|
+
venv/
|
|
13
|
+
env/
|
|
14
|
+
.env
|
|
15
|
+
*.log
|
|
16
|
+
.mypy_cache/
|
|
17
|
+
.pytest_cache/
|
|
18
|
+
.ruff_cache/
|
|
19
|
+
.tox/
|
|
20
|
+
.coverage
|
|
21
|
+
htmlcov/
|
|
22
|
+
.idea/
|
|
23
|
+
.vscode/
|
|
24
|
+
*.swp
|
|
25
|
+
*.swo
|
|
26
|
+
*~
|
|
27
|
+
.DS_Store
|
|
28
|
+
Thumbs.db
|
|
29
|
+
|
|
30
|
+
# Local working notes (TODOs, project instructions, scratch)
|
|
31
|
+
00_project_files/
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to **smythe** are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
|
|
7
|
+
with the pre-1.0 stability note below.
|
|
8
|
+
|
|
9
|
+
## Versioning policy (pre-1.0)
|
|
10
|
+
|
|
11
|
+
While the project is on a `0.x` line, the public API is **not yet stable**:
|
|
12
|
+
|
|
13
|
+
- `0.x` minor bumps (e.g. `0.1.0` -> `0.2.0`) MAY include backward-incompatible changes.
|
|
14
|
+
Each minor release will document its breaking changes in this file.
|
|
15
|
+
- `0.x.y` patch bumps (e.g. `0.1.0` -> `0.1.1`) are **non-breaking** and contain only
|
|
16
|
+
bug fixes, documentation, or internal improvements.
|
|
17
|
+
- The first stable release will be `1.0.0`. Until then, pin to a specific minor
|
|
18
|
+
version (`smythe~=0.1.0`) if API stability matters to you.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## [Unreleased]
|
|
23
|
+
|
|
24
|
+
Future work tracked in [ROADMAP.md](ROADMAP.md).
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## [0.2.0] - 2026-07-05
|
|
29
|
+
|
|
30
|
+
First PyPI release. The v0.2 line makes agents real: they use tools, survive
|
|
31
|
+
crashes, and everything they do is visible.
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
|
|
35
|
+
- **Provider tool contract** — neutral tool-calling types (`ToolSpec`, `ToolCall`,
|
|
36
|
+
`ToolResult`, `ChatMessage`) and `Provider.chat()`, mapped to native tool use on
|
|
37
|
+
Anthropic, OpenAI, and Gemini. First milestone of MCP tool support
|
|
38
|
+
(plans/04-mcp-tool-support.md).
|
|
39
|
+
- **MCP tool support** — agents consume MCP servers as tool sources
|
|
40
|
+
(`pip install smythe[mcp]`): `MCPServerSpec` (stdio + streamable HTTP) with
|
|
41
|
+
`env_passthrough` secret handling (variable names in config, values resolved
|
|
42
|
+
from the environment — never serialized), per-server `allowed_tools` with a
|
|
43
|
+
large-toolset warning, per-call timeouts, and cancellation-safe teardown.
|
|
44
|
+
`MCPSkillProvider` grounds capability-based assignment in real tools, and the
|
|
45
|
+
`LLMArchitect` planning prompt now includes an available-agents/tools
|
|
46
|
+
inventory so plans exploit the toolset. Examples: offline filesystem
|
|
47
|
+
(bundled server), GitHub (allowlisted), and generic SaaS over HTTP.
|
|
48
|
+
Docs and threat model: docs/mcp.md.
|
|
49
|
+
- **Tool-calling loop** — nodes whose Swarm has a `tool_runtime` run a bounded
|
|
50
|
+
tool loop: `max_tool_iterations` circuit breaker (per node and per Swarm),
|
|
51
|
+
mid-loop budget enforcement, per-call trace entries, tool failures fed back to
|
|
52
|
+
the model as error results, and `timeout_s` covering the whole loop. Budget
|
|
53
|
+
recording moved into the loop via the new accumulating `Sentinel.add_cost()`;
|
|
54
|
+
`node.metadata["cost_usd"]` is now cumulative across a node's provider calls.
|
|
55
|
+
`ToolRuntime` / `ToolSession` define the interface the MCP runtime implements
|
|
56
|
+
next (plans/04 M2).
|
|
57
|
+
- **Graph export** — `ExecutionGraph.to_mermaid()` (with node-status styling),
|
|
58
|
+
`to_dot()`, and `to_json()` (with per-node cost).
|
|
59
|
+
- **`OfflineProvider`** — deterministic, no-network provider; every example runs
|
|
60
|
+
offline and CI smoke-tests them with API keys stripped.
|
|
61
|
+
- **OpenAI-compatible `base_url`** on `OpenAIProvider` (env: `OPENAI_BASE_URL`) for
|
|
62
|
+
Ollama, LM Studio, vLLM, and other compatible endpoints.
|
|
63
|
+
- **Release workflow** — tag-triggered PyPI publishing via trusted publishing, plus
|
|
64
|
+
README badges and a public [ROADMAP.md](ROADMAP.md).
|
|
65
|
+
|
|
66
|
+
- **Durable, resumable execution** — `Swarm(checkpoint_store=...)` persists the full
|
|
67
|
+
execution state (graph, node results, agents, budget consumed) after every node.
|
|
68
|
+
`swarm.resume(execution_id)` picks up from the last completed node; finished nodes
|
|
69
|
+
are never re-executed and cost accounting continues against the original cap.
|
|
70
|
+
Ships with `FileCheckpointStore` (one JSON file per execution, atomic writes) and a
|
|
71
|
+
`CheckpointStore` ABC for custom backends. Format documented in
|
|
72
|
+
docs/checkpoint-format.md; demonstrated in examples/04_resume_after_crash.py.
|
|
73
|
+
|
|
74
|
+
- **Per-node timeouts** — `Node.timeout_s` (also settable in YAML) caps the wall-clock
|
|
75
|
+
time of a single execution attempt in both executors; timeouts are handled by the
|
|
76
|
+
node's failure policy like any other error.
|
|
77
|
+
- **Concurrency cap** — `AsyncExecutor(max_concurrency=...)` bounds in-flight provider
|
|
78
|
+
calls; exposed as `Swarm(max_concurrency=...)` with a default of 8.
|
|
79
|
+
- **`examples/` directory** — three runnable scripts (YAML quickstart, dynamic LLM
|
|
80
|
+
planning, budget-capped parallel run) that work offline via a built-in demo provider.
|
|
81
|
+
|
|
82
|
+
### Changed
|
|
83
|
+
|
|
84
|
+
- README aligned with shipped behavior: recursive subgraph decomposition, approval
|
|
85
|
+
gates, and performance-history routing are now explicitly labeled roadmap items.
|
|
86
|
+
- Executor and AsyncExecutor share a single provider-call path
|
|
87
|
+
(`ExecutorBase.acall_node`), removing duplicated prompt-building logic.
|
|
88
|
+
|
|
89
|
+
### Fixed
|
|
90
|
+
|
|
91
|
+
- Deflaked `test_registry_cache_expires_after_ttl` (deterministic clock instead of
|
|
92
|
+
`time.sleep`).
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## [0.1.0] - 2026-03-28
|
|
97
|
+
|
|
98
|
+
Initial public release.
|
|
99
|
+
|
|
100
|
+
### Added — Core runtime
|
|
101
|
+
|
|
102
|
+
- **Task -> Architect -> Graph -> Executor -> Synthesizer pipeline.** The full
|
|
103
|
+
orchestration loop from a `Task` through plan generation, parallel or serial
|
|
104
|
+
execution, and output synthesis.
|
|
105
|
+
- **`ExecutionGraph` DAG model** with first-class topology
|
|
106
|
+
(`SERIAL`, `FORK_JOIN`, `BROADCAST_REDUCE`), per-node status (`PENDING`,
|
|
107
|
+
`RUNNING`, `COMPLETED`, `FAILED`, `SKIPPED`), failure policies
|
|
108
|
+
(`HALT`, `SKIP`, `RETRY`), and dependency edges with cycle, duplicate-ID,
|
|
109
|
+
and unknown-dependency validation.
|
|
110
|
+
- **Three-tier architect routing via `WhiteRabbit`** — deterministic
|
|
111
|
+
(template-based), constrained (LLM with strict topology vocabulary), and
|
|
112
|
+
autonomous (`LLMArchitect`, full freedom). Routes by classifier prompt or
|
|
113
|
+
explicit override.
|
|
114
|
+
- **`Architect` implementations** — `SimpleArchitect` (single-node fallback),
|
|
115
|
+
`DeterministicArchitect` (template-based), `ConstrainedArchitect`
|
|
116
|
+
(LLM with restricted topology vocabulary), `LLMArchitect` (autonomous,
|
|
117
|
+
with JSON-mode planning and context-preserving retries on malformed output).
|
|
118
|
+
- **`AsyncExecutor`** — concurrent DAG execution with topological wave
|
|
119
|
+
scheduling, deadlock detection, and partial-reservation rollback on
|
|
120
|
+
budget exhaustion mid-wave.
|
|
121
|
+
- **`Executor`** — serial DAG execution with the same failure-policy
|
|
122
|
+
semantics as the async executor.
|
|
123
|
+
- **`Sentinel` budget guardrails** — reservation/record/release protocol
|
|
124
|
+
for safe concurrent cost tracking, with hard USD caps and per-node
|
|
125
|
+
cost attribution.
|
|
126
|
+
- **`Synthesizer`** with three strategies: `CONCATENATE` (zero-cost join),
|
|
127
|
+
`STRUCTURED` (JSON shallow-merge), and `LLM_MERGE` (provider-backed
|
|
128
|
+
intelligent synthesis with optional budget and tracer integration).
|
|
129
|
+
- **`Tracer`** — structured per-node spans with start/end/error hooks
|
|
130
|
+
and a JSON-serializable summary for downstream observability.
|
|
131
|
+
- **`Registry` and `Agent`/`AgentProfile`** — persistent agent identities
|
|
132
|
+
with capabilities, persona, and append-only execution history.
|
|
133
|
+
- **`PlannerMemory`** — JSONL-backed outcome store for the architect
|
|
134
|
+
feedback loop (recall surface implemented; closing the loop into
|
|
135
|
+
prompt context is on the roadmap).
|
|
136
|
+
- **YAML pipeline loader** (`Swarm.from_yaml`) — declare a graph and
|
|
137
|
+
agent registry in YAML and execute it directly.
|
|
138
|
+
- **Skills system** (`SkillRef`, `SkillProvider`, `CapabilityMapper`)
|
|
139
|
+
for capability hydration from external skill inventories.
|
|
140
|
+
|
|
141
|
+
### Added — LLM providers
|
|
142
|
+
|
|
143
|
+
- **`AnthropicProvider`** — async wrapper over the official `anthropic` SDK.
|
|
144
|
+
- **`OpenAIProvider`** — async wrapper over the official `openai` SDK.
|
|
145
|
+
- **`GeminiProvider`** — async wrapper over the official `google-genai` SDK,
|
|
146
|
+
including support for `gemini-3-pro-image-preview` and other Gemini models.
|
|
147
|
+
- **Auto-detection** in `Swarm` — picks the right provider from the model
|
|
148
|
+
name prefix (`claude*`, `gpt*`/`o1`/`o3`/`o4`, `gemini*`).
|
|
149
|
+
- **`OpenClawSkillProvider`** — adapter for OpenClaw `AgentSkills`,
|
|
150
|
+
translating SDK skill objects into `SkillRef`s for capability hydration.
|
|
151
|
+
|
|
152
|
+
### Added — Testing & CI
|
|
153
|
+
|
|
154
|
+
- **240 passing tests, 3 skipped** across the full suite, including
|
|
155
|
+
dedicated test files for router edge cases, tracer/span lifecycle,
|
|
156
|
+
agent model invariants, and a full pipeline integration suite.
|
|
157
|
+
- **Shared test fixtures** in `tests/helpers.py` (mock providers,
|
|
158
|
+
failing providers, classifier mocks, fixed architects, completed-graph
|
|
159
|
+
builder).
|
|
160
|
+
- **GitHub Actions CI** ([.github/workflows/ci.yml](.github/workflows/ci.yml))
|
|
161
|
+
with `ruff` lint and a `pytest` matrix across Python 3.11 / 3.12 / 3.13.
|
|
162
|
+
|
|
163
|
+
### Fixed
|
|
164
|
+
|
|
165
|
+
- **Async exception masking** — `AsyncExecutor` cascading failures no
|
|
166
|
+
longer mask the original exception with a `RuntimeError`.
|
|
167
|
+
- **Partial-reservation leak in `AsyncExecutor`** — if `Sentinel.reserve()`
|
|
168
|
+
fails partway through a wave, all previously successful reservations in
|
|
169
|
+
that wave are now released before the exception propagates.
|
|
170
|
+
- **Synthesizer model passthrough** — `LLM_MERGE` synthesis now receives the
|
|
171
|
+
swarm's configured model instead of an empty string.
|
|
172
|
+
- **Direct-graph validation** — `Swarm.execute(graph)` (with a pre-built
|
|
173
|
+
`ExecutionGraph` instead of a `Task`) now runs `graph.validate()` before
|
|
174
|
+
execution.
|
|
175
|
+
- **Executor dependency guard** — `Executor._walk` now raises a clear
|
|
176
|
+
`ValueError` (instead of a `KeyError`) when a node depends on an unknown
|
|
177
|
+
node ID.
|
|
178
|
+
- **`LLMArchitect` retry robustness** — `aplan` now also recovers from
|
|
179
|
+
`TypeError` during LLM-response parsing, not only `ValueError`.
|
|
180
|
+
|
|
181
|
+
### Documentation
|
|
182
|
+
|
|
183
|
+
- **`Readme.md`** — full pitch, four worked examples (fork-join, broadcast-reduce,
|
|
184
|
+
YAML pipeline, agent registry), API reference for the public surface,
|
|
185
|
+
installation instructions for each provider extra, and an "Async usage"
|
|
186
|
+
section documenting `asyncio.run()` limitations and recommending the
|
|
187
|
+
async APIs (`aplan`, `execute_async`).
|
|
188
|
+
- **`LICENSE`** — MIT.
|
|
189
|
+
|
|
190
|
+
### Known issues
|
|
191
|
+
|
|
192
|
+
- **`tests/test_skills_registry.py::test_registry_cache_expires_after_ttl`** is
|
|
193
|
+
timing-flaky on Windows under suite load. The test uses a 50ms TTL with a
|
|
194
|
+
60ms sleep, which is too tight for `time.sleep()` precision on Windows.
|
|
195
|
+
Passes consistently in isolation. Tracked for fix in 0.1.1.
|
|
196
|
+
|
|
197
|
+
[Unreleased]: https://github.com/petehottelet/smythe/compare/v0.1.0...HEAD
|
|
198
|
+
[0.1.0]: https://github.com/petehottelet/smythe/releases/tag/v0.1.0
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
|
9
|
+
nationality, personal appearance, race, caste, color, religion, or sexual
|
|
10
|
+
identity and orientation.
|
|
11
|
+
|
|
12
|
+
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
13
|
+
diverse, inclusive, and healthy community.
|
|
14
|
+
|
|
15
|
+
## Our Standards
|
|
16
|
+
|
|
17
|
+
Examples of behavior that contributes to a positive environment for our
|
|
18
|
+
community include:
|
|
19
|
+
|
|
20
|
+
- Demonstrating empathy and kindness toward other people
|
|
21
|
+
- Being respectful of differing opinions, viewpoints, and experiences
|
|
22
|
+
- Giving and gracefully accepting constructive feedback
|
|
23
|
+
- Accepting responsibility and apologizing to those affected by our mistakes,
|
|
24
|
+
and learning from the experience
|
|
25
|
+
- Focusing on what is best not just for us as individuals, but for the overall
|
|
26
|
+
community
|
|
27
|
+
|
|
28
|
+
Examples of unacceptable behavior include:
|
|
29
|
+
|
|
30
|
+
- The use of sexualized language or imagery, and sexual attention or advances
|
|
31
|
+
of any kind
|
|
32
|
+
- Trolling, insulting or derogatory comments, and personal or political attacks
|
|
33
|
+
- Public or private harassment
|
|
34
|
+
- Publishing others' private information, such as a physical or email address,
|
|
35
|
+
without their explicit permission
|
|
36
|
+
- Other conduct which could reasonably be considered inappropriate in a
|
|
37
|
+
professional setting
|
|
38
|
+
|
|
39
|
+
## Enforcement Responsibilities
|
|
40
|
+
|
|
41
|
+
Community leaders are responsible for clarifying and enforcing our standards of
|
|
42
|
+
acceptable behavior and will take appropriate and fair corrective action in
|
|
43
|
+
response to any behavior that they deem inappropriate, threatening, offensive,
|
|
44
|
+
or harmful.
|
|
45
|
+
|
|
46
|
+
Community leaders have the right and responsibility to remove, edit, or reject
|
|
47
|
+
comments, commits, code, wiki edits, issues, and other contributions that are
|
|
48
|
+
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
|
49
|
+
decisions when appropriate.
|
|
50
|
+
|
|
51
|
+
## Scope
|
|
52
|
+
|
|
53
|
+
This Code of Conduct applies within all community spaces, and also applies when
|
|
54
|
+
an individual is officially representing the community in public spaces.
|
|
55
|
+
Examples of representing our community include using an official e-mail address,
|
|
56
|
+
posting via an official social media account, or acting as an appointed
|
|
57
|
+
representative at an online or offline event.
|
|
58
|
+
|
|
59
|
+
## Enforcement
|
|
60
|
+
|
|
61
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
62
|
+
reported to the project maintainers via a private GitHub message to
|
|
63
|
+
[@petehottelet](https://github.com/petehottelet) or by opening a confidential
|
|
64
|
+
[security advisory](https://github.com/petehottelet/smythe/security/advisories/new)
|
|
65
|
+
on this repository.
|
|
66
|
+
|
|
67
|
+
All complaints will be reviewed and investigated promptly and fairly.
|
|
68
|
+
|
|
69
|
+
All community leaders are obligated to respect the privacy and security of the
|
|
70
|
+
reporter of any incident.
|
|
71
|
+
|
|
72
|
+
## Enforcement Guidelines
|
|
73
|
+
|
|
74
|
+
Community leaders will follow these Community Impact Guidelines in determining
|
|
75
|
+
the consequences for any action they deem in violation of this Code of Conduct:
|
|
76
|
+
|
|
77
|
+
### 1. Correction
|
|
78
|
+
|
|
79
|
+
**Community Impact**: Use of inappropriate language or other behavior deemed
|
|
80
|
+
unprofessional or unwelcome in the community.
|
|
81
|
+
|
|
82
|
+
**Consequence**: A private, written warning from community leaders, providing
|
|
83
|
+
clarity around the nature of the violation and an explanation of why the
|
|
84
|
+
behavior was inappropriate. A public apology may be requested.
|
|
85
|
+
|
|
86
|
+
### 2. Warning
|
|
87
|
+
|
|
88
|
+
**Community Impact**: A violation through a single incident or series of
|
|
89
|
+
actions.
|
|
90
|
+
|
|
91
|
+
**Consequence**: A warning with consequences for continued behavior. No
|
|
92
|
+
interaction with the people involved, including unsolicited interaction with
|
|
93
|
+
those enforcing the Code of Conduct, for a specified period of time. This
|
|
94
|
+
includes avoiding interactions in community spaces as well as external channels
|
|
95
|
+
like social media. Violating these terms may lead to a temporary or permanent
|
|
96
|
+
ban.
|
|
97
|
+
|
|
98
|
+
### 3. Temporary Ban
|
|
99
|
+
|
|
100
|
+
**Community Impact**: A serious violation of community standards, including
|
|
101
|
+
sustained inappropriate behavior.
|
|
102
|
+
|
|
103
|
+
**Consequence**: A temporary ban from any sort of interaction or public
|
|
104
|
+
communication with the community for a specified period of time. No public or
|
|
105
|
+
private interaction with the people involved, including unsolicited interaction
|
|
106
|
+
with those enforcing the Code of Conduct, is allowed during this period.
|
|
107
|
+
Violating these terms may lead to a permanent ban.
|
|
108
|
+
|
|
109
|
+
### 4. Permanent Ban
|
|
110
|
+
|
|
111
|
+
**Community Impact**: Demonstrating a pattern of violation of community
|
|
112
|
+
standards, including sustained inappropriate behavior, harassment of an
|
|
113
|
+
individual, or aggression toward or disparagement of classes of individuals.
|
|
114
|
+
|
|
115
|
+
**Consequence**: A permanent ban from any sort of public interaction within the
|
|
116
|
+
community.
|
|
117
|
+
|
|
118
|
+
## Attribution
|
|
119
|
+
|
|
120
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
|
121
|
+
version 2.1, available at
|
|
122
|
+
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
|
123
|
+
|
|
124
|
+
Community Impact Guidelines were inspired by
|
|
125
|
+
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
|
126
|
+
|
|
127
|
+
For answers to common questions about this code of conduct, see the FAQ at
|
|
128
|
+
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
|
|
129
|
+
[https://www.contributor-covenant.org/translations][translations].
|
|
130
|
+
|
|
131
|
+
[homepage]: https://www.contributor-covenant.org
|
|
132
|
+
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
|
133
|
+
[Mozilla CoC]: https://github.com/mozilla/diversity
|
|
134
|
+
[FAQ]: https://www.contributor-covenant.org/faq
|
|
135
|
+
[translations]: https://www.contributor-covenant.org/translations
|