@nekzus/liop 2.4.0-alpha.7 → 2.4.0-alpha.9
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/NOTICE +19 -0
- package/README.md +36 -17
- package/dist/bin/agent.js +674 -82
- package/dist/bin/agent.js.map +1 -1
- package/dist/bridge.d.ts +2 -2
- package/dist/bridge.js +3 -3
- package/dist/{chunk-T5IUZF47.js → chunk-3L2O2XKG.js} +12 -5
- package/dist/chunk-3L2O2XKG.js.map +1 -0
- package/dist/{chunk-SONUORBT.js → chunk-7BSCUYUE.js} +2 -2
- package/dist/chunk-7BSCUYUE.js.map +1 -0
- package/dist/{chunk-QLCOEP5J.js → chunk-7PITYWOV.js} +2 -2
- package/dist/chunk-7PITYWOV.js.map +1 -0
- package/dist/{chunk-74CISO2I.js → chunk-7RXOIDXP.js} +28 -4
- package/dist/chunk-7RXOIDXP.js.map +1 -0
- package/dist/{chunk-GA3Q2S7O.js → chunk-BOISQ45Z.js} +5 -5
- package/dist/chunk-BOISQ45Z.js.map +1 -0
- package/dist/{chunk-547TYL27.js → chunk-DZ2FQGJD.js} +26 -1423
- package/dist/chunk-DZ2FQGJD.js.map +1 -0
- package/dist/{chunk-PYKRQAER.js → chunk-EG46XMJT.js} +2 -2
- package/dist/chunk-EG46XMJT.js.map +1 -0
- package/dist/chunk-ESRXG36Y.js +115 -0
- package/dist/chunk-ESRXG36Y.js.map +1 -0
- package/dist/chunk-FTF6AMF6.js +3 -0
- package/dist/{chunk-RWRRBYG4.js.map → chunk-FTF6AMF6.js.map} +1 -1
- package/dist/{chunk-72MNYFR6.js → chunk-HA6YZ42O.js} +2 -2
- package/dist/chunk-HA6YZ42O.js.map +1 -0
- package/dist/{chunk-WCCGE4QR.js → chunk-HD2N3IJX.js} +144 -30
- package/dist/chunk-HD2N3IJX.js.map +1 -0
- package/dist/{chunk-OUUTDSOW.js → chunk-IK7CGWAZ.js} +3 -3
- package/dist/chunk-IK7CGWAZ.js.map +1 -0
- package/dist/chunk-L6J72C5X.js +1477 -0
- package/dist/chunk-L6J72C5X.js.map +1 -0
- package/dist/{chunk-U5BZ66VX.js → chunk-PAICJCKJ.js} +60 -175
- package/dist/chunk-PAICJCKJ.js.map +1 -0
- package/dist/{chunk-32ADSAJS.js → chunk-PEN3KFLF.js} +14 -4
- package/dist/chunk-PEN3KFLF.js.map +1 -0
- package/dist/{chunk-CRZBVFDV.js → chunk-T7R5HUFD.js} +225 -66
- package/dist/chunk-T7R5HUFD.js.map +1 -0
- package/dist/{chunk-WSW6YJNY.js → chunk-TKRX6CFI.js} +3 -3
- package/dist/chunk-TKRX6CFI.js.map +1 -0
- package/dist/chunk-UCVP3XAL.js +279 -0
- package/dist/chunk-UCVP3XAL.js.map +1 -0
- package/dist/chunk-VH4K4U45.js +180 -0
- package/dist/chunk-VH4K4U45.js.map +1 -0
- package/dist/{chunk-JIJPZFR2.js → chunk-Y62GORQF.js} +2 -2
- package/dist/chunk-Y62GORQF.js.map +1 -0
- package/dist/chunk-ZP3VVXOI.js +66 -0
- package/dist/chunk-ZP3VVXOI.js.map +1 -0
- package/dist/client.d.ts +2 -2
- package/dist/client.js +11 -8
- package/dist/gateway.d.ts +3 -3
- package/dist/gateway.js +11 -9
- package/dist/{hybrid-CF__0YnC.d.ts → hybrid-CrKB50nh.d.ts} +2 -2
- package/dist/{index-cMV0_yD9.d.ts → index-CX43dvMs.d.ts} +2 -32
- package/dist/{index-BW95kAL4.d.ts → index-DoW2gzBZ.d.ts} +3 -21
- package/dist/index.d.ts +170 -46
- package/dist/index.js +20 -15
- package/dist/index.js.map +1 -1
- package/dist/kyber-CGOA7Q6A.js +3 -0
- package/dist/{kyber-3ULIJSE3.js.map → kyber-CGOA7Q6A.js.map} +1 -1
- package/dist/mesh.d.ts +27 -143
- package/dist/mesh.js +4 -3
- package/dist/node-B0b2vUFS.d.ts +164 -0
- package/dist/protocol/liop_core.proto +3 -0
- package/dist/server.d.ts +2 -2
- package/dist/server.js +7 -6
- package/dist/types.js +1 -1
- package/dist/verifier-HRFXBKT5.js +6 -0
- package/dist/{verifier-3FAKCFNN.js.map → verifier-HRFXBKT5.js.map} +1 -1
- package/dist/workers/logic-execution.js +3 -3
- package/dist/workers/logic-execution.js.map +1 -1
- package/dist/workers/zk-verifier.js +1 -1
- package/dist/workers/zk-verifier.js.map +1 -1
- package/package.json +8 -2
- package/dist/chunk-32ADSAJS.js.map +0 -1
- package/dist/chunk-547TYL27.js.map +0 -1
- package/dist/chunk-72MNYFR6.js.map +0 -1
- package/dist/chunk-74CISO2I.js.map +0 -1
- package/dist/chunk-CRZBVFDV.js.map +0 -1
- package/dist/chunk-GA3Q2S7O.js.map +0 -1
- package/dist/chunk-JIJPZFR2.js.map +0 -1
- package/dist/chunk-OUUTDSOW.js.map +0 -1
- package/dist/chunk-PYKRQAER.js.map +0 -1
- package/dist/chunk-QLCOEP5J.js.map +0 -1
- package/dist/chunk-RWRRBYG4.js +0 -3
- package/dist/chunk-SONUORBT.js.map +0 -1
- package/dist/chunk-T5IUZF47.js.map +0 -1
- package/dist/chunk-U5BZ66VX.js.map +0 -1
- package/dist/chunk-WCCGE4QR.js.map +0 -1
- package/dist/chunk-WSW6YJNY.js.map +0 -1
- package/dist/kyber-3ULIJSE3.js +0 -3
- package/dist/verifier-3FAKCFNN.js +0 -5
package/dist/bin/agent.js
CHANGED
|
@@ -1,28 +1,42 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import '../chunk-
|
|
4
|
-
import {
|
|
5
|
-
import '../chunk-
|
|
6
|
-
import '../chunk-
|
|
7
|
-
import '../chunk-
|
|
8
|
-
import '../chunk-
|
|
9
|
-
import '../chunk-
|
|
10
|
-
import '../chunk-
|
|
11
|
-
import '../chunk-
|
|
12
|
-
import
|
|
13
|
-
import
|
|
2
|
+
import { probeTopology, RoutingTable } from '../chunk-UCVP3XAL.js';
|
|
3
|
+
import { TokenManager } from '../chunk-ESRXG36Y.js';
|
|
4
|
+
import { LiopServer } from '../chunk-HD2N3IJX.js';
|
|
5
|
+
import '../chunk-Y62GORQF.js';
|
|
6
|
+
import { LiopMcpRouter } from '../chunk-L6J72C5X.js';
|
|
7
|
+
import '../chunk-DZ2FQGJD.js';
|
|
8
|
+
import '../chunk-PEN3KFLF.js';
|
|
9
|
+
import '../chunk-IK7CGWAZ.js';
|
|
10
|
+
import '../chunk-7PITYWOV.js';
|
|
11
|
+
import '../chunk-VH4K4U45.js';
|
|
12
|
+
import '../chunk-TKRX6CFI.js';
|
|
13
|
+
import '../chunk-PAICJCKJ.js';
|
|
14
|
+
import { isLegacyRequest } from '../chunk-EG46XMJT.js';
|
|
15
|
+
import '../chunk-FTF6AMF6.js';
|
|
16
|
+
import '../chunk-ZP3VVXOI.js';
|
|
17
|
+
import { MeshNode } from '../chunk-7RXOIDXP.js';
|
|
18
|
+
import { log } from '../chunk-HA6YZ42O.js';
|
|
14
19
|
import * as fs from 'fs';
|
|
15
20
|
import * as os from 'os';
|
|
16
21
|
import * as path from 'path';
|
|
22
|
+
import * as readline from 'readline';
|
|
17
23
|
import { multiaddr } from '@multiformats/multiaddr';
|
|
18
24
|
|
|
25
|
+
var LIOP_MESH_STATUS_TOOL = {
|
|
26
|
+
name: "LiopMeshStatus",
|
|
27
|
+
description: "LiopMeshStatus: Returns the current dynamic diagnostic status of the Zero-Trust Neural Mesh.",
|
|
28
|
+
inputSchema: {
|
|
29
|
+
type: "object",
|
|
30
|
+
properties: {},
|
|
31
|
+
additionalProperties: false
|
|
32
|
+
}
|
|
33
|
+
};
|
|
19
34
|
async function resolveBootstrapFromUrl(url) {
|
|
20
35
|
try {
|
|
21
36
|
const healthUrl = url.endsWith("/health") ? url : `${url}/health`;
|
|
22
37
|
const response = await fetch(healthUrl, {
|
|
23
38
|
headers: { Accept: "application/json" },
|
|
24
39
|
signal: AbortSignal.timeout(1e4)
|
|
25
|
-
// Increased to 10s
|
|
26
40
|
});
|
|
27
41
|
if (!response.ok) return null;
|
|
28
42
|
const data = await response.json();
|
|
@@ -61,6 +75,26 @@ function normalizeBootstrap(addr) {
|
|
|
61
75
|
return trimmed;
|
|
62
76
|
}
|
|
63
77
|
function industrialAddressMapper(addr) {
|
|
78
|
+
if (addr.includes("/ip4/172.23.0.10"))
|
|
79
|
+
return addr.replace(
|
|
80
|
+
/\/ip4\/172\.23\.0\.10\/tcp\/[0-9]+/,
|
|
81
|
+
"/ip4/127.0.0.1/tcp/15001"
|
|
82
|
+
);
|
|
83
|
+
if (addr.includes("/ip4/172.23.0.20"))
|
|
84
|
+
return addr.replace(
|
|
85
|
+
/\/ip4\/172\.23\.0\.20\/tcp\/[0-9]+/,
|
|
86
|
+
"/ip4/127.0.0.1/tcp/15011"
|
|
87
|
+
);
|
|
88
|
+
if (addr.includes("/ip4/172.21.0.13"))
|
|
89
|
+
return addr.replace(
|
|
90
|
+
/\/ip4\/172\.21\.0\.13\/tcp\/[0-9]+/,
|
|
91
|
+
"/ip4/127.0.0.1/tcp/15031"
|
|
92
|
+
);
|
|
93
|
+
if (addr.includes("/ip4/172.21.0.14"))
|
|
94
|
+
return addr.replace(
|
|
95
|
+
/\/ip4\/172\.21\.0\.14\/tcp\/[0-9]+/,
|
|
96
|
+
"/ip4/127.0.0.1/tcp/15041"
|
|
97
|
+
);
|
|
64
98
|
if (addr.includes("/ip4/172.20.0.10"))
|
|
65
99
|
return addr.replace(
|
|
66
100
|
/\/ip4\/172\.20\.0\.10\/tcp\/[0-9]+/,
|
|
@@ -89,7 +123,7 @@ function industrialAddressMapper(addr) {
|
|
|
89
123
|
function isDockerDemoHost(urlStr) {
|
|
90
124
|
try {
|
|
91
125
|
const u = new URL(urlStr);
|
|
92
|
-
return (u.hostname === "127.0.0.1" || u.hostname === "localhost") && (u.port === "13000" || u.port === "13001");
|
|
126
|
+
return (u.hostname === "127.0.0.1" || u.hostname === "localhost") && (u.port === "13000" || u.port === "13001" || u.port === "15000" || u.port === "15018");
|
|
93
127
|
} catch {
|
|
94
128
|
return false;
|
|
95
129
|
}
|
|
@@ -97,45 +131,14 @@ function isDockerDemoHost(urlStr) {
|
|
|
97
131
|
function shouldEnableDockerMap() {
|
|
98
132
|
return process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test" || process.env.LIOP_DOCKER_MAP === "true" || process.env.LIOP_DEV_MODE === "true" || !!process.env.LIOP_NEXUS_URL && isDockerDemoHost(process.env.LIOP_NEXUS_URL);
|
|
99
133
|
}
|
|
100
|
-
async function
|
|
101
|
-
if ((process.platform === "win32" || process.platform === "darwin") && !process.execArgv.includes("--use-system-ca") && !(process.env.NODE_OPTIONS ?? "").includes("--use-system-ca")) {
|
|
102
|
-
const { spawn } = await import('child_process');
|
|
103
|
-
const child = spawn(
|
|
104
|
-
process.execPath,
|
|
105
|
-
["--use-system-ca", ...process.argv.slice(1)],
|
|
106
|
-
{ stdio: "inherit", env: process.env }
|
|
107
|
-
);
|
|
108
|
-
child.on("exit", (code) => process.exit(code ?? 1));
|
|
109
|
-
child.on("error", () => process.exit(1));
|
|
110
|
-
await new Promise(() => {
|
|
111
|
-
});
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
const buildTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
115
|
-
log.info(`[LIOP-Agent] \u{1F680} Version 1.2.0-alpha.9 | Build: ${buildTime}`);
|
|
116
|
-
const liopDir = path.join(os.homedir(), ".liop");
|
|
117
|
-
const identityPath = path.join(liopDir, "identity.json");
|
|
118
|
-
if (!fs.existsSync(liopDir)) {
|
|
119
|
-
fs.mkdirSync(liopDir, { recursive: true });
|
|
120
|
-
}
|
|
134
|
+
async function resolveBootstrapNodes(liopDir) {
|
|
121
135
|
let bootstrapNodes = [];
|
|
122
136
|
const args = process.argv.slice(2);
|
|
123
137
|
if (args.length > 0) {
|
|
124
138
|
bootstrapNodes = args.filter((a) => a.startsWith("/"));
|
|
125
139
|
}
|
|
126
140
|
if (bootstrapNodes.length === 0) {
|
|
127
|
-
const searchDirs = [
|
|
128
|
-
if (process.env.LIOP_BOOTSTRAP_FILE) {
|
|
129
|
-
log.warn(
|
|
130
|
-
"LIOP_BOOTSTRAP_FILE is deprecated and will be removed in the next major version. Use LIOP_NEXUS_URL for Auto-Discovery instead."
|
|
131
|
-
);
|
|
132
|
-
const filePath = path.resolve(process.env.LIOP_BOOTSTRAP_FILE);
|
|
133
|
-
if (fs.existsSync(filePath)) {
|
|
134
|
-
const addr = fs.readFileSync(filePath, "utf8").trim();
|
|
135
|
-
if (addr) bootstrapNodes.push(normalizeBootstrap(addr));
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
searchDirs.push(
|
|
141
|
+
const searchDirs = [
|
|
139
142
|
process.cwd(),
|
|
140
143
|
path.join(process.cwd(), "tests/infra/nexus-data"),
|
|
141
144
|
liopDir,
|
|
@@ -143,7 +146,7 @@ async function main() {
|
|
|
143
146
|
path.dirname(new URL(import.meta.url).pathname).replace(/^\/([A-Z]:)/, "$1"),
|
|
144
147
|
"../../tests/infra/nexus-data"
|
|
145
148
|
)
|
|
146
|
-
|
|
149
|
+
];
|
|
147
150
|
for (const dir of searchDirs) {
|
|
148
151
|
try {
|
|
149
152
|
if (fs.existsSync(dir)) {
|
|
@@ -162,15 +165,12 @@ async function main() {
|
|
|
162
165
|
}
|
|
163
166
|
if (bootstrapNodes.length > 0) break;
|
|
164
167
|
}
|
|
165
|
-
} catch
|
|
168
|
+
} catch {
|
|
166
169
|
}
|
|
167
170
|
}
|
|
168
171
|
}
|
|
169
172
|
if (process.env.LIOP_NEXUS_URL) {
|
|
170
173
|
const nexusUrl = process.env.LIOP_NEXUS_URL;
|
|
171
|
-
log.info(
|
|
172
|
-
`[LIOP-Agent] \u{1F310} Running parallel discovery from: ${nexusUrl} (Sources Found: ${bootstrapNodes.length})`
|
|
173
|
-
);
|
|
174
174
|
const resolved = await resolveBootstrapFromUrl(nexusUrl);
|
|
175
175
|
if (resolved) {
|
|
176
176
|
const normalized = normalizeBootstrap(resolved);
|
|
@@ -185,36 +185,322 @@ async function main() {
|
|
|
185
185
|
if (bootstrapNodes.length === 0 && process.env.LIOP_BOOTSTRAP) {
|
|
186
186
|
bootstrapNodes.push(process.env.LIOP_BOOTSTRAP.trim());
|
|
187
187
|
}
|
|
188
|
-
|
|
189
|
-
bootstrapNodes.push(
|
|
190
|
-
"/ip4/127.0.0.1/tcp/13001/p2p/12D3KooWD8FUFdnLQzzLFNdicsaTknM5cpD7os9sK9NWVSVABJMD"
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
bootstrapNodes = bootstrapNodes.filter((addr) => {
|
|
188
|
+
return bootstrapNodes.filter((addr) => {
|
|
194
189
|
try {
|
|
195
190
|
multiaddr(addr);
|
|
196
191
|
return true;
|
|
197
192
|
} catch {
|
|
198
|
-
log.warn(`[LIOP-Agent] Ignoring invalid bootstrap multiaddr: ${addr}`);
|
|
199
193
|
return false;
|
|
200
194
|
}
|
|
201
195
|
});
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
196
|
+
}
|
|
197
|
+
async function forwardToGateway(mcpEndpoint, request, tokenManager) {
|
|
198
|
+
const send = async (token2) => {
|
|
199
|
+
const headers = {
|
|
200
|
+
"Content-Type": "application/json"
|
|
201
|
+
};
|
|
202
|
+
if (token2) {
|
|
203
|
+
headers.Authorization = `Bearer ${token2}`;
|
|
204
|
+
}
|
|
205
|
+
if (request.method) {
|
|
206
|
+
headers["Mcp-Method"] = request.method;
|
|
207
|
+
}
|
|
208
|
+
const params = request.params;
|
|
209
|
+
if (params?.name) {
|
|
210
|
+
headers["Mcp-Name"] = params.name;
|
|
211
|
+
}
|
|
212
|
+
return await fetch(mcpEndpoint, {
|
|
213
|
+
method: "POST",
|
|
214
|
+
headers,
|
|
215
|
+
body: JSON.stringify(request),
|
|
216
|
+
signal: AbortSignal.timeout(3e4)
|
|
217
|
+
});
|
|
218
|
+
};
|
|
219
|
+
let token;
|
|
220
|
+
try {
|
|
221
|
+
token = await tokenManager.getToken();
|
|
222
|
+
} catch (err) {
|
|
223
|
+
log.warn(
|
|
224
|
+
`[LIOP-Agent] Token acquisition warning: ${err instanceof Error ? err.message : String(err)}`
|
|
205
225
|
);
|
|
226
|
+
}
|
|
227
|
+
let response = await send(token);
|
|
228
|
+
if (response.status === 401 && token) {
|
|
206
229
|
log.info(
|
|
207
|
-
"[LIOP-Agent]
|
|
230
|
+
"[LIOP-Agent] \u{1F504} 401 received from Gateway. Refreshing token and retrying..."
|
|
208
231
|
);
|
|
232
|
+
tokenManager.invalidate();
|
|
233
|
+
try {
|
|
234
|
+
token = await tokenManager.getToken();
|
|
235
|
+
response = await send(token);
|
|
236
|
+
} catch {
|
|
237
|
+
}
|
|
209
238
|
}
|
|
239
|
+
if (!response.ok) {
|
|
240
|
+
const errorBody = await response.text();
|
|
241
|
+
let parsedError = null;
|
|
242
|
+
try {
|
|
243
|
+
parsedError = JSON.parse(errorBody);
|
|
244
|
+
} catch {
|
|
245
|
+
}
|
|
246
|
+
const errorObj = parsedError?.error;
|
|
247
|
+
return {
|
|
248
|
+
jsonrpc: "2.0",
|
|
249
|
+
id: request.id,
|
|
250
|
+
error: {
|
|
251
|
+
code: errorObj?.code ?? -32603,
|
|
252
|
+
message: errorObj?.message ?? `Gateway returned HTTP ${response.status}: ${errorBody}`
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
return await response.json();
|
|
257
|
+
}
|
|
258
|
+
async function runGatewayMode(gateway, tokenManager, routingTable) {
|
|
259
|
+
log.info(
|
|
260
|
+
`[LIOP-Agent] \u{1F6E1}\uFE0F Running in ADAPTIVE GATEWAY MODE -> ${gateway.mcpEndpoint}`
|
|
261
|
+
);
|
|
262
|
+
routingTable.registerLocalTool(LIOP_MESH_STATUS_TOOL);
|
|
263
|
+
routingTable.registerGatewayTools(
|
|
264
|
+
gateway.tools.map((t) => ({ name: t })),
|
|
265
|
+
gateway.mcpEndpoint
|
|
266
|
+
);
|
|
267
|
+
let lastToolCount = gateway.tools.length;
|
|
268
|
+
const pollInterval = setInterval(async () => {
|
|
269
|
+
try {
|
|
270
|
+
const res = await fetch(gateway.healthEndpoint, {
|
|
271
|
+
headers: { Accept: "application/json" },
|
|
272
|
+
signal: AbortSignal.timeout(4e3)
|
|
273
|
+
});
|
|
274
|
+
if (res.ok) {
|
|
275
|
+
const data = await res.json();
|
|
276
|
+
if (data.tools && data.tools.length !== lastToolCount) {
|
|
277
|
+
log.info(
|
|
278
|
+
`[LIOP-Agent] Gateway tools topology updated (${lastToolCount} -> ${data.tools.length})`
|
|
279
|
+
);
|
|
280
|
+
lastToolCount = data.tools.length;
|
|
281
|
+
routingTable.registerGatewayTools(
|
|
282
|
+
data.tools.map((t) => ({ name: t })),
|
|
283
|
+
gateway.mcpEndpoint
|
|
284
|
+
);
|
|
285
|
+
process.stdout.write(
|
|
286
|
+
`{"jsonrpc":"2.0","method":"notifications/tools/list_changed"}
|
|
287
|
+
`
|
|
288
|
+
);
|
|
289
|
+
process.stdout.write(
|
|
290
|
+
`{"jsonrpc":"2.0","method":"notifications/resources/list_changed"}
|
|
291
|
+
`
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
} catch {
|
|
296
|
+
}
|
|
297
|
+
}, 15e3);
|
|
298
|
+
const rl = readline.createInterface({
|
|
299
|
+
input: process.stdin,
|
|
300
|
+
terminal: false
|
|
301
|
+
});
|
|
302
|
+
process.stdout.on("error", (err) => {
|
|
303
|
+
if (err.code === "EPIPE") {
|
|
304
|
+
clearInterval(pollInterval);
|
|
305
|
+
process.exit(0);
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
rl.on("line", async (line) => {
|
|
309
|
+
const trimmed = line.trim();
|
|
310
|
+
if (!trimmed) return;
|
|
311
|
+
let request;
|
|
312
|
+
try {
|
|
313
|
+
request = JSON.parse(trimmed);
|
|
314
|
+
} catch {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
const { id, method } = request;
|
|
318
|
+
if (method === "server/discover") {
|
|
319
|
+
const discoverResponse = {
|
|
320
|
+
jsonrpc: "2.0",
|
|
321
|
+
id,
|
|
322
|
+
result: {
|
|
323
|
+
resultType: "complete",
|
|
324
|
+
supportedVersions: ["2026-07-28", "2025-11-25"],
|
|
325
|
+
capabilities: {
|
|
326
|
+
tools: { listChanged: true },
|
|
327
|
+
resources: { listChanged: true, subscribe: true },
|
|
328
|
+
prompts: { listChanged: true }
|
|
329
|
+
},
|
|
330
|
+
serverInfo: {
|
|
331
|
+
name: "liop-adaptive-agent",
|
|
332
|
+
version: "2.5.0"
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
process.stdout.write(`${JSON.stringify(discoverResponse)}
|
|
337
|
+
`);
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
if (method === "initialize") {
|
|
341
|
+
const clientVersion = request.params?.protocolVersion ?? request.params?._meta?.["io.modelcontextprotocol/protocolVersion"];
|
|
342
|
+
const protocolVersion = clientVersion === "2026-07-28" ? "2026-07-28" : "2025-11-25";
|
|
343
|
+
const initResponse = {
|
|
344
|
+
jsonrpc: "2.0",
|
|
345
|
+
id,
|
|
346
|
+
result: {
|
|
347
|
+
protocolVersion,
|
|
348
|
+
capabilities: {
|
|
349
|
+
tools: { listChanged: true },
|
|
350
|
+
resources: { listChanged: true, subscribe: true },
|
|
351
|
+
prompts: { listChanged: true }
|
|
352
|
+
},
|
|
353
|
+
serverInfo: {
|
|
354
|
+
name: "liop-adaptive-agent",
|
|
355
|
+
version: "2.5.0"
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
process.stdout.write(`${JSON.stringify(initResponse)}
|
|
360
|
+
`);
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
if (method === "notifications/initialized" || method === "notifications/cancelled") {
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
if (method === "ping") {
|
|
367
|
+
process.stdout.write(
|
|
368
|
+
`${JSON.stringify({ jsonrpc: "2.0", id, result: {} })}
|
|
369
|
+
`
|
|
370
|
+
);
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
if (method === "resources/templates/list") {
|
|
374
|
+
const templatesResponse = {
|
|
375
|
+
jsonrpc: "2.0",
|
|
376
|
+
id,
|
|
377
|
+
result: {
|
|
378
|
+
resultType: "complete",
|
|
379
|
+
ttlMs: 3e5,
|
|
380
|
+
cacheScope: "public",
|
|
381
|
+
resourceTemplates: []
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
process.stdout.write(`${JSON.stringify(templatesResponse)}
|
|
385
|
+
`);
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
if (method === "subscriptions/listen") {
|
|
389
|
+
const listenResponse = {
|
|
390
|
+
jsonrpc: "2.0",
|
|
391
|
+
id,
|
|
392
|
+
result: {
|
|
393
|
+
resultType: "complete"
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
process.stdout.write(`${JSON.stringify(listenResponse)}
|
|
397
|
+
`);
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
if (method === "tools/call") {
|
|
401
|
+
const params = request.params;
|
|
402
|
+
if (params?.name === "LiopMeshStatus") {
|
|
403
|
+
const statusResponse = {
|
|
404
|
+
jsonrpc: "2.0",
|
|
405
|
+
id,
|
|
406
|
+
result: {
|
|
407
|
+
content: [
|
|
408
|
+
{
|
|
409
|
+
type: "text",
|
|
410
|
+
text: JSON.stringify({
|
|
411
|
+
mode: "adaptive-gateway",
|
|
412
|
+
gatewayUrl: gateway.baseUrl,
|
|
413
|
+
tier: gateway.tier,
|
|
414
|
+
toolsAvailable: routingTable.getAllToolDefinitions().length,
|
|
415
|
+
authenticated: true,
|
|
416
|
+
status: "ONLINE"
|
|
417
|
+
})
|
|
418
|
+
}
|
|
419
|
+
]
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
process.stdout.write(`${JSON.stringify(statusResponse)}
|
|
423
|
+
`);
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
try {
|
|
428
|
+
const response = await forwardToGateway(
|
|
429
|
+
gateway.mcpEndpoint,
|
|
430
|
+
request,
|
|
431
|
+
tokenManager
|
|
432
|
+
);
|
|
433
|
+
if (method === "tools/list" && response.result && typeof response.result === "object") {
|
|
434
|
+
const resObj = response.result;
|
|
435
|
+
const toolsList = resObj.tools;
|
|
436
|
+
if (Array.isArray(toolsList)) {
|
|
437
|
+
const hasStatus = toolsList.some((t) => t.name === "LiopMeshStatus");
|
|
438
|
+
if (!hasStatus) {
|
|
439
|
+
toolsList.unshift(LIOP_MESH_STATUS_TOOL);
|
|
440
|
+
}
|
|
441
|
+
routingTable.registerGatewayTools(toolsList, gateway.mcpEndpoint);
|
|
442
|
+
}
|
|
443
|
+
if (!isLegacyRequest(request)) {
|
|
444
|
+
if (!resObj.resultType) {
|
|
445
|
+
resObj.resultType = "complete";
|
|
446
|
+
}
|
|
447
|
+
if (!resObj.ttlMs) {
|
|
448
|
+
resObj.ttlMs = 3e5;
|
|
449
|
+
}
|
|
450
|
+
if (!resObj.cacheScope) {
|
|
451
|
+
resObj.cacheScope = "public";
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
process.stdout.write(`${JSON.stringify(response)}
|
|
456
|
+
`);
|
|
457
|
+
} catch (err) {
|
|
458
|
+
if (method === "tools/list") {
|
|
459
|
+
const isLegacy = isLegacyRequest(request);
|
|
460
|
+
const fallbackResult = isLegacy ? { tools: routingTable.getAllToolDefinitions() } : {
|
|
461
|
+
resultType: "complete",
|
|
462
|
+
ttlMs: 3e5,
|
|
463
|
+
cacheScope: "public",
|
|
464
|
+
tools: routingTable.getAllToolDefinitions()
|
|
465
|
+
};
|
|
466
|
+
const fallbackResponse = {
|
|
467
|
+
jsonrpc: "2.0",
|
|
468
|
+
id,
|
|
469
|
+
result: fallbackResult
|
|
470
|
+
};
|
|
471
|
+
process.stdout.write(`${JSON.stringify(fallbackResponse)}
|
|
472
|
+
`);
|
|
473
|
+
} else {
|
|
474
|
+
const errResponse = {
|
|
475
|
+
jsonrpc: "2.0",
|
|
476
|
+
id,
|
|
477
|
+
error: {
|
|
478
|
+
code: -32603,
|
|
479
|
+
message: `Forwarding failed: ${err instanceof Error ? err.message : String(err)}`
|
|
480
|
+
}
|
|
481
|
+
};
|
|
482
|
+
process.stdout.write(`${JSON.stringify(errResponse)}
|
|
483
|
+
`);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
});
|
|
487
|
+
rl.on("close", () => {
|
|
488
|
+
clearInterval(pollInterval);
|
|
489
|
+
process.exit(0);
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
async function runMeshMode(mesh) {
|
|
493
|
+
log.info(
|
|
494
|
+
`[LIOP-Agent] \u{1F310} Running in P2P MESH MODE (${mesh.bootstrapNodes.length} bootstraps)`
|
|
495
|
+
);
|
|
210
496
|
const liopServer = new LiopServer({
|
|
211
497
|
name: "@nekzus/liop",
|
|
212
|
-
version: "
|
|
498
|
+
version: "2.5.0"
|
|
213
499
|
});
|
|
214
500
|
liopServer.enableZeroShotAutonomy();
|
|
215
501
|
const meshNode = new MeshNode({
|
|
216
|
-
identityPath,
|
|
217
|
-
bootstrapNodes,
|
|
502
|
+
identityPath: mesh.identityPath,
|
|
503
|
+
bootstrapNodes: mesh.bootstrapNodes,
|
|
218
504
|
addressMapper: shouldEnableDockerMap() ? industrialAddressMapper : void 0
|
|
219
505
|
});
|
|
220
506
|
await meshNode.start();
|
|
@@ -230,8 +516,6 @@ async function main() {
|
|
|
230
516
|
);
|
|
231
517
|
};
|
|
232
518
|
setTimeout(() => {
|
|
233
|
-
const rtSize = meshNode.getRoutingTableSize?.() || 0;
|
|
234
|
-
log.info(`[LIOP-Agent] Warm-up complete. Routing Table size: ${rtSize}`);
|
|
235
519
|
router.refreshManifestCache(true).catch(() => {
|
|
236
520
|
});
|
|
237
521
|
}, 2e3);
|
|
@@ -246,9 +530,6 @@ async function main() {
|
|
|
246
530
|
const newSize = router.getCacheSize();
|
|
247
531
|
if (newSize !== prevSize) {
|
|
248
532
|
pollIntervalMs = POLL_BASE_MS;
|
|
249
|
-
log.info(
|
|
250
|
-
`[LIOP-Agent] Topology change detected (${prevSize} \u2192 ${newSize}). Resetting poll to ${POLL_BASE_MS / 1e3}s.`
|
|
251
|
-
);
|
|
252
533
|
} else {
|
|
253
534
|
pollIntervalMs = Math.min(
|
|
254
535
|
Math.round(pollIntervalMs * 1.5),
|
|
@@ -259,15 +540,12 @@ async function main() {
|
|
|
259
540
|
}, pollIntervalMs);
|
|
260
541
|
};
|
|
261
542
|
scheduleAdaptivePoll();
|
|
262
|
-
const readline = await import('readline');
|
|
263
543
|
const rl = readline.createInterface({
|
|
264
544
|
input: process.stdin,
|
|
265
545
|
terminal: false
|
|
266
546
|
});
|
|
267
547
|
process.stdout.on("error", (err) => {
|
|
268
|
-
if (err.code === "EPIPE")
|
|
269
|
-
process.exit(0);
|
|
270
|
-
}
|
|
548
|
+
if (err.code === "EPIPE") process.exit(0);
|
|
271
549
|
});
|
|
272
550
|
rl.on("line", async (line) => {
|
|
273
551
|
const trimmed = line.trim();
|
|
@@ -281,22 +559,336 @@ async function main() {
|
|
|
281
559
|
`);
|
|
282
560
|
}
|
|
283
561
|
}
|
|
284
|
-
} catch
|
|
562
|
+
} catch {
|
|
285
563
|
}
|
|
286
564
|
});
|
|
287
|
-
rl.on("close", () =>
|
|
565
|
+
rl.on("close", () => process.exit(0));
|
|
566
|
+
process.on("SIGINT", async () => {
|
|
567
|
+
await meshNode.stop();
|
|
288
568
|
process.exit(0);
|
|
289
569
|
});
|
|
290
|
-
|
|
570
|
+
}
|
|
571
|
+
async function runHybridMode(topology, tokenManager, routingTable) {
|
|
572
|
+
const gateway = topology.gateway;
|
|
573
|
+
const mesh = topology.mesh;
|
|
574
|
+
if (!gateway || !mesh) {
|
|
575
|
+
if (gateway) return runGatewayMode(gateway, tokenManager, routingTable);
|
|
576
|
+
if (mesh) return runMeshMode(mesh);
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
291
579
|
log.info(
|
|
292
|
-
`[LIOP-Agent]
|
|
580
|
+
`[LIOP-Agent] \u26A1 Running in HYBRID MODE (Gateway: ${gateway.baseUrl} + Mesh P2P)`
|
|
293
581
|
);
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
582
|
+
routingTable.registerLocalTool(LIOP_MESH_STATUS_TOOL);
|
|
583
|
+
routingTable.registerGatewayTools(
|
|
584
|
+
gateway.tools.map((t) => ({ name: t })),
|
|
585
|
+
gateway.mcpEndpoint
|
|
586
|
+
);
|
|
587
|
+
let meshNode = null;
|
|
588
|
+
let router = null;
|
|
589
|
+
const initMeshPromise = (async () => {
|
|
590
|
+
try {
|
|
591
|
+
const liopServer = new LiopServer({
|
|
592
|
+
name: "@nekzus/liop-hybrid",
|
|
593
|
+
version: "2.5.0"
|
|
594
|
+
});
|
|
595
|
+
liopServer.enableZeroShotAutonomy();
|
|
596
|
+
meshNode = new MeshNode({
|
|
597
|
+
identityPath: mesh.identityPath,
|
|
598
|
+
bootstrapNodes: mesh.bootstrapNodes,
|
|
599
|
+
addressMapper: shouldEnableDockerMap() ? industrialAddressMapper : void 0
|
|
600
|
+
});
|
|
601
|
+
await meshNode.start();
|
|
602
|
+
router = new LiopMcpRouter(liopServer, meshNode);
|
|
603
|
+
router.onToolsChanged = () => {
|
|
604
|
+
process.stdout.write(
|
|
605
|
+
`{"jsonrpc":"2.0","method":"notifications/tools/list_changed"}
|
|
606
|
+
`
|
|
607
|
+
);
|
|
608
|
+
process.stdout.write(
|
|
609
|
+
`{"jsonrpc":"2.0","method":"notifications/resources/list_changed"}
|
|
610
|
+
`
|
|
611
|
+
);
|
|
612
|
+
};
|
|
613
|
+
await router.refreshManifestCache(true).catch(() => {
|
|
614
|
+
});
|
|
615
|
+
log.info("[LIOP-Agent] \u2705 Background P2P Mesh initialization completed.");
|
|
616
|
+
} catch (err) {
|
|
617
|
+
log.warn(
|
|
618
|
+
`[LIOP-Agent] Background Mesh init warning: ${err instanceof Error ? err.message : String(err)}`
|
|
619
|
+
);
|
|
620
|
+
}
|
|
621
|
+
})();
|
|
622
|
+
const rl = readline.createInterface({
|
|
623
|
+
input: process.stdin,
|
|
624
|
+
terminal: false
|
|
625
|
+
});
|
|
626
|
+
process.stdout.on("error", (err) => {
|
|
627
|
+
if (err.code === "EPIPE") process.exit(0);
|
|
628
|
+
});
|
|
629
|
+
rl.on("line", async (line) => {
|
|
630
|
+
const trimmed = line.trim();
|
|
631
|
+
if (!trimmed) return;
|
|
632
|
+
let request;
|
|
633
|
+
try {
|
|
634
|
+
request = JSON.parse(trimmed);
|
|
635
|
+
} catch {
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
const { id, method } = request;
|
|
639
|
+
if (method === "server/discover") {
|
|
640
|
+
const discoverResponse = {
|
|
641
|
+
jsonrpc: "2.0",
|
|
642
|
+
id,
|
|
643
|
+
result: {
|
|
644
|
+
resultType: "complete",
|
|
645
|
+
supportedVersions: ["2026-07-28", "2025-11-25"],
|
|
646
|
+
capabilities: {
|
|
647
|
+
tools: { listChanged: true },
|
|
648
|
+
resources: { listChanged: true, subscribe: true },
|
|
649
|
+
prompts: { listChanged: true }
|
|
650
|
+
},
|
|
651
|
+
serverInfo: {
|
|
652
|
+
name: "liop-hybrid-agent",
|
|
653
|
+
version: "2.5.0"
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
};
|
|
657
|
+
process.stdout.write(`${JSON.stringify(discoverResponse)}
|
|
658
|
+
`);
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
if (method === "initialize") {
|
|
662
|
+
const clientVersion = request.params?.protocolVersion ?? request.params?._meta?.["io.modelcontextprotocol/protocolVersion"];
|
|
663
|
+
const protocolVersion = clientVersion === "2026-07-28" ? "2026-07-28" : "2025-11-25";
|
|
664
|
+
const initResponse = {
|
|
665
|
+
jsonrpc: "2.0",
|
|
666
|
+
id,
|
|
667
|
+
result: {
|
|
668
|
+
protocolVersion,
|
|
669
|
+
capabilities: {
|
|
670
|
+
tools: { listChanged: true },
|
|
671
|
+
resources: { listChanged: true, subscribe: true },
|
|
672
|
+
prompts: { listChanged: true }
|
|
673
|
+
},
|
|
674
|
+
serverInfo: {
|
|
675
|
+
name: "liop-hybrid-agent",
|
|
676
|
+
version: "2.5.0"
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
};
|
|
680
|
+
process.stdout.write(`${JSON.stringify(initResponse)}
|
|
681
|
+
`);
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
if (method === "notifications/initialized" || method === "notifications/cancelled") {
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
if (method === "ping") {
|
|
688
|
+
process.stdout.write(
|
|
689
|
+
`${JSON.stringify({ jsonrpc: "2.0", id, result: {} })}
|
|
690
|
+
`
|
|
691
|
+
);
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
if (method === "resources/templates/list") {
|
|
695
|
+
const templatesResponse = {
|
|
696
|
+
jsonrpc: "2.0",
|
|
697
|
+
id,
|
|
698
|
+
result: {
|
|
699
|
+
resultType: "complete",
|
|
700
|
+
ttlMs: 3e5,
|
|
701
|
+
cacheScope: "public",
|
|
702
|
+
resourceTemplates: []
|
|
703
|
+
}
|
|
704
|
+
};
|
|
705
|
+
process.stdout.write(`${JSON.stringify(templatesResponse)}
|
|
706
|
+
`);
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
if (method === "subscriptions/listen") {
|
|
710
|
+
const listenResponse = {
|
|
711
|
+
jsonrpc: "2.0",
|
|
712
|
+
id,
|
|
713
|
+
result: {
|
|
714
|
+
resultType: "complete"
|
|
715
|
+
}
|
|
716
|
+
};
|
|
717
|
+
process.stdout.write(`${JSON.stringify(listenResponse)}
|
|
718
|
+
`);
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
if (method === "tools/call") {
|
|
722
|
+
const params = request.params;
|
|
723
|
+
const toolName = params?.name || "";
|
|
724
|
+
const route = routingTable.resolve(toolName);
|
|
725
|
+
if (route?.provider === "http-gateway") {
|
|
726
|
+
const start = Date.now();
|
|
727
|
+
try {
|
|
728
|
+
const res = await forwardToGateway(
|
|
729
|
+
gateway.mcpEndpoint,
|
|
730
|
+
request,
|
|
731
|
+
tokenManager
|
|
732
|
+
);
|
|
733
|
+
routingTable.recordSuccess(toolName, Date.now() - start);
|
|
734
|
+
process.stdout.write(`${JSON.stringify(res)}
|
|
735
|
+
`);
|
|
736
|
+
return;
|
|
737
|
+
} catch (_err) {
|
|
738
|
+
routingTable.recordFailure(toolName);
|
|
739
|
+
log.warn(
|
|
740
|
+
`[LIOP-Agent] Gateway call failed for '${toolName}'. Checking P2P fallback...`
|
|
741
|
+
);
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
await initMeshPromise;
|
|
745
|
+
if (router) {
|
|
746
|
+
const res = await router.dispatch(request);
|
|
747
|
+
if (res) process.stdout.write(`${JSON.stringify(res)}
|
|
748
|
+
`);
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
if (method === "tools/list") {
|
|
753
|
+
let gatewayTools = [];
|
|
754
|
+
try {
|
|
755
|
+
const gwRes = await forwardToGateway(
|
|
756
|
+
gateway.mcpEndpoint,
|
|
757
|
+
request,
|
|
758
|
+
tokenManager
|
|
759
|
+
);
|
|
760
|
+
const resObj = gwRes.result;
|
|
761
|
+
if (Array.isArray(resObj?.tools)) {
|
|
762
|
+
gatewayTools = resObj.tools;
|
|
763
|
+
routingTable.registerGatewayTools(gatewayTools, gateway.mcpEndpoint);
|
|
764
|
+
}
|
|
765
|
+
} catch {
|
|
766
|
+
gatewayTools = routingTable.getAllToolDefinitions();
|
|
767
|
+
}
|
|
768
|
+
let meshTools = [];
|
|
769
|
+
if (router) {
|
|
770
|
+
const meshRes = await router.dispatch(request);
|
|
771
|
+
const meshObj = meshRes?.result;
|
|
772
|
+
if (Array.isArray(meshObj?.tools)) {
|
|
773
|
+
meshTools = meshObj.tools;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
const toolMap = /* @__PURE__ */ new Map();
|
|
777
|
+
toolMap.set("LiopMeshStatus", LIOP_MESH_STATUS_TOOL);
|
|
778
|
+
for (const t of gatewayTools) toolMap.set(t.name, t);
|
|
779
|
+
for (const t of meshTools)
|
|
780
|
+
if (!toolMap.has(t.name)) toolMap.set(t.name, t);
|
|
781
|
+
const merged = Array.from(toolMap.values()).sort(
|
|
782
|
+
(a, b) => a.name.localeCompare(b.name)
|
|
783
|
+
);
|
|
784
|
+
const isLegacy = isLegacyRequest(request);
|
|
785
|
+
const toolsResult = isLegacy ? { tools: merged } : {
|
|
786
|
+
resultType: "complete",
|
|
787
|
+
ttlMs: 3e5,
|
|
788
|
+
cacheScope: "public",
|
|
789
|
+
tools: merged
|
|
790
|
+
};
|
|
791
|
+
process.stdout.write(
|
|
792
|
+
`${JSON.stringify({ jsonrpc: "2.0", id, result: toolsResult })}
|
|
793
|
+
`
|
|
794
|
+
);
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
try {
|
|
798
|
+
const res = await forwardToGateway(
|
|
799
|
+
gateway.mcpEndpoint,
|
|
800
|
+
request,
|
|
801
|
+
tokenManager
|
|
802
|
+
);
|
|
803
|
+
if (!isLegacyRequest(request) && res.result && typeof res.result === "object") {
|
|
804
|
+
const resObj = res.result;
|
|
805
|
+
if (!resObj.resultType) {
|
|
806
|
+
resObj.resultType = "complete";
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
process.stdout.write(`${JSON.stringify(res)}
|
|
810
|
+
`);
|
|
811
|
+
} catch {
|
|
812
|
+
await initMeshPromise;
|
|
813
|
+
if (router) {
|
|
814
|
+
const res = await router.dispatch(request);
|
|
815
|
+
if (res) process.stdout.write(`${JSON.stringify(res)}
|
|
816
|
+
`);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
});
|
|
820
|
+
rl.on("close", async () => {
|
|
821
|
+
if (meshNode) await meshNode.stop();
|
|
297
822
|
process.exit(0);
|
|
298
823
|
});
|
|
299
824
|
}
|
|
825
|
+
async function main() {
|
|
826
|
+
if ((process.platform === "win32" || process.platform === "darwin") && !process.execArgv.includes("--use-system-ca") && !(process.env.NODE_OPTIONS ?? "").includes("--use-system-ca")) {
|
|
827
|
+
const { spawn } = await import('child_process');
|
|
828
|
+
const child = spawn(
|
|
829
|
+
process.execPath,
|
|
830
|
+
["--use-system-ca", ...process.argv.slice(1)],
|
|
831
|
+
{ stdio: "inherit", env: process.env }
|
|
832
|
+
);
|
|
833
|
+
child.on("exit", (code) => process.exit(code ?? 1));
|
|
834
|
+
child.on("error", () => process.exit(1));
|
|
835
|
+
await new Promise(() => {
|
|
836
|
+
});
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
const buildTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
840
|
+
log.info(
|
|
841
|
+
`[LIOP-Agent] \u{1F680} Version 2.5.0 (Adaptive Zero-Config) | Build: ${buildTime}`
|
|
842
|
+
);
|
|
843
|
+
const liopDir = path.join(os.homedir(), ".liop");
|
|
844
|
+
const identityPath = path.join(liopDir, "identity.json");
|
|
845
|
+
if (!fs.existsSync(liopDir)) {
|
|
846
|
+
fs.mkdirSync(liopDir, { recursive: true });
|
|
847
|
+
}
|
|
848
|
+
const bootstrapNodes = await resolveBootstrapNodes(liopDir);
|
|
849
|
+
const blgUrl = process.env.LIOP_BLG_URL;
|
|
850
|
+
const nexusUrl = process.env.LIOP_NEXUS_URL;
|
|
851
|
+
const clientId = process.env.LIOP_CLIENT_ID || process.env.LIOP_OAUTH_CLIENT_ID || "liop-agent";
|
|
852
|
+
const clientSecret = process.env.LIOP_CLIENT_SECRET || process.env.LIOP_OAUTH_CLIENT_SECRET || "dev-secret-change-me";
|
|
853
|
+
const staticToken = process.env.LIOP_TOKEN || process.env.LIOP_OAUTH_TOKEN;
|
|
854
|
+
const topology = await probeTopology({
|
|
855
|
+
blgUrl,
|
|
856
|
+
nexusUrl,
|
|
857
|
+
clientId,
|
|
858
|
+
clientSecret,
|
|
859
|
+
staticToken,
|
|
860
|
+
bootstrapNodes,
|
|
861
|
+
identityPath
|
|
862
|
+
});
|
|
863
|
+
const routingTable = new RoutingTable();
|
|
864
|
+
const tokenManager = new TokenManager({
|
|
865
|
+
tokenEndpoint: topology.gateway?.tokenEndpoint || `${nexusUrl || "http://127.0.0.1:15000"}/oidc/token`,
|
|
866
|
+
clientId,
|
|
867
|
+
clientSecret,
|
|
868
|
+
audience: topology.gateway?.audience,
|
|
869
|
+
scopes: topology.gateway?.scopes,
|
|
870
|
+
staticToken
|
|
871
|
+
});
|
|
872
|
+
switch (topology.mode) {
|
|
873
|
+
case "gateway":
|
|
874
|
+
if (!topology.gateway)
|
|
875
|
+
throw new Error(
|
|
876
|
+
"Topology probe indicated gateway mode without gateway info."
|
|
877
|
+
);
|
|
878
|
+
await runGatewayMode(topology.gateway, tokenManager, routingTable);
|
|
879
|
+
break;
|
|
880
|
+
case "mesh":
|
|
881
|
+
if (!topology.mesh)
|
|
882
|
+
throw new Error(
|
|
883
|
+
"Topology probe indicated mesh mode without mesh info."
|
|
884
|
+
);
|
|
885
|
+
await runMeshMode(topology.mesh);
|
|
886
|
+
break;
|
|
887
|
+
case "hybrid":
|
|
888
|
+
await runHybridMode(topology, tokenManager, routingTable);
|
|
889
|
+
break;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
300
892
|
main().catch((err) => {
|
|
301
893
|
log.error(`[LIOP-Agent] Fatal Error: ${err.message}`);
|
|
302
894
|
process.exit(1);
|