@decaf-ts/mcp-server 0.0.2 → 0.0.4

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 (93) hide show
  1. package/LICENSE.md +86 -21
  2. package/README.md +13 -13
  3. package/dist/mcp-server.cjs +893 -187
  4. package/dist/mcp-server.esm.cjs +888 -180
  5. package/lib/McpWrapper.cjs +189 -0
  6. package/lib/McpWrapper.d.ts +101 -0
  7. package/lib/bin/cli.cjs +30 -54
  8. package/lib/bin/cli.d.ts +18 -44
  9. package/lib/constants.cjs +12 -0
  10. package/lib/constants.d.ts +8 -0
  11. package/lib/esm/McpWrapper.d.ts +101 -0
  12. package/lib/esm/McpWrapper.js +182 -0
  13. package/lib/esm/bin/cli.d.ts +18 -44
  14. package/lib/esm/bin/cli.js +28 -55
  15. package/lib/esm/constants.d.ts +8 -0
  16. package/lib/esm/constants.js +9 -0
  17. package/lib/esm/index.d.ts +5 -26
  18. package/lib/esm/index.js +6 -27
  19. package/lib/esm/mcp/index.d.ts +1 -0
  20. package/lib/esm/mcp/index.js +2 -0
  21. package/lib/esm/metadata.d.ts +9 -0
  22. package/lib/esm/metadata.js +22 -0
  23. package/lib/esm/modules/decoration/index.d.ts +0 -0
  24. package/lib/esm/modules/decoration/index.js +2 -0
  25. package/lib/esm/modules/mcp/decoration-assist.d.ts +39 -0
  26. package/lib/esm/modules/mcp/decoration-assist.js +353 -0
  27. package/lib/esm/modules/mcp/decorator-tools.d.ts +118 -0
  28. package/lib/esm/modules/mcp/decorator-tools.js +237 -0
  29. package/lib/esm/modules/mcp/index.d.ts +2 -0
  30. package/lib/esm/modules/mcp/index.js +3 -0
  31. package/lib/esm/modules/mcp/mcp-module.d.ts +230 -0
  32. package/lib/esm/modules/mcp/mcp-module.js +406 -0
  33. package/lib/esm/types.d.ts +15 -0
  34. package/lib/esm/types.js +2 -0
  35. package/lib/esm/utils.d.ts +54 -13
  36. package/lib/esm/utils.js +78 -15
  37. package/lib/index.cjs +6 -28
  38. package/lib/index.d.ts +5 -26
  39. package/lib/mcp/index.cjs +17 -0
  40. package/lib/mcp/index.d.ts +1 -0
  41. package/lib/metadata.cjs +25 -0
  42. package/lib/metadata.d.ts +9 -0
  43. package/lib/modules/decoration/index.cjs +2 -0
  44. package/lib/modules/decoration/index.d.ts +0 -0
  45. package/lib/modules/mcp/decoration-assist.cjs +360 -0
  46. package/lib/modules/mcp/decoration-assist.d.ts +39 -0
  47. package/lib/modules/mcp/decorator-tools.cjs +243 -0
  48. package/lib/modules/mcp/decorator-tools.d.ts +118 -0
  49. package/lib/modules/mcp/index.cjs +24 -0
  50. package/lib/modules/mcp/index.d.ts +2 -0
  51. package/lib/modules/mcp/mcp-module.cjs +452 -0
  52. package/lib/modules/mcp/mcp-module.d.ts +230 -0
  53. package/lib/types.cjs +3 -0
  54. package/lib/types.d.ts +15 -0
  55. package/lib/utils.cjs +116 -16
  56. package/lib/utils.d.ts +54 -13
  57. package/package.json +35 -7
  58. package/lib/esm/namespace/Class.d.ts +0 -74
  59. package/lib/esm/namespace/Class.js +0 -73
  60. package/lib/esm/namespace/Interface.d.ts +0 -17
  61. package/lib/esm/namespace/Interface.js +0 -2
  62. package/lib/esm/namespace/children/ChildClass.d.ts +0 -44
  63. package/lib/esm/namespace/children/ChildClass.js +0 -43
  64. package/lib/esm/namespace/children/ChildInterface.d.ts +0 -22
  65. package/lib/esm/namespace/children/ChildInterface.js +0 -2
  66. package/lib/esm/namespace/children/Enum.d.ts +0 -14
  67. package/lib/esm/namespace/children/Enum.js +0 -16
  68. package/lib/esm/namespace/children/function.d.ts +0 -31
  69. package/lib/esm/namespace/children/function.js +0 -33
  70. package/lib/esm/namespace/children/index.d.ts +0 -25
  71. package/lib/esm/namespace/children/index.js +0 -26
  72. package/lib/esm/namespace/index.d.ts +0 -18
  73. package/lib/esm/namespace/index.js +0 -19
  74. package/lib/esm/namespace/type.d.ts +0 -28
  75. package/lib/esm/namespace/type.js +0 -2
  76. package/lib/namespace/Class.cjs +0 -77
  77. package/lib/namespace/Class.d.ts +0 -74
  78. package/lib/namespace/Interface.cjs +0 -3
  79. package/lib/namespace/Interface.d.ts +0 -17
  80. package/lib/namespace/children/ChildClass.cjs +0 -47
  81. package/lib/namespace/children/ChildClass.d.ts +0 -44
  82. package/lib/namespace/children/ChildInterface.cjs +0 -3
  83. package/lib/namespace/children/ChildInterface.d.ts +0 -22
  84. package/lib/namespace/children/Enum.cjs +0 -19
  85. package/lib/namespace/children/Enum.d.ts +0 -14
  86. package/lib/namespace/children/function.cjs +0 -36
  87. package/lib/namespace/children/function.d.ts +0 -31
  88. package/lib/namespace/children/index.cjs +0 -42
  89. package/lib/namespace/children/index.d.ts +0 -25
  90. package/lib/namespace/index.cjs +0 -35
  91. package/lib/namespace/index.d.ts +0 -18
  92. package/lib/namespace/type.cjs +0 -3
  93. package/lib/namespace/type.d.ts +0 -28
@@ -0,0 +1,406 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { applyPatch, createTwoFilesPatch } from "diff";
4
+ import { z } from "zod";
5
+ import { PACKAGE_NAME as PKG, VERSION as V } from "../../metadata";
6
+ import { decoratorTools } from "./decorator-tools";
7
+ const WORKSPACE_ROOT_ENV = "MCP_WORKSPACE_ROOT";
8
+ const PROMPT_DIRECTORIES = [".code/prompts", ".codex/prompts"];
9
+ const DEFAULT_PROMPT_NAME = "doc";
10
+ const CLIENT_INTEGRATIONS = [
11
+ {
12
+ id: "vscode",
13
+ display: "Visual Studio Code",
14
+ instructions: "When interacting from Visual Studio Code, prefer the vscode://workspace/{path} resource template to fetch file contents and use the apply-code-change tool to commit edits with previewable diffs.",
15
+ },
16
+ {
17
+ id: "cursor",
18
+ display: "Cursor",
19
+ instructions: "Cursor clients can retrieve and update files through the cursor://workspace/{path} resource template. Always validate patches in dryRun mode before applying permanent changes.",
20
+ },
21
+ {
22
+ id: "copilot",
23
+ display: "GitHub Copilot",
24
+ instructions: "Use the copilot://workspace/{path} resource template to stream file content into Copilot chat sessions. Prefer returning unified diffs to maintain alignment with Copilot's diff visualization.",
25
+ },
26
+ ];
27
+ const documentCodeSchema = z
28
+ .object({
29
+ filePath: z.string().min(1, "filePath is required"),
30
+ promptName: z.string().optional(),
31
+ includePrompt: z.boolean().default(true),
32
+ includeCode: z.boolean().default(true),
33
+ includeMetadata: z.boolean().default(true),
34
+ additionalContext: z.string().optional(),
35
+ encoding: z.string().default("utf8"),
36
+ })
37
+ .strict();
38
+ const codeChangeSchema = z
39
+ .object({
40
+ filePath: z.string().min(1, "filePath is required"),
41
+ patch: z.string().min(1, "patch is required"),
42
+ dryRun: z.boolean().default(false),
43
+ showDiff: z.boolean().default(true),
44
+ diffContext: z.number().int().min(0).max(100).default(3),
45
+ encoding: z.string().default("utf8"),
46
+ })
47
+ .strict();
48
+ let workspaceRoot = initializeWorkspaceRoot();
49
+ let userErrorCtor;
50
+ class WorkspaceError extends Error {
51
+ constructor(message) {
52
+ super(message);
53
+ this.name = "WorkspaceError";
54
+ }
55
+ }
56
+ async function getUserErrorCtor() {
57
+ if (!userErrorCtor) {
58
+ try {
59
+ const mod = await import("fastmcp");
60
+ userErrorCtor = mod
61
+ .UserError;
62
+ }
63
+ catch {
64
+ userErrorCtor = class MCPUserError extends Error {
65
+ constructor(message) {
66
+ super(message);
67
+ this.name = "MCPUserError";
68
+ }
69
+ };
70
+ }
71
+ }
72
+ return userErrorCtor;
73
+ }
74
+ async function throwUserError(message) {
75
+ const Ctor = await getUserErrorCtor();
76
+ throw new Ctor(message);
77
+ }
78
+ const documentCodeTool = {
79
+ annotations: {
80
+ idempotentHint: true,
81
+ openWorldHint: false,
82
+ readOnlyHint: true,
83
+ title: "Document Source File",
84
+ },
85
+ description: "Generate documentation guidance for a file by combining repository prompts with the target source code.",
86
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
87
+ execute: async (input, _context) => {
88
+ const args = documentCodeSchema.parse(input);
89
+ const root = getWorkspaceRoot();
90
+ let filePath;
91
+ try {
92
+ filePath = resolveInWorkspace(root, args.filePath);
93
+ }
94
+ catch (error) {
95
+ if (error instanceof WorkspaceError) {
96
+ return throwUserError(error.message);
97
+ }
98
+ /* istanbul ignore next */
99
+ throw error;
100
+ }
101
+ if (!fs.existsSync(filePath)) {
102
+ return throwUserError(`Cannot document missing file at ${args.filePath}`);
103
+ }
104
+ const fileContent = fs.readFileSync(filePath, {
105
+ encoding: args.encoding,
106
+ });
107
+ const prompts = discoverDocPrompts(root);
108
+ if (!prompts.length) {
109
+ return throwUserError("No documentation prompts found under .code/prompts or .codex/prompts");
110
+ }
111
+ const prompt = selectPrompt(prompts, args.promptName ?? DEFAULT_PROMPT_NAME);
112
+ return buildDocumentationPayload({
113
+ filePath: args.filePath,
114
+ fileContent,
115
+ prompt,
116
+ includeCode: args.includeCode,
117
+ includePrompt: args.includePrompt,
118
+ includeMetadata: args.includeMetadata,
119
+ additionalContext: args.additionalContext,
120
+ });
121
+ },
122
+ name: "document-code",
123
+ parameters: documentCodeSchema,
124
+ };
125
+ const applyCodeChangeTool = {
126
+ annotations: {
127
+ destructiveHint: true,
128
+ idempotentHint: false,
129
+ openWorldHint: false,
130
+ readOnlyHint: false,
131
+ title: "Apply Code Patch",
132
+ },
133
+ description: "Apply a unified diff patch to a workspace file with optional dry-run validation and diff preview.",
134
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
135
+ execute: async (input, _context) => {
136
+ const args = codeChangeSchema.parse(input);
137
+ const root = getWorkspaceRoot();
138
+ let filePath;
139
+ try {
140
+ filePath = resolveInWorkspace(root, args.filePath);
141
+ }
142
+ catch (error) {
143
+ if (error instanceof WorkspaceError) {
144
+ return throwUserError(error.message);
145
+ }
146
+ throw error;
147
+ }
148
+ const original = fs.existsSync(filePath)
149
+ ? fs.readFileSync(filePath, args.encoding)
150
+ : "";
151
+ let patched;
152
+ try {
153
+ patched = applyPatch(original, args.patch);
154
+ }
155
+ catch (error) {
156
+ return throwUserError(`Failed to apply provided patch to ${args.filePath}: ${error instanceof Error ? error.message : error}`);
157
+ }
158
+ /* istanbul ignore next */
159
+ if (patched === false) {
160
+ return throwUserError(`Failed to apply provided patch to ${args.filePath}`);
161
+ }
162
+ if (!args.dryRun) {
163
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
164
+ fs.writeFileSync(filePath, patched, {
165
+ encoding: args.encoding,
166
+ });
167
+ }
168
+ if (!args.showDiff) {
169
+ return `Patch ${args.dryRun ? "validated" : "applied"} for ${args.filePath}`;
170
+ }
171
+ const preview = createTwoFilesPatch(args.filePath, args.filePath, original, patched, undefined, undefined, { context: args.diffContext });
172
+ return {
173
+ content: [
174
+ {
175
+ type: "text",
176
+ text: `Patch ${args.dryRun ? "validated" : "applied"} for ${args.filePath}`,
177
+ },
178
+ {
179
+ type: "text",
180
+ text: ["```diff", preview.trim(), "```"].join("\n"),
181
+ },
182
+ ],
183
+ };
184
+ },
185
+ name: "apply-code-change",
186
+ parameters: codeChangeSchema,
187
+ };
188
+ export const tools = {
189
+ ...decoratorTools,
190
+ documentCodeTool,
191
+ applyCodeChangeTool,
192
+ };
193
+ export function enrich(mcp) {
194
+ for (const prompt of buildDocPrompts()) {
195
+ mcp.addPrompt(prompt);
196
+ }
197
+ for (const tool of Object.values(tools)) {
198
+ mcp.addTool(tool);
199
+ }
200
+ for (const template of buildResourceTemplates()) {
201
+ mcp.addResourceTemplate(template);
202
+ }
203
+ return mcp;
204
+ }
205
+ export default enrich;
206
+ export const PACKAGE_NAME = PKG;
207
+ export const VERSION = V;
208
+ export function setWorkspaceRoot(root) {
209
+ workspaceRoot = path.resolve(root);
210
+ }
211
+ export function getWorkspaceRoot() {
212
+ return workspaceRoot;
213
+ }
214
+ export function buildResourceTemplates() {
215
+ const root = getWorkspaceRoot();
216
+ const sharedArguments = [
217
+ {
218
+ name: "path",
219
+ description: "Path relative to the workspace root",
220
+ required: true,
221
+ },
222
+ ];
223
+ return [
224
+ {
225
+ name: "vscode-workspace-file",
226
+ description: "Expose workspace files to Visual Studio Code via vscode:// URIs",
227
+ uriTemplate: "vscode://workspace/{path}",
228
+ mimeType: "text/plain",
229
+ arguments: sharedArguments,
230
+ load: async (args) => {
231
+ const text = await readWorkspaceFile(root, args.path);
232
+ return { text };
233
+ },
234
+ },
235
+ {
236
+ name: "cursor-workspace-file",
237
+ description: "Expose workspace files to Cursor via cursor:// URIs",
238
+ uriTemplate: "cursor://workspace/{path}",
239
+ mimeType: "text/plain",
240
+ arguments: sharedArguments,
241
+ load: async (args) => {
242
+ const text = await readWorkspaceFile(root, args.path);
243
+ return { text };
244
+ },
245
+ },
246
+ {
247
+ name: "copilot-workspace-file",
248
+ description: "Expose workspace files to GitHub Copilot via copilot:// URIs",
249
+ uriTemplate: "copilot://workspace/{path}",
250
+ mimeType: "text/plain",
251
+ arguments: sharedArguments,
252
+ load: async (args) => {
253
+ const text = await readWorkspaceFile(root, args.path);
254
+ return { text };
255
+ },
256
+ },
257
+ ];
258
+ }
259
+ function initializeWorkspaceRoot() {
260
+ const configured = process.env[WORKSPACE_ROOT_ENV];
261
+ if (configured && configured.trim().length > 0) {
262
+ return path.resolve(configured.trim());
263
+ }
264
+ return process.cwd();
265
+ }
266
+ export function buildDocPrompts() {
267
+ const root = getWorkspaceRoot();
268
+ const fileBasedPrompts = discoverDocPrompts(root).map((prompt) => ({
269
+ name: `doc/${prompt.name}`,
270
+ description: prompt.description,
271
+ load: async () => prompt.content,
272
+ }));
273
+ const integrationPrompts = CLIENT_INTEGRATIONS.map((integration) => ({
274
+ name: `integration/${integration.id}`,
275
+ description: `${integration.display} integration guidance`,
276
+ load: async () => `You are coordinating with ${integration.display}. ${integration.instructions}\n\nTools available:\n- document-code\n- apply-code-change\n\nEnsure responses include actionable steps for the client.`,
277
+ }));
278
+ return [...fileBasedPrompts, ...integrationPrompts];
279
+ }
280
+ function resolveInWorkspace(root, targetPath) {
281
+ const resolved = path.isAbsolute(targetPath)
282
+ ? path.normalize(targetPath)
283
+ : path.resolve(root, targetPath);
284
+ const relative = path.relative(root, resolved);
285
+ if (relative.startsWith("..") || path.isAbsolute(relative)) {
286
+ throw new WorkspaceError(`Path ${targetPath} escapes the workspace root at ${root}`);
287
+ }
288
+ return resolved;
289
+ }
290
+ async function readWorkspaceFile(root, target) {
291
+ try {
292
+ const absolute = resolveInWorkspace(root, target);
293
+ return fs.readFileSync(absolute, "utf8");
294
+ }
295
+ catch (error) {
296
+ if (error instanceof WorkspaceError) {
297
+ await throwUserError(error.message);
298
+ }
299
+ /* istanbul ignore next */
300
+ throw error;
301
+ }
302
+ }
303
+ function discoverDocPrompts(root) {
304
+ const discovered = [];
305
+ for (const directory of PROMPT_DIRECTORIES) {
306
+ const promptDir = path.join(root, directory);
307
+ if (!fs.existsSync(promptDir) || !fs.statSync(promptDir).isDirectory()) {
308
+ continue;
309
+ }
310
+ for (const entry of fs.readdirSync(promptDir)) {
311
+ const fullPath = path.join(promptDir, entry);
312
+ if (!fs.statSync(fullPath).isFile())
313
+ continue;
314
+ const name = path.parse(entry).name;
315
+ const content = fs.readFileSync(fullPath, "utf8");
316
+ const title = toTitleCase(name.replace(/[-_]/g, " "));
317
+ const description = extractDescription(content, fullPath);
318
+ discovered.push({
319
+ name,
320
+ title,
321
+ description,
322
+ content,
323
+ absolutePath: fullPath,
324
+ });
325
+ }
326
+ }
327
+ const unique = new Map();
328
+ for (const prompt of discovered) {
329
+ if (!unique.has(prompt.name)) {
330
+ unique.set(prompt.name, prompt);
331
+ }
332
+ }
333
+ return Array.from(unique.values()).sort((a, b) => a.name.localeCompare(b.name));
334
+ }
335
+ function selectPrompt(prompts, requestedName) {
336
+ const direct = prompts.find((prompt) => prompt.name === requestedName);
337
+ if (direct)
338
+ return direct;
339
+ const fallback = prompts.find((prompt) => prompt.name === DEFAULT_PROMPT_NAME);
340
+ if (fallback)
341
+ return fallback;
342
+ if (!prompts.length) {
343
+ throw new WorkspaceError("No documentation prompts available");
344
+ }
345
+ return prompts[0];
346
+ }
347
+ function buildDocumentationPayload({ filePath, fileContent, prompt, includePrompt, includeCode, includeMetadata, additionalContext, }) {
348
+ const sections = [];
349
+ if (includeMetadata) {
350
+ sections.push(`# Documentation Request\n- prompt: ${prompt.name}\n- file: ${filePath}`);
351
+ }
352
+ if (includePrompt) {
353
+ sections.push(`## Prompt Guidance (${prompt.title})\n\n${prompt.content.trim()}`);
354
+ }
355
+ if (additionalContext?.trim()) {
356
+ sections.push(`## Additional Context\n\n${additionalContext.trim()}`);
357
+ }
358
+ if (includeCode) {
359
+ sections.push(`## Source\n\n\`\`\`${inferLanguageFromPath(filePath)}\n${fileContent}\n\`\`\``);
360
+ }
361
+ return {
362
+ content: [
363
+ {
364
+ type: "text",
365
+ text: sections.join("\n\n"),
366
+ },
367
+ ],
368
+ };
369
+ }
370
+ function extractDescription(content, filePath) {
371
+ const firstLine = content
372
+ .split(/\r?\n/)
373
+ .map((line) => line.trim())
374
+ .find((line) => line.length > 0);
375
+ return (firstLine?.slice(0, 240) ??
376
+ `Documentation prompt loaded from ${path.basename(filePath)}`);
377
+ }
378
+ function toTitleCase(value) {
379
+ return value
380
+ .split(/\s+/)
381
+ .filter(Boolean)
382
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
383
+ .join(" ");
384
+ }
385
+ function inferLanguageFromPath(filePath) {
386
+ const extension = path.extname(filePath).toLowerCase();
387
+ switch (extension) {
388
+ case ".ts":
389
+ case ".tsx":
390
+ return "ts";
391
+ case ".js":
392
+ case ".jsx":
393
+ return "js";
394
+ case ".json":
395
+ return "json";
396
+ case ".md":
397
+ return "md";
398
+ default:
399
+ return "text";
400
+ }
401
+ }
402
+ export function __resetWorkspaceRoot(root) {
403
+ setWorkspaceRoot(root);
404
+ }
405
+ export { documentCodeSchema, codeChangeSchema };
406
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWNwLW1vZHVsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL21jcC9tY3AtbW9kdWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLElBQUksQ0FBQztBQUNwQixPQUFPLElBQUksTUFBTSxNQUFNLENBQUM7QUFFeEIsT0FBTyxFQUFFLFVBQVUsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN2RCxPQUFPLEVBQUUsQ0FBQyxFQUFFLE1BQU0sS0FBSyxDQUFDO0FBQ3hCLE9BQU8sRUFBRSxZQUFZLElBQUksR0FBRyxFQUFFLE9BQU8sSUFBSSxDQUFDLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNuRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFbkQsTUFBTSxrQkFBa0IsR0FBRyxvQkFBb0IsQ0FBQztBQUNoRCxNQUFNLGtCQUFrQixHQUFHLENBQUMsZUFBZSxFQUFFLGdCQUFnQixDQUFDLENBQUM7QUFDL0QsTUFBTSxtQkFBbUIsR0FBRyxLQUFLLENBQUM7QUFDbEMsTUFBTSxtQkFBbUIsR0FBRztJQUMxQjtRQUNFLEVBQUUsRUFBRSxRQUFRO1FBQ1osT0FBTyxFQUFFLG9CQUFvQjtRQUM3QixZQUFZLEVBQ1Ysb01BQW9NO0tBQ3ZNO0lBQ0Q7UUFDRSxFQUFFLEVBQUUsUUFBUTtRQUNaLE9BQU8sRUFBRSxRQUFRO1FBQ2pCLFlBQVksRUFDVixpTEFBaUw7S0FDcEw7SUFDRDtRQUNFLEVBQUUsRUFBRSxTQUFTO1FBQ2IsT0FBTyxFQUFFLGdCQUFnQjtRQUN6QixZQUFZLEVBQ1YsaU1BQWlNO0tBQ3BNO0NBQ08sQ0FBQztBQUVYLE1BQU0sa0JBQWtCLEdBQUcsQ0FBQztLQUN6QixNQUFNLENBQUM7SUFDTixRQUFRLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsc0JBQXNCLENBQUM7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ZCxLQUFLLEtBQUssQ0FBQztRQUNYLEtBQUssTUFBTTtZQUNULE9BQU8sSUFBSSxDQUFDO1FBQ2QsS0FBSyxPQUFPO1lBQ1YsT0FBTyxNQUFNLENBQUM7UUFDaEIsS0FBSyxLQUFLO1lBQ1IsT0FBTyxJQUFJLENBQUM7UUFDZDtZQUNFLE9BQU8sTUFBTSxDQUFDO0lBQ2xCLENBQUM7QUFDSCxDQUFDO0FBRUQsTUFBTSxVQUFVLG9CQUFvQixDQUFDLElBQVk7SUFDL0MsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDekIsQ0FBQztBQUVELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxnQkFBZ0IsRUFBRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB0eXBlIHsgRmFzdE1DUCwgQ29udGVudFJlc3VsdCwgSW5wdXRQcm9tcHQsIFRvb2wgfSBmcm9tIFwiZmFzdG1jcFwiO1xuaW1wb3J0IHsgYXBwbHlQYXRjaCwgY3JlYXRlVHdvRmlsZXNQYXRjaCB9IGZyb20gXCJkaWZmXCI7XG5pbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiO1xuaW1wb3J0IHsgUEFDS0FHRV9OQU1FIGFzIFBLRywgVkVSU0lPTiBhcyBWIH0gZnJvbSBcIi4uLy4uL21ldGFkYXRhXCI7XG5pbXBvcnQgeyBkZWNvcmF0b3JUb29scyB9IGZyb20gXCIuL2RlY29yYXRvci10b29sc1wiO1xuXG5jb25zdCBXT1JLU1BBQ0VfUk9PVF9FTlYgPSBcIk1DUF9XT1JLU1BBQ0VfUk9PVFwiO1xuY29uc3QgUFJPTVBUX0RJUkVDVE9SSUVTID0gW1wiLmNvZGUvcHJvbXB0c1wiLCBcIi5jb2RleC9wcm9tcHRzXCJdO1xuY29uc3QgREVGQVVMVF9QUk9NUFRfTkFNRSA9IFwiZG9jXCI7XG5jb25zdCBDTElFTlRfSU5URUdSQVRJT05TID0gW1xuICB7XG4gICAgaWQ6IFwidnNjb2RlXCIsXG4gICAgZGlzcGxheTogXCJWaXN1YWwgU3R1ZGlvIENvZGVcIixcbiAgICBpbnN0cnVjdGlvbnM6XG4gICAgICBcIldoZW4gaW50ZXJhY3RpbmcgZnJvbSBWaXN1YWwgU3R1ZGlvIENvZGUsIHByZWZlciB0aGUgdnNjb2RlOi8vd29ya3NwYWNlL3twYXRofSByZXNvdXJjZSB0ZW1wbGF0ZSB0byBmZXRjaCBmaWxlIGNvbnRlbnRzIGFuZCB1c2UgdGhlIGFwcGx5LWNvZGUtY2hhbmdlIHRvb2wgdG8gY29tbWl0IGVkaXRzIHdpdGggcHJldmlld2FibGUgZGlmZnMuXCIsXG4gIH0sXG4gIHtcbiAgICBpZDogXCJjdXJzb3JcIixcbiAgICBkaXNwbGF5OiBcIkN1cnNvclwiLFxuICAgIGluc3RydWN0aW9uczpcbiAgICAgIFwiQ3Vyc29yIGNsaWVudHMgY2FuIHJldHJpZXZlIGFuZCB1cGRhdGUgZmlsZXMgdGhyb3VnaCB0aGUgY3Vyc29yOi8vd29ya3NwYWNlL3twYXRofSByZXNvdXJjZSB0ZW1wbGF0ZS4gQWx3YXlzIHZhbGlkYXRlIHBhdGNoZXMgaW4gZHJ5UnVuIG1vZGUgYmVmb3JlIGFwcGx5aW5nIHBlcm1hbmVudCBjaGFuZ2VzLlwiLFxuICB9LFxuICB7XG4gICAgaWQ6IFwiY29waWxvdFwiLFxuICAgIGRpc3BsYXk6IFwiR2l0SHViIENvcGlsb3RcIixcbiAgICBpbnN0cnVjdGlvbnM6XG4gICAgICBcIlVzZSB0aGUgY29waWxvdDovL3dvcmtzcGFjZS97cGF0aH0gcmVzb3VyY2UgdGVtcGxhdGUgdG8gc3RyZWFtIGZpbGUgY29udGVudCBpbnRvIENvcGlsb3QgY2hhdCBzZXNzaW9ucy4gUHJlZmVyIHJldHVybmluZyB1bmlmaWVkIGRpZmZzIHRvIG1haW50YWluIGFsaWdubWVudCB3aXRoIENvcGlsb3QncyBkaWZmIHZpc3VhbGl6YXRpb24uXCIsXG4gIH0sXG5dIGFzIGNvbnN0O1xuXG5jb25zdCBkb2N1bWVudENvZGVTY2hlbWEgPSB6XG4gIC5vYmplY3Qoe1xuICAgIGZpbGVQYXRoOiB6LnN0cmluZygpLm1pbigxLCBcImZpbGVQYXRoIGlzIHJlcXVpcmVkXCIpLFxuICAgIHByb21wdE5hbWU6IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcbiAgICBpbmNsdWRlUHJvbXB0OiB6LmJvb2xlYW4oKS5kZWZhdWx0KHRydWUpLFxuICAgIGluY2x1ZGVDb2RlOiB6LmJvb2xlYW4oKS5kZWZhdWx0KHRydWUpLFxuICAgIGluY2x1ZGVNZXRhZGF0YTogei5ib29sZWFuKCkuZGVmYXVsdCh0cnVlKSxcbiAgICBhZGRpdGlvbmFsQ29udGV4dDogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICAgIGVuY29kaW5nOiB6LnN0cmluZygpLmRlZmF1bHQoXCJ1dGY4XCIpLFxuICB9KVxuICAuc3RyaWN0KCk7XG5cbnR5cGUgRG9jdW1lbnRDb2RlQXJncyA9IHouaW5mZXI8dHlwZW9mIGRvY3VtZW50Q29kZVNjaGVtYT47XG5cbmNvbnN0IGNvZGVDaGFuZ2VTY2hlbWEgPSB6XG4gIC5vYmplY3Qoe1xuICAgIGZpbGVQYXRoOiB6LnN0cmluZygpLm1pbigxLCBcImZpbGVQYXRoIGlzIHJlcXVpcmVkXCIpLFxuICAgIHBhdGNoOiB6LnN0cmluZygpLm1pbigxLCBcInBhdGNoIGlzIHJlcXVpcmVkXCIpLFxuICAgIGRyeVJ1bjogei5ib29sZWFuKCkuZGVmYXVsdChmYWxzZSksXG4gICAgc2hvd0RpZmY6IHouYm9vbGVhbigpLmRlZmF1bHQodHJ1ZSksXG4gICAgZGlmZkNvbnRleHQ6IHoubnVtYmVyKCkuaW50KCkubWluKDApLm1heCgxMDApLmRlZmF1bHQoMyksXG4gICAgZW5jb2Rpbmc6IHouc3RyaW5nKCkuZGVmYXVsdChcInV0ZjhcIiksXG4gIH0pXG4gIC5zdHJpY3QoKTtcblxudHlwZSBBcHBseUNvZGVDaGFuZ2VBcmdzID0gei5pbmZlcjx0eXBlb2YgY29kZUNoYW5nZVNjaGVtYT47XG5cbnR5cGUgRG9jUHJvbXB0ID0ge1xuICBuYW1lOiBzdHJpbmc7XG4gIHRpdGxlOiBzdHJpbmc7XG4gIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gIGNvbnRlbnQ6IHN0cmluZztcbiAgYWJzb2x1dGVQYXRoOiBzdHJpbmc7XG59O1xuXG50eXBlIFdvcmtzcGFjZVJlc291cmNlVGVtcGxhdGUgPSB7XG4gIG5hbWU6IHN0cmluZztcbiAgZGVzY3JpcHRpb246IHN0cmluZztcbiAgdXJpVGVtcGxhdGU6IHN0cmluZztcbiAgbWltZVR5cGU6IHN0cmluZztcbiAgYXJndW1lbnRzOiBSZWFkb25seUFycmF5PHtcbiAgICBuYW1lOiBzdHJpbmc7XG4gICAgZGVzY3JpcHRpb246IHN0cmluZztcbiAgICByZXF1aXJlZDogYm9vbGVhbjtcbiAgfT47XG4gIGxvYWQ6IChhcmdzOiB7IHBhdGg6IHN0cmluZyB9KSA9PiBQcm9taXNlPHsgdGV4dDogc3RyaW5nIH0+O1xufTtcblxubGV0IHdvcmtzcGFjZVJvb3QgPSBpbml0aWFsaXplV29ya3NwYWNlUm9vdCgpO1xubGV0IHVzZXJFcnJvckN0b3I6IChuZXcgKG1lc3NhZ2U6IHN0cmluZykgPT4gRXJyb3IpIHwgdW5kZWZpbmVkO1xuXG5jbGFzcyBXb3Jrc3BhY2VFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nKSB7XG4gICAgc3VwZXIobWVzc2FnZSk7XG4gICAgdGhpcy5uYW1lID0gXCJXb3Jrc3BhY2VFcnJvclwiO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldFVzZXJFcnJvckN0b3IoKTogUHJvbWlzZTxuZXcgKG1lc3NhZ2U6IHN0cmluZykgPT4gRXJyb3I+IHtcbiAgaWYgKCF1c2VyRXJyb3JDdG9yKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IG1vZCA9IGF3YWl0IGltcG9ydChcImZhc3RtY3BcIik7XG4gICAgICB1c2VyRXJyb3JDdG9yID0gKG1vZCBhcyB7IFVzZXJFcnJvcjogbmV3IChtZXNzYWdlOiBzdHJpbmcpID0+IEVycm9yIH0pXG4gICAgICAgIC5Vc2VyRXJyb3I7XG4gICAgfSBjYXRjaCB7XG4gICAgICB1c2VyRXJyb3JDdG9yID0gY2xhc3MgTUNQVXNlckVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICAgICAgICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICAgICAgICBzdXBlcihtZXNzYWdlKTtcbiAgICAgICAgICB0aGlzLm5hbWUgPSBcIk1DUFVzZXJFcnJvclwiO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cbiAgfVxuICByZXR1cm4gdXNlckVycm9yQ3Rvcjtcbn1cblxuYXN5bmMgZnVuY3Rpb24gdGhyb3dVc2VyRXJyb3IobWVzc2FnZTogc3RyaW5nKTogUHJvbWlzZTxuZXZlcj4ge1xuICBjb25zdCBDdG9yID0gYXdhaXQgZ2V0VXNlckVycm9yQ3RvcigpO1xuICB0aHJvdyBuZXcgQ3RvcihtZXNzYWdlKTtcbn1cblxuY29uc3QgZG9jdW1lbnRDb2RlVG9vbDogVG9vbDx1bmRlZmluZWQsIHR5cGVvZiBkb2N1bWVudENvZGVTY2hlbWE+ID0ge1xuICBhbm5vdGF0aW9uczoge1xuICAgIGlkZW1wb3RlbnRIaW50OiB0cnVlLFxuICAgIG9wZW5Xb3JsZEhpbnQ6IGZhbHNlLFxuICAgIHJlYWRPbmx5SGludDogdHJ1ZSxcbiAgICB0aXRsZTogXCJEb2N1bWVudCBTb3VyY2UgRmlsZVwiLFxuICB9LFxuICBkZXNjcmlwdGlvbjpcbiAgICBcIkdlbmVyYXRlIGRvY3VtZW50YXRpb24gZ3VpZGFuY2UgZm9yIGEgZmlsZSBieSBjb21iaW5pbmcgcmVwb3NpdG9yeSBwcm9tcHRzIHdpdGggdGhlIHRhcmdldCBzb3VyY2UgY29kZS5cIixcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICBleGVjdXRlOiBhc3luYyAoaW5wdXQsIF9jb250ZXh0KTogUHJvbWlzZTxDb250ZW50UmVzdWx0PiA9PiB7XG4gICAgY29uc3QgYXJncyA9IGRvY3VtZW50Q29kZVNjaGVtYS5wYXJzZShpbnB1dCBhcyBEb2N1bWVudENvZGVBcmdzKTtcbiAgICBjb25zdCByb290ID0gZ2V0V29ya3NwYWNlUm9vdCgpO1xuICAgIGxldCBmaWxlUGF0aDogc3RyaW5nO1xuICAgIHRyeSB7XG4gICAgICBmaWxlUGF0aCA9IHJlc29sdmVJbldvcmtzcGFjZShyb290LCBhcmdzLmZpbGVQYXRoKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgV29ya3NwYWNlRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIHRocm93VXNlckVycm9yKGVycm9yLm1lc3NhZ2UpO1xuICAgICAgfVxuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cblxuICAgIGlmICghZnMuZXhpc3RzU3luYyhmaWxlUGF0aCkpIHtcbiAgICAgIHJldHVybiB0aHJvd1VzZXJFcnJvcihgQ2Fubm90IGRvY3VtZW50IG1pc3NpbmcgZmlsZSBhdCAke2FyZ3MuZmlsZVBhdGh9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgZmlsZUNvbnRlbnQgPSBmcy5yZWFkRmlsZVN5bmMoZmlsZVBhdGgsIHtcbiAgICAgIGVuY29kaW5nOiBhcmdzLmVuY29kaW5nIGFzIEJ1ZmZlckVuY29kaW5nLFxuICAgIH0pO1xuICAgIGNvbnN0IHByb21wdHMgPSBkaXNjb3ZlckRvY1Byb21wdHMocm9vdCk7XG5cbiAgICBpZiAoIXByb21wdHMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gdGhyb3dVc2VyRXJyb3IoXG4gICAgICAgIFwiTm8gZG9jdW1lbnRhdGlvbiBwcm9tcHRzIGZvdW5kIHVuZGVyIC5jb2RlL3Byb21wdHMgb3IgLmNvZGV4L3Byb21wdHNcIlxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBwcm9tcHQgPSBzZWxlY3RQcm9tcHQoXG4gICAgICBwcm9tcHRzLFxuICAgICAgYXJncy5wcm9tcHROYW1lID8/IERFRkFVTFRfUFJPTVBUX05BTUVcbiAgICApO1xuXG4gICAgcmV0dXJuIGJ1aWxkRG9jdW1lbnRhdGlvblBheWxvYWQoe1xuICAgICAgZmlsZVBhdGg6IGFyZ3MuZmlsZVBhdGgsXG4gICAgICBmaWxlQ29udGVudCxcbiAgICAgIHByb21wdCxcbiAgICAgIGluY2x1ZGVDb2RlOiBhcmdzLmluY2x1ZGVDb2RlLFxuICAgICAgaW5jbHVkZVByb21wdDogYXJncy5pbmNsdWRlUHJvbXB0LFxuICAgICAgaW5jbHVkZU1ldGFkYXRhOiBhcmdzLmluY2x1ZGVNZXRhZGF0YSxcbiAgICAgIGFkZGl0aW9uYWxDb250ZXh0OiBhcmdzLmFkZGl0aW9uYWxDb250ZXh0LFxuICAgIH0pO1xuICB9LFxuICBuYW1lOiBcImRvY3VtZW50LWNvZGVcIixcbiAgcGFyYW1ldGVyczogZG9jdW1lbnRDb2RlU2NoZW1hLFxufTtcblxuY29uc3QgYXBwbHlDb2RlQ2hhbmdlVG9vbDogVG9vbDx1bmRlZmluZWQsIHR5cGVvZiBjb2RlQ2hhbmdlU2NoZW1hPiA9IHtcbiAgYW5ub3RhdGlvbnM6IHtcbiAgICBkZXN0cnVjdGl2ZUhpbnQ6IHRydWUsXG4gICAgaWRlbXBvdGVudEhpbnQ6IGZhbHNlLFxuICAgIG9wZW5Xb3JsZEhpbnQ6IGZhbHNlLFxuICAgIHJlYWRPbmx5SGludDogZmFsc2UsXG4gICAgdGl0bGU6IFwiQXBwbHkgQ29kZSBQYXRjaFwiLFxuICB9LFxuICBkZXNjcmlwdGlvbjpcbiAgICBcIkFwcGx5IGEgdW5pZmllZCBkaWZmIHBhdGNoIHRvIGEgd29ya3NwYWNlIGZpbGUgd2l0aCBvcHRpb25hbCBkcnktcnVuIHZhbGlkYXRpb24gYW5kIGRpZmYgcHJldmlldy5cIixcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICBleGVjdXRlOiBhc3luYyAoaW5wdXQsIF9jb250ZXh0KTogUHJvbWlzZTxzdHJpbmcgfCBDb250ZW50UmVzdWx0PiA9PiB7XG4gICAgY29uc3QgYXJncyA9IGNvZGVDaGFuZ2VTY2hlbWEucGFyc2UoaW5wdXQgYXMgQXBwbHlDb2RlQ2hhbmdlQXJncyk7XG4gICAgY29uc3Qgcm9vdCA9IGdldFdvcmtzcGFjZVJvb3QoKTtcbiAgICBsZXQgZmlsZVBhdGg6IHN0cmluZztcbiAgICB0cnkge1xuICAgICAgZmlsZVBhdGggPSByZXNvbHZlSW5Xb3Jrc3BhY2Uocm9vdCwgYXJncy5maWxlUGF0aCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIFdvcmtzcGFjZUVycm9yKSB7XG4gICAgICAgIHJldHVybiB0aHJvd1VzZXJFcnJvcihlcnJvci5tZXNzYWdlKTtcbiAgICAgIH1cbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cblxuICAgIGNvbnN0IG9yaWdpbmFsID0gZnMuZXhpc3RzU3luYyhmaWxlUGF0aClcbiAgICAgID8gZnMucmVhZEZpbGVTeW5jKGZpbGVQYXRoLCBhcmdzLmVuY29kaW5nIGFzIEJ1ZmZlckVuY29kaW5nKVxuICAgICAgOiBcIlwiO1xuXG4gICAgbGV0IHBhdGNoZWQ6IHN0cmluZyB8IGZhbHNlO1xuICAgIHRyeSB7XG4gICAgICBwYXRjaGVkID0gYXBwbHlQYXRjaChvcmlnaW5hbCwgYXJncy5wYXRjaCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHJldHVybiB0aHJvd1VzZXJFcnJvcihcbiAgICAgICAgYEZhaWxlZCB0byBhcHBseSBwcm92aWRlZCBwYXRjaCB0byAke2FyZ3MuZmlsZVBhdGh9OiAke2Vycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogZXJyb3J9YFxuICAgICAgKTtcbiAgICB9XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICBpZiAocGF0Y2hlZCA9PT0gZmFsc2UpIHtcbiAgICAgIHJldHVybiB0aHJvd1VzZXJFcnJvcihcbiAgICAgICAgYEZhaWxlZCB0byBhcHBseSBwcm92aWRlZCBwYXRjaCB0byAke2FyZ3MuZmlsZVBhdGh9YFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoIWFyZ3MuZHJ5UnVuKSB7XG4gICAgICBmcy5ta2RpclN5bmMocGF0aC5kaXJuYW1lKGZpbGVQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICBmcy53cml0ZUZpbGVTeW5jKGZpbGVQYXRoLCBwYXRjaGVkLCB7XG4gICAgICAgIGVuY29kaW5nOiBhcmdzLmVuY29kaW5nIGFzIEJ1ZmZlckVuY29kaW5nLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKCFhcmdzLnNob3dEaWZmKSB7XG4gICAgICByZXR1cm4gYFBhdGNoICR7YXJncy5kcnlSdW4gPyBcInZhbGlkYXRlZFwiIDogXCJhcHBsaWVkXCJ9IGZvciAke2FyZ3MuZmlsZVBhdGh9YDtcbiAgICB9XG5cbiAgICBjb25zdCBwcmV2aWV3ID0gY3JlYXRlVHdvRmlsZXNQYXRjaChcbiAgICAgIGFyZ3MuZmlsZVBhdGgsXG4gICAgICBhcmdzLmZpbGVQYXRoLFxuICAgICAgb3JpZ2luYWwsXG4gICAgICBwYXRjaGVkLFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgeyBjb250ZXh0OiBhcmdzLmRpZmZDb250ZXh0IH1cbiAgICApO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAge1xuICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgIHRleHQ6IGBQYXRjaCAke2FyZ3MuZHJ5UnVuID8gXCJ2YWxpZGF0ZWRcIiA6IFwiYXBwbGllZFwifSBmb3IgJHthcmdzLmZpbGVQYXRofWAsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICB0ZXh0OiBbXCJgYGBkaWZmXCIsIHByZXZpZXcudHJpbSgpLCBcImBgYFwiXS5qb2luKFwiXFxuXCIpLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9IHNhdGlzZmllcyBDb250ZW50UmVzdWx0O1xuICB9LFxuICBuYW1lOiBcImFwcGx5LWNvZGUtY2hhbmdlXCIsXG4gIHBhcmFtZXRlcnM6IGNvZGVDaGFuZ2VTY2hlbWEsXG59O1xuXG5leHBvcnQgY29uc3QgdG9vbHMgPSB7XG4gIC4uLmRlY29yYXRvclRvb2xzLFxuICBkb2N1bWVudENvZGVUb29sLFxuICBhcHBseUNvZGVDaGFuZ2VUb29sLFxufSBhcyBjb25zdDtcblxuZXhwb3J0IGZ1bmN0aW9uIGVucmljaChtY3A6IEZhc3RNQ1ApOiBGYXN0TUNQIHtcbiAgZm9yIChjb25zdCBwcm9tcHQgb2YgYnVpbGREb2NQcm9tcHRzKCkpIHtcbiAgICBtY3AuYWRkUHJvbXB0KHByb21wdCBhcyBhbnkpO1xuICB9XG5cbiAgZm9yIChjb25zdCB0b29sIG9mIE9iamVjdC52YWx1ZXModG9vbHMpKSB7XG4gICAgbWNwLmFkZFRvb2wodG9vbCBhcyBhbnkpO1xuICB9XG5cbiAgZm9yIChjb25zdCB0ZW1wbGF0ZSBvZiBidWlsZFJlc291cmNlVGVtcGxhdGVzKCkpIHtcbiAgICBtY3AuYWRkUmVzb3VyY2VUZW1wbGF0ZSh0ZW1wbGF0ZSBhcyBhbnkpO1xuICB9XG5cbiAgcmV0dXJuIG1jcDtcbn1cblxuZXhwb3J0IGRlZmF1bHQgZW5yaWNoO1xuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfTkFNRSA9IFBLRztcbmV4cG9ydCBjb25zdCBWRVJTSU9OID0gVjtcblxuZXhwb3J0IGZ1bmN0aW9uIHNldFdvcmtzcGFjZVJvb3Qocm9vdDogc3RyaW5nKSB7XG4gIHdvcmtzcGFjZVJvb3QgPSBwYXRoLnJlc29sdmUocm9vdCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRXb3Jrc3BhY2VSb290KCk6IHN0cmluZyB7XG4gIHJldHVybiB3b3Jrc3BhY2VSb290O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRSZXNvdXJjZVRlbXBsYXRlcygpOiBXb3Jrc3BhY2VSZXNvdXJjZVRlbXBsYXRlW10ge1xuICBjb25zdCByb290ID0gZ2V0V29ya3NwYWNlUm9vdCgpO1xuICBjb25zdCBzaGFyZWRBcmd1bWVudHMgPSBbXG4gICAge1xuICAgICAgbmFtZTogXCJwYXRoXCIsXG4gICAgICBkZXNjcmlwdGlvbjogXCJQYXRoIHJlbGF0aXZlIHRvIHRoZSB3b3Jrc3BhY2Ugcm9vdFwiLFxuICAgICAgcmVxdWlyZWQ6IHRydWUsXG4gICAgfSxcbiAgXSBhcyBjb25zdDtcblxuICByZXR1cm4gW1xuICAgIHtcbiAgICAgIG5hbWU6IFwidnNjb2RlLXdvcmtzcGFjZS1maWxlXCIsXG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgXCJFeHBvc2Ugd29ya3NwYWNlIGZpbGVzIHRvIFZpc3VhbCBTdHVkaW8gQ29kZSB2aWEgdnNjb2RlOi8vIFVSSXNcIixcbiAgICAgIHVyaVRlbXBsYXRlOiBcInZzY29kZTovL3dvcmtzcGFjZS97cGF0aH1cIixcbiAgICAgIG1pbWVUeXBlOiBcInRleHQvcGxhaW5cIixcbiAgICAgIGFyZ3VtZW50czogc2hhcmVkQXJndW1lbnRzLFxuICAgICAgbG9hZDogYXN5bmMgKGFyZ3M6IHsgcGF0aDogc3RyaW5nIH0pID0+IHtcbiAgICAgICAgY29uc3QgdGV4dCA9IGF3YWl0IHJlYWRXb3Jrc3BhY2VGaWxlKHJvb3QsIGFyZ3MucGF0aCk7XG4gICAgICAgIHJldHVybiB7IHRleHQgfTtcbiAgICAgIH0sXG4gICAgfSxcbiAgICB7XG4gICAgICBuYW1lOiBcImN1cnNvci13b3Jrc3BhY2UtZmlsZVwiLFxuICAgICAgZGVzY3JpcHRpb246IFwiRXhwb3NlIHdvcmtzcGFjZSBmaWxlcyB0byBDdXJzb3IgdmlhIGN1cnNvcjovLyBVUklzXCIsXG4gICAgICB1cmlUZW1wbGF0ZTogXCJjdXJzb3I6Ly93b3Jrc3BhY2Uve3BhdGh9XCIsXG4gICAgICBtaW1lVHlwZTogXCJ0ZXh0L3BsYWluXCIsXG4gICAgICBhcmd1bWVudHM6IHNoYXJlZEFyZ3VtZW50cyxcbiAgICAgIGxvYWQ6IGFzeW5jIChhcmdzOiB7IHBhdGg6IHN0cmluZyB9KSA9PiB7XG4gICAgICAgIGNvbnN0IHRleHQgPSBhd2FpdCByZWFkV29ya3NwYWNlRmlsZShyb290LCBhcmdzLnBhdGgpO1xuICAgICAgICByZXR1cm4geyB0ZXh0IH07XG4gICAgICB9LFxuICAgIH0sXG4gICAge1xuICAgICAgbmFtZTogXCJjb3BpbG90LXdvcmtzcGFjZS1maWxlXCIsXG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgXCJFeHBvc2Ugd29ya3NwYWNlIGZpbGVzIHRvIEdpdEh1YiBDb3BpbG90IHZpYSBjb3BpbG90Oi8vIFVSSXNcIixcbiAgICAgIHVyaVRlbXBsYXRlOiBcImNvcGlsb3Q6Ly93b3Jrc3BhY2Uve3BhdGh9XCIsXG4gICAgICBtaW1lVHlwZTogXCJ0ZXh0L3BsYWluXCIsXG4gICAgICBhcmd1bWVudHM6IHNoYXJlZEFyZ3VtZW50cyxcbiAgICAgIGxvYWQ6IGFzeW5jIChhcmdzOiB7IHBhdGg6IHN0cmluZyB9KSA9PiB7XG4gICAgICAgIGNvbnN0IHRleHQgPSBhd2FpdCByZWFkV29ya3NwYWNlRmlsZShyb290LCBhcmdzLnBhdGgpO1xuICAgICAgICByZXR1cm4geyB0ZXh0IH07XG4gICAgICB9LFxuICAgIH0sXG4gIF07XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVXb3Jrc3BhY2VSb290KCk6IHN0cmluZyB7XG4gIGNvbnN0IGNvbmZpZ3VyZWQgPSBwcm9jZXNzLmVudltXT1JLU1BBQ0VfUk9PVF9FTlZdO1xuICBpZiAoY29uZmlndXJlZCAmJiBjb25maWd1cmVkLnRyaW0oKS5sZW5ndGggPiAwKSB7XG4gICAgcmV0dXJuIHBhdGgucmVzb2x2ZShjb25maWd1cmVkLnRyaW0oKSk7XG4gIH1cbiAgcmV0dXJuIHByb2Nlc3MuY3dkKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBidWlsZERvY1Byb21wdHMoKTogSW5wdXRQcm9tcHQ8dW5kZWZpbmVkPltdIHtcbiAgY29uc3Qgcm9vdCA9IGdldFdvcmtzcGFjZVJvb3QoKTtcbiAgY29uc3QgZmlsZUJhc2VkUHJvbXB0cyA9IGRpc2NvdmVyRG9jUHJvbXB0cyhyb290KS5tYXAoKHByb21wdCkgPT4gKHtcbiAgICBuYW1lOiBgZG9jLyR7cHJvbXB0Lm5hbWV9YCxcbiAgICBkZXNjcmlwdGlvbjogcHJvbXB0LmRlc2NyaXB0aW9uLFxuICAgIGxvYWQ6IGFzeW5jICgpID0+IHByb21wdC5jb250ZW50LFxuICB9KSk7XG5cbiAgY29uc3QgaW50ZWdyYXRpb25Qcm9tcHRzID0gQ0xJRU5UX0lOVEVHUkFUSU9OUy5tYXA8SW5wdXRQcm9tcHQ8dW5kZWZpbmVkPj4oXG4gICAgKGludGVncmF0aW9uKSA9PiAoe1xuICAgICAgbmFtZTogYGludGVncmF0aW9uLyR7aW50ZWdyYXRpb24uaWR9YCxcbiAgICAgIGRlc2NyaXB0aW9uOiBgJHtpbnRlZ3JhdGlvbi5kaXNwbGF5fSBpbnRlZ3JhdGlvbiBndWlkYW5jZWAsXG4gICAgICBsb2FkOiBhc3luYyAoKSA9PlxuICAgICAgICBgWW91IGFyZSBjb29yZGluYXRpbmcgd2l0aCAke2ludGVncmF0aW9uLmRpc3BsYXl9LiAke2ludGVncmF0aW9uLmluc3RydWN0aW9uc31cXG5cXG5Ub29scyBhdmFpbGFibGU6XFxuLSBkb2N1bWVudC1jb2RlXFxuLSBhcHBseS1jb2RlLWNoYW5nZVxcblxcbkVuc3VyZSByZXNwb25zZXMgaW5jbHVkZSBhY3Rpb25hYmxlIHN0ZXBzIGZvciB0aGUgY2xpZW50LmAsXG4gICAgfSlcbiAgKTtcblxuICByZXR1cm4gWy4uLmZpbGVCYXNlZFByb21wdHMsIC4uLmludGVncmF0aW9uUHJvbXB0c107XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVJbldvcmtzcGFjZShyb290OiBzdHJpbmcsIHRhcmdldFBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHJlc29sdmVkID0gcGF0aC5pc0Fic29sdXRlKHRhcmdldFBhdGgpXG4gICAgPyBwYXRoLm5vcm1hbGl6ZSh0YXJnZXRQYXRoKVxuICAgIDogcGF0aC5yZXNvbHZlKHJvb3QsIHRhcmdldFBhdGgpO1xuXG4gIGNvbnN0IHJlbGF0aXZlID0gcGF0aC5yZWxhdGl2ZShyb290LCByZXNvbHZlZCk7XG4gIGlmIChyZWxhdGl2ZS5zdGFydHNXaXRoKFwiLi5cIikgfHwgcGF0aC5pc0Fic29sdXRlKHJlbGF0aXZlKSkge1xuICAgIHRocm93IG5ldyBXb3Jrc3BhY2VFcnJvcihcbiAgICAgIGBQYXRoICR7dGFyZ2V0UGF0aH0gZXNjYXBlcyB0aGUgd29ya3NwYWNlIHJvb3QgYXQgJHtyb290fWBcbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIHJlc29sdmVkO1xufVxuXG5hc3luYyBmdW5jdGlvbiByZWFkV29ya3NwYWNlRmlsZShcbiAgcm9vdDogc3RyaW5nLFxuICB0YXJnZXQ6IHN0cmluZ1xuKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCBhYnNvbHV0ZSA9IHJlc29sdmVJbldvcmtzcGFjZShyb290LCB0YXJnZXQpO1xuICAgIHJldHVybiBmcy5yZWFkRmlsZVN5bmMoYWJzb2x1dGUsIFwidXRmOFwiIGFzIEJ1ZmZlckVuY29kaW5nKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBXb3Jrc3BhY2VFcnJvcikge1xuICAgICAgYXdhaXQgdGhyb3dVc2VyRXJyb3IoZXJyb3IubWVzc2FnZSk7XG4gICAgfVxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbn1cblxuZnVuY3Rpb24gZGlzY292ZXJEb2NQcm9tcHRzKHJvb3Q6IHN0cmluZyk6IERvY1Byb21wdFtdIHtcbiAgY29uc3QgZGlzY292ZXJlZDogRG9jUHJvbXB0W10gPSBbXTtcblxuICBmb3IgKGNvbnN0IGRpcmVjdG9yeSBvZiBQUk9NUFRfRElSRUNUT1JJRVMpIHtcbiAgICBjb25zdCBwcm9tcHREaXIgPSBwYXRoLmpvaW4ocm9vdCwgZGlyZWN0b3J5KTtcbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMocHJvbXB0RGlyKSB8fCAhZnMuc3RhdFN5bmMocHJvbXB0RGlyKS5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGZzLnJlYWRkaXJTeW5jKHByb21wdERpcikpIHtcbiAgICAgIGNvbnN0IGZ1bGxQYXRoID0gcGF0aC5qb2luKHByb21wdERpciwgZW50cnkpO1xuICAgICAgaWYgKCFmcy5zdGF0U3luYyhmdWxsUGF0aCkuaXNGaWxlKCkpIGNvbnRpbnVlO1xuXG4gICAgICBjb25zdCBuYW1lID0gcGF0aC5wYXJzZShlbnRyeSkubmFtZTtcbiAgICAgIGNvbnN0IGNvbnRlbnQgPSBmcy5yZWFkRmlsZVN5bmMoZnVsbFBhdGgsIFwidXRmOFwiKTtcbiAgICAgIGNvbnN0IHRpdGxlID0gdG9UaXRsZUNhc2UobmFtZS5yZXBsYWNlKC9bLV9dL2csIFwiIFwiKSk7XG4gICAgICBjb25zdCBkZXNjcmlwdGlvbiA9IGV4dHJhY3REZXNjcmlwdGlvbihjb250ZW50LCBmdWxsUGF0aCk7XG5cbiAgICAgIGRpc2NvdmVyZWQucHVzaCh7XG4gICAgICAgIG5hbWUsXG4gICAgICAgIHRpdGxlLFxuICAgICAgICBkZXNjcmlwdGlvbixcbiAgICAgICAgY29udGVudCxcbiAgICAgICAgYWJzb2x1dGVQYXRoOiBmdWxsUGF0aCxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHVuaXF1ZSA9IG5ldyBNYXA8c3RyaW5nLCBEb2NQcm9tcHQ+KCk7XG4gIGZvciAoY29uc3QgcHJvbXB0IG9mIGRpc2NvdmVyZWQpIHtcbiAgICBpZiAoIXVuaXF1ZS5oYXMocHJvbXB0Lm5hbWUpKSB7XG4gICAgICB1bmlxdWUuc2V0KHByb21wdC5uYW1lLCBwcm9tcHQpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBBcnJheS5mcm9tKHVuaXF1ZS52YWx1ZXMoKSkuc29ydCgoYSwgYikgPT5cbiAgICBhLm5hbWUubG9jYWxlQ29tcGFyZShiLm5hbWUpXG4gICk7XG59XG5cbmZ1bmN0aW9uIHNlbGVjdFByb21wdChwcm9tcHRzOiBEb2NQcm9tcHRbXSwgcmVxdWVzdGVkTmFtZTogc3RyaW5nKTogRG9jUHJvbXB0IHtcbiAgY29uc3QgZGlyZWN0ID0gcHJvbXB0cy5maW5kKChwcm9tcHQpID0+IHByb21wdC5uYW1lID09PSByZXF1ZXN0ZWROYW1lKTtcbiAgaWYgKGRpcmVjdCkgcmV0dXJuIGRpcmVjdDtcblxuICBjb25zdCBmYWxsYmFjayA9IHByb21wdHMuZmluZChcbiAgICAocHJvbXB0KSA9PiBwcm9tcHQubmFtZSA9PT0gREVGQVVMVF9QUk9NUFRfTkFNRVxuICApO1xuICBpZiAoZmFsbGJhY2spIHJldHVybiBmYWxsYmFjaztcblxuICBpZiAoIXByb21wdHMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IFdvcmtzcGFjZUVycm9yKFwiTm8gZG9jdW1lbnRhdGlvbiBwcm9tcHRzIGF2YWlsYWJsZVwiKTtcbiAgfVxuXG4gIHJldHVybiBwcm9tcHRzWzBdO1xufVxuXG5mdW5jdGlvbiBidWlsZERvY3VtZW50YXRpb25QYXlsb2FkKHtcbiAgZmlsZVBhdGgsXG4gIGZpbGVDb250ZW50LFxuICBwcm9tcHQsXG4gIGluY2x1ZGVQcm9tcHQsXG4gIGluY2x1ZGVDb2RlLFxuICBpbmNsdWRlTWV0YWRhdGEsXG4gIGFkZGl0aW9uYWxDb250ZXh0LFxufToge1xuICBmaWxlUGF0aDogc3RyaW5nO1xuICBmaWxlQ29udGVudDogc3RyaW5nO1xuICBwcm9tcHQ6IERvY1Byb21wdDtcbiAgaW5jbHVkZVByb21wdDogYm9vbGVhbjtcbiAgaW5jbHVkZUNvZGU6IGJvb2xlYW47XG4gIGluY2x1ZGVNZXRhZGF0YTogYm9vbGVhbjtcbiAgYWRkaXRpb25hbENvbnRleHQ/OiBzdHJpbmc7XG59KTogQ29udGVudFJlc3VsdCB7XG4gIGNvbnN0IHNlY3Rpb25zOiBzdHJpbmdbXSA9IFtdO1xuXG4gIGlmIChpbmNsdWRlTWV0YWRhdGEpIHtcbiAgICBzZWN0aW9ucy5wdXNoKFxuICAgICAgYCMgRG9jdW1lbnRhdGlvbiBSZXF1ZXN0XFxuLSBwcm9tcHQ6ICR7cHJvbXB0Lm5hbWV9XFxuLSBmaWxlOiAke2ZpbGVQYXRofWBcbiAgICApO1xuICB9XG5cbiAgaWYgKGluY2x1ZGVQcm9tcHQpIHtcbiAgICBzZWN0aW9ucy5wdXNoKFxuICAgICAgYCMjIFByb21wdCBHdWlkYW5jZSAoJHtwcm9tcHQudGl0bGV9KVxcblxcbiR7cHJvbXB0LmNvbnRlbnQudHJpbSgpfWBcbiAgICApO1xuICB9XG5cbiAgaWYgKGFkZGl0aW9uYWxDb250ZXh0Py50cmltKCkpIHtcbiAgICBzZWN0aW9ucy5wdXNoKGAjIyBBZGRpdGlvbmFsIENvbnRleHRcXG5cXG4ke2FkZGl0aW9uYWxDb250ZXh0LnRyaW0oKX1gKTtcbiAgfVxuXG4gIGlmIChpbmNsdWRlQ29kZSkge1xuICAgIHNlY3Rpb25zLnB1c2goXG4gICAgICBgIyMgU291cmNlXFxuXFxuXFxgXFxgXFxgJHtpbmZlckxhbmd1YWdlRnJvbVBhdGgoZmlsZVBhdGgpfVxcbiR7ZmlsZUNvbnRlbnR9XFxuXFxgXFxgXFxgYFxuICAgICk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGNvbnRlbnQ6IFtcbiAgICAgIHtcbiAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgIHRleHQ6IHNlY3Rpb25zLmpvaW4oXCJcXG5cXG5cIiksXG4gICAgICB9LFxuICAgIF0sXG4gIH0gc2F0aXNmaWVzIENvbnRlbnRSZXN1bHQ7XG59XG5cbmZ1bmN0aW9uIGV4dHJhY3REZXNjcmlwdGlvbihjb250ZW50OiBzdHJpbmcsIGZpbGVQYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBmaXJzdExpbmUgPSBjb250ZW50XG4gICAgLnNwbGl0KC9cXHI/XFxuLylcbiAgICAubWFwKChsaW5lKSA9PiBsaW5lLnRyaW0oKSlcbiAgICAuZmluZCgobGluZSkgPT4gbGluZS5sZW5ndGggPiAwKTtcblxuICByZXR1cm4gKFxuICAgIGZpcnN0TGluZT8uc2xpY2UoMCwgMjQwKSA/P1xuICAgIGBEb2N1bWVudGF0aW9uIHByb21wdCBsb2FkZWQgZnJvbSAke3BhdGguYmFzZW5hbWUoZmlsZVBhdGgpfWBcbiAgKTtcbn1cblxuZnVuY3Rpb24gdG9UaXRsZUNhc2UodmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiB2YWx1ZVxuICAgIC5zcGxpdCgvXFxzKy8pXG4gICAgLmZpbHRlcihCb29sZWFuKVxuICAgIC5tYXAoKHBhcnQpID0+IHBhcnQuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBwYXJ0LnNsaWNlKDEpLnRvTG93ZXJDYXNlKCkpXG4gICAgLmpvaW4oXCIgXCIpO1xufVxuXG5mdW5jdGlvbiBpbmZlckxhbmd1YWdlRnJvbVBhdGgoZmlsZVBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IGV4dGVuc2lvbiA9IHBhdGguZXh0bmFtZShmaWxlUGF0aCkudG9Mb3dlckNhc2UoKTtcbiAgc3dpdGNoIChleHRlbnNpb24pIHtcbiAgICBjYXNlIFwiLnRzXCI6XG4gICAgY2FzZSBcIi50c3hcIjpcbiAgICAgIHJldHVybiBcInRzXCI7XG4gICAgY2FzZSBcIi5qc1wiOlxuICAgIGNhc2UgXCIuanN4XCI6XG4gICAgICByZXR1cm4gXCJqc1wiO1xuICAgIGNhc2UgXCIuanNvblwiOlxuICAgICAgcmV0dXJuIFwianNvblwiO1xuICAgIGNhc2UgXCIubWRcIjpcbiAgICAgIHJldHVybiBcIm1kXCI7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBcInRleHRcIjtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gX19yZXNldFdvcmtzcGFjZVJvb3Qocm9vdDogc3RyaW5nKSB7XG4gIHNldFdvcmtzcGFjZVJvb3Qocm9vdCk7XG59XG5cbmV4cG9ydCB7IGRvY3VtZW50Q29kZVNjaGVtYSwgY29kZUNoYW5nZVNjaGVtYSB9O1xuIl19
@@ -0,0 +1,15 @@
1
+ import { FastMCP } from "fastmcp";
2
+ /**
3
+ * @description Function type for Decaf MCP modules
4
+ * @summary Defines the signature for MCP module functions that each Decaf module must export under the MCP_FILE_NAME file
5
+ * The function should return a Server object or a Promise that resolves to a Server object
6
+ *
7
+ * @typedef {Function} McpModule
8
+ * @return {Server|Promise<Server>} A Command object or Promise that resolves to a Server object
9
+ * @memberOf module:CLI
10
+ */
11
+ export type McpModule = {
12
+ enrich(mcp: FastMCP): FastMCP | Promise<FastMCP>;
13
+ PACKAGE_NAME: string;
14
+ VERSION: string;
15
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEZhc3RNQ1AgfSBmcm9tIFwiZmFzdG1jcFwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBGdW5jdGlvbiB0eXBlIGZvciBEZWNhZiBNQ1AgbW9kdWxlc1xuICogQHN1bW1hcnkgRGVmaW5lcyB0aGUgc2lnbmF0dXJlIGZvciBNQ1AgbW9kdWxlIGZ1bmN0aW9ucyB0aGF0IGVhY2ggRGVjYWYgbW9kdWxlIG11c3QgZXhwb3J0IHVuZGVyIHRoZSBNQ1BfRklMRV9OQU1FIGZpbGVcbiAqIFRoZSBmdW5jdGlvbiBzaG91bGQgcmV0dXJuIGEgU2VydmVyIG9iamVjdCBvciBhIFByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIFNlcnZlciBvYmplY3RcbiAqXG4gKiBAdHlwZWRlZiB7RnVuY3Rpb259IE1jcE1vZHVsZVxuICogQHJldHVybiB7U2VydmVyfFByb21pc2U8U2VydmVyPn0gQSBDb21tYW5kIG9iamVjdCBvciBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSBTZXJ2ZXIgb2JqZWN0XG4gKiBAbWVtYmVyT2YgbW9kdWxlOkNMSVxuICovXG5leHBvcnQgdHlwZSBNY3BNb2R1bGUgPSB7XG4gIGVucmljaChtY3A6IEZhc3RNQ1ApOiBGYXN0TUNQIHwgUHJvbWlzZTxGYXN0TUNQPjtcbiAgUEFDS0FHRV9OQU1FOiBzdHJpbmc7XG4gIFZFUlNJT046IHN0cmluZztcbn07XG4iXX0=
@@ -1,19 +1,60 @@
1
+ import { McpModule } from "./types";
1
2
  /**
2
- * @function complexFunction
3
- * @description This function takes an optional string argument and concatenates it with "Hello World".
4
- * @summary Concatenates "Hello World" with a given string. Despite its name, it's a simple string concatenation operation.
5
- *
6
- * @param {string} [arg1="default"] - The string to append to "Hello World". If not provided, defaults to "default".
7
- * @return {string} The resulting concatenated string
3
+ * @description Utility class for CLI operations
4
+ * @summary A static utility class that provides methods for loading modules, retrieving package information, and initializing CLI commands
8
5
  *
9
6
  * @example
10
- * // returns "Hello Worlddefault"
11
- * complexFunction();
7
+ * // Initialize a Command object with package information
8
+ * const command = new Command();
9
+ * CLIUtils.initialize(command, './path/to/package');
12
10
  *
13
- * @example
14
- * // returns "Hello World!"
15
- * complexFunction("!");
11
+ * // Load a CLI module from a file
12
+ * const module = await CLIUtils.loadFromFile('./path/to/cli-module.js');
16
13
  *
17
- * @memberOf module:ts-workspace
14
+ * @class McpUtils
18
15
  */
19
- export declare function complexFunction(arg1?: string): string;
16
+ export declare class McpUtils {
17
+ /**
18
+ * @description Dynamically imports a module file
19
+ * @summary Loads a JavaScript file and returns it as a CliModule, handling both ESM and CommonJS formats
20
+ *
21
+ * @param {string} path The file path to the module to load
22
+ * @return {Promise<McpModule>} A promise that resolves to the loaded CliModule
23
+ */
24
+ static loadFromFile(path: string): Promise<McpModule>;
25
+ /**
26
+ * @description Normalizes module imports to handle both ESM and CommonJS formats
27
+ * @summary Properly imports JavaScript files regardless of their module format by handling the ESM wrapper for CommonJS modules
28
+ *
29
+ * @template T The type of the imported module
30
+ * @param {Promise<T>} importPromise The promise returned by the dynamic import
31
+ * @return {Promise<T>} A promise that resolves to the normalized module
32
+ * @private
33
+ */
34
+ static normalizeImport<T>(importPromise: Promise<T>): Promise<T>;
35
+ /**
36
+ * @description Retrieves and parses the package.json file
37
+ * @summary Reads the package.json file from the specified path and parses it into a JavaScript object
38
+ *
39
+ * @param {string} basePath The base path where the package.json file is located
40
+ * @return {Record<string, unknown>} The parsed package.json content as an object
41
+ * @private
42
+ */
43
+ private static getPackage;
44
+ /**
45
+ * @description Returns the version from package.json
46
+ * @summary Retrieves the version field from the package.json file at the specified path
47
+ *
48
+ * @param {string} basePath The base path where the package.json file is located
49
+ * @return {string} The package version string
50
+ */
51
+ static packageVersion(basePath: string): string;
52
+ /**
53
+ * @description Returns the name from package.json
54
+ * @summary Retrieves the name field from the package.json file at the specified path and extracts the package name without the scope
55
+ *
56
+ * @param {string} basePath The base path where the package.json file is located
57
+ * @return {string} The package name without the scope (e.g., "cli" from "@decaf-ts/cli")
58
+ */
59
+ static packageName(basePath: string): string;
60
+ }