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