@nekzus/liop 2.0.1-beta.1 → 2.1.0-alpha.10

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 (97) hide show
  1. package/README.md +69 -12
  2. package/dist/bin/agent.js +303 -4
  3. package/dist/bin/agent.js.map +1 -1
  4. package/dist/bridge.d.ts +2 -2
  5. package/dist/bridge.js +4 -1
  6. package/dist/chunk-32ADSAJS.js +104 -0
  7. package/dist/chunk-32ADSAJS.js.map +1 -0
  8. package/dist/chunk-72MNYFR6.js +64 -0
  9. package/dist/chunk-72MNYFR6.js.map +1 -0
  10. package/dist/chunk-E5QBDD5E.js +469 -0
  11. package/dist/chunk-E5QBDD5E.js.map +1 -0
  12. package/dist/chunk-EEYEVHO2.js +9329 -0
  13. package/dist/chunk-EEYEVHO2.js.map +1 -0
  14. package/dist/chunk-F5YNYL5L.js +14512 -0
  15. package/dist/chunk-F5YNYL5L.js.map +1 -0
  16. package/dist/chunk-HB5DXX3Q.js +1976 -0
  17. package/dist/chunk-HB5DXX3Q.js.map +1 -0
  18. package/dist/chunk-IJHTRIZC.js +56 -0
  19. package/dist/chunk-IJHTRIZC.js.map +1 -0
  20. package/dist/chunk-IMPCCZ2Y.js +463 -0
  21. package/dist/chunk-IMPCCZ2Y.js.map +1 -0
  22. package/dist/chunk-J3WPBMJ5.js +332 -0
  23. package/dist/chunk-J3WPBMJ5.js.map +1 -0
  24. package/dist/chunk-MCXMS5ZI.js +30 -0
  25. package/dist/chunk-MCXMS5ZI.js.map +1 -0
  26. package/dist/chunk-NJRSFFD7.js +815 -0
  27. package/dist/chunk-NJRSFFD7.js.map +1 -0
  28. package/dist/chunk-OUUTDSOW.js +24 -0
  29. package/dist/chunk-OUUTDSOW.js.map +1 -0
  30. package/dist/chunk-PHTWUTY7.js +300 -0
  31. package/dist/chunk-PHTWUTY7.js.map +1 -0
  32. package/dist/chunk-PZ5AY32C.js +9 -0
  33. package/dist/{chunk-4C666HHU.js.map → chunk-PZ5AY32C.js.map} +1 -1
  34. package/dist/chunk-QLCOEP5J.js +68 -0
  35. package/dist/chunk-QLCOEP5J.js.map +1 -0
  36. package/dist/chunk-RDWCGZ2A.js +87 -0
  37. package/dist/chunk-RDWCGZ2A.js.map +1 -0
  38. package/dist/chunk-RWRRBYG4.js +1 -0
  39. package/dist/client.d.ts +3 -3
  40. package/dist/client.js +9 -1
  41. package/dist/gateway.d.ts +3 -3
  42. package/dist/gateway.js +10 -1
  43. package/dist/{index-CL8m1L1d.d.ts → index-BlGc0iym.d.ts} +24 -1
  44. package/dist/{index-B_Vbrb_I.d.ts → index-qM8ZH8sC.d.ts} +2 -2
  45. package/dist/index.d.ts +6 -6
  46. package/dist/index.js +60 -4
  47. package/dist/index.js.map +1 -1
  48. package/dist/kyber-FCVPX6CE.js +4 -0
  49. package/dist/{kyber-NONMBQNH.js.map → kyber-FCVPX6CE.js.map} +1 -1
  50. package/dist/mesh.js +5 -1
  51. package/dist/server.d.ts +2 -2
  52. package/dist/server.js +8 -1
  53. package/dist/{types-DzEXgi4s.d.ts → types-sKeUxuky.d.ts} +4 -46
  54. package/dist/types.d.ts +1 -1
  55. package/dist/types.js +4 -1
  56. package/dist/{verifier-DTCD9imJ.d.ts → verifier-COnid_dg.d.ts} +1 -1
  57. package/dist/verifier-GCZDNZK7.js +6 -0
  58. package/dist/{verifier-Z26UC7M4.js.map → verifier-GCZDNZK7.js.map} +1 -1
  59. package/dist/workers/logic-execution.js +256 -1
  60. package/dist/workers/logic-execution.js.map +1 -1
  61. package/dist/workers/zk-verifier.d.ts +2 -0
  62. package/dist/workers/zk-verifier.js +174 -1
  63. package/dist/workers/zk-verifier.js.map +1 -1
  64. package/package.json +43 -44
  65. package/dist/chunk-2MGFSIXN.js +0 -2
  66. package/dist/chunk-2MGFSIXN.js.map +0 -1
  67. package/dist/chunk-4C666HHU.js +0 -2
  68. package/dist/chunk-ANFXJGMP.js +0 -2
  69. package/dist/chunk-ANFXJGMP.js.map +0 -1
  70. package/dist/chunk-DBXGYHKY.js +0 -2
  71. package/dist/chunk-DBXGYHKY.js.map +0 -1
  72. package/dist/chunk-DQ6UW6L7.js +0 -2
  73. package/dist/chunk-DQ6UW6L7.js.map +0 -1
  74. package/dist/chunk-L5A64CNT.js +0 -54
  75. package/dist/chunk-L5A64CNT.js.map +0 -1
  76. package/dist/chunk-N6FGTZ6A.js +0 -3
  77. package/dist/chunk-N6FGTZ6A.js.map +0 -1
  78. package/dist/chunk-RYYRR4N5.js +0 -31
  79. package/dist/chunk-RYYRR4N5.js.map +0 -1
  80. package/dist/chunk-S6RJHZV2.js +0 -2
  81. package/dist/chunk-S6RJHZV2.js.map +0 -1
  82. package/dist/chunk-SB5XJXKV.js +0 -2
  83. package/dist/chunk-SB5XJXKV.js.map +0 -1
  84. package/dist/chunk-SW53FNSN.js +0 -2
  85. package/dist/chunk-SW53FNSN.js.map +0 -1
  86. package/dist/chunk-TYVG6TXQ.js +0 -2
  87. package/dist/chunk-TYVG6TXQ.js.map +0 -1
  88. package/dist/chunk-V5MKJT6S.js +0 -2
  89. package/dist/chunk-V5MKJT6S.js.map +0 -1
  90. package/dist/chunk-VGXNGTIC.js +0 -33
  91. package/dist/chunk-VGXNGTIC.js.map +0 -1
  92. package/dist/chunk-W2QGWRTT.js +0 -3
  93. package/dist/chunk-W2QGWRTT.js.map +0 -1
  94. package/dist/chunk-YZVCAJJO.js +0 -13
  95. package/dist/chunk-YZVCAJJO.js.map +0 -1
  96. package/dist/kyber-NONMBQNH.js +0 -2
  97. package/dist/verifier-Z26UC7M4.js +0 -2
package/README.md CHANGED
@@ -35,11 +35,11 @@ This fundamentally solves the data privacy, bandwidth, and latency challenges of
35
35
  | **Logic-Injection-on-Origin** | LLMs send code, not queries. Data never leaves the origin server. |
36
36
  | **MCP Drop-in Replacement** | `LiopServer` mirrors the Anthropic MCP `Server` API — tools, resources, and prompts with `Zod` schemas. |
37
37
  | **Guardian AST** | Zero-time heuristic inspection blocks sandbox escapes (`require`, `fs`, `eval`, `fetch`, prototype pollution). |
38
- | **WASI Sandbox** | JavaScript payloads execute inside V8 isolates with CPU fuel limits and no access to Node.js globals. |
39
- | **PII Shield** | Multi-layer egress filter with Regional Presets (Email, Credit Card with Luhn, IP, Phone, SSN, IBAN Mod-97, Passport MRZ) and custom keys. |
40
- | **ZK-Receipts** | Cryptographic proof (SHA-256 ImageID + HMAC-SHA256 seal) that the returned result was computed honestly from the injected logic. |
41
- | **Worker Pool** | Heavy computation (crypto, sandboxing) dispatched to OS threads via `piscina`, unblocking the V8 event loop. |
42
- | **Cross-AI Adapters** | Zero-Shot system prompts automatically adapt instructions for Claude (XML-heavy) vs OpenAI/Gemini (JSON-schema). |
38
+ | **WASI Sandbox** | JavaScript payloads execute inside V8 isolates with CPU fuel limits, no Node.js globals, and safe environment isolation (`allowEnv`). |
39
+ | **PII Shield** | Multi-layer egress filter with Regional Presets, custom keys, and recursive floats sanitization (`sanitizeOutput`). |
40
+ | **ZK-Receipts** | Cryptographic proof with `output_hash` cross-verification (Replay Mitigation) and balanced-brace proxy extraction. |
41
+ | **Worker Pool** | Heavy computation (crypto, sandboxing) dispatched to OS threads via `piscina` with background async warmup. |
42
+ | **Cross-AI Adapters** | Zero-Shot system prompts automatically adapt instructions for Claude (XML-heavy) vs OpenAI/Gemini (JSON-schema). |
43
43
  | **MCP Bridge** | `LiopMcpBridge` adapts any `LiopServer` to the JSON-RPC 2.0 / stdio protocol used by Claude Desktop, Cursor, etc. |
44
44
  | **Post-Quantum Ready** | ML-KEM-768 (Kyber) handshake + AES-256-GCM symmetric encryption for transport-layer security. |
45
45
  | **P2P Mesh** | Kademlia DHT discovery via `libp2p` with TCP + WebSocket + Yamux multiplexing and Noise encryption. |
@@ -245,6 +245,8 @@ new LiopServer(
245
245
  };
246
246
  auth?: LiopAuthConfig; // OAuth 2.1 Hybrid authentication config
247
247
  tokenSlug?: string; // Deterministic token resolution slug (e.g., "BANK", "VAULT")
248
+ allowEnv?: boolean; // Enable safe host environment propagation (default: false)
249
+ budgetStorePath?: string; // Path to a shared JSON file for persistent Query Budget tracking
248
250
  }
249
251
  )
250
252
  ```
@@ -253,7 +255,7 @@ new LiopServer(
253
255
 
254
256
  | Method | Signature | Description |
255
257
  | :--------------------------- | :------------------------------------------------- | :---------------------------------------------------------------------------------- |
256
- | `tool()` | `(name, description, zodSchema, handler)` | Registers a callable tool with Zod input validation. |
258
+ | `tool()` | `(name, description, shape, handler, policy?)` | Registers a callable tool with Zod input validation and logic execution policies. |
257
259
  | `prompt()` | `(name, description, args, handler)` | Registers a dynamic prompt template. |
258
260
  | `resource()` | `(name, uri, description?, mimeType?, content?)` | Registers a readable resource. |
259
261
  | `dataDictionary()` | `(schema, name?, uri?, description?)` | Broadcasts a data schema so LLMs can write accurate Logic-Injection-on-Origin code. |
@@ -270,6 +272,24 @@ new LiopServer(
270
272
  | `clearAstCache()` | `()` | Invalidates the Guardian AST logic cache. |
271
273
  | `close()` | `()` | Destroys the worker pool and releases threads. |
272
274
 
275
+ #### LogicExecutionPolicy Options
276
+
277
+ When registering a tool via `server.tool()`, you can optionally pass a `policy` object to configure security and privacy guards for that specific tool:
278
+
279
+ ```typescript
280
+ interface LogicExecutionPolicy {
281
+ outputSchema?: z.ZodType<unknown>; // Validate returned business payload (strict by default)
282
+ enforceAggregationFirst?: boolean | AggregationPolicy; // Block row-level exports & enforce K-Anonymity
283
+ preflightDenyPatterns?: RegExp[]; // Custom regex patterns blocked in static analysis
284
+ dpEpsilon?: number; // Laplace Differential Privacy epsilon (default: 1.0)
285
+ dpSensitivity?: number; // Maximum change per single record (default: 1.0)
286
+ dpSmallDatasetThreshold?: number; // Size threshold below which DP is active (default: 50)
287
+ queryBudgetPerField?: number; // Uniform session query limit per field (legacy compatibility)
288
+ sensitiveKeys?: string[]; // Tool-level fields under the 8-query sensitive budget tier
289
+ budgetStorePath?: string; // Shared path for persistent and concurrent query budgets
290
+ }
291
+ ```
292
+
273
293
  ### `LiopMcpBridge`
274
294
 
275
295
  Adapter that connects any `LiopServer` to MCP-compatible clients via JSON-RPC 2.0 over stdio.
@@ -300,11 +320,11 @@ await bridge.connect();
300
320
  │ Layer 1: Guardian AST (Zero-Time Static Analysis) │
301
321
  │ 14-function WASI allowlist • 128 import cap • Blocks │
302
322
  │ require, import(), fs, eval, fetch, __proto__ │
303
- ├───────────────────────────────────────────────────────────┤
323
+ ├───────────────────────────────────────────────────────────┐
304
324
  │ Layer 2: WASI Sandbox (V8 Isolate) │
305
325
  │ 25 poisoned globals (incl. Date, TypedArrays) • │
306
326
  │ CPU Fuel limits • 5s timeout • maxHeapMb (64MB default) │
307
- │ Object.freeze() on 11 core prototypes (strict mode)
327
+ │ Object.freeze() on 11 core prototypes allowEnv allowlist
308
328
  ├───────────────────────────────────────────────────────────┤
309
329
  │ Layer 3: Taint Analyzer (IFC — Static) │
310
330
  │ Acorn AST 3-pass analysis blocks PII side-channels: │
@@ -312,15 +332,16 @@ await bridge.connect();
312
332
  ├───────────────────────────────────────────────────────────┤
313
333
  │ Layer 4: PII Shield (Egress Filter) │
314
334
  │ 4-stage pipeline: exact key → fuzzy key → pattern │
315
- │ validators (Luhn, IBAN Mod-97) → NER (compromise)
335
+ │ validators (Luhn, IBAN Mod-97) → NER (compromise)
336
+ │ Recursive In-Memory Numerical Sanitization (4 decimals) │
316
337
  ├───────────────────────────────────────────────────────────┤
317
338
  │ Layer 5: Aggregation-First Policy │
318
339
  │ Blocks raw row export • maxOutputRows (default: 10) • │
319
340
  │ Conditional error: detailed (dev) vs opaque (production) │
320
341
  ├───────────────────────────────────────────────────────────┤
321
- │ Layer 6: ZK-Receipt (Integrity Verification)
322
- │ SHA-256 ImageID + HMAC-SHA256 Seal (Kyber768-derived)
323
- Timing-safe verification • LiopMcpBridge auto-verifies
342
+ │ Layer 6: ZK-Receipt (Integrity & Replay Mitigation)
343
+ │ SHA-256 ImageID + HMAC-SHA256 Seal (Kyber768-derived)
344
+ output_hash cross-verification • Balanced-brace extractor
324
345
  └───────────────────────────────────────────────────────────┘
325
346
  ```
326
347
 
@@ -386,6 +407,32 @@ For maximum host security, the WASI sandbox enforces a poisoned environment that
386
407
  - **Poisoned/Disabled**: `Date` (Date.now, parse, etc. throw an exception to prevent timing analysis), `eval`, `Function`, `setTimeout`, `setInterval`, `Buffer`, `ArrayBuffer`, and all `TypedArrays`.
387
408
  - **Date Workaround**: To perform date checks, use lexicographical string comparison on ISO 8601 strings (e.g., `record.date >= "2026-01-01"`).
388
409
 
410
+ ### 🧹 Recursive In-Memory Numerical Sanitization
411
+
412
+ To mitigate timing channels, statistical differentiation, and floats side-channels, the SDK executes a recursive sanitization pipeline before the PII scanner runs:
413
+ - Positive floating-point numbers are recursively rounded to exactly **4 decimal places**.
414
+ - Negative values are safely clamped to **0** (via `sanitizeOutput()`).
415
+ - This operation runs entirely in-memory and recursively on all fields, preserving data structure immutability without expensive and fragile serialization-deserialization cycles.
416
+
417
+ ### 🌐 Environment Isolation & allowEnv Allowlist
418
+
419
+ For robust sandboxing, the WASI execution path isolates host environment variables. Propagation can be enabled explicitly:
420
+ ```typescript
421
+ const server = new LiopServer(info, {
422
+ allowEnv: true
423
+ });
424
+ ```
425
+ To block arbitrary command execution (e.g., Shellshock) and prevent exposure of host credentials, the SDK filters environment variables through a **strict system allowlist** (`getDefaultEnvironment()`):
426
+ - **Windows Allowlist**: `APPDATA`, `HOMEDRIVE`, `HOMEPATH`, `LOCALAPPDATA`, `PATH`, `PROCESSOR_ARCHITECTURE`, `SYSTEMDRIVE`, `SYSTEMROOT`, `TEMP`, `USERNAME`, `USERPROFILE`, `PROGRAMFILES`.
427
+ - **Unix/Linux Allowlist**: `HOME`, `LOGNAME`, `PATH`, `SHELL`, `TERM`, `USER`.
428
+ Variables starting with shell functions `()` are dropped.
429
+
430
+ ### 🔒 ZK-Receipt Replay & Tampering Mitigation
431
+
432
+ LIOP ZK-Receipts provide cryptographic evidence that a computation was executed honestly under zero-trust bounds. To defeat **Man-in-the-Middle (MITM) reply tampering and replay attacks** (re-using old signatures on new query data):
433
+ - The verification pipeline computes the SHA-256 hash of the received business output (`expectedOutput`) and strictly asserts its equivalence with `Journal.output_hash` signed inside the ZK-Receipt (via `verifyZkReceipt`).
434
+ - **Balanced-Brace Proxy Extractor**: If the tool call was delegated to a proxied tool (`__liop_proxy_tool`), the verifier invokes an in-process balanced-brace state machine to safely isolate proxy arguments from the response metadata, preventing false validation failures.
435
+
389
436
  ---
390
437
 
391
438
  ## Logic-Injection-on-Origin Flow
@@ -489,6 +536,16 @@ This package is continuously tested across multiple platforms and Node.js versio
489
536
 
490
537
  > To run tests locally or contribute, clone the [repository](https://github.com/Nekzus/LIOP) and follow the [Contributing Guide](https://github.com/Nekzus/LIOP/blob/main/CONTRIBUTING.md).
491
538
 
539
+ ## Security Auditing & Supply Chain
540
+
541
+ This repository is integrated with [Socket.dev](https://socket.dev) to continuously monitor and secure the software supply chain against malicious packages, hidden telemetry, and dependency vulnerabilities.
542
+
543
+ You can run security audits and check package health scores directly from the monorepo root:
544
+
545
+ - **Scan Monorepo Dependencies:** `pnpm socket:scan` (performs a security scan and generates a report)
546
+ - **Check SDK Security Score:** `pnpm socket:score` (shows the detailed package score for the SDK in Markdown format)
547
+ - **Fix Vulnerabilities:** `pnpm socket:fix` (automatically remediates known CVEs in package.json)
548
+
492
549
  ---
493
550
 
494
551
  ## Related
package/dist/bin/agent.js CHANGED
@@ -1,6 +1,305 @@
1
1
  #!/usr/bin/env node
2
- import {j}from'../chunk-L5A64CNT.js';import'../chunk-2MGFSIXN.js';import {g}from'../chunk-VGXNGTIC.js';import'../chunk-SW53FNSN.js';import'../chunk-ANFXJGMP.js';import'../chunk-DBXGYHKY.js';import'../chunk-SB5XJXKV.js';import'../chunk-V5MKJT6S.js';import'../chunk-RWRRBYG4.js';import {a as a$1}from'../chunk-DQ6UW6L7.js';import {a}from'../chunk-S6RJHZV2.js';import'../chunk-4C666HHU.js';import*as l from'fs';import*as w from'os';import*as u from'path';import {multiaddr}from'@multiformats/multiaddr';async function x(t){try{let o=t.endsWith("/health")?t:`${t}/health`,d=await fetch(o,{headers:{Accept:"application/json"},signal:AbortSignal.timeout(1e4)});if(!d.ok)return null;let e=await d.json();if(!e.mesh?.multiaddrs?.length||!e.mesh?.peerId)return null;let p=e.mesh.multiaddrs.find(c=>c.includes("/tcp/")&&!c.includes("/ws")&&!c.includes("/ip4/127.0.0.1/"));if(!p)return null;let r=E()?R(p):p;if(!r||r===p){let c=new URL(t).hostname;r=p.replace(/\/ip4\/[^/]+/,`/ip4/${c}`);}return r?(r+=r.includes("/p2p/")?"":`/p2p/${e.mesh.peerId}`,r):null}catch{return null}}function L(t){let o=t.trim(),d=/\/ip4\/172\.(1[6-9]|2[0-9]|3[0-1])\.[0-9]{1,3}\.[0-9]{1,3}/,e=/\/ip4\/127\.0\.0\.1/,p=/\/ip4\/192\.168\.[0-9]{1,3}\.[0-9]{1,3}/;if(d.test(o)||e.test(o)||p.test(o)){let r="127.0.0.1",c=o.replace(d,`/ip4/${r}`).replace(e,`/ip4/${r}`).replace(p,`/ip4/${r}`);return c!==o&&a.info(`[LIOP-Agent] \u{1F504} Local Routing Hack \u2192 Forced 127.0.0.1: ${c}`),c}return o}function R(t){return t.includes("/ip4/172.20.0.10")?t.replace(/\/ip4\/172\.20\.0\.10\/tcp\/[0-9]+/,"/ip4/127.0.0.1/tcp/13001"):t.includes("/ip4/172.20.0.11")?t.replace(/\/ip4\/172\.20\.0\.11\/tcp\/[0-9]+/,"/ip4/127.0.0.1/tcp/13003"):t.includes("/ip4/172.20.0.12")?t.replace(/\/ip4\/172\.20\.0\.12\/tcp\/[0-9]+/,"/ip4/127.0.0.1/tcp/13004"):t.includes("/ip4/172.20.0.13")?t.replace(/\/ip4\/172\.20\.0\.13\/tcp\/[0-9]+/,"/ip4/127.0.0.1/tcp/13005"):t.includes("/ip4/127.0.0.1/tcp/4000")||t.includes("/ip4/127.0.0.1/tcp/3000")?null:t}function D(t){try{let o=new URL(t);return (o.hostname==="127.0.0.1"||o.hostname==="localhost")&&(o.port==="13000"||o.port==="13001")}catch{return false}}function E(){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&&D(process.env.LIOP_NEXUS_URL)}async function M(){if((process.platform==="win32"||process.platform==="darwin")&&!process.execArgv.includes("--use-system-ca")&&!(process.env.NODE_OPTIONS??"").includes("--use-system-ca")){let{spawn:s}=await import('child_process'),n=s(process.execPath,["--use-system-ca",...process.argv.slice(1)],{stdio:"inherit",env:process.env});n.on("exit",a=>process.exit(a??1)),n.on("error",()=>process.exit(1)),await new Promise(()=>{});return}let t=new Date().toISOString();a.info(`[LIOP-Agent] \u{1F680} Version 1.2.0-alpha.9 | Build: ${t}`);let o=u.join(w.homedir(),".liop"),d=u.join(o,"identity.json");l.existsSync(o)||l.mkdirSync(o,{recursive:true});let e=[],p=process.argv.slice(2);if(p.length>0&&(e=p.filter(s=>s.startsWith("/"))),e.length===0){let s=[];if(process.env.LIOP_BOOTSTRAP_FILE){a.warn("LIOP_BOOTSTRAP_FILE is deprecated and will be removed in the next major version. Use LIOP_NEXUS_URL for Auto-Discovery instead.");let n=u.resolve(process.env.LIOP_BOOTSTRAP_FILE);if(l.existsSync(n)){let a=l.readFileSync(n,"utf8").trim();a&&e.push(L(a));}}s.push(process.cwd(),u.join(process.cwd(),"tests/infra/nexus-data"),o,u.join(u.dirname(new URL(import.meta.url).pathname).replace(/^\/([A-Z]:)/,"$1"),"../../tests/infra/nexus-data"));for(let n of s)try{if(l.existsSync(n)){let h=l.readdirSync(n).filter(g=>g.endsWith(".multiaddr"));for(let g of h){let $=u.join(n,g),v=l.readFileSync($,"utf8").trim();if(v){let S=L(v);e.includes(S)||(e.push(S),a.info(`[LIOP-Agent] \u2705 Loaded beacon: ${g} from ${n}`));}}if(e.length>0)break}}catch{}}if(process.env.LIOP_NEXUS_URL){let s=process.env.LIOP_NEXUS_URL;a.info(`[LIOP-Agent] \u{1F310} Running parallel discovery from: ${s} (Sources Found: ${e.length})`);let n=await x(s);if(n){let a$1=L(n);e.includes(a$1)||(e.push(a$1),a.info(`[LIOP-Agent] \u2705 Added bootstrap from URL discovery: ${a$1}`));}}e.length===0&&process.env.LIOP_BOOTSTRAP&&e.push(process.env.LIOP_BOOTSTRAP.trim()),e.length===0&&e.push("/ip4/127.0.0.1/tcp/13001/p2p/12D3KooWD8FUFdnLQzzLFNdicsaTknM5cpD7os9sK9NWVSVABJMD"),e=e.filter(s=>{try{return multiaddr(s),!0}catch{return a.warn(`[LIOP-Agent] Ignoring invalid bootstrap multiaddr: ${s}`),false}}),e.length===0&&(a.info("[LIOP-Agent] No bootstrap nodes configured. Operating in standalone mode."),a.info("[LIOP-Agent] Pass a multiaddr as argument or create 'nexus.multiaddr' file."));let r=new j({name:"@nekzus/liop",version:"1.0.0"});r.enableZeroShotAutonomy();let c=new a$1({identityPath:d,bootstrapNodes:e,addressMapper:E()?R:void 0});await c.start();let f=new g(r,c);f.onToolsChanged=()=>{process.stdout.write(`{"jsonrpc":"2.0","method":"notifications/tools/list_changed"}
3
- `),process.stdout.write(`{"jsonrpc":"2.0","method":"notifications/resources/list_changed"}
4
- `);},setTimeout(()=>{let s=c.getRoutingTableSize?.()||0;a.info(`[LIOP-Agent] Warm-up complete. Routing Table size: ${s}`),f.refreshManifestCache(true).catch(()=>{});},2e3);let O=1e4,T=12e4,m=O,P=()=>{setTimeout(async()=>{let s=f.getCacheSize();await f.refreshManifestCache(true).catch(()=>{});let n=f.getCacheSize();n!==s?(m=O,a.info(`[LIOP-Agent] Topology change detected (${s} \u2192 ${n}). Resetting poll to ${O/1e3}s.`)):m=Math.min(Math.round(m*1.5),T),P();},m);};P();let I=(await import('readline')).createInterface({input:process.stdin,terminal:false});process.stdout.on("error",s=>{s.code==="EPIPE"&&process.exit(0);}),I.on("line",async s=>{let n=s.trim();if(n)try{let a=JSON.parse(n);if(a.method){let h=await f.dispatch(a);h&&process.stdout.write(`${JSON.stringify(h)}
5
- `);}}catch{}}),I.on("close",()=>{process.exit(0);}),a.info("[LIOP-Agent] Guarding Claude Desktop via STDIO."),a.info(`[LIOP-Agent] P2P Mesh: Joined (${e.length} bootstraps)`),a.info("[LIOP-Agent] Tool discovery: Dynamic via /liop/manifest/1.0.0"),process.on("SIGINT",async()=>{await c.stop(),process.exit(0);});}M().catch(t=>{a.error(`[LIOP-Agent] Fatal Error: ${t.message}`),process.exit(1);});//# sourceMappingURL=agent.js.map
2
+ import { LiopServer } from '../chunk-EEYEVHO2.js';
3
+ import '../chunk-F5YNYL5L.js';
4
+ import { LiopMcpRouter } from '../chunk-HB5DXX3Q.js';
5
+ import '../chunk-32ADSAJS.js';
6
+ import '../chunk-OUUTDSOW.js';
7
+ import '../chunk-QLCOEP5J.js';
8
+ import '../chunk-IJHTRIZC.js';
9
+ import '../chunk-RDWCGZ2A.js';
10
+ import '../chunk-RWRRBYG4.js';
11
+ import { MeshNode } from '../chunk-NJRSFFD7.js';
12
+ import { log } from '../chunk-72MNYFR6.js';
13
+ import '../chunk-PZ5AY32C.js';
14
+ import * as fs from 'fs';
15
+ import * as os from 'os';
16
+ import * as path from 'path';
17
+ import { multiaddr } from '@multiformats/multiaddr';
18
+
19
+ async function resolveBootstrapFromUrl(url) {
20
+ try {
21
+ const healthUrl = url.endsWith("/health") ? url : `${url}/health`;
22
+ const response = await fetch(healthUrl, {
23
+ headers: { Accept: "application/json" },
24
+ signal: AbortSignal.timeout(1e4)
25
+ // Increased to 10s
26
+ });
27
+ if (!response.ok) return null;
28
+ const data = await response.json();
29
+ if (!data.mesh?.multiaddrs?.length || !data.mesh?.peerId) return null;
30
+ const tcpAddr = data.mesh.multiaddrs.find(
31
+ (a) => a.includes("/tcp/") && !a.includes("/ws") && !a.includes("/ip4/127.0.0.1/")
32
+ );
33
+ if (!tcpAddr) return null;
34
+ let resolved = shouldEnableDockerMap() ? industrialAddressMapper(tcpAddr) : tcpAddr;
35
+ if (!resolved || resolved === tcpAddr) {
36
+ const urlHost = new URL(url).hostname;
37
+ resolved = tcpAddr.replace(/\/ip4\/[^/]+/, `/ip4/${urlHost}`);
38
+ }
39
+ if (!resolved) return null;
40
+ resolved += resolved.includes("/p2p/") ? "" : `/p2p/${data.mesh.peerId}`;
41
+ return resolved;
42
+ } catch {
43
+ return null;
44
+ }
45
+ }
46
+ function normalizeBootstrap(addr) {
47
+ const trimmed = addr.trim();
48
+ const dockerIpRegex = /\/ip4\/172\.(1[6-9]|2[0-9]|3[0-1])\.[0-9]{1,3}\.[0-9]{1,3}/;
49
+ const loopbackRegex = /\/ip4\/127\.0\.0\.1/;
50
+ const physicalIpRegex = /\/ip4\/192\.168\.[0-9]{1,3}\.[0-9]{1,3}/;
51
+ if (dockerIpRegex.test(trimmed) || loopbackRegex.test(trimmed) || physicalIpRegex.test(trimmed)) {
52
+ const targetIp = "127.0.0.1";
53
+ const normalized = trimmed.replace(dockerIpRegex, `/ip4/${targetIp}`).replace(loopbackRegex, `/ip4/${targetIp}`).replace(physicalIpRegex, `/ip4/${targetIp}`);
54
+ if (normalized !== trimmed) {
55
+ log.info(
56
+ `[LIOP-Agent] \u{1F504} Local Routing Hack \u2192 Forced 127.0.0.1: ${normalized}`
57
+ );
58
+ }
59
+ return normalized;
60
+ }
61
+ return trimmed;
62
+ }
63
+ function industrialAddressMapper(addr) {
64
+ if (addr.includes("/ip4/172.20.0.10"))
65
+ return addr.replace(
66
+ /\/ip4\/172\.20\.0\.10\/tcp\/[0-9]+/,
67
+ "/ip4/127.0.0.1/tcp/13001"
68
+ );
69
+ if (addr.includes("/ip4/172.20.0.11"))
70
+ return addr.replace(
71
+ /\/ip4\/172\.20\.0\.11\/tcp\/[0-9]+/,
72
+ "/ip4/127.0.0.1/tcp/13003"
73
+ );
74
+ if (addr.includes("/ip4/172.20.0.12"))
75
+ return addr.replace(
76
+ /\/ip4\/172\.20\.0\.12\/tcp\/[0-9]+/,
77
+ "/ip4/127.0.0.1/tcp/13004"
78
+ );
79
+ if (addr.includes("/ip4/172.20.0.13"))
80
+ return addr.replace(
81
+ /\/ip4\/172\.20\.0\.13\/tcp\/[0-9]+/,
82
+ "/ip4/127.0.0.1/tcp/13005"
83
+ );
84
+ if (addr.includes("/ip4/127.0.0.1/tcp/4000") || addr.includes("/ip4/127.0.0.1/tcp/3000")) {
85
+ return null;
86
+ }
87
+ return addr;
88
+ }
89
+ function isDockerDemoHost(urlStr) {
90
+ try {
91
+ const u = new URL(urlStr);
92
+ return (u.hostname === "127.0.0.1" || u.hostname === "localhost") && (u.port === "13000" || u.port === "13001");
93
+ } catch {
94
+ return false;
95
+ }
96
+ }
97
+ function shouldEnableDockerMap() {
98
+ 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
+ }
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
+ }
121
+ let bootstrapNodes = [];
122
+ const args = process.argv.slice(2);
123
+ if (args.length > 0) {
124
+ bootstrapNodes = args.filter((a) => a.startsWith("/"));
125
+ }
126
+ 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(
139
+ process.cwd(),
140
+ path.join(process.cwd(), "tests/infra/nexus-data"),
141
+ liopDir,
142
+ path.join(
143
+ path.dirname(new URL(import.meta.url).pathname).replace(/^\/([A-Z]:)/, "$1"),
144
+ "../../tests/infra/nexus-data"
145
+ )
146
+ );
147
+ for (const dir of searchDirs) {
148
+ try {
149
+ if (fs.existsSync(dir)) {
150
+ const files = fs.readdirSync(dir);
151
+ const multiaddrFiles = files.filter((f) => f.endsWith(".multiaddr"));
152
+ for (const file of multiaddrFiles) {
153
+ const filePath = path.join(dir, file);
154
+ const addr = fs.readFileSync(filePath, "utf8").trim();
155
+ if (addr) {
156
+ const normalized = normalizeBootstrap(addr);
157
+ if (!bootstrapNodes.includes(normalized)) {
158
+ bootstrapNodes.push(normalized);
159
+ log.info(`[LIOP-Agent] \u2705 Loaded beacon: ${file} from ${dir}`);
160
+ }
161
+ }
162
+ }
163
+ if (bootstrapNodes.length > 0) break;
164
+ }
165
+ } catch (_e) {
166
+ }
167
+ }
168
+ }
169
+ if (process.env.LIOP_NEXUS_URL) {
170
+ 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
+ const resolved = await resolveBootstrapFromUrl(nexusUrl);
175
+ if (resolved) {
176
+ const normalized = normalizeBootstrap(resolved);
177
+ if (!bootstrapNodes.includes(normalized)) {
178
+ bootstrapNodes.push(normalized);
179
+ log.info(
180
+ `[LIOP-Agent] \u2705 Added bootstrap from URL discovery: ${normalized}`
181
+ );
182
+ }
183
+ }
184
+ }
185
+ if (bootstrapNodes.length === 0 && process.env.LIOP_BOOTSTRAP) {
186
+ bootstrapNodes.push(process.env.LIOP_BOOTSTRAP.trim());
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) => {
194
+ try {
195
+ multiaddr(addr);
196
+ return true;
197
+ } catch {
198
+ log.warn(`[LIOP-Agent] Ignoring invalid bootstrap multiaddr: ${addr}`);
199
+ return false;
200
+ }
201
+ });
202
+ if (bootstrapNodes.length === 0) {
203
+ log.info(
204
+ "[LIOP-Agent] No bootstrap nodes configured. Operating in standalone mode."
205
+ );
206
+ log.info(
207
+ "[LIOP-Agent] Pass a multiaddr as argument or create 'nexus.multiaddr' file."
208
+ );
209
+ }
210
+ const liopServer = new LiopServer({
211
+ name: "@nekzus/liop",
212
+ version: "1.0.0"
213
+ });
214
+ liopServer.enableZeroShotAutonomy();
215
+ const meshNode = new MeshNode({
216
+ identityPath,
217
+ bootstrapNodes,
218
+ addressMapper: shouldEnableDockerMap() ? industrialAddressMapper : void 0
219
+ });
220
+ await meshNode.start();
221
+ const router = new LiopMcpRouter(liopServer, meshNode);
222
+ router.onToolsChanged = () => {
223
+ process.stdout.write(
224
+ `{"jsonrpc":"2.0","method":"notifications/tools/list_changed"}
225
+ `
226
+ );
227
+ process.stdout.write(
228
+ `{"jsonrpc":"2.0","method":"notifications/resources/list_changed"}
229
+ `
230
+ );
231
+ };
232
+ setTimeout(() => {
233
+ const rtSize = meshNode.getRoutingTableSize?.() || 0;
234
+ log.info(`[LIOP-Agent] Warm-up complete. Routing Table size: ${rtSize}`);
235
+ router.refreshManifestCache(true).catch(() => {
236
+ });
237
+ }, 2e3);
238
+ const POLL_BASE_MS = 1e4;
239
+ const POLL_MAX_MS = 12e4;
240
+ let pollIntervalMs = POLL_BASE_MS;
241
+ const scheduleAdaptivePoll = () => {
242
+ setTimeout(async () => {
243
+ const prevSize = router.getCacheSize();
244
+ await router.refreshManifestCache(true).catch(() => {
245
+ });
246
+ const newSize = router.getCacheSize();
247
+ if (newSize !== prevSize) {
248
+ 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
+ } else {
253
+ pollIntervalMs = Math.min(
254
+ Math.round(pollIntervalMs * 1.5),
255
+ POLL_MAX_MS
256
+ );
257
+ }
258
+ scheduleAdaptivePoll();
259
+ }, pollIntervalMs);
260
+ };
261
+ scheduleAdaptivePoll();
262
+ const readline = await import('readline');
263
+ const rl = readline.createInterface({
264
+ input: process.stdin,
265
+ terminal: false
266
+ });
267
+ process.stdout.on("error", (err) => {
268
+ if (err.code === "EPIPE") {
269
+ process.exit(0);
270
+ }
271
+ });
272
+ rl.on("line", async (line) => {
273
+ const trimmed = line.trim();
274
+ if (!trimmed) return;
275
+ try {
276
+ const request = JSON.parse(trimmed);
277
+ if (request.method) {
278
+ const response = await router.dispatch(request);
279
+ if (response) {
280
+ process.stdout.write(`${JSON.stringify(response)}
281
+ `);
282
+ }
283
+ }
284
+ } catch (_err) {
285
+ }
286
+ });
287
+ rl.on("close", () => {
288
+ process.exit(0);
289
+ });
290
+ log.info(`[LIOP-Agent] Guarding Claude Desktop via STDIO.`);
291
+ log.info(
292
+ `[LIOP-Agent] P2P Mesh: Joined (${bootstrapNodes.length} bootstraps)`
293
+ );
294
+ log.info("[LIOP-Agent] Tool discovery: Dynamic via /liop/manifest/1.0.0");
295
+ process.on("SIGINT", async () => {
296
+ await meshNode.stop();
297
+ process.exit(0);
298
+ });
299
+ }
300
+ main().catch((err) => {
301
+ log.error(`[LIOP-Agent] Fatal Error: ${err.message}`);
302
+ process.exit(1);
303
+ });
304
+ //# sourceMappingURL=agent.js.map
6
305
  //# sourceMappingURL=agent.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/bin/agent.ts"],"names":["resolveBootstrapFromUrl","url","healthUrl","response","data","tcpAddr","a","resolved","shouldEnableDockerMap","industrialAddressMapper","urlHost","normalizeBootstrap","addr","trimmed","dockerIpRegex","loopbackRegex","physicalIpRegex","targetIp","normalized","log","isDockerDemoHost","urlStr","u","main","spawn","child","code","buildTime","liopDir","identityPath","bootstrapNodes","args","searchDirs","filePath","dir","multiaddrFiles","f","file","nexusUrl","multiaddr","liopServer","LiopServer","meshNode","MeshNode","router","LiopMcpRouter","rtSize","POLL_BASE_MS","POLL_MAX_MS","pollIntervalMs","scheduleAdaptivePoll","prevSize","newSize","rl","err","line","request"],"mappings":"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","file":"agent.js","sourcesContent":["#!/usr/bin/env node\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { multiaddr } from \"@multiformats/multiaddr\";\nimport { LiopMcpRouter } from \"../gateway/router.js\";\nimport { MeshNode } from \"../mesh/index.js\";\nimport { LiopServer } from \"../server/index.js\";\nimport type { McpRequest } from \"../types.js\";\nimport { log } from \"../utils/logger.js\";\n\n/**\n * Resolves a full libp2p multiaddr (with PeerID) from a LIOP node's\n * HTTP health endpoint. This enables zero-config bootstrap — users\n * only need to provide a URL, not a cryptographic PeerID.\n *\n * @param url - HTTP URL of a LIOP node's health endpoint (e.g. \"http://host:3000\")\n * @returns Full multiaddr string with PeerID, or null if resolution fails\n */\nasync function resolveBootstrapFromUrl(url: string): Promise<string | null> {\n\ttry {\n\t\tconst healthUrl = url.endsWith(\"/health\") ? url : `${url}/health`;\n\t\tconst response = await fetch(healthUrl, {\n\t\t\theaders: { Accept: \"application/json\" },\n\t\t\tsignal: AbortSignal.timeout(10000), // Increased to 10s\n\t\t});\n\t\tif (!response.ok) return null;\n\n\t\tconst data = await response.json();\n\t\tif (!data.mesh?.multiaddrs?.length || !data.mesh?.peerId) return null;\n\n\t\t// Find TCP multiaddr (prefer non-websocket for stability)\n\t\tconst tcpAddr = data.mesh.multiaddrs.find(\n\t\t\t(a: string) =>\n\t\t\t\ta.includes(\"/tcp/\") &&\n\t\t\t\t!a.includes(\"/ws\") &&\n\t\t\t\t!a.includes(\"/ip4/127.0.0.1/\"),\n\t\t);\n\t\tif (!tcpAddr) return null;\n\n\t\t// Rewrite internal Docker IP using the address mapper if enabled\n\t\tlet resolved = shouldEnableDockerMap()\n\t\t\t? industrialAddressMapper(tcpAddr)\n\t\t\t: tcpAddr;\n\t\tif (!resolved || resolved === tcpAddr) {\n\t\t\tconst urlHost = new URL(url).hostname;\n\t\t\tresolved = tcpAddr.replace(/\\/ip4\\/[^/]+/, `/ip4/${urlHost}`);\n\t\t}\n\n\t\tif (!resolved) return null;\n\n\t\tresolved += resolved.includes(\"/p2p/\") ? \"\" : `/p2p/${data.mesh.peerId}`;\n\n\t\treturn resolved;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Normalizes a bootstrap multiaddr string.\n * If the address contains a Docker bridge IP (172.16-31.x.x) or Loopback (127.0.0.1),\n * rewrites it to the host accessible via LIOP_NEXUS_URL (e.g. WSL2 IP).\n * This is critical when WSL2 mirror-mode networking is broken.\n */\nfunction normalizeBootstrap(addr: string): string {\n\tconst trimmed = addr.trim();\n\t// Remap Docker bridge IPs and ANY external physical IPs to 127.0.0.1\n\t// because Test-NetConnection confirmed 127.0.0.1 is the only reliable path to Docker ports.\n\tconst dockerIpRegex =\n\t\t/\\/ip4\\/172\\.(1[6-9]|2[0-9]|3[0-1])\\.[0-9]{1,3}\\.[0-9]{1,3}/;\n\tconst loopbackRegex = /\\/ip4\\/127\\.0\\.0\\.1/;\n\tconst physicalIpRegex = /\\/ip4\\/192\\.168\\.[0-9]{1,3}\\.[0-9]{1,3}/;\n\n\tif (\n\t\tdockerIpRegex.test(trimmed) ||\n\t\tloopbackRegex.test(trimmed) ||\n\t\tphysicalIpRegex.test(trimmed)\n\t) {\n\t\tconst targetIp = \"127.0.0.1\";\n\t\tconst normalized = trimmed\n\t\t\t.replace(dockerIpRegex, `/ip4/${targetIp}`)\n\t\t\t.replace(loopbackRegex, `/ip4/${targetIp}`)\n\t\t\t.replace(physicalIpRegex, `/ip4/${targetIp}`);\n\n\t\tif (normalized !== trimmed) {\n\t\t\tlog.info(\n\t\t\t\t`[LIOP-Agent] 🔄 Local Routing Hack → Forced 127.0.0.1: ${normalized}`,\n\t\t\t);\n\t\t}\n\t\treturn normalized;\n\t}\n\n\treturn trimmed;\n}\n\n/**\n * industrialAddressMapper\n *\n * Maps Docker-internal IPs to host-published ports for local demo environments.\n * Activated when any of the following conditions are met:\n * - NODE_ENV is \"development\" or \"test\"\n * - LIOP_DOCKER_MAP=\"true\" or LIOP_DEV_MODE=\"true\" is set\n * - LIOP_NEXUS_URL points to a local Docker demo port (127.0.0.1:13000|13001)\n *\n * Nexus (172.20.0.10) -> 13001\n * Vault (172.20.0.11) -> 13003\n * Bank (172.20.0.12) -> 13004\n * Oracle(172.20.0.13) -> 13005\n */\nfunction industrialAddressMapper(addr: string): string | null {\n\tif (addr.includes(\"/ip4/172.20.0.10\"))\n\t\treturn addr.replace(\n\t\t\t/\\/ip4\\/172\\.20\\.0\\.10\\/tcp\\/[0-9]+/,\n\t\t\t\"/ip4/127.0.0.1/tcp/13001\",\n\t\t);\n\tif (addr.includes(\"/ip4/172.20.0.11\"))\n\t\treturn addr.replace(\n\t\t\t/\\/ip4\\/172\\.20\\.0\\.11\\/tcp\\/[0-9]+/,\n\t\t\t\"/ip4/127.0.0.1/tcp/13003\",\n\t\t);\n\tif (addr.includes(\"/ip4/172.20.0.12\"))\n\t\treturn addr.replace(\n\t\t\t/\\/ip4\\/172\\.20\\.0\\.12\\/tcp\\/[0-9]+/,\n\t\t\t\"/ip4/127.0.0.1/tcp/13004\",\n\t\t);\n\tif (addr.includes(\"/ip4/172.20.0.13\"))\n\t\treturn addr.replace(\n\t\t\t/\\/ip4\\/172\\.20\\.0\\.13\\/tcp\\/[0-9]+/,\n\t\t\t\"/ip4/127.0.0.1/tcp/13005\",\n\t\t);\n\n\t// Drop container-internal loopbacks to prevent the Host Agent from dialing itself or conflicting ports\n\tif (\n\t\taddr.includes(\"/ip4/127.0.0.1/tcp/4000\") ||\n\t\taddr.includes(\"/ip4/127.0.0.1/tcp/3000\")\n\t) {\n\t\treturn null;\n\t}\n\n\treturn addr;\n}\n\n/**\n * Checks if a URL points to the local Docker demo environment\n * (loopback address on known demo ports).\n */\nfunction isDockerDemoHost(urlStr: string): boolean {\n\ttry {\n\t\tconst u = new URL(urlStr);\n\t\treturn (\n\t\t\t(u.hostname === \"127.0.0.1\" || u.hostname === \"localhost\") &&\n\t\t\t(u.port === \"13000\" || u.port === \"13001\")\n\t\t);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Determines whether Docker address mapping should be enabled.\n * True when running in development/test mode, when explicitly requested\n * via LIOP_DOCKER_MAP/LIOP_DEV_MODE, or when the Nexus URL points to\n * a local Docker demo port.\n */\nfunction shouldEnableDockerMap(): boolean {\n\treturn (\n\t\tprocess.env.NODE_ENV === \"development\" ||\n\t\tprocess.env.NODE_ENV === \"test\" ||\n\t\tprocess.env.LIOP_DOCKER_MAP === \"true\" ||\n\t\tprocess.env.LIOP_DEV_MODE === \"true\" ||\n\t\t(!!process.env.LIOP_NEXUS_URL &&\n\t\t\tisDockerDemoHost(process.env.LIOP_NEXUS_URL))\n\t);\n}\n\n/**\n * LIOP Agent (Zero-Config CLI)\n *\n * Secure Logic-on-Origin gateway for Claude Desktop.\n * Communicates via STDIO / JSON-RPC.\n *\n * All tool discovery is DYNAMIC via the /liop/manifest/1.0.0 protocol.\n * No hardcoded tools, PeerIDs, or port mappings.\n */\nasync function main() {\n\t// Auto-Relaunch: Ensure system CA certificates are loaded for TLS compatibility.\n\t// Corporate proxies (Cloudflare WARP, Zscaler) inject custom root CAs into the\n\t// OS certificate store. Node.js ignores these by default, causing UNABLE_TO_VERIFY_LEAF_SIGNATURE.\n\t// Pattern: if --use-system-ca is not active, re-spawn with the flag transparently.\n\t// stdio: \"inherit\" ensures Claude Desktop's JSON-RPC pipe is passed through cleanly.\n\tif (\n\t\t(process.platform === \"win32\" || process.platform === \"darwin\") &&\n\t\t!process.execArgv.includes(\"--use-system-ca\") &&\n\t\t!(process.env.NODE_OPTIONS ?? \"\").includes(\"--use-system-ca\")\n\t) {\n\t\tconst { spawn } = await import(\"node:child_process\");\n\t\tconst child = spawn(\n\t\t\tprocess.execPath,\n\t\t\t[\"--use-system-ca\", ...process.argv.slice(1)],\n\t\t\t{ stdio: \"inherit\", env: process.env },\n\t\t);\n\t\tchild.on(\"exit\", (code) => process.exit(code ?? 1));\n\t\tchild.on(\"error\", () => process.exit(1));\n\t\t// Block parent — child handles all I/O from here\n\t\tawait new Promise(() => {});\n\t\treturn;\n\t}\n\n\tconst buildTime = new Date().toISOString();\n\tlog.info(`[LIOP-Agent] 🚀 Version 1.2.0-alpha.9 | Build: ${buildTime}`);\n\n\tconst liopDir = path.join(os.homedir(), \".liop\");\n\tconst identityPath = path.join(liopDir, \"identity.json\");\n\n\tif (!fs.existsSync(liopDir)) {\n\t\tfs.mkdirSync(liopDir, { recursive: true });\n\t}\n\n\t// 1. Determine Bootstrap Nodes (Zero-Config Discovery)\n\tlet bootstrapNodes: string[] = [];\n\n\t// Command line arguments take precedence\n\tconst args = process.argv.slice(2);\n\tif (args.length > 0) {\n\t\tbootstrapNodes = args.filter((a) => a.startsWith(\"/\"));\n\t}\n\n\t// Priority 1: Physical Beacons (Industrial Pattern) - DETERMINISTIC & INSTANT\n\tif (bootstrapNodes.length === 0) {\n\t\tconst searchDirs = [];\n\n\t\t// Priority 1.1: Explicit file from environment variable\n\t\tif (process.env.LIOP_BOOTSTRAP_FILE) {\n\t\t\tlog.warn(\n\t\t\t\t\"LIOP_BOOTSTRAP_FILE is deprecated and will be removed in the next major version. \" +\n\t\t\t\t\t\"Use LIOP_NEXUS_URL for Auto-Discovery instead.\",\n\t\t\t);\n\t\t\tconst filePath = path.resolve(process.env.LIOP_BOOTSTRAP_FILE);\n\t\t\tif (fs.existsSync(filePath)) {\n\t\t\t\tconst addr = fs.readFileSync(filePath, \"utf8\").trim();\n\t\t\t\tif (addr) bootstrapNodes.push(normalizeBootstrap(addr));\n\t\t\t}\n\t\t}\n\n\t\t// Priority 1.2: Traditional locations (Scan for all *.multiaddr)\n\t\tsearchDirs.push(\n\t\t\tprocess.cwd(),\n\t\t\tpath.join(process.cwd(), \"tests/infra/nexus-data\"),\n\t\t\tliopDir,\n\t\t\tpath.join(\n\t\t\t\tpath\n\t\t\t\t\t.dirname(new URL(import.meta.url).pathname)\n\t\t\t\t\t.replace(/^\\/([A-Z]:)/, \"$1\"),\n\t\t\t\t\"../../tests/infra/nexus-data\",\n\t\t\t),\n\t\t);\n\n\t\tfor (const dir of searchDirs) {\n\t\t\ttry {\n\t\t\t\tif (fs.existsSync(dir)) {\n\t\t\t\t\tconst files = fs.readdirSync(dir);\n\t\t\t\t\tconst multiaddrFiles = files.filter((f) => f.endsWith(\".multiaddr\"));\n\n\t\t\t\t\tfor (const file of multiaddrFiles) {\n\t\t\t\t\t\tconst filePath = path.join(dir, file);\n\t\t\t\t\t\tconst addr = fs.readFileSync(filePath, \"utf8\").trim();\n\t\t\t\t\t\tif (addr) {\n\t\t\t\t\t\t\tconst normalized = normalizeBootstrap(addr);\n\t\t\t\t\t\t\tif (!bootstrapNodes.includes(normalized)) {\n\t\t\t\t\t\t\t\tbootstrapNodes.push(normalized);\n\t\t\t\t\t\t\t\tlog.info(`[LIOP-Agent] ✅ Loaded beacon: ${file} from ${dir}`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// If we found any beacons in this directory, we consider discovery successful for this layer\n\t\t\t\t\tif (bootstrapNodes.length > 0) break;\n\t\t\t\t}\n\t\t\t} catch (_e) {\n\t\t\t\t/* ignore */\n\t\t\t}\n\t\t}\n\t}\n\n\t// Priority 2: Auto-Discovery via NEXUS URL (Aggressive Parallel Discovery)\n\tif (process.env.LIOP_NEXUS_URL) {\n\t\tconst nexusUrl = process.env.LIOP_NEXUS_URL;\n\t\tlog.info(\n\t\t\t`[LIOP-Agent] 🌐 Running parallel discovery from: ${nexusUrl} (Sources Found: ${bootstrapNodes.length})`,\n\t\t);\n\n\t\tconst resolved = await resolveBootstrapFromUrl(nexusUrl);\n\t\tif (resolved) {\n\t\t\tconst normalized = normalizeBootstrap(resolved);\n\t\t\tif (!bootstrapNodes.includes(normalized)) {\n\t\t\t\tbootstrapNodes.push(normalized);\n\t\t\t\tlog.info(\n\t\t\t\t\t`[LIOP-Agent] ✅ Added bootstrap from URL discovery: ${normalized}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Priority 3: Environment variable (direct multiaddr)\n\tif (bootstrapNodes.length === 0 && process.env.LIOP_BOOTSTRAP) {\n\t\tbootstrapNodes.push(process.env.LIOP_BOOTSTRAP.trim());\n\t}\n\n\t// Final fallback: local Nexus bootstrap for demo environments.\n\t// Avoid injecting stale static peer IDs when discovery already found valid peers.\n\tif (bootstrapNodes.length === 0) {\n\t\tbootstrapNodes.push(\n\t\t\t\"/ip4/127.0.0.1/tcp/13001/p2p/12D3KooWD8FUFdnLQzzLFNdicsaTknM5cpD7os9sK9NWVSVABJMD\",\n\t\t);\n\t}\n\n\t// Sanitize/validate all candidate multiaddrs so malformed PeerIDs don't crash startup.\n\tbootstrapNodes = bootstrapNodes.filter((addr) => {\n\t\ttry {\n\t\t\tmultiaddr(addr);\n\t\t\treturn true;\n\t\t} catch {\n\t\t\tlog.warn(`[LIOP-Agent] Ignoring invalid bootstrap multiaddr: ${addr}`);\n\t\t\treturn false;\n\t\t}\n\t});\n\n\t// If no bootstrap nodes found, the agent operates in standalone mode.\n\t// It will only serve local tools until peers are discovered.\n\tif (bootstrapNodes.length === 0) {\n\t\tlog.info(\n\t\t\t\"[LIOP-Agent] No bootstrap nodes configured. Operating in standalone mode.\",\n\t\t);\n\t\tlog.info(\n\t\t\t\"[LIOP-Agent] Pass a multiaddr as argument or create 'nexus.multiaddr' file.\",\n\t\t);\n\t}\n\n\t// Initialize local server node (lightweight, no tools registered locally)\n\tconst liopServer = new LiopServer({\n\t\tname: \"@nekzus/liop\",\n\t\tversion: \"1.0.0\",\n\t});\n\n\t// Enable Zero-Shot Autonomy (Industrial Prompt Injection)\n\tliopServer.enableZeroShotAutonomy();\n\n\t// 2. Mesh Node Configuration\n\tconst meshNode = new MeshNode({\n\t\tidentityPath: identityPath,\n\t\tbootstrapNodes: bootstrapNodes,\n\t\taddressMapper: shouldEnableDockerMap()\n\t\t\t? industrialAddressMapper\n\t\t\t: undefined,\n\t});\n\n\t// Start P2P Mesh\n\tawait meshNode.start();\n\n\t// 3. Initialize the Dynamic Router\n\t// No hardcoded tools — all discovery happens via liop:manifest protocol\n\tconst router = new LiopMcpRouter(liopServer, meshNode);\n\n\t// Proactive Notification to Claude Desktop when tools/resources are discovered dynamically\n\trouter.onToolsChanged = () => {\n\t\tprocess.stdout.write(\n\t\t\t`{\"jsonrpc\":\"2.0\",\"method\":\"notifications/tools/list_changed\"}\\n`,\n\t\t);\n\t\tprocess.stdout.write(\n\t\t\t`{\"jsonrpc\":\"2.0\",\"method\":\"notifications/resources/list_changed\"}\\n`,\n\t\t);\n\t};\n\n\t// Initial warming period (2s) then Adaptive Background Discovery\n\t// Polls DHT for new nodes and triggers onToolsChanged when topology shifts.\n\t// Uses exponential backoff to reduce polling load on stable meshes.\n\tsetTimeout(() => {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: access internal for telemetry\n\t\tconst rtSize = (meshNode as any).getRoutingTableSize?.() || 0;\n\t\tlog.info(`[LIOP-Agent] Warm-up complete. Routing Table size: ${rtSize}`);\n\t\trouter.refreshManifestCache(true).catch(() => {});\n\t}, 2000);\n\n\tconst POLL_BASE_MS = 10_000;\n\tconst POLL_MAX_MS = 120_000;\n\tlet pollIntervalMs = POLL_BASE_MS;\n\n\tconst scheduleAdaptivePoll = () => {\n\t\tsetTimeout(async () => {\n\t\t\tconst prevSize = router.getCacheSize();\n\t\t\tawait router.refreshManifestCache(true).catch(() => {});\n\t\t\tconst newSize = router.getCacheSize();\n\n\t\t\tif (newSize !== prevSize) {\n\t\t\t\t// Topology changed — reset to aggressive polling\n\t\t\t\tpollIntervalMs = POLL_BASE_MS;\n\t\t\t\tlog.info(\n\t\t\t\t\t`[LIOP-Agent] Topology change detected (${prevSize} → ${newSize}). Resetting poll to ${POLL_BASE_MS / 1000}s.`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// Stable — relax polling interval (factor 1.5)\n\t\t\t\tpollIntervalMs = Math.min(\n\t\t\t\t\tMath.round(pollIntervalMs * 1.5),\n\t\t\t\t\tPOLL_MAX_MS,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tscheduleAdaptivePoll();\n\t\t}, pollIntervalMs);\n\t};\n\n\tscheduleAdaptivePoll();\n\n\t// 4. STDIO Transport — Buffered Line Reader\n\t// Uses readline to guarantee complete JSON-RPC messages before parsing.\n\t// Raw stdin.on(\"data\") can fragment large payloads across multiple chunks.\n\tconst readline = await import(\"node:readline\");\n\tconst rl = readline.createInterface({\n\t\tinput: process.stdin,\n\t\tterminal: false,\n\t});\n\n\tprocess.stdout.on(\"error\", (err: Error & { code?: string }) => {\n\t\tif (err.code === \"EPIPE\") {\n\t\t\tprocess.exit(0); // Graceful exit when Claude Desktop disconnects\n\t\t}\n\t});\n\n\trl.on(\"line\", async (line) => {\n\t\tconst trimmed = line.trim();\n\t\tif (!trimmed) return;\n\n\t\ttry {\n\t\t\tconst request = JSON.parse(trimmed) as McpRequest;\n\t\t\tif (request.method) {\n\t\t\t\tconst response = await router.dispatch(request);\n\t\t\t\tif (response) {\n\t\t\t\t\tprocess.stdout.write(`${JSON.stringify(response)}\\n`);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (_err) {\n\t\t\t// Silent catch for binary noise or malformed lines\n\t\t}\n\t});\n\n\trl.on(\"close\", () => {\n\t\tprocess.exit(0);\n\t});\n\n\t// Status directed only to stderr\n\tlog.info(`[LIOP-Agent] Guarding Claude Desktop via STDIO.`);\n\tlog.info(\n\t\t`[LIOP-Agent] P2P Mesh: Joined (${bootstrapNodes.length} bootstraps)`,\n\t);\n\tlog.info(\"[LIOP-Agent] Tool discovery: Dynamic via /liop/manifest/1.0.0\");\n\n\tprocess.on(\"SIGINT\", async () => {\n\t\tawait meshNode.stop();\n\t\tprocess.exit(0);\n\t});\n}\n\nmain().catch((err) => {\n\tlog.error(`[LIOP-Agent] Fatal Error: ${err.message}`);\n\tprocess.exit(1);\n});\n"]}
1
+ {"version":3,"sources":["../../src/bin/agent.ts"],"names":[],"mappings":"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","file":"agent.js","sourcesContent":["#!/usr/bin/env node\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { multiaddr } from \"@multiformats/multiaddr\";\nimport { LiopMcpRouter } from \"../gateway/router.js\";\nimport { MeshNode } from \"../mesh/index.js\";\nimport { LiopServer } from \"../server/index.js\";\nimport type { McpRequest } from \"../types.js\";\nimport { log } from \"../utils/logger.js\";\n\n/**\n * Resolves a full libp2p multiaddr (with PeerID) from a LIOP node's\n * HTTP health endpoint. This enables zero-config bootstrap — users\n * only need to provide a URL, not a cryptographic PeerID.\n *\n * @param url - HTTP URL of a LIOP node's health endpoint (e.g. \"http://host:3000\")\n * @returns Full multiaddr string with PeerID, or null if resolution fails\n */\nasync function resolveBootstrapFromUrl(url: string): Promise<string | null> {\n\ttry {\n\t\tconst healthUrl = url.endsWith(\"/health\") ? url : `${url}/health`;\n\t\tconst response = await fetch(healthUrl, {\n\t\t\theaders: { Accept: \"application/json\" },\n\t\t\tsignal: AbortSignal.timeout(10000), // Increased to 10s\n\t\t});\n\t\tif (!response.ok) return null;\n\n\t\tconst data = await response.json();\n\t\tif (!data.mesh?.multiaddrs?.length || !data.mesh?.peerId) return null;\n\n\t\t// Find TCP multiaddr (prefer non-websocket for stability)\n\t\tconst tcpAddr = data.mesh.multiaddrs.find(\n\t\t\t(a: string) =>\n\t\t\t\ta.includes(\"/tcp/\") &&\n\t\t\t\t!a.includes(\"/ws\") &&\n\t\t\t\t!a.includes(\"/ip4/127.0.0.1/\"),\n\t\t);\n\t\tif (!tcpAddr) return null;\n\n\t\t// Rewrite internal Docker IP using the address mapper if enabled\n\t\tlet resolved = shouldEnableDockerMap()\n\t\t\t? industrialAddressMapper(tcpAddr)\n\t\t\t: tcpAddr;\n\t\tif (!resolved || resolved === tcpAddr) {\n\t\t\tconst urlHost = new URL(url).hostname;\n\t\t\tresolved = tcpAddr.replace(/\\/ip4\\/[^/]+/, `/ip4/${urlHost}`);\n\t\t}\n\n\t\tif (!resolved) return null;\n\n\t\tresolved += resolved.includes(\"/p2p/\") ? \"\" : `/p2p/${data.mesh.peerId}`;\n\n\t\treturn resolved;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Normalizes a bootstrap multiaddr string.\n * If the address contains a Docker bridge IP (172.16-31.x.x) or Loopback (127.0.0.1),\n * rewrites it to the host accessible via LIOP_NEXUS_URL (e.g. WSL2 IP).\n * This is critical when WSL2 mirror-mode networking is broken.\n */\nfunction normalizeBootstrap(addr: string): string {\n\tconst trimmed = addr.trim();\n\t// Remap Docker bridge IPs and ANY external physical IPs to 127.0.0.1\n\t// because Test-NetConnection confirmed 127.0.0.1 is the only reliable path to Docker ports.\n\tconst dockerIpRegex =\n\t\t/\\/ip4\\/172\\.(1[6-9]|2[0-9]|3[0-1])\\.[0-9]{1,3}\\.[0-9]{1,3}/;\n\tconst loopbackRegex = /\\/ip4\\/127\\.0\\.0\\.1/;\n\tconst physicalIpRegex = /\\/ip4\\/192\\.168\\.[0-9]{1,3}\\.[0-9]{1,3}/;\n\n\tif (\n\t\tdockerIpRegex.test(trimmed) ||\n\t\tloopbackRegex.test(trimmed) ||\n\t\tphysicalIpRegex.test(trimmed)\n\t) {\n\t\tconst targetIp = \"127.0.0.1\";\n\t\tconst normalized = trimmed\n\t\t\t.replace(dockerIpRegex, `/ip4/${targetIp}`)\n\t\t\t.replace(loopbackRegex, `/ip4/${targetIp}`)\n\t\t\t.replace(physicalIpRegex, `/ip4/${targetIp}`);\n\n\t\tif (normalized !== trimmed) {\n\t\t\tlog.info(\n\t\t\t\t`[LIOP-Agent] 🔄 Local Routing Hack → Forced 127.0.0.1: ${normalized}`,\n\t\t\t);\n\t\t}\n\t\treturn normalized;\n\t}\n\n\treturn trimmed;\n}\n\n/**\n * industrialAddressMapper\n *\n * Maps Docker-internal IPs to host-published ports for local demo environments.\n * Activated when any of the following conditions are met:\n * - NODE_ENV is \"development\" or \"test\"\n * - LIOP_DOCKER_MAP=\"true\" or LIOP_DEV_MODE=\"true\" is set\n * - LIOP_NEXUS_URL points to a local Docker demo port (127.0.0.1:13000|13001)\n *\n * Nexus (172.20.0.10) -> 13001\n * Vault (172.20.0.11) -> 13003\n * Bank (172.20.0.12) -> 13004\n * Oracle(172.20.0.13) -> 13005\n */\nfunction industrialAddressMapper(addr: string): string | null {\n\tif (addr.includes(\"/ip4/172.20.0.10\"))\n\t\treturn addr.replace(\n\t\t\t/\\/ip4\\/172\\.20\\.0\\.10\\/tcp\\/[0-9]+/,\n\t\t\t\"/ip4/127.0.0.1/tcp/13001\",\n\t\t);\n\tif (addr.includes(\"/ip4/172.20.0.11\"))\n\t\treturn addr.replace(\n\t\t\t/\\/ip4\\/172\\.20\\.0\\.11\\/tcp\\/[0-9]+/,\n\t\t\t\"/ip4/127.0.0.1/tcp/13003\",\n\t\t);\n\tif (addr.includes(\"/ip4/172.20.0.12\"))\n\t\treturn addr.replace(\n\t\t\t/\\/ip4\\/172\\.20\\.0\\.12\\/tcp\\/[0-9]+/,\n\t\t\t\"/ip4/127.0.0.1/tcp/13004\",\n\t\t);\n\tif (addr.includes(\"/ip4/172.20.0.13\"))\n\t\treturn addr.replace(\n\t\t\t/\\/ip4\\/172\\.20\\.0\\.13\\/tcp\\/[0-9]+/,\n\t\t\t\"/ip4/127.0.0.1/tcp/13005\",\n\t\t);\n\n\t// Drop container-internal loopbacks to prevent the Host Agent from dialing itself or conflicting ports\n\tif (\n\t\taddr.includes(\"/ip4/127.0.0.1/tcp/4000\") ||\n\t\taddr.includes(\"/ip4/127.0.0.1/tcp/3000\")\n\t) {\n\t\treturn null;\n\t}\n\n\treturn addr;\n}\n\n/**\n * Checks if a URL points to the local Docker demo environment\n * (loopback address on known demo ports).\n */\nfunction isDockerDemoHost(urlStr: string): boolean {\n\ttry {\n\t\tconst u = new URL(urlStr);\n\t\treturn (\n\t\t\t(u.hostname === \"127.0.0.1\" || u.hostname === \"localhost\") &&\n\t\t\t(u.port === \"13000\" || u.port === \"13001\")\n\t\t);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Determines whether Docker address mapping should be enabled.\n * True when running in development/test mode, when explicitly requested\n * via LIOP_DOCKER_MAP/LIOP_DEV_MODE, or when the Nexus URL points to\n * a local Docker demo port.\n */\nfunction shouldEnableDockerMap(): boolean {\n\treturn (\n\t\tprocess.env.NODE_ENV === \"development\" ||\n\t\tprocess.env.NODE_ENV === \"test\" ||\n\t\tprocess.env.LIOP_DOCKER_MAP === \"true\" ||\n\t\tprocess.env.LIOP_DEV_MODE === \"true\" ||\n\t\t(!!process.env.LIOP_NEXUS_URL &&\n\t\t\tisDockerDemoHost(process.env.LIOP_NEXUS_URL))\n\t);\n}\n\n/**\n * LIOP Agent (Zero-Config CLI)\n *\n * Secure Logic-on-Origin gateway for Claude Desktop.\n * Communicates via STDIO / JSON-RPC.\n *\n * All tool discovery is DYNAMIC via the /liop/manifest/1.0.0 protocol.\n * No hardcoded tools, PeerIDs, or port mappings.\n */\nasync function main() {\n\t// Auto-Relaunch: Ensure system CA certificates are loaded for TLS compatibility.\n\t// Corporate proxies (Cloudflare WARP, Zscaler) inject custom root CAs into the\n\t// OS certificate store. Node.js ignores these by default, causing UNABLE_TO_VERIFY_LEAF_SIGNATURE.\n\t// Pattern: if --use-system-ca is not active, re-spawn with the flag transparently.\n\t// stdio: \"inherit\" ensures Claude Desktop's JSON-RPC pipe is passed through cleanly.\n\tif (\n\t\t(process.platform === \"win32\" || process.platform === \"darwin\") &&\n\t\t!process.execArgv.includes(\"--use-system-ca\") &&\n\t\t!(process.env.NODE_OPTIONS ?? \"\").includes(\"--use-system-ca\")\n\t) {\n\t\tconst { spawn } = await import(\"node:child_process\");\n\t\tconst child = spawn(\n\t\t\tprocess.execPath,\n\t\t\t[\"--use-system-ca\", ...process.argv.slice(1)],\n\t\t\t{ stdio: \"inherit\", env: process.env },\n\t\t);\n\t\tchild.on(\"exit\", (code) => process.exit(code ?? 1));\n\t\tchild.on(\"error\", () => process.exit(1));\n\t\t// Block parent — child handles all I/O from here\n\t\tawait new Promise(() => {});\n\t\treturn;\n\t}\n\n\tconst buildTime = new Date().toISOString();\n\tlog.info(`[LIOP-Agent] 🚀 Version 1.2.0-alpha.9 | Build: ${buildTime}`);\n\n\tconst liopDir = path.join(os.homedir(), \".liop\");\n\tconst identityPath = path.join(liopDir, \"identity.json\");\n\n\tif (!fs.existsSync(liopDir)) {\n\t\tfs.mkdirSync(liopDir, { recursive: true });\n\t}\n\n\t// 1. Determine Bootstrap Nodes (Zero-Config Discovery)\n\tlet bootstrapNodes: string[] = [];\n\n\t// Command line arguments take precedence\n\tconst args = process.argv.slice(2);\n\tif (args.length > 0) {\n\t\tbootstrapNodes = args.filter((a) => a.startsWith(\"/\"));\n\t}\n\n\t// Priority 1: Physical Beacons (Industrial Pattern) - DETERMINISTIC & INSTANT\n\tif (bootstrapNodes.length === 0) {\n\t\tconst searchDirs = [];\n\n\t\t// Priority 1.1: Explicit file from environment variable\n\t\tif (process.env.LIOP_BOOTSTRAP_FILE) {\n\t\t\tlog.warn(\n\t\t\t\t\"LIOP_BOOTSTRAP_FILE is deprecated and will be removed in the next major version. \" +\n\t\t\t\t\t\"Use LIOP_NEXUS_URL for Auto-Discovery instead.\",\n\t\t\t);\n\t\t\tconst filePath = path.resolve(process.env.LIOP_BOOTSTRAP_FILE);\n\t\t\tif (fs.existsSync(filePath)) {\n\t\t\t\tconst addr = fs.readFileSync(filePath, \"utf8\").trim();\n\t\t\t\tif (addr) bootstrapNodes.push(normalizeBootstrap(addr));\n\t\t\t}\n\t\t}\n\n\t\t// Priority 1.2: Traditional locations (Scan for all *.multiaddr)\n\t\tsearchDirs.push(\n\t\t\tprocess.cwd(),\n\t\t\tpath.join(process.cwd(), \"tests/infra/nexus-data\"),\n\t\t\tliopDir,\n\t\t\tpath.join(\n\t\t\t\tpath\n\t\t\t\t\t.dirname(new URL(import.meta.url).pathname)\n\t\t\t\t\t.replace(/^\\/([A-Z]:)/, \"$1\"),\n\t\t\t\t\"../../tests/infra/nexus-data\",\n\t\t\t),\n\t\t);\n\n\t\tfor (const dir of searchDirs) {\n\t\t\ttry {\n\t\t\t\tif (fs.existsSync(dir)) {\n\t\t\t\t\tconst files = fs.readdirSync(dir);\n\t\t\t\t\tconst multiaddrFiles = files.filter((f) => f.endsWith(\".multiaddr\"));\n\n\t\t\t\t\tfor (const file of multiaddrFiles) {\n\t\t\t\t\t\tconst filePath = path.join(dir, file);\n\t\t\t\t\t\tconst addr = fs.readFileSync(filePath, \"utf8\").trim();\n\t\t\t\t\t\tif (addr) {\n\t\t\t\t\t\t\tconst normalized = normalizeBootstrap(addr);\n\t\t\t\t\t\t\tif (!bootstrapNodes.includes(normalized)) {\n\t\t\t\t\t\t\t\tbootstrapNodes.push(normalized);\n\t\t\t\t\t\t\t\tlog.info(`[LIOP-Agent] ✅ Loaded beacon: ${file} from ${dir}`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// If we found any beacons in this directory, we consider discovery successful for this layer\n\t\t\t\t\tif (bootstrapNodes.length > 0) break;\n\t\t\t\t}\n\t\t\t} catch (_e) {\n\t\t\t\t/* ignore */\n\t\t\t}\n\t\t}\n\t}\n\n\t// Priority 2: Auto-Discovery via NEXUS URL (Aggressive Parallel Discovery)\n\tif (process.env.LIOP_NEXUS_URL) {\n\t\tconst nexusUrl = process.env.LIOP_NEXUS_URL;\n\t\tlog.info(\n\t\t\t`[LIOP-Agent] 🌐 Running parallel discovery from: ${nexusUrl} (Sources Found: ${bootstrapNodes.length})`,\n\t\t);\n\n\t\tconst resolved = await resolveBootstrapFromUrl(nexusUrl);\n\t\tif (resolved) {\n\t\t\tconst normalized = normalizeBootstrap(resolved);\n\t\t\tif (!bootstrapNodes.includes(normalized)) {\n\t\t\t\tbootstrapNodes.push(normalized);\n\t\t\t\tlog.info(\n\t\t\t\t\t`[LIOP-Agent] ✅ Added bootstrap from URL discovery: ${normalized}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Priority 3: Environment variable (direct multiaddr)\n\tif (bootstrapNodes.length === 0 && process.env.LIOP_BOOTSTRAP) {\n\t\tbootstrapNodes.push(process.env.LIOP_BOOTSTRAP.trim());\n\t}\n\n\t// Final fallback: local Nexus bootstrap for demo environments.\n\t// Avoid injecting stale static peer IDs when discovery already found valid peers.\n\tif (bootstrapNodes.length === 0) {\n\t\tbootstrapNodes.push(\n\t\t\t\"/ip4/127.0.0.1/tcp/13001/p2p/12D3KooWD8FUFdnLQzzLFNdicsaTknM5cpD7os9sK9NWVSVABJMD\",\n\t\t);\n\t}\n\n\t// Sanitize/validate all candidate multiaddrs so malformed PeerIDs don't crash startup.\n\tbootstrapNodes = bootstrapNodes.filter((addr) => {\n\t\ttry {\n\t\t\tmultiaddr(addr);\n\t\t\treturn true;\n\t\t} catch {\n\t\t\tlog.warn(`[LIOP-Agent] Ignoring invalid bootstrap multiaddr: ${addr}`);\n\t\t\treturn false;\n\t\t}\n\t});\n\n\t// If no bootstrap nodes found, the agent operates in standalone mode.\n\t// It will only serve local tools until peers are discovered.\n\tif (bootstrapNodes.length === 0) {\n\t\tlog.info(\n\t\t\t\"[LIOP-Agent] No bootstrap nodes configured. Operating in standalone mode.\",\n\t\t);\n\t\tlog.info(\n\t\t\t\"[LIOP-Agent] Pass a multiaddr as argument or create 'nexus.multiaddr' file.\",\n\t\t);\n\t}\n\n\t// Initialize local server node (lightweight, no tools registered locally)\n\tconst liopServer = new LiopServer({\n\t\tname: \"@nekzus/liop\",\n\t\tversion: \"1.0.0\",\n\t});\n\n\t// Enable Zero-Shot Autonomy (Industrial Prompt Injection)\n\tliopServer.enableZeroShotAutonomy();\n\n\t// 2. Mesh Node Configuration\n\tconst meshNode = new MeshNode({\n\t\tidentityPath: identityPath,\n\t\tbootstrapNodes: bootstrapNodes,\n\t\taddressMapper: shouldEnableDockerMap()\n\t\t\t? industrialAddressMapper\n\t\t\t: undefined,\n\t});\n\n\t// Start P2P Mesh\n\tawait meshNode.start();\n\n\t// 3. Initialize the Dynamic Router\n\t// No hardcoded tools — all discovery happens via liop:manifest protocol\n\tconst router = new LiopMcpRouter(liopServer, meshNode);\n\n\t// Proactive Notification to Claude Desktop when tools/resources are discovered dynamically\n\trouter.onToolsChanged = () => {\n\t\tprocess.stdout.write(\n\t\t\t`{\"jsonrpc\":\"2.0\",\"method\":\"notifications/tools/list_changed\"}\\n`,\n\t\t);\n\t\tprocess.stdout.write(\n\t\t\t`{\"jsonrpc\":\"2.0\",\"method\":\"notifications/resources/list_changed\"}\\n`,\n\t\t);\n\t};\n\n\t// Initial warming period (2s) then Adaptive Background Discovery\n\t// Polls DHT for new nodes and triggers onToolsChanged when topology shifts.\n\t// Uses exponential backoff to reduce polling load on stable meshes.\n\tsetTimeout(() => {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: access internal for telemetry\n\t\tconst rtSize = (meshNode as any).getRoutingTableSize?.() || 0;\n\t\tlog.info(`[LIOP-Agent] Warm-up complete. Routing Table size: ${rtSize}`);\n\t\trouter.refreshManifestCache(true).catch(() => {});\n\t}, 2000);\n\n\tconst POLL_BASE_MS = 10_000;\n\tconst POLL_MAX_MS = 120_000;\n\tlet pollIntervalMs = POLL_BASE_MS;\n\n\tconst scheduleAdaptivePoll = () => {\n\t\tsetTimeout(async () => {\n\t\t\tconst prevSize = router.getCacheSize();\n\t\t\tawait router.refreshManifestCache(true).catch(() => {});\n\t\t\tconst newSize = router.getCacheSize();\n\n\t\t\tif (newSize !== prevSize) {\n\t\t\t\t// Topology changed — reset to aggressive polling\n\t\t\t\tpollIntervalMs = POLL_BASE_MS;\n\t\t\t\tlog.info(\n\t\t\t\t\t`[LIOP-Agent] Topology change detected (${prevSize} → ${newSize}). Resetting poll to ${POLL_BASE_MS / 1000}s.`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// Stable — relax polling interval (factor 1.5)\n\t\t\t\tpollIntervalMs = Math.min(\n\t\t\t\t\tMath.round(pollIntervalMs * 1.5),\n\t\t\t\t\tPOLL_MAX_MS,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tscheduleAdaptivePoll();\n\t\t}, pollIntervalMs);\n\t};\n\n\tscheduleAdaptivePoll();\n\n\t// 4. STDIO Transport — Buffered Line Reader\n\t// Uses readline to guarantee complete JSON-RPC messages before parsing.\n\t// Raw stdin.on(\"data\") can fragment large payloads across multiple chunks.\n\tconst readline = await import(\"node:readline\");\n\tconst rl = readline.createInterface({\n\t\tinput: process.stdin,\n\t\tterminal: false,\n\t});\n\n\tprocess.stdout.on(\"error\", (err: Error & { code?: string }) => {\n\t\tif (err.code === \"EPIPE\") {\n\t\t\tprocess.exit(0); // Graceful exit when Claude Desktop disconnects\n\t\t}\n\t});\n\n\trl.on(\"line\", async (line) => {\n\t\tconst trimmed = line.trim();\n\t\tif (!trimmed) return;\n\n\t\ttry {\n\t\t\tconst request = JSON.parse(trimmed) as McpRequest;\n\t\t\tif (request.method) {\n\t\t\t\tconst response = await router.dispatch(request);\n\t\t\t\tif (response) {\n\t\t\t\t\tprocess.stdout.write(`${JSON.stringify(response)}\\n`);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (_err) {\n\t\t\t// Silent catch for binary noise or malformed lines\n\t\t}\n\t});\n\n\trl.on(\"close\", () => {\n\t\tprocess.exit(0);\n\t});\n\n\t// Status directed only to stderr\n\tlog.info(`[LIOP-Agent] Guarding Claude Desktop via STDIO.`);\n\tlog.info(\n\t\t`[LIOP-Agent] P2P Mesh: Joined (${bootstrapNodes.length} bootstraps)`,\n\t);\n\tlog.info(\"[LIOP-Agent] Tool discovery: Dynamic via /liop/manifest/1.0.0\");\n\n\tprocess.on(\"SIGINT\", async () => {\n\t\tawait meshNode.stop();\n\t\tprocess.exit(0);\n\t});\n}\n\nmain().catch((err) => {\n\tlog.error(`[LIOP-Agent] Fatal Error: ${err.message}`);\n\tprocess.exit(1);\n});\n"]}
package/dist/bridge.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { L as LiopServer, a as LiopServerOptions } from './index-CL8m1L1d.js';
2
+ import { L as LiopServer, a as LiopServerOptions } from './index-BlGc0iym.js';
3
3
  import 'zod';
4
4
  import './mesh.js';
5
- import './types-DzEXgi4s.js';
5
+ import './types-sKeUxuky.js';
6
6
  import 'jose';
7
7
 
8
8
  /**
package/dist/bridge.js CHANGED
@@ -1,2 +1,5 @@
1
- export{b as LiopMcpBridge,a as LiopStreamBridge}from'./chunk-W2QGWRTT.js';import'./chunk-S6RJHZV2.js';import'./chunk-4C666HHU.js';//# sourceMappingURL=bridge.js.map
1
+ export { LiopMcpBridge, LiopStreamBridge } from './chunk-IMPCCZ2Y.js';
2
+ import './chunk-72MNYFR6.js';
3
+ import './chunk-PZ5AY32C.js';
4
+ //# sourceMappingURL=bridge.js.map
2
5
  //# sourceMappingURL=bridge.js.map