@nekzus/liop 1.2.0-alpha.9 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +12 -3
  2. package/dist/bin/agent.js +222 -51
  3. package/dist/bridge/index.js +7 -6
  4. package/dist/bridge/stream.js +11 -11
  5. package/dist/client/index.js +46 -35
  6. package/dist/crypto/logic-image-id.d.ts +3 -0
  7. package/dist/crypto/logic-image-id.js +27 -0
  8. package/dist/crypto/verifier.js +7 -19
  9. package/dist/economy/estimator.d.ts +53 -0
  10. package/dist/economy/estimator.js +69 -0
  11. package/dist/economy/index.d.ts +5 -0
  12. package/dist/economy/index.js +3 -0
  13. package/dist/economy/otel.d.ts +38 -0
  14. package/dist/economy/otel.js +100 -0
  15. package/dist/economy/telemetry.d.ts +77 -0
  16. package/dist/economy/telemetry.js +224 -0
  17. package/dist/errors.d.ts +14 -0
  18. package/dist/errors.js +19 -0
  19. package/dist/gateway/hybrid.d.ts +3 -1
  20. package/dist/gateway/hybrid.js +38 -13
  21. package/dist/gateway/router.d.ts +25 -9
  22. package/dist/gateway/router.js +484 -133
  23. package/dist/index.d.ts +3 -0
  24. package/dist/index.js +3 -0
  25. package/dist/mesh/node.d.ts +16 -0
  26. package/dist/mesh/node.js +394 -113
  27. package/dist/prompts/adapters.d.ts +16 -0
  28. package/dist/prompts/adapters.js +55 -0
  29. package/dist/rpc/proto.js +2 -1
  30. package/dist/rpc/server.d.ts +1 -1
  31. package/dist/rpc/server.js +4 -3
  32. package/dist/rpc/tls.js +3 -2
  33. package/dist/sandbox/wasi.d.ts +1 -1
  34. package/dist/sandbox/wasi.js +43 -3
  35. package/dist/security/guardian.js +3 -2
  36. package/dist/security/zk.d.ts +2 -3
  37. package/dist/security/zk.js +22 -9
  38. package/dist/server/index.d.ts +53 -4
  39. package/dist/server/index.js +362 -49
  40. package/dist/server/pii.d.ts +12 -0
  41. package/dist/server/pii.js +90 -0
  42. package/dist/types.d.ts +16 -0
  43. package/dist/utils/logger.d.ts +21 -0
  44. package/dist/utils/logger.js +70 -0
  45. package/dist/utils/mcpCompact.d.ts +11 -0
  46. package/dist/utils/mcpCompact.js +29 -0
  47. package/dist/workers/logic-execution.d.ts +1 -1
  48. package/dist/workers/logic-execution.js +38 -20
  49. package/dist/workers/zk-verifier.js +37 -33
  50. package/package.json +14 -2
@@ -0,0 +1,224 @@
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
+ }
@@ -0,0 +1,14 @@
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 ADDED
@@ -0,0 +1,19 @@
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,5 +1,6 @@
1
1
  import type { MeshNode } from "../mesh/index.js";
2
2
  import type { LiopServer } from "../server/index.js";
3
+ import { LiopMcpRouter } from "./router.js";
3
4
  /**
4
5
  * LIOP Hybrid Gateway
5
6
  * High-level orchestration for connecting MCP (JSON-RPC) clients to the LIOP Mesh.
@@ -16,6 +17,7 @@ export declare class LiopHybridGateway {
16
17
  private setupH1Routes;
17
18
  private handleGrpcStream;
18
19
  private handleMcpH2Stream;
19
- listen(port: number, host?: string): Promise<void>;
20
+ listen(port: number, host?: string): Promise<number>;
20
21
  stop(): Promise<void>;
22
+ getRouter(): LiopMcpRouter;
21
23
  }
@@ -1,6 +1,7 @@
1
1
  import * as http from "node:http";
2
2
  import * as http2 from "node:http2";
3
3
  import * as net from "node:net";
4
+ import { log } from "../utils/logger.js";
4
5
  import { LiopMcpRouter } from "./router.js";
5
6
  /**
6
7
  * LIOP Hybrid Gateway
@@ -28,7 +29,7 @@ export class LiopHybridGateway {
28
29
  this.netServer = net.createServer((socket) => {
29
30
  socket.once("data", (buffer) => {
30
31
  const isHttp2 = buffer.toString().startsWith("PRI * HTTP/2.0");
31
- console.error(`[LIOP-Gateway] Incoming L4 Connection. Protocol: ${isHttp2 ? "HTTP/2 (gRPC)" : "HTTP/1.1 (MCP)"}`);
32
+ log.info(`[LIOP-Gateway] Incoming L4 Connection. Protocol: ${isHttp2 ? "HTTP/2 (gRPC)" : "HTTP/1.1 (MCP)"}`);
32
33
  if (isHttp2) {
33
34
  this.h2Server.emit("connection", socket);
34
35
  }
@@ -37,12 +38,12 @@ export class LiopHybridGateway {
37
38
  }
38
39
  socket.unshift(buffer);
39
40
  });
40
- socket.on("error", (err) => console.error(`[LIOP-Gateway] NetServer Socket Error: ${err.message}`));
41
+ socket.on("error", (err) => log.error(`[LIOP-Gateway] NetServer Socket Error: ${err.message}`));
41
42
  });
42
43
  // Attach error listeners to sub-servers to catch silent failures
43
- this.h1Server.on("error", (err) => console.error(`[LIOP-Gateway] H1 Server Error: ${err.message}`));
44
- this.h2Server.on("error", (err) => console.error(`[LIOP-Gateway] H2 Server Error: ${err.message}`));
45
- console.error("[LIOP-Gateway] Hybrid adapter initialized.");
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.");
46
47
  }
47
48
  setupH2Routes() {
48
49
  this.h2Server.on("stream", (stream, headers) => {
@@ -62,6 +63,26 @@ export class LiopHybridGateway {
62
63
  const method = req.method;
63
64
  if (method === "GET" &&
64
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
+ }
65
86
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
66
87
  res.end(`
67
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">
@@ -88,7 +109,7 @@ export class LiopHybridGateway {
88
109
  res.end(JSON.stringify(response));
89
110
  }
90
111
  catch (e) {
91
- console.error(`[LIOP-Gateway] Error processing JSON-RPC payload: ${e.message}`);
112
+ log.info(`[LIOP-Gateway] Error processing JSON-RPC payload: ${e.message}`);
92
113
  res.writeHead(400);
93
114
  res.end(JSON.stringify({
94
115
  jsonrpc: "2.0",
@@ -108,7 +129,7 @@ export class LiopHybridGateway {
108
129
  // biome-ignore lint/suspicious/noExplicitAny: Standard gRPC stream data is Buffer
109
130
  const data = chunk;
110
131
  if (data)
111
- console.error(`[LIOP-Gateway] Native gRPC Proxy passing ${data.length} bytes`);
132
+ log.info(`[LIOP-Gateway] Native gRPC Proxy passing ${data.length} bytes`);
112
133
  });
113
134
  stream.respond({ ":status": 200, "content-type": "application/grpc" });
114
135
  stream.end();
@@ -135,31 +156,32 @@ export class LiopHybridGateway {
135
156
  }
136
157
  });
137
158
  }
138
- async listen(port, host = "::") {
159
+ async listen(port, host = "0.0.0.0") {
139
160
  if (this.meshNode) {
140
161
  await this.meshNode.start();
141
162
  // Announce all local tools to the DHT
142
163
  const tools = this.liopServer.listTools();
143
164
  for (const tool of tools) {
144
165
  await this.meshNode.announceCapability(tool.name);
145
- console.error(`[LIOP-Gateway] 📡 Announced local tool to Mesh: ${tool.name}`);
166
+ log.info(`[LIOP-Gateway] 📡 Announced local tool to Mesh: ${tool.name}`);
146
167
  }
147
168
  }
148
169
  return new Promise((resolve, reject) => {
149
170
  this.netServer.on("error", (err) => {
150
171
  if (err.code === "EADDRINUSE") {
151
- console.error(`[LIOP-Gateway] FATAL: Port ${port} is already in use by another process.`);
172
+ log.info(`[LIOP-Gateway] FATAL: Port ${port} is already in use by another process.`);
152
173
  }
153
174
  else {
154
- console.error(`[LIOP-Gateway] Binding Error: ${err.message}`);
175
+ log.error(`[LIOP-Gateway] Binding Error: ${err.message}`);
155
176
  }
156
177
  reject(err);
157
178
  });
158
179
  this.netServer.listen(port, host, () => {
159
180
  const addr = this.netServer.address();
160
181
  const actualHost = typeof addr === "string" ? addr : addr?.address || host;
161
- console.error(`[LIOP-Gateway] Transformer Mesh Gateway READY and listening on ${actualHost}:${port}`);
162
- resolve();
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);
163
185
  });
164
186
  });
165
187
  }
@@ -171,4 +193,7 @@ export class LiopHybridGateway {
171
193
  this.h2Server.close();
172
194
  this.h1Server.close();
173
195
  }
196
+ getRouter() {
197
+ return this.router;
198
+ }
174
199
  }
@@ -1,5 +1,7 @@
1
+ import { LiopVerifier } from "../crypto/verifier.js";
1
2
  import type { MeshNode } from "../mesh/index.js";
2
3
  import type { LiopServer } from "../server/index.js";
4
+ import type { McpRequest, McpResponse } from "../types.js";
3
5
  /**
4
6
  * LIOP MCP Router
5
7
  *
@@ -18,21 +20,35 @@ export declare class LiopMcpRouter {
18
20
  /** Guards against concurrent discovery storms */
19
21
  private currentDiscovery;
20
22
  /** Verifier for Tier-0 integrity checks */
21
- private verifier;
23
+ verifier: LiopVerifier;
22
24
  /** Callback when new remote tools are discovered */
23
25
  onToolsChanged?: () => void;
26
+ /** Circuit-breaker state for peers that repeatedly fail manifest queries. */
27
+ private manifestFailureState;
28
+ private static readonly MANIFEST_FAILURE_BASE_COOLDOWN_MS;
29
+ private static readonly MANIFEST_FAILURE_MAX_COOLDOWN_MS;
30
+ private static readonly MANIFEST_SKIP_LOG_THROTTLE_MS;
24
31
  constructor(liopServer: LiopServer, meshNode?: MeshNode | null, defaultRpcPort?: number);
25
- dispatch(request: {
26
- method: string;
27
- params?: any;
28
- id?: any;
29
- }): Promise<any>;
32
+ private shouldSkipManifestQuery;
33
+ private recordManifestQuerySuccess;
34
+ private recordManifestQueryFailure;
35
+ dispatch(request: McpRequest): Promise<McpResponse | null>;
36
+ /**
37
+ * MCP clients often send notifications/initialized then immediately tools/list.
38
+ * Start manifest discovery without blocking the notification handler.
39
+ */
40
+ private kickDiscoveryAfterInitialized;
30
41
  /**
31
42
  * Discovers and caches manifests from all remote LIOP providers in the mesh.
32
43
  * Uses Kademlia DHT to find "liop:manifest" providers, then opens
33
44
  * /liop/manifest/1.0.0 protocol streams to retrieve their full metadata.
34
45
  */
35
46
  refreshManifestCache(silent?: boolean): Promise<void>;
47
+ /**
48
+ * Returns the current manifest cache size for external telemetry.
49
+ * Used by the adaptive polling system to detect topology stabilization.
50
+ */
51
+ getCacheSize(): number;
36
52
  /**
37
53
  * Returns all remote tools discovered via the manifest protocol.
38
54
  */
@@ -42,10 +58,10 @@ export declare class LiopMcpRouter {
42
58
  */
43
59
  private getRemoteResources;
44
60
  /**
45
- * Resolves the gRPC target (host:port) for a given tool name
46
- * by searching the manifest cache. Returns null if not found.
61
+ * Resolves the gRPC target (host:port) AND the peerId for a given tool name
62
+ * by searching the manifest cache. Supports exact names and suffixed names.
47
63
  */
48
- private resolveGrpcTarget;
64
+ private resolveManifestTarget;
49
65
  private transcodeMcpToLiop;
50
66
  private routeToRemoteProvider;
51
67
  private performTranscoding;