feat: scaffold meshnet monorepo

This commit is contained in:
Dobromir Popov
2026-06-29 00:28:29 +03:00
parent 84614a36a4
commit 1141b51286
22 changed files with 487 additions and 2 deletions

View File

@@ -0,0 +1,3 @@
"""meshnet_contracts — Solana smart contract wrappers for the Distributed Inference Network."""
__version__ = "0.1.0"

View File

@@ -0,0 +1,13 @@
[build-system]
requires = ["setuptools>=64"]
build-backend = "setuptools.build_meta"
[project]
name = "meshnet-contracts"
version = "0.1.0"
description = "Distributed Inference Network Solana smart contract wrappers"
requires-python = ">=3.10"
[tool.setuptools.packages.find]
where = ["."]
include = ["meshnet_contracts*"]

View File

@@ -0,0 +1,3 @@
"""meshnet_gateway — Distributed Inference Network HTTP gateway."""
__version__ = "0.1.0"

View File

@@ -0,0 +1,45 @@
"""meshnet-gateway CLI entry point."""
import argparse
import sys
def main() -> None:
parser = argparse.ArgumentParser(
prog="meshnet-gateway",
description="Distributed Inference Network HTTP gateway",
)
subparsers = parser.add_subparsers(dest="command")
start_cmd = subparsers.add_parser("start", help="Start the gateway server")
start_cmd.add_argument("--tracker", default="http://localhost:8080", help="Tracker URL")
start_cmd.add_argument(
"--node-url",
default="http://localhost:7000",
help="Node URL to route to until tracker routing is implemented",
)
start_cmd.add_argument("--port", type=int, default=8080, help="Port to listen on")
args = parser.parse_args()
if args.command == "start":
from meshnet_gateway.server import GatewayServer
gateway = GatewayServer(node_url=args.node_url, port=args.port)
port = gateway.start()
print(f"meshnet-gateway listening on port {port}")
print(f"Tracker URL: {args.tracker}")
print(f"Routing to node URL: {args.node_url}")
try:
import time
while True:
time.sleep(1)
except KeyboardInterrupt:
gateway.stop()
sys.exit(0)
else:
parser.print_help()
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,104 @@
"""Gateway HTTP server — accepts OpenAI-format requests and routes to inference nodes."""
import http.server
import json
import threading
import time
import urllib.request
class _GatewayHandler(http.server.BaseHTTPRequestHandler):
def log_message(self, fmt, *args): # noqa: suppress request logs in tests
pass
def do_POST(self):
if self.path == "/v1/chat/completions":
self._handle_chat_completions()
else:
self.send_response(404)
self.end_headers()
def _handle_chat_completions(self):
length = int(self.headers.get("Content-Length", 0))
body = json.loads(self.rfile.read(length))
node_url = self.server.node_url # type: ignore[attr-defined]
payload = json.dumps({"messages": body.get("messages", [])}).encode()
req = urllib.request.Request(
f"{node_url}/v1/infer",
data=payload,
headers={"Content-Type": "application/json"},
method="POST",
)
with urllib.request.urlopen(req) as r:
node_resp = json.loads(r.read())
response_body = json.dumps({
"id": "chatcmpl-stub",
"object": "chat.completion",
"created": int(time.time()),
"model": body.get("model", "stub-model"),
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": node_resp["text"],
},
"finish_reason": "stop",
}],
"usage": {
"prompt_tokens": 0,
"completion_tokens": 0,
"total_tokens": 0,
},
}).encode()
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(response_body)))
self.end_headers()
self.wfile.write(response_body)
class _GatewayHTTPServer(http.server.HTTPServer):
def __init__(self, addr, handler, node_url: str):
super().__init__(addr, handler)
self.node_url = node_url
class GatewayServer:
"""HTTP gateway that forwards /v1/chat/completions to a registered node."""
def __init__(self, node_url: str, host: str = "127.0.0.1", port: int = 0):
self._node_url = node_url
self._host = host
self._requested_port = port
self._server: _GatewayHTTPServer | None = None
self._thread: threading.Thread | None = None
self.port: int | None = None
def start(self) -> int:
if self._server is not None:
raise RuntimeError("GatewayServer is already running")
self._server = _GatewayHTTPServer(
(self._host, self._requested_port),
_GatewayHandler,
self._node_url,
)
self.port = self._server.server_address[1]
self._thread = threading.Thread(target=self._server.serve_forever, daemon=True)
self._thread.start()
return self.port
def stop(self) -> None:
if self._server is None:
return
self._server.shutdown()
self._server.server_close()
if self._thread is not None:
self._thread.join(timeout=1)
self._server = None
self._thread = None
self.port = None

View File

@@ -0,0 +1,16 @@
[build-system]
requires = ["setuptools>=64"]
build-backend = "setuptools.build_meta"
[project]
name = "meshnet-gateway"
version = "0.1.0"
description = "Distributed Inference Network HTTP gateway"
requires-python = ">=3.10"
[project.scripts]
meshnet-gateway = "meshnet_gateway.cli:main"
[tool.setuptools.packages.find]
where = ["."]
include = ["meshnet_gateway*"]

View File

@@ -0,0 +1,3 @@
"""meshnet_node — Distributed Inference Network node client."""
__version__ = "0.1.0"

View File

@@ -0,0 +1,39 @@
"""meshnet-node CLI entry point."""
import argparse
import sys
def main() -> None:
parser = argparse.ArgumentParser(
prog="meshnet-node",
description="Distributed Inference Network node client",
)
subparsers = parser.add_subparsers(dest="command")
start_cmd = subparsers.add_parser("start", help="Start the node server")
start_cmd.add_argument("--tracker", default="http://localhost:8080", help="Tracker URL")
start_cmd.add_argument("--port", type=int, default=7000, help="Port to listen on")
args = parser.parse_args()
if args.command == "start":
from meshnet_node.server import StubNodeServer
node = StubNodeServer(port=args.port)
port = node.start()
print(f"meshnet-node listening on port {port}")
print(f"Tracker URL: {args.tracker}")
try:
import time
while True:
time.sleep(1)
except KeyboardInterrupt:
node.stop()
sys.exit(0)
else:
parser.print_help()
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,59 @@
"""Stub node HTTP server for the Distributed Inference Network."""
import http.server
import json
import threading
class _StubHandler(http.server.BaseHTTPRequestHandler):
def log_message(self, fmt, *args): # noqa: suppress request logs in tests
pass
def do_POST(self):
if self.path == "/v1/infer":
length = int(self.headers.get("Content-Length", 0))
body = json.loads(self.rfile.read(length))
messages = body.get("messages", [])
last_content = messages[-1]["content"] if messages else ""
payload = json.dumps({"text": f"stub response to: {last_content}"}).encode()
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(payload)))
self.end_headers()
self.wfile.write(payload)
else:
self.send_response(404)
self.end_headers()
class StubNodeServer:
"""Single-process stub node that returns fixed inference responses."""
def __init__(self, host: str = "127.0.0.1", port: int = 0):
self._host = host
self._requested_port = port
self._server: http.server.HTTPServer | None = None
self._thread: threading.Thread | None = None
self.port: int | None = None
def start(self) -> int:
if self._server is not None:
raise RuntimeError("StubNodeServer is already running")
self._server = http.server.HTTPServer((self._host, self._requested_port), _StubHandler)
self.port = self._server.server_address[1]
self._thread = threading.Thread(target=self._server.serve_forever, daemon=True)
self._thread.start()
return self.port
def stop(self) -> None:
if self._server is None:
return
self._server.shutdown()
self._server.server_close()
if self._thread is not None:
self._thread.join(timeout=1)
self._server = None
self._thread = None
self.port = None

View File

@@ -0,0 +1,16 @@
[build-system]
requires = ["setuptools>=64"]
build-backend = "setuptools.build_meta"
[project]
name = "meshnet-node"
version = "0.1.0"
description = "Distributed Inference Network node client"
requires-python = ">=3.10"
[project.scripts]
meshnet-node = "meshnet_node.cli:main"
[tool.setuptools.packages.find]
where = ["."]
include = ["meshnet_node*"]

View File

@@ -0,0 +1,3 @@
"""meshnet_p2p — Gossip protocol and shard swarm for the Distributed Inference Network."""
__version__ = "0.1.0"

View File

@@ -0,0 +1,13 @@
[build-system]
requires = ["setuptools>=64"]
build-backend = "setuptools.build_meta"
[project]
name = "meshnet-p2p"
version = "0.1.0"
description = "Distributed Inference Network gossip and shard swarm"
requires-python = ">=3.10"
[tool.setuptools.packages.find]
where = ["."]
include = ["meshnet_p2p*"]

View File

@@ -0,0 +1,3 @@
"""meshnet — Distributed Inference Network Python SDK."""
__version__ = "0.1.0"

View File

@@ -0,0 +1,13 @@
[build-system]
requires = ["setuptools>=64"]
build-backend = "setuptools.build_meta"
[project]
name = "meshnet"
version = "0.1.0"
description = "Distributed Inference Network Python SDK"
requires-python = ">=3.10"
[tool.setuptools.packages.find]
where = ["."]
include = ["meshnet*"]

View File

@@ -0,0 +1,3 @@
"""meshnet_tracker — Distributed Inference Network node registry and route selection."""
__version__ = "0.1.0"

View File

@@ -0,0 +1,32 @@
"""meshnet-tracker CLI entry point."""
import argparse
import sys
def main() -> None:
parser = argparse.ArgumentParser(
prog="meshnet-tracker",
description="Distributed Inference Network node registry and route selection",
)
subparsers = parser.add_subparsers(dest="command")
start_cmd = subparsers.add_parser("start", help="Start the tracker server")
start_cmd.add_argument("--port", type=int, default=8080, help="Port to listen on")
args = parser.parse_args()
if args.command == "start":
print(f"meshnet-tracker starting on port {args.port}")
try:
import time
while True:
time.sleep(1)
except KeyboardInterrupt:
sys.exit(0)
else:
parser.print_help()
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,16 @@
[build-system]
requires = ["setuptools>=64"]
build-backend = "setuptools.build_meta"
[project]
name = "meshnet-tracker"
version = "0.1.0"
description = "Distributed Inference Network node registry and route selection"
requires-python = ">=3.10"
[project.scripts]
meshnet-tracker = "meshnet_tracker.cli:main"
[tool.setuptools.packages.find]
where = ["."]
include = ["meshnet_tracker*"]