@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.
Files changed (92) hide show
  1. package/NOTICE +19 -0
  2. package/README.md +36 -17
  3. package/dist/bin/agent.js +674 -82
  4. package/dist/bin/agent.js.map +1 -1
  5. package/dist/bridge.d.ts +2 -2
  6. package/dist/bridge.js +3 -3
  7. package/dist/{chunk-T5IUZF47.js → chunk-3L2O2XKG.js} +12 -5
  8. package/dist/chunk-3L2O2XKG.js.map +1 -0
  9. package/dist/{chunk-SONUORBT.js → chunk-7BSCUYUE.js} +2 -2
  10. package/dist/chunk-7BSCUYUE.js.map +1 -0
  11. package/dist/{chunk-QLCOEP5J.js → chunk-7PITYWOV.js} +2 -2
  12. package/dist/chunk-7PITYWOV.js.map +1 -0
  13. package/dist/{chunk-74CISO2I.js → chunk-7RXOIDXP.js} +28 -4
  14. package/dist/chunk-7RXOIDXP.js.map +1 -0
  15. package/dist/{chunk-GA3Q2S7O.js → chunk-BOISQ45Z.js} +5 -5
  16. package/dist/chunk-BOISQ45Z.js.map +1 -0
  17. package/dist/{chunk-547TYL27.js → chunk-DZ2FQGJD.js} +26 -1423
  18. package/dist/chunk-DZ2FQGJD.js.map +1 -0
  19. package/dist/{chunk-PYKRQAER.js → chunk-EG46XMJT.js} +2 -2
  20. package/dist/chunk-EG46XMJT.js.map +1 -0
  21. package/dist/chunk-ESRXG36Y.js +115 -0
  22. package/dist/chunk-ESRXG36Y.js.map +1 -0
  23. package/dist/chunk-FTF6AMF6.js +3 -0
  24. package/dist/{chunk-RWRRBYG4.js.map → chunk-FTF6AMF6.js.map} +1 -1
  25. package/dist/{chunk-72MNYFR6.js → chunk-HA6YZ42O.js} +2 -2
  26. package/dist/chunk-HA6YZ42O.js.map +1 -0
  27. package/dist/{chunk-WCCGE4QR.js → chunk-HD2N3IJX.js} +144 -30
  28. package/dist/chunk-HD2N3IJX.js.map +1 -0
  29. package/dist/{chunk-OUUTDSOW.js → chunk-IK7CGWAZ.js} +3 -3
  30. package/dist/chunk-IK7CGWAZ.js.map +1 -0
  31. package/dist/chunk-L6J72C5X.js +1477 -0
  32. package/dist/chunk-L6J72C5X.js.map +1 -0
  33. package/dist/{chunk-U5BZ66VX.js → chunk-PAICJCKJ.js} +60 -175
  34. package/dist/chunk-PAICJCKJ.js.map +1 -0
  35. package/dist/{chunk-32ADSAJS.js → chunk-PEN3KFLF.js} +14 -4
  36. package/dist/chunk-PEN3KFLF.js.map +1 -0
  37. package/dist/{chunk-CRZBVFDV.js → chunk-T7R5HUFD.js} +225 -66
  38. package/dist/chunk-T7R5HUFD.js.map +1 -0
  39. package/dist/{chunk-WSW6YJNY.js → chunk-TKRX6CFI.js} +3 -3
  40. package/dist/chunk-TKRX6CFI.js.map +1 -0
  41. package/dist/chunk-UCVP3XAL.js +279 -0
  42. package/dist/chunk-UCVP3XAL.js.map +1 -0
  43. package/dist/chunk-VH4K4U45.js +180 -0
  44. package/dist/chunk-VH4K4U45.js.map +1 -0
  45. package/dist/{chunk-JIJPZFR2.js → chunk-Y62GORQF.js} +2 -2
  46. package/dist/chunk-Y62GORQF.js.map +1 -0
  47. package/dist/chunk-ZP3VVXOI.js +66 -0
  48. package/dist/chunk-ZP3VVXOI.js.map +1 -0
  49. package/dist/client.d.ts +2 -2
  50. package/dist/client.js +11 -8
  51. package/dist/gateway.d.ts +3 -3
  52. package/dist/gateway.js +11 -9
  53. package/dist/{hybrid-CF__0YnC.d.ts → hybrid-CrKB50nh.d.ts} +2 -2
  54. package/dist/{index-cMV0_yD9.d.ts → index-CX43dvMs.d.ts} +2 -32
  55. package/dist/{index-BW95kAL4.d.ts → index-DoW2gzBZ.d.ts} +3 -21
  56. package/dist/index.d.ts +170 -46
  57. package/dist/index.js +20 -15
  58. package/dist/index.js.map +1 -1
  59. package/dist/kyber-CGOA7Q6A.js +3 -0
  60. package/dist/{kyber-3ULIJSE3.js.map → kyber-CGOA7Q6A.js.map} +1 -1
  61. package/dist/mesh.d.ts +27 -143
  62. package/dist/mesh.js +4 -3
  63. package/dist/node-B0b2vUFS.d.ts +164 -0
  64. package/dist/protocol/liop_core.proto +3 -0
  65. package/dist/server.d.ts +2 -2
  66. package/dist/server.js +7 -6
  67. package/dist/types.js +1 -1
  68. package/dist/verifier-HRFXBKT5.js +6 -0
  69. package/dist/{verifier-3FAKCFNN.js.map → verifier-HRFXBKT5.js.map} +1 -1
  70. package/dist/workers/logic-execution.js +3 -3
  71. package/dist/workers/logic-execution.js.map +1 -1
  72. package/dist/workers/zk-verifier.js +1 -1
  73. package/dist/workers/zk-verifier.js.map +1 -1
  74. package/package.json +8 -2
  75. package/dist/chunk-32ADSAJS.js.map +0 -1
  76. package/dist/chunk-547TYL27.js.map +0 -1
  77. package/dist/chunk-72MNYFR6.js.map +0 -1
  78. package/dist/chunk-74CISO2I.js.map +0 -1
  79. package/dist/chunk-CRZBVFDV.js.map +0 -1
  80. package/dist/chunk-GA3Q2S7O.js.map +0 -1
  81. package/dist/chunk-JIJPZFR2.js.map +0 -1
  82. package/dist/chunk-OUUTDSOW.js.map +0 -1
  83. package/dist/chunk-PYKRQAER.js.map +0 -1
  84. package/dist/chunk-QLCOEP5J.js.map +0 -1
  85. package/dist/chunk-RWRRBYG4.js +0 -3
  86. package/dist/chunk-SONUORBT.js.map +0 -1
  87. package/dist/chunk-T5IUZF47.js.map +0 -1
  88. package/dist/chunk-U5BZ66VX.js.map +0 -1
  89. package/dist/chunk-WCCGE4QR.js.map +0 -1
  90. package/dist/chunk-WSW6YJNY.js.map +0 -1
  91. package/dist/kyber-3ULIJSE3.js +0 -3
  92. 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 { LiopServer } from '../chunk-WCCGE4QR.js';
3
- import '../chunk-JIJPZFR2.js';
4
- import { LiopMcpRouter } from '../chunk-547TYL27.js';
5
- import '../chunk-32ADSAJS.js';
6
- import '../chunk-OUUTDSOW.js';
7
- import '../chunk-QLCOEP5J.js';
8
- import '../chunk-U5BZ66VX.js';
9
- import '../chunk-WSW6YJNY.js';
10
- import '../chunk-PYKRQAER.js';
11
- import '../chunk-RWRRBYG4.js';
12
- import { MeshNode } from '../chunk-74CISO2I.js';
13
- import { log } from '../chunk-72MNYFR6.js';
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 main() {
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 (_e) {
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
- if (bootstrapNodes.length === 0) {
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
- if (bootstrapNodes.length === 0) {
203
- log.info(
204
- "[LIOP-Agent] No bootstrap nodes configured. Operating in standalone mode."
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] Pass a multiaddr as argument or create 'nexus.multiaddr' file."
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: "1.0.0"
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 (_err) {
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
- log.info(`[LIOP-Agent] Guarding Claude Desktop via STDIO.`);
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] P2P Mesh: Joined (${bootstrapNodes.length} bootstraps)`
580
+ `[LIOP-Agent] \u26A1 Running in HYBRID MODE (Gateway: ${gateway.baseUrl} + Mesh P2P)`
293
581
  );
294
- log.info("[LIOP-Agent] Tool discovery: Dynamic via /liop/manifest/1.0.0");
295
- process.on("SIGINT", async () => {
296
- await meshNode.stop();
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);