@nekzus/liop-studio 1.0.0-alpha.0 → 1.0.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.
- package/README.md +9 -0
- package/dist/cli/index.js +118 -28
- package/dist/cli/index.js.map +1 -1
- package/dist/{index-DLA-Sm4s.d.ts → index-Cl7IupN0.d.ts} +2 -0
- package/dist/index.d.ts +9 -3
- package/dist/index.js +97 -25
- package/dist/index.js.map +1 -1
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.js +87 -25
- package/dist/server/index.js.map +1 -1
- package/package.json +35 -6
- package/ui/README.md +45 -59
- package/ui/dist/assets/index-BjiNGEL8.js +306 -0
- package/ui/dist/assets/index-Cr1w0czW.css +1 -0
- package/ui/dist/favicon.svg +14 -0
- package/ui/dist/icons.svg +24 -0
- package/ui/dist/index.html +14 -0
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# @nekzus/liop-studio
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@nekzus/liop-studio)
|
|
4
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
5
|
+
[](https://nekzus-32.mintlify.app/)
|
|
6
|
+
|
|
3
7
|
> **LIOP Sovereign Studio & Mesh Scanner**: Developer studio, interactive testbed, and network scanner for the Logic-Injection-on-Origin Protocol (LIOP) and Model Context Protocol (MCP).
|
|
4
8
|
|
|
5
9
|
---
|
|
@@ -40,5 +44,10 @@ npx @nekzus/liop-studio scan /ip4/127.0.0.1/tcp/4000/p2p/12D3KooW...
|
|
|
40
44
|
|
|
41
45
|
---
|
|
42
46
|
|
|
47
|
+
## 📚 Documentation
|
|
48
|
+
For complete guides, API references, and architecture specifications, visit the [official LIOP documentation](https://nekzus-32.mintlify.app/).
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
43
52
|
## 📄 License
|
|
44
53
|
Apache-2.0. Copyright 2026 Nekzus Solutions and contributors.
|
package/dist/cli/index.js
CHANGED
|
@@ -5,9 +5,9 @@ import { Command } from "commander";
|
|
|
5
5
|
import pc2 from "picocolors";
|
|
6
6
|
|
|
7
7
|
// src/server/index.ts
|
|
8
|
-
import
|
|
8
|
+
import path2 from "path";
|
|
9
9
|
import process3 from "process";
|
|
10
|
-
import { fileURLToPath } from "url";
|
|
10
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
11
11
|
import { serve } from "@hono/node-server";
|
|
12
12
|
import { serveStatic } from "@hono/node-server/serve-static";
|
|
13
13
|
import { TokenTelemetryEngine as TokenTelemetryEngine5 } from "@nekzus/liop";
|
|
@@ -63,10 +63,29 @@ function validateHttpTarget(targetUrl) {
|
|
|
63
63
|
}
|
|
64
64
|
return parsed;
|
|
65
65
|
}
|
|
66
|
-
function validateHostHeader(host, allowedHosts = [
|
|
66
|
+
function validateHostHeader(host, allowedHosts = [
|
|
67
|
+
"localhost",
|
|
68
|
+
"127.0.0.1",
|
|
69
|
+
"0.0.0.0",
|
|
70
|
+
"::1",
|
|
71
|
+
"[::1]"
|
|
72
|
+
]) {
|
|
67
73
|
if (!host) return false;
|
|
68
|
-
const
|
|
69
|
-
|
|
74
|
+
const trimmed = host.trim();
|
|
75
|
+
let hostname;
|
|
76
|
+
if (trimmed.startsWith("[")) {
|
|
77
|
+
const closingIndex = trimmed.indexOf("]");
|
|
78
|
+
hostname = closingIndex !== -1 ? trimmed.slice(0, closingIndex + 1) : trimmed;
|
|
79
|
+
} else if (trimmed.includes(":") && trimmed.indexOf(":") !== trimmed.lastIndexOf(":")) {
|
|
80
|
+
hostname = trimmed;
|
|
81
|
+
} else {
|
|
82
|
+
hostname = trimmed.split(":")[0];
|
|
83
|
+
}
|
|
84
|
+
hostname = hostname.toLowerCase();
|
|
85
|
+
return allowedHosts.some((allowed) => {
|
|
86
|
+
const normAllowed = allowed.toLowerCase();
|
|
87
|
+
return normAllowed === hostname || hostname === "[::1]" && normAllowed === "::1" || hostname === "::1" && normAllowed === "[::1]";
|
|
88
|
+
});
|
|
70
89
|
}
|
|
71
90
|
|
|
72
91
|
// src/transports/grpc.transport.ts
|
|
@@ -91,7 +110,8 @@ var DEFAULT_PRESET_PROFILES = [
|
|
|
91
110
|
role: "Clinical Healthcare & EHR Patient Records",
|
|
92
111
|
isolation: "pnet Swarm Key (PSK) + HIPAA Strict Mode",
|
|
93
112
|
dataset: "2,500 clinical EHR patient records",
|
|
94
|
-
defaultTool: "Analyze_Synthetic_Medical_Records"
|
|
113
|
+
defaultTool: "Analyze_Synthetic_Medical_Records",
|
|
114
|
+
defaultTools: ["Analyze_Synthetic_Medical_Records"]
|
|
95
115
|
},
|
|
96
116
|
{
|
|
97
117
|
id: "bank",
|
|
@@ -103,7 +123,8 @@ var DEFAULT_PRESET_PROFILES = [
|
|
|
103
123
|
role: "Core Banking & Financial Settlement",
|
|
104
124
|
isolation: "pnet Swarm Key (PSK) + Differential Privacy",
|
|
105
125
|
dataset: "1,500 synthetic accounts ($148M balance)",
|
|
106
|
-
defaultTool: "Analyze_Synthetic_Bank_Transactions"
|
|
126
|
+
defaultTool: "Analyze_Synthetic_Bank_Transactions",
|
|
127
|
+
defaultTools: ["Analyze_Synthetic_Bank_Transactions"]
|
|
107
128
|
},
|
|
108
129
|
{
|
|
109
130
|
id: "blg",
|
|
@@ -114,7 +135,12 @@ var DEFAULT_PRESET_PROFILES = [
|
|
|
114
135
|
tierLabel: "Tier 1: Sovereign Enclaves (In-Situ Origin)",
|
|
115
136
|
role: "Dual-NIC Perimeter Security Bridge (Tier 1 <-> Tier 2)",
|
|
116
137
|
isolation: "6-Layer Zero-Trust + AST Guardian + Egress Shield",
|
|
117
|
-
defaultTool: "BLG_Inspect_Enclave_Perimeter"
|
|
138
|
+
defaultTool: "BLG_Inspect_Enclave_Perimeter",
|
|
139
|
+
defaultTools: [
|
|
140
|
+
"BLG_Inspect_Enclave_Perimeter",
|
|
141
|
+
"BLG_Execute_Healthcare_Analytics",
|
|
142
|
+
"BLG_Execute_Banking_Analytics"
|
|
143
|
+
]
|
|
118
144
|
},
|
|
119
145
|
{
|
|
120
146
|
id: "oracle",
|
|
@@ -126,7 +152,8 @@ var DEFAULT_PRESET_PROFILES = [
|
|
|
126
152
|
role: "Real-time High Frequency Trading Market Simulator",
|
|
127
153
|
isolation: "Consortium Node + 50ms Tick Streaming Buffer",
|
|
128
154
|
dataset: "8 Instruments + L2 Orderbook",
|
|
129
|
-
defaultTool: "Analyze_HFT_Market_Data"
|
|
155
|
+
defaultTool: "Analyze_HFT_Market_Data",
|
|
156
|
+
defaultTools: ["Analyze_HFT_Market_Data", "LiopMeshStatus"]
|
|
130
157
|
},
|
|
131
158
|
{
|
|
132
159
|
id: "relay",
|
|
@@ -136,7 +163,8 @@ var DEFAULT_PRESET_PROFILES = [
|
|
|
136
163
|
tierLabel: "Tier 2: Consortium Routing & Gateways",
|
|
137
164
|
role: "Kademlia DHT & libp2p Circuit Relay v2 Node",
|
|
138
165
|
isolation: "Public Swarm Mesh Relay",
|
|
139
|
-
defaultTool: "LiopMeshStatus"
|
|
166
|
+
defaultTool: "LiopMeshStatus",
|
|
167
|
+
defaultTools: ["LiopMeshStatus"]
|
|
140
168
|
},
|
|
141
169
|
{
|
|
142
170
|
id: "nexus",
|
|
@@ -146,7 +174,8 @@ var DEFAULT_PRESET_PROFILES = [
|
|
|
146
174
|
tierLabel: "Tier 2: Consortium Routing & Gateways",
|
|
147
175
|
role: "OAuth 2.1 RFC 8707 Auth Server & Mesh Authority",
|
|
148
176
|
isolation: "Zero-Trust Identity Provider",
|
|
149
|
-
defaultTool: "Authenticate_Client"
|
|
177
|
+
defaultTool: "Authenticate_Client",
|
|
178
|
+
defaultTools: ["Authenticate_Client"]
|
|
150
179
|
},
|
|
151
180
|
{
|
|
152
181
|
id: "edge",
|
|
@@ -158,7 +187,8 @@ var DEFAULT_PRESET_PROFILES = [
|
|
|
158
187
|
role: "Edge Telemetry & Hostile 3G WAN Industrial Node",
|
|
159
188
|
isolation: "WAN Jitter/Loss Resistant Client",
|
|
160
189
|
dataset: "Edge Telemetry Sensors (Pressure, RPM, Temp)",
|
|
161
|
-
defaultTool: "Analyze_IoT_Sensor_Data"
|
|
190
|
+
defaultTool: "Analyze_IoT_Sensor_Data",
|
|
191
|
+
defaultTools: ["Analyze_IoT_Sensor_Data"]
|
|
162
192
|
}
|
|
163
193
|
];
|
|
164
194
|
var NetworkDiscoveryEngine = class _NetworkDiscoveryEngine {
|
|
@@ -191,7 +221,7 @@ var NetworkDiscoveryEngine = class _NetworkDiscoveryEngine {
|
|
|
191
221
|
/**
|
|
192
222
|
* Probe a specific HTTP/Health endpoint dynamically.
|
|
193
223
|
*/
|
|
194
|
-
async probeHttpNode(host, port, timeoutMs =
|
|
224
|
+
async probeHttpNode(host, port, timeoutMs = 3500) {
|
|
195
225
|
const url = `http://${host}:${port}`;
|
|
196
226
|
const t0 = performance.now();
|
|
197
227
|
const controller = new AbortController();
|
|
@@ -278,7 +308,7 @@ var NetworkDiscoveryEngine = class _NetworkDiscoveryEngine {
|
|
|
278
308
|
peerId: probe.peerId || `peer-${profile.id}`,
|
|
279
309
|
multiaddrs: probe.multiaddrs || [],
|
|
280
310
|
version: probe.version || "2.5.0",
|
|
281
|
-
tools: probe.tools && probe.tools.length > 0 ? probe.tools : [],
|
|
311
|
+
tools: probe.tools && probe.tools.length > 0 ? probe.tools : profile.defaultTools || (profile.defaultTool ? [profile.defaultTool] : []),
|
|
282
312
|
role: profile.role,
|
|
283
313
|
isolation: profile.isolation,
|
|
284
314
|
dataset: profile.dataset,
|
|
@@ -300,7 +330,7 @@ var NetworkDiscoveryEngine = class _NetworkDiscoveryEngine {
|
|
|
300
330
|
peerId: `peer-${profile.id}`,
|
|
301
331
|
multiaddrs: [],
|
|
302
332
|
version: "2.5.0",
|
|
303
|
-
tools: [],
|
|
333
|
+
tools: profile.defaultTools || (profile.defaultTool ? [profile.defaultTool] : []),
|
|
304
334
|
role: profile.role,
|
|
305
335
|
isolation: profile.isolation,
|
|
306
336
|
dataset: profile.dataset,
|
|
@@ -338,7 +368,7 @@ var NetworkDiscoveryEngine = class _NetworkDiscoveryEngine {
|
|
|
338
368
|
const probe = await this.probeHttpNode(host, matchedProfile.httpPort);
|
|
339
369
|
const isOnline = status === "online" || Boolean(probe?.tools) && (probe?.tools?.length ?? 0) > 0;
|
|
340
370
|
const nodeName = probe?.name?.replace("PRODUCTION-", "").replace(/-/g, " ") || matchedProfile.defaultName;
|
|
341
|
-
const defaultTools = matchedProfile.defaultTool ? [matchedProfile.defaultTool] : ["Execute_WASI_Logic"];
|
|
371
|
+
const defaultTools = matchedProfile.defaultTools || (matchedProfile.defaultTool ? [matchedProfile.defaultTool] : ["Execute_WASI_Logic"]);
|
|
342
372
|
const tools = isOnline ? probe?.tools && probe.tools.length > 0 ? probe.tools : defaultTools : [];
|
|
343
373
|
const enriched = isOnline && probe?.enrichedTools && probe.enrichedTools.length > 0 ? probe.enrichedTools : tools.map((t) => ({
|
|
344
374
|
name: t,
|
|
@@ -456,16 +486,22 @@ var GrpcTransport = class {
|
|
|
456
486
|
connected = false;
|
|
457
487
|
target;
|
|
458
488
|
token;
|
|
489
|
+
tlsConfig;
|
|
459
490
|
constructor(options) {
|
|
460
491
|
this.target = options.target.replace(/^grpc:\/\//, "");
|
|
461
492
|
this.token = options.token;
|
|
493
|
+
this.tlsConfig = options.tls;
|
|
462
494
|
}
|
|
463
495
|
isConnected() {
|
|
464
496
|
return this.connected && this.client !== null;
|
|
465
497
|
}
|
|
466
498
|
async connect() {
|
|
467
499
|
const tokenProvider = this.token || createStudioTokenProvider();
|
|
468
|
-
|
|
500
|
+
const tls = this.tlsConfig || {
|
|
501
|
+
insecure: true,
|
|
502
|
+
suppressWarning: true
|
|
503
|
+
};
|
|
504
|
+
this.client = new LiopRpcClient(this.target, tls, tokenProvider);
|
|
469
505
|
this.connected = true;
|
|
470
506
|
}
|
|
471
507
|
async disconnect() {
|
|
@@ -1180,9 +1216,7 @@ var MeshTransport = class {
|
|
|
1180
1216
|
if (!this.isConnected()) {
|
|
1181
1217
|
await this.connect();
|
|
1182
1218
|
}
|
|
1183
|
-
const
|
|
1184
|
-
const peerId = clientAny.meshNode?.getPeerId?.()?.toString() || "UnknownPeer";
|
|
1185
|
-
const _connections = clientAny.meshNode?.node?.getConnections?.() || [];
|
|
1219
|
+
const peerId = this.client.peerId ?? "UnknownPeer";
|
|
1186
1220
|
const latencyMs = Math.max(1, Math.round(performance.now() - tStart));
|
|
1187
1221
|
const discovery = NetworkDiscoveryEngine.getInstance();
|
|
1188
1222
|
const meshDiscovered = await discovery.scanNetwork("127.0.0.1").catch(() => []);
|
|
@@ -1867,12 +1901,40 @@ function createTransport(config) {
|
|
|
1867
1901
|
}
|
|
1868
1902
|
}
|
|
1869
1903
|
|
|
1870
|
-
// src/
|
|
1904
|
+
// src/version.ts
|
|
1905
|
+
import fs from "fs";
|
|
1906
|
+
import path from "path";
|
|
1907
|
+
import { fileURLToPath } from "url";
|
|
1871
1908
|
var __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
1909
|
+
function getPackageVersion() {
|
|
1910
|
+
try {
|
|
1911
|
+
let currentDir = __dirname;
|
|
1912
|
+
for (let i = 0; i < 4; i++) {
|
|
1913
|
+
const candidate = path.join(currentDir, "package.json");
|
|
1914
|
+
if (fs.existsSync(candidate)) {
|
|
1915
|
+
const raw = fs.readFileSync(candidate, "utf-8");
|
|
1916
|
+
const parsed = JSON.parse(raw);
|
|
1917
|
+
if (parsed.name === "@nekzus/liop-studio" && typeof parsed.version === "string") {
|
|
1918
|
+
return parsed.version;
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
currentDir = path.dirname(currentDir);
|
|
1922
|
+
}
|
|
1923
|
+
} catch {
|
|
1924
|
+
}
|
|
1925
|
+
return "1.0.0-alpha.5";
|
|
1926
|
+
}
|
|
1927
|
+
var STUDIO_VERSION = getPackageVersion();
|
|
1928
|
+
|
|
1929
|
+
// src/server/index.ts
|
|
1930
|
+
var __dirname2 = path2.dirname(fileURLToPath2(import.meta.url));
|
|
1872
1931
|
function createStudioServer(options = {}) {
|
|
1932
|
+
if (!process3.env.LIOP_SUPPRESS_TLS_WARNING) {
|
|
1933
|
+
process3.env.LIOP_SUPPRESS_TLS_WARNING = "true";
|
|
1934
|
+
}
|
|
1873
1935
|
const app = new Hono();
|
|
1874
1936
|
const port = options.port || 16e3;
|
|
1875
|
-
const distPath = options.distPath ||
|
|
1937
|
+
const distPath = options.distPath || path2.resolve(__dirname2, "../../ui/dist");
|
|
1876
1938
|
let activeConfig = options.initialTarget || {
|
|
1877
1939
|
type: "http",
|
|
1878
1940
|
http: { url: process3.env.LIOP_MCP_URL || "http://127.0.0.1:15000/mcp" }
|
|
@@ -1892,7 +1954,7 @@ function createStudioServer(options = {}) {
|
|
|
1892
1954
|
app.use(
|
|
1893
1955
|
"/*",
|
|
1894
1956
|
serveStatic({
|
|
1895
|
-
root:
|
|
1957
|
+
root: distPath,
|
|
1896
1958
|
rewriteRequestPath: (pathStr) => {
|
|
1897
1959
|
if (!pathStr.includes(".") && !pathStr.startsWith("/api") && pathStr !== "/health") {
|
|
1898
1960
|
return "/index.html";
|
|
@@ -1905,7 +1967,7 @@ function createStudioServer(options = {}) {
|
|
|
1905
1967
|
const isConnected = activeTransport.isConnected() && lastReport?.status === "online";
|
|
1906
1968
|
return c.json({
|
|
1907
1969
|
status: isConnected ? "healthy" : "offline",
|
|
1908
|
-
version:
|
|
1970
|
+
version: STUDIO_VERSION,
|
|
1909
1971
|
targetType: activeConfig.type,
|
|
1910
1972
|
connected: isConnected
|
|
1911
1973
|
});
|
|
@@ -1921,7 +1983,7 @@ function createStudioServer(options = {}) {
|
|
|
1921
1983
|
connected: isConnected,
|
|
1922
1984
|
toolsCount: isConnected ? lastReport?.totalTools || 0 : 0,
|
|
1923
1985
|
latencyMs: isConnected ? lastReport?.latencyMs || 0 : 0,
|
|
1924
|
-
version:
|
|
1986
|
+
version: STUDIO_VERSION,
|
|
1925
1987
|
serverInfo: lastReport?.serverInfo
|
|
1926
1988
|
});
|
|
1927
1989
|
});
|
|
@@ -2186,7 +2248,11 @@ function resolveTargetConfig(target, options = {}) {
|
|
|
2186
2248
|
if (isGrpcExplicit || /^([a-zA-Z0-9.-]+):(\d+)$/.test(trimmed) || trimmed.startsWith("grpc://")) {
|
|
2187
2249
|
return {
|
|
2188
2250
|
type: "grpc",
|
|
2189
|
-
grpc: {
|
|
2251
|
+
grpc: {
|
|
2252
|
+
target: trimmed,
|
|
2253
|
+
token,
|
|
2254
|
+
tls: { insecure: true, suppressWarning: true }
|
|
2255
|
+
}
|
|
2190
2256
|
};
|
|
2191
2257
|
}
|
|
2192
2258
|
const parts = trimmed.split(/\s+/);
|
|
@@ -2199,6 +2265,9 @@ function resolveTargetConfig(target, options = {}) {
|
|
|
2199
2265
|
};
|
|
2200
2266
|
}
|
|
2201
2267
|
async function runScan(targetStr, options) {
|
|
2268
|
+
if (!process4.env.LIOP_SUPPRESS_TLS_WARNING) {
|
|
2269
|
+
process4.env.LIOP_SUPPRESS_TLS_WARNING = "true";
|
|
2270
|
+
}
|
|
2202
2271
|
const config = resolveTargetConfig(targetStr, options.token);
|
|
2203
2272
|
const transport = createTransport(config);
|
|
2204
2273
|
try {
|
|
@@ -2226,14 +2295,24 @@ async function main() {
|
|
|
2226
2295
|
const program = new Command();
|
|
2227
2296
|
program.name("liop-studio").description(
|
|
2228
2297
|
"LIOP Sovereign Studio & Mesh Scanner (Universal MCP / LIOP Inspector)"
|
|
2229
|
-
).version(
|
|
2298
|
+
).version(STUDIO_VERSION).option("-p, --port <port>", "Port to bind local Studio server", "16000").option("--no-open", "Do not automatically open browser on launch").option(
|
|
2230
2299
|
"--stdio <command>",
|
|
2231
2300
|
"Initial target: Stdio command (e.g. 'node server.js')"
|
|
2232
2301
|
).option("--http <url>", "Initial target: HTTP / SSE MCP URL").option("--grpc <target>", "Initial target: Native LIOP gRPC endpoint").option("--mesh <multiaddr>", "Initial target: Libp2p P2P bootstrap node").option(
|
|
2233
2302
|
"--token <token>",
|
|
2234
2303
|
"Bearer or access token for target authentication"
|
|
2304
|
+
).option("--tls-ca <path>", "Path to root CA certificate for gRPC target").option(
|
|
2305
|
+
"--tls-cert <path>",
|
|
2306
|
+
"Path to client certificate chain for gRPC target"
|
|
2307
|
+
).option("--tls-key <path>", "Path to client private key for gRPC target").option(
|
|
2308
|
+
"--insecure",
|
|
2309
|
+
"Explicitly permit unencrypted gRPC credentials",
|
|
2310
|
+
true
|
|
2235
2311
|
).action(async (options) => {
|
|
2236
2312
|
const port = Number.parseInt(options.port, 10) || 16e3;
|
|
2313
|
+
if (!options.tlsCa && !options.tlsCert && !options.tlsKey) {
|
|
2314
|
+
process5.env.LIOP_SUPPRESS_TLS_WARNING = "true";
|
|
2315
|
+
}
|
|
2237
2316
|
let initialTarget;
|
|
2238
2317
|
if (options.stdio) {
|
|
2239
2318
|
const parts = options.stdio.trim().split(/\s+/);
|
|
@@ -2249,7 +2328,18 @@ async function main() {
|
|
|
2249
2328
|
} else if (options.grpc) {
|
|
2250
2329
|
initialTarget = {
|
|
2251
2330
|
type: "grpc",
|
|
2252
|
-
grpc: {
|
|
2331
|
+
grpc: {
|
|
2332
|
+
target: options.grpc,
|
|
2333
|
+
token: options.token,
|
|
2334
|
+
tls: options.tlsCa ? {
|
|
2335
|
+
rootCert: options.tlsCa,
|
|
2336
|
+
certChain: options.tlsCert,
|
|
2337
|
+
privateKey: options.tlsKey
|
|
2338
|
+
} : {
|
|
2339
|
+
insecure: true,
|
|
2340
|
+
suppressWarning: true
|
|
2341
|
+
}
|
|
2342
|
+
}
|
|
2253
2343
|
};
|
|
2254
2344
|
} else if (options.mesh) {
|
|
2255
2345
|
initialTarget = {
|