shugonet 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- shugonet-0.5.0/LICENSE +21 -0
- shugonet-0.5.0/PKG-INFO +325 -0
- shugonet-0.5.0/README.md +301 -0
- shugonet-0.5.0/agent_registry.py +176 -0
- shugonet-0.5.0/audit.py +183 -0
- shugonet-0.5.0/bluetooth_transport.py +314 -0
- shugonet-0.5.0/dashboard.py +465 -0
- shugonet-0.5.0/discovery.py +191 -0
- shugonet-0.5.0/fallbacks.py +135 -0
- shugonet-0.5.0/link_simulator.py +264 -0
- shugonet-0.5.0/lora_transport.py +320 -0
- shugonet-0.5.0/memory_sync.py +646 -0
- shugonet-0.5.0/mesh_query.py +203 -0
- shugonet-0.5.0/pg_store.py +202 -0
- shugonet-0.5.0/policy.py +41 -0
- shugonet-0.5.0/protocol.py +550 -0
- shugonet-0.5.0/pyproject.toml +37 -0
- shugonet-0.5.0/relay_server.py +299 -0
- shugonet-0.5.0/relay_transport.py +241 -0
- shugonet-0.5.0/security.py +63 -0
- shugonet-0.5.0/setup.cfg +4 -0
- shugonet-0.5.0/shugocore_adapter.py +147 -0
- shugonet-0.5.0/shugocore_bridge.py +223 -0
- shugonet-0.5.0/shugonet.egg-info/PKG-INFO +325 -0
- shugonet-0.5.0/shugonet.egg-info/SOURCES.txt +63 -0
- shugonet-0.5.0/shugonet.egg-info/dependency_links.txt +1 -0
- shugonet-0.5.0/shugonet.egg-info/entry_points.txt +2 -0
- shugonet-0.5.0/shugonet.egg-info/requires.txt +18 -0
- shugonet-0.5.0/shugonet.egg-info/top_level.txt +27 -0
- shugonet-0.5.0/shugonet_client.py +419 -0
- shugonet-0.5.0/shugonet_runtime.py +181 -0
- shugonet-0.5.0/shugonet_web/__init__.py +16 -0
- shugonet-0.5.0/shugonet_web/static/assets/index-BQCxUM6l.css +1 -0
- shugonet-0.5.0/shugonet_web/static/assets/index-CDOtMJAn.js +1 -0
- shugonet-0.5.0/shugonet_web/static/index.html +15 -0
- shugonet-0.5.0/store_forward.py +169 -0
- shugonet-0.5.0/tcp_transport.py +446 -0
- shugonet-0.5.0/telemetry.py +53 -0
- shugonet-0.5.0/tests/test_agent_registry.py +121 -0
- shugonet-0.5.0/tests/test_audit.py +79 -0
- shugonet-0.5.0/tests/test_bluetooth.py +157 -0
- shugonet-0.5.0/tests/test_bridge_sync.py +66 -0
- shugonet-0.5.0/tests/test_concurrency.py +375 -0
- shugonet-0.5.0/tests/test_dashboard.py +258 -0
- shugonet-0.5.0/tests/test_discovery.py +73 -0
- shugonet-0.5.0/tests/test_fallbacks.py +109 -0
- shugonet-0.5.0/tests/test_host.py +201 -0
- shugonet-0.5.0/tests/test_integration.py +284 -0
- shugonet-0.5.0/tests/test_link_simulator.py +154 -0
- shugonet-0.5.0/tests/test_lora.py +227 -0
- shugonet-0.5.0/tests/test_memory_compat.py +256 -0
- shugonet-0.5.0/tests/test_memory_sync.py +198 -0
- shugonet-0.5.0/tests/test_mesh_query.py +123 -0
- shugonet-0.5.0/tests/test_pg_mirror.py +81 -0
- shugonet-0.5.0/tests/test_protocol.py +201 -0
- shugonet-0.5.0/tests/test_relay.py +192 -0
- shugonet-0.5.0/tests/test_shugocore.py +106 -0
- shugonet-0.5.0/tests/test_store_forward.py +100 -0
- shugonet-0.5.0/tests/test_tcp_transport.py +120 -0
- shugonet-0.5.0/tests/test_transport_fallback.py +229 -0
- shugonet-0.5.0/tests/test_transports.py +171 -0
- shugonet-0.5.0/tests/test_version_handshake.py +153 -0
- shugonet-0.5.0/transport_fallback.py +326 -0
- shugonet-0.5.0/transports.py +243 -0
- shugonet-0.5.0/version.py +30 -0
shugonet-0.5.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SamurAI-Official
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
shugonet-0.5.0/PKG-INFO
ADDED
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: shugonet
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: Networking integration for connecting multiple Shugocore agents together for collaboration between Shugocore agents in simulation and physical spaces, designed to be used over 5G, 4G, EDGE, LoRa, Wifi-Halow, Wifi, and Bluetooth networks.
|
|
5
|
+
Author: SamurAI-Official
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: agent,networking,mesh,memory,fallback,shugocore
|
|
8
|
+
Requires-Python: >=3.9
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Provides-Extra: ws
|
|
12
|
+
Requires-Dist: websocket-client>=1.6; extra == "ws"
|
|
13
|
+
Provides-Extra: relay
|
|
14
|
+
Requires-Dist: requests>=2.32.0; extra == "relay"
|
|
15
|
+
Provides-Extra: serial
|
|
16
|
+
Requires-Dist: pyserial>=3.5; extra == "serial"
|
|
17
|
+
Provides-Extra: ble
|
|
18
|
+
Requires-Dist: bleak>=0.20; extra == "ble"
|
|
19
|
+
Provides-Extra: telemetry
|
|
20
|
+
Requires-Dist: opentelemetry-api>=1.20; extra == "telemetry"
|
|
21
|
+
Provides-Extra: postgres
|
|
22
|
+
Requires-Dist: psycopg2-binary>=2.9; extra == "postgres"
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# Shogunet
|
|
26
|
+
|
|
27
|
+
> Networking integration for connecting multiple Shugocore agents together for
|
|
28
|
+
> collaboration between Shugocore agents in simulation and physical spaces,
|
|
29
|
+
> designed to be used over 5G, 4G, EDGE, LoRa, Wifi-Halow, Wifi, and Bluetooth
|
|
30
|
+
> networks.
|
|
31
|
+
|
|
32
|
+
[](https://pypi.org/project/shugonet/)
|
|
33
|
+

|
|
34
|
+

|
|
35
|
+

|
|
36
|
+

|
|
37
|
+
|
|
38
|
+
## Installation
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install shugonet
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The core is dependency-free (stdlib-only). Optional extras:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install shugonet[postgres] # PostgreSQL mesh backend (PgSemanticMemory parity)
|
|
48
|
+
pip install shugonet[ws] # rosbridge-style WebSocket transport
|
|
49
|
+
pip install shugonet[relay] # HTTPS relay transport (5G/4G/EDGE)
|
|
50
|
+
pip install shugonet[serial] # LoRa SX126x/SX127x serial modules
|
|
51
|
+
pip install shugonet[ble] # BLE transport
|
|
52
|
+
pip install shugonet[telemetry] # OpenTelemetry integration
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The compiled fleet dashboard ships inside the wheel — no JavaScript toolchain
|
|
56
|
+
is needed at install time.
|
|
57
|
+
|
|
58
|
+
Shogunet is the networking layer for [ShugoCore](https://github.com/SamurAI-Official/ShugoCore).
|
|
59
|
+
It lets a fleet of ShugoCore agents — running in Gazebo simulation, on servers,
|
|
60
|
+
on robots, or on Android handsets — discover each other, exchange tasks and
|
|
61
|
+
events, and consolidate a *codependent* memory mesh, over whatever networks the
|
|
62
|
+
mission has available, with deterministic fallback between them.
|
|
63
|
+
|
|
64
|
+
## Design principles
|
|
65
|
+
|
|
66
|
+
**One protocol, every network.** A single versioned envelope is spoken over all
|
|
67
|
+
transports, from 5G to LoRa. Two codecs exist for it: a JSON codec for
|
|
68
|
+
broadband links and a compact binary codec (16-byte header + TLV payload) for
|
|
69
|
+
constrained links such as LoRa (0.3–27 kbit/s, ~220-byte frames) and BLE.
|
|
70
|
+
|
|
71
|
+
**Memory invariants survive the network.** ShugoCore's memory tiers map to
|
|
72
|
+
network tiers: Tier 0/1 never leave the agent (N0). Tier 2 semantic facts sync
|
|
73
|
+
between paired agents (N1). Tier 3 is read-only everywhere: only *promotion
|
|
74
|
+
proposals* travel, and application stays operator-attributed (N2).
|
|
75
|
+
|
|
76
|
+
**Codependent memory.** Facts propagate with provenance
|
|
77
|
+
`(origin_agent_id, fact_id)`; salience merges additively; pruning propagates as
|
|
78
|
+
tombstones; and reinforcement is a *feedback loop* — when a peer's fact proves
|
|
79
|
+
useful, a tiny `reinforce` message flows back so useful memories survive decay
|
|
80
|
+
fleet-wide. Over LoRa, the loop runs on ~50-byte digest frames; bulk fact
|
|
81
|
+
content moves later over any broadband link (digest anti-entropy).
|
|
82
|
+
|
|
83
|
+
**Pairing is consent.** Only operator-allowlisted agent IDs pair, grants carry
|
|
84
|
+
TTLs, topics are namespaced (`/shugunet/{agent_id}/{topic}`), and every
|
|
85
|
+
ingress/egress field is sanitized and size-capped. Every network event lands in
|
|
86
|
+
a hash-chained audit log.
|
|
87
|
+
|
|
88
|
+
**Deterministic fallback.** Transports form an ordered, health-ranked chain
|
|
89
|
+
with per-transport circuit breakers. If the LAN drops, traffic falls to the
|
|
90
|
+
relay; if everything drops, a bounded store-and-forward WAL replays on
|
|
91
|
+
reconnect. Total transport exhaustion latches the ShugoCore governor through
|
|
92
|
+
its fallback triggers instead of failing silently.
|
|
93
|
+
|
|
94
|
+
## Network tiers
|
|
95
|
+
|
|
96
|
+
| Class | Networks | Protocol response |
|
|
97
|
+
|---|---|---|
|
|
98
|
+
| Broadband IP | 5G, 4G, WiFi | JSON codec, mesh query fan-out, bulk sync; LAN = direct TCP, cellular = relay hub |
|
|
99
|
+
| Midband IP | EDGE, WiFi-Halow | Compact codec, batching, latency-tolerant profiles |
|
|
100
|
+
| Constrained | LoRa | 16-byte header frames ≤ 220 B, P0/P1 priority only, digest anti-entropy, duty-cycle honored |
|
|
101
|
+
| Short-range | Bluetooth (RFCOMM/BLE) | Stream framing or segmented compact codec; pairing-based discovery |
|
|
102
|
+
|
|
103
|
+
Message priority classes: **P0** control (announce/heartbeat/ack/tombstone) →
|
|
104
|
+
all links · **P1** memory deltas (facts/reinforce/digests) → constrained-capable
|
|
105
|
+
· **P2** tasks and queries → IP links · **P3** bulk snapshots and audit
|
|
106
|
+
shipping → broadband only, deferred under low power / thermal pressure.
|
|
107
|
+
|
|
108
|
+
## Module map
|
|
109
|
+
|
|
110
|
+
| Module | Responsibility |
|
|
111
|
+
|---|---|
|
|
112
|
+
| `protocol.py` | Envelope schema, 16-byte binary header, JSON + compact TLV codecs, segmentation, validation |
|
|
113
|
+
| `transports.py` | `BaseTransport`, `LinkProfile` registry (7 networks + loopback), loopback bus |
|
|
114
|
+
| `link_simulator.py` | In-process impairment: bandwidth, latency, jitter, loss, MTU, duty cycle |
|
|
115
|
+
| `discovery.py` | Per-medium peer discovery (multicast beacons, hub rendezvous, pairing, duty-cycled LoRa) |
|
|
116
|
+
| `agent_registry.py` | Pairing = consent, allowlists, TTL grants, topic ACLs, sim/phys manifests |
|
|
117
|
+
| `tcp_transport.py` | Length-prefixed TCP transport with announce handshake (WiFi / WiFi-Halow profiles) |
|
|
118
|
+
| `relay_transport.py` / `relay_server.py` | Cellular path: HTTPS relay hub + long-poll client (5G/4G/EDGE, cross-NAT) |
|
|
119
|
+
| `lora_transport.py` | Serial SX126x/SX127x point-to-point transport (optional `pyserial`) |
|
|
120
|
+
| `bluetooth_transport.py` | RFCOMM (AF_BLUETOOTH) and BLE (optional `bleak`) transports |
|
|
121
|
+
| `transport_fallback.py` | Link-aware chain: eligibility, EWMA health ranking, breakers, QoS |
|
|
122
|
+
| `store_forward.py` | Bounded JSONL WAL outbox/inbox with replay + dedup |
|
|
123
|
+
| `memory_sync.py` / `mesh_query.py` | Codependent memory mesh: fact replication, conflict resolution, fan-out queries |
|
|
124
|
+
| `audit.py`, `fallbacks.py`, `policy.py`, `telemetry.py` | ShugoCore-aligned safety surface |
|
|
125
|
+
| `shugocore_bridge.py` | Adapter hosting a Shogunet node beside a ShugoCore `DecisionEngine` |
|
|
126
|
+
|
|
127
|
+
## Hosting a fleet
|
|
128
|
+
|
|
129
|
+
Shogunet runs as a single server process that owns the fleet's trust plane so
|
|
130
|
+
every ShugoCore agent only needs a ~20-line client runtime to join.
|
|
131
|
+
|
|
132
|
+
### Start a host
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
from host import ShugonetHost
|
|
136
|
+
|
|
137
|
+
host = ShugonetHost(agent_id="fleet-1", tcp_port=9000, relay_port=9001)
|
|
138
|
+
host.start()
|
|
139
|
+
|
|
140
|
+
# Grant consent to a joining agent (pairing = consent)
|
|
141
|
+
host.pair("agent-001", manifest={"realm": "phys", "role": "perception"})
|
|
142
|
+
|
|
143
|
+
print(host.status()) # roster, alive count, breaker health, mesh counts
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Or from the CLI:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
python3 host.py --tcp-port 9000 --relay-port 9001
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Join from a ShugoCore process
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
from shugonet_runtime import ShugonetAgentRuntime
|
|
156
|
+
|
|
157
|
+
runtime = ShugonetAgentRuntime(
|
|
158
|
+
agent_id="agent-001",
|
|
159
|
+
host_tcp_host="127.0.0.1",
|
|
160
|
+
host_tcp_port=9000,
|
|
161
|
+
host_relay_url="http://127.0.0.1:9001",
|
|
162
|
+
on_message=lambda sender, msg: print(f"from {sender}: {msg}"))
|
|
163
|
+
runtime.connect_to_host()
|
|
164
|
+
|
|
165
|
+
# Send a task to another agent
|
|
166
|
+
runtime.send("agent-002", "/shugunet/agent-001/task",
|
|
167
|
+
{"action": "scan", "zone": "north"})
|
|
168
|
+
|
|
169
|
+
# Search the fleet's memory
|
|
170
|
+
results = runtime.query("obstacle in zone north")
|
|
171
|
+
|
|
172
|
+
# Sync memory with the fleet
|
|
173
|
+
runtime.sync()
|
|
174
|
+
|
|
175
|
+
# Leave the fleet
|
|
176
|
+
runtime.stop()
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Cross-platform CLI client
|
|
180
|
+
|
|
181
|
+
Shogunet ships a standard CLI client that works on macOS, Linux, and Windows:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
# Install (ships with the wheel)
|
|
185
|
+
pip install shugonet
|
|
186
|
+
|
|
187
|
+
# Connect and stay connected (foreground daemon)
|
|
188
|
+
shugonet-client run
|
|
189
|
+
|
|
190
|
+
# One-shot status
|
|
191
|
+
shugonet-client status
|
|
192
|
+
|
|
193
|
+
# One-shot send to a peer
|
|
194
|
+
shugonet-client send agent-002 /shugunet/agent-001/task '{"action":"scan"}'
|
|
195
|
+
|
|
196
|
+
# One-shot memory query
|
|
197
|
+
shugonet-client query "obstacle in zone north"
|
|
198
|
+
|
|
199
|
+
# One-shot digest sync
|
|
200
|
+
shugonet-client sync agent-002
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
The client is configured via environment variables:
|
|
204
|
+
|
|
205
|
+
| Variable | Default | Description |
|
|
206
|
+
|---|---|---|
|
|
207
|
+
| `SHUGONET_AGENT_ID` | hostname | Agent identifier |
|
|
208
|
+
| `SHUGONET_HOST` | 127.0.0.1 | ShugonetHost address |
|
|
209
|
+
| `SHUGONET_TCP_PORT` | 9000 | TCP port |
|
|
210
|
+
| `SHUGONET_RELAY_URL` | *(none)* | Relay hub URL |
|
|
211
|
+
| `SHUGONET_REALM` | phys | sim or phys realm |
|
|
212
|
+
| `SHUGONET_LOG_LEVEL` | info | Log verbosity |
|
|
213
|
+
|
|
214
|
+
Or use it programmatically:
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
from shugonet_client import ShugonetClient
|
|
218
|
+
|
|
219
|
+
client = ShugonetClient(agent_id="robot-1", host="10.0.0.5", tcp_port=9000)
|
|
220
|
+
client.connect()
|
|
221
|
+
client.send("robot-2", "/shugunet/robot-1/status", {"battery": 87})
|
|
222
|
+
print(client.status())
|
|
223
|
+
client.disconnect()
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Routing model
|
|
227
|
+
|
|
228
|
+
Agents connect **to** the host (hub-and-spoke). The host forwards addressed
|
|
229
|
+
mail to its recipient and fans broadcasts out as addressed copies to every
|
|
230
|
+
other paired agent. Host-addressed mail — heartbeats, mesh queries, memory
|
|
231
|
+
broadcasts — is processed locally by the host's own chain handlers.
|
|
232
|
+
|
|
233
|
+
**Pairing is enforced twice** — at TCP admission (handshake hook) and again on
|
|
234
|
+
every host-processed or forwarded envelope (the relay path has no registry gate
|
|
235
|
+
of its own, so the host re-checks the sender there).
|
|
236
|
+
|
|
237
|
+
### Failure semantics
|
|
238
|
+
|
|
239
|
+
- **Agent crash/disconnect** → host governor latches `pause` (ShugoCore
|
|
240
|
+
deterministic latch contract).
|
|
241
|
+
- **Message durability** → per-agent `OutboxStore` + `at_least_once` QoS + hub
|
|
242
|
+
mailbox TTL bounds.
|
|
243
|
+
- **Cross-talk** → chain and mesh recipient guards (hardened in the
|
|
244
|
+
concurrency suite) hold at host scale.
|
|
245
|
+
|
|
246
|
+
### Fleet dashboard
|
|
247
|
+
|
|
248
|
+
Every `ShugunetHost` can expose an operator console — a compiled single-page
|
|
249
|
+
app (TypeScript + SolidJS, built with Vite) served directly by the host over a
|
|
250
|
+
loopback HTTP port. No JavaScript toolchain is needed at install time: the
|
|
251
|
+
built assets ship inside the wheel (`shugonet_web/static`).
|
|
252
|
+
|
|
253
|
+
```python
|
|
254
|
+
host = ShugonetHost(agent_id="fleet-1", tcp_port=9000, relay_port=9001,
|
|
255
|
+
dashboard_port=9002)
|
|
256
|
+
host.start()
|
|
257
|
+
# open http://127.0.0.1:9002 in a browser
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
The console streams a live event feed (Server-Sent Events), shows the roster,
|
|
261
|
+
transport-chain health, memory-mesh counters, and audit-chain integrity, and
|
|
262
|
+
exposes pair / unpair / resume / broadcast controls. State-changing POSTs are
|
|
263
|
+
audited and can be gated by a token (`dashboard_token=...`).
|
|
264
|
+
|
|
265
|
+
The SPA source lives in `dashboard/`; rebuild it with:
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
cd dashboard && npm ci && npm run build
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## Module map (continued)
|
|
272
|
+
|
|
273
|
+
| Module | Responsibility |
|
|
274
|
+
|---|---|
|
|
275
|
+
| `host.py` | `ShugunetHost`: admit paired agents, route traffic, seed the mesh |
|
|
276
|
+
| `shugonet_runtime.py` | `ShugonetAgentRuntime`: client half a ShugoCore process instantiates |
|
|
277
|
+
| `shugonet_client.py` | `ShugonetClient`: cross-platform CLI and programmatic client |
|
|
278
|
+
| `dashboard.py` | `DashboardServer`: stdlib HTTP operator plane (REST + SSE + SPA) |
|
|
279
|
+
| `pg_store.py` | `PgFactStore`: optional PostgreSQL mesh backend (ShugoCore `PgSemanticMemory` parity) |
|
|
280
|
+
|
|
281
|
+
## Testing
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
python3 -m unittest discover -s tests -v
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
The suite is dependency-free and runs everywhere: transports are exercised
|
|
288
|
+
through the loopback bus and the in-process link simulator, which models every
|
|
289
|
+
network's bandwidth, latency, loss, MTU and duty-cycle constraints. The
|
|
290
|
+
integration suite spins up a real `ShugonetHost` with multiple threaded
|
|
291
|
+
`ShugonetAgentRuntime` clients, validates cross-talk isolation, memory
|
|
292
|
+
convergence, peer-lost latching, and unpaired-agent refusal.
|
|
293
|
+
|
|
294
|
+
## Changelog
|
|
295
|
+
|
|
296
|
+
### 0.5.0
|
|
297
|
+
|
|
298
|
+
- **ShugoCore 1.20.0 compatibility**: renamed ``agent_runtime.py`` to
|
|
299
|
+
``shugonet_runtime.py`` to avoid naming collision with ShugoCore's own
|
|
300
|
+
``agent_runtime`` module. All imports updated accordingly.
|
|
301
|
+
- **Cross-platform CLI client**: ``shugonet-client`` command (installed by
|
|
302
|
+
``pip``) with ``run``, ``status``, ``send``, ``query``, and ``sync``
|
|
303
|
+
subcommands. Configured via ``SHUGONET_*`` environment variables. Works
|
|
304
|
+
on macOS, Linux, and Windows.
|
|
305
|
+
- **Standard programmatic client**: ``shugonet_client.ShugonetClient`` wraps
|
|
306
|
+
the full runtime in a simple ``connect()`` / ``send()`` / ``disconnect()``
|
|
307
|
+
interface.
|
|
308
|
+
- Version bumped 0.4.0 → 0.5.0.
|
|
309
|
+
|
|
310
|
+
### 0.4.0
|
|
311
|
+
|
|
312
|
+
- **Fleet dashboard**: stdlib HTTP operator plane (`dashboard.py`) with a
|
|
313
|
+
compiled TypeScript + SolidJS SPA (`dashboard/` → `shugonet_web/static`).
|
|
314
|
+
Serves JSON REST, a live SSE event stream, and the console; ships inside the
|
|
315
|
+
wheel so no JS toolchain is needed at install time.
|
|
316
|
+
- **ShugoCore memory compatibility**: fact schema aligned with
|
|
317
|
+
`SemanticMemory` / `PgSemanticMemory` columns (`kind`, `metadata`,
|
|
318
|
+
`created_at`); `pg_store.PgFactStore` mirrors mesh facts into PostgreSQL
|
|
319
|
+
(optional `postgres` extra).
|
|
320
|
+
- **Version handshake**: `shugonet_version` + `protocol_version` exchanged at
|
|
321
|
+
TCP admission; mismatches emit a `version_mismatch` audit event and refuse
|
|
322
|
+
the join.
|
|
323
|
+
- **Bridge sync test**: `tests/test_bridge_sync.py` keeps Shogunet's
|
|
324
|
+
`shugocore_adapter` and ShugoCore's vendored `shugonet_bridge` from drifting.
|
|
325
|
+
- Version bumped 0.1.0 → 0.4.0.
|
shugonet-0.5.0/README.md
ADDED
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
# Shogunet
|
|
2
|
+
|
|
3
|
+
> Networking integration for connecting multiple Shugocore agents together for
|
|
4
|
+
> collaboration between Shugocore agents in simulation and physical spaces,
|
|
5
|
+
> designed to be used over 5G, 4G, EDGE, LoRa, Wifi-Halow, Wifi, and Bluetooth
|
|
6
|
+
> networks.
|
|
7
|
+
|
|
8
|
+
[](https://pypi.org/project/shugonet/)
|
|
9
|
+

|
|
10
|
+

|
|
11
|
+

|
|
12
|
+

|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install shugonet
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The core is dependency-free (stdlib-only). Optional extras:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install shugonet[postgres] # PostgreSQL mesh backend (PgSemanticMemory parity)
|
|
24
|
+
pip install shugonet[ws] # rosbridge-style WebSocket transport
|
|
25
|
+
pip install shugonet[relay] # HTTPS relay transport (5G/4G/EDGE)
|
|
26
|
+
pip install shugonet[serial] # LoRa SX126x/SX127x serial modules
|
|
27
|
+
pip install shugonet[ble] # BLE transport
|
|
28
|
+
pip install shugonet[telemetry] # OpenTelemetry integration
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The compiled fleet dashboard ships inside the wheel — no JavaScript toolchain
|
|
32
|
+
is needed at install time.
|
|
33
|
+
|
|
34
|
+
Shogunet is the networking layer for [ShugoCore](https://github.com/SamurAI-Official/ShugoCore).
|
|
35
|
+
It lets a fleet of ShugoCore agents — running in Gazebo simulation, on servers,
|
|
36
|
+
on robots, or on Android handsets — discover each other, exchange tasks and
|
|
37
|
+
events, and consolidate a *codependent* memory mesh, over whatever networks the
|
|
38
|
+
mission has available, with deterministic fallback between them.
|
|
39
|
+
|
|
40
|
+
## Design principles
|
|
41
|
+
|
|
42
|
+
**One protocol, every network.** A single versioned envelope is spoken over all
|
|
43
|
+
transports, from 5G to LoRa. Two codecs exist for it: a JSON codec for
|
|
44
|
+
broadband links and a compact binary codec (16-byte header + TLV payload) for
|
|
45
|
+
constrained links such as LoRa (0.3–27 kbit/s, ~220-byte frames) and BLE.
|
|
46
|
+
|
|
47
|
+
**Memory invariants survive the network.** ShugoCore's memory tiers map to
|
|
48
|
+
network tiers: Tier 0/1 never leave the agent (N0). Tier 2 semantic facts sync
|
|
49
|
+
between paired agents (N1). Tier 3 is read-only everywhere: only *promotion
|
|
50
|
+
proposals* travel, and application stays operator-attributed (N2).
|
|
51
|
+
|
|
52
|
+
**Codependent memory.** Facts propagate with provenance
|
|
53
|
+
`(origin_agent_id, fact_id)`; salience merges additively; pruning propagates as
|
|
54
|
+
tombstones; and reinforcement is a *feedback loop* — when a peer's fact proves
|
|
55
|
+
useful, a tiny `reinforce` message flows back so useful memories survive decay
|
|
56
|
+
fleet-wide. Over LoRa, the loop runs on ~50-byte digest frames; bulk fact
|
|
57
|
+
content moves later over any broadband link (digest anti-entropy).
|
|
58
|
+
|
|
59
|
+
**Pairing is consent.** Only operator-allowlisted agent IDs pair, grants carry
|
|
60
|
+
TTLs, topics are namespaced (`/shugunet/{agent_id}/{topic}`), and every
|
|
61
|
+
ingress/egress field is sanitized and size-capped. Every network event lands in
|
|
62
|
+
a hash-chained audit log.
|
|
63
|
+
|
|
64
|
+
**Deterministic fallback.** Transports form an ordered, health-ranked chain
|
|
65
|
+
with per-transport circuit breakers. If the LAN drops, traffic falls to the
|
|
66
|
+
relay; if everything drops, a bounded store-and-forward WAL replays on
|
|
67
|
+
reconnect. Total transport exhaustion latches the ShugoCore governor through
|
|
68
|
+
its fallback triggers instead of failing silently.
|
|
69
|
+
|
|
70
|
+
## Network tiers
|
|
71
|
+
|
|
72
|
+
| Class | Networks | Protocol response |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| Broadband IP | 5G, 4G, WiFi | JSON codec, mesh query fan-out, bulk sync; LAN = direct TCP, cellular = relay hub |
|
|
75
|
+
| Midband IP | EDGE, WiFi-Halow | Compact codec, batching, latency-tolerant profiles |
|
|
76
|
+
| Constrained | LoRa | 16-byte header frames ≤ 220 B, P0/P1 priority only, digest anti-entropy, duty-cycle honored |
|
|
77
|
+
| Short-range | Bluetooth (RFCOMM/BLE) | Stream framing or segmented compact codec; pairing-based discovery |
|
|
78
|
+
|
|
79
|
+
Message priority classes: **P0** control (announce/heartbeat/ack/tombstone) →
|
|
80
|
+
all links · **P1** memory deltas (facts/reinforce/digests) → constrained-capable
|
|
81
|
+
· **P2** tasks and queries → IP links · **P3** bulk snapshots and audit
|
|
82
|
+
shipping → broadband only, deferred under low power / thermal pressure.
|
|
83
|
+
|
|
84
|
+
## Module map
|
|
85
|
+
|
|
86
|
+
| Module | Responsibility |
|
|
87
|
+
|---|---|
|
|
88
|
+
| `protocol.py` | Envelope schema, 16-byte binary header, JSON + compact TLV codecs, segmentation, validation |
|
|
89
|
+
| `transports.py` | `BaseTransport`, `LinkProfile` registry (7 networks + loopback), loopback bus |
|
|
90
|
+
| `link_simulator.py` | In-process impairment: bandwidth, latency, jitter, loss, MTU, duty cycle |
|
|
91
|
+
| `discovery.py` | Per-medium peer discovery (multicast beacons, hub rendezvous, pairing, duty-cycled LoRa) |
|
|
92
|
+
| `agent_registry.py` | Pairing = consent, allowlists, TTL grants, topic ACLs, sim/phys manifests |
|
|
93
|
+
| `tcp_transport.py` | Length-prefixed TCP transport with announce handshake (WiFi / WiFi-Halow profiles) |
|
|
94
|
+
| `relay_transport.py` / `relay_server.py` | Cellular path: HTTPS relay hub + long-poll client (5G/4G/EDGE, cross-NAT) |
|
|
95
|
+
| `lora_transport.py` | Serial SX126x/SX127x point-to-point transport (optional `pyserial`) |
|
|
96
|
+
| `bluetooth_transport.py` | RFCOMM (AF_BLUETOOTH) and BLE (optional `bleak`) transports |
|
|
97
|
+
| `transport_fallback.py` | Link-aware chain: eligibility, EWMA health ranking, breakers, QoS |
|
|
98
|
+
| `store_forward.py` | Bounded JSONL WAL outbox/inbox with replay + dedup |
|
|
99
|
+
| `memory_sync.py` / `mesh_query.py` | Codependent memory mesh: fact replication, conflict resolution, fan-out queries |
|
|
100
|
+
| `audit.py`, `fallbacks.py`, `policy.py`, `telemetry.py` | ShugoCore-aligned safety surface |
|
|
101
|
+
| `shugocore_bridge.py` | Adapter hosting a Shogunet node beside a ShugoCore `DecisionEngine` |
|
|
102
|
+
|
|
103
|
+
## Hosting a fleet
|
|
104
|
+
|
|
105
|
+
Shogunet runs as a single server process that owns the fleet's trust plane so
|
|
106
|
+
every ShugoCore agent only needs a ~20-line client runtime to join.
|
|
107
|
+
|
|
108
|
+
### Start a host
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from host import ShugonetHost
|
|
112
|
+
|
|
113
|
+
host = ShugonetHost(agent_id="fleet-1", tcp_port=9000, relay_port=9001)
|
|
114
|
+
host.start()
|
|
115
|
+
|
|
116
|
+
# Grant consent to a joining agent (pairing = consent)
|
|
117
|
+
host.pair("agent-001", manifest={"realm": "phys", "role": "perception"})
|
|
118
|
+
|
|
119
|
+
print(host.status()) # roster, alive count, breaker health, mesh counts
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Or from the CLI:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
python3 host.py --tcp-port 9000 --relay-port 9001
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Join from a ShugoCore process
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
from shugonet_runtime import ShugonetAgentRuntime
|
|
132
|
+
|
|
133
|
+
runtime = ShugonetAgentRuntime(
|
|
134
|
+
agent_id="agent-001",
|
|
135
|
+
host_tcp_host="127.0.0.1",
|
|
136
|
+
host_tcp_port=9000,
|
|
137
|
+
host_relay_url="http://127.0.0.1:9001",
|
|
138
|
+
on_message=lambda sender, msg: print(f"from {sender}: {msg}"))
|
|
139
|
+
runtime.connect_to_host()
|
|
140
|
+
|
|
141
|
+
# Send a task to another agent
|
|
142
|
+
runtime.send("agent-002", "/shugunet/agent-001/task",
|
|
143
|
+
{"action": "scan", "zone": "north"})
|
|
144
|
+
|
|
145
|
+
# Search the fleet's memory
|
|
146
|
+
results = runtime.query("obstacle in zone north")
|
|
147
|
+
|
|
148
|
+
# Sync memory with the fleet
|
|
149
|
+
runtime.sync()
|
|
150
|
+
|
|
151
|
+
# Leave the fleet
|
|
152
|
+
runtime.stop()
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Cross-platform CLI client
|
|
156
|
+
|
|
157
|
+
Shogunet ships a standard CLI client that works on macOS, Linux, and Windows:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
# Install (ships with the wheel)
|
|
161
|
+
pip install shugonet
|
|
162
|
+
|
|
163
|
+
# Connect and stay connected (foreground daemon)
|
|
164
|
+
shugonet-client run
|
|
165
|
+
|
|
166
|
+
# One-shot status
|
|
167
|
+
shugonet-client status
|
|
168
|
+
|
|
169
|
+
# One-shot send to a peer
|
|
170
|
+
shugonet-client send agent-002 /shugunet/agent-001/task '{"action":"scan"}'
|
|
171
|
+
|
|
172
|
+
# One-shot memory query
|
|
173
|
+
shugonet-client query "obstacle in zone north"
|
|
174
|
+
|
|
175
|
+
# One-shot digest sync
|
|
176
|
+
shugonet-client sync agent-002
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
The client is configured via environment variables:
|
|
180
|
+
|
|
181
|
+
| Variable | Default | Description |
|
|
182
|
+
|---|---|---|
|
|
183
|
+
| `SHUGONET_AGENT_ID` | hostname | Agent identifier |
|
|
184
|
+
| `SHUGONET_HOST` | 127.0.0.1 | ShugonetHost address |
|
|
185
|
+
| `SHUGONET_TCP_PORT` | 9000 | TCP port |
|
|
186
|
+
| `SHUGONET_RELAY_URL` | *(none)* | Relay hub URL |
|
|
187
|
+
| `SHUGONET_REALM` | phys | sim or phys realm |
|
|
188
|
+
| `SHUGONET_LOG_LEVEL` | info | Log verbosity |
|
|
189
|
+
|
|
190
|
+
Or use it programmatically:
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
from shugonet_client import ShugonetClient
|
|
194
|
+
|
|
195
|
+
client = ShugonetClient(agent_id="robot-1", host="10.0.0.5", tcp_port=9000)
|
|
196
|
+
client.connect()
|
|
197
|
+
client.send("robot-2", "/shugunet/robot-1/status", {"battery": 87})
|
|
198
|
+
print(client.status())
|
|
199
|
+
client.disconnect()
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Routing model
|
|
203
|
+
|
|
204
|
+
Agents connect **to** the host (hub-and-spoke). The host forwards addressed
|
|
205
|
+
mail to its recipient and fans broadcasts out as addressed copies to every
|
|
206
|
+
other paired agent. Host-addressed mail — heartbeats, mesh queries, memory
|
|
207
|
+
broadcasts — is processed locally by the host's own chain handlers.
|
|
208
|
+
|
|
209
|
+
**Pairing is enforced twice** — at TCP admission (handshake hook) and again on
|
|
210
|
+
every host-processed or forwarded envelope (the relay path has no registry gate
|
|
211
|
+
of its own, so the host re-checks the sender there).
|
|
212
|
+
|
|
213
|
+
### Failure semantics
|
|
214
|
+
|
|
215
|
+
- **Agent crash/disconnect** → host governor latches `pause` (ShugoCore
|
|
216
|
+
deterministic latch contract).
|
|
217
|
+
- **Message durability** → per-agent `OutboxStore` + `at_least_once` QoS + hub
|
|
218
|
+
mailbox TTL bounds.
|
|
219
|
+
- **Cross-talk** → chain and mesh recipient guards (hardened in the
|
|
220
|
+
concurrency suite) hold at host scale.
|
|
221
|
+
|
|
222
|
+
### Fleet dashboard
|
|
223
|
+
|
|
224
|
+
Every `ShugunetHost` can expose an operator console — a compiled single-page
|
|
225
|
+
app (TypeScript + SolidJS, built with Vite) served directly by the host over a
|
|
226
|
+
loopback HTTP port. No JavaScript toolchain is needed at install time: the
|
|
227
|
+
built assets ship inside the wheel (`shugonet_web/static`).
|
|
228
|
+
|
|
229
|
+
```python
|
|
230
|
+
host = ShugonetHost(agent_id="fleet-1", tcp_port=9000, relay_port=9001,
|
|
231
|
+
dashboard_port=9002)
|
|
232
|
+
host.start()
|
|
233
|
+
# open http://127.0.0.1:9002 in a browser
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
The console streams a live event feed (Server-Sent Events), shows the roster,
|
|
237
|
+
transport-chain health, memory-mesh counters, and audit-chain integrity, and
|
|
238
|
+
exposes pair / unpair / resume / broadcast controls. State-changing POSTs are
|
|
239
|
+
audited and can be gated by a token (`dashboard_token=...`).
|
|
240
|
+
|
|
241
|
+
The SPA source lives in `dashboard/`; rebuild it with:
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
cd dashboard && npm ci && npm run build
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Module map (continued)
|
|
248
|
+
|
|
249
|
+
| Module | Responsibility |
|
|
250
|
+
|---|---|
|
|
251
|
+
| `host.py` | `ShugunetHost`: admit paired agents, route traffic, seed the mesh |
|
|
252
|
+
| `shugonet_runtime.py` | `ShugonetAgentRuntime`: client half a ShugoCore process instantiates |
|
|
253
|
+
| `shugonet_client.py` | `ShugonetClient`: cross-platform CLI and programmatic client |
|
|
254
|
+
| `dashboard.py` | `DashboardServer`: stdlib HTTP operator plane (REST + SSE + SPA) |
|
|
255
|
+
| `pg_store.py` | `PgFactStore`: optional PostgreSQL mesh backend (ShugoCore `PgSemanticMemory` parity) |
|
|
256
|
+
|
|
257
|
+
## Testing
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
python3 -m unittest discover -s tests -v
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
The suite is dependency-free and runs everywhere: transports are exercised
|
|
264
|
+
through the loopback bus and the in-process link simulator, which models every
|
|
265
|
+
network's bandwidth, latency, loss, MTU and duty-cycle constraints. The
|
|
266
|
+
integration suite spins up a real `ShugonetHost` with multiple threaded
|
|
267
|
+
`ShugonetAgentRuntime` clients, validates cross-talk isolation, memory
|
|
268
|
+
convergence, peer-lost latching, and unpaired-agent refusal.
|
|
269
|
+
|
|
270
|
+
## Changelog
|
|
271
|
+
|
|
272
|
+
### 0.5.0
|
|
273
|
+
|
|
274
|
+
- **ShugoCore 1.20.0 compatibility**: renamed ``agent_runtime.py`` to
|
|
275
|
+
``shugonet_runtime.py`` to avoid naming collision with ShugoCore's own
|
|
276
|
+
``agent_runtime`` module. All imports updated accordingly.
|
|
277
|
+
- **Cross-platform CLI client**: ``shugonet-client`` command (installed by
|
|
278
|
+
``pip``) with ``run``, ``status``, ``send``, ``query``, and ``sync``
|
|
279
|
+
subcommands. Configured via ``SHUGONET_*`` environment variables. Works
|
|
280
|
+
on macOS, Linux, and Windows.
|
|
281
|
+
- **Standard programmatic client**: ``shugonet_client.ShugonetClient`` wraps
|
|
282
|
+
the full runtime in a simple ``connect()`` / ``send()`` / ``disconnect()``
|
|
283
|
+
interface.
|
|
284
|
+
- Version bumped 0.4.0 → 0.5.0.
|
|
285
|
+
|
|
286
|
+
### 0.4.0
|
|
287
|
+
|
|
288
|
+
- **Fleet dashboard**: stdlib HTTP operator plane (`dashboard.py`) with a
|
|
289
|
+
compiled TypeScript + SolidJS SPA (`dashboard/` → `shugonet_web/static`).
|
|
290
|
+
Serves JSON REST, a live SSE event stream, and the console; ships inside the
|
|
291
|
+
wheel so no JS toolchain is needed at install time.
|
|
292
|
+
- **ShugoCore memory compatibility**: fact schema aligned with
|
|
293
|
+
`SemanticMemory` / `PgSemanticMemory` columns (`kind`, `metadata`,
|
|
294
|
+
`created_at`); `pg_store.PgFactStore` mirrors mesh facts into PostgreSQL
|
|
295
|
+
(optional `postgres` extra).
|
|
296
|
+
- **Version handshake**: `shugonet_version` + `protocol_version` exchanged at
|
|
297
|
+
TCP admission; mismatches emit a `version_mismatch` audit event and refuse
|
|
298
|
+
the join.
|
|
299
|
+
- **Bridge sync test**: `tests/test_bridge_sync.py` keeps Shogunet's
|
|
300
|
+
`shugocore_adapter` and ShugoCore's vendored `shugonet_bridge` from drifting.
|
|
301
|
+
- Version bumped 0.1.0 → 0.4.0.
|