leanswarm 0.1.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.
Files changed (32) hide show
  1. leanswarm-0.1.0/LICENSE +22 -0
  2. leanswarm-0.1.0/PKG-INFO +181 -0
  3. leanswarm-0.1.0/README.md +145 -0
  4. leanswarm-0.1.0/pyproject.toml +77 -0
  5. leanswarm-0.1.0/setup.cfg +4 -0
  6. leanswarm-0.1.0/src/lean_swarm/__init__.py +6 -0
  7. leanswarm-0.1.0/src/lean_swarm/api/__init__.py +4 -0
  8. leanswarm-0.1.0/src/lean_swarm/api/app.py +31 -0
  9. leanswarm-0.1.0/src/lean_swarm/cli.py +130 -0
  10. leanswarm-0.1.0/src/lean_swarm/engine/__init__.py +6 -0
  11. leanswarm-0.1.0/src/lean_swarm/engine/config.py +54 -0
  12. leanswarm-0.1.0/src/lean_swarm/engine/llm.py +615 -0
  13. leanswarm-0.1.0/src/lean_swarm/engine/logging.py +22 -0
  14. leanswarm-0.1.0/src/lean_swarm/engine/memory.py +103 -0
  15. leanswarm-0.1.0/src/lean_swarm/engine/models.py +223 -0
  16. leanswarm-0.1.0/src/lean_swarm/engine/population.py +620 -0
  17. leanswarm-0.1.0/src/lean_swarm/engine/simulator.py +544 -0
  18. leanswarm-0.1.0/src/lean_swarm/engine/world.py +1008 -0
  19. leanswarm-0.1.0/src/lean_swarm/tools/__init__.py +4 -0
  20. leanswarm-0.1.0/src/lean_swarm/tools/benchmark.py +483 -0
  21. leanswarm-0.1.0/src/leanswarm.egg-info/PKG-INFO +181 -0
  22. leanswarm-0.1.0/src/leanswarm.egg-info/SOURCES.txt +30 -0
  23. leanswarm-0.1.0/src/leanswarm.egg-info/dependency_links.txt +1 -0
  24. leanswarm-0.1.0/src/leanswarm.egg-info/entry_points.txt +2 -0
  25. leanswarm-0.1.0/src/leanswarm.egg-info/requires.txt +19 -0
  26. leanswarm-0.1.0/src/leanswarm.egg-info/top_level.txt +1 -0
  27. leanswarm-0.1.0/tests/test_api.py +27 -0
  28. leanswarm-0.1.0/tests/test_benchmark.py +85 -0
  29. leanswarm-0.1.0/tests/test_cli.py +67 -0
  30. leanswarm-0.1.0/tests/test_engine.py +22 -0
  31. leanswarm-0.1.0/tests/test_llm.py +28 -0
  32. leanswarm-0.1.0/tests/test_phase2_integration.py +231 -0
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mohith Das
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,181 @@
1
+ Metadata-Version: 2.4
2
+ Name: leanswarm
3
+ Version: 0.1.0
4
+ Summary: Lean Swarm multi-agent prediction and simulation engine
5
+ Author: Mohith Das
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/mohith-das/leanswarm
8
+ Project-URL: Repository, https://github.com/mohith-das/leanswarm.git
9
+ Keywords: agents,forecasting,simulation,llm,pydantic
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Framework :: FastAPI
16
+ Requires-Python: >=3.11
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Requires-Dist: diskcache<6.0,>=5.6
20
+ Requires-Dist: fastapi<1.0,>=0.115
21
+ Requires-Dist: litellm<2.0,>=1.72
22
+ Requires-Dist: networkx<4.0,>=3.3
23
+ Requires-Dist: pydantic<3.0,>=2.8
24
+ Requires-Dist: sentence-transformers<4.0,>=3.0
25
+ Requires-Dist: sqlite-vss>=0.1.2; platform_system != "Windows"
26
+ Requires-Dist: uvicorn<1.0,>=0.30
27
+ Provides-Extra: dev
28
+ Requires-Dist: build>=1.2; extra == "dev"
29
+ Requires-Dist: httpx>=0.27; extra == "dev"
30
+ Requires-Dist: mypy>=1.11; extra == "dev"
31
+ Requires-Dist: pre-commit>=3.8; extra == "dev"
32
+ Requires-Dist: pytest>=8.3; extra == "dev"
33
+ Requires-Dist: ruff>=0.6; extra == "dev"
34
+ Requires-Dist: twine>=5.1; extra == "dev"
35
+ Dynamic: license-file
36
+
37
+ # Lean Swarm
38
+
39
+ Lean Swarm is a cost-focused multi-agent prediction and simulation engine designed to approximate
40
+ MiroFish-class narrative forecasting with aggressive batching, sparse activation, hybrid state, and
41
+ strict LLM routing guardrails.
42
+
43
+ ## Overview
44
+
45
+ Given a seed document and a prediction question, Lean Swarm builds a simulated world of agents,
46
+ runs a bounded number of interaction ticks, and returns:
47
+
48
+ - a structured prediction report
49
+ - a post-simulation world snapshot with agent states and relationship edges
50
+
51
+ The project is structured for open-source collaboration, MIT licensing, and PyPI publishing from
52
+ day one.
53
+
54
+ ## Quickstart
55
+
56
+ ### Install
57
+
58
+ ```bash
59
+ pip install -e .[dev]
60
+ cp .env.example .env
61
+ ```
62
+
63
+ Optional with `uv`:
64
+
65
+ ```bash
66
+ uv venv
67
+ uv pip install -e .[dev]
68
+ ```
69
+
70
+ ### Run
71
+
72
+ ```bash
73
+ lean-swarm smoke
74
+ lean-swarm simulate --seed examples/seed.txt --question "Will public trust rise this quarter?"
75
+ lean-swarm api
76
+ lean-swarm bench
77
+ ```
78
+
79
+ ## Architecture
80
+
81
+ ### Core rules
82
+
83
+ - All model traffic is routed through `engine/llm.py`.
84
+ - Every LLM route and simulation tick is logged.
85
+ - The engine uses Pydantic schemas at every boundary.
86
+ - LLM calls are retried and concurrency-limited with semaphores.
87
+
88
+ ### Phase 1 engine shape
89
+
90
+ - Tiered model routing with `FLAGSHIP`, `STANDARD`, and `CHEAP` tiers.
91
+ - Batched group actions for active agents.
92
+ - Archetype pooling with 96 archetypes and up to 50 named agents.
93
+ - Hybrid numeric state for mood, energy, attention, and relationships.
94
+ - Event-driven activation with a bounded active fraction per tick.
95
+ - Hierarchical memory slices for working, episodic, and semantic references.
96
+ - Disk-backed action caching via `diskcache`.
97
+ - Early convergence detection on low-delta ticks.
98
+
99
+ See [docs/architecture.md](docs/architecture.md) for more detail.
100
+
101
+ ## CLI Usage
102
+
103
+ ### Smoke test
104
+
105
+ ```bash
106
+ lean-swarm smoke
107
+ ```
108
+
109
+ ### Simulate a scenario
110
+
111
+ ```bash
112
+ lean-swarm simulate \
113
+ --seed examples/seed.txt \
114
+ --question "Will the policy announcement improve sentiment?" \
115
+ --activation-mode lean \
116
+ --active-agent-fraction 0.25
117
+ ```
118
+
119
+ ### Run the API
120
+
121
+ ```bash
122
+ lean-swarm api --host 127.0.0.1 --port 8000
123
+ ```
124
+
125
+ ### Run the benchmark harness
126
+
127
+ ```bash
128
+ lean-swarm bench
129
+ ```
130
+
131
+ ## API Usage
132
+
133
+ ### Start server
134
+
135
+ ```bash
136
+ lean-swarm api
137
+ ```
138
+
139
+ ### Example request
140
+
141
+ ```bash
142
+ curl -X POST http://127.0.0.1:8000/simulate \
143
+ -H "Content-Type: application/json" \
144
+ -d '{
145
+ "seed_document": "A national survey shows mixed views on new policy proposals.",
146
+ "question": "Will approval improve over the next month?",
147
+ "rounds": 4
148
+ }'
149
+ ```
150
+
151
+ ## Benchmarks
152
+
153
+ `lean-swarm bench` runs the same benchmark cases in both `lean` and `naive` activation modes and
154
+ returns a comparison payload with:
155
+
156
+ - top-level deltas: `cost_ratio_naive_to_lean`, `quality_delta_lean_vs_naive`,
157
+ `runtime_ratio_naive_to_lean`
158
+ - per-mode outputs under `modes.lean` and `modes.naive` (quality proxy, runtime, cache stats, token
159
+ and estimated cost totals)
160
+ - `plot_points`: per-case points with `mode`, `score`, `cost_usd`, `runtime_seconds`,
161
+ `token_total`, and related fields for quality-vs-cost plotting
162
+
163
+ This lets you compare lean efficiency against naive full activation and plot quality-vs-cost points
164
+ directly from benchmark output without extra transforms.
165
+
166
+ ## Limitations
167
+
168
+ - The Phase 1 engine uses deterministic mock responses unless live credentials are configured.
169
+ - Semantic memory is scaffolded but not yet backed by a production embedding and retrieval flow.
170
+ - The web client is intentionally minimal at this stage.
171
+
172
+ ## Roadmap
173
+
174
+ See [ROADMAP.md](ROADMAP.md) for V2 priorities including multi-world simulations, Monte Carlo
175
+ runs, intervention testing, replay UX, plugin architecture, large-scale agent support, and
176
+ hybrid local+cloud routing.
177
+
178
+ ## Contributing
179
+
180
+ Contributions are welcome. Start with [CONTRIBUTING.md](CONTRIBUTING.md), pick an issue template
181
+ that matches your contribution track, and open a focused PR.
@@ -0,0 +1,145 @@
1
+ # Lean Swarm
2
+
3
+ Lean Swarm is a cost-focused multi-agent prediction and simulation engine designed to approximate
4
+ MiroFish-class narrative forecasting with aggressive batching, sparse activation, hybrid state, and
5
+ strict LLM routing guardrails.
6
+
7
+ ## Overview
8
+
9
+ Given a seed document and a prediction question, Lean Swarm builds a simulated world of agents,
10
+ runs a bounded number of interaction ticks, and returns:
11
+
12
+ - a structured prediction report
13
+ - a post-simulation world snapshot with agent states and relationship edges
14
+
15
+ The project is structured for open-source collaboration, MIT licensing, and PyPI publishing from
16
+ day one.
17
+
18
+ ## Quickstart
19
+
20
+ ### Install
21
+
22
+ ```bash
23
+ pip install -e .[dev]
24
+ cp .env.example .env
25
+ ```
26
+
27
+ Optional with `uv`:
28
+
29
+ ```bash
30
+ uv venv
31
+ uv pip install -e .[dev]
32
+ ```
33
+
34
+ ### Run
35
+
36
+ ```bash
37
+ lean-swarm smoke
38
+ lean-swarm simulate --seed examples/seed.txt --question "Will public trust rise this quarter?"
39
+ lean-swarm api
40
+ lean-swarm bench
41
+ ```
42
+
43
+ ## Architecture
44
+
45
+ ### Core rules
46
+
47
+ - All model traffic is routed through `engine/llm.py`.
48
+ - Every LLM route and simulation tick is logged.
49
+ - The engine uses Pydantic schemas at every boundary.
50
+ - LLM calls are retried and concurrency-limited with semaphores.
51
+
52
+ ### Phase 1 engine shape
53
+
54
+ - Tiered model routing with `FLAGSHIP`, `STANDARD`, and `CHEAP` tiers.
55
+ - Batched group actions for active agents.
56
+ - Archetype pooling with 96 archetypes and up to 50 named agents.
57
+ - Hybrid numeric state for mood, energy, attention, and relationships.
58
+ - Event-driven activation with a bounded active fraction per tick.
59
+ - Hierarchical memory slices for working, episodic, and semantic references.
60
+ - Disk-backed action caching via `diskcache`.
61
+ - Early convergence detection on low-delta ticks.
62
+
63
+ See [docs/architecture.md](docs/architecture.md) for more detail.
64
+
65
+ ## CLI Usage
66
+
67
+ ### Smoke test
68
+
69
+ ```bash
70
+ lean-swarm smoke
71
+ ```
72
+
73
+ ### Simulate a scenario
74
+
75
+ ```bash
76
+ lean-swarm simulate \
77
+ --seed examples/seed.txt \
78
+ --question "Will the policy announcement improve sentiment?" \
79
+ --activation-mode lean \
80
+ --active-agent-fraction 0.25
81
+ ```
82
+
83
+ ### Run the API
84
+
85
+ ```bash
86
+ lean-swarm api --host 127.0.0.1 --port 8000
87
+ ```
88
+
89
+ ### Run the benchmark harness
90
+
91
+ ```bash
92
+ lean-swarm bench
93
+ ```
94
+
95
+ ## API Usage
96
+
97
+ ### Start server
98
+
99
+ ```bash
100
+ lean-swarm api
101
+ ```
102
+
103
+ ### Example request
104
+
105
+ ```bash
106
+ curl -X POST http://127.0.0.1:8000/simulate \
107
+ -H "Content-Type: application/json" \
108
+ -d '{
109
+ "seed_document": "A national survey shows mixed views on new policy proposals.",
110
+ "question": "Will approval improve over the next month?",
111
+ "rounds": 4
112
+ }'
113
+ ```
114
+
115
+ ## Benchmarks
116
+
117
+ `lean-swarm bench` runs the same benchmark cases in both `lean` and `naive` activation modes and
118
+ returns a comparison payload with:
119
+
120
+ - top-level deltas: `cost_ratio_naive_to_lean`, `quality_delta_lean_vs_naive`,
121
+ `runtime_ratio_naive_to_lean`
122
+ - per-mode outputs under `modes.lean` and `modes.naive` (quality proxy, runtime, cache stats, token
123
+ and estimated cost totals)
124
+ - `plot_points`: per-case points with `mode`, `score`, `cost_usd`, `runtime_seconds`,
125
+ `token_total`, and related fields for quality-vs-cost plotting
126
+
127
+ This lets you compare lean efficiency against naive full activation and plot quality-vs-cost points
128
+ directly from benchmark output without extra transforms.
129
+
130
+ ## Limitations
131
+
132
+ - The Phase 1 engine uses deterministic mock responses unless live credentials are configured.
133
+ - Semantic memory is scaffolded but not yet backed by a production embedding and retrieval flow.
134
+ - The web client is intentionally minimal at this stage.
135
+
136
+ ## Roadmap
137
+
138
+ See [ROADMAP.md](ROADMAP.md) for V2 priorities including multi-world simulations, Monte Carlo
139
+ runs, intervention testing, replay UX, plugin architecture, large-scale agent support, and
140
+ hybrid local+cloud routing.
141
+
142
+ ## Contributing
143
+
144
+ Contributions are welcome. Start with [CONTRIBUTING.md](CONTRIBUTING.md), pick an issue template
145
+ that matches your contribution track, and open a focused PR.
@@ -0,0 +1,77 @@
1
+ [build-system]
2
+ requires = ["setuptools>=69", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "leanswarm"
7
+ version = "0.1.0"
8
+ description = "Lean Swarm multi-agent prediction and simulation engine"
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = "MIT"
12
+ authors = [{ name = "Mohith Das" }]
13
+ keywords = ["agents", "forecasting", "simulation", "llm", "pydantic"]
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "Intended Audience :: Developers",
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3.11",
19
+ "Programming Language :: Python :: 3.12",
20
+ "Framework :: FastAPI",
21
+ ]
22
+ dependencies = [
23
+ "diskcache>=5.6,<6.0",
24
+ "fastapi>=0.115,<1.0",
25
+ "litellm>=1.72,<2.0",
26
+ "networkx>=3.3,<4.0",
27
+ "pydantic>=2.8,<3.0",
28
+ "sentence-transformers>=3.0,<4.0",
29
+ "sqlite-vss>=0.1.2; platform_system != 'Windows'",
30
+ "uvicorn>=0.30,<1.0",
31
+ ]
32
+
33
+ [project.optional-dependencies]
34
+ dev = [
35
+ "build>=1.2",
36
+ "httpx>=0.27",
37
+ "mypy>=1.11",
38
+ "pre-commit>=3.8",
39
+ "pytest>=8.3",
40
+ "ruff>=0.6",
41
+ "twine>=5.1",
42
+ ]
43
+
44
+ [project.scripts]
45
+ lean-swarm = "lean_swarm.cli:main"
46
+
47
+ [project.urls]
48
+ Homepage = "https://github.com/mohith-das/leanswarm"
49
+ Repository = "https://github.com/mohith-das/leanswarm.git"
50
+
51
+ [tool.setuptools]
52
+ package-dir = { "" = "src" }
53
+
54
+ [tool.setuptools.packages.find]
55
+ where = ["src"]
56
+
57
+ [tool.pytest.ini_options]
58
+ testpaths = ["tests"]
59
+
60
+ [tool.ruff]
61
+ target-version = "py311"
62
+ line-length = 100
63
+
64
+ [tool.ruff.lint]
65
+ select = ["E", "F", "I", "B", "UP", "ASYNC"]
66
+
67
+ [tool.mypy]
68
+ python_version = "3.11"
69
+ warn_unused_configs = true
70
+ warn_redundant_casts = true
71
+ warn_unused_ignores = true
72
+ strict_optional = true
73
+ check_untyped_defs = true
74
+ disallow_incomplete_defs = true
75
+ disallow_untyped_defs = true
76
+ ignore_missing_imports = true
77
+ packages = ["lean_swarm"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,6 @@
1
+ """Lean Swarm package."""
2
+
3
+ __all__ = ["__version__"]
4
+
5
+ __version__ = "0.1.0"
6
+
@@ -0,0 +1,4 @@
1
+ from .app import create_app
2
+
3
+ __all__ = ["create_app"]
4
+
@@ -0,0 +1,31 @@
1
+ from __future__ import annotations
2
+
3
+ from fastapi import FastAPI
4
+
5
+ from lean_swarm import __version__
6
+ from lean_swarm.engine.models import SimulationRequest, SimulationResult
7
+ from lean_swarm.engine.simulator import LeanSwarmEngine
8
+
9
+
10
+ def create_app() -> FastAPI:
11
+ app = FastAPI(
12
+ title="Lean Swarm API",
13
+ version=__version__,
14
+ description="HTTP surface for the Lean Swarm simulation engine.",
15
+ )
16
+ engine = LeanSwarmEngine()
17
+
18
+ @app.get("/healthz")
19
+ async def healthz() -> dict[str, str]:
20
+ return {"status": "ok"}
21
+
22
+ @app.get("/smoke", response_model=SimulationResult)
23
+ async def smoke() -> SimulationResult:
24
+ return await engine.smoke_test()
25
+
26
+ @app.post("/simulate", response_model=SimulationResult)
27
+ async def simulate(request: SimulationRequest) -> SimulationResult:
28
+ return await engine.simulate(request)
29
+
30
+ return app
31
+
@@ -0,0 +1,130 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import asyncio
5
+ import json
6
+ from collections.abc import Sequence
7
+ from pathlib import Path
8
+
9
+ import uvicorn
10
+
11
+ from lean_swarm.api.app import create_app
12
+ from lean_swarm.engine.config import RuntimeSettings
13
+ from lean_swarm.engine.models import ActivationMode, SimulationRequest
14
+ from lean_swarm.engine.simulator import LeanSwarmEngine
15
+ from lean_swarm.tools.benchmark import run_benchmark
16
+
17
+
18
+ def build_parser() -> argparse.ArgumentParser:
19
+ parser = argparse.ArgumentParser(prog="lean-swarm", description="Lean Swarm CLI")
20
+ subparsers = parser.add_subparsers(dest="command", required=True)
21
+
22
+ smoke_parser = subparsers.add_parser("smoke", help="Run a deterministic smoke simulation")
23
+ smoke_parser.set_defaults(handler=handle_smoke)
24
+
25
+ simulate_parser = subparsers.add_parser(
26
+ "simulate", help="Run a simulation from a seed document and prediction question"
27
+ )
28
+ simulate_parser.add_argument("--seed", required=True, help="Path to a seed document")
29
+ simulate_parser.add_argument("--question", required=True, help="Prediction question")
30
+ simulate_parser.add_argument("--rounds", type=int, default=6, help="Maximum tick count")
31
+ simulate_parser.add_argument(
32
+ "--max-agents", type=int, default=24, help="Maximum number of simulated agents"
33
+ )
34
+ simulate_parser.add_argument(
35
+ "--active-agent-fraction",
36
+ type=float,
37
+ default=0.2,
38
+ help="Fraction of agents active on each tick",
39
+ )
40
+ simulate_parser.add_argument(
41
+ "--activation-mode",
42
+ choices=[mode.value for mode in ActivationMode],
43
+ default=ActivationMode.LEAN.value,
44
+ help="Activation strategy for selecting active agents",
45
+ )
46
+ simulate_parser.add_argument(
47
+ "--group-size", type=int, default=5, help="Number of active agents processed per batch"
48
+ )
49
+ simulate_parser.add_argument(
50
+ "--convergence-threshold",
51
+ type=int,
52
+ default=2,
53
+ help="Stable tick streak before ending simulation early",
54
+ )
55
+ simulate_parser.add_argument(
56
+ "--random-seed", type=int, default=7, help="Random seed for deterministic behavior"
57
+ )
58
+ simulate_parser.add_argument(
59
+ "--use-llm",
60
+ action="store_true",
61
+ dest="use_llm",
62
+ default=True,
63
+ help="Enable live LLM calls when credentials are available",
64
+ )
65
+ simulate_parser.add_argument(
66
+ "--no-use-llm",
67
+ action="store_false",
68
+ dest="use_llm",
69
+ help="Disable live LLM calls and force mock execution",
70
+ )
71
+ simulate_parser.set_defaults(handler=handle_simulate)
72
+
73
+ api_parser = subparsers.add_parser("api", help="Run the FastAPI server")
74
+ api_parser.add_argument("--host", default=None, help="API host override")
75
+ api_parser.add_argument("--port", type=int, default=None, help="API port override")
76
+ api_parser.set_defaults(handler=handle_api)
77
+
78
+ bench_parser = subparsers.add_parser("bench", help="Run the benchmark harness")
79
+ bench_parser.set_defaults(handler=handle_bench)
80
+
81
+ return parser
82
+
83
+
84
+ def main(argv: Sequence[str] | None = None) -> int:
85
+ parser = build_parser()
86
+ args = parser.parse_args(argv)
87
+ return int(args.handler(args))
88
+
89
+
90
+ def handle_smoke(_: argparse.Namespace) -> int:
91
+ result = asyncio.run(LeanSwarmEngine().smoke_test())
92
+ print(result.model_dump_json(indent=2))
93
+ return 0
94
+
95
+
96
+ def handle_simulate(args: argparse.Namespace) -> int:
97
+ seed_path = Path(args.seed)
98
+ request = SimulationRequest(
99
+ seed_document=seed_path.read_text(encoding="utf-8"),
100
+ question=args.question,
101
+ rounds=args.rounds,
102
+ max_agents=args.max_agents,
103
+ active_agent_fraction=args.active_agent_fraction,
104
+ activation_mode=args.activation_mode,
105
+ group_size=args.group_size,
106
+ convergence_threshold=args.convergence_threshold,
107
+ random_seed=args.random_seed,
108
+ use_llm=args.use_llm,
109
+ )
110
+ result = asyncio.run(LeanSwarmEngine().simulate(request))
111
+ print(result.model_dump_json(indent=2))
112
+ return 0
113
+
114
+
115
+ def handle_api(args: argparse.Namespace) -> int:
116
+ settings = RuntimeSettings.from_env()
117
+ host = args.host or settings.api_host
118
+ port = args.port or settings.api_port
119
+ uvicorn.run(create_app(), host=host, port=port)
120
+ return 0
121
+
122
+
123
+ def handle_bench(_: argparse.Namespace) -> int:
124
+ result = asyncio.run(run_benchmark())
125
+ print(json.dumps(result, indent=2))
126
+ return 0
127
+
128
+
129
+ if __name__ == "__main__":
130
+ raise SystemExit(main())
@@ -0,0 +1,6 @@
1
+ from .llm import LiteLLMRouter
2
+ from .models import SimulationRequest, SimulationResult
3
+ from .simulator import LeanSwarmEngine
4
+
5
+ __all__ = ["LeanSwarmEngine", "LiteLLMRouter", "SimulationRequest", "SimulationResult"]
6
+
@@ -0,0 +1,54 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from pathlib import Path
5
+
6
+ from pydantic import BaseModel, Field
7
+
8
+
9
+ def _env_flag(name: str, default: bool) -> bool:
10
+ value = os.getenv(name)
11
+ if value is None:
12
+ return default
13
+ return value.strip().lower() in {"1", "true", "yes", "on"}
14
+
15
+
16
+ class RuntimeSettings(BaseModel):
17
+ cache_dir: Path = Field(default=Path(".leanswarm/cache"))
18
+ log_dir: Path = Field(default=Path(".leanswarm/logs"))
19
+ dry_run: bool = True
20
+ max_concurrency: int = 4
21
+ retry_attempts: int = 3
22
+ api_host: str = "127.0.0.1"
23
+ api_port: int = 8000
24
+ flagship_model: str = "gpt-4.1"
25
+ standard_model: str = "gpt-4.1-mini"
26
+ cheap_model: str = "gpt-4.1-nano"
27
+
28
+ @classmethod
29
+ def from_env(cls) -> "RuntimeSettings":
30
+ return cls(
31
+ cache_dir=Path(os.getenv("LEANSWARM_CACHE_DIR", ".leanswarm/cache")),
32
+ log_dir=Path(os.getenv("LEANSWARM_LOG_DIR", ".leanswarm/logs")),
33
+ dry_run=_env_flag("LEANSWARM_DRY_RUN", True),
34
+ max_concurrency=int(os.getenv("LEANSWARM_MAX_CONCURRENCY", "4")),
35
+ retry_attempts=int(os.getenv("LEANSWARM_RETRY_ATTEMPTS", "3")),
36
+ api_host=os.getenv("LEANSWARM_API_HOST", "127.0.0.1"),
37
+ api_port=int(os.getenv("LEANSWARM_API_PORT", "8000")),
38
+ flagship_model=os.getenv("LEANSWARM_FLAGSHIP_MODEL", "gpt-4.1"),
39
+ standard_model=os.getenv("LEANSWARM_STANDARD_MODEL", "gpt-4.1-mini"),
40
+ cheap_model=os.getenv("LEANSWARM_CHEAP_MODEL", "gpt-4.1-nano"),
41
+ )
42
+
43
+ def ensure_dirs(self) -> None:
44
+ self.cache_dir.mkdir(parents=True, exist_ok=True)
45
+ self.log_dir.mkdir(parents=True, exist_ok=True)
46
+
47
+ @property
48
+ def llm_log_path(self) -> Path:
49
+ return self.log_dir / "llm_calls.jsonl"
50
+
51
+ @property
52
+ def tick_log_path(self) -> Path:
53
+ return self.log_dir / "ticks.jsonl"
54
+