swarph-mesh
Model-agnostic Python substrate for the swarph-mesh ecosystem. Pure library, no CLI.
Designed to fill the gap left by existing tools (aichat, mods, Simon Willison's llm, gemini-cli, claude-cli): none expose mesh-gateway participation, per-caller attribution, structured-output discipline, or the cooperative-protocol patterns the swarph encodes.
This is one of three repos in the v0.3.x architecture:
| Repo | Role |
|---|---|
swarph-mesh |
This package — typed Protocol + adapters + SwarphCall + MeshClient |
swarph-cli |
The swarph binary. Thin client over swarph-mesh |
swarph-meshlm |
Simon Willison llm plugin. Same primitives wired into llm's plugin host |
All three sit on top of swarph-shared which provides the cross-billing-path attribution + subprocess env scrubbing + JSON-mode harness + peer-name registry primitives.
Status
v0.6.1 — PRICING table catch-up + alias resolution. Patches v0.6.0's discovery substrate with corrected pricing for ~20 models surfaced by the AIMLAPI catalog diff:
- Critical fix:
gpt-5was at(5.00, 20.00)speculative in v0.5.x; real direct OpenAI pricing is(1.25, 10.00)— anyone callinggpt-5between v0.5.x and v0.6.1 hadcost_usdover-attributed by ~4x. - New OpenAI entries:
gpt-4.1family (4.1 / 4.1-mini / 4.1-nano),gpt-5-mini,gpt-5-nano,gpt-5.2,gpt-5.2-pro. - New Anthropic entries:
claude-opus-4-1(premium $15/$75 tier),claude-sonnet-4-5,claude-sonnet-4,claude-haiku-3-5,claude-haiku-3+ dated-build aliases (claude-opus-4-5-20251101, etc.). - New xAI entries:
grok-4-3,grok-4-20-*,grok-4-1-fast-*,grok-4-fast-*(current generation per xAI docs).grok-4+grok-code-fast-1retire 2026-05-15 per xAI; v0.6.1 documents this in_GROK_RETIREMENT_NOTICE. - New xAI / DeepSeek alias normalizers:
_normalize_xai_idstripsx-ai/prefix +-beta+ dated suffixes;_normalize_deepseek_idstripsdeepseek/prefix + version suffixes. AIMLAPI's prefixed catalog IDs now resolve to PRICING entries instead of falling through to_default. - New Gemini entries:
gemini-2.0-flash,gemini-2.0-flash-001. _OPENAI_PRICING_VERIFIED_AT/_GROK_PRICING_VERIFIED_AT/_GEMINI_PRICING_VERIFIED_ATmetadata added for future drift detection (drop DM #720 direction).
v0.6.0 — architectural promotion: model discovery substrate. Four primitives:
- Catalog (AIMLAPI primary + per-provider fallback)
- Gemini pricing (Cloud Billing Catalog API)
- Anthropic pricing (manual table from claude.com/pricing with
verified_atprovenance) - OpenAI cost reconciliation (admin-key gated
/v1/organization/costs) LLMAdapter.list_models()Protocol method (breaking change → v0.6.0 major-version bump)
Public surface:
-
LLMAdapterProtocol (runtime-checkable) +ChatMessage+LLMResponse -
SwarphCall— caller-convention-validated entry point with hooks + attribution -
GeminiAdapter— wrapslanggraph-genai-bridge(Flex tier, context caching) -
DeepSeekAdapter(v0.3.0) — OpenAI-protocol-compatible client for V4-Flash / V4-Pro / V3 aliases; preserves reasoning content as[reasoning]preamble for portability -
ClaudeAdapter(v0.4.0) — subprocess-based wrapper aroundclaude -pfor subscription billing path (noANTHROPIC_API_KEYneeded; reads~/.claude/.credentials.json). Reusesswarph_shared.scrub_env_for_subprocessto keep billing-relevant env keys out of the subprocess.cost_usd=0.0for subscription calls (flat-rate marginal cost). A metered-equivalent is placed inraw_response["api_metered_cost_usd"]— but note thatraw_responseis stripped before the attribution row is written andAttributionEvent.extrais never populated, so this value does NOT currently reach an auditor. Tracked as a contract defect, not a documented feature. -
OpenAIAdapter(v0.5.0) — native async viaopenai.AsyncOpenAI(noasyncio.to_threadthreadpool ceiling). Pricing forgpt-4o/gpt-4o-mini/o1/o3/o3-mini/o4-mini/gpt-5. o-seriesreasoning_contentpreserved as[reasoning]preamble.OPENAI_API_KEYenv fallback. -
GrokAdapter(v0.5.0) — xAI's OpenAI-compatible API athttps://api.x.ai/v1, also viaAsyncOpenAI. Pricing forgrok-4/grok-3/grok-3-mini. Dual env-var resolution:XAI_API_KEY(canonical) →GROK_API_KEY(alias). Same[reasoning]preamble shape as the rest of the adapter family. -
AntigravityAdapter— Google subscription lane via the antigravity CLI, firejail-sandboxed.cost_usd=0.0(subscription). -
GeminiCLIAdapter— Gemini subscription lane via the local CLI (sibling of the meteredGeminiAdapter). -
GrokCLIAdapter(v0.7.9) — xAI subscription lane: firejail-sandboxedgrok --prompt-fileon a SuperGrok-Heavy OIDC session token. Stateless per call (--no-memory,--no-subagents); meteredXAI_API_KEYis deliberately scrubbed so no pay-per-token fallback can fire. -
VibeCLIAdapter(v0.8.0) — Mistral subscription lane: firejail-sandboxedvibe -p, prompt piped on stdin (never written to disk), no tools at all (--disabled-tools '*'), and an ephemeralVIBE_HOMEso the worker is stateless by construction. Carries--max-price, a hard per-call dollar ceiling enforced by the CLI — the only lane with a call-site cost bound. Note the inversion from the grok lane: Mistral issues subscription API keys, soMISTRAL_API_KEYis the subscription path and must be allowlisted through the env scrub, not stripped. Reportsvendor_domicile="FR"andprocessing_residency="unknown"as separate informational facts — neither is a routing-eligibility jurisdiction. -
swarph_mesh.discovery(NEW v0.6.0) — three primitives:- Catalog backed by AIMLAPI's public
/modelsendpoint (no auth, ~600+ entries) with per-provider/v1/modelsfallback when AIMLAPI is unreachable.list_models(provider=...),is_model_supported(model_id),get_model_info(model_id). 24h TTL cache. - Gemini pricing via Google's Cloud Billing Catalog API (service
241C-273D-49C8= Vertex AI).fetch_gemini_pricing()andpricing_for_gemini_model(hint, direction, tier). Auth:GOOGLE_CLOUD_BILLING_API_KEYenv (separate fromGEMINI_API_KEY— Cloud Console project key with Billing API scope). - Anthropic pricing via static manual table mirrored from claude.com/pricing (Anthropic does not expose programmatic pricing).
pricing_for_anthropic_model(id)returns full 5-tuple (base input + 5m cache + 1h cache + cache hit + output) per model. Honest about origin viaverified_atfield; update by re-pasting the docs table. - OpenAI/xAI/DeepSeek pricing stays in adapter-local
PRICINGdicts until programmatic sources surface.
- Catalog backed by AIMLAPI's public
-
LLMAdapter.list_models()(NEW v0.6.0) — Protocol-level method. Each adapter delegates todiscovery.list_models(provider=self.name). Breaking change: external implementations ofLLMAdapterfrom v0.5.x must implement this method to satisfy the runtime-checkable Protocol. -
JSON-mode harness — retry-once with [USER]-turn feedback (per swarph-shared invariant)
-
Attribution:
FileAttributionWriterdefault;set_default_writer()for production TSDB consumers -
MeshClient(v0.2.0) — async wrapper around mesh-gateway HTTP API; replaces hand-rolled curl in inbox-drain scripts
Tests: 253+ passing (250 offline + live gates: 1 claude subscription + 1 deepseek + 2 mesh + 1 gemini + 1 openai + 1 grok + 3 discovery against live AIMLAPI; live tests gated on env/creds or SWARPH_SKIP_NETWORK=1).
from swarph_mesh import SwarphCall, ChatMessage
# Phase 1 — LLM call with attribution
result = await SwarphCall(
provider="gemini",
caller="orchestrator.boss",
).chat(
messages=[ChatMessage(role="user", content="hi")],
)
print(result.text, result.cost_usd, result.input_tokens)
from swarph_mesh import MeshClient
import os
# Phase 3 — mesh-gateway DM coordination
async with MeshClient(node="my-cell") as client: # token from MESH_GATEWAY_TOKEN env
peers = await client.list_peers()
msgs = await client.fetch(unread_only=True)
sent = await client.send(to="peer-cell", kind="fyi", content="hello")
await client.mark_read(msgs[0].id)
MeshClient.send() enforces two structural invariants:
- Recipient name validation via
swarph_shared.validate_node_name— closes the framing-contagion class (Vector A peer-onboarding chatter, Vector B human-prompt shorthand). - Mesh-secrets out-of-band guard — best-effort regex sniff for credential-shaped content (PyPI tokens, Anthropic keys, GitHub tokens, JWTs, AWS keys). Hits raise
MeshSecretLeakErrorBEFORE the POST. Operator escape hatch viaskip_secret_check=Truefor legitimate prose mentioning credential shapes. Treat "mesh secrets out-of-band only" as non-negotiable; the guard catches obvious cases.
Phase rollout
| Phase | Scope |
|---|---|
| 0 (v0.0.1) | Typed substrate — Protocol + dataclasses + exceptions |
| 1 (v0.1.0) | Gemini adapter + SwarphCall surface + caller convention import + JSON-mode harness + attribution hook |
| 3 (v0.2.0) | MeshClient async wrapper + recipient validation + mesh-secrets guard |
| 4 #2 (v0.3.0) | DeepSeek adapter — OpenAI-protocol-compatible, V4-Flash default, V4-Pro premium, V3 aliases preserved, reasoning_content kept as [reasoning] preamble |
| 4 #3 (v0.4.0) | Claude subscription adapter — wraps claude -p via subprocess, reads ~/.claude/.credentials.json, billing-leak prevention via scrub_env_for_subprocess |
| 4 #4 + #5 (v0.5.0 — this release) | OpenAI + Grok adapters — both native-async via AsyncOpenAI from day one (per issue #7); xAI on base_url=https://api.x.ai/v1; Phase 4 ship-order complete |
| 5.5 | swarph onboard + swarph ratify (lives in swarph-cli, depends on this) |
| 5.7 | swarph daemon + REPL drain coroutine (lives in swarph-cli) |
| 6 | (already done) PyPI publish |
| 7 | swarph-meshlm plugin (separate repo, this dep) |
Install (dev)
git clone https://github.com/BrainSurfing-tech/swarph-mesh
cd swarph-mesh
python -m venv venv && source venv/bin/activate
pip install -e ".[dev]"
pytest
License
MIT. Pierre Samson + Claude Opus, 2026.
Release files for swarph-mesh 0.8.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| swarph_mesh-0.8.0.tar.gz | 152.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| swarph_mesh-0.8.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 263.0 kB
Release files / swarph_mesh-0.8.0.tar.gz
| Download URL | swarph_mesh-0.8.0.tar.gz |
|---|---|
| Size | 152.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
930e0ba29987a5aae66f479f32e47acc791dea57dd4a5affb9e6a591b6543370
|
|
BLAKE2b-256 checksum How to use checksums |
c63c77053bc171f70fc1ef36e58dfca2d18aa1f0c58f3b131c596981456396a6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.3
|
Release files / swarph_mesh-0.8.0-py3-none-any.whl
| Download URL | swarph_mesh-0.8.0-py3-none-any.whl |
|---|---|
| Size | 110.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0b7abcf376472304170f48f9fca395e5e5187073f168389814313391a8ba0a24
|
|
BLAKE2b-256 checksum How to use checksums |
1414298e7e33792846db2c9b6ed4418fa7a48c0163213d0a99632f1110d232ac
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.3
|