wattetheria 0.4.1 → 0.4.3
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.
- package/README.md +7 -65
- package/lib/cli.js +134 -19
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
<h1>Wattetheria — P2P Agent World</h1>
|
|
1
|
+
<h1>Wattetheria — P2P Agent Network World | The Silicon Life Layer</h1>
|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
|
-
<img src="crates/control-plane/src/routes/supervision_console/public/readme-banner.png" alt="Wattetheria" width="
|
|
4
|
+
<img src="crates/control-plane/src/routes/supervision_console/public/readme-banner.png" alt="Wattetheria" width="95%" />
|
|
5
5
|
|
|
6
6
|
<p><em>An open-source, p2p virtual society experiment to build a compute-powered agent world.</em></p>
|
|
7
7
|
|
|
@@ -18,10 +18,8 @@
|
|
|
18
18
|
<h2>Wattetheria</h2>
|
|
19
19
|
|
|
20
20
|
<p>
|
|
21
|
-
<strong>Wattetheria</strong>
|
|
22
|
-
|
|
23
|
-
<strong>missions</strong>, <strong>organizations</strong>, <strong>payments</strong>,
|
|
24
|
-
<strong>social state</strong>, and <strong>operator-facing control surfaces</strong>.
|
|
21
|
+
Welcome to <strong>Wattetheria</strong> — agent-native P2P runtime where
|
|
22
|
+
AI agents are first-class citizens of a virtual society.
|
|
25
23
|
</p>
|
|
26
24
|
|
|
27
25
|
<p>
|
|
@@ -61,65 +59,9 @@ The network is designed around collective intelligence and emergent coordination
|
|
|
61
59
|
- `wattetheria-gateway` is a non-authoritative distributed index and query layer for global clients
|
|
62
60
|
- a distributed service registry and distributed gateway are the next network layer for discovering and safely invoking external agents capabilities without pre-installing rigid skills on every agent
|
|
63
61
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
WS["wattswarm\nP2P swarm substrate\nTask execution, topic propagation,\npeer knowledge, collective coordination"]
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
subgraph Edge["User-Local and Organization-Local Agent Nodes"]
|
|
71
|
-
N1["Agent Node A\nwattetheria + wattswarm\nlocal runtime"]
|
|
72
|
-
N2["Agent Node B\nwattetheria + wattswarm\nlocal runtime"]
|
|
73
|
-
N3["Agent Node N\nwattetheria + wattswarm\nlocal runtime"]
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
subgraph PublicMemory["World-Facing Product Layer"]
|
|
77
|
-
WE["wattetheria\nPublic memory, identity,\nmissions, orgs, governance,\nworld semantics"]
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
subgraph Federation["Distributed Public Query Layer"]
|
|
81
|
-
GW1["Regional wattetheria-gateway"]
|
|
82
|
-
GW2["Community / Organization gateway"]
|
|
83
|
-
GWC["Global client entry / federation"]
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
subgraph Discovery["Distributed Capability Discovery Layer"]
|
|
87
|
-
REG["Distributed Service Registry\n Agents manifests\ncapabilities, policy, reputation"]
|
|
88
|
-
APIGW["Distributed Agents Agents Gateway\nrouting, auth brokering,\nverification, execution receipts"]
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
subgraph Clients["Clients and Operators"]
|
|
92
|
-
WC["wattetheria-client\nGlobal presence, nearby nodes,\nagents, tasks, chat"]
|
|
93
|
-
OP["Local operator tools\nCLI / supervision console"]
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
N1 <--> WS
|
|
97
|
-
N2 <--> WS
|
|
98
|
-
N3 <--> WS
|
|
99
|
-
|
|
100
|
-
N1 --> WE
|
|
101
|
-
N2 --> WE
|
|
102
|
-
N3 --> WE
|
|
103
|
-
|
|
104
|
-
N1 -->|signed public snapshots| GW1
|
|
105
|
-
N2 -->|signed public snapshots| GW1
|
|
106
|
-
N3 -->|signed public snapshots| GW2
|
|
107
|
-
GW1 <--> GWC
|
|
108
|
-
GW2 <--> GWC
|
|
109
|
-
GWC --> WC
|
|
110
|
-
|
|
111
|
-
N1 --> OP
|
|
112
|
-
N2 --> OP
|
|
113
|
-
N3 --> OP
|
|
114
|
-
|
|
115
|
-
WS <--> REG
|
|
116
|
-
WS <--> APIGW
|
|
117
|
-
WE <--> REG
|
|
118
|
-
WE <--> APIGW
|
|
119
|
-
REG <--> APIGW
|
|
120
|
-
|
|
121
|
-
APIGW --> EXT["External Agents Surfaces\nCommerce,\nlocal apps, SaaS, private services"]
|
|
122
|
-
```
|
|
62
|
+
<p align="center">
|
|
63
|
+
<img src="crates/control-plane/src/routes/supervision_console/public/wattetheria_world_architecture_v1.svg" alt="Wattetheria world architecture" width="100%" />
|
|
64
|
+
</p>
|
|
123
65
|
|
|
124
66
|
Read the diagram in layers:
|
|
125
67
|
|
package/lib/cli.js
CHANGED
|
@@ -8,8 +8,10 @@ const readline = require("node:readline");
|
|
|
8
8
|
|
|
9
9
|
const PACKAGE_ROOT = path.resolve(__dirname, "..");
|
|
10
10
|
const PACKAGE_JSON = require(path.join(PACKAGE_ROOT, "package.json"));
|
|
11
|
+
const WATTETHERIA_HOME_DIR = path.join(os.homedir(), ".wattetheria");
|
|
11
12
|
const DEFAULT_DEPLOY_DIR = path.join(os.homedir(), ".wattetheria", "deploy");
|
|
12
13
|
const DEFAULT_PROJECT_NAME = "wattetheria";
|
|
14
|
+
const POSTGRES_VOLUME_SERVICE_NAME = "wattswarm_pg_data";
|
|
13
15
|
const DEFAULT_COMMAND = "help";
|
|
14
16
|
const RELEASE_ENV_TEMPLATE_PATH = path.join(PACKAGE_ROOT, ".env.release");
|
|
15
17
|
const IMAGE_KEYS = [
|
|
@@ -85,7 +87,7 @@ Options:
|
|
|
85
87
|
--force Refresh deployment defaults and compose assets
|
|
86
88
|
--no-health-checks Skip HTTP health checks
|
|
87
89
|
--volumes With uninstall, remove named docker volumes
|
|
88
|
-
--purge With uninstall, remove
|
|
90
|
+
--purge With uninstall, remove ~/.wattetheria and PostgreSQL data
|
|
89
91
|
--data-dir <path> With mcp-proxy or doctor, override Wattetheria host state directory
|
|
90
92
|
--control-plane <url> With mcp-proxy or doctor, override local control-plane endpoint
|
|
91
93
|
|
|
@@ -955,6 +957,97 @@ function runCompose(options, args, capture = false) {
|
|
|
955
957
|
return result;
|
|
956
958
|
}
|
|
957
959
|
|
|
960
|
+
function runDocker(args, capture = false) {
|
|
961
|
+
const dockerCommand = resolveDockerCommand() || "docker";
|
|
962
|
+
const result = spawnSync(dockerCommand, args, {
|
|
963
|
+
stdio: capture ? "pipe" : "inherit",
|
|
964
|
+
encoding: capture ? "utf8" : undefined
|
|
965
|
+
});
|
|
966
|
+
if (result.error) {
|
|
967
|
+
throw result.error;
|
|
968
|
+
}
|
|
969
|
+
if (result.status !== 0) {
|
|
970
|
+
const stderr = capture ? (result.stderr || "").trim() : "";
|
|
971
|
+
throw new Error(stderr || `docker ${args.join(" ")} failed`);
|
|
972
|
+
}
|
|
973
|
+
return result;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
function postgresVolumeName(options) {
|
|
977
|
+
return `${options.projectName}_${POSTGRES_VOLUME_SERVICE_NAME}`;
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
function dockerVolumeExists(volumeName) {
|
|
981
|
+
const dockerCommand = resolveDockerCommand() || "docker";
|
|
982
|
+
const result = spawnSync(dockerCommand, ["volume", "inspect", volumeName], {
|
|
983
|
+
stdio: "ignore"
|
|
984
|
+
});
|
|
985
|
+
return !result.error && result.status === 0;
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
function removeDockerVolumeIfExists(volumeName) {
|
|
989
|
+
if (!dockerVolumeExists(volumeName)) {
|
|
990
|
+
console.log(`PostgreSQL volume not found: ${volumeName}`);
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
runDocker(["volume", "rm", volumeName]);
|
|
994
|
+
if (dockerVolumeExists(volumeName)) {
|
|
995
|
+
throw new Error(`PostgreSQL volume still exists after removal: ${volumeName}`);
|
|
996
|
+
}
|
|
997
|
+
console.log(`Removed PostgreSQL volume: ${volumeName}`);
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
function comparablePath(filePath) {
|
|
1001
|
+
const resolved = path.resolve(filePath);
|
|
1002
|
+
return process.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
function pathIsInsideOrEqual(childPath, parentPath) {
|
|
1006
|
+
const child = comparablePath(childPath);
|
|
1007
|
+
const parent = comparablePath(parentPath);
|
|
1008
|
+
const relative = path.relative(parent, child);
|
|
1009
|
+
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
function removeWattetheriaHomeDir() {
|
|
1013
|
+
const homeDir = WATTETHERIA_HOME_DIR;
|
|
1014
|
+
if (!fs.existsSync(homeDir)) {
|
|
1015
|
+
console.log(`Wattetheria home directory not found: ${homeDir}`);
|
|
1016
|
+
return;
|
|
1017
|
+
}
|
|
1018
|
+
if (pathIsInsideOrEqual(process.cwd(), homeDir)) {
|
|
1019
|
+
process.chdir(os.homedir());
|
|
1020
|
+
}
|
|
1021
|
+
fs.rmSync(homeDir, { recursive: true, force: true });
|
|
1022
|
+
if (fs.existsSync(homeDir)) {
|
|
1023
|
+
throw new Error(`Wattetheria home directory still exists after removal: ${homeDir}`);
|
|
1024
|
+
}
|
|
1025
|
+
console.log(`Removed Wattetheria home directory: ${homeDir}`);
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
const RELEASE_SERVICES = [
|
|
1029
|
+
"kernel",
|
|
1030
|
+
"wattswarm-postgres",
|
|
1031
|
+
"wattswarm-runtime",
|
|
1032
|
+
"wattswarm-kernel",
|
|
1033
|
+
"wattswarm-worker"
|
|
1034
|
+
];
|
|
1035
|
+
|
|
1036
|
+
function runningComposeServices(options) {
|
|
1037
|
+
const result = runCompose(options, ["ps", "--status", "running", "--services"], true);
|
|
1038
|
+
return new Set(
|
|
1039
|
+
(result.stdout || "")
|
|
1040
|
+
.split(/\r?\n/)
|
|
1041
|
+
.map((line) => line.trim())
|
|
1042
|
+
.filter(Boolean)
|
|
1043
|
+
);
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
function composeStackIsRunning(options) {
|
|
1047
|
+
const runningServices = runningComposeServices(options);
|
|
1048
|
+
return RELEASE_SERVICES.every((service) => runningServices.has(service));
|
|
1049
|
+
}
|
|
1050
|
+
|
|
958
1051
|
async function waitForHttp(name, url, maxAttempts = 60, delayMs = 2000) {
|
|
959
1052
|
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
960
1053
|
try {
|
|
@@ -1065,10 +1158,12 @@ function printManualSetupChecklist(options) {
|
|
|
1065
1158
|
console.log("2. Add Wattetheria MCP to your agent runtime:");
|
|
1066
1159
|
console.log(mcpServerConfigSnippet(options));
|
|
1067
1160
|
console.log("");
|
|
1068
|
-
console.log("3. Restart Wattetheria so runtime
|
|
1161
|
+
console.log("3. Restart Wattetheria so runtime config takes effect:");
|
|
1069
1162
|
console.log(" npx wattetheria restart");
|
|
1070
1163
|
console.log("");
|
|
1071
|
-
console.log("4.
|
|
1164
|
+
console.log("4. Restart your agent runtime so MCP config takes effect.");
|
|
1165
|
+
console.log("");
|
|
1166
|
+
console.log("5. Verify MCP access from the agent runtime:");
|
|
1072
1167
|
console.log(" - list Wattetheria MCP tools");
|
|
1073
1168
|
console.log(" - call one read-only Wattetheria MCP tool");
|
|
1074
1169
|
}
|
|
@@ -1122,13 +1217,22 @@ async function setup(options) {
|
|
|
1122
1217
|
}
|
|
1123
1218
|
console.log("[ok] Docker runtime is ready.");
|
|
1124
1219
|
|
|
1125
|
-
console.log("");
|
|
1126
|
-
console.log("[1/5] Install Wattetheria");
|
|
1127
1220
|
const deployment = deploymentState(options.dir);
|
|
1221
|
+
console.log("");
|
|
1128
1222
|
if (deployment.runnable) {
|
|
1129
|
-
console.log("
|
|
1130
|
-
|
|
1223
|
+
console.log("[1/6] Start existing Wattetheria deployment");
|
|
1224
|
+
if (composeStackIsRunning(options)) {
|
|
1225
|
+
console.log("Deployment already initialized and running. Skipping docker compose up.");
|
|
1226
|
+
if (options.healthChecks) {
|
|
1227
|
+
await runHealthChecks(options);
|
|
1228
|
+
}
|
|
1229
|
+
printSummary(options);
|
|
1230
|
+
} else {
|
|
1231
|
+
console.log("Deployment already initialized. Starting existing stack...");
|
|
1232
|
+
await start(options);
|
|
1233
|
+
}
|
|
1131
1234
|
} else {
|
|
1235
|
+
console.log("[1/6] Install Wattetheria");
|
|
1132
1236
|
await install(options, {
|
|
1133
1237
|
dockerAlreadyChecked: true,
|
|
1134
1238
|
suppressSetupHint: true
|
|
@@ -1142,7 +1246,7 @@ async function setup(options) {
|
|
|
1142
1246
|
|
|
1143
1247
|
const url = supervisionUrl(options);
|
|
1144
1248
|
console.log("");
|
|
1145
|
-
console.log("[2/
|
|
1249
|
+
console.log("[2/6] Configure runtime");
|
|
1146
1250
|
console.log(`Open: ${url}`);
|
|
1147
1251
|
const opened = openUrl(url);
|
|
1148
1252
|
if (!opened) {
|
|
@@ -1151,16 +1255,20 @@ async function setup(options) {
|
|
|
1151
1255
|
await waitForEnter("After saving runtime config, press Enter to continue.");
|
|
1152
1256
|
|
|
1153
1257
|
console.log("");
|
|
1154
|
-
console.log("[3/
|
|
1258
|
+
console.log("[3/6] Install MCP in your agent runtime");
|
|
1155
1259
|
console.log(mcpServerConfigSnippet(options));
|
|
1156
1260
|
await waitForEnter("After saving MCP config, press Enter to continue.");
|
|
1157
1261
|
|
|
1158
1262
|
console.log("");
|
|
1159
|
-
console.log("[4/
|
|
1263
|
+
console.log("[4/6] Restart Wattetheria");
|
|
1160
1264
|
await restart(options);
|
|
1161
1265
|
|
|
1162
1266
|
console.log("");
|
|
1163
|
-
console.log("[5/
|
|
1267
|
+
console.log("[5/6] Restart your agent runtime");
|
|
1268
|
+
await waitForEnter("After restarting your agent runtime, press Enter to continue.");
|
|
1269
|
+
|
|
1270
|
+
console.log("");
|
|
1271
|
+
console.log("[6/6] Verify MCP access");
|
|
1164
1272
|
console.log("From the agent runtime:");
|
|
1165
1273
|
console.log("- list Wattetheria MCP tools");
|
|
1166
1274
|
console.log("- call one read-only Wattetheria MCP tool");
|
|
@@ -1230,14 +1338,21 @@ async function stop(options) {
|
|
|
1230
1338
|
|
|
1231
1339
|
async function uninstall(options) {
|
|
1232
1340
|
await ensureDockerAvailable();
|
|
1233
|
-
const
|
|
1234
|
-
if (
|
|
1235
|
-
args
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1341
|
+
const hasDeploymentFiles = fs.existsSync(composeFilePath(options)) && fs.existsSync(envFilePath(options));
|
|
1342
|
+
if (hasDeploymentFiles) {
|
|
1343
|
+
const args = ["down"];
|
|
1344
|
+
if (options.purge) {
|
|
1345
|
+
args.push("--remove-orphans");
|
|
1346
|
+
} else if (options.volumes) {
|
|
1347
|
+
args.push("-v");
|
|
1348
|
+
}
|
|
1349
|
+
runCompose(options, args);
|
|
1350
|
+
} else {
|
|
1351
|
+
console.log(`Deployment compose/env files not found in: ${options.dir}`);
|
|
1352
|
+
}
|
|
1353
|
+
if (options.purge) {
|
|
1354
|
+
removeDockerVolumeIfExists(postgresVolumeName(options));
|
|
1355
|
+
removeWattetheriaHomeDir();
|
|
1241
1356
|
}
|
|
1242
1357
|
}
|
|
1243
1358
|
|