@nekzus/liop 1.0.0-alpha.1
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/LICENSE +201 -0
- package/NOTICE +24 -0
- package/README.md +641 -0
- package/dist/bin/agent.d.ts +1 -0
- package/dist/bin/agent.js +897 -0
- package/dist/bin/agent.js.map +1 -0
- package/dist/bridge.d.ts +105 -0
- package/dist/bridge.js +5 -0
- package/dist/bridge.js.map +1 -0
- package/dist/chunk-3L2O2XKG.js +723 -0
- package/dist/chunk-3L2O2XKG.js.map +1 -0
- package/dist/chunk-7BSCUYUE.js +421 -0
- package/dist/chunk-7BSCUYUE.js.map +1 -0
- package/dist/chunk-7PITYWOV.js +68 -0
- package/dist/chunk-7PITYWOV.js.map +1 -0
- package/dist/chunk-7RXOIDXP.js +877 -0
- package/dist/chunk-7RXOIDXP.js.map +1 -0
- package/dist/chunk-BOISQ45Z.js +558 -0
- package/dist/chunk-BOISQ45Z.js.map +1 -0
- package/dist/chunk-DZ2FQGJD.js +206712 -0
- package/dist/chunk-DZ2FQGJD.js.map +1 -0
- package/dist/chunk-EG46XMJT.js +77 -0
- package/dist/chunk-EG46XMJT.js.map +1 -0
- package/dist/chunk-ESRXG36Y.js +115 -0
- package/dist/chunk-ESRXG36Y.js.map +1 -0
- package/dist/chunk-FTF6AMF6.js +3 -0
- package/dist/chunk-FTF6AMF6.js.map +1 -0
- package/dist/chunk-HA6YZ42O.js +64 -0
- package/dist/chunk-HA6YZ42O.js.map +1 -0
- package/dist/chunk-HD2N3IJX.js +3634 -0
- package/dist/chunk-HD2N3IJX.js.map +1 -0
- package/dist/chunk-IK7CGWAZ.js +24 -0
- package/dist/chunk-IK7CGWAZ.js.map +1 -0
- package/dist/chunk-L6J72C5X.js +1477 -0
- package/dist/chunk-L6J72C5X.js.map +1 -0
- package/dist/chunk-PAICJCKJ.js +332 -0
- package/dist/chunk-PAICJCKJ.js.map +1 -0
- package/dist/chunk-PEN3KFLF.js +114 -0
- package/dist/chunk-PEN3KFLF.js.map +1 -0
- package/dist/chunk-T7R5HUFD.js +775 -0
- package/dist/chunk-T7R5HUFD.js.map +1 -0
- package/dist/chunk-TKRX6CFI.js +168 -0
- package/dist/chunk-TKRX6CFI.js.map +1 -0
- package/dist/chunk-UCVP3XAL.js +279 -0
- package/dist/chunk-UCVP3XAL.js.map +1 -0
- package/dist/chunk-VH4K4U45.js +180 -0
- package/dist/chunk-VH4K4U45.js.map +1 -0
- package/dist/chunk-Y62GORQF.js +51 -0
- package/dist/chunk-Y62GORQF.js.map +1 -0
- package/dist/chunk-ZP3VVXOI.js +66 -0
- package/dist/chunk-ZP3VVXOI.js.map +1 -0
- package/dist/client.d.ts +7 -0
- package/dist/client.js +13 -0
- package/dist/client.js.map +1 -0
- package/dist/gateway.d.ts +7 -0
- package/dist/gateway.js +13 -0
- package/dist/gateway.js.map +1 -0
- package/dist/hybrid-CrKB50nh.d.ts +170 -0
- package/dist/index-CX43dvMs.d.ts +170 -0
- package/dist/index-DoW2gzBZ.d.ts +566 -0
- package/dist/index.d.ts +810 -0
- package/dist/index.js +357 -0
- package/dist/index.js.map +1 -0
- package/dist/kyber-CGOA7Q6A.js +3 -0
- package/dist/kyber-CGOA7Q6A.js.map +1 -0
- package/dist/mesh.d.ts +32 -0
- package/dist/mesh.js +6 -0
- package/dist/mesh.js.map +1 -0
- package/dist/node-B0b2vUFS.d.ts +164 -0
- package/dist/protocol/liop_core.proto +47 -0
- package/dist/server.d.ts +5 -0
- package/dist/server.js +9 -0
- package/dist/server.js.map +1 -0
- package/dist/types-lJIxBlWF.d.ts +256 -0
- package/dist/types.d.ts +3 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/verifier-COnid_dg.d.ts +31 -0
- package/dist/verifier-HRFXBKT5.js +6 -0
- package/dist/verifier-HRFXBKT5.js.map +1 -0
- package/dist/workers/logic-execution.d.ts +26 -0
- package/dist/workers/logic-execution.js +272 -0
- package/dist/workers/logic-execution.js.map +1 -0
- package/dist/workers/zk-verifier.d.ts +26 -0
- package/dist/workers/zk-verifier.js +174 -0
- package/dist/workers/zk-verifier.js.map +1 -0
- package/package.json +230 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
// src/types.ts
|
|
4
|
+
|
|
5
|
+
// src/gateway/mcp-compat.ts
|
|
6
|
+
var MCP_LEGACY_SUPPORT_ENABLED = true;
|
|
7
|
+
var MCP_PROTOCOL_VERSION_LEGACY = "2025-11-25";
|
|
8
|
+
function buildLegacyInitializeResponse(serverInfo, id) {
|
|
9
|
+
return {
|
|
10
|
+
jsonrpc: "2.0",
|
|
11
|
+
id: id ?? null,
|
|
12
|
+
result: {
|
|
13
|
+
protocolVersion: MCP_PROTOCOL_VERSION_LEGACY,
|
|
14
|
+
capabilities: {
|
|
15
|
+
tools: { listChanged: true },
|
|
16
|
+
resources: { listChanged: true },
|
|
17
|
+
prompts: { listChanged: true }
|
|
18
|
+
},
|
|
19
|
+
serverInfo
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function isLegacyRequest(request) {
|
|
24
|
+
if (request.method === "initialize" || request.method === "notifications/initialized") {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
const params = request.params;
|
|
28
|
+
const meta = params?._meta;
|
|
29
|
+
const version = meta?.["io.modelcontextprotocol/protocolVersion"];
|
|
30
|
+
if (!version || version === MCP_PROTOCOL_VERSION_LEGACY) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
function adaptResponseForLegacyClient(response) {
|
|
36
|
+
if (!response.result || typeof response.result !== "object") {
|
|
37
|
+
return response;
|
|
38
|
+
}
|
|
39
|
+
const rawResult = { ...response.result };
|
|
40
|
+
delete rawResult.resultType;
|
|
41
|
+
delete rawResult.ttlMs;
|
|
42
|
+
delete rawResult.cacheScope;
|
|
43
|
+
return {
|
|
44
|
+
...response,
|
|
45
|
+
result: rawResult
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// src/types.ts
|
|
50
|
+
var MCP_PROTOCOL_VERSION = "2026-07-28";
|
|
51
|
+
var ToolSchema = z.object({
|
|
52
|
+
name: z.string(),
|
|
53
|
+
description: z.string().optional(),
|
|
54
|
+
inputSchema: z.record(z.string(), z.unknown())
|
|
55
|
+
// Represents a JSON Schema
|
|
56
|
+
});
|
|
57
|
+
var ResourceSchema = z.object({
|
|
58
|
+
uri: z.string(),
|
|
59
|
+
name: z.string(),
|
|
60
|
+
description: z.string().optional(),
|
|
61
|
+
mimeType: z.string().optional()
|
|
62
|
+
});
|
|
63
|
+
var PromptSchema = z.object({
|
|
64
|
+
name: z.string(),
|
|
65
|
+
description: z.string().optional(),
|
|
66
|
+
arguments: z.array(
|
|
67
|
+
z.object({
|
|
68
|
+
name: z.string(),
|
|
69
|
+
description: z.string().optional(),
|
|
70
|
+
required: z.boolean().optional()
|
|
71
|
+
})
|
|
72
|
+
).optional()
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
export { MCP_LEGACY_SUPPORT_ENABLED, MCP_PROTOCOL_VERSION, MCP_PROTOCOL_VERSION_LEGACY, PromptSchema, ResourceSchema, ToolSchema, adaptResponseForLegacyClient, buildLegacyInitializeResponse, isLegacyRequest };
|
|
76
|
+
//# sourceMappingURL=chunk-EG46XMJT.js.map
|
|
77
|
+
//# sourceMappingURL=chunk-EG46XMJT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/gateway/mcp-compat.ts","../src/types.ts"],"names":[],"mappings":";;;;;AAiBO,IAAM,0BAAA,GAA6B;AAKnC,IAAM,2BAAA,GAA8B;AAKpC,SAAS,6BAAA,CACf,YACA,EAAA,EACc;AACd,EAAA,OAAO;AAAA,IACN,OAAA,EAAS,KAAA;AAAA,IACT,IAAI,EAAA,IAAM,IAAA;AAAA,IACV,MAAA,EAAQ;AAAA,MACP,eAAA,EAAiB,2BAAA;AAAA,MACjB,YAAA,EAAc;AAAA,QACb,KAAA,EAAO,EAAE,WAAA,EAAa,IAAA,EAAK;AAAA,QAC3B,SAAA,EAAW,EAAE,WAAA,EAAa,IAAA,EAAK;AAAA,QAC/B,OAAA,EAAS,EAAE,WAAA,EAAa,IAAA;AAAK,OAC9B;AAAA,MACA;AAAA;AACD,GACD;AACD;AAOO,SAAS,gBAAgB,OAAA,EAA8B;AAC7D,EAAA,IACC,OAAA,CAAQ,MAAA,KAAW,YAAA,IACnB,OAAA,CAAQ,WAAW,2BAAA,EAClB;AACD,IAAA,OAAO,IAAA;AAAA,EACR;AAEA,EAAA,MAAM,SAAS,OAAA,CAAQ,MAAA;AACvB,EAAA,MAAM,OAAO,MAAA,EAAQ,KAAA;AACrB,EAAA,MAAM,OAAA,GAAU,OAAO,yCAAyC,CAAA;AAEhE,EAAA,IAAI,CAAC,OAAA,IAAW,OAAA,KAAY,2BAAA,EAA6B;AACxD,IAAA,OAAO,IAAA;AAAA,EACR;AAEA,EAAA,OAAO,KAAA;AACR;AAMO,SAAS,6BACf,QAAA,EACc;AACd,EAAA,IAAI,CAAC,QAAA,CAAS,MAAA,IAAU,OAAO,QAAA,CAAS,WAAW,QAAA,EAAU;AAC5D,IAAA,OAAO,QAAA;AAAA,EACR;AAEA,EAAA,MAAM,SAAA,GAAY,EAAE,GAAI,QAAA,CAAS,MAAA,EAAmC;AAGpE,EAAA,OAAO,SAAA,CAAU,UAAA;AACjB,EAAA,OAAO,SAAA,CAAU,KAAA;AACjB,EAAA,OAAO,SAAA,CAAU,UAAA;AAEjB,EAAA,OAAO;AAAA,IACN,GAAG,QAAA;AAAA,IACH,MAAA,EAAQ;AAAA,GACT;AACD;;;ACpFO,IAAM,oBAAA,GAAuB;AAyD7B,IAAM,UAAA,GAAa,EAAE,MAAA,CAAO;AAAA,EAClC,IAAA,EAAM,EAAE,MAAA,EAAO;AAAA,EACf,WAAA,EAAa,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EACjC,WAAA,EAAa,EAAE,MAAA,CAAO,CAAA,CAAE,QAAO,EAAG,CAAA,CAAE,SAAS;AAAA;AAC9C,CAAC;AAIM,IAAM,cAAA,GAAiB,EAAE,MAAA,CAAO;AAAA,EACtC,GAAA,EAAK,EAAE,MAAA,EAAO;AAAA,EACd,IAAA,EAAM,EAAE,MAAA,EAAO;AAAA,EACf,WAAA,EAAa,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EACjC,QAAA,EAAU,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AACtB,CAAC;AAIM,IAAM,YAAA,GAAe,EAAE,MAAA,CAAO;AAAA,EACpC,IAAA,EAAM,EAAE,MAAA,EAAO;AAAA,EACf,WAAA,EAAa,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EACjC,WAAW,CAAA,CACT,KAAA;AAAA,IACA,EAAE,MAAA,CAAO;AAAA,MACR,IAAA,EAAM,EAAE,MAAA,EAAO;AAAA,MACf,WAAA,EAAa,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,MACjC,QAAA,EAAU,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAA;AAAS,KAC/B;AAAA,IAED,QAAA;AACH,CAAC","file":"chunk-EG46XMJT.js","sourcesContent":["// Copyright 2026 Nekzus Solutions and contributors\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { McpRequest, McpResponse, ServerInfo } from \"../types.js\";\n\n/**\n * @mcp-legacy ENTIRE FILE — MCP 2025-era backward compatibility layer.\n * Remove this file when MCP v1 (2025-11-25) reaches EOL.\n *\n * SUNSET INSTRUCTION: Delete this file, then grep for \"@mcp-legacy\" in the\n * codebase to find and remove all remaining legacy seams.\n */\n\n/**\n * @mcp-legacy Master kill switch for MCP 2025-era backward compatibility.\n * Set to `false` when MCP v1 reaches End-of-Life (EOL) to disable all legacy seams.\n */\nexport const MCP_LEGACY_SUPPORT_ENABLED = true;\n\n/**\n * @mcp-legacy Legacy protocol version constant.\n */\nexport const MCP_PROTOCOL_VERSION_LEGACY = \"2025-11-25\" as const;\n\n/**\n * @mcp-legacy Build the legacy initialize handshake response.\n */\nexport function buildLegacyInitializeResponse(\n\tserverInfo: ServerInfo,\n\tid?: string | number | null,\n): McpResponse {\n\treturn {\n\t\tjsonrpc: \"2.0\",\n\t\tid: id ?? null,\n\t\tresult: {\n\t\t\tprotocolVersion: MCP_PROTOCOL_VERSION_LEGACY,\n\t\t\tcapabilities: {\n\t\t\t\ttools: { listChanged: true },\n\t\t\t\tresources: { listChanged: true },\n\t\t\t\tprompts: { listChanged: true },\n\t\t\t},\n\t\t\tserverInfo,\n\t\t},\n\t};\n}\n\n/**\n * @mcp-legacy Detect if a request is strictly from a 2025-era legacy client.\n * Legacy requests either invoke 'initialize', 'notifications/initialized',\n * or lack modern '_meta' protocol envelopes.\n */\nexport function isLegacyRequest(request: McpRequest): boolean {\n\tif (\n\t\trequest.method === \"initialize\" ||\n\t\trequest.method === \"notifications/initialized\"\n\t) {\n\t\treturn true;\n\t}\n\n\tconst params = request.params as Record<string, unknown> | undefined;\n\tconst meta = params?._meta as Record<string, unknown> | undefined;\n\tconst version = meta?.[\"io.modelcontextprotocol/protocolVersion\"];\n\n\tif (!version || version === MCP_PROTOCOL_VERSION_LEGACY) {\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n/**\n * @mcp-legacy Wrap and strip modern-era fields (resultType, ttlMs, cacheScope, etc.)\n * from a response to ensure 100% wire-compatibility with strict 2025 MCP clients.\n */\nexport function adaptResponseForLegacyClient(\n\tresponse: McpResponse,\n): McpResponse {\n\tif (!response.result || typeof response.result !== \"object\") {\n\t\treturn response;\n\t}\n\n\tconst rawResult = { ...(response.result as Record<string, unknown>) };\n\n\t// Strip modern-only envelope tags\n\tdelete rawResult.resultType;\n\tdelete rawResult.ttlMs;\n\tdelete rawResult.cacheScope;\n\n\treturn {\n\t\t...response,\n\t\tresult: rawResult,\n\t};\n}\n","// Copyright 2026 Nekzus Solutions and contributors\n// SPDX-License-Identifier: Apache-2.0\n\nimport { z } from \"zod\";\n\n/**\n * Protocol Version Identifiers\n */\nexport const MCP_PROTOCOL_VERSION = \"2026-07-28\" as const;\n\nexport {\n\tMCP_LEGACY_SUPPORT_ENABLED,\n\tMCP_PROTOCOL_VERSION_LEGACY,\n} from \"./gateway/mcp-compat.js\";\n\n/**\n * Protocol Era Classification\n */\nexport type McpEra = \"legacy\" | \"modern\";\n\n/**\n * Caching Hints for MCP 2026-07-28 Spec\n */\nexport interface CacheableResult {\n\tttlMs?: number;\n\tcacheScope?: \"public\" | \"private\";\n}\n\n/**\n * Multi-Round-Trip Requests (MRTR) Specification Types\n */\nexport interface InputRequest {\n\tid: string;\n\tmessage: string;\n\tschema?: Record<string, unknown>;\n}\n\nexport interface InputResponse {\n\tid: string;\n\tvalue: unknown;\n}\n\nexport interface InputRequiredResult {\n\tresultType: \"input_required\";\n\tinputRequests: InputRequest[];\n\trequestState?: string;\n}\n\n/**\n * Modern Envelope Metadata (_meta)\n */\nexport interface McpRequestMeta {\n\t\"io.modelcontextprotocol/protocolVersion\"?: string;\n\t\"io.modelcontextprotocol/clientInfo\"?: {\n\t\tname: string;\n\t\tversion: string;\n\t};\n\t\"io.modelcontextprotocol/clientCapabilities\"?: Record<string, unknown>;\n\t[key: string]: unknown;\n}\n\n/**\n * Base Protocol Types representing parity with Model Context Protocol\n */\n\nexport const ToolSchema = z.object({\n\tname: z.string(),\n\tdescription: z.string().optional(),\n\tinputSchema: z.record(z.string(), z.unknown()), // Represents a JSON Schema\n});\n\nexport type Tool = z.infer<typeof ToolSchema>;\n\nexport const ResourceSchema = z.object({\n\turi: z.string(),\n\tname: z.string(),\n\tdescription: z.string().optional(),\n\tmimeType: z.string().optional(),\n});\n\nexport type Resource = z.infer<typeof ResourceSchema>;\n\nexport const PromptSchema = z.object({\n\tname: z.string(),\n\tdescription: z.string().optional(),\n\targuments: z\n\t\t.array(\n\t\t\tz.object({\n\t\t\t\tname: z.string(),\n\t\t\t\tdescription: z.string().optional(),\n\t\t\t\trequired: z.boolean().optional(),\n\t\t\t}),\n\t\t)\n\t\t.optional(),\n});\n\nexport type Prompt = z.infer<typeof PromptSchema>;\n\nexport interface CallToolRequest {\n\tname: string;\n\targuments?: Record<string, unknown>;\n}\n\nexport interface CallToolResult {\n\tcontent: Array<{\n\t\ttype: \"text\" | \"image\" | \"resource\";\n\t\ttext?: string;\n\t\tdata?: string;\n\t\tmimeType?: string;\n\t\tresource?: {\n\t\t\turi: string;\n\t\t\ttext?: string;\n\t\t\tblob?: string;\n\t\t};\n\t}>;\n\tisError?: boolean;\n}\n\nexport interface GetPromptRequest {\n\tname: string;\n\targuments?: Record<string, string>;\n}\n\nexport interface GetPromptResult {\n\tdescription?: string;\n\tmessages: Array<{\n\t\trole: \"user\" | \"assistant\";\n\t\tcontent:\n\t\t\t| { type: \"text\"; text: string }\n\t\t\t| { type: \"image\"; data: string; mimeType: string }\n\t\t\t| {\n\t\t\t\t\ttype: \"resource\";\n\t\t\t\t\tresource: { uri: string; text?: string; blob?: string };\n\t\t\t };\n\t}>;\n}\n\nexport interface ServerInfo {\n\tname: string;\n\tversion: string;\n\tcapabilities?: {\n\t\tprompts?: { listChanged?: boolean };\n\t\tresources?: { subscribe?: boolean; listChanged?: boolean };\n\t\ttools?: { listChanged?: boolean };\n\t\t/** @mcp-legacy @deprecated Deprecated in MCP 2026-07-28 spec */\n\t\tlogging?: Record<string, unknown>;\n\t};\n}\n\nexport interface DiscoverResult {\n\tresultType: \"complete\";\n\tsupportedVersions: string[];\n\tcapabilities: ServerInfo[\"capabilities\"];\n\tserverInfo: ServerInfo;\n\tinstructions?: string;\n}\n\nexport interface McpRequest {\n\tmethod: string;\n\tparams?: unknown;\n\tid?: string | number | null;\n\tjsonrpc?: \"2.0\";\n}\n\nexport interface McpResponse {\n\tjsonrpc: \"2.0\";\n\tid?: string | number | null;\n\tresult?: unknown;\n\terror?: {\n\t\tcode: number;\n\t\tmessage: string;\n\t\tdata?: unknown;\n\t};\n}\n\n/**\n * Re-export AuthInfo from the security module for convenience.\n * Compatible with MCP TypeScript SDK AuthInfo interface shape.\n */\nexport type { AuthInfo } from \"./security/jwt-validator.js\";\n"]}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { log } from './chunk-HA6YZ42O.js';
|
|
2
|
+
|
|
3
|
+
// src/runtime/token-manager.ts
|
|
4
|
+
var TokenManager = class _TokenManager {
|
|
5
|
+
cachedToken = null;
|
|
6
|
+
expiresAt = 0;
|
|
7
|
+
// Epoch ms
|
|
8
|
+
pendingPromise = null;
|
|
9
|
+
tokenEndpoint;
|
|
10
|
+
clientId;
|
|
11
|
+
clientSecret;
|
|
12
|
+
audience;
|
|
13
|
+
scope;
|
|
14
|
+
staticToken;
|
|
15
|
+
// Preemptive refresh threshold: 30 seconds before expiration
|
|
16
|
+
static REFRESH_BUFFER_MS = 3e4;
|
|
17
|
+
constructor(options) {
|
|
18
|
+
this.tokenEndpoint = options.tokenEndpoint;
|
|
19
|
+
this.clientId = options.clientId;
|
|
20
|
+
this.clientSecret = options.clientSecret;
|
|
21
|
+
this.audience = options.audience ?? "urn:liop:mesh:api";
|
|
22
|
+
this.scope = Array.isArray(options.scopes) ? options.scopes.join(" ") : options.scopes ?? "liop:tools:call liop:tools:list liop:resources:read liop:schema:read liop:mesh:query";
|
|
23
|
+
this.staticToken = options.staticToken;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Returns a valid OAuth 2.1 access token.
|
|
27
|
+
* Automatically performs preemptive refresh if the token is close to expiry.
|
|
28
|
+
*/
|
|
29
|
+
async getToken() {
|
|
30
|
+
if (this.staticToken) {
|
|
31
|
+
return this.staticToken;
|
|
32
|
+
}
|
|
33
|
+
const now = Date.now();
|
|
34
|
+
if (this.cachedToken && now < this.expiresAt - _TokenManager.REFRESH_BUFFER_MS) {
|
|
35
|
+
return this.cachedToken;
|
|
36
|
+
}
|
|
37
|
+
if (this.pendingPromise) {
|
|
38
|
+
return this.pendingPromise;
|
|
39
|
+
}
|
|
40
|
+
this.pendingPromise = (async () => {
|
|
41
|
+
try {
|
|
42
|
+
const token = await this.fetchNewToken();
|
|
43
|
+
this.cachedToken = token;
|
|
44
|
+
return token;
|
|
45
|
+
} finally {
|
|
46
|
+
this.pendingPromise = null;
|
|
47
|
+
}
|
|
48
|
+
})();
|
|
49
|
+
return this.pendingPromise;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Force-invalidates cached token, e.g. after receiving a 401 Unauthorized response.
|
|
53
|
+
*/
|
|
54
|
+
invalidate() {
|
|
55
|
+
this.cachedToken = null;
|
|
56
|
+
this.expiresAt = 0;
|
|
57
|
+
if (this.clientId && this.clientSecret) {
|
|
58
|
+
this.staticToken = void 0;
|
|
59
|
+
}
|
|
60
|
+
log.info("[TokenManager] Cached OAuth access token invalidated.");
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Returns true if the token is absent or has passed the refresh threshold.
|
|
64
|
+
*/
|
|
65
|
+
isExpired() {
|
|
66
|
+
if (this.staticToken) return false;
|
|
67
|
+
return !this.cachedToken || Date.now() >= this.expiresAt - _TokenManager.REFRESH_BUFFER_MS;
|
|
68
|
+
}
|
|
69
|
+
getExpiresAt() {
|
|
70
|
+
return this.expiresAt;
|
|
71
|
+
}
|
|
72
|
+
async fetchNewToken() {
|
|
73
|
+
log.info(
|
|
74
|
+
`[TokenManager] Requesting M2M token from ${this.tokenEndpoint} for client '${this.clientId}'...`
|
|
75
|
+
);
|
|
76
|
+
const params = new URLSearchParams({
|
|
77
|
+
grant_type: "client_credentials",
|
|
78
|
+
client_id: this.clientId,
|
|
79
|
+
client_secret: this.clientSecret,
|
|
80
|
+
resource: this.audience,
|
|
81
|
+
scope: this.scope
|
|
82
|
+
});
|
|
83
|
+
const response = await fetch(this.tokenEndpoint, {
|
|
84
|
+
method: "POST",
|
|
85
|
+
headers: {
|
|
86
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
87
|
+
Accept: "application/json"
|
|
88
|
+
},
|
|
89
|
+
body: params.toString(),
|
|
90
|
+
signal: AbortSignal.timeout(1e4)
|
|
91
|
+
});
|
|
92
|
+
if (!response.ok) {
|
|
93
|
+
const errorText = await response.text();
|
|
94
|
+
throw new Error(
|
|
95
|
+
`OAuth token request failed [HTTP ${response.status}]: ${errorText}`
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
const data = await response.json();
|
|
99
|
+
if (!data.access_token) {
|
|
100
|
+
throw new Error(
|
|
101
|
+
"OAuth token response did not contain an 'access_token' field."
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
const expiresInSec = typeof data.expires_in === "number" ? data.expires_in : 3600;
|
|
105
|
+
this.expiresAt = Date.now() + expiresInSec * 1e3;
|
|
106
|
+
log.info(
|
|
107
|
+
`[TokenManager] Acquired access token successfully. Expires in ${expiresInSec}s.`
|
|
108
|
+
);
|
|
109
|
+
return data.access_token;
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export { TokenManager };
|
|
114
|
+
//# sourceMappingURL=chunk-ESRXG36Y.js.map
|
|
115
|
+
//# sourceMappingURL=chunk-ESRXG36Y.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/runtime/token-manager.ts"],"names":[],"mappings":"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","file":"chunk-ESRXG36Y.js","sourcesContent":["// Copyright 2026 Nekzus Solutions and contributors\n// SPDX-License-Identifier: Apache-2.0\n\n/**\n * LIOP Token Manager — Adaptive OAuth 2.1 M2M Token Lifecycle\n *\n * Implements resilient token caching with preemptive refresh (30s safety buffer),\n * concurrency de-duplication (single in-flight HTTP request), and on-demand\n * invalidation for 401 Unauthorized handling.\n *\n * Standards: RFC 6749, RFC 8707 (Resource Indicators), RFC 9068 (JWT Profile)\n */\n\nimport { log } from \"../utils/logger.js\";\n\nexport interface TokenManagerOptions {\n\ttokenEndpoint: string;\n\tclientId: string;\n\tclientSecret: string;\n\taudience?: string;\n\tscopes?: string | string[];\n\tstaticToken?: string;\n}\n\nexport class TokenManager {\n\tprivate cachedToken: string | null = null;\n\tprivate expiresAt = 0; // Epoch ms\n\tprivate pendingPromise: Promise<string> | null = null;\n\n\tprivate readonly tokenEndpoint: string;\n\tprivate readonly clientId: string;\n\tprivate readonly clientSecret: string;\n\tprivate readonly audience: string;\n\tprivate readonly scope: string;\n\tprivate staticToken?: string;\n\n\t// Preemptive refresh threshold: 30 seconds before expiration\n\tprivate static readonly REFRESH_BUFFER_MS = 30_000;\n\n\tconstructor(options: TokenManagerOptions) {\n\t\tthis.tokenEndpoint = options.tokenEndpoint;\n\t\tthis.clientId = options.clientId;\n\t\tthis.clientSecret = options.clientSecret;\n\t\tthis.audience = options.audience ?? \"urn:liop:mesh:api\";\n\t\tthis.scope = Array.isArray(options.scopes)\n\t\t\t? options.scopes.join(\" \")\n\t\t\t: (options.scopes ??\n\t\t\t\t\"liop:tools:call liop:tools:list liop:resources:read liop:schema:read liop:mesh:query\");\n\t\tthis.staticToken = options.staticToken;\n\t}\n\n\t/**\n\t * Returns a valid OAuth 2.1 access token.\n\t * Automatically performs preemptive refresh if the token is close to expiry.\n\t */\n\tpublic async getToken(): Promise<string> {\n\t\tif (this.staticToken) {\n\t\t\treturn this.staticToken;\n\t\t}\n\n\t\tconst now = Date.now();\n\t\tif (\n\t\t\tthis.cachedToken &&\n\t\t\tnow < this.expiresAt - TokenManager.REFRESH_BUFFER_MS\n\t\t) {\n\t\t\treturn this.cachedToken;\n\t\t}\n\n\t\tif (this.pendingPromise) {\n\t\t\treturn this.pendingPromise;\n\t\t}\n\n\t\tthis.pendingPromise = (async () => {\n\t\t\ttry {\n\t\t\t\tconst token = await this.fetchNewToken();\n\t\t\t\tthis.cachedToken = token;\n\t\t\t\treturn token;\n\t\t\t} finally {\n\t\t\t\tthis.pendingPromise = null;\n\t\t\t}\n\t\t})();\n\n\t\treturn this.pendingPromise;\n\t}\n\n\t/**\n\t * Force-invalidates cached token, e.g. after receiving a 401 Unauthorized response.\n\t */\n\tpublic invalidate(): void {\n\t\tthis.cachedToken = null;\n\t\tthis.expiresAt = 0;\n\t\tif (this.clientId && this.clientSecret) {\n\t\t\tthis.staticToken = undefined;\n\t\t}\n\t\tlog.info(\"[TokenManager] Cached OAuth access token invalidated.\");\n\t}\n\n\t/**\n\t * Returns true if the token is absent or has passed the refresh threshold.\n\t */\n\tpublic isExpired(): boolean {\n\t\tif (this.staticToken) return false;\n\t\treturn (\n\t\t\t!this.cachedToken ||\n\t\t\tDate.now() >= this.expiresAt - TokenManager.REFRESH_BUFFER_MS\n\t\t);\n\t}\n\n\tpublic getExpiresAt(): number {\n\t\treturn this.expiresAt;\n\t}\n\n\tprivate async fetchNewToken(): Promise<string> {\n\t\tlog.info(\n\t\t\t`[TokenManager] Requesting M2M token from ${this.tokenEndpoint} for client '${this.clientId}'...`,\n\t\t);\n\n\t\tconst params = new URLSearchParams({\n\t\t\tgrant_type: \"client_credentials\",\n\t\t\tclient_id: this.clientId,\n\t\t\tclient_secret: this.clientSecret,\n\t\t\tresource: this.audience,\n\t\t\tscope: this.scope,\n\t\t});\n\n\t\tconst response = await fetch(this.tokenEndpoint, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: params.toString(),\n\t\t\tsignal: AbortSignal.timeout(10_000),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst errorText = await response.text();\n\t\t\tthrow new Error(\n\t\t\t\t`OAuth token request failed [HTTP ${response.status}]: ${errorText}`,\n\t\t\t);\n\t\t}\n\n\t\tconst data = (await response.json()) as {\n\t\t\taccess_token?: string;\n\t\t\texpires_in?: number;\n\t\t\ttoken_type?: string;\n\t\t};\n\n\t\tif (!data.access_token) {\n\t\t\tthrow new Error(\n\t\t\t\t\"OAuth token response did not contain an 'access_token' field.\",\n\t\t\t);\n\t\t}\n\n\t\tconst expiresInSec =\n\t\t\ttypeof data.expires_in === \"number\" ? data.expires_in : 3600;\n\t\tthis.expiresAt = Date.now() + expiresInSec * 1000;\n\n\t\tlog.info(\n\t\t\t`[TokenManager] Acquired access token successfully. Expires in ${expiresInSec}s.`,\n\t\t);\n\n\t\treturn data.access_token;\n\t}\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-FTF6AMF6.js"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// src/utils/logger.ts
|
|
2
|
+
var LiopLogger = class _LiopLogger {
|
|
3
|
+
static instance;
|
|
4
|
+
level = "info";
|
|
5
|
+
constructor() {
|
|
6
|
+
this.setLevelFromEnv();
|
|
7
|
+
}
|
|
8
|
+
static getInstance() {
|
|
9
|
+
if (!_LiopLogger.instance) {
|
|
10
|
+
_LiopLogger.instance = new _LiopLogger();
|
|
11
|
+
}
|
|
12
|
+
return _LiopLogger.instance;
|
|
13
|
+
}
|
|
14
|
+
setLevelFromEnv() {
|
|
15
|
+
const envLevel = process.env.LIOP_LOG_LEVEL?.toLowerCase();
|
|
16
|
+
if (envLevel === "silent" || envLevel === "error" || envLevel === "warn" || envLevel === "info" || envLevel === "debug") {
|
|
17
|
+
this.level = envLevel;
|
|
18
|
+
} else {
|
|
19
|
+
this.level = "info";
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
setLevel(level) {
|
|
23
|
+
this.level = level;
|
|
24
|
+
}
|
|
25
|
+
shouldLog(targetLevel) {
|
|
26
|
+
const levels = {
|
|
27
|
+
silent: 0,
|
|
28
|
+
error: 1,
|
|
29
|
+
warn: 2,
|
|
30
|
+
info: 3,
|
|
31
|
+
debug: 4
|
|
32
|
+
};
|
|
33
|
+
return levels[this.level] >= levels[targetLevel];
|
|
34
|
+
}
|
|
35
|
+
formatMessage(level, message) {
|
|
36
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
37
|
+
return `[${ts}] [${level}] ${message}`;
|
|
38
|
+
}
|
|
39
|
+
error(message, ...args) {
|
|
40
|
+
if (this.shouldLog("error")) {
|
|
41
|
+
console.error(this.formatMessage("ERROR", message), ...args);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
warn(message, ...args) {
|
|
45
|
+
if (this.shouldLog("warn")) {
|
|
46
|
+
console.error(this.formatMessage("WARN", message), ...args);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
info(message, ...args) {
|
|
50
|
+
if (this.shouldLog("info")) {
|
|
51
|
+
console.error(this.formatMessage("INFO", message), ...args);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
debug(message, ...args) {
|
|
55
|
+
if (this.shouldLog("debug")) {
|
|
56
|
+
console.error(this.formatMessage("DEBUG", message), ...args);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
var log = LiopLogger.getInstance();
|
|
61
|
+
|
|
62
|
+
export { log };
|
|
63
|
+
//# sourceMappingURL=chunk-HA6YZ42O.js.map
|
|
64
|
+
//# sourceMappingURL=chunk-HA6YZ42O.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/logger.ts"],"names":[],"mappings":";AAUO,IAAM,UAAA,GAAN,MAAM,WAAA,CAAW;AAAA,EACvB,OAAe,QAAA;AAAA,EACP,KAAA,GAAkB,MAAA;AAAA,EAElB,WAAA,GAAc;AACrB,IAAA,IAAA,CAAK,eAAA,EAAgB;AAAA,EACtB;AAAA,EAEA,OAAc,WAAA,GAA0B;AACvC,IAAA,IAAI,CAAC,YAAW,QAAA,EAAU;AACzB,MAAA,WAAA,CAAW,QAAA,GAAW,IAAI,WAAA,EAAW;AAAA,IACtC;AACA,IAAA,OAAO,WAAA,CAAW,QAAA;AAAA,EACnB;AAAA,EAEQ,eAAA,GAAkB;AACzB,IAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,GAAA,CAAI,cAAA,EAAgB,WAAA,EAAY;AACzD,IAAA,IACC,QAAA,KAAa,YACb,QAAA,KAAa,OAAA,IACb,aAAa,MAAA,IACb,QAAA,KAAa,MAAA,IACb,QAAA,KAAa,OAAA,EACZ;AACD,MAAA,IAAA,CAAK,KAAA,GAAQ,QAAA;AAAA,IACd,CAAA,MAAO;AAEN,MAAA,IAAA,CAAK,KAAA,GAAQ,MAAA;AAAA,IACd;AAAA,EACD;AAAA,EAEO,SAAS,KAAA,EAAiB;AAChC,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AAAA,EACd;AAAA,EAEQ,UAAU,WAAA,EAAgC;AACjD,IAAA,MAAM,MAAA,GAAmC;AAAA,MACxC,MAAA,EAAQ,CAAA;AAAA,MACR,KAAA,EAAO,CAAA;AAAA,MACP,IAAA,EAAM,CAAA;AAAA,MACN,IAAA,EAAM,CAAA;AAAA,MACN,KAAA,EAAO;AAAA,KACR;AACA,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,IAAK,OAAO,WAAW,CAAA;AAAA,EAChD;AAAA,EAEQ,aAAA,CAAc,OAAe,OAAA,EAAyB;AAC7D,IAAA,MAAM,EAAA,GAAA,iBAAK,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAClC,IAAA,OAAO,CAAA,CAAA,EAAI,EAAE,CAAA,GAAA,EAAM,KAAK,KAAK,OAAO,CAAA,CAAA;AAAA,EACrC;AAAA,EAEO,KAAA,CAAM,YAAoB,IAAA,EAAiB;AACjD,IAAA,IAAI,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA,EAAG;AAC5B,MAAA,OAAA,CAAQ,MAAM,IAAA,CAAK,aAAA,CAAc,SAAS,OAAO,CAAA,EAAG,GAAG,IAAI,CAAA;AAAA,IAC5D;AAAA,EACD;AAAA,EAEO,IAAA,CAAK,YAAoB,IAAA,EAAiB;AAChD,IAAA,IAAI,IAAA,CAAK,SAAA,CAAU,MAAM,CAAA,EAAG;AAC3B,MAAA,OAAA,CAAQ,MAAM,IAAA,CAAK,aAAA,CAAc,QAAQ,OAAO,CAAA,EAAG,GAAG,IAAI,CAAA;AAAA,IAC3D;AAAA,EACD;AAAA,EAEO,IAAA,CAAK,YAAoB,IAAA,EAAiB;AAChD,IAAA,IAAI,IAAA,CAAK,SAAA,CAAU,MAAM,CAAA,EAAG;AAC3B,MAAA,OAAA,CAAQ,MAAM,IAAA,CAAK,aAAA,CAAc,QAAQ,OAAO,CAAA,EAAG,GAAG,IAAI,CAAA;AAAA,IAC3D;AAAA,EACD;AAAA,EAEO,KAAA,CAAM,YAAoB,IAAA,EAAiB;AACjD,IAAA,IAAI,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA,EAAG;AAC5B,MAAA,OAAA,CAAQ,MAAM,IAAA,CAAK,aAAA,CAAc,SAAS,OAAO,CAAA,EAAG,GAAG,IAAI,CAAA;AAAA,IAC5D;AAAA,EACD;AACD,CAAA;AAEO,IAAM,GAAA,GAAM,WAAW,WAAA","file":"chunk-HA6YZ42O.js","sourcesContent":["// Copyright 2026 Nekzus Solutions and contributors\n// SPDX-License-Identifier: Apache-2.0\n\nexport type LogLevel = \"silent\" | \"error\" | \"warn\" | \"info\" | \"debug\";\n\n/**\n * LiopLogger - Structured Logging Abstraction\n * Configurable via `process.env.LIOP_LOG_LEVEL`.\n * Emits strictly to stderr to comply with MCP stdio protocols.\n */\nexport class LiopLogger {\n\tprivate static instance: LiopLogger;\n\tprivate level: LogLevel = \"info\";\n\n\tprivate constructor() {\n\t\tthis.setLevelFromEnv();\n\t}\n\n\tpublic static getInstance(): LiopLogger {\n\t\tif (!LiopLogger.instance) {\n\t\t\tLiopLogger.instance = new LiopLogger();\n\t\t}\n\t\treturn LiopLogger.instance;\n\t}\n\n\tprivate setLevelFromEnv() {\n\t\tconst envLevel = process.env.LIOP_LOG_LEVEL?.toLowerCase();\n\t\tif (\n\t\t\tenvLevel === \"silent\" ||\n\t\t\tenvLevel === \"error\" ||\n\t\t\tenvLevel === \"warn\" ||\n\t\t\tenvLevel === \"info\" ||\n\t\t\tenvLevel === \"debug\"\n\t\t) {\n\t\t\tthis.level = envLevel as LogLevel;\n\t\t} else {\n\t\t\t// Default level: info\n\t\t\tthis.level = \"info\";\n\t\t}\n\t}\n\n\tpublic setLevel(level: LogLevel) {\n\t\tthis.level = level;\n\t}\n\n\tprivate shouldLog(targetLevel: LogLevel): boolean {\n\t\tconst levels: Record<LogLevel, number> = {\n\t\t\tsilent: 0,\n\t\t\terror: 1,\n\t\t\twarn: 2,\n\t\t\tinfo: 3,\n\t\t\tdebug: 4,\n\t\t};\n\t\treturn levels[this.level] >= levels[targetLevel];\n\t}\n\n\tprivate formatMessage(level: string, message: string): string {\n\t\tconst ts = new Date().toISOString();\n\t\treturn `[${ts}] [${level}] ${message}`;\n\t}\n\n\tpublic error(message: string, ...args: unknown[]) {\n\t\tif (this.shouldLog(\"error\")) {\n\t\t\tconsole.error(this.formatMessage(\"ERROR\", message), ...args);\n\t\t}\n\t}\n\n\tpublic warn(message: string, ...args: unknown[]) {\n\t\tif (this.shouldLog(\"warn\")) {\n\t\t\tconsole.error(this.formatMessage(\"WARN\", message), ...args);\n\t\t}\n\t}\n\n\tpublic info(message: string, ...args: unknown[]) {\n\t\tif (this.shouldLog(\"info\")) {\n\t\t\tconsole.error(this.formatMessage(\"INFO\", message), ...args);\n\t\t}\n\t}\n\n\tpublic debug(message: string, ...args: unknown[]) {\n\t\tif (this.shouldLog(\"debug\")) {\n\t\t\tconsole.error(this.formatMessage(\"DEBUG\", message), ...args);\n\t\t}\n\t}\n}\n\nexport const log = LiopLogger.getInstance();\n"]}
|