Compare commits
9 commits
83cda680d2
...
25b36e9ffb
| Author | SHA1 | Date | |
|---|---|---|---|
| 25b36e9ffb | |||
| 51694acc64 | |||
| 3886ee8480 | |||
| 5e2dd7aac3 | |||
| 178f373fe1 | |||
| 91ca883ccb | |||
| 362fd2e5b3 | |||
| 430061c0ff | |||
| 82393ccdc5 |
45 changed files with 1370 additions and 626 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -1 +1,7 @@
|
|||
.m2herd/
|
||||
|
||||
__pycache__/
|
||||
*.pyc
|
||||
.venv/
|
||||
uv.lock
|
||||
.pytest_cache/
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -18,6 +18,7 @@ from m2_market.catalog import CatalogClient
|
|||
from m2_market.config import Config, ConfigError, load_config
|
||||
from m2_market.ledger import InsufficientFunds, LedgerClient
|
||||
from m2_market.output import emit_json, format_price, render_kv, render_table, search_results_table
|
||||
from m2_market.publish import PublishValidationError, publish_bundle, validate_bundle
|
||||
from m2_market.registry import RegistryClient, RegistryError
|
||||
|
||||
# Exit-code map (contracts/cli.md).
|
||||
|
|
@ -304,8 +305,25 @@ def wallet(ctx: click.Context, operator: str | None) -> None:
|
|||
@click.argument("bundle_dir")
|
||||
@click.pass_context
|
||||
def publish(ctx: click.Context, bundle_dir: str) -> None:
|
||||
"""Validate a bundle and open a listing PR on the registry."""
|
||||
_not_implemented(ctx, "publish")
|
||||
"""Validate a bundle and open a listing PR on the registry (Story 2 step 1-2)."""
|
||||
config: Config = ctx.obj["config"]
|
||||
json_output = ctx.obj["json"]
|
||||
|
||||
try:
|
||||
solution, listing = validate_bundle(Path(bundle_dir))
|
||||
except PublishValidationError as exc:
|
||||
for line in exc.errors:
|
||||
click.echo(f"m2-market publish: {line}", err=True)
|
||||
ctx.exit(EXIT_VALIDATION)
|
||||
return
|
||||
|
||||
with RegistryClient(config.forgejo_url, config.forgejo_token) as registry:
|
||||
pr_url = publish_bundle(Path(bundle_dir), solution, listing, registry)
|
||||
|
||||
if json_output:
|
||||
emit_json({"status": "ok", "pr_url": pr_url})
|
||||
else:
|
||||
click.echo(pr_url)
|
||||
|
||||
|
||||
@main.command()
|
||||
|
|
|
|||
181
cli/src/m2_market/publish.py
Normal file
181
cli/src/m2_market/publish.py
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
"""Publish command implementation (contracts/cli.md publish, contracts/registry-layout.md).
|
||||
|
||||
Validates a bundle against the frozen schemas (schemas/*.json), packages
|
||||
payload/+recipe.yaml+solution.json into a release tarball, and runs the
|
||||
publish protocol against the registry: branch -> commit -> release -> PR.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
import tarfile
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
from jsonschema import Draft202012Validator
|
||||
|
||||
from m2_market.registry import RegistryClient
|
||||
|
||||
|
||||
class PublishValidationError(Exception):
|
||||
"""Raised when the bundle fails schema validation (contracts/cli.md exit 5)."""
|
||||
|
||||
def __init__(self, errors: list[str]):
|
||||
super().__init__("; ".join(errors))
|
||||
self.errors = errors
|
||||
|
||||
|
||||
def schemas_dir() -> Path:
|
||||
"""Resolve the frozen schemas dir, honoring the M2_MARKET_SCHEMAS_DIR override."""
|
||||
override = os.environ.get("M2_MARKET_SCHEMAS_DIR")
|
||||
if override:
|
||||
return Path(override)
|
||||
return Path(__file__).resolve().parents[3] / "schemas"
|
||||
|
||||
|
||||
def _load_json(path: Path) -> dict:
|
||||
with path.open(encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def _validate(instance: dict, schema_path: Path, label: str) -> list[str]:
|
||||
schema = _load_json(schema_path)
|
||||
validator = Draft202012Validator(schema)
|
||||
errors = []
|
||||
for err in sorted(validator.iter_errors(instance), key=lambda e: list(map(str, e.path))):
|
||||
loc = "/".join(str(p) for p in err.path) or "<root>"
|
||||
errors.append(f"{label}: {loc}: {err.message}")
|
||||
return errors
|
||||
|
||||
|
||||
def validate_bundle(bundle_dir: Path) -> tuple[dict, dict]:
|
||||
"""Validate BUNDLE_DIR/solution.json + listing.json against the frozen schemas.
|
||||
|
||||
Returns (solution, listing) on success; raises PublishValidationError
|
||||
(one message per violation, including tenant-firewall rules encoded in
|
||||
solution.schema.json's if/else) otherwise.
|
||||
"""
|
||||
solution_path = bundle_dir / "solution.json"
|
||||
listing_path = bundle_dir / "listing.json"
|
||||
|
||||
errors: list[str] = []
|
||||
solution: dict | None = None
|
||||
listing: dict | None = None
|
||||
|
||||
try:
|
||||
solution = _load_json(solution_path)
|
||||
except (OSError, json.JSONDecodeError) as exc:
|
||||
errors.append(f"solution.json: {exc}")
|
||||
try:
|
||||
listing = _load_json(listing_path)
|
||||
except (OSError, json.JSONDecodeError) as exc:
|
||||
errors.append(f"listing.json: {exc}")
|
||||
|
||||
if errors:
|
||||
raise PublishValidationError(errors)
|
||||
|
||||
schemas = schemas_dir()
|
||||
errors += _validate(solution, schemas / "solution.schema.json", "solution.json")
|
||||
errors += _validate(listing, schemas / "listing.schema.json", "listing.json")
|
||||
|
||||
if errors:
|
||||
raise PublishValidationError(errors)
|
||||
|
||||
return solution, listing
|
||||
|
||||
|
||||
def build_bundle_tarball(bundle_dir: Path, solution: dict, dest_path: Path) -> str:
|
||||
"""Tar payload/+recipe.yaml+solution.json into dest_path; return its sha256:<hex> hash."""
|
||||
payload_dir = bundle_dir / "payload"
|
||||
recipe_path = bundle_dir / "recipe.yaml"
|
||||
|
||||
with tarfile.open(dest_path, "w:gz") as tar:
|
||||
if payload_dir.is_dir():
|
||||
tar.add(payload_dir, arcname="payload")
|
||||
if recipe_path.is_file():
|
||||
tar.add(recipe_path, arcname="recipe.yaml")
|
||||
solution_bytes = json.dumps(solution, indent=2, sort_keys=True).encode("utf-8")
|
||||
info = tarfile.TarInfo(name="solution.json")
|
||||
info.size = len(solution_bytes)
|
||||
tar.addfile(info, io.BytesIO(solution_bytes))
|
||||
|
||||
digest = hashlib.sha256()
|
||||
with dest_path.open("rb") as fh:
|
||||
for chunk in iter(lambda: fh.read(65536), b""):
|
||||
digest.update(chunk)
|
||||
return f"sha256:{digest.hexdigest()}"
|
||||
|
||||
|
||||
def render_pr_body(solution: dict, listing: dict) -> str:
|
||||
"""PR template body (registry-layout.md publish protocol step 2)."""
|
||||
permissions = solution.get("permissions") or []
|
||||
permissions_lines = "\n".join(f"- `{perm}`" for perm in permissions) or "- (none)"
|
||||
price = solution.get("price") or {}
|
||||
tenant_scope = solution.get("tenant_scope", "-")
|
||||
|
||||
body = (
|
||||
f"## Evidence summary\n{listing.get('evidence_summary', '-')}\n\n"
|
||||
f"## Price\n{price.get('amount', '-')} {price.get('currency', '-')}\n\n"
|
||||
f"## Permissions\n{permissions_lines}\n\n"
|
||||
f"## Rollback\nRe-run `m2-market install` after uninstall; the apply adapter "
|
||||
f"restores pre-install backups (contracts/apply-adapter.md).\n"
|
||||
)
|
||||
|
||||
if tenant_scope != "m2-core":
|
||||
owner_initiated = bool(solution.get("owner_initiated"))
|
||||
double_scrubbed = bool((solution.get("scrub_status") or {}).get("double_scrubbed"))
|
||||
body += (
|
||||
"\n## Tenant-derived attestations\n"
|
||||
f"- [{'x' if owner_initiated else ' '}] owner_initiated\n"
|
||||
f"- [{'x' if double_scrubbed else ' '}] double_scrubbed\n"
|
||||
)
|
||||
|
||||
return body
|
||||
|
||||
|
||||
def publish_bundle(bundle_dir: Path, solution: dict, listing: dict, registry: RegistryClient) -> str:
|
||||
"""Run the publish protocol (branch -> commit -> release -> PR); returns the PR URL."""
|
||||
listing_id = listing["listing_id"]
|
||||
branch = f"listing/{listing_id}"
|
||||
install_ref = listing["install_ref"]
|
||||
|
||||
with tempfile.TemporaryDirectory(prefix="m2-market-publish-") as tmp_dir_str:
|
||||
tarball_path = Path(tmp_dir_str) / f"{install_ref}.tar.gz"
|
||||
content_hash = build_bundle_tarball(bundle_dir, solution, tarball_path)
|
||||
|
||||
solution = dict(solution)
|
||||
solution["content_hash"] = content_hash
|
||||
|
||||
registry.create_branch(branch)
|
||||
registry.create_file(
|
||||
f"listings/{listing_id}/listing.json",
|
||||
json.dumps(listing, indent=2, sort_keys=True).encode("utf-8") + b"\n",
|
||||
message=f"listing({listing_id}): add listing.json",
|
||||
branch=branch,
|
||||
)
|
||||
registry.create_file(
|
||||
f"listings/{listing_id}/solution.json",
|
||||
json.dumps(solution, indent=2, sort_keys=True).encode("utf-8") + b"\n",
|
||||
message=f"listing({listing_id}): add solution.json",
|
||||
branch=branch,
|
||||
)
|
||||
|
||||
release = registry.create_release(
|
||||
tag_name=install_ref,
|
||||
target_commitish=branch,
|
||||
name=install_ref,
|
||||
body=f"Bundle release for {listing_id}",
|
||||
)
|
||||
registry.upload_release_asset(release["id"], tarball_path.name, tarball_path.read_bytes())
|
||||
|
||||
pr = registry.create_pull_request(
|
||||
title=f"listing: {listing.get('name', listing_id)} ({listing_id})",
|
||||
body=render_pr_body(solution, listing),
|
||||
head=branch,
|
||||
base="main",
|
||||
)
|
||||
|
||||
return pr["html_url"]
|
||||
|
|
@ -84,6 +84,56 @@ class RegistryClient:
|
|||
|
||||
return dest_path
|
||||
|
||||
def create_branch(self, new_branch: str, old_branch: str = "main") -> dict:
|
||||
resp = self._client.post(
|
||||
self._repo_api("/branches"),
|
||||
json={"new_branch_name": new_branch, "old_branch_name": old_branch},
|
||||
)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def create_file(self, repo_path: str, content: bytes, message: str, branch: str) -> dict:
|
||||
resp = self._client.post(
|
||||
self._repo_api(f"/contents/{repo_path}"),
|
||||
json={
|
||||
"content": base64.b64encode(content).decode("ascii"),
|
||||
"message": message,
|
||||
"branch": branch,
|
||||
},
|
||||
)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def create_release(self, tag_name: str, target_commitish: str, name: str, body: str) -> dict:
|
||||
resp = self._client.post(
|
||||
self._repo_api("/releases"),
|
||||
json={
|
||||
"tag_name": tag_name,
|
||||
"target_commitish": target_commitish,
|
||||
"name": name,
|
||||
"body": body,
|
||||
},
|
||||
)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def upload_release_asset(self, release_id: int, filename: str, content: bytes) -> dict:
|
||||
resp = self._client.post(
|
||||
self._repo_api(f"/releases/{release_id}/assets"),
|
||||
params={"name": filename},
|
||||
files={"attachment": (filename, content, "application/gzip")},
|
||||
)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def create_pull_request(self, title: str, body: str, head: str, base: str = "main") -> dict:
|
||||
resp = self._client.post(
|
||||
self._repo_api("/pulls"),
|
||||
json={"title": title, "body": body, "head": head, "base": base},
|
||||
)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
@staticmethod
|
||||
def verify_bundle(path: str | Path, content_hash: str) -> bool:
|
||||
algo, _, expected = content_hash.partition(":")
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
161
cli/tests/test_publish.py
Normal file
161
cli/tests/test_publish.py
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
"""Inline verification for the publish CLI command (contracts/cli.md, registry-layout.md).
|
||||
|
||||
Covers: (1) invalid bundle -> schema errors printed, exit 5, before any registry
|
||||
call; (2) valid bundle -> happy-path branch/commit/release/PR sequence against
|
||||
a MockTransport fake of the Forgejo API.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
from click.testing import CliRunner
|
||||
|
||||
import m2_market.cli as cli_mod
|
||||
|
||||
LISTING_ID = "lst_mm-pdf-report"
|
||||
SOLUTION_ID = "sol_mm-pdf-report"
|
||||
INSTALL_REF = "lst_mm-pdf-report-v1.0.0"
|
||||
SELLER = "sdjs-operator"
|
||||
|
||||
VALID_SOLUTION = {
|
||||
"schema_version": "m2.solution.v1",
|
||||
"solution_id": SOLUTION_ID,
|
||||
"name": "MM PDF Branded Report",
|
||||
"summary": "Generate branded PDF reports from Markdown",
|
||||
"intent": "Produce publish-ready branded PDF output without manual design work",
|
||||
"deployment": {
|
||||
"recipe_ref": "recipes/mm-pdf-report/recipe.yaml",
|
||||
"entrypoint": "skills/mm-pdf/render.py",
|
||||
"verify_command": "python skills/mm-pdf/render.py --self-test",
|
||||
},
|
||||
"applicability": {"image_classes": ["desktop-agent"]},
|
||||
"tenant_scope": "m2-core",
|
||||
"evidence": [{"source": "session:2026-05-11-mm-pdf-branded-report"}],
|
||||
"content_hash": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"price": {"amount": 500, "currency": "m2cr", "model": "fixed"},
|
||||
"seller": SELLER,
|
||||
"license": {"terms": "internal", "major_version_coverage": True},
|
||||
"permissions": [{"scope": "filesystem:write", "path": "/tmp/mm-pdf-output"}],
|
||||
}
|
||||
|
||||
VALID_LISTING = {
|
||||
"schema_version": "m2.listing.v1",
|
||||
"listing_id": LISTING_ID,
|
||||
"solution_id": SOLUTION_ID,
|
||||
"solution_version": "1.0.0",
|
||||
"inventory_type": "solution",
|
||||
"name": "MM PDF Branded Report",
|
||||
"summary": "Generate branded PDF reports from Markdown",
|
||||
"category": "reporting",
|
||||
"price": {"amount": 500, "currency": "m2cr", "model": "fixed"},
|
||||
"seller": SELLER,
|
||||
"evidence_summary": "Generated branded PDF report; operator confirmed styling matched brand deck.",
|
||||
"tenant_visibility": ["*"],
|
||||
"stats": {"installs": 0, "proposals_shown": 0, "proposals_accepted": 0},
|
||||
"status": "draft",
|
||||
"install_ref": INSTALL_REF,
|
||||
}
|
||||
|
||||
|
||||
def _write_bundle(bundle_dir, solution=None, listing=None):
|
||||
bundle_dir.mkdir(parents=True, exist_ok=True)
|
||||
(bundle_dir / "solution.json").write_text(json.dumps(solution if solution is not None else VALID_SOLUTION))
|
||||
(bundle_dir / "listing.json").write_text(json.dumps(listing if listing is not None else VALID_LISTING))
|
||||
payload_dir = bundle_dir / "payload"
|
||||
payload_dir.mkdir(exist_ok=True)
|
||||
(payload_dir / "report.md").write_text("# hello\n")
|
||||
(bundle_dir / "recipe.yaml").write_text("targets: []\nchecks: []\n")
|
||||
return bundle_dir
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def config_env(tmp_path, monkeypatch):
|
||||
config_path = tmp_path / "config.toml"
|
||||
config_path.write_text(
|
||||
"""
|
||||
operator_id = "buyer1"
|
||||
tenant = "test-tenant"
|
||||
ledger_url = "https://ledger.test"
|
||||
ledger_api_key = "lk"
|
||||
memory_api_url = "https://catalog.test"
|
||||
memory_api_key = "mk"
|
||||
forgejo_url = "https://registry.test"
|
||||
forgejo_token = "rt"
|
||||
"""
|
||||
)
|
||||
monkeypatch.setenv("M2_MARKET_CONFIG", str(config_path))
|
||||
monkeypatch.setenv("M2_MARKET_SCHEMAS_DIR", str(_repo_schemas_dir()))
|
||||
return config_path
|
||||
|
||||
|
||||
def _repo_schemas_dir():
|
||||
from pathlib import Path
|
||||
|
||||
return Path(__file__).resolve().parents[2] / "schemas"
|
||||
|
||||
|
||||
def test_invalid_bundle_fails_validation_before_any_network_call(tmp_path, config_env, monkeypatch):
|
||||
def fail_if_called(*args, **kwargs):
|
||||
raise AssertionError("registry must not be contacted when validation fails")
|
||||
|
||||
monkeypatch.setattr(httpx.Client, "post", fail_if_called)
|
||||
|
||||
bad_solution = dict(VALID_SOLUTION)
|
||||
bad_solution["evidence"] = [] # violates evidence minItems (Principle III evidence-backed listings)
|
||||
bundle_dir = _write_bundle(tmp_path / "bundle", solution=bad_solution)
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli_mod.main, ["publish", str(bundle_dir)])
|
||||
|
||||
assert result.exit_code == cli_mod.EXIT_VALIDATION, result.output
|
||||
assert "evidence" in result.output
|
||||
|
||||
|
||||
def test_publish_happy_path_opens_pr(tmp_path, config_env, monkeypatch):
|
||||
calls = {"branch": 0, "files": [], "release": 0, "asset": 0, "pr": 0}
|
||||
|
||||
def handler(request: httpx.Request) -> httpx.Response:
|
||||
path = request.url.path
|
||||
if path.endswith("/branches") and request.method == "POST":
|
||||
calls["branch"] += 1
|
||||
return httpx.Response(201, json={"name": f"listing/{LISTING_ID}"})
|
||||
if "/contents/" in path and request.method == "POST":
|
||||
calls["files"].append(path)
|
||||
return httpx.Response(201, json={"content": {"path": path}})
|
||||
if path.endswith("/releases") and request.method == "POST":
|
||||
calls["release"] += 1
|
||||
return httpx.Response(201, json={"id": 42, "tag_name": INSTALL_REF})
|
||||
if path.endswith("/releases/42/assets") and request.method == "POST":
|
||||
calls["asset"] += 1
|
||||
return httpx.Response(201, json={"name": f"{INSTALL_REF}.tar.gz"})
|
||||
if path.endswith("/pulls") and request.method == "POST":
|
||||
calls["pr"] += 1
|
||||
return httpx.Response(
|
||||
201,
|
||||
json={"html_url": f"https://registry.test/m2/market-registry/pulls/7"},
|
||||
)
|
||||
raise AssertionError(f"unexpected request: {request.method} {request.url}")
|
||||
|
||||
orig_init = httpx.Client.__init__
|
||||
|
||||
def patched_init(self, *args, **kwargs):
|
||||
kwargs["transport"] = httpx.MockTransport(handler)
|
||||
orig_init(self, *args, **kwargs)
|
||||
|
||||
monkeypatch.setattr(httpx.Client, "__init__", patched_init)
|
||||
|
||||
bundle_dir = _write_bundle(tmp_path / "bundle")
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli_mod.main, ["publish", str(bundle_dir)])
|
||||
|
||||
assert result.exit_code == 0, result.output
|
||||
assert "https://registry.test/m2/market-registry/pulls/7" in result.output
|
||||
assert calls["branch"] == 1
|
||||
assert len(calls["files"]) == 2
|
||||
assert calls["release"] == 1
|
||||
assert calls["asset"] == 1
|
||||
assert calls["pr"] == 1
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
26
solutions/agent-scaffold/listing.json
Normal file
26
solutions/agent-scaffold/listing.json
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"schema_version": "m2.listing.v1",
|
||||
"listing_id": "lst_agent-scaffold",
|
||||
"solution_id": "sol_agent-scaffold",
|
||||
"solution_version": "1.0.0",
|
||||
"inventory_type": "solution",
|
||||
"name": "Agent Scaffold Generator",
|
||||
"summary": "Scaffold OpenClaw/Hermes agent workspaces (PRD.md + SOUL.md + MEMORY.md) from m2-memory context.",
|
||||
"category": "agent-tooling",
|
||||
"keywords": ["agent", "scaffold", "openclaw", "hermes", "prd", "soul", "memory"],
|
||||
"price": {
|
||||
"amount": 60,
|
||||
"currency": "m2cr",
|
||||
"model": "fixed"
|
||||
},
|
||||
"seller": "sdjs-operator",
|
||||
"evidence_summary": "Skill in production use on the m2 host since 2026-04-20, extracted from a real workflow: four PRD.md/SOUL.md agent workspaces at /home/m2/gmi-clinic/agents/ (GMI Clinic fleet deployment) created within a minute of SKILL.md's own mtime, plus three more SOUL.md digital-twin identities at /home/m2/agent-restore-harness/agents/ from 2026-04-22/23 confirming continued production use. Requires buyer-side memory-api access for full function.",
|
||||
"tenant_visibility": ["*"],
|
||||
"stats": {
|
||||
"installs": 0,
|
||||
"proposals_shown": 0,
|
||||
"proposals_accepted": 0
|
||||
},
|
||||
"status": "draft",
|
||||
"install_ref": "lst_agent-scaffold-v1.0.0"
|
||||
}
|
||||
41
solutions/agent-scaffold/payload/SKILL.md
Normal file
41
solutions/agent-scaffold/payload/SKILL.md
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
---
|
||||
name: agent-scaffold
|
||||
description: Scaffolds OpenClaw/Hermes agent workspaces from m2-memory. Query memory for context, generate PRD.md + SOUL.md for a new agent, and optionally wire into the fleet.
|
||||
---
|
||||
|
||||
# agent-scaffold
|
||||
|
||||
Generate a complete agent workspace (PRD + SOUL + MEMORY seed) from context in m2-memory.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/agent-scaffold <agent-name> "<what this agent does>"
|
||||
```
|
||||
|
||||
Examples:
|
||||
```
|
||||
/agent-scaffold gesy-rates-fetcher "Fetches and monitors GESY reimbursement rate updates for GMI Clinic"
|
||||
/agent-scaffold platform-unifier "Maps and unifies the 3-5 GMI Clinic software platforms into Machine.Machine"
|
||||
/agent-scaffold nasr-research-runner "Runs parallel deep research tasks for Nasr's healthcare domain work"
|
||||
```
|
||||
|
||||
## What it produces
|
||||
|
||||
For each agent, the skill:
|
||||
|
||||
1. **Queries m2-memory** for relevant context (entity/project history, related agents, decisions)
|
||||
2. **Generates `PRD.md`** — problem, personas, functional requirements, success metrics, open items
|
||||
3. **Generates `SOUL.md`** — agent identity, values, communication style, scope boundaries
|
||||
4. **Generates `MEMORY.md`** — seed memories pre-loaded from m2-memory search results
|
||||
5. **Prints a deploy snippet** — `docker run` or Coolify env vars to spawn the agent
|
||||
|
||||
## Output location
|
||||
|
||||
`~/agents/<agent-name>/` — commit to `git.machinemachine.ai/machine.machine/specs/` when ready.
|
||||
|
||||
## Design principle
|
||||
|
||||
The goal is reproducibility: if an agent's context is lost (like Nasr's Apr 8 research agents),
|
||||
this skill can reconstruct the workspace from the vector store and hand it to OpenClaw or Hermes
|
||||
to re-execute without starting from scratch.
|
||||
162
solutions/agent-scaffold/payload/scripts/scaffold.py
Executable file
162
solutions/agent-scaffold/payload/scripts/scaffold.py
Executable file
|
|
@ -0,0 +1,162 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
agent-scaffold — generate PRD.md + SOUL.md + MEMORY.md for a new agent
|
||||
from m2-memory context.
|
||||
|
||||
Usage:
|
||||
python3 scaffold.py <agent-name> "<description>"
|
||||
python3 scaffold.py gesy-rates-fetcher "Monitors GESY rates for GMI Clinic DRG billing"
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
|
||||
MEMORY_API = os.environ.get("M2_MEMORY_API_URL", "http://172.18.0.20:8000")
|
||||
AGENT_ID = os.environ.get("M2_MEMORY_AGENT_ID", "m2")
|
||||
API_KEY = os.environ.get("M2_MEMORY_API_KEY")
|
||||
OUT_BASE = Path.home() / "agents"
|
||||
|
||||
|
||||
def search_memory(query: str, limit: int = 10) -> list[dict]:
|
||||
url = f"{MEMORY_API}/memory/search"
|
||||
body = json.dumps({
|
||||
"query": query,
|
||||
"agent_id": AGENT_ID,
|
||||
"routing_strategy": "deep",
|
||||
"limit": limit,
|
||||
}).encode()
|
||||
headers = {"Content-Type": "application/json"}
|
||||
if API_KEY:
|
||||
headers["X-API-Key"] = API_KEY
|
||||
req = urllib.request.Request(url, data=body, headers=headers, method="POST")
|
||||
with urllib.request.urlopen(req, timeout=30) as r:
|
||||
return json.loads(r.read()).get("results", [])
|
||||
|
||||
|
||||
def fmt_memory_block(results: list[dict]) -> str:
|
||||
lines = []
|
||||
for r in results:
|
||||
ts = (r.get("timestamp") or "")[:10]
|
||||
score = r.get("score", 0)
|
||||
content = (r.get("content") or "").replace("\n", " ")[:200]
|
||||
lines.append(f"- [{ts} score={score:.2f}] {content}")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def generate_prd(name: str, description: str, memories: list[dict]) -> str:
|
||||
mem_block = fmt_memory_block(memories)
|
||||
return f"""# {name.replace("-", " ").title()} — PRD
|
||||
|
||||
**Agent ID:** {name}
|
||||
**Description:** {description}
|
||||
**Generated from:** m2-memory search ({len(memories)} relevant memories)
|
||||
|
||||
---
|
||||
|
||||
## Problem
|
||||
|
||||
> TODO: Refine based on memory context below
|
||||
|
||||
{description}
|
||||
|
||||
## Relevant Memory Context
|
||||
|
||||
{mem_block}
|
||||
|
||||
## Personas
|
||||
|
||||
| Persona | Goal |
|
||||
|---------|------|
|
||||
| TODO | TODO |
|
||||
|
||||
## Functional Requirements
|
||||
|
||||
1. TODO — derived from memory context above
|
||||
2.
|
||||
3.
|
||||
|
||||
## Success Metrics
|
||||
|
||||
- TODO
|
||||
|
||||
## Open Items
|
||||
|
||||
- TODO — check memory for unresolved gaps
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- Agent runtime: OpenClaw / Hermes
|
||||
- Memory: m2-memory (agent_id={name})
|
||||
- Deploy: Coolify stack on Machine.Machine fleet
|
||||
"""
|
||||
|
||||
|
||||
def generate_soul(name: str, description: str) -> str:
|
||||
title = name.replace("-", " ").title()
|
||||
return f"""# {title} — Agent Identity
|
||||
|
||||
You are **{title}**, part of the Machine.Machine agent fleet.
|
||||
|
||||
{description}
|
||||
|
||||
## Values
|
||||
- TODO: define 3 core values for this agent
|
||||
|
||||
## Communication style
|
||||
- TODO: define tone and output format
|
||||
|
||||
## Scope boundaries
|
||||
- You do not TODO
|
||||
- You do not TODO
|
||||
"""
|
||||
|
||||
|
||||
def generate_memory_seed(memories: list[dict]) -> str:
|
||||
lines = ["# Seed Memories\n",
|
||||
"These memories are pre-loaded from m2-memory at agent creation time.\n"]
|
||||
for r in memories[:10]:
|
||||
ts = (r.get("timestamp") or "")[:19]
|
||||
mtype = r.get("memory_type", "semantic")
|
||||
content = (r.get("content") or "").strip()[:500]
|
||||
lines.append(f"## [{mtype} {ts}]\n{content}\n")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main():
|
||||
p = argparse.ArgumentParser()
|
||||
p.add_argument("name", help="agent slug (e.g. gesy-rates-fetcher)")
|
||||
p.add_argument("description", help="one-line description of what the agent does")
|
||||
p.add_argument("--out", default=None, help="output directory (default: ~/agents/<name>)")
|
||||
p.add_argument("--limit", type=int, default=10, help="memory search limit")
|
||||
args = p.parse_args()
|
||||
|
||||
out_dir = Path(args.out) if args.out else OUT_BASE / args.name
|
||||
out_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
print(f"Searching m2-memory for: {args.description}", file=sys.stderr)
|
||||
try:
|
||||
memories = search_memory(args.description, args.limit)
|
||||
print(f" Found {len(memories)} relevant memories", file=sys.stderr)
|
||||
except Exception as e:
|
||||
print(f" Memory search failed ({e}) — generating without context", file=sys.stderr)
|
||||
memories = []
|
||||
|
||||
(out_dir / "PRD.md").write_text(generate_prd(args.name, args.description, memories))
|
||||
(out_dir / "SOUL.md").write_text(generate_soul(args.name, args.description))
|
||||
(out_dir / "MEMORY.md").write_text(generate_memory_seed(memories))
|
||||
|
||||
print(f"\nScaffolded: {out_dir}")
|
||||
print(f" PRD.md — {(out_dir / 'PRD.md').stat().st_size} bytes")
|
||||
print(f" SOUL.md — {(out_dir / 'SOUL.md').stat().st_size} bytes")
|
||||
print(f" MEMORY.md — {(out_dir / 'MEMORY.md').stat().st_size} bytes")
|
||||
print(f"\nNext: review + fill TODOs, then commit to git.machinemachine.ai/machine.machine/specs/")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
13
solutions/agent-scaffold/recipe.yaml
Normal file
13
solutions/agent-scaffold/recipe.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# agent-scaffold install recipe (apply-adapter.md bundle layout, local adapter v1)
|
||||
# Places the agent-scaffold skill into the buyer's Claude Code skills directory.
|
||||
targets:
|
||||
- src: SKILL.md
|
||||
dest: ~/.claude/skills/agent-scaffold/SKILL.md
|
||||
- src: scripts/scaffold.py
|
||||
dest: ~/.claude/skills/agent-scaffold/scripts/scaffold.py
|
||||
checks:
|
||||
- cmd: test -f ~/.claude/skills/agent-scaffold/SKILL.md
|
||||
expect_exit: 0
|
||||
- cmd: test -x ~/.claude/skills/agent-scaffold/scripts/scaffold.py
|
||||
expect_exit: 0
|
||||
entrypoint: "Ask your agent to use the agent-scaffold skill, or run: python3 ~/.claude/skills/agent-scaffold/scripts/scaffold.py <agent-name> \"<description>\""
|
||||
98
solutions/agent-scaffold/solution.json
Normal file
98
solutions/agent-scaffold/solution.json
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
{
|
||||
"schema_version": "m2.solution.v1",
|
||||
"solution_id": "sol_agent-scaffold",
|
||||
"name": "Agent Scaffold Generator",
|
||||
"summary": "Scaffold OpenClaw/Hermes agent workspaces (PRD.md + SOUL.md + MEMORY.md) from m2-memory context.",
|
||||
"description": "Installs the agent-scaffold skill: given an agent name and a one-line description, it queries m2-memory (agent.memory.system / memory-api) for relevant context and generates a complete agent workspace — PRD.md (problem, personas, functional requirements, success metrics), SOUL.md (identity, values, communication style, scope boundaries), and MEMORY.md (seed memories pre-loaded from the search results) — plus a deploy snippet for OpenClaw or Hermes. Ships two artifacts: SKILL.md and scripts/scaffold.py (a single-file Python script using only the stdlib, talking HTTP to memory-api). Requirement: the buyer machine needs memory-api (m2-memory) network access for full function — scripts/scaffold.py calls M2_MEMORY_API_URL (default http://172.18.0.20:8000, override via env) at /memory/search. Without reachable memory-api the script still runs and produces PRD.md/SOUL.md, but with an empty 'Relevant Memory Context' section and no MEMORY.md content — degraded, not blocked. content_hash is computed over payload/ + recipe.yaml only (not solution.json itself, to avoid the self-referential hash problem of hashing a file that contains its own hash): sha256 of `tar --sort=name --mtime='@0' --owner=0 --group=0 --numeric-owner -czf - payload recipe.yaml` run from this bundle's root.",
|
||||
"intent": "Give an operator a reproducible way to stand up (or reconstruct) a new agent's working context — PRD + identity + seed memory — from what the fleet's memory system already knows, instead of starting from a blank page.",
|
||||
"behavior": {
|
||||
"skill_ref": "payload/SKILL.md"
|
||||
},
|
||||
"tools": [
|
||||
{
|
||||
"name": "memory-api",
|
||||
"kind": "http-api",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "python3",
|
||||
"kind": "cli",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"runtime": {
|
||||
"surfaces": [
|
||||
"claude-code-skill"
|
||||
]
|
||||
},
|
||||
"permissions": [
|
||||
{
|
||||
"action": "write",
|
||||
"target": "~/.claude/skills/agent-scaffold/"
|
||||
},
|
||||
{
|
||||
"action": "write",
|
||||
"target": "~/agents/<agent-name>/ (PRD.md, SOUL.md, MEMORY.md — output of running the skill, not part of the install)"
|
||||
},
|
||||
{
|
||||
"action": "net",
|
||||
"target": "HTTP POST to the configured M2_MEMORY_API_URL /memory/search endpoint"
|
||||
}
|
||||
],
|
||||
"deployment": {
|
||||
"recipe_ref": "recipe.yaml",
|
||||
"entrypoint": "Ask your agent to use the agent-scaffold skill, or run: python3 ~/.claude/skills/agent-scaffold/scripts/scaffold.py <agent-name> \"<description>\"",
|
||||
"verify_command": "test -f ~/.claude/skills/agent-scaffold/SKILL.md"
|
||||
},
|
||||
"applicability": {
|
||||
"image_classes": [
|
||||
"primus",
|
||||
"agent-latest"
|
||||
],
|
||||
"roles": [
|
||||
"operator",
|
||||
"desktop-agent"
|
||||
],
|
||||
"tool_requirements": [
|
||||
"python3",
|
||||
"memory-api"
|
||||
]
|
||||
},
|
||||
"tenant_scope": "m2-core",
|
||||
"evidence": [
|
||||
{
|
||||
"source": "/home/m2/.claude/skills/agent-scaffold/ (SKILL.md, scripts/scaffold.py) — the proven skill this bundle packages, present on the m2 host since 2026-04-20 (SKILL.md mtime 2026-04-20T22:48:00+02:00, scripts/scaffold.py mtime 2026-04-28T00:33:10+02:00 — a later revision of the same script)",
|
||||
"machine": "m2",
|
||||
"excerpt": "SKILL.md frontmatter: 'Scaffolds OpenClaw/Hermes agent workspaces from m2-memory. Query memory for context, generate PRD.md + SOUL.md for a new agent, and optionally wire into the fleet.'"
|
||||
},
|
||||
{
|
||||
"source": "/home/m2/gmi-clinic/agents/{admin-data-bridge,clinical-entity-extraction,drg-los-optimizer}/{PRD.md,SOUL.md} — three real PRD+SOUL agent-workspace pairs on disk, all created 2026-04-20 22:46:27–22:47:19 (mtimes), roughly one minute before this skill's own SKILL.md mtime (22:48:00) — the exact PRD.md/SOUL.md workspace shape this skill formalizes and automates, produced for the GMI Clinic AI fleet deployment immediately prior to the skill being written",
|
||||
"machine": "m2",
|
||||
"excerpt": "admin-data-bridge/SOUL.md: 'You are the Admin Data Bridge for GMI Clinic... ## Values ## Communication style ## Scope boundaries' — same section structure generate_soul() in scaffold.py emits"
|
||||
},
|
||||
{
|
||||
"source": "/home/m2/gmi-clinic/agents/gesy-research/PRD.md — a fourth real workspace, mtime 2026-04-20T22:47:48+02:00, whose own text names the exact incident SKILL.md's 'Design principle' section cites as the skill's reason for existing: 'On 2026-04-08, Nasr ran 4 parallel research agents on his machine... The output was intended to be stored in m2-memory, Planka, and Forgejo but the storage step failed (m2 errored). This PRD reconstructs the agent's purpose and gaps so the research can be completed and properly stored.'",
|
||||
"machine": "m2",
|
||||
"excerpt": "SKILL.md: 'The goal is reproducibility: if an agent's context is lost (like Nasr's Apr 8 research agents), this skill can reconstruct the workspace from the vector store and hand it to OpenClaw or Hermes to re-execute without starting from scratch.'"
|
||||
},
|
||||
{
|
||||
"source": "/home/m2/agent-restore-harness/agents/*/SOUL.md — three further real SOUL.md agent-identity files for actual named fleet agents (machine names withheld from shared catalog per tenant-firewall hygiene), mtimes 2026-04-22T23:41–2026-04-23T00:48, confirming the PRD+SOUL workspace pattern stayed in production use after the skill was written, not a one-off",
|
||||
"machine": "m2",
|
||||
"excerpt": "nasr/SOUL.md: 'You are Nasr's digital twin — his AI counterpart in the Machine.Machine fleet... ## Core Capabilities'"
|
||||
}
|
||||
],
|
||||
"content_hash": "sha256:202aaff5519e774e2669bd2ca6220fc67284a506775a90ff7710fb2361cc58ee",
|
||||
"price": {
|
||||
"amount": 60,
|
||||
"currency": "m2cr",
|
||||
"model": "fixed"
|
||||
},
|
||||
"seller": "sdjs-operator",
|
||||
"license": {
|
||||
"terms": "Perpetual use on operator-owned machines for the buyer's own agent-workspace generation; no redistribution of the skill files as a standalone product.",
|
||||
"major_version_coverage": true
|
||||
},
|
||||
"revenue_split": {
|
||||
"platform_pct": 10
|
||||
}
|
||||
}
|
||||
26
solutions/mm-pdf-report/listing.json
Normal file
26
solutions/mm-pdf-report/listing.json
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"schema_version": "m2.listing.v1",
|
||||
"listing_id": "lst_mm-pdf-report",
|
||||
"solution_id": "sol_mm-pdf-report",
|
||||
"solution_version": "1.0.0",
|
||||
"inventory_type": "solution",
|
||||
"name": "MM PDF Report Generator",
|
||||
"summary": "Generate Machine.Machine branded PDF reports and slide decks from Markdown.",
|
||||
"category": "document-generation",
|
||||
"keywords": ["pdf", "branding", "markdown", "reports", "decks"],
|
||||
"price": {
|
||||
"amount": 40,
|
||||
"currency": "m2cr",
|
||||
"model": "fixed"
|
||||
},
|
||||
"seller": "sdjs-operator",
|
||||
"evidence_summary": "Skill in production use on the m2 host since 2026-04-21; two real generated PDF/HTML pairs on disk (session-2026-04-20.pdf, spark-cluster-old/fabric-setup.pdf) confirm the pipeline works end-to-end.",
|
||||
"tenant_visibility": ["*"],
|
||||
"stats": {
|
||||
"installs": 0,
|
||||
"proposals_shown": 0,
|
||||
"proposals_accepted": 0
|
||||
},
|
||||
"status": "draft",
|
||||
"install_ref": "lst_mm-pdf-report-v1.0.0"
|
||||
}
|
||||
89
solutions/mm-pdf-report/payload/SKILL.md
Normal file
89
solutions/mm-pdf-report/payload/SKILL.md
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
---
|
||||
name: mm-pdf
|
||||
description: Generate beautifully styled Machine.Machine branded PDFs and slide decks from Markdown. Dark navy aesthetic, cyan accents, professional A4 layout. Uses a headless-Chrome render container (any container with Node + Chrome, e.g. a "*-m2o" agent-desktop image) or a local WeasyPrint fallback. Produces PDF + HTML output.
|
||||
---
|
||||
|
||||
# mm-pdf
|
||||
|
||||
Generate MM-branded documents from Markdown content.
|
||||
|
||||
## Design system
|
||||
|
||||
| Token | Value | Use |
|
||||
|-------|-------|-----|
|
||||
| Cover background | `#0a0e1a` | Dark navy |
|
||||
| Primary accent | `#4bb8d4` | Cyan — headings, kickers, borders |
|
||||
| Section banners | `#3d4550` | Slate grey |
|
||||
| Purple sidebar | `#6b46c1` | Alt cover variant |
|
||||
| Body text | `#e2e8f0` | Light grey on dark bg |
|
||||
| Body background | `#111827` | Dark page bg |
|
||||
| Code/data blocks | `#1e2533` | Slightly lighter navy |
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# Generate PDF from markdown
|
||||
mm-pdf generate input.md [--out output.pdf] [--style dark|purple|light]
|
||||
|
||||
# Generate slide deck (Marp)
|
||||
mm-pdf slides input.md [--out output.pdf]
|
||||
|
||||
# With explicit container (auto-discovery picks the first "*m2o*" container if omitted)
|
||||
mm-pdf generate input.md --container <your-render-container-name>
|
||||
```
|
||||
|
||||
## Pipeline
|
||||
|
||||
1. **MD → HTML** — a small Node script (via `marked`) renders Markdown into full MM-styled
|
||||
HTML. Extracts YAML frontmatter (`title`, `subtitle`, `date`, `client`) for the cover
|
||||
page. Strips the first `# H1` to use as title if no frontmatter is present.
|
||||
2. **HTML → PDF** — Chrome headless renders the HTML to PDF (`--print-to-pdf`).
|
||||
|
||||
Both outputs are saved alongside the input file.
|
||||
|
||||
## Output
|
||||
|
||||
- `<name>.html` — standalone styled HTML (preview, shareable)
|
||||
- `<name>.pdf` — print-ready PDF
|
||||
|
||||
## Styles
|
||||
|
||||
| Style | Cover | Use case |
|
||||
|-------|-------|----------|
|
||||
| `dark` | Navy `#0a0e1a` + cyan accent | Technical specs, deployment docs |
|
||||
| `purple` | Purple sidebar `#6b46c1` | Partner decks |
|
||||
| `light` | White + navy header | Client-facing docs |
|
||||
|
||||
`dark.css` and `purple.css` ship in `templates/`. `light` is documented for forward
|
||||
compatibility but has no template in this bundle yet — add `templates/light.css` locally
|
||||
if you need it (it will be picked up automatically; `generate.sh` falls back to `dark.css`
|
||||
for any missing style file).
|
||||
|
||||
## Components (in Markdown)
|
||||
|
||||
```markdown
|
||||
<!-- KPI card row -->
|
||||
<div class="kpi-row">
|
||||
<div class="kpi">**€5K** setup</div>
|
||||
<div class="kpi">**€2K**/mo</div>
|
||||
<div class="kpi">**8 weeks** pilot</div>
|
||||
</div>
|
||||
|
||||
<!-- Section kicker -->
|
||||
<span class="kicker">DEPLOYMENT ARCHITECTURE</span>
|
||||
|
||||
<!-- Warning/callout -->
|
||||
<div class="callout">⚠️ Open item: integration path TBD</div>
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- Docker, with a running container that has Node.js + Google Chrome (headless) installed
|
||||
and reachable via `docker exec`/`docker cp` from the host running this skill. Any
|
||||
container name is fine — `scripts/generate.sh` auto-discovers the first container whose
|
||||
name matches `nasr-m2o|m2o`, or accepts `--container <name>` to target any other
|
||||
container that meets the Node+Chrome requirement.
|
||||
- `docker` CLI available on the host invoking `mm-pdf`.
|
||||
|
||||
No absolute host paths, hostnames, or client-identifying data are baked into this skill —
|
||||
`--container` and the input Markdown path are the only machine-specific inputs at run time.
|
||||
145
solutions/mm-pdf-report/payload/scripts/generate.sh
Executable file
145
solutions/mm-pdf-report/payload/scripts/generate.sh
Executable file
|
|
@ -0,0 +1,145 @@
|
|||
#!/usr/bin/env bash
|
||||
# mm-pdf generate — render Markdown → HTML → PDF using nasr-m2o container
|
||||
set -euo pipefail
|
||||
|
||||
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
STYLE="${MM_PDF_STYLE:-dark}"
|
||||
OUT=""
|
||||
OUT_HTML=""
|
||||
CONTAINER=""
|
||||
INPUT=""
|
||||
|
||||
usage() {
|
||||
echo "Usage: mm-pdf generate <input.md> [--out output.pdf] [--style dark|purple|light] [--container NAME]"
|
||||
exit 1
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--out) OUT="$2"; shift 2 ;;
|
||||
--style) STYLE="$2"; shift 2 ;;
|
||||
--container) CONTAINER="$2"; shift 2 ;;
|
||||
--help|-h) usage ;;
|
||||
*) INPUT="$1"; shift ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -z "$INPUT" ]] && usage
|
||||
[[ ! -f "$INPUT" ]] && { echo "Error: $INPUT not found"; exit 1; }
|
||||
|
||||
INPUT_ABS="$(realpath "$INPUT")"
|
||||
BASENAME="${INPUT_ABS%.md}"
|
||||
OUT="${OUT:-${BASENAME}.pdf}"
|
||||
OUT_ABS="$(realpath -m "$OUT")"
|
||||
OUT_HTML_ABS="${OUT_ABS%.pdf}.html"
|
||||
|
||||
# Auto-discover container
|
||||
if [[ -z "$CONTAINER" ]]; then
|
||||
CONTAINER=$(docker ps --format "{{.Names}}" | grep -E "nasr-m2o|m2o" | head -1)
|
||||
[[ -z "$CONTAINER" ]] && { echo "Error: no m2o container running. Start nasr-m2o or pass --container"; exit 1; }
|
||||
fi
|
||||
echo "Using container: $CONTAINER"
|
||||
|
||||
# Copy files into container
|
||||
TMP="/tmp/mm-pdf-$$"
|
||||
docker exec "$CONTAINER" mkdir -p "$TMP"
|
||||
docker cp "$INPUT_ABS" "$CONTAINER:$TMP/input.md"
|
||||
|
||||
if [[ -f "$SKILL_DIR/templates/${STYLE}.css" ]]; then
|
||||
docker cp "$SKILL_DIR/templates/${STYLE}.css" "$CONTAINER:$TMP/style.css"
|
||||
else
|
||||
docker cp "$SKILL_DIR/templates/dark.css" "$CONTAINER:$TMP/style.css"
|
||||
fi
|
||||
|
||||
# Step 1: Markdown → styled HTML (via Node/marked)
|
||||
echo "Step 1: Converting Markdown → HTML..."
|
||||
docker exec "$CONTAINER" bash -c "
|
||||
cd $TMP
|
||||
# Install marked locally in tmp dir so require() can find it
|
||||
[ -d node_modules/marked ] || npm install marked --prefix . -q 2>/dev/null
|
||||
|
||||
node - <<'JSEOF'
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { marked } = require('marked');
|
||||
|
||||
const mdRaw = fs.readFileSync('input.md', 'utf8');
|
||||
const css = fs.readFileSync('style.css', 'utf8');
|
||||
|
||||
// Strip YAML frontmatter
|
||||
let body = mdRaw;
|
||||
const fm = {};
|
||||
const fmMatch = mdRaw.match(/^---\s*\n([\s\S]*?)\n---\s*\n/);
|
||||
if (fmMatch) {
|
||||
fmMatch[1].split('\n').forEach(line => {
|
||||
const i = line.indexOf(':');
|
||||
if (i > 0) fm[line.slice(0,i).trim().toLowerCase()] = line.slice(i+1).trim();
|
||||
});
|
||||
body = mdRaw.slice(fmMatch[0].length);
|
||||
}
|
||||
|
||||
// Extract first H1 as title
|
||||
let title = fm.title || '';
|
||||
if (!title) {
|
||||
const h1 = body.match(/^#\s+(.+)$/m);
|
||||
if (h1) { title = h1[1].trim(); body = body.replace(h1[0], ''); }
|
||||
}
|
||||
title = title || 'Machine.Machine';
|
||||
const subtitle = fm.subtitle || fm.description || '';
|
||||
const dateLine = [fm.client, fm.date].filter(Boolean).join(' \u00a0·\u00a0 ');
|
||||
|
||||
marked.setOptions({ gfm: true, breaks: false });
|
||||
const contentHtml = marked.parse(body);
|
||||
|
||||
const coverHtml = \`<div class=\"cover\">
|
||||
<div class=\"logo\">MACHINE.MACHINE</div>
|
||||
<div>
|
||||
<h1 class=\"title\">\${title}</h1>
|
||||
\${subtitle ? '<div class=\"subtitle\">' + subtitle + '</div>' : ''}
|
||||
</div>
|
||||
\${dateLine ? '<div class=\"meta\">' + dateLine + '</div>' : ''}
|
||||
</div>\`;
|
||||
|
||||
const html = \`<!DOCTYPE html>
|
||||
<html lang=\"en\">
|
||||
<head>
|
||||
<meta charset=\"utf-8\">
|
||||
<title>\${title}</title>
|
||||
<style>\${css}</style>
|
||||
</head>
|
||||
<body>
|
||||
\${coverHtml}
|
||||
<div class=\"body-content\">
|
||||
\${contentHtml}
|
||||
</div>
|
||||
</body>
|
||||
</html>\`;
|
||||
|
||||
fs.writeFileSync('output.html', html);
|
||||
console.log('HTML written:', html.length, 'bytes');
|
||||
JSEOF
|
||||
"
|
||||
|
||||
echo "Step 2: Rendering HTML → PDF..."
|
||||
docker exec "$CONTAINER" bash -c "
|
||||
cd $TMP
|
||||
google-chrome \
|
||||
--headless \
|
||||
--no-sandbox \
|
||||
--disable-gpu \
|
||||
--disable-web-security \
|
||||
--print-to-pdf=output.pdf \
|
||||
--print-to-pdf-no-header \
|
||||
--run-all-compositor-stages-before-draw \
|
||||
--virtual-time-budget=5000 \
|
||||
'file://$TMP/output.html'
|
||||
"
|
||||
|
||||
# Copy both outputs back
|
||||
docker cp "$CONTAINER:$TMP/output.html" "$OUT_HTML_ABS"
|
||||
docker cp "$CONTAINER:$TMP/output.pdf" "$OUT_ABS"
|
||||
docker exec "$CONTAINER" rm -rf "$TMP"
|
||||
|
||||
echo ""
|
||||
echo "HTML: $OUT_HTML_ABS ($(du -h "$OUT_HTML_ABS" | cut -f1))"
|
||||
echo "PDF: $OUT_ABS ($(du -h "$OUT_ABS" | cut -f1))"
|
||||
236
solutions/mm-pdf-report/payload/templates/dark.css
Normal file
236
solutions/mm-pdf-report/payload/templates/dark.css
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
/* MM Dark Design System — WeasyPrint / Marp compatible */
|
||||
|
||||
:root {
|
||||
--cover-bg: #0a0e1a;
|
||||
--accent: #4bb8d4;
|
||||
--section-bg: #3d4550;
|
||||
--body-bg: #111827;
|
||||
--body-text: #e2e8f0;
|
||||
--muted: #94a3b8;
|
||||
--code-bg: #1e2533;
|
||||
--border: #2d3748;
|
||||
--white: #ffffff;
|
||||
}
|
||||
|
||||
/* --- PAGE --- */
|
||||
@page {
|
||||
size: A4;
|
||||
margin: 15mm 18mm 15mm 18mm;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Inter', 'Helvetica Neue', Arial, sans-serif;
|
||||
font-size: 10pt;
|
||||
line-height: 1.6;
|
||||
color: var(--body-text);
|
||||
background: var(--body-bg);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.body-content {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* --- COVER PAGE --- */
|
||||
.cover {
|
||||
background: var(--cover-bg);
|
||||
min-height: 100vh;
|
||||
padding: 52px 52px 40px 52px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
page-break-after: always;
|
||||
}
|
||||
|
||||
.cover .logo {
|
||||
font-size: 11pt;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.15em;
|
||||
text-transform: uppercase;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.cover .title {
|
||||
font-size: 28pt;
|
||||
font-weight: 800;
|
||||
color: var(--white);
|
||||
line-height: 1.15;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.cover .subtitle {
|
||||
font-size: 13pt;
|
||||
color: var(--accent);
|
||||
margin-top: 8px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.cover .meta {
|
||||
font-size: 9pt;
|
||||
color: var(--muted);
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
.cover .version-badge {
|
||||
display: inline-block;
|
||||
background: var(--accent);
|
||||
color: var(--cover-bg);
|
||||
font-size: 8pt;
|
||||
font-weight: 700;
|
||||
padding: 3px 10px;
|
||||
border-radius: 3px;
|
||||
letter-spacing: 0.08em;
|
||||
}
|
||||
|
||||
/* --- SECTION BANNERS --- */
|
||||
.section-banner, h2 {
|
||||
background: var(--section-bg);
|
||||
color: var(--white);
|
||||
padding: 8px 16px;
|
||||
margin: 24px -18mm 16px -18mm;
|
||||
font-size: 10pt;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/* --- KICKER --- */
|
||||
.kicker {
|
||||
display: block;
|
||||
font-size: 8pt;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.18em;
|
||||
text-transform: uppercase;
|
||||
color: var(--accent);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
/* --- HEADINGS --- */
|
||||
h1 {
|
||||
font-size: 20pt;
|
||||
font-weight: 800;
|
||||
color: var(--white);
|
||||
margin: 0 0 8px 0;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 11pt;
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
margin: 16px 0 6px 0;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 10pt;
|
||||
font-weight: 600;
|
||||
color: var(--white);
|
||||
margin: 12px 0 4px 0;
|
||||
}
|
||||
|
||||
/* --- KPI CARDS --- */
|
||||
.kpi-row {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
margin: 16px 0;
|
||||
}
|
||||
|
||||
.kpi {
|
||||
flex: 1;
|
||||
background: var(--code-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-top: 3px solid var(--accent);
|
||||
padding: 12px 14px;
|
||||
border-radius: 4px;
|
||||
font-size: 9pt;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.kpi strong {
|
||||
display: block;
|
||||
font-size: 16pt;
|
||||
font-weight: 800;
|
||||
color: var(--white);
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
/* --- TABLES --- */
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 12px 0;
|
||||
font-size: 9pt;
|
||||
}
|
||||
|
||||
th {
|
||||
background: var(--section-bg);
|
||||
color: var(--white);
|
||||
padding: 7px 10px;
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
font-size: 8pt;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 6px 10px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
color: var(--body-text);
|
||||
}
|
||||
|
||||
tr:nth-child(even) td {
|
||||
background: rgba(255,255,255,0.02);
|
||||
}
|
||||
|
||||
/* --- CODE BLOCKS --- */
|
||||
pre, code {
|
||||
background: var(--code-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 3px;
|
||||
font-family: 'JetBrains Mono', 'Fira Code', monospace;
|
||||
font-size: 8.5pt;
|
||||
color: #a5d6a7;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 12px 14px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
code { padding: 1px 5px; }
|
||||
|
||||
/* --- CALLOUTS --- */
|
||||
.callout {
|
||||
background: rgba(75, 184, 212, 0.08);
|
||||
border-left: 3px solid var(--accent);
|
||||
padding: 10px 14px;
|
||||
margin: 12px 0;
|
||||
border-radius: 0 4px 4px 0;
|
||||
font-size: 9pt;
|
||||
color: var(--body-text);
|
||||
}
|
||||
|
||||
.callout.warn {
|
||||
border-left-color: #f6a623;
|
||||
background: rgba(246, 166, 35, 0.06);
|
||||
}
|
||||
|
||||
.callout.danger {
|
||||
border-left-color: #e53e3e;
|
||||
background: rgba(229, 62, 62, 0.06);
|
||||
}
|
||||
|
||||
/* --- FOOTER --- */
|
||||
@page {
|
||||
@bottom-center {
|
||||
content: "Machine.Machine — Confidential";
|
||||
font-size: 7.5pt;
|
||||
color: #4a5568;
|
||||
}
|
||||
@bottom-right {
|
||||
content: counter(page);
|
||||
font-size: 7.5pt;
|
||||
color: #4a5568;
|
||||
}
|
||||
}
|
||||
32
solutions/mm-pdf-report/payload/templates/purple.css
Normal file
32
solutions/mm-pdf-report/payload/templates/purple.css
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/* MM Purple Sidebar — Nasr reference style */
|
||||
@import url("dark.css");
|
||||
|
||||
:root {
|
||||
--cover-bg: #1a0533;
|
||||
--accent: #9f7aea;
|
||||
--sidebar-bg: #6b46c1;
|
||||
}
|
||||
|
||||
.cover {
|
||||
background: var(--cover-bg);
|
||||
padding-left: 0;
|
||||
display: grid;
|
||||
grid-template-columns: 6px 1fr;
|
||||
}
|
||||
|
||||
.cover::before {
|
||||
content: '';
|
||||
background: var(--sidebar-bg);
|
||||
grid-column: 1;
|
||||
}
|
||||
|
||||
.cover-content {
|
||||
grid-column: 2;
|
||||
padding: 52px 52px 40px 36px;
|
||||
}
|
||||
|
||||
.cover .logo { color: var(--accent); }
|
||||
.cover .subtitle { color: var(--accent); }
|
||||
h3 { color: var(--accent); }
|
||||
.kpi { border-top-color: var(--accent); }
|
||||
.callout { border-left-color: var(--accent); }
|
||||
17
solutions/mm-pdf-report/recipe.yaml
Normal file
17
solutions/mm-pdf-report/recipe.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# mm-pdf-report install recipe (apply-adapter.md bundle layout, local adapter v1)
|
||||
# Places the mm-pdf skill into the buyer's Claude Code skills directory.
|
||||
targets:
|
||||
- src: SKILL.md
|
||||
dest: ~/.claude/skills/mm-pdf/SKILL.md
|
||||
- src: scripts/generate.sh
|
||||
dest: ~/.claude/skills/mm-pdf/scripts/generate.sh
|
||||
- src: templates/dark.css
|
||||
dest: ~/.claude/skills/mm-pdf/templates/dark.css
|
||||
- src: templates/purple.css
|
||||
dest: ~/.claude/skills/mm-pdf/templates/purple.css
|
||||
checks:
|
||||
- cmd: test -f ~/.claude/skills/mm-pdf/SKILL.md
|
||||
expect_exit: 0
|
||||
- cmd: test -x ~/.claude/skills/mm-pdf/scripts/generate.sh
|
||||
expect_exit: 0
|
||||
entrypoint: "Ask your agent to use the mm-pdf skill, or run: ~/.claude/skills/mm-pdf/scripts/generate.sh <input.md> --style dark"
|
||||
63
solutions/mm-pdf-report/solution.json
Normal file
63
solutions/mm-pdf-report/solution.json
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
{
|
||||
"schema_version": "m2.solution.v1",
|
||||
"solution_id": "sol_mm-pdf-report",
|
||||
"name": "MM PDF Report Generator",
|
||||
"summary": "Generate Machine.Machine branded PDF reports and slide decks from Markdown.",
|
||||
"description": "Installs the mm-pdf skill: a Markdown-to-branded-PDF/HTML pipeline (dark navy aesthetic, cyan accents, A4 layout) built on a Node+marked HTML render step and headless-Chrome print-to-pdf inside a Docker container. Ships three artifacts: SKILL.md, scripts/generate.sh, and templates/{dark,purple}.css. content_hash is computed over payload/ + recipe.yaml only (not solution.json itself, to avoid the self-referential hash problem of hashing a file that contains its own hash): sha256 of `tar --sort=name --mtime='@0' --owner=0 --group=0 --numeric-owner -czf - payload recipe.yaml` run from this bundle's root.",
|
||||
"intent": "Give an operator a working branded-document pipeline (proposal PDFs, spec sheets, decks) without building one from scratch.",
|
||||
"behavior": {
|
||||
"skill_ref": "payload/SKILL.md"
|
||||
},
|
||||
"tools": [
|
||||
{ "name": "docker", "kind": "cli", "required": true }
|
||||
],
|
||||
"runtime": {
|
||||
"surfaces": ["claude-code-skill"]
|
||||
},
|
||||
"permissions": [
|
||||
{ "action": "write", "target": "~/.claude/skills/mm-pdf/" },
|
||||
{ "action": "exec", "target": "docker exec/docker cp against a caller-selected container" }
|
||||
],
|
||||
"deployment": {
|
||||
"recipe_ref": "recipe.yaml",
|
||||
"entrypoint": "Ask your agent to use the mm-pdf skill, or run: ~/.claude/skills/mm-pdf/scripts/generate.sh <input.md> --style dark",
|
||||
"verify_command": "test -f ~/.claude/skills/mm-pdf/SKILL.md"
|
||||
},
|
||||
"applicability": {
|
||||
"image_classes": ["primus", "agent-latest"],
|
||||
"roles": ["operator", "desktop-agent"],
|
||||
"tool_requirements": ["docker"]
|
||||
},
|
||||
"tenant_scope": "m2-core",
|
||||
"evidence": [
|
||||
{
|
||||
"source": "/home/m2/.claude/skills/mm-pdf/ (SKILL.md, scripts/generate.sh, templates/dark.css, templates/purple.css) — the proven skill this bundle packages, present on the m2 host since 2026-04-21 (SKILL.md mtime 2026-04-21T00:05:01+02:00, templates/dark.css mtime 2026-04-21T00:04, scripts/generate.sh mtime 2026-04-21T00:09)",
|
||||
"machine": "m2",
|
||||
"excerpt": "SKILL.md frontmatter: 'Generate beautifully styled Machine.Machine branded PDFs and slide decks from Markdown. Dark navy aesthetic, cyan accents, professional A4 layout.'"
|
||||
},
|
||||
{
|
||||
"source": "/home/m2/session-2026-04-20.pdf — real output of this pipeline: 4-page A4 PDF, PDF metadata Title 'output.html' (the pipeline's fixed intermediate filename), Creator 'HeadlessChrome/145.0.0.0' (Chrome print-to-pdf, matches scripts/generate.sh Step 2), CreationDate 2026-04-20T22:56:51+02:00; pdftotext shows the 'MACHINE.MACHINE' cover logo and MM design-system markup",
|
||||
"machine": "m2",
|
||||
"excerpt": "pdfinfo: Title=output.html; Creator=Mozilla/5.0 ... HeadlessChrome/145.0.0.0 ...; Producer=Skia/PDF m145; Pages=4; page size 594.96x841.92pts (A4)"
|
||||
},
|
||||
{
|
||||
"source": "/home/m2/spark-cluster-old/fabric-setup.pdf + fabric-setup.html — second real generated pair, 4-page A4 PDF titled 'DGX Spark Cluster — Fabric Setup Reference', same HeadlessChrome/145.0.0.0 print-to-pdf signature, CreationDate 2026-04-21T00:09:40+02:00 (12 seconds before this SKILL.md's own mtime, i.e. produced by the exact skill version in this bundle)",
|
||||
"machine": "m2",
|
||||
"excerpt": "pdftotext footer: 'Machine.Machine — Confidential' page-number footer matches templates/dark.css `@bottom-center`/`@bottom-right` rules"
|
||||
}
|
||||
],
|
||||
"content_hash": "sha256:aaee0b1a894efafabddd1bd95c5023c915a6fcd05007776ad921d420f38ea916",
|
||||
"price": {
|
||||
"amount": 40,
|
||||
"currency": "m2cr",
|
||||
"model": "fixed"
|
||||
},
|
||||
"seller": "sdjs-operator",
|
||||
"license": {
|
||||
"terms": "Perpetual use on operator-owned machines for the buyer's own document generation; no redistribution of the skill files as a standalone product.",
|
||||
"major_version_coverage": true
|
||||
},
|
||||
"revenue_split": {
|
||||
"platform_pct": 10
|
||||
}
|
||||
}
|
||||
|
|
@ -79,11 +79,11 @@ published listing
|
|||
|
||||
**Independent test**: quickstart.md Scenario A
|
||||
|
||||
- [ ] T027 [US2] `publish` command in `cli/src/m2_market/cli.py` + `cli/src/m2_market/publish.py`: validate bundle against schemas (exit 5 on violation incl. tenant firewall), push `listing/<id>` branch, open PR via Forgejo API with template
|
||||
- [x] T027 [US2] `publish` command in `cli/src/m2_market/cli.py` + `cli/src/m2_market/publish.py`: validate bundle against schemas (exit 5 on violation incl. tenant firewall), push `listing/<id>` branch, open PR via Forgejo API with template
|
||||
- [ ] T028 [US2] Registry CI hardening in `m2/market-registry` CI config: evidence-required, owner-initiated + double-scrub attestations for tenant-scoped submissions, content_hash-vs-release check (Story 2 AC-2/AC-4 mechanical rejection)
|
||||
- [ ] T029 [P] [US2] Package seed Solution `solutions/mm-pdf-report/` (from the proven mm-pdf outcome): solution.json, payload/, recipe.yaml, real evidence refs
|
||||
- [ ] T030 [P] [US2] Package seed Solution `solutions/agent-scaffold/` (from the agent-scaffold skill outcome): solution.json, payload/, recipe.yaml, real evidence
|
||||
- [ ] T031 [P] [US2] Package seed Solution `solutions/competitor-scan/` (from the competitor-scan report outcome): solution.json, payload/, recipe.yaml, real evidence
|
||||
- [x] T029 [P] [US2] Package seed Solution `solutions/mm-pdf-report/` (from the proven mm-pdf outcome): solution.json, payload/, recipe.yaml, real evidence refs
|
||||
- [x] T030 [P] [US2] Package seed Solution `solutions/agent-scaffold/` (from the agent-scaffold skill outcome): solution.json, payload/, recipe.yaml, real evidence
|
||||
- [ ] T031 [P] [US2] BLOCKED-ON-OPERATOR: competitor-scan seed has no real evidence (constitution III) — t031 report recommends substituting Parlobyg email-triage (tenant-derived: needs owner-initiated + double-scrub sign-off) or another proven outcome
|
||||
- [ ] T032 [US2] Publish all three seeds through the real protocol (PRs, review, merge), verify each discoverable via `m2-market search` (SC-002)
|
||||
|
||||
**Checkpoint**: ≥3 published evidence-backed listings live
|
||||
|
|
|
|||
620
uv.lock
620
uv.lock
|
|
@ -1,620 +0,0 @@
|
|||
version = 1
|
||||
revision = 3
|
||||
requires-python = ">=3.12"
|
||||
|
||||
[manifest]
|
||||
members = [
|
||||
"m2-ledger",
|
||||
"m2-market",
|
||||
"m2-market-indexer",
|
||||
"m2-market-workspace",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "annotated-doc"
|
||||
version = "0.0.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "annotated-types"
|
||||
version = "0.7.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyio"
|
||||
version = "4.14.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "idna" },
|
||||
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/3b/72/5562aabb8dd7181e8e860622a38bea08d17842b99ecd4c91f84ac95251b0/anyio-4.14.1.tar.gz", hash = "sha256:8d648a3544c1a700e3ff78615cd679e4c5c3f149904287e73687b2596963629e", size = 254831, upload-time = "2026-06-24T20:56:06.017Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/7b/90df4a0a816d98d6ea26f559d87836d494a2cf1fcf063be67df50a7bcc30/anyio-4.14.1-py3-none-any.whl", hash = "sha256:4e5533c5b8ff0a24f5d7a176cbe6877129cd183893f66b537f8f227d10527d72", size = 124875, upload-time = "2026-06-24T20:56:04.413Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "attrs"
|
||||
version = "26.1.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055, upload-time = "2026-03-19T14:22:25.026Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2026.6.17"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c9/c7/424b75da314c1045981bd9777432fad05a9e0c69daa4ed7e308bbaffe405/certifi-2026.6.17.tar.gz", hash = "sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432", size = 134594, upload-time = "2026-06-17T10:31:07.894Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/2f/c5464532e965badff2f4c4c1a3a83f5697f0d7c407ed0cda44aaa99bb451/certifi-2026.6.17-py3-none-any.whl", hash = "sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db", size = 133289, upload-time = "2026-06-17T10:31:06.348Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.4.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/76/d4/81420972a676e8ffea40450d8c8c92943e7218a78fe9b64359836cc9876b/click-8.4.2.tar.gz", hash = "sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6", size = 338000, upload-time = "2026-06-24T17:45:15.148Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/e2/79c688af8b210d232694e31e59da9f6ec747bae31c3f5946e4e9b98860d5/click-8.4.2-py3-none-any.whl", hash = "sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76", size = 119243, upload-time = "2026-06-24T17:45:13.73Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastapi"
|
||||
version = "0.139.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "annotated-doc" },
|
||||
{ name = "pydantic" },
|
||||
{ name = "starlette" },
|
||||
{ name = "typing-extensions" },
|
||||
{ name = "typing-inspection" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d3/af/a5f50ccfa659ec1802cb4ca842c23f06d906a8cc9aef6016a2caeea3d4ed/fastapi-0.139.0.tar.gz", hash = "sha256:99ab7b2d92223c76d6cf10757ab3f89d45b38267fc20b2a136cf02f6beac3145", size = 423016, upload-time = "2026-07-01T16:35:33.436Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/7c/8e3c6ad324ea5cb36604fc3f968554887891c316d9dfde57761611d907ad/fastapi-0.139.0-py3-none-any.whl", hash = "sha256:cf15e1e9e667ddb0ad63811e60bd11390d1aac838ca4a7a23f421807b2308189", size = 130339, upload-time = "2026-07-01T16:35:32.19Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h11"
|
||||
version = "0.16.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httpcore"
|
||||
version = "1.0.9"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "certifi" },
|
||||
{ name = "h11" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httpx"
|
||||
version = "0.28.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "anyio" },
|
||||
{ name = "certifi" },
|
||||
{ name = "httpcore" },
|
||||
{ name = "idna" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hypothesis"
|
||||
version = "6.155.7"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "sortedcontainers" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f2/55/983b6bc1b6b343a5ff6020388f9d0680ab477be59a731517e6c4a0387100/hypothesis-6.155.7.tar.gz", hash = "sha256:d8d6091753d0669db3c90c5e5b346cb37c72f3dd9378c8413acb1fd5da63f7ea", size = 478291, upload-time = "2026-06-21T05:54:31.573Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/01/f8/c151e196d4f397ed9436a071e52666c70a2f021138dea828b0a461e245db/hypothesis-6.155.7-py3-none-any.whl", hash = "sha256:9f634bdb1f9e9b8ab6ba09431cf2deedb750c96978125a6fb3c5a0f6c6db4131", size = 544762, upload-time = "2026-06-21T05:54:29.506Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.18"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/cd/63/9496c57188a2ee585e0f1db071d75089a11e98aa86eb99d9d7618fc1edce/idna-3.18.tar.gz", hash = "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848", size = 196711, upload-time = "2026-06-02T14:34:07.794Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/5e/d4e9f1a599fb8e573b7b87160658329fbf28d19eac2718f51fc3def3aa5a/idna-3.18-py3-none-any.whl", hash = "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", size = 65455, upload-time = "2026-06-02T14:34:06.319Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iniconfig"
|
||||
version = "2.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jsonschema"
|
||||
version = "4.26.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "attrs" },
|
||||
{ name = "jsonschema-specifications" },
|
||||
{ name = "referencing" },
|
||||
{ name = "rpds-py" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jsonschema-specifications"
|
||||
version = "2025.9.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "referencing" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "m2-ledger"
|
||||
version = "0.1.0"
|
||||
source = { editable = "ledger" }
|
||||
dependencies = [
|
||||
{ name = "fastapi" },
|
||||
{ name = "httpx" },
|
||||
{ name = "uvicorn" },
|
||||
]
|
||||
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "hypothesis" },
|
||||
{ name = "pytest" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "fastapi", specifier = ">=0.115" },
|
||||
{ name = "httpx", specifier = ">=0.27" },
|
||||
{ name = "uvicorn", specifier = ">=0.30" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "hypothesis", specifier = ">=6" },
|
||||
{ name = "pytest", specifier = ">=8" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "m2-market"
|
||||
version = "0.1.0"
|
||||
source = { editable = "cli" }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "httpx" },
|
||||
{ name = "jsonschema" },
|
||||
{ name = "pyyaml" },
|
||||
]
|
||||
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "pytest" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "click", specifier = ">=8.1" },
|
||||
{ name = "httpx", specifier = ">=0.27" },
|
||||
{ name = "jsonschema", specifier = ">=4.23" },
|
||||
{ name = "pyyaml", specifier = ">=6" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [{ name = "pytest", specifier = ">=8" }]
|
||||
|
||||
[[package]]
|
||||
name = "m2-market-indexer"
|
||||
version = "0.1.0"
|
||||
source = { editable = "indexer" }
|
||||
dependencies = [
|
||||
{ name = "httpx" },
|
||||
{ name = "jsonschema" },
|
||||
]
|
||||
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "pytest" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "httpx", specifier = ">=0.27" },
|
||||
{ name = "jsonschema", specifier = ">=4.23" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [{ name = "pytest", specifier = ">=8" }]
|
||||
|
||||
[[package]]
|
||||
name = "m2-market-workspace"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "26.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pluggy"
|
||||
version = "1.6.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "2.13.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "annotated-types" },
|
||||
{ name = "pydantic-core" },
|
||||
{ name = "typing-extensions" },
|
||||
{ name = "typing-inspection" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775, upload-time = "2026-05-06T13:43:05.343Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262, upload-time = "2026-05-06T13:43:02.641Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-core"
|
||||
version = "2.46.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464, upload-time = "2026-05-06T13:37:06.98Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/8c/af022f0af448d7747c5154288d46b5f2bc5f17366eaa0e23e9aa04d59f3b/pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2", size = 2106158, upload-time = "2026-05-06T13:38:57.215Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f", size = 1951724, upload-time = "2026-05-06T13:37:02.697Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8e/bc/f47d1ff9cbb1620e1b5b697eef06010035735f07820180e74178226b27b3/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7", size = 1975742, upload-time = "2026-05-06T13:37:09.448Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/11/9b9a5b0306345664a2da6410877af6e8082481b5884b3ddd78d47c6013ce/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7", size = 2052418, upload-time = "2026-05-06T13:37:38.234Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/b7/a65fec226f5d78fc39f4a13c4cc0c768c22b113438f60c14adc9d2865038/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712", size = 2232274, upload-time = "2026-05-06T13:38:27.753Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/f0/92039db98b907ef49269a8271f67db9cb78ae2fc68062ef7e4e77adb5f61/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4", size = 2309940, upload-time = "2026-05-06T13:38:05.353Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce", size = 2094516, upload-time = "2026-05-06T13:39:10.577Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/37/a8aca44d40d737dde2bc05b3c6c07dff0de07ce6f82e9f3167aeaf4d5dea/pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987", size = 2136854, upload-time = "2026-05-06T13:40:22.59Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/99/fcef1b79238c06a8cbec70819ac722ba76e02bc8ada9b0fd66eba40da01b/pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b", size = 2180306, upload-time = "2026-05-06T13:40:10.666Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/6c/fc44000918855b42779d007ae63b0532794739027b2f417321cddbc44f6a/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458", size = 2190044, upload-time = "2026-05-06T13:40:43.231Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/65/d9cadc9f1920d7a127ad2edba16c1db7916e59719285cd6c94600b0080ba/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b", size = 2329133, upload-time = "2026-05-06T13:39:57.365Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/cf/c873d91679f3a30bcf5e7ac280ce5573483e72295307685120d0d5ad3416/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c", size = 2374464, upload-time = "2026-05-06T13:38:06.976Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/bd/6f2fc8188f31bf10590f1e98e7b306336161fac930a8c514cd7bd828c7dc/pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894", size = 1974823, upload-time = "2026-05-06T13:40:47.985Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89", size = 2072919, upload-time = "2026-05-06T13:39:21.153Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/ba/f463d006e0c47373ca7ec5e1a261c59dc01ef4d62b2657af925fb0deee3a/pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a", size = 2027604, upload-time = "2026-05-06T13:39:03.753Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/51/a2/5d30b469c5267a17b39dec53208222f76a8d351dfac4af661888c5aee77d/pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008", size = 2106306, upload-time = "2026-05-06T13:37:48.029Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/81/4fa520eaffa8bd7d1525e644cd6d39e7d60b1592bc5b516693c7340b50f1/pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4", size = 1951906, upload-time = "2026-05-06T13:37:17.012Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/03/d5/fd02da45b659668b05923b17ba3a0100a0a3d5541e3bd8fcc4ecb711309e/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76", size = 1976802, upload-time = "2026-05-06T13:37:35.113Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/f2/95727e1368be3d3ed485eaab7adbd7dda408f33f7a36e8b48e0144002b91/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3", size = 2052446, upload-time = "2026-05-06T13:37:12.313Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9c/86/5d99feea3f77c7234b8718075b23db11532773c1a0dbd9b9490215dc2eeb/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76", size = 2232757, upload-time = "2026-05-06T13:39:01.149Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/3a/508ac615935ef7588cf6d9e9b91309fdc2da751af865e02a9098de88258c/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4", size = 2309275, upload-time = "2026-05-06T13:37:41.406Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/f8/41db9de19d7987d6b04715a02b3b40aea467000275d9d758ffaa31af7d50/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a", size = 2094467, upload-time = "2026-05-06T13:39:18.847Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/e2/f35033184cb11d0052daf4416e8e10a502ea2ac006fc4f459aee872727d1/pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262", size = 2134417, upload-time = "2026-05-06T13:40:17.944Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/7b/6ceeb1cc90e193862f444ebe373d8fdf613f0a82572dde03fb10734c6c71/pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e", size = 2179782, upload-time = "2026-05-06T13:40:32.618Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/f2/c8d7773ede6af08036423a00ae0ceffce266c3c52a096c435d68c896083f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd", size = 2188782, upload-time = "2026-05-06T13:36:51.018Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/31/0c864784e31f09f05cdd87606f08923b9c9e7f6e51dd27f20f62f975ce9f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be", size = 2328334, upload-time = "2026-05-06T13:40:37.764Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/eb/4f6c8a41efa30baa755590f4141abf3a8c370fab610915733e74134a7270/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d", size = 2372986, upload-time = "2026-05-06T13:39:34.152Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/24/b375a480d53113860c299764bfe9f349a3dc9108b3adc0d7f0d786492ebf/pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb", size = 1973693, upload-time = "2026-05-06T13:37:55.072Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/e8/cff247591966f2d22ec8c003cd7587e27b7ba7b81ab2fb888e3ab75dc285/pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292", size = 2071819, upload-time = "2026-05-06T13:38:49.139Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/1a/f4aee670d5670e9e148e0c82c7db98d780be566c6e6a97ee8035528ca0b3/pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d", size = 2027411, upload-time = "2026-05-06T13:40:45.796Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/74/228a26ddad29c6672b805d9fd78e8d251cd04004fa7eed0e622096cd0250/pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb", size = 2102079, upload-time = "2026-05-06T13:38:41.019Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462", size = 1952179, upload-time = "2026-05-06T13:36:59.812Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/95/30/5211a831ae054928054b2f79731661087a2bc5c01e825c672b3a4a8f1b3e/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9", size = 1978926, upload-time = "2026-05-06T13:37:39.933Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/e9/689668733b1eb67adeef047db3c2e8788fcf65a7fd9c9e2b46b7744fe245/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4", size = 2046785, upload-time = "2026-05-06T13:38:01.995Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/60/d9/6715260422ff50a2109878fd24d948a6c3446bb2664f34ee78cd972b3acd/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914", size = 2228733, upload-time = "2026-05-06T13:40:50.371Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/ae/fdb2f64316afca925640f8e70bb1a564b0ec2721c1389e25b8eb4bf9a299/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28", size = 2307534, upload-time = "2026-05-06T13:37:21.531Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b", size = 2099732, upload-time = "2026-05-06T13:39:31.942Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/06/d5/ee5a3366637fee41dee51a1fc91562dcf12ddbc68fda34e6b253da2324bb/pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c", size = 2129627, upload-time = "2026-05-06T13:37:25.033Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/94/33/2414be571d2c6a6c4d08be21f9292b6d3fdb08949a97b6dfe985017821db/pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb", size = 2179141, upload-time = "2026-05-06T13:37:14.046Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/79/7daa95be995be0eecc4cf75064cb33f9bbbfe3fe0158caf2f0d4a996a5c7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898", size = 2184325, upload-time = "2026-05-06T13:36:53.615Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/cb/d0a382f5c0de8a222dc61c65348e0ce831b1f68e0a018450d31c2cace3a5/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e", size = 2323990, upload-time = "2026-05-06T13:40:29.971Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/db/d9ba624cc4a5aced1598e88c04fdbd8310c8a69b9d38b9a3d39ce3a61ed7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519", size = 2369978, upload-time = "2026-05-06T13:37:23.027Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/20/d15df15ba918c423461905802bfd2981c3af0bfa0e40d05e13edbfa48bc3/pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4", size = 1966354, upload-time = "2026-05-06T13:38:03.499Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac", size = 2072238, upload-time = "2026-05-06T13:39:40.807Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/36/51eb763beec1f4cf59b1db243a7dcc39cbb41230f050a09b9d69faaf0a48/pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a", size = 2018251, upload-time = "2026-05-06T13:37:26.72Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/91/855af51d625b23aa987116a19e231d2aaef9c4a415273ddc189b79a45fee/pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0", size = 2099593, upload-time = "2026-05-06T13:39:47.682Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/1b/8784a54c65edb5f49f0a14d6977cf1b209bba85a4c77445b255c2de58ab3/pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d", size = 1935226, upload-time = "2026-05-06T13:40:40.428Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/e7/1955d28d1afc56dd4b3ad7cc0cf39df1b9852964cf16e5d13912756d6d6b/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b", size = 1974605, upload-time = "2026-05-06T13:37:32.029Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/93/e2/3fedbf0ba7a22850e6e9fd78117f1c0f10f950182344d8a6c535d468fdd8/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000", size = 2030777, upload-time = "2026-05-06T13:38:55.239Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/61/46be275fcaaba0b4f5b9669dd852267ce1ff616592dccf7a7845588df091/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e", size = 2236641, upload-time = "2026-05-06T13:37:08.096Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/60/db/12e93e46a8bac9988be3c016860f83293daea8c716c029c9ace279036f2f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd", size = 2286404, upload-time = "2026-05-06T13:40:20.221Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/4a/4d8b19008f38d31c53b8219cfedc2e3d5de5fe99d90076b7e767de29274f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3", size = 2109219, upload-time = "2026-05-06T13:38:12.153Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/70/3cbc40978fefb7bb09c6708d40d4ad1a5d70fd7213c3d17f971de868ec1f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7", size = 2110594, upload-time = "2026-05-06T13:40:02.971Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/20/b8d36736216e29491125531685b2f9e61aa5b4b2599893f8268551da3338/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff", size = 2159542, upload-time = "2026-05-06T13:39:27.506Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/a2/367df868eb584dacf6bf82a389272406d7178e301c4ac82545ab98bc2dd9/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424", size = 2168146, upload-time = "2026-05-06T13:38:31.93Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/b8/4460f77f7e201893f649a29ab355dddd3beee8a97bcb1a320db414f9a06e/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6", size = 2306309, upload-time = "2026-05-06T13:37:44.717Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/64/c4/be2639293acd87dc8ddbcec41a73cee9b2ebf996fe6d892a1a74e88ad3f7/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565", size = 2369736, upload-time = "2026-05-06T13:37:05.645Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/a6/9f9f380dbb301f67023bf8f707aaa75daadf84f7152d95c410fd7e81d994/pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02", size = 1955575, upload-time = "2026-05-06T13:38:51.116Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/40/1f/f1eb9eb350e795d1af8586289746f5c5677d16043040d63710e22abc43c9/pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5", size = 2051624, upload-time = "2026-05-06T13:38:21.672Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325, upload-time = "2026-05-06T13:40:52.723Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/1d/8987ad40f65ae1432753072f214fb5c74fe47ffbd0698bb9cbbb585664f8/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7", size = 2095527, upload-time = "2026-05-06T13:39:52.283Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/64/d3/84c282a7eee1d3ac4c0377546ef5a1ea436ce26840d9ac3b7ed54a377507/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df", size = 1936024, upload-time = "2026-05-06T13:40:15.671Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/ca/eac61596cdeb4d7e174d3dc0bd8a6238f14f75f97a24e7b7db4c7e7340a0/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526", size = 1990696, upload-time = "2026-05-06T13:38:34.717Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/c3/7c8b240552251faf6b3a957db200fcfbbcec36763c050428b601e0c9b83b/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0", size = 2147590, upload-time = "2026-05-06T13:39:29.883Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pygments"
|
||||
version = "2.20.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "9.1.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
{ name = "iniconfig" },
|
||||
{ name = "packaging" },
|
||||
{ name = "pluggy" },
|
||||
{ name = "pygments" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyyaml"
|
||||
version = "6.0.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "referencing"
|
||||
version = "0.37.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "attrs" },
|
||||
{ name = "rpds-py" },
|
||||
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rpds-py"
|
||||
version = "2026.6.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/aa/2a/9618a122aeb2a169a28b03889a2995fe297588964333d4a7d67bdf46e147/rpds_py-2026.6.3.tar.gz", hash = "sha256:1cebd1337c242e4ec2293e541f712b2da849b29f48f0c293684b71c0632625d4", size = 64051, upload-time = "2026-06-30T07:17:53.009Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/be/2e8974163072e7bab7df1a5acd54c4498e75e35d6d18b864d3a9d5dadc92/rpds_py-2026.6.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a0811d33247c3d6128a3001d763f2aa056bb3425204335400ac54f89eec3a0d0", size = 343691, upload-time = "2026-06-30T07:15:14.96Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/73/319dfa745dd668efe89309141ded489126461fcecd2b8f3a3cda185129b6/rpds_py-2026.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:538949e262e46caa31ac01bdb3c1e8f642622922cacbabbae6a8445d9dc33eaf", size = 338542, upload-time = "2026-06-30T07:15:16.267Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/63/4239893be1c4d09b709b1a8f6be4188f0870084ff547f46606b8a75f1b03/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55927d532399c2c646100ff7feb48eaa940ad70f42cd68e1328f3ded9f81ca24", size = 368180, upload-time = "2026-06-30T07:15:17.62Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1c/ca/9c5de382225234ceb37b1844ebdb140db12b2a278bb9efe2fcd19f6c82ce/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f56f1695bc5c0871cbc33dc0130fcf503aab0c57dcc5a6700a4f49eba4f2652e", size = 375067, upload-time = "2026-06-30T07:15:18.952Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/dc/863f69d1bf04ade34b7fe0d59b9fdf6f0135fe2d7cbca74f1d665589559d/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:270b293dae9058fc9fcedab50f13cebf46fb8ed1d1d54e0521a9da5d6b211975", size = 490509, upload-time = "2026-06-30T07:15:20.434Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/ef/eac16a12048b45ec7c7fa94f2be3438a5f26bf9cc8580b18a1cfd609b7f6/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:127565fead0a10943b282957bd5447804ff3160ad79f2ad2635e6d249e380680", size = 382754, upload-time = "2026-06-30T07:15:21.831Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/8f/d2f3f532616be4d06c316ef119683e832bd3d41e112bf3a88f4151c95b17/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecabd69db66de867690f9797f2f8fa27ba501bbc24540cbdbdc649cd15888ba6", size = 366189, upload-time = "2026-06-30T07:15:23.371Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/29/41a7b0e98a4b44cd676ab7598419623373eb43b20be68c084935c1a8cf88/rpds_py-2026.6.3-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:58eadac9cd119677b60e1cf8ac4052f35949d71b8a9e5556efccbe82533cf22a", size = 377750, upload-time = "2026-06-30T07:15:24.659Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/05/ecda0bec46f9a1565090bcdc941d023f6a25aff85fda28f89f8d19878152/rpds_py-2026.6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7491ee23305ac3eb59e492b6945881f5cd77a6f731061a3f25b77fd40f9e99a4", size = 395576, upload-time = "2026-06-30T07:15:25.987Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/a8/6ed52f03ee6cb854ce78785cc9a9a672eb880e83fd7224d471f667d151f1/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2c99f7e8ccb3dd6e3e4bfeac657a7b208c9bac8075f4b078c02d7404c34107fa", size = 543807, upload-time = "2026-06-30T07:15:27.356Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/d6/156c0d3eea27ba09b92562ba2364ba124c0a061b199e17eac637cd25a5e2/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:62698275682bf121181861295c9181e789030a2d516071f5b8f3c23c170cd0fc", size = 611187, upload-time = "2026-06-30T07:15:28.931Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/31/774212ed989c62f7f310220089f9b0a3fb8f40f5443d1727abd5d9f52bc9/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a214c993455f99a89aaeadc9b21241900037adc9d97203e374d75513c5911822", size = 573030, upload-time = "2026-06-30T07:15:30.553Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/50/22f73127a41f1ce4f87fe39aadfb9a126345801c274aa93ae88456249327/rpds_py-2026.6.3-cp312-cp312-win32.whl", hash = "sha256:501f9f04a588d6a09179368c57071301445191767c64e4b52a6aa9871f1ef5ed", size = 202185, upload-time = "2026-06-30T07:15:32.027Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/3a/f0ee4d4dde9d3b69dedf1b5f74e7a40017046d55052d173e418c6a94f960/rpds_py-2026.6.3-cp312-cp312-win_amd64.whl", hash = "sha256:2c958bf94822e9290a40aaf2a822d4bc5c88099093e3948ad6c571eca9272e5f", size = 220394, upload-time = "2026-06-30T07:15:33.359Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/83/3382fe37f809b59f02aac04dbc4e765b480b46ee0227ed516e3bdc4d3dfc/rpds_py-2026.6.3-cp312-cp312-win_arm64.whl", hash = "sha256:22bffe6042b9bcb0822bcd1955ec00e245daf17b4344e4ed8e9551b976b63e96", size = 215753, upload-time = "2026-06-30T07:15:34.778Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/9e/b818ee580026ec578138e961027a68820c40afeb1ec8f6819b54fb99e196/rpds_py-2026.6.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:3cfe765c1da0072636ca06628261e0ea05688e160d5c8a03e0217c3854037223", size = 343012, upload-time = "2026-06-30T07:15:36.005Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/6b/686d9dc4359a8f163cfbbf89ee0b4e586431de22fe8248edb63a8cf50d49/rpds_py-2026.6.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f4d78253f6996be4901669ad25319f842f740eccf4d58e3c7f3dd39e6dde1d8f", size = 338203, upload-time = "2026-06-30T07:15:37.462Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/9b/069aa329940f8207615e091f5eedbbd40e1e15eac68a0790fd05ccdf796c/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54f45a148e28767bf343d33a684693c70e451c6f4c0e9904709a723fafbdfc1f", size = 367984, upload-time = "2026-06-30T07:15:39.008Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/db/34c203e4becff3703e4d3bc121842c00b8689197f398161203a880052f4e/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:842e7b070435622248c7a2c44ae53fa1440e073cc3023bc919fed570884097a7", size = 374815, upload-time = "2026-06-30T07:15:40.253Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ee/7d/8071067d2cc453d916ad836e828c943f575e8a44612537759002a1e07381/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8020133a74bd81b4572dd8e4be028a6b1ebcd70e6726edc3918008c08bee6ee6", size = 490545, upload-time = "2026-06-30T07:15:41.729Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/42/da06c5aa8f0484ff07f270787434204d9f4535e2f8c3b51ed402267e63c3/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cdc7e35386f3847df728fbcb5e887e2d79c19e2fa1eba9e51b6621d23e3243af", size = 382828, upload-time = "2026-06-30T07:15:43.327Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/d7/fe978efc2ae50abe48eb7464668ea99f53c010c60aeebb7b35ad27f23661/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acac386b453c2516111b50985d60ce46e7fadb5ea71ae7b25f4c946935bf27cf", size = 365678, upload-time = "2026-06-30T07:15:44.992Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/69/9d/1d8922e1990b2a6eb532b6ff53d3e73d2b3bbffc84116c75826bee73dfc6/rpds_py-2026.6.3-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:425560c6fa0415f27261727bb20bd097568485e5eb0c121f1949417d1c516885", size = 377811, upload-time = "2026-06-30T07:15:46.523Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/3d/198dceafb4fb034a6a47347e1b0735d34e0bd4a50be4e898d408ee66cb14/rpds_py-2026.6.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a550fb4950a06dde3beb4721f5ad4b25bf4513784665b0a8522c792e2bd822a4", size = 395382, upload-time = "2026-06-30T07:15:47.955Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1f/f1/13968e49655d40b6b19d8b9140296bbc6f1d86b3f0f6c346cf9f1adddf4b/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f4bca01b63096f606e095734dd56e74e175f94cfbf24ff3d63281cec61f7bb7", size = 543832, upload-time = "2026-06-30T07:15:49.33Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ac/ab/289bcb1b90bd3e40a2900c561fa0e2087345ecbb094f0b870f2345142b7c/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ccffae9a092a00deb7efd545fe5e2c33c33b88e7c054337e9a74c179347d0b7d", size = 611011, upload-time = "2026-06-30T07:15:50.847Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/16/5043105e679436ccfbc8e5e0dd2d663ed18a8b8113515fd06a5e5d77c83e/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1cf01971c4f2c5553b772a542e4aaf191789cd331bc2cd4ff0e6e65ba49e1e97", size = 572431, upload-time = "2026-06-30T07:15:52.394Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/85/ed/adab103321c0a6565d5ae1c2998349bc3ee175b82ccc5ae8fc04cc413075/rpds_py-2026.6.3-cp313-cp313-win32.whl", hash = "sha256:8c3d1e9c15b9d51ca0391e13da1a25a0a4df3c58a37c9dc368e0736cf7f69df0", size = 201710, upload-time = "2026-06-30T07:15:53.894Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/ed/a03b09668e74e5dabbf2e211f6468e1820c0552f7b0500082da31841bf7b/rpds_py-2026.6.3-cp313-cp313-win_amd64.whl", hash = "sha256:9250a9a0a6fd4648b3f868da8d91a4c52b5811a62df58e753d50ae4454a36f80", size = 219454, upload-time = "2026-06-30T07:15:55.25Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/17/b8642c12930b71bc2b25831f6708ccf0f75abcd11883932ec9ce54ba3a78/rpds_py-2026.6.3-cp313-cp313-win_arm64.whl", hash = "sha256:900a67df3fd1660b035a4761c4ce73c382ea6b35f90f9863c36c6fd8bf8b09bb", size = 215063, upload-time = "2026-06-30T07:15:56.573Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b6/36/7fbe9dcdaf857fb3f63c2a2284b62492d95f5e8334e947e5fb6e7f68c9be/rpds_py-2026.6.3-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:931908d9fc855d8f74783377822be318edb6dcb19e47169dc038f9a1bf60b06e", size = 344510, upload-time = "2026-06-30T07:15:57.921Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/54/f785cc3d3f60839ca57a5af4927a9f347b07b2799c373fc20f7949f87c7e/rpds_py-2026.6.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d7469697dce35be237db177d42e2a2ee26e6dcc5fc052078a6fefabd288c6edd", size = 339495, upload-time = "2026-06-30T07:15:59.238Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/63/ef/d4cdaf309e6b095b43597103cf8c0b951d6cca2acce68c474f75ec12e0c7/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcfbcf66006befb9fd2aeaa9e01feaf881b4dc330a02ba07d2322b1c11be7b5d", size = 369454, upload-time = "2026-06-30T07:16:01.021Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/4a/9559a68b7ee15db09d7981212e8c2e219d2a1d6d4faa0391d813c3496a36/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:847927daf4cffbd4e90e42bc890069897101edd015f956cb8721b3473372edda", size = 374583, upload-time = "2026-06-30T07:16:02.287Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/75/8964aa7d2c6e8ac43eba8eb6e6b0fdda1f46d39f2fc3e6aa9f2cb17f485d/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aca6c1ef08a82bfe327cc156da694660f599923e2e6665b6d81c9c2d0ac9ffc8", size = 492919, upload-time = "2026-06-30T07:16:03.723Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/97/6908094ac804115e65aedfd90f1b5fee4eebebd3f6c4cfc5419939267565/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ae50181a047c871561212bb97f7932a2d45fb53e947bd9b57ebad85b529cbc53", size = 383725, upload-time = "2026-06-30T07:16:05.305Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/9c/0d1fdc2e7aba23e290d603bc494e97bd205bae262ce33c6b32a69768ed5e/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc319e5a1de4b6913aac94bf6a2f9e847371e0a140a43dd4991db1a09bc2d504", size = 367255, upload-time = "2026-06-30T07:16:07.086Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/fe/f0209ca4a9ed074bc8acb44dfd0e81c3122e94c9689f5645b7973a866719/rpds_py-2026.6.3-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:e4316bf32babbed84e691e352faf967ce2f0f024174a8643c37c94a1080374fc", size = 379060, upload-time = "2026-06-30T07:16:08.525Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/8d/f1cc54c616b9d8897de8738aac148d20afca93f68187475fe194d09a71b9/rpds_py-2026.6.3-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8c6e5a2f750cc71c3e3b11d71661f21d6f9bc6cebc6564b1466417a1ec03ec77", size = 395960, upload-time = "2026-06-30T07:16:09.989Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/04/aafff00f73aeca2945f734f1d483c64ab8f472d0864ab02377fd8e89c3b2/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4470ce197d4090875cf6affbf1f853338387428df97c4fb7b7106317b8214698", size = 545356, upload-time = "2026-06-30T07:16:11.816Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/cc/e229663b9e4ddac5a4acbe9085dd80a71af2a5d356b8b39d6bff233f24b0/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ea964164cc9afa72d4d9b23cc28dafae93693c0a53e0b42acbff15b22c3f9ddd", size = 612319, upload-time = "2026-06-30T07:16:13.586Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/7a/8a0e6d3e6cd066af108b71b43122c3fe158dd9eb86acac626593a2582eb1/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:639c8929aa0afe81be836b04de888460d6bed38b9c54cfc18da8f6bfabf5af5d", size = 573508, upload-time = "2026-06-30T07:16:15.23Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/03/2a69ab618a789cf6cf85c86bb844c62d090e700ab1a2aa676b3741b6c516/rpds_py-2026.6.3-cp314-cp314-win32.whl", hash = "sha256:882076c00c0a608b131187055ddc5ae29f2e7eaf870d6168980420d58528a5c8", size = 202504, upload-time = "2026-06-30T07:16:16.893Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/85/62/a3892ba945f4e24c78f352e5de3c7620d8479f73f211406a97263d13c7d2/rpds_py-2026.6.3-cp314-cp314-win_amd64.whl", hash = "sha256:0be972be84cfcaf46c8c6edf690ca0f154ac17babf1f6a955a51579b34ad2dc5", size = 220380, upload-time = "2026-06-30T07:16:18.108Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/e7/c2bd44dc831931815ad11ebb5f430b5a0a4d3caa9de837107876c30c3432/rpds_py-2026.6.3-cp314-cp314-win_arm64.whl", hash = "sha256:2a9c6f195058cb45335e8cc3802745c603d716eb96bc9625950c1aac71c0c703", size = 215976, upload-time = "2026-06-30T07:16:19.654Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/79/9c/fff7b74bce9a091ec9a012a03f9ff5f69364eaf9451060dfc4486da2ffdd/rpds_py-2026.6.3-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:f90938e92afda60266da758ee7d363447f7f0138c9559f9e1811629580582d90", size = 346840, upload-time = "2026-06-30T07:16:21.268Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/44/77bcb1168b33704908295533d27f10eb811e9e3e193e8993dc99572211d3/rpds_py-2026.6.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ec829541c45bca16e61c7ae50c20501f213605beb75d1aba91a6ee37fbbb56a4", size = 340282, upload-time = "2026-06-30T07:16:22.875Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/3c/7a9081c7c9e645b39efe19e4ffbeccd80add246327cd9b888aecffd72317/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afd70d95892096cdb26f15a00c45907b17817577aa8d1c76b2dcc2788391f9e9", size = 370403, upload-time = "2026-06-30T07:16:24.415Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f7/69/af47021eb7dad6ff3396cb001c08f0f3c4d06c20253f75be6421a59fe6b7/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29dfa0533a5d4c94d4dfa1b694fcb56c9c63aad8330ffdd816fd225d0a7a162f", size = 376055, upload-time = "2026-06-30T07:16:26.111Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/81/fc/a3bcf517084396a6dd258c592567a3c011ba4557f2fde23dceaf26e74f2e/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:af05d726809bff6b141be124d4c7ce998f9c9c7f30edb1f46c07aa103d540b41", size = 494419, upload-time = "2026-06-30T07:16:27.596Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/eb/13d529d1788135425c7bf207f8463458ca5d92e43f3f701365b83e9dffc1/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9826217f048f620d9a712672818bf231442c1b35d96b227a07eabd11b4bb6945", size = 384848, upload-time = "2026-06-30T07:16:29.183Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8e/f4/b7ac49f30013aba8f7b9566b1dd07e81de95e708c1374b7bacc5b9bc5c9c/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:536bceea4fa4acf7e1c61da2b5786304367c816c8895be71b8f537c480b0ea1f", size = 371369, upload-time = "2026-06-30T07:16:30.912Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/31/86/6260bafa622f788b07ddec0e52d810305c8b9b0b8c27f58a2ab04bf62b4f/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:bc0011654b91cc4fb2ae701bec0a0ba1e552c0714247fa7af6c59e0ccfa3a4e1", size = 379673, upload-time = "2026-06-30T07:16:32.486Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/c3/03f1ee79a047b48daeca157c89a18509cde22b6b951d642b9b0af1be660a/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:539d75de9e0d536c84ff18dfeb805398e58227001ce09231a26a08b9aed1ee0e", size = 397500, upload-time = "2026-06-30T07:16:34.471Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/95/8ed0cd8c377dca12aea498f119fe639fc474d1461545c39d2b5872eb1c0f/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:166cf54d9f44fc6ceb53c7860258dde44a81406646de79f8ed3234fca3b6e538", size = 545978, upload-time = "2026-06-30T07:16:36.45Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/f2/0eb57f0eaa83f8fc152a7e03de968ab77e1f00732bebc892b190c6eebde7/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:d34c20167764fbcf927194d532dd7e0c56772f0a5f943fa5ef9e9afbba8fb9db", size = 613350, upload-time = "2026-06-30T07:16:38.213Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/de/e0674bdbc3ef7634989b3f854c3f34bc1f587d36e5bfdc5c378d57034619/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ea7bb13b7c9a29791f87a0387ba7d3ad3a6d783d827e4d3f27b40a0ff44495e2", size = 576486, upload-time = "2026-06-30T07:16:39.797Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/f6/21101359743cd136ada781e8210a85769578422ba460672eea0e29739200/rpds_py-2026.6.3-cp314-cp314t-win32.whl", hash = "sha256:6de4744d05bd1aa1be4ed7ea1189e3979196808008113bbbf899a460966b925e", size = 201068, upload-time = "2026-06-30T07:16:41.316Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/b2/9574d4d44f7760c2aa32d92a0a4f41698e33f5b204a0bf5c9758f52c79d5/rpds_py-2026.6.3-cp314-cp314t-win_amd64.whl", hash = "sha256:c7b9a2f8f4d8e90af72571d3d495deebdd7e3c75451f5b41719aee166e940fc2", size = 220600, upload-time = "2026-06-30T07:16:43.091Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/08/ae/f23a2697e6ee6340a578b0f136be6483657bef0c6f9497b752bb5c0964bb/rpds_py-2026.6.3-cp315-cp315-macosx_10_12_x86_64.whl", hash = "sha256:e059c5dde6452b44424bd1834557556c226b57781dee1227af23518459722b13", size = 344726, upload-time = "2026-06-30T07:16:44.5Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/63/e7b3a1a5358dd32c930a1062d8e15b67fd6e8922e81df9e91706d66ee5c8/rpds_py-2026.6.3-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:2f7c26fbc5acd2522b95d4177fe4710ffd8e9b20529e703ffbf8db4d93903f05", size = 339587, upload-time = "2026-06-30T07:16:46.255Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/64/10a85681916ca55fffb91b0a211f84e34297c109243484dd6394660a8a7c/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3086b538543802f84c843911242db20447de00d8752dd0efc936dbcf02218ba", size = 369585, upload-time = "2026-06-30T07:16:48.101Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/c2/baf95c7c38823e12ba34407c5f5767a89e5cf2233895e56f608167ae9493/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8f2e5c5ee828d42cb11760761c0af6507927bec42d0ad5458f97c9203b054617", size = 375479, upload-time = "2026-06-30T07:16:49.93Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/94/0aad06c72d65101e11d33528d438cda99a39ce0da99466e156158f2541d3/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed0c1e5d10cdc7135537988c74a0188da68e2f3c30813ba3744ab1e42e0480f9", size = 492418, upload-time = "2026-06-30T07:16:51.641Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/17/de3f5a479a1f056535d7489819639d8cd591ea6281d700390b43b1abd745/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c2642a7603ec0b16ed77da4555db3b4b472341904873788327c0b0d7b95f1bb", size = 384123, upload-time = "2026-06-30T07:16:53.622Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/7d/bf09bd1b145bb2671c03e1e6d1ab8651858d90d8c7dfeadd85a37a934fd8/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e4320744c1ffdd95a603def63344bfab2d33edeab301c5007e7de9f9f5b3885", size = 367351, upload-time = "2026-06-30T07:16:55.241Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/ea/1bb734f314b8be319149ddee80b18bd41372bdcfbdf88d28131c0cd37719/rpds_py-2026.6.3-cp315-cp315-manylinux_2_31_riscv64.whl", hash = "sha256:a9f4645593036b81bbdb36b9c8e0ea0d1c3fee968c4d59db0344c14087ef143a", size = 378827, upload-time = "2026-06-30T07:16:56.841Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/93/d9611e5b25e26df9a3649813ed66193ace9347a7c7fc4ab7cf70e94851c0/rpds_py-2026.6.3-cp315-cp315-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e55d236be29255554da47abe5c577637db7c24a02b8b46f0ca9524c855801868", size = 395966, upload-time = "2026-06-30T07:16:58.557Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/cb/99d77e16e5534ae1d90629bbe419ba6ee170833a6a85e3aa1cc41726fbbc/rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:24e9c5386e16669b674a69c156c8eeefcb578f3b3397b713b08e6d60f3c7b187", size = 545680, upload-time = "2026-06-30T07:17:00.164Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/15/11a29755f790cef7a2f755e8e14f4f0c33f39489e1893a632a2eee59672b/rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:c60924535c75f1566b6eb75b5c31a48a43fef04fa2d0d201acbad8a9969c6107", size = 611853, upload-time = "2026-06-30T07:17:01.962Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/86/0c27547e21644da938fb530f7e1a8148dd24d02db07e7a5f2567a17ce710/rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:38a2fea2787428f811719ceb9114cb78964a3138838320c29ac39526c79c16ba", size = 573715, upload-time = "2026-06-30T07:17:03.693Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/29/71/4d8fcf700931815594bce892255bbd973b94efaf0fc1932b0590df18d886/rpds_py-2026.6.3-cp315-cp315-win32.whl", hash = "sha256:d483fe17f01ad64b7bf7cc38fcefff1ca9fb83f8c2b2542b68f97ffe0611b369", size = 202864, upload-time = "2026-06-30T07:17:05.746Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/62/b577562de0edbb55b2be85ce5fd09c33e386b9b13eee09833af4240fd5c4/rpds_py-2026.6.3-cp315-cp315-win_amd64.whl", hash = "sha256:67e3a721ffc5d8d2210d3671872298c4a84e4b8035cfe42ffd7cde35d772b146", size = 220430, upload-time = "2026-06-30T07:17:07.471Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/95/d6d0b2509825141eef60669a5739eec88dbc6a48053d6c92993a5704defe/rpds_py-2026.6.3-cp315-cp315-win_arm64.whl", hash = "sha256:6e84adbcf4bf841aed8116a8264b9f50b4cb3e7bd89b516122e616ac56ca269e", size = 215877, upload-time = "2026-06-30T07:17:09.008Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/bf/f3ea278f0afd615c1d0f19cb69043a41526e2bb600c2b536eb192218eb27/rpds_py-2026.6.3-cp315-cp315t-macosx_10_12_x86_64.whl", hash = "sha256:ae6dd8f10bd17aad820876d24caec9efdafd80a318d16c0a48edb5e136902c6b", size = 346933, upload-time = "2026-06-30T07:17:10.762Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/29/9907bdf1c5346763cf10b7f6852aad86652168c259def904cbe0082c5864/rpds_py-2026.6.3-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:bdbd97738551fca3917c1bd7188bec1920bb520104f28e7e1007f9ceb17b7690", size = 340274, upload-time = "2026-06-30T07:17:12.266Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/2c/8e03767b5778ef25cebf74a7a91a2c3806f8eced4c92cb7406bbe060756d/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b95977e7211527ab0ba576e286d023389fbeeb32a6b7b771665d333c60e5342", size = 370763, upload-time = "2026-06-30T07:17:14.107Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/e1/df2a7e1ba2efd796af26194250b8d42c821b46592311595162af9ef0528d/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d15fde0e6fb0d88a60d221204873743e5d9f0b7d29165e62cd86d0413ad74ba6", size = 376467, upload-time = "2026-06-30T07:17:15.76Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/de/8a0814d1946af29cb068fb259aa8622f856df1d0bab58429448726b537f5/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a136d453475ac0fcbda502ef1e6504bd28d6d904700915d278deeab0d00fe140", size = 496689, upload-time = "2026-06-30T07:17:17.308Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/df/f3/f19e0c852ba13694f5a79f3b719331051573cb5693feacf8a88ffffc3a71/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f826877d462181e5eb1c26a0026b8d0cab05d99844ecb6d8bf3627a2ca0c0442", size = 385340, upload-time = "2026-06-30T07:17:18.928Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/ae/7ec3a9d2d4351f99e37bcb06b6b6f954512646bfdbf9742e1de727865daf/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79486287de1730dbaff3dbd124d0ca4d2ef7f9d29bf2544f1f93c09b5bcbbd12", size = 372179, upload-time = "2026-06-30T07:17:20.539Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/ac/9cee911dff2aaa9a5a8354f6610bf2e6a616de9197c5fff4f54f82585f1e/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_31_riscv64.whl", hash = "sha256:808345f53cb952433ca2816f1604ff3515608a81784954f38d4452acfe8e61d5", size = 379993, upload-time = "2026-06-30T07:17:22.212Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/6b/7c2a07ba88d1e9a936612f7a5d067467ed03d971d5a06f7d309dff044a7e/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1967debc37f64f2c4dc90a7f563aec558b471966e12adcac4e1c4240496b6ebf", size = 398909, upload-time = "2026-06-30T07:17:23.66Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/0b/776ffcb66783637b0031f6d58d6fb55913c8b5abf00aeecd46bf933fb477/rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:f0840b5b17057f7fd918b76183a4b5a0635f43e14eb2ce60dce1d4ee4707ea00", size = 546584, upload-time = "2026-06-30T07:17:25.264Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/55/33/ba3bc04d7092bd553c9b2b195624992d2cc4f3de1f380b7b93cbee67bd79/rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:faa679d19a6696fd54259ad321251ad77a13e70e03dd834daa762a44fb6196ef", size = 614357, upload-time = "2026-06-30T07:17:26.888Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/71/14edf065f04630b1a8472f7653cad03f6c478bcf95ea0e6aed55451e33ea/rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:23a439f31ccbeff1574e24889128821d1f7917470e830cf6544dced1c662262a", size = 576533, upload-time = "2026-06-30T07:17:28.546Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/76/65002b08596c389105720a8c0d22298b8dc25a4baf89b2ce431343c8b1de/rpds_py-2026.6.3-cp315-cp315t-win32.whl", hash = "sha256:913ca42ccad3f8cc6e292b587ae8ae49c8c823e5dce51a736252fc7c7cdfa577", size = 201204, upload-time = "2026-06-30T07:17:30.193Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/97/d855d6b3c322d1f27e26f5241c42016b56cf01377ea8ed348285f54652f0/rpds_py-2026.6.3-cp315-cp315t-win_amd64.whl", hash = "sha256:ae3d4fe8c0b9213624fdce7279d70e3b148b682ca20719ebd193a23ebfa47324", size = 220719, upload-time = "2026-06-30T07:17:31.788Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sortedcontainers"
|
||||
version = "2.4.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594, upload-time = "2021-05-16T22:03:42.897Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575, upload-time = "2021-05-16T22:03:41.177Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "starlette"
|
||||
version = "1.3.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "anyio" },
|
||||
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/eb/e3/7c1dc7381d9f8ab7d854328ebfa884e62cb3f3d8549ddfd37c7814f42afa/starlette-1.3.1.tar.gz", hash = "sha256:05d0213193f2fbaae60e2ecb593b4add4262ad4e46536b54abe36f11a71724e0", size = 2703240, upload-time = "2026-06-12T09:23:11.602Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/bb/2799cc2ede3ed41131f8975621e7213dfc7ef4acbbaadfa440f32500c370/starlette-1.3.1-py3-none-any.whl", hash = "sha256:c7372aae11c3c3f26a42df7bd626cec2f47d03483d261d369516a615a53714c6", size = 73632, upload-time = "2026-06-12T09:23:10.017Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.15.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-inspection"
|
||||
version = "0.4.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uvicorn"
|
||||
version = "0.49.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "h11" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c4/1f/fa18009dea8469069cca78a4e877a008ab78f08b064bfc9ab891579077ff/uvicorn-0.49.0.tar.gz", hash = "sha256:ebf4271aa580d9de97f93192d4595176df6e91f9aae919ca73e4fc07df1e66a3", size = 91284, upload-time = "2026-06-03T22:01:30.448Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/88/fa/e1388bbcf24ef3274f45c0c1c7b501fd14971037c1b6ee23610553307497/uvicorn-0.49.0-py3-none-any.whl", hash = "sha256:ba3d14c3ee7e41c6c654c46c9eb489d33213cdd30aa1696eab1374337c13f68f", size = 71376, upload-time = "2026-06-03T22:01:29.037Z" },
|
||||
]
|
||||
Loading…
Reference in a new issue