@nekzus/liop 2.0.0-alpha.1 → 2.0.0-alpha.2

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 (123) hide show
  1. package/dist/bin/agent.d.ts +0 -1
  2. package/dist/bin/agent.js +5 -306
  3. package/dist/bin/agent.js.map +1 -0
  4. package/dist/{bridge/stream.d.ts → bridge.d.ts} +44 -3
  5. package/dist/bridge.js +2 -0
  6. package/dist/bridge.js.map +1 -0
  7. package/dist/chunk-4ABAFG44.js +33 -0
  8. package/dist/chunk-4ABAFG44.js.map +1 -0
  9. package/dist/chunk-ANFXJGMP.js +2 -0
  10. package/dist/chunk-ANFXJGMP.js.map +1 -0
  11. package/dist/chunk-DBXGYHKY.js +2 -0
  12. package/dist/chunk-DBXGYHKY.js.map +1 -0
  13. package/dist/chunk-HM77MWB6.js +2 -0
  14. package/dist/chunk-HM77MWB6.js.map +1 -0
  15. package/dist/chunk-HNDVAKEK.js +24 -0
  16. package/dist/chunk-HNDVAKEK.js.map +1 -0
  17. package/dist/chunk-HQZHZM6U.js +2 -0
  18. package/dist/chunk-HQZHZM6U.js.map +1 -0
  19. package/dist/chunk-P52IE4L6.js +2 -0
  20. package/dist/chunk-P52IE4L6.js.map +1 -0
  21. package/dist/chunk-PIBCW4BD.js +13 -0
  22. package/dist/chunk-PIBCW4BD.js.map +1 -0
  23. package/dist/chunk-PPCOS2NU.js +2 -0
  24. package/dist/chunk-PPCOS2NU.js.map +1 -0
  25. package/dist/chunk-RWRRBYG4.js +2 -0
  26. package/dist/chunk-RWRRBYG4.js.map +1 -0
  27. package/dist/chunk-S6RJHZV2.js +2 -0
  28. package/dist/chunk-S6RJHZV2.js.map +1 -0
  29. package/dist/chunk-UVTEJYHN.js +2 -0
  30. package/dist/chunk-UVTEJYHN.js.map +1 -0
  31. package/dist/chunk-X6FJATUE.js +29 -0
  32. package/dist/chunk-X6FJATUE.js.map +1 -0
  33. package/dist/chunk-XLVRRGOX.js +3 -0
  34. package/dist/chunk-XLVRRGOX.js.map +1 -0
  35. package/dist/client.d.ts +5 -0
  36. package/dist/client.js +2 -0
  37. package/dist/client.js.map +1 -0
  38. package/dist/{gateway/router.d.ts → gateway.d.ts} +30 -5
  39. package/dist/gateway.js +2 -0
  40. package/dist/gateway.js.map +1 -0
  41. package/dist/{client/index.d.ts → index-CyxNLlz7.d.ts} +24 -5
  42. package/dist/index.d.ts +313 -12
  43. package/dist/index.js +31 -12
  44. package/dist/index.js.map +1 -0
  45. package/dist/kyber-2WDOTUQX.js +2 -0
  46. package/dist/kyber-2WDOTUQX.js.map +1 -0
  47. package/dist/{mesh/node.d.ts → mesh.d.ts} +5 -3
  48. package/dist/mesh.js +2 -0
  49. package/dist/mesh.js.map +1 -0
  50. package/dist/{server/index.d.ts → server.d.ts} +125 -12
  51. package/dist/server.js +2 -0
  52. package/dist/server.js.map +1 -0
  53. package/dist/types.d.ts +17 -14
  54. package/dist/types.js +2 -26
  55. package/dist/types.js.map +1 -0
  56. package/dist/{crypto/verifier.d.ts → verifier-DTCD9imJ.d.ts} +3 -1
  57. package/dist/verifier-RQRYXA4C.js +2 -0
  58. package/dist/verifier-RQRYXA4C.js.map +1 -0
  59. package/dist/workers/logic-execution.d.ts +4 -2
  60. package/dist/workers/logic-execution.js +2 -123
  61. package/dist/workers/logic-execution.js.map +1 -0
  62. package/dist/workers/zk-verifier.d.ts +4 -2
  63. package/dist/workers/zk-verifier.js +2 -98
  64. package/dist/workers/zk-verifier.js.map +1 -0
  65. package/package.json +31 -18
  66. package/dist/bridge/index.d.ts +0 -37
  67. package/dist/bridge/index.js +0 -249
  68. package/dist/bridge/stream.js +0 -210
  69. package/dist/client/index.js +0 -275
  70. package/dist/crypto/logic-image-id.d.ts +0 -3
  71. package/dist/crypto/logic-image-id.js +0 -27
  72. package/dist/crypto/verifier.js +0 -97
  73. package/dist/economy/estimator.d.ts +0 -53
  74. package/dist/economy/estimator.js +0 -69
  75. package/dist/economy/index.d.ts +0 -5
  76. package/dist/economy/index.js +0 -3
  77. package/dist/economy/otel.d.ts +0 -38
  78. package/dist/economy/otel.js +0 -100
  79. package/dist/economy/telemetry.d.ts +0 -77
  80. package/dist/economy/telemetry.js +0 -224
  81. package/dist/errors.d.ts +0 -14
  82. package/dist/errors.js +0 -19
  83. package/dist/gateway/hybrid.d.ts +0 -23
  84. package/dist/gateway/hybrid.js +0 -199
  85. package/dist/gateway/router.js +0 -1054
  86. package/dist/mesh/index.d.ts +0 -1
  87. package/dist/mesh/index.js +0 -1
  88. package/dist/mesh/node.js +0 -853
  89. package/dist/prompts/adapters.d.ts +0 -16
  90. package/dist/prompts/adapters.js +0 -55
  91. package/dist/rpc/client.d.ts +0 -22
  92. package/dist/rpc/client.js +0 -40
  93. package/dist/rpc/codec/lpm.d.ts +0 -20
  94. package/dist/rpc/codec/lpm.js +0 -36
  95. package/dist/rpc/crypto/aes.d.ts +0 -22
  96. package/dist/rpc/crypto/aes.js +0 -47
  97. package/dist/rpc/crypto/kyber.d.ts +0 -27
  98. package/dist/rpc/crypto/kyber.js +0 -70
  99. package/dist/rpc/proto.d.ts +0 -2
  100. package/dist/rpc/proto.js +0 -33
  101. package/dist/rpc/server.d.ts +0 -13
  102. package/dist/rpc/server.js +0 -50
  103. package/dist/rpc/tls.d.ts +0 -26
  104. package/dist/rpc/tls.js +0 -54
  105. package/dist/rpc/types.d.ts +0 -28
  106. package/dist/rpc/types.js +0 -5
  107. package/dist/sandbox/guardian.d.ts +0 -18
  108. package/dist/sandbox/guardian.js +0 -58
  109. package/dist/sandbox/wasi.d.ts +0 -36
  110. package/dist/sandbox/wasi.js +0 -233
  111. package/dist/security/guardian.d.ts +0 -22
  112. package/dist/security/guardian.js +0 -52
  113. package/dist/security/zk.d.ts +0 -37
  114. package/dist/security/zk.js +0 -76
  115. package/dist/server/index.js +0 -1047
  116. package/dist/server/ner-scanner.d.ts +0 -29
  117. package/dist/server/ner-scanner.js +0 -141
  118. package/dist/server/pii.d.ts +0 -66
  119. package/dist/server/pii.js +0 -428
  120. package/dist/utils/logger.d.ts +0 -21
  121. package/dist/utils/logger.js +0 -70
  122. package/dist/utils/mcpCompact.d.ts +0 -11
  123. package/dist/utils/mcpCompact.js +0 -29
@@ -1,77 +0,0 @@
1
- /** Single MCP operation token footprint */
2
- export interface TokenOperationMetric {
3
- readonly type: "tools_list" | "tool_call" | "resource_read" | "resource_list" | "prompt_get" | "prompt_list" | "diagnostic";
4
- readonly method: string;
5
- readonly estimatedInputTokens: number;
6
- readonly estimatedOutputTokens: number;
7
- readonly timestamp: number;
8
- readonly toolName?: string;
9
- readonly peerId?: string;
10
- readonly durationMs?: number;
11
- }
12
- /** Session-level aggregate report */
13
- export interface TokenSessionReport {
14
- readonly sessionId: string;
15
- readonly operations: ReadonlyArray<TokenOperationMetric>;
16
- readonly totalInputTokens: number;
17
- readonly totalOutputTokens: number;
18
- readonly estimatorName: string;
19
- readonly sessionUptimeMs: number;
20
- }
21
- /** Per-tool aggregate breakdown */
22
- export interface ToolTokenBreakdown {
23
- readonly input: number;
24
- readonly output: number;
25
- readonly calls: number;
26
- readonly avgDurationMs: number;
27
- }
28
- /**
29
- * TokenTelemetryEngine — Full-spectrum observational singleton for token cost measurement.
30
- *
31
- * Design principles:
32
- * - Pure observer pattern: NEVER mutates MCP payloads or protocol flow.
33
- * - Real tokenization: o200k_base BPE via gpt-tokenizer (async init, sync counting).
34
- * - OTel gen_ai.* emission: standard metrics via @opentelemetry/api (NoOp if no provider).
35
- * - Error isolation: telemetry failures never propagate to protocol operations.
36
- */
37
- export declare class TokenTelemetryEngine {
38
- private static instance;
39
- private operations;
40
- private readonly sessionId;
41
- private readonly startedAt;
42
- private estimator;
43
- private otelBridge;
44
- private constructor();
45
- /** Async upgrade from heuristic to real BPE tokenizer */
46
- private initRealEstimator;
47
- static getInstance(): TokenTelemetryEngine;
48
- /**
49
- * Count tokens in a string using the active estimator.
50
- * Delegates to o200k_base BPE tokenizer (or heuristic fallback).
51
- */
52
- countTokens(content: string): number;
53
- /**
54
- * Record a single MCP operation's token footprint.
55
- * Emits both internal metrics and OTel gen_ai.* histograms.
56
- */
57
- record(metric: Omit<TokenOperationMetric, "timestamp">): void;
58
- /**
59
- * @deprecated Use countTokens() instead. Kept for backward compatibility.
60
- */
61
- estimateTokens(content: string): number;
62
- /** Generate the full session report */
63
- getReport(): TokenSessionReport;
64
- /** Get per-tool token breakdown for diagnostic display */
65
- getPerToolReport(): Map<string, ToolTokenBreakdown>;
66
- /**
67
- * Format a rich, human-readable summary block for LiopMeshStatus diagnostic.
68
- * Returns empty string when no operations have been recorded.
69
- */
70
- formatStatusBlock(): string;
71
- /** Format milliseconds into human-readable uptime string */
72
- private formatUptime;
73
- /** Reset all recorded metrics (used in tests) */
74
- reset(): void;
75
- /** Destroy the singleton (used in tests to guarantee isolation) */
76
- static destroy(): void;
77
- }
@@ -1,224 +0,0 @@
1
- import { createSyncTokenEstimator, createTokenEstimator, } from "./estimator.js";
2
- import { LiopOTelBridge } from "./otel.js";
3
- /**
4
- * Maps operation types to OTel gen_ai.operation.name values.
5
- * @see https://opentelemetry.io/docs/specs/semconv/gen-ai/
6
- */
7
- const OTEL_OPERATION_MAP = {
8
- tools_list: "chat",
9
- tool_call: "execute_tool",
10
- resource_read: "chat",
11
- resource_list: "chat",
12
- prompt_get: "chat",
13
- prompt_list: "chat",
14
- diagnostic: "chat",
15
- };
16
- /**
17
- * TokenTelemetryEngine — Full-spectrum observational singleton for token cost measurement.
18
- *
19
- * Design principles:
20
- * - Pure observer pattern: NEVER mutates MCP payloads or protocol flow.
21
- * - Real tokenization: o200k_base BPE via gpt-tokenizer (async init, sync counting).
22
- * - OTel gen_ai.* emission: standard metrics via @opentelemetry/api (NoOp if no provider).
23
- * - Error isolation: telemetry failures never propagate to protocol operations.
24
- */
25
- export class TokenTelemetryEngine {
26
- static instance = null;
27
- operations = [];
28
- sessionId;
29
- startedAt;
30
- estimator;
31
- otelBridge;
32
- constructor() {
33
- this.sessionId = crypto.randomUUID();
34
- this.startedAt = Date.now();
35
- // Start with sync heuristic estimator (available immediately)
36
- this.estimator = createSyncTokenEstimator();
37
- this.otelBridge = new LiopOTelBridge();
38
- // Upgrade to real tokenizer asynchronously
39
- this.initRealEstimator();
40
- }
41
- /** Async upgrade from heuristic to real BPE tokenizer */
42
- initRealEstimator() {
43
- createTokenEstimator()
44
- .then((real) => {
45
- this.estimator = real;
46
- })
47
- .catch(() => {
48
- // Keep heuristic fallback — already assigned in constructor
49
- });
50
- }
51
- static getInstance() {
52
- if (!TokenTelemetryEngine.instance) {
53
- TokenTelemetryEngine.instance = new TokenTelemetryEngine();
54
- }
55
- return TokenTelemetryEngine.instance;
56
- }
57
- /**
58
- * Count tokens in a string using the active estimator.
59
- * Delegates to o200k_base BPE tokenizer (or heuristic fallback).
60
- */
61
- countTokens(content) {
62
- try {
63
- return this.estimator.countTokens(content);
64
- }
65
- catch {
66
- // Fallback: never let counting failures break protocol flow
67
- return Math.ceil(content.length / 4);
68
- }
69
- }
70
- /**
71
- * Record a single MCP operation's token footprint.
72
- * Emits both internal metrics and OTel gen_ai.* histograms.
73
- */
74
- record(metric) {
75
- const fullMetric = {
76
- ...metric,
77
- timestamp: Date.now(),
78
- };
79
- this.operations.push(fullMetric);
80
- // Emit to OTel bridge (NoOp if no MeterProvider configured)
81
- try {
82
- const otelOp = OTEL_OPERATION_MAP[metric.type] || "chat";
83
- if (metric.estimatedInputTokens > 0) {
84
- this.otelBridge.recordTokens(metric.estimatedInputTokens, "input", otelOp, metric.toolName);
85
- }
86
- if (metric.estimatedOutputTokens > 0) {
87
- this.otelBridge.recordTokens(metric.estimatedOutputTokens, "output", otelOp, metric.toolName);
88
- }
89
- if (metric.durationMs !== undefined) {
90
- this.otelBridge.recordDuration(metric.durationMs, otelOp);
91
- }
92
- }
93
- catch {
94
- // OTel emission failure must never affect protocol operations
95
- }
96
- }
97
- /**
98
- * @deprecated Use countTokens() instead. Kept for backward compatibility.
99
- */
100
- estimateTokens(content) {
101
- return this.countTokens(content);
102
- }
103
- /** Generate the full session report */
104
- getReport() {
105
- return {
106
- sessionId: this.sessionId,
107
- operations: [...this.operations],
108
- totalInputTokens: this.operations.reduce((sum, op) => sum + op.estimatedInputTokens, 0),
109
- totalOutputTokens: this.operations.reduce((sum, op) => sum + op.estimatedOutputTokens, 0),
110
- estimatorName: this.estimator.name,
111
- sessionUptimeMs: Date.now() - this.startedAt,
112
- };
113
- }
114
- /** Get per-tool token breakdown for diagnostic display */
115
- getPerToolReport() {
116
- const breakdown = new Map();
117
- for (const op of this.operations) {
118
- const key = op.toolName || op.method;
119
- const existing = breakdown.get(key) || {
120
- input: 0,
121
- output: 0,
122
- calls: 0,
123
- avgDurationMs: 0,
124
- };
125
- const totalDuration = existing.avgDurationMs * existing.calls + (op.durationMs || 0);
126
- const newCalls = existing.calls + 1;
127
- breakdown.set(key, {
128
- input: existing.input + op.estimatedInputTokens,
129
- output: existing.output + op.estimatedOutputTokens,
130
- calls: newCalls,
131
- avgDurationMs: newCalls > 0 ? totalDuration / newCalls : 0,
132
- });
133
- }
134
- return breakdown;
135
- }
136
- /**
137
- * Format a rich, human-readable summary block for LiopMeshStatus diagnostic.
138
- * Returns empty string when no operations have been recorded.
139
- */
140
- formatStatusBlock() {
141
- const report = this.getReport();
142
- if (report.operations.length === 0)
143
- return "";
144
- const uptimeStr = this.formatUptime(report.sessionUptimeMs);
145
- const totalCombined = report.totalInputTokens + report.totalOutputTokens;
146
- // Aggregate operations by type
147
- const byType = new Map();
148
- for (const op of report.operations) {
149
- const key = op.type;
150
- const existing = byType.get(key) || {
151
- count: 0,
152
- input: 0,
153
- output: 0,
154
- };
155
- byType.set(key, {
156
- count: existing.count + 1,
157
- input: existing.input + op.estimatedInputTokens,
158
- output: existing.output + op.estimatedOutputTokens,
159
- });
160
- }
161
- // Build type breakdown lines
162
- const typeEntries = Array.from(byType.entries());
163
- const typeLines = typeEntries.map(([type, data], idx) => {
164
- const prefix = idx === typeEntries.length - 1 ? "│ └─" : "│ ├─";
165
- const outputPart = data.output > 0 ? ` / ${data.output.toLocaleString()} out` : "";
166
- return `${prefix} ${type} ×${data.count} → ${data.input.toLocaleString()} in${outputPart}`;
167
- });
168
- // Build per-tool breakdown
169
- const toolReport = this.getPerToolReport();
170
- const toolEntries = Array.from(toolReport.entries()).filter(([key]) => key !== "tools/list" && key !== "LiopMeshStatus");
171
- const toolLines = [];
172
- if (toolEntries.length > 0) {
173
- toolLines.push("├─ By Tool:");
174
- toolEntries.forEach(([name, data], idx) => {
175
- const prefix = idx === toolEntries.length - 1 ? "│ └─" : "│ ├─";
176
- const outputPart = data.output > 0 ? ` / ${data.output.toLocaleString()} out` : "";
177
- const durationPart = data.avgDurationMs > 0 ? ` ~${Math.round(data.avgDurationMs)}ms` : "";
178
- toolLines.push(`${prefix} ${name}: ${data.input.toLocaleString()} in${outputPart} (×${data.calls})${durationPart}`);
179
- });
180
- }
181
- // Calculate average latency across all timed operations
182
- const timedOps = report.operations.filter((op) => op.durationMs !== undefined);
183
- const avgLatency = timedOps.length > 0
184
- ? Math.round(timedOps.reduce((sum, op) => sum + (op.durationMs || 0), 0) /
185
- timedOps.length)
186
- : 0;
187
- const otelStatus = this.otelBridge.isActive()
188
- ? "gen_ai.client.token.usage → active"
189
- : "disabled";
190
- const lines = [
191
- "\nToken Economy:",
192
- `├─ Session: ${report.sessionId.slice(0, 8)} (${uptimeStr})`,
193
- `├─ Estimator: ${report.estimatorName}`,
194
- `├─ Operations: ${report.operations.length}`,
195
- ...typeLines,
196
- `├─ Total: ${report.totalInputTokens.toLocaleString()} in / ${report.totalOutputTokens.toLocaleString()} out (${totalCombined.toLocaleString()} combined)`,
197
- ...toolLines,
198
- ...(avgLatency > 0 ? [`├─ Avg Latency: ${avgLatency}ms`] : []),
199
- `└─ OTel: ${otelStatus}`,
200
- ];
201
- return lines.join("\n");
202
- }
203
- /** Format milliseconds into human-readable uptime string */
204
- formatUptime(ms) {
205
- const seconds = Math.floor(ms / 1000);
206
- if (seconds < 60)
207
- return `${seconds}s`;
208
- const minutes = Math.floor(seconds / 60);
209
- const remainingSeconds = seconds % 60;
210
- if (minutes < 60)
211
- return `${minutes}m ${remainingSeconds}s`;
212
- const hours = Math.floor(minutes / 60);
213
- const remainingMinutes = minutes % 60;
214
- return `${hours}h ${remainingMinutes}m`;
215
- }
216
- /** Reset all recorded metrics (used in tests) */
217
- reset() {
218
- this.operations = [];
219
- }
220
- /** Destroy the singleton (used in tests to guarantee isolation) */
221
- static destroy() {
222
- TokenTelemetryEngine.instance = null;
223
- }
224
- }
package/dist/errors.d.ts DELETED
@@ -1,14 +0,0 @@
1
- export declare enum ErrorCode {
2
- CapabilityViolation = "CapabilityViolation",
3
- SandboxEscape = "SandboxEscape",
4
- PiiLeak = "PiiLeak",
5
- InvalidIntent = "InvalidIntent",
6
- Throttled = "Throttled",
7
- ZkVerificationFailed = "ZkVerificationFailed",
8
- MeshUnavailable = "MeshUnavailable",
9
- ConnectionFailed = "ConnectionFailed"
10
- }
11
- export declare class LiopError extends Error {
12
- readonly code: ErrorCode;
13
- constructor(code: ErrorCode, message: string);
14
- }
package/dist/errors.js DELETED
@@ -1,19 +0,0 @@
1
- export var ErrorCode;
2
- (function (ErrorCode) {
3
- ErrorCode["CapabilityViolation"] = "CapabilityViolation";
4
- ErrorCode["SandboxEscape"] = "SandboxEscape";
5
- ErrorCode["PiiLeak"] = "PiiLeak";
6
- ErrorCode["InvalidIntent"] = "InvalidIntent";
7
- ErrorCode["Throttled"] = "Throttled";
8
- ErrorCode["ZkVerificationFailed"] = "ZkVerificationFailed";
9
- ErrorCode["MeshUnavailable"] = "MeshUnavailable";
10
- ErrorCode["ConnectionFailed"] = "ConnectionFailed";
11
- })(ErrorCode || (ErrorCode = {}));
12
- export class LiopError extends Error {
13
- code;
14
- constructor(code, message) {
15
- super(message);
16
- this.name = "LiopError";
17
- this.code = code;
18
- }
19
- }
@@ -1,23 +0,0 @@
1
- import type { MeshNode } from "../mesh/index.js";
2
- import type { LiopServer } from "../server/index.js";
3
- import { LiopMcpRouter } from "./router.js";
4
- /**
5
- * LIOP Hybrid Gateway
6
- * High-level orchestration for connecting MCP (JSON-RPC) clients to the LIOP Mesh.
7
- */
8
- export declare class LiopHybridGateway {
9
- private liopServer;
10
- private meshNode;
11
- private netServer;
12
- private h2Server;
13
- private h1Server;
14
- private router;
15
- constructor(liopServer: LiopServer, meshNode?: MeshNode | null, rpcPort?: number);
16
- private setupH2Routes;
17
- private setupH1Routes;
18
- private handleGrpcStream;
19
- private handleMcpH2Stream;
20
- listen(port: number, host?: string): Promise<number>;
21
- stop(): Promise<void>;
22
- getRouter(): LiopMcpRouter;
23
- }
@@ -1,199 +0,0 @@
1
- import * as http from "node:http";
2
- import * as http2 from "node:http2";
3
- import * as net from "node:net";
4
- import { log } from "../utils/logger.js";
5
- import { LiopMcpRouter } from "./router.js";
6
- /**
7
- * LIOP Hybrid Gateway
8
- * High-level orchestration for connecting MCP (JSON-RPC) clients to the LIOP Mesh.
9
- */
10
- export class LiopHybridGateway {
11
- liopServer;
12
- meshNode;
13
- netServer;
14
- h2Server;
15
- h1Server;
16
- router;
17
- constructor(liopServer, meshNode = null, rpcPort = 50051) {
18
- this.liopServer = liopServer;
19
- this.meshNode = meshNode;
20
- // Initialize the Universal Router
21
- this.router = new LiopMcpRouter(this.liopServer, this.meshNode, rpcPort);
22
- // Internal HTTP/2 Server (for Native gRPC Proxying)
23
- this.h2Server = http2.createServer();
24
- this.setupH2Routes();
25
- // Internal HTTP/1 Server (for Browser/MCP)
26
- this.h1Server = http.createServer();
27
- this.setupH1Routes();
28
- // Primary Multiplexer (L4)
29
- this.netServer = net.createServer((socket) => {
30
- socket.once("data", (buffer) => {
31
- const isHttp2 = buffer.toString().startsWith("PRI * HTTP/2.0");
32
- log.info(`[LIOP-Gateway] Incoming L4 Connection. Protocol: ${isHttp2 ? "HTTP/2 (gRPC)" : "HTTP/1.1 (MCP)"}`);
33
- if (isHttp2) {
34
- this.h2Server.emit("connection", socket);
35
- }
36
- else {
37
- this.h1Server.emit("connection", socket);
38
- }
39
- socket.unshift(buffer);
40
- });
41
- socket.on("error", (err) => log.error(`[LIOP-Gateway] NetServer Socket Error: ${err.message}`));
42
- });
43
- // Attach error listeners to sub-servers to catch silent failures
44
- this.h1Server.on("error", (err) => log.error(`[LIOP-Gateway] H1 Server Error: ${err.message}`));
45
- this.h2Server.on("error", (err) => log.error(`[LIOP-Gateway] H2 Server Error: ${err.message}`));
46
- log.info("[LIOP-Gateway] Hybrid adapter initialized.");
47
- }
48
- setupH2Routes() {
49
- this.h2Server.on("stream", (stream, headers) => {
50
- const contentType = headers["content-type"];
51
- const path = headers[":path"];
52
- if (contentType === "application/grpc") {
53
- this.handleGrpcStream(stream);
54
- }
55
- else if (path === "/mcp") {
56
- this.handleMcpH2Stream(stream, headers);
57
- }
58
- });
59
- }
60
- setupH1Routes() {
61
- this.h1Server.on("request", async (req, res) => {
62
- const url = req.url || "";
63
- const method = req.method;
64
- if (method === "GET" &&
65
- (url === "/" || url === "/mcp" || url === "/health")) {
66
- if (url === "/health" &&
67
- req.headers.accept?.includes("application/json")) {
68
- const meshInfo = this.meshNode
69
- ? {
70
- peerId: this.meshNode.getPeerId()?.toString() || "",
71
- multiaddrs: this.meshNode
72
- .getMultiaddrs()
73
- .map((m) => m.toString()),
74
- }
75
- : null;
76
- res.writeHead(200, { "Content-Type": "application/json" });
77
- res.end(JSON.stringify({
78
- status: "healthy",
79
- node: this.liopServer.getServerInfo(),
80
- mesh: meshInfo,
81
- tools: this.liopServer.listTools().map((t) => t.name),
82
- timestamp: new Date().toISOString(),
83
- }));
84
- return;
85
- }
86
- res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
87
- res.end(`
88
- <body style="background:#0f172a;color:#f8fafc;font-family:sans-serif;display:flex;flex-direction:column;align-items:center;justify-content:center;height:100vh;margin:0">
89
- <div style="background:#1e293b;padding:40px;border-radius:16px;border:1px solid #38bdf8;text-align:center;box-shadow:0 20px 25px -5px rgba(0,0,0,0.1)">
90
- <h1 style="color:#38bdf8;margin-top:0">LIOP Protocol Transformer</h1>
91
- <p style="opacity:0.8;font-weight:600">L4/L7 Transcoding: JSON-RPC &harr; gRPC</p>
92
- <p style="opacity:0.6;font-size:14px">Active Protections: Kyber768 + AES-256-GCM + ZK-Proof Ready</p>
93
- <div style="background:#0f172a;padding:15px;border-radius:8px;margin-top:20px;border:1px dashed #334155">
94
- <code style="color:#10b981">Endpoint: http://localhost:3000/mcp</code>
95
- </div>
96
- </div>
97
- </body>
98
- `);
99
- return;
100
- }
101
- if (url === "/mcp" && method === "POST") {
102
- let body = "";
103
- req.on("data", (chunk) => (body += chunk.toString()));
104
- req.on("end", async () => {
105
- try {
106
- const jsonRequest = JSON.parse(body);
107
- const response = await this.router.dispatch(jsonRequest);
108
- res.writeHead(200, { "Content-Type": "application/json" });
109
- res.end(JSON.stringify(response));
110
- }
111
- catch (e) {
112
- log.info(`[LIOP-Gateway] Error processing JSON-RPC payload: ${e.message}`);
113
- res.writeHead(400);
114
- res.end(JSON.stringify({
115
- jsonrpc: "2.0",
116
- error: { code: -32700, message: "Parse error" },
117
- }));
118
- }
119
- });
120
- }
121
- else {
122
- res.writeHead(404);
123
- res.end("Not Found");
124
- }
125
- });
126
- }
127
- handleGrpcStream(stream) {
128
- stream.on("data", (chunk) => {
129
- // biome-ignore lint/suspicious/noExplicitAny: Standard gRPC stream data is Buffer
130
- const data = chunk;
131
- if (data)
132
- log.info(`[LIOP-Gateway] Native gRPC Proxy passing ${data.length} bytes`);
133
- });
134
- stream.respond({ ":status": 200, "content-type": "application/grpc" });
135
- stream.end();
136
- }
137
- handleMcpH2Stream(stream, _headers) {
138
- let body = "";
139
- stream.on("data", (chunk) => (body += chunk.toString()));
140
- stream.on("end", async () => {
141
- try {
142
- const response = await this.router.dispatch(JSON.parse(body));
143
- if (response) {
144
- stream.respond({
145
- ":status": 200,
146
- "content-type": "application/json",
147
- });
148
- stream.end(JSON.stringify(response));
149
- }
150
- else
151
- stream.close();
152
- }
153
- catch (_e) {
154
- stream.respond({ ":status": 400 });
155
- stream.end();
156
- }
157
- });
158
- }
159
- async listen(port, host = "0.0.0.0") {
160
- if (this.meshNode) {
161
- await this.meshNode.start();
162
- // Announce all local tools to the DHT
163
- const tools = this.liopServer.listTools();
164
- for (const tool of tools) {
165
- await this.meshNode.announceCapability(tool.name);
166
- log.info(`[LIOP-Gateway] 📡 Announced local tool to Mesh: ${tool.name}`);
167
- }
168
- }
169
- return new Promise((resolve, reject) => {
170
- this.netServer.on("error", (err) => {
171
- if (err.code === "EADDRINUSE") {
172
- log.info(`[LIOP-Gateway] FATAL: Port ${port} is already in use by another process.`);
173
- }
174
- else {
175
- log.error(`[LIOP-Gateway] Binding Error: ${err.message}`);
176
- }
177
- reject(err);
178
- });
179
- this.netServer.listen(port, host, () => {
180
- const addr = this.netServer.address();
181
- const actualHost = typeof addr === "string" ? addr : addr?.address || host;
182
- const assignedPort = typeof addr === "string" ? port : addr?.port || port;
183
- log.info(`[LIOP-Gateway] ✅ Transformer Mesh Gateway READY and listening on ${actualHost}:${assignedPort}`);
184
- resolve(assignedPort);
185
- });
186
- });
187
- }
188
- async stop() {
189
- if (this.meshNode) {
190
- await this.meshNode.stop();
191
- }
192
- this.netServer.close();
193
- this.h2Server.close();
194
- this.h1Server.close();
195
- }
196
- getRouter() {
197
- return this.router;
198
- }
199
- }