diff --git a/mcp-servers/mcp-server-vscode/out/extension.js b/mcp-servers/mcp-server-vscode/out/extension.js index 4681ef9ae..8120003bb 100644 --- a/mcp-servers/mcp-server-vscode/out/extension.js +++ b/mcp-servers/mcp-server-vscode/out/extension.js @@ -10,7 +10,9 @@ import packageJson from '../package.json'; import { codeCheckerTool } from './tools/code_checker'; import { listDebugSessions, listDebugSessionsSchema, startDebugSession, startDebugSessionSchema, stopDebugSession, stopDebugSessionSchema, } from './tools/debug_tools'; import { focusEditorTool } from './tools/focus_editor'; +import { closeTerminal, closeTerminalSchema, createTerminal, createTerminalSchema, getTerminalOutput, getTerminalOutputSchema, listTerminals, listTerminalsSchema, sendTerminalText, sendTerminalTextSchema, } from './tools/terminal_tools'; import { resolvePort } from './utils/port'; +import { initTerminalOutputCapture } from './utils/terminal_output_capture'; const extensionName = 'vscode-mcp-server'; const extensionDisplayName = 'VSCode MCP Server'; export const activate = async (context) => { @@ -97,6 +99,65 @@ export const activate = async (context) => { })), }; }); + mcpServer.tool('create_terminal', dedent ` + Create a new integrated terminal in the VSCode workspace. + Optionally set a name, working directory, and an initial command to execute. + `.trim(), createTerminalSchema.shape, async (params) => { + const result = await createTerminal(params); + return { + ...result, + content: result.content.map((item) => ({ + ...item, + type: 'text', + })), + }; + }); + mcpServer.tool('list_terminals', 'List all active terminals in the workspace.', listTerminalsSchema.shape, async () => { + const result = listTerminals(); + return { + ...result, + content: result.content.map((item) => ({ type: 'text', text: JSON.stringify(item.json) })), + }; + }); + mcpServer.tool('send_terminal_text', dedent ` + Send text to an existing terminal by name. + Use this to execute commands or type input in a terminal that was previously created. + `.trim(), sendTerminalTextSchema.shape, async (params) => { + const result = await sendTerminalText(params); + return { + ...result, + content: result.content.map((item) => ({ + ...item, + type: 'text', + })), + }; + }); + mcpServer.tool('close_terminal', 'Close an active terminal by name.', closeTerminalSchema.shape, async (params) => { + const result = await closeTerminal(params); + return { + ...result, + content: result.content.map((item) => ({ + ...item, + type: 'text', + })), + }; + }); + mcpServer.tool('get_terminal_output', dedent ` + Read captured command output from a terminal. + Output is captured per-command via shell execution events. + Returns clean output without ANSI escape codes. + Requires VS Code shell integration to be active (enabled by default). + `.trim(), getTerminalOutputSchema.shape, async (params) => { + const result = await getTerminalOutput(params); + return { + ...result, + content: result.content.map((item) => ({ + ...item, + type: 'text', + })), + }; + }); + initTerminalOutputCapture(context); const app = express(); const mcpConfig = vscode.workspace.getConfiguration('mcpServer'); const port = await resolvePort(mcpConfig.get('port', 6010)); @@ -198,4 +259,4 @@ export const activate = async (context) => { }; export function deactivate() { } -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXh0ZW5zaW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2V4dGVuc2lvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFDcEUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFDN0UsT0FBTyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBQzVCLE9BQU8sT0FBOEIsTUFBTSxTQUFTLENBQUM7QUFDckQsT0FBTyxLQUFLLElBQUksTUFBTSxNQUFNLENBQUM7QUFDN0IsT0FBTyxLQUFLLE1BQU0sTUFBTSxRQUFRLENBQUM7QUFDakMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQzVDLE9BQU8sRUFBRSxDQUFDLEVBQUUsTUFBTSxLQUFLLENBQUM7QUFDeEIsT0FBTyxXQUFXLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3ZELE9BQU8sRUFDSCxpQkFBaUIsRUFDakIsdUJBQXVCLEVBQ3ZCLGlCQUFpQixFQUNqQix1QkFBdUIsRUFDdkIsZ0JBQWdCLEVBQ2hCLHNCQUFzQixHQUN6QixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUN2RCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRTNDLE1BQU0sYUFBYSxHQUFHLG1CQUFtQixDQUFDO0FBQzFDLE1BQU0sb0JBQW9CLEdBQUcsbUJBQW1CLENBQUM7QUFFakQsTUFBTSxDQUFDLE1BQU0sUUFBUSxHQUFHLEtBQUssRUFBRSxPQUFnQyxFQUFFLEVBQUU7SUFFL0QsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO0lBRzlFLGFBQWEsQ0FBQyxVQUFV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ZXIgfSBmcm9tICdAbW9kZWxjb250ZXh0cHJvdG9jb2wvc2RrL3NlcnZlci9tY3AuanMnO1xuaW1wb3J0IHsgU1NFU2VydmVyVHJhbnNwb3J0IH0gZnJvbSAnQG1vZGVsY29udGV4dHByb3RvY29sL3Nkay9zZXJ2ZXIvc3NlLmpzJztcbmltcG9ydCBkZWRlbnQgZnJvbSAnZGVkZW50JztcbmltcG9ydCBleHByZXNzLCB7IFJlcXVlc3QsIFJlc3BvbnNlIH0gZnJvbSAnZXhwcmVzcyc7XG5pbXBvcnQgKiBhcyBodHRwIGZyb20gJ2h0dHAnO1xuaW1wb3J0ICogYXMgdnNjb2RlIGZyb20gJ3ZzY29kZSc7XG5pbXBvcnQgeyBEaWFnbm9zdGljU2V2ZXJpdHkgfSBmcm9tICd2c2NvZGUnO1xuaW1wb3J0IHsgeiB9IGZyb20gJ3pvZCc7XG5pbXBvcnQgcGFja2FnZUpzb24gZnJvbSAnLi4vcGFja2FnZS5qc29uJztcbmltcG9ydCB7IGNvZGVDaGVja2VyVG9vbCB9IGZyb20gJy4vdG9vbHMvY29kZV9jaGVja2VyJztcbmltcG9ydCB7XG4gICAgbGlzdERlYnVnU2Vzc2lvbnMsXG4gICAgbGlzdERlYnVnU2Vzc2lvbnNTY2hlbWEsXG4gICAgc3RhcnREZWJ1Z1Nlc3Npb24sXG4gICAgc3RhcnREZWJ1Z1Nlc3Npb25TY2hlbWEsXG4gICAgc3RvcERlYnVnU2Vzc2lvbixcbiAgICBzdG9wRGVidWdTZXNzaW9uU2NoZW1hLFxufSBmcm9tICcuL3Rvb2xzL2RlYnVnX3Rvb2xzJztcbmltcG9ydCB7IGZvY3VzRWRpdG9yVG9vbCB9IGZyb20gJy4vdG9vbHMvZm9jdXNfZWRpdG9yJztcbmltcG9ydCB7IHJlc29sdmVQb3J0IH0gZnJvbSAnLi91dGlscy9wb3J0JztcblxuY29uc3QgZXh0ZW5zaW9uTmFtZSA9ICd2c2NvZGUtbWNwLXNlcnZlcic7XG5jb25zdCBleHRlbnNpb25EaXNwbGF5TmFtZSA9ICdWU0NvZGUgTUNQIFNlcnZlcic7XG5cbmV4cG9ydCBjb25zdCBhY3RpdmF0ZSA9IGFzeW5jIChjb250ZXh0OiB2c2NvZGUuRXh0ZW5zaW9uQ29udGV4dCkgPT4ge1xuICAgIC8vIENyZWF0ZSB0aGUgb3V0cHV0IGNoYW5uZWwgZm9yIGxvZ2dpbmdcbiAgICBjb25zdCBvdXRwdXRDaGFubmVsID0gdnNjb2RlLndpbmRvdy5jcmVhdGVPdXRwdXRDaGFubmVsKGV4dGVuc2lvbkRpc3BsYXlOYW1lKTtcblxuICAgIC8vIFdyaXRlIGFuIGluaXRpYWwgbWVzc2FnZSB0byBlbnN1cmUgdGhlIGNoYW5uZWwgYXBwZWFycyBpbiB0aGUgT3V0cHV0IGRyb3Bkb3duXG4gICAgb3V0cHV0Q2hhbm5lbC5hcHBlbmRMaW5lKGBBY3RpdmF0aW5nICR7ZXh0ZW5zaW9uRGlzcGxheU5hbWV9Li4uYCk7XG4gICAgLy8gVW5jb21tZW50IHRvIGF1dG9tYXRpY2FsbHkgc3dpdGNoIHRvIHRoZSBvdXRwdXQgdGFiIGFuZCB0aGlzIGV4dGVuc2lvbiBjaGFubmVsIG9uIGFjdGl2YXRpb25cbiAgICAvLyBvdXRwdXRDaGFubmVsLnNob3coKTtcblxuICAgIC8vIEluaXRpYWxpemUgdGhlIE1DUCBzZXJ2ZXIgaW5zdGFuY2VcbiAgICBjb25zdCBtY3BTZXJ2ZXIgPSBuZXcgTWNwU2VydmVyKHtcbiAgICAgICAgbmFtZTogZXh0ZW5zaW9uTmFtZSxcbiAgICAgICAgdmVyc2lvbjogcGFja2FnZUpzb24udmVyc2lvbixcbiAgICB9KTtcblxuICAgIC8vIFJlZ2lzdGVyIHRoZSBcImNvZGVfY2hlY2tlclwiIHRvb2wuXG4gICAgLy8gVGhpcyB0b29sIHJldHJpZXZlcyBkaWFnbm9zdGljcyBmcm9tIFZTQ29kZSdzIGxhbmd1YWdlIHNlcnZpY2VzLFxuICAgIC8vIGZpbHRlcmluZyBvdXQgZmlsZXMgd2l0aG91dCBpc3N1ZXMuXG4gICAgbWNwU2VydmVyLnRvb2woXG4gICAgICAgICdjb2RlX2NoZWNrZXInLFxuICAgICAgICBkZWRlbnRgXG4gICAgICAgICAgICBSZXRyaWV2ZSBkaWFnbm9zdGljcyBmcm9tIFZTQ29kZSdzIGxhbmd1YWdlIHNlcnZpY2VzIGZvciB0aGUgYWN0aXZlIHdvcmtzcGFjZS5cbiAgICAgICAgICAgIFVzZSB0aGlzIHRvb2wgYWZ0ZXIgbWFraW5nIGNoYW5nZXMgdG8gYW55IGNvZGUgaW4gdGhlIGZpbGVzeXN0ZW0gdG8gZW5zdXJlIG5vIG5ld1xuICAgICAgICAgICAgZXJyb3JzIHdlcmUgaW50cm9kdWNlZCwgb3Igd2hlbiByZXF1ZXN0ZWQgYnkgdGhlIHVzZXIuXG4gICAgICAgIGAudHJpbSgpLFxuICAgICAgICAvLyBQYXNzaW5nIHRoZSByYXcgc2hhcGUgb2JqZWN0IGRpcmVjdGx5XG4gICAgICAgIHtcbiAgICAgICAgICAgIHNldmVyaXR5TGV2ZWw6IHpcbiAgICAgICAgICAgICAgICAuZW51bShbJ0Vycm9yJywgJ1dhcm5pbmcnLCAnSW5mb3JtYXRpb24nLCAnSGludCddKVxuICAgICAgICAgICAgICAgIC5kZWZhdWx0KCdXYXJuaW5nJylcbiAgICAgICAgICAgICAgICAuZGVzY3JpYmUoXCJNaW5pbXVtIHNldmVyaXR5IGxldmVsIGZvciBjaGVja2luZyBpc3N1ZXM6ICdFcnJvcicsICdXYXJuaW5nJywgJ0luZm9ybWF0aW9uJywgb3IgJ0hpbnQnLlwiKSxcbiAgICAgICAgfSxcbiAgICAgICAgYXN5bmMgKHBhcmFtczogeyBzZXZlcml0eUxldmVsPzogJ0Vycm9yJyB8ICdXYXJuaW5nJyB8ICdJbmZvcm1hdGlvbicgfCAnSGludCcgfSkgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc2V2ZXJpdHlMZXZlbCA9IHBhcmFtcy5zZXZlcml0eUxldmVsXG4gICAgICAgICAgICAgICAgPyBEaWFnbm9zdGljU2V2ZXJpdHlbcGFyYW1zLnNldmVyaXR5TGV2ZWxdXG4gICAgICAgICAgICAgICAgOiBEaWFnbm9zdGljU2V2ZXJpdHkuV2FybmluZztcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvZGVDaGVja2VyVG9vbChzZXZlcml0eUxldmVsKTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgLi4ucmVzdWx0LFxuICAgICAgICAgICAgICAgIGNvbnRlbnQ6IHJlc3VsdC5jb250ZW50Lm1hcCgoYykgPT4gKHtcbiAgICAgICAgICAgICAgICAgICAgLi4uYyxcbiAgICAgICAgICAgICAgICAgICAgdGV4dDogdHlwZW9mIGMudGV4dCA9PT0gJ3N0cmluZycgPyBjLnRleHQgOiBTdHJpbmcoYy50ZXh0KSxcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ3RleHQnLFxuICAgICAgICAgICAgICAgIH0pKSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sXG4gICAgKTtcblxuICAgIC8vIFJlZ2lzdGVyICdmb2N1c19lZGl0b3InIHRvb2xcbiAgICBtY3BTZXJ2ZXIudG9vbChcbiAgICAgICAgJ2ZvY3VzX2VkaXRvcicsXG4gICAgICAgIGRlZGVudGBcbiAgICAgICAgT3BlbiB0aGUgc3BlY2lmaWVkIGZpbGUgaW4gdGhlIFZTQ29kZSBlZGl0b3IgYW5kIG5hdmlnYXRlIHRvIGEgc3BlY2lmaWMgbGluZSBhbmQgY29sdW1uLlxuICAgICAgICBVc2UgdGhpcyB0b29sIHRvIGJyaW5nIGEgZmlsZSBpbnRvIGZvY3VzIGFuZCBwb3NpdGlvbiB0aGUgZWRpdG9yJ3MgY3Vyc29yIHdoZXJlIGRlc2lyZWQuXG4gICAgICAgIE5vdGU6IFRoaXMgdG9vbCBvcGVyYXRlcyBvbiB0aGUgZWRpdG9yIHZpc3VhbCBlbnZpcm9ubWVudCBzbyB0aGF0IHRoZSB1c2VyIGNhbiBzZWUgdGhlIGZpbGUuIEl0IGRvZXMgbm90IHJldHVybiB0aGUgZmlsZSBjb250ZW50cyBpbiB0aGUgdG9vbCBjYWxsIHJlc3VsdC5cbiAgICAgICAgYC50cmltKCksXG4gICAgICAgIHtcbiAgICAgICAgICAgIGZpbGVQYXRoOiB6LnN0cmluZygpLmRlc2NyaWJlKCdUaGUgYWJzb2x1dGUgcGF0aCB0byB0aGUgZmlsZSB0byBmb2N1cyBpbiB0aGUgZWRpdG9yLicpLFxuICAgICAgICAgICAgbGluZTogei5udW1iZXIoKS5pbnQoKS5taW4oMCkuZGVmYXVsdCgwKS5kZXNjcmliZSgnVGhlIGxpbmUgbnVtYmVyIHRvIG5hdmlnYXRlIHRvIChkZWZhdWx0OiAwKS4nKSxcbiAgICAgICAgICAgIGNvbHVtbjogei5udW1iZXIoKS5pbnQoKS5taW4oMCkuZGVmYXVsdCgwKS5kZXNjcmliZSgnVGhlIGNvbHVtbiBwb3NpdGlvbiB0byBuYXZpZ2F0ZSB0byAoZGVmYXVsdDogMCkuJyksXG4gICAgICAgICAgICBzdGFydExpbmU6IHoubnVtYmVyKCkuaW50KCkubWluKDApLm9wdGlvbmFsKCkuZGVzY3JpYmUoJ1RoZSBzdGFydGluZyBsaW5lIG51bWJlciBmb3IgaGlnaGxpZ2h0aW5nLicpLFxuICAgICAgICAgICAgc3RhcnRDb2x1bW46IHoubnVtYmVyKCkuaW50KCkubWluKDApLm9wdGlvbmFsKCkuZGVzY3JpYmUoJ1RoZSBzdGFydGluZyBjb2x1bW4gbnVtYmVyIGZvciBoaWdobGlnaHRpbmcuJyksXG4gICAgICAgICAgICBlbmRMaW5lOiB6Lm51bWJlcigpLmludCgpLm1pbigwKS5vcHRpb25hbCgpLmRlc2NyaWJlKCdUaGUgZW5kaW5nIGxpbmUgbnVtYmVyIGZvciBoaWdobGlnaHRpbmcuJyksXG4gICAgICAgICAgICBlbmRDb2x1bW46IHoubnVtYmVyKCkuaW50KCkubWluKDApLm9wdGlvbmFsKCkuZGVzY3JpYmUoJ1RoZSBlbmRpbmcgY29sdW1uIG51bWJlciBmb3IgaGlnaGxpZ2h0aW5nLicpLFxuICAgICAgICB9LFxuICAgICAgICBhc3luYyAocGFyYW1zOiB7IGZpbGVQYXRoOiBzdHJpbmc7IGxpbmU/OiBudW1iZXI7IGNvbHVtbj86IG51bWJlciB9KSA9PiB7XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBmb2N1c0VkaXRvclRvb2wocGFyYW1zKTtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH0sXG4gICAgKTtcblxuICAgIC8vIEZJWE1FOiBUaGlzIGRvZXNuJ3QgcmV0dXJuIHJlc3VsdHMgeWV0XG4gICAgLy8gLy8gUmVnaXN0ZXIgJ3NlYXJjaF9zeW1ib2wnIHRvb2xcbiAgICAvLyBtY3BTZXJ2ZXIudG9vbChcbiAgICAvLyAgICAgJ3NlYXJjaF9zeW1ib2wnLFxuICAgIC8vICAgICBkZWRlbnRgXG4gICAgLy8gICAgIFNlYXJjaCBmb3IgYSBzeW1ib2wgd2l0aGluIHRoZSB3b3Jrc3BhY2UuXG4gICAgLy8gICAgIC0gVHJpZXMgdG8gcmVzb2x2ZSB0aGUgZGVmaW5pdGlvbiB2aWEgVlNDb2Rl4oCZcyBcIkdvIHRvIERlZmluaXRpb25cIi5cbiAgICAvLyAgICAgLSBJZiBub3QgZm91bmQsIHNlYXJjaGVzIHRoZSBlbnRpcmUgd29ya3NwYWNlIGZvciB0aGUgdGV4dCwgc2ltaWxhciB0byBDdHJsK1NoaWZ0K0YuXG4gICAgLy8gICAgIGAudHJpbSgpLFxuICAgIC8vICAgICB7XG4gICAgLy8gICAgICAgICBxdWVyeTogei5zdHJpbmcoKS5kZXNjcmliZSgnVGhlIHN5bWJvbCBvciB0ZXh0IHRvIHNlYXJjaCBmb3IuJyksXG4gICAgLy8gICAgICAgICB1c2VEZWZpbml0aW9uOiB6LmJvb2xlYW4oKS5kZWZhdWx0KHRydWUpLmRlc2NyaWJlKFwiV2hldGhlciB0byB1c2UgJ0dvIHRvIERlZmluaXRpb24nIGFzIHRoZSBmaXJzdCBtZXRob2QuXCIpLFxuICAgIC8vICAgICAgICAgbWF4UmVzdWx0czogei5udW1iZXIoKS5kZWZhdWx0KDUwKS5kZXNjcmliZSgnTWF4aW11bSBudW1iZXIgb2YgZ2xvYmFsIHNlYXJjaCByZXN1bHRzIHRvIHJldHVybi4nKSxcbiAgICAvLyAgICAgICAgIG9wZW5GaWxlOiB6LmJvb2xlYW4oKS5kZWZhdWx0KGZhbHNlKS5kZXNjcmliZSgnV2hldGhlciB0byBvcGVuIHRoZSBmb3VuZCBmaWxlIGluIHRoZSBlZGl0b3IuJyksXG4gICAgLy8gICAgIH0sXG4gICAgLy8gICAgIGFzeW5jIChwYXJhbXM6IHsgcXVlcnk6IHN0cmluZzsgdXNlRGVmaW5pdGlvbj86IGJvb2xlYW47IG1heFJlc3VsdHM/OiBudW1iZXI7IG9wZW5GaWxlPzogYm9vbGVhbiB9KSA9PiB7XG4gICAgLy8gICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzZWFyY2hTeW1ib2xUb29sKHBhcmFtcyk7XG4gICAgLy8gICAgICAgICByZXR1cm4ge1xuICAgIC8vICAgICAgICAgICAgIC4uLnJlc3VsdCxcbiAgICAvLyAgICAgICAgICAgICBjb250ZW50OiBbXG4gICAgLy8gICAgICAgICAgICAgICAgIHtcbiAgICAvLyAgICAgICAgICAgICAgICAgICAgIHRleHQ6IEpTT04uc3RyaW5naWZ5KHJlc3VsdCksXG4gICAgLy8gICAgICAgICAgICAgICAgICAgICB0eXBlOiAndGV4dCcsXG4gICAgLy8gICAgICAgICAgICAgICAgIH0sXG4gICAgLy8gICAgICAgICAgICAgXSxcbiAgICAvLyAgICAgICAgIH07XG4gICAgLy8gICAgIH0sXG4gICAgLy8gKTtcblxuICAgIC8vIFJlZ2lzdGVyICdsaXN0X2RlYnVnX3Nlc3Npb25zJyB0b29sXG4gICAgbWNwU2VydmVyLnRvb2woXG4gICAgICAgICdsaXN0X2RlYnVnX3Nlc3Npb25zJyxcbiAgICAgICAgJ0xpc3QgYWxsIGFjdGl2ZSBkZWJ1ZyBzZXNzaW9ucyBpbiB0aGUgd29ya3NwYWNlLicsXG4gICAgICAgIGxpc3REZWJ1Z1Nlc3Npb25zU2NoZW1hLnNoYXBlLCAvLyBObyBwYXJhbWV0ZXJzIHJlcXVpcmVkXG4gICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGxpc3REZWJ1Z1Nlc3Npb25zKCk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIC4uLnJlc3VsdCxcbiAgICAgICAgICAgICAgICBjb250ZW50OiByZXN1bHQuY29udGVudC5tYXAoKGl0ZW0pID0+ICh7IHR5cGU6ICd0ZXh0JywgdGV4dDogSlNPTi5zdHJpbmdpZnkoaXRlbS5qc29uKSB9KSksXG4gICAgICAgICAgICB9O1xuICAgICAgICB9LFxuICAgICk7XG5cbiAgICAvLyBSZWdpc3RlciAnc3RhcnRfZGVidWdfc2Vzc2lvbicgdG9vbFxuICAgIG1jcFNlcnZlci50b29sKFxuICAgICAgICAnc3RhcnRfZGVidWdfc2Vzc2lvbicsXG4gICAgICAgICdTdGFydCBhIG5ldyBkZWJ1ZyBzZXNzaW9uIHdpdGggdGhlIHByb3ZpZGVkIGNvbmZpZ3VyYXRpb24uJyxcbiAgICAgICAgc3RhcnREZWJ1Z1Nlc3Npb25TY2hlbWEuc2hhcGUsXG4gICAgICAgIGFzeW5jIChwYXJhbXMpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHN0YXJ0RGVidWdTZXNzaW9uKHBhcmFtcyk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIC4uLnJlc3VsdCxcbiAgICAgICAgICAgICAgICBjb250ZW50OiByZXN1bHQuY29udGVudC5tYXAoKGl0ZW0pID0+ICh7XG4gICAgICAgICAgICAgICAgICAgIC4uLml0ZW0sXG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICd0ZXh0JyBhcyBjb25zdCxcbiAgICAgICAgICAgICAgICB9KSksXG4gICAgICAgICAgICB9O1xuICAgICAgICB9LFxuICAgICk7XG5cbiAgICAvLyBSZWdpc3RlciAnc3RvcF9kZWJ1Z19zZXNzaW9uJyB0b29sXG5cbiAgICAvLyBSZWdpc3RlciAncmVzdGFydF9kZWJ1Z19zZXNzaW9uJyB0b29sXG4gICAgbWNwU2VydmVyLnRvb2woXG4gICAgICAgICdyZXN0YXJ0X2RlYnVnX3Nlc3Npb24nLFxuICAgICAgICAnUmVzdGFydCBhIGRlYnVnIHNlc3Npb24gYnkgc3RvcHBpbmcgaXQgYW5kIHRoZW4gc3RhcnRpbmcgaXQgd2l0aCB0aGUgcHJvdmlkZWQgY29uZmlndXJhdGlvbi4nLFxuICAgICAgICBzdGFydERlYnVnU2Vzc2lvblNjaGVtYS5zaGFwZSwgLy8gdXNpbmcgdGhlIHNhbWUgc2NoZW1hIGFzICdzdGFydF9kZWJ1Z19zZXNzaW9uJ1xuICAgICAgICBhc3luYyAocGFyYW1zKSA9PiB7XG4gICAgICAgICAgICAvLyBTdG9wIGN1cnJlbnQgc2Vzc2lvbiB1c2luZyB0aGUgcHJvdmlkZWQgc2Vzc2lvbiBuYW1lXG4gICAgICAgICAgICBhd2FpdCBzdG9wRGVidWdTZXNzaW9uKHsgc2Vzc2lvbk5hbWU6IHBhcmFtcy5jb25maWd1cmF0aW9uLm5hbWUgfSk7XG5cbiAgICAgICAgICAgIC8vIFRoZW4gc3RhcnQgYSBuZXcgZGVidWcgc2Vzc2lvbiB3aXRoIHRoZSBnaXZlbiBjb25maWd1cmF0aW9uXG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzdGFydERlYnVnU2Vzc2lvbihwYXJhbXMpO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAuLi5yZXN1bHQsXG4gICAgICAgICAgICAgICAgY29udGVudDogcmVzdWx0LmNvbnRlbnQubWFwKChpdGVtKSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICAuLi5pdGVtLFxuICAgICAgICAgICAgICAgICAgICB0eXBlOiAndGV4dCcgYXMgY29uc3QsXG4gICAgICAgICAgICAgICAgfSkpLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSxcbiAgICApO1xuICAgIG1jcFNlcnZlci50b29sKFxuICAgICAgICAnc3RvcF9kZWJ1Z19zZXNzaW9uJyxcbiAgICAgICAgJ1N0b3AgYWxsIGRlYnVnIHNlc3Npb25zIHRoYXQgbWF0Y2ggdGhlIHByb3ZpZGVkIHNlc3Npb24gbmFtZS4nLFxuICAgICAgICBzdG9wRGVidWdTZXNzaW9uU2NoZW1hLnNoYXBlLFxuICAgICAgICBhc3luYyAocGFyYW1zKSA9PiB7XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzdG9wRGVidWdTZXNzaW9uKHBhcmFtcyk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIC4uLnJlc3VsdCxcbiAgICAgICAgICAgICAgICBjb250ZW50OiByZXN1bHQuY29udGVudC5tYXAoKGl0ZW0pID0+ICh7XG4gICAgICAgICAgICAgICAgICAgIC4uLml0ZW0sXG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICd0ZXh0JyBhcyBjb25zdCxcbiAgICAgICAgICAgICAgICB9KSksXG4gICAgICAgICAgICB9O1xuICAgICAgICB9LFxuICAgICk7XG5cbiAgICAvLyBTZXQgdXAgYW4gRXhwcmVzcyBhcHAgdG8gaGFuZGxlIFNTRSBjb25uZWN0aW9uc1xuICAgIGNvbnN0IGFwcCA9IGV4cHJlc3MoKTtcbiAgICBjb25zdCBtY3BDb25maWcgPSB2c2NvZGUud29ya3NwYWNlLmdldENvbmZpZ3VyYXRpb24oJ21jcFNlcnZlcicpO1xuICAgIGNvbnN0IHBvcnQgPSBhd2FpdCByZXNvbHZlUG9ydChtY3BDb25maWcuZ2V0PG51bWJlcj4oJ3BvcnQnLCA2MDEwKSk7XG5cbiAgICBsZXQgc3NlVHJhbnNwb3J0OiBTU0VTZXJ2ZXJUcmFuc3BvcnQgfCB1bmRlZmluZWQ7XG5cbiAgICAvLyBHRVQgL3NzZSBlbmRwb2ludDogdGhlIGV4dGVybmFsIE1DUCBjbGllbnQgY29ubmVjdHMgaGVyZSAoU1NFKVxuICAgIGFwcC5nZXQoJy9zc2UnLCBhc3luYyAoX3JlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgICAgICBvdXRwdXRDaGFubmVsLmFwcGVuZExpbmUoJ1NTRSBjb25uZWN0aW9uIGluaXRpYXRlZC4uLicpO1xuICAgICAgICBzc2VUcmFuc3BvcnQgPSBuZXcgU1NFU2VydmVyVHJhbnNwb3J0KCcvbWVzc2FnZXMnLCByZXMpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgbWNwU2VydmVyLmNvbm5lY3Qoc3NlVHJhbnNwb3J0KTtcbiAgICAgICAgICAgIG91dHB1dENoYW5uZWwuYXBwZW5kTGluZSgnTUNQIFNlcnZlciBjb25uZWN0ZWQgdmlhIFNTRS4nKTtcbiAgICAgICAgICAgIG91dHB1dENoYW5uZWwuYXBwZW5kTGluZShgU1NFIFRyYW5zcG9ydCBzZXNzaW9uSWQ6ICR7c3NlVHJhbnNwb3J0LnNlc3Npb25JZH1gKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBvdXRwdXRDaGFubmVsLmFwcGVuZExpbmUoJ0Vycm9yIGNvbm5lY3RpbmcgTUNQIFNlcnZlciB2aWEgU1NFOiAnICsgZXJyKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gUE9TVCAvbWVzc2FnZXMgZW5kcG9pbnQ6IHRoZSBleHRlcm5hbCBNQ1AgY2xpZW50IHNlbmRzIG1lc3NhZ2VzIGhlcmVcbiAgICBhcHAucG9zdCgnL21lc3NhZ2VzJywgZXhwcmVzcy5qc29uKCksIGFzeW5jIChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UpID0+IHtcbiAgICAgICAgLy8gTG9nIGluIG91dHB1dCBjaGFubmVsXG4gICAgICAgIG91dHB1dENoYW5uZWwuYXBwZW5kTGluZShgUE9TVCAvbWVzc2FnZXM6IFBheWxvYWQgLSAke0pTT04uc3RyaW5naWZ5KHJlcS5ib2R5LCBudWxsLCAyKX1gKTtcblxuICAgICAgICBpZiAoc3NlVHJhbnNwb3J0KSB7XG4gICAgICAgICAgICAvLyBMb2cgdGhlIHNlc3Npb24gSUQgb2YgdGhlIHRyYW5zcG9ydCB0byBjb25maXJtIGl0cyBpbml0aWFsaXphdGlvblxuICAgICAgICAgICAgb3V0cHV0Q2hhbm5lbC5hcHBlbmRMaW5lKGBTU0UgVHJhbnNwb3J0IHNlc3Npb25JZDogJHtzc2VUcmFuc3BvcnQuc2Vzc2lvbklkfWApO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAvLyBOb3RlOiBQYXNzaW5nIHJlcS5ib2R5IHRvIGhhbmRsZVBvc3RNZXNzYWdlIGlzIGNyaXRpY2FsIGJlY2F1c2UgZXhwcmVzcy5qc29uKClcbiAgICAgICAgICAgICAgICAvLyBjb25zdW1lcyB0aGUgcmVxdWVzdCBzdHJlYW0uIFdpdGhvdXQgdGhpcywgYXR0ZW1wdGluZyB0byByZS1yZWFkIHRoZSBzdHJlYW1cbiAgICAgICAgICAgICAgICAvLyB3aXRoaW4gaGFuZGxlUG9zdE1lc3NhZ2Ugd291bGQgcmVzdWx0IGluIGEgXCJzdHJlYW0gaXMgbm90IHJlYWRhYmxlXCIgZXJyb3IuXG4gICAgICAgICAgICAgICAgYXdhaXQgc3NlVHJhbnNwb3J0LmhhbmRsZVBvc3RNZXNzYWdlKHJlcSwgcmVzLCByZXEuYm9keSk7XG4gICAgICAgICAgICAgICAgb3V0cHV0Q2hhbm5lbC5hcHBlbmRMaW5lKCdIYW5kbGVkIFBPU1QgL21lc3NhZ2VzIHN1Y2Nlc3NmdWxseS4nKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIG91dHB1dENoYW5uZWwuYXBwZW5kTGluZSgnRXJyb3IgaGFuZGxpbmcgUE9TVCAvbWVzc2FnZXM6ICcgKyBlcnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzLnN0YXR1cyg1MDApLnNlbmQoJ1NTRSBUcmFuc3BvcnQgbm90IGluaXRpYWxpemVkLicpO1xuICAgICAgICAgICAgb3V0cHV0Q2hhbm5lbC5hcHBlbmRMaW5lKCdQT1NUIC9tZXNzYWdlcyBmYWlsZWQ6IFNTRSBUcmFuc3BvcnQgbm90IGluaXRpYWxpemVkLicpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBDcmVhdGUgYW5kIHN0YXJ0IHRoZSBIVFRQIHNlcnZlclxuICAgIGNvbnN0IHNlcnZlciA9IGh0dHAuY3JlYXRlU2VydmVyKGFwcCk7XG4gICAgZnVuY3Rpb24gc3RhcnRTZXJ2ZXIocG9ydDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHNlcnZlci5saXN0ZW4ocG9ydCwgKCkgPT4ge1xuICAgICAgICAgICAgb3V0cHV0Q2hhbm5lbC5hcHBlbmRMaW5lKGBNQ1AgU1NFIFNlcnZlciBydW5uaW5nIGF0IGh0dHA6Ly8xMjcuMC4wLjE6JHtwb3J0fS9zc2VgKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gQWRkIGRpc3Bvc2FsIHRvIHNodXQgZG93biB0aGUgSFRUUCBzZXJ2ZXIgYW5kIG91dHB1dCBjaGFubmVsIG9uIGV4dGVuc2lvbiBkZWFjdGl2YXRpb25cbiAgICAgICAgY29udGV4dC5zdWJzY3JpcHRpb25zLnB1c2goe1xuICAgICAgICAgICAgZGlzcG9zZTogKCkgPT4ge1xuICAgICAgICAgICAgICAgIHNlcnZlci5jbG9zZSgpO1xuICAgICAgICAgICAgICAgIG91dHB1dENoYW5uZWwuZGlzcG9zZSgpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGNvbnN0IHN0YXJ0T25BY3RpdmF0ZSA9IG1jcENvbmZpZy5nZXQ8Ym9vbGVhbj4oJ3N0YXJ0T25BY3RpdmF0ZScsIHRydWUpO1xuICAgIGlmIChzdGFydE9uQWN0aXZhdGUpIHtcbiAgICAgICAgc3RhcnRTZXJ2ZXIocG9ydCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgb3V0cHV0Q2hhbm5lbC5hcHBlbmRMaW5lKCdNQ1AgU2VydmVyIHN0YXJ0dXAgZGlzYWJsZWQgYnkgY29uZmlndXJhdGlvbi4nKTtcbiAgICB9XG5cbiAgICAvLyBDT01NQU5EIFBBTEVUVEUgQ09NTUFORDogU3RvcCB0aGUgTUNQIFNlcnZlclxuICAgIGNvbnRleHQuc3Vic2NyaXB0aW9ucy5wdXNoKFxuICAgICAgICB2c2NvZGUuY29tbWFuZHMucmVnaXN0ZXJDb21tYW5kKCdtY3BTZXJ2ZXIuc3RvcFNlcnZlcicsICgpID0+IHtcbiAgICAgICAgICAgIGlmICghc2VydmVyLmxpc3RlbmluZykge1xuICAgICAgICAgICAgICAgIHZzY29kZS53aW5kb3cuc2hvd1dhcm5pbmdNZXNzYWdlKCdNQ1AgU2VydmVyIGlzIG5vdCBydW5uaW5nLicpO1xuICAgICAgICAgICAgICAgIG91dHB1dENoYW5uZWwuYXBwZW5kTGluZSgnQXR0ZW1wdGVkIHRvIHN0b3AgdGhlIE1DUCBTZXJ2ZXIsIGJ1dCBpdCBpcyBub3QgcnVubmluZy4nKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZXJ2ZXIuY2xvc2UoKCkgPT4ge1xuICAgICAgICAgICAgICAgIG91dHB1dENoYW5uZWwuYXBwZW5kTGluZSgnTUNQIFNlcnZlciBzdG9wcGVkLicpO1xuICAgICAgICAgICAgICAgIHZzY29kZS53aW5kb3cuc2hvd0luZm9ybWF0aW9uTWVzc2FnZSgnTUNQIFNlcnZlciBzdG9wcGVkLicpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pLFxuICAgICk7XG5cbiAgICAvLyBDT01NQU5EIFBBTEVUVEUgQ09NTUFORDogU3RhcnQgdGhlIE1DUCBTZXJ2ZXJcbiAgICBjb250ZXh0LnN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgICAgdnNjb2RlLmNvbW1hbmRzLnJlZ2lzdGVyQ29tbWFuZCgnbWNwU2VydmVyLnN0YXJ0U2VydmVyJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHNlcnZlci5saXN0ZW5pbmcpIHtcbiAgICAgICAgICAgICAgICB2c2NvZGUud2luZG93LnNob3dXYXJuaW5nTWVzc2FnZSgnTUNQIFNlcnZlciBpcyBhbHJlYWR5IHJ1bm5pbmcuJyk7XG4gICAgICAgICAgICAgICAgb3V0cHV0Q2hhbm5lbC5hcHBlbmRMaW5lKCdBdHRlbXB0ZWQgdG8gc3RhcnQgdGhlIE1DUCBTZXJ2ZXIsIGJ1dCBpdCBpcyBhbHJlYWR5IHJ1bm5pbmcuJyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbmV3UG9ydCA9IGF3YWl0IHJlc29sdmVQb3J0KG1jcENvbmZpZy5nZXQ8bnVtYmVyPigncG9ydCcsIDYwMTApKTtcbiAgICAgICAgICAgIHN0YXJ0U2VydmVyKG5ld1BvcnQpO1xuICAgICAgICAgICAgb3V0cHV0Q2hhbm5lbC5hcHBlbmRMaW5lKGBNQ1AgU2VydmVyIHN0YXJ0ZWQgb24gcG9ydCAke25ld1BvcnR9LmApO1xuICAgICAgICAgICAgdnNjb2RlLndpbmRvdy5zaG93SW5mb3JtYXRpb25NZXNzYWdlKGBNQ1AgU2VydmVyIHN0YXJ0ZWQgb24gcG9ydCAke25ld1BvcnR9LmApO1xuICAgICAgICB9KSxcbiAgICApO1xuXG4gICAgLy8gQ09NTUFORCBQQUxFVFRFIENPTU1BTkQ6IFNldCB0aGUgTUNQIHNlcnZlciBwb3J0IGFuZCByZXN0YXJ0IHRoZSBzZXJ2ZXJcbiAgICBjb250ZXh0LnN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgICAgdnNjb2RlLmNvbW1hbmRzLnJlZ2lzdGVyQ29tbWFuZCgnbWNwU2VydmVyLnNldFBvcnQnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBuZXdQb3J0SW5wdXQgPSBhd2FpdCB2c2NvZGUud2luZG93LnNob3dJbnB1dEJveCh7XG4gICAgICAgICAgICAgICAgcHJvbXB0OiAnRW50ZXIgbmV3IHBvcnQgbnVtYmVyIGZvciB0aGUgTUNQIFNlcnZlcjonLFxuICAgICAgICAgICAgICAgIHZhbHVlOiBTdHJpbmcocG9ydCksXG4gICAgICAgICAgICAgICAgdmFsaWRhdGVJbnB1dDogKGlucHV0KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG51bSA9IE51bWJlcihpbnB1dCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc05hTihudW0pIHx8IG51bSA8IDEgfHwgbnVtID4gNjU1MzUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnUGxlYXNlIGVudGVyIGEgdmFsaWQgcG9ydCBudW1iZXIgKDEtNjU1MzUpLic7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKG5ld1BvcnRJbnB1dCAmJiBuZXdQb3J0SW5wdXQudHJpbSgpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdQb3J0ID0gTnVtYmVyKG5ld1BvcnRJbnB1dCk7XG4gICAgICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSBjb25maWd1cmF0aW9uIHNvIHRoYXQgc3Vic2VxdWVudCBzdGFydHVwcyB1c2UgdGhlIG5ldyBwb3J0XG4gICAgICAgICAgICAgICAgYXdhaXQgdnNjb2RlLndvcmtzcGFjZVxuICAgICAgICAgICAgICAgICAgICAuZ2V0Q29uZmlndXJhdGlvbignbWNwU2VydmVyJylcbiAgICAgICAgICAgICAgICAgICAgLnVwZGF0ZSgncG9ydCcsIG5ld1BvcnQsIHZzY29kZS5Db25maWd1cmF0aW9uVGFyZ2V0Lkdsb2JhbCk7XG4gICAgICAgICAgICAgICAgLy8gUmVzdGFydCB0aGUgc2VydmVyOiBjbG9zZSBleGlzdGluZyBzZXJ2ZXIgYW5kIHN0YXJ0IGEgbmV3IG9uZVxuICAgICAgICAgICAgICAgIHNlcnZlci5jbG9zZSgpO1xuICAgICAgICAgICAgICAgIHN0YXJ0U2VydmVyKG5ld1BvcnQpO1xuICAgICAgICAgICAgICAgIG91dHB1dENoYW5uZWwuYXBwZW5kTGluZShgTUNQIFNlcnZlciByZXN0YXJ0ZWQgb24gcG9ydCAke25ld1BvcnR9YCk7XG4gICAgICAgICAgICAgICAgdnNjb2RlLndpbmRvdy5zaG93SW5mb3JtYXRpb25NZXNzYWdlKGBNQ1AgU2VydmVyIHJlc3RhcnRlZCBvbiBwb3J0ICR7bmV3UG9ydH1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSksXG4gICAgKTtcblxuICAgIG91dHB1dENoYW5uZWwuYXBwZW5kTGluZShgJHtleHRlbnNpb25EaXNwbGF5TmFtZX0gYWN0aXZhdGVkLmApO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGRlYWN0aXZhdGUoKSB7XG4gICAgLy8gQ2xlYW4tdXAgaXMgbWFuYWdlZCBieSB0aGUgZGlzcG9zYWJsZXMgYWRkZWQgaW4gdGhlIGFjdGl2YXRlIG1ldGhvZC5cbn1cbiJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXh0ZW5zaW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2V4dGVuc2lvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFDcEUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFDN0UsT0FBTyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBQzVCLE9BQU8sT0FBOEIsTUFBTSxTQUFTLENBQUM7QUFDckQsT0FBTyxLQUFLLElBQUksTUFBTSxNQUFNLENBQUM7QUFDN0IsT0FBTyxLQUFLLE1BQU0sTUFBTSxRQUFRLENBQUM7QUFDakMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQzVDLE9BQU8sRUFBRSxDQUFDLEVBQUUsTUFBTSxLQUFLLENBQUM7QUFDeEIsT0FBTyxXQUFXLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3ZELE9BQU8sRUFDSCxpQkFBaUIsRUFDakIsdUJBQXVCLEVBQ3ZCLGlCQUFpQixFQUNqQix1QkFBdUIsRUFDdkIsZ0JBQWdCLEVBQ2hCLHNCQUFzQixHQUN6QixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUN2RCxPQUFPLEVBQ0gsYUFBYSxFQUNiLG1CQUFtQixFQUNuQixjQUFjLEVBQ2Qsb0JBQW9CLEVBQ3BCLGlCQUFpQixFQUNqQix1QkFBdUIsRUFDdkIsYUFBYSxFQUNiLG1CQUFtQixFQUNuQixnQkFBZ0IsRUFDaEIsc0JBQXNCLEdBQ3pCLE1BQU0sd0JBQXdCLENBQUM7QUFDaEMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUMzQyxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUU1RSxNQUFNLGFBQWEs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LE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDcEYsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUNMLENBQUM7SUFFRixhQUFhLENBQUMsVUFBVSxDQUFDLEdBQUcsb0JBQW9CLGFBQWEsQ0FBQyxDQUFDO0FBQ25FLENBQUMsQ0FBQztBQUVGLE1BQU0sVUFBVSxVQUFVO0FBRTFCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBNY3BTZXJ2ZXIgfSBmcm9tICdAbW9kZWxjb250ZXh0cHJvdG9jb2wvc2RrL3NlcnZlci9tY3AuanMnO1xuaW1wb3J0IHsgU1NFU2VydmVyVHJhbnNwb3J0IH0gZnJvbSAnQG1vZGVsY29udGV4dHByb3RvY29sL3Nkay9zZXJ2ZXIvc3NlLmpzJztcbmltcG9ydCBkZWRlbnQgZnJvbSAnZGVkZW50JztcbmltcG9ydCBleHByZXNzLCB7IFJlcXVlc3QsIFJlc3BvbnNlIH0gZnJvbSAnZXhwcmVzcyc7XG5pbXBvcnQgKiBhcyBodHRwIGZyb20gJ2h0dHAnO1xuaW1wb3J0ICogYXMgdnNjb2RlIGZyb20gJ3ZzY29kZSc7XG5pbXBvcnQgeyBEaWFnbm9zdGljU2V2ZXJpdHkgfSBmcm9tICd2c2NvZGUnO1xuaW1wb3J0IHsgeiB9IGZyb20gJ3pvZCc7XG5pbXBvcnQgcGFja2FnZUpzb24gZnJvbSAnLi4vcGFja2FnZS5qc29uJztcbmltcG9ydCB7IGNvZGVDaGVja2VyVG9vbCB9IGZyb20gJy4vdG9vbHMvY29kZV9jaGVja2VyJztcbmltcG9ydCB7XG4gICAgbGlzdERlYnVnU2Vzc2lvbnMsXG4gICAgbGlzdERlYnVnU2Vzc2lvbnNTY2hlbWEsXG4gICAgc3RhcnREZWJ1Z1Nlc3Npb24sXG4gICAgc3RhcnREZWJ1Z1Nlc3Npb25TY2hlbWEsXG4gICAgc3RvcERlYnVnU2Vzc2lvbixcbiAgICBzdG9wRGVidWdTZXNzaW9uU2NoZW1hLFxufSBmcm9tICcuL3Rvb2xzL2RlYnVnX3Rvb2xzJztcbmltcG9ydCB7IGZvY3VzRWRpdG9yVG9vbCB9IGZyb20gJy4vdG9vbHMvZm9jdXNfZWRpdG9yJztcbmltcG9ydCB7XG4gICAgY2xvc2VUZXJtaW5hbCxcbiAgICBjbG9zZVRlcm1pbmFsU2NoZW1hLFxuICAgIGNyZWF0ZVRlcm1pbmFsLFxuICAgIGNyZWF0ZVRlcm1pbmFsU2NoZW1hLFxuICAgIGdldFRlcm1pbmFsT3V0cHV0LFxuICAgIGdldFRlcm1pbmFsT3V0cHV0U2NoZW1hLFxuICAgIGxpc3RUZXJtaW5hbHMsXG4gICAgbGlzdFRlcm1pbmFsc1NjaGVtYSxcbiAgICBzZW5kVGVybWluYWxUZXh0LFxuICAgIHNlbmRUZXJtaW5hbFRleHRTY2hlbWEsXG59IGZyb20gJy4vdG9vbHMvdGVybWluYWxfdG9vbHMnO1xuaW1wb3J0IHsgcmVzb2x2ZVBvcnQgfSBmcm9tICcuL3V0aWxzL3BvcnQnO1xuaW1wb3J0IHsgaW5pdFRlcm1pbmFsT3V0cHV0Q2FwdHVyZSB9IGZyb20gJy4vdXRpbHMvdGVybWluYWxfb3V0cHV0X2NhcHR1cmUnO1xuXG5jb25zdCBleHRlbnNpb25OYW1lID0gJ3ZzY29kZS1tY3Atc2VydmVyJztcbmNvbnN0IGV4dGVuc2lvbkRpc3BsYXlOYW1lID0gJ1ZTQ29kZSBNQ1AgU2VydmVyJztcblxuZXhwb3J0IGNvbnN0IGFjdGl2YXRlID0gYXN5bmMgKGNvbnRleHQ6IHZzY29kZS5FeHRlbnNpb25Db250ZXh0KSA9PiB7XG4gICAgLy8gQ3JlYXRlIHRoZSBvdXRwdXQgY2hhbm5lbCBmb3IgbG9nZ2luZ1xuICAgIGNvbnN0IG91dHB1dENoYW5uZWwgPSB2c2NvZGUud2luZG93LmNyZWF0ZU91dHB1dENoYW5uZWwoZXh0ZW5zaW9uRGlzcGxheU5hbWUpO1xuXG4gICAgLy8gV3JpdGUgYW4gaW5pdGlhbCBtZXNzYWdlIHRvIGVuc3VyZSB0aGUgY2hhbm5lbCBhcHBlYXJzIGluIHRoZSBPdXRwdXQgZHJvcGRvd25cbiAgICBvdXRwdXRDaGFubmVsLmFwcGVuZExpbmUoYEFjdGl2YXRpbmcgJHtleHRlbnNpb25EaXNwbGF5TmFtZX0uLi5gKTtcbiAgICAvLyBVbmNvbW1lbnQgdG8gYXV0b21hdGljYWxseSBzd2l0Y2ggdG8gdGhlIG91dHB1dCB0YWIgYW5kIHRoaXMgZXh0ZW5zaW9uIGNoYW5uZWwgb24gYWN0aXZhdGlvblxuICAgIC8vIG91dHB1dENoYW5uZWwuc2hvdygpO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSB0aGUgTUNQIHNlcnZlciBpbnN0YW5jZVxuICAgIGNvbnN0IG1jcFNlcnZlciA9IG5ldyBNY3BTZXJ2ZXIoe1xuICAgICAgICBuYW1lOiBleHRlbnNpb25OYW1lLFxuICAgICAgICB2ZXJzaW9uOiBwYWNrYWdlSnNvbi52ZXJzaW9uLFxuICAgIH0pO1xuXG4gICAgLy8gUmVnaXN0ZXIgdGhlIFwiY29kZV9jaGVja2VyXCIgdG9vbC5cbiAgICAvLyBUaGlzIHRvb2wgcmV0cmlldmVzIGRpYWdub3N0aWNzIGZyb20gVlNDb2RlJ3MgbGFuZ3VhZ2Ugc2VydmljZXMsXG4gICAgLy8gZmlsdGVyaW5nIG91dCBmaWxlcyB3aXRob3V0IGlzc3Vlcy5cbiAgICBtY3BTZXJ2ZXIudG9vbChcbiAgICAgICAgJ2NvZGVfY2hlY2tlcicsXG4gICAgICAgIGRlZGVudGBcbiAgICAgICAgICAgIFJldHJpZXZlIGRpYWdub3N0aWNzIGZyb20gVlNDb2RlJ3MgbGFuZ3VhZ2Ugc2VydmljZXMgZm9yIHRoZSBhY3RpdmUgd29ya3NwYWNlLlxuICAgICAgICAgICAgVXNlIHRoaXMgdG9vbCBhZnRlciBtYWtpbmcgY2hhbmdlcyB0byBhbnkgY29kZSBpbiB0aGUgZmlsZXN5c3RlbSB0byBlbnN1cmUgbm8gbmV3XG4gICAgICAgICAgICBlcnJvcnMgd2VyZSBpbnRyb2R1Y2VkLCBvciB3aGVuIHJlcXVlc3RlZCBieSB0aGUgdXNlci5cbiAgICAgICAgYC50cmltKCksXG4gICAgICAgIC8vIFBhc3NpbmcgdGhlIHJhdyBzaGFwZSBvYmplY3QgZGlyZWN0bHlcbiAgICAgICAge1xuICAgICAgICAgICAgc2V2ZXJpdHlMZXZlbDogelxuICAgICAgICAgICAgICAgIC5lbnVtKFsnRXJyb3InLCAnV2FybmluZycsICdJbmZvcm1hdGlvbicsICdIaW50J10pXG4gICAgICAgICAgICAgICAgLmRlZmF1bHQoJ1dhcm5pbmcnKVxuICAgICAgICAgICAgICAgIC5kZXNjcmliZShcIk1pbmltdW0gc2V2ZXJpdHkgbGV2ZWwgZm9yIGNoZWNraW5nIGlzc3VlczogJ0Vycm9yJywgJ1dhcm5pbmcnLCAnSW5mb3JtYXRpb24nLCBvciAnSGludCcuXCIpLFxuICAgICAgICB9LFxuICAgICAgICBhc3luYyAocGFyYW1zOiB7IHNldmVyaXR5TGV2ZWw/OiAnRXJyb3InIHwgJ1dhcm5pbmcnIHwgJ0luZm9ybWF0aW9uJyB8ICdIaW50JyB9KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBzZXZlcml0eUxldmVsID0gcGFyYW1zLnNldmVyaXR5TGV2ZWxcbiAgICAgICAgICAgICAgICA/IERpYWdub3N0aWNTZXZlcml0eVtwYXJhbXMuc2V2ZXJpdHlMZXZlbF1cbiAgICAgICAgICAgICAgICA6IERpYWdub3N0aWNTZXZlcml0eS5XYXJuaW5nO1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29kZUNoZWNrZXJUb29sKHNldmVyaXR5TGV2ZWwpO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAuLi5yZXN1bHQsXG4gICAgICAgICAgICAgICAgY29udGVudDogcmVzdWx0LmNvbnRlbnQubWFwKChjKSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICAuLi5jLFxuICAgICAgICAgICAgICAgICAgICB0ZXh0OiB0eXBlb2YgYy50ZXh0ID09PSAnc3RyaW5nJyA/IGMudGV4dCA6IFN0cmluZyhjLnRleHQpLFxuICAgICAgICAgICAgICAgICAgICB0eXBlOiAndGV4dCcsXG4gICAgICAgICAgICAgICAgfSkpLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSxcbiAgICApO1xuXG4gICAgLy8gUmVnaXN0ZXIgJ2ZvY3VzX2VkaXRvcicgdG9vbFxuICAgIG1jcFNlcnZlci50b29sKFxuICAgICAgICAnZm9jdXNfZWRpdG9yJyxcbiAgICAgICAgZGVkZW50YFxuICAgICAgICBPcGVuIHRoZSBzcGVjaWZpZWQgZmlsZSBpbiB0aGUgVlNDb2RlIGVkaXRvciBhbmQgbmF2aWdhdGUgdG8gYSBzcGVjaWZpYyBsaW5lIGFuZCBjb2x1bW4uXG4gICAgICAgIFVzZSB0aGlzIHRvb2wgdG8gYnJpbmcgYSBmaWxlIGludG8gZm9jdXMgYW5kIHBvc2l0aW9uIHRoZSBlZGl0b3IncyBjdXJzb3Igd2hlcmUgZGVzaXJlZC5cbiAgICAgICAgTm90ZTogVGhpcyB0b29sIG9wZXJhdGVzIG9uIHRoZSBlZGl0b3IgdmlzdWFsIGVudmlyb25tZW50IHNvIHRoYXQgdGhlIHVzZXIgY2FuIHNlZSB0aGUgZmlsZS4gSXQgZG9lcyBub3QgcmV0dXJuIHRoZSBmaWxlIGNvbnRlbnRzIGluIHRoZSB0b29sIGNhbGwgcmVzdWx0LlxuICAgICAgICBgLnRyaW0oKSxcbiAgICAgICAge1xuICAgICAgICAgICAgZmlsZVBhdGg6IHouc3RyaW5nKCkuZGVzY3JpYmUoJ1RoZSBhYnNvbHV0ZSBwYXRoIHRvIHRoZSBmaWxlIHRvIGZvY3VzIGluIHRoZSBlZGl0b3IuJyksXG4gICAgICAgICAgICBsaW5lOiB6Lm51bWJlcigpLmludCgpLm1pbigwKS5kZWZhdWx0KDApLmRlc2NyaWJlKCdUaGUgbGluZSBudW1iZXIgdG8gbmF2aWdhdGUgdG8gKGRlZmF1bHQ6IDApLicpLFxuICAgICAgICAgICAgY29sdW1uOiB6Lm51bWJlcigpLmludCgpLm1pbigwKS5kZWZhdWx0KDApLmRlc2NyaWJlKCdUaGUgY29sdW1uIHBvc2l0aW9uIHRvIG5hdmlnYXRlIHRvIChkZWZhdWx0OiAwKS4nKSxcbiAgICAgICAgICAgIHN0YXJ0TGluZTogei5udW1iZXIoKS5pbnQoKS5taW4oMCkub3B0aW9uYWwoKS5kZXNjcmliZSgnVGhlIHN0YXJ0aW5nIGxpbmUgbnVtYmVyIGZvciBoaWdobGlnaHRpbmcuJyksXG4gICAgICAgICAgICBzdGFydENvbHVtbjogei5udW1iZXIoKS5pbnQoKS5taW4oMCkub3B0aW9uYWwoKS5kZXNjcmliZSgnVGhlIHN0YXJ0aW5nIGNvbHVtbiBudW1iZXIgZm9yIGhpZ2hsaWdodGluZy4nKSxcbiAgICAgICAgICAgIGVuZExpbmU6IHoubnVtYmVyKCkuaW50KCkubWluKDApLm9wdGlvbmFsKCkuZGVzY3JpYmUoJ1RoZSBlbmRpbmcgbGluZSBudW1iZXIgZm9yIGhpZ2hsaWdodGluZy4nKSxcbiAgICAgICAgICAgIGVuZENvbHVtbjogei5udW1iZXIoKS5pbnQoKS5taW4oMCkub3B0aW9uYWwoKS5kZXNjcmliZSgnVGhlIGVuZGluZyBjb2x1bW4gbnVtYmVyIGZvciBoaWdobGlnaHRpbmcuJyksXG4gICAgICAgIH0sXG4gICAgICAgIGFzeW5jIChwYXJhbXM6IHsgZmlsZVBhdGg6IHN0cmluZzsgbGluZT86IG51bWJlcjsgY29sdW1uPzogbnVtYmVyIH0pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGZvY3VzRWRpdG9yVG9vbChwYXJhbXMpO1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfSxcbiAgICApO1xuXG4gICAgLy8gRklYTUU6IFRoaXMgZG9lc24ndCByZXR1cm4gcmVzdWx0cyB5ZXRcbiAgICAvLyAvLyBSZWdpc3RlciAnc2VhcmNoX3N5bWJvbCcgdG9vbFxuICAgIC8vIG1jcFNlcnZlci50b29sKFxuICAgIC8vICAgICAnc2VhcmNoX3N5bWJvbCcsXG4gICAgLy8gICAgIGRlZGVudGBcbiAgICAvLyAgICAgU2VhcmNoIGZvciBhIHN5bWJvbCB3aXRoaW4gdGhlIHdvcmtzcGFjZS5cbiAgICAvLyAgICAgLSBUcmllcyB0byByZXNvbHZlIHRoZSBkZWZpbml0aW9uIHZpYSBWU0NvZGXigJlzIFwiR28gdG8gRGVmaW5pdGlvblwiLlxuICAgIC8vICAgICAtIElmIG5vdCBmb3VuZCwgc2VhcmNoZXMgdGhlIGVudGlyZSB3b3Jrc3BhY2UgZm9yIHRoZSB0ZXh0LCBzaW1pbGFyIHRvIEN0cmwrU2hpZnQrRi5cbiAgICAvLyAgICAgYC50cmltKCksXG4gICAgLy8gICAgIHtcbiAgICAvLyAgICAgICAgIHF1ZXJ5OiB6LnN0cmluZygpLmRlc2NyaWJlKCdUaGUgc3ltYm9sIG9yIHRleHQgdG8gc2VhcmNoIGZvci4nKSxcbiAgICAvLyAgICAgICAgIHVzZURlZmluaXRpb246IHouYm9vbGVhbigpLmRlZmF1bHQodHJ1ZSkuZGVzY3JpYmUoXCJXaGV0aGVyIHRvIHVzZSAnR28gdG8gRGVmaW5pdGlvbicgYXMgdGhlIGZpcnN0IG1ldGhvZC5cIiksXG4gICAgLy8gICAgICAgICBtYXhSZXN1bHRzOiB6Lm51bWJlcigpLmRlZmF1bHQoNTApLmRlc2NyaWJlKCdNYXhpbXVtIG51bWJlciBvZiBnbG9iYWwgc2VhcmNoIHJlc3VsdHMgdG8gcmV0dXJuLicpLFxuICAgIC8vICAgICAgICAgb3BlbkZpbGU6IHouYm9vbGVhbigpLmRlZmF1bHQoZmFsc2UpLmRlc2NyaWJlKCdXaGV0aGVyIHRvIG9wZW4gdGhlIGZvdW5kIGZpbGUgaW4gdGhlIGVkaXRvci4nKSxcbiAgICAvLyAgICAgfSxcbiAgICAvLyAgICAgYXN5bmMgKHBhcmFtczogeyBxdWVyeTogc3RyaW5nOyB1c2VEZWZpbml0aW9uPzogYm9vbGVhbjsgbWF4UmVzdWx0cz86IG51bWJlcjsgb3BlbkZpbGU/OiBib29sZWFuIH0pID0+IHtcbiAgICAvLyAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHNlYXJjaFN5bWJvbFRvb2wocGFyYW1zKTtcbiAgICAvLyAgICAgICAgIHJldHVybiB7XG4gICAgLy8gICAgICAgICAgICAgLi4ucmVzdWx0LFxuICAgIC8vICAgICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAvLyAgICAgICAgICAgICAgICAge1xuICAgIC8vICAgICAgICAgICAgICAgICAgICAgdGV4dDogSlNPTi5zdHJpbmdpZnkocmVzdWx0KSxcbiAgICAvLyAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICd0ZXh0JyxcbiAgICAvLyAgICAgICAgICAgICAgICAgfSxcbiAgICAvLyAgICAgICAgICAgICBdLFxuICAgIC8vICAgICAgICAgfTtcbiAgICAvLyAgICAgfSxcbiAgICAvLyApO1xuXG4gICAgLy8gUmVnaXN0ZXIgJ2xpc3RfZGVidWdfc2Vzc2lvbnMnIHRvb2xcbiAgICBtY3BTZXJ2ZXIudG9vbChcbiAgICAgICAgJ2xpc3RfZGVidWdfc2Vzc2lvbnMnLFxuICAgICAgICAnTGlzdCBhbGwgYWN0aXZlIGRlYnVnIHNlc3Npb25zIGluIHRoZSB3b3Jrc3BhY2UuJyxcbiAgICAgICAgbGlzdERlYnVnU2Vzc2lvbnNTY2hlbWEuc2hhcGUsIC8vIE5vIHBhcmFtZXRlcnMgcmVxdWlyZWRcbiAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgbGlzdERlYnVnU2Vzc2lvbnMoKTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgLi4ucmVzdWx0LFxuICAgICAgICAgICAgICAgIGNvbnRlbnQ6IHJlc3VsdC5jb250ZW50Lm1hcCgoaXRlbSkgPT4gKHsgdHlwZTogJ3RleHQnLCB0ZXh0OiBKU09OLnN0cmluZ2lmeShpdGVtLmpzb24pIH0pKSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sXG4gICAgKTtcblxuICAgIC8vIFJlZ2lzdGVyICdzdGFydF9kZWJ1Z19zZXNzaW9uJyB0b29sXG4gICAgbWNwU2VydmVyLnRvb2woXG4gICAgICAgICdzdGFydF9kZWJ1Z19zZXNzaW9uJyxcbiAgICAgICAgJ1N0YXJ0IGEgbmV3IGRlYnVnIHNlc3Npb24gd2l0aCB0aGUgcHJvdmlkZWQgY29uZmlndXJhdGlvbi4nLFxuICAgICAgICBzdGFydERlYnVnU2Vzc2lvblNjaGVtYS5zaGFwZSxcbiAgICAgICAgYXN5bmMgKHBhcmFtcykgPT4ge1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RhcnREZWJ1Z1Nlc3Npb24ocGFyYW1zKTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgLi4ucmVzdWx0LFxuICAgICAgICAgICAgICAgIGNvbnRlbnQ6IHJlc3VsdC5jb250ZW50Lm1hcCgoaXRlbSkgPT4gKHtcbiAgICAgICAgICAgICAgICAgICAgLi4uaXRlbSxcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ3RleHQnIGFzIGNvbnN0LFxuICAgICAgICAgICAgICAgIH0pKSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sXG4gICAgKTtcblxuICAgIC8vIFJlZ2lzdGVyICdzdG9wX2RlYnVnX3Nlc3Npb24nIHRvb2xcblxuICAgIC8vIFJlZ2lzdGVyICdyZXN0YXJ0X2RlYnVnX3Nlc3Npb24nIHRvb2xcbiAgICBtY3BTZXJ2ZXIudG9vbChcbiAgICAgICAgJ3Jlc3RhcnRfZGVidWdfc2Vzc2lvbicsXG4gICAgICAgICdSZXN0YXJ0IGEgZGVidWcgc2Vzc2lvbiBieSBzdG9wcGluZyBpdCBhbmQgdGhlbiBzdGFydGluZyBpdCB3aXRoIHRoZSBwcm92aWRlZCBjb25maWd1cmF0aW9uLicsXG4gICAgICAgIHN0YXJ0RGVidWdTZXNzaW9uU2NoZW1hLnNoYXBlLCAvLyB1c2luZyB0aGUgc2FtZSBzY2hlbWEgYXMgJ3N0YXJ0X2RlYnVnX3Nlc3Npb24nXG4gICAgICAgIGFzeW5jIChwYXJhbXMpID0+IHtcbiAgICAgICAgICAgIC8vIFN0b3AgY3VycmVudCBzZXNzaW9uIHVzaW5nIHRoZSBwcm92aWRlZCBzZXNzaW9uIG5hbWVcbiAgICAgICAgICAgIGF3YWl0IHN0b3BEZWJ1Z1Nlc3Npb24oeyBzZXNzaW9uTmFtZTogcGFyYW1zLmNvbmZpZ3VyYXRpb24ubmFtZSB9KTtcblxuICAgICAgICAgICAgLy8gVGhlbiBzdGFydCBhIG5ldyBkZWJ1ZyBzZXNzaW9uIHdpdGggdGhlIGdpdmVuIGNvbmZpZ3VyYXRpb25cbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHN0YXJ0RGVidWdTZXNzaW9uKHBhcmFtcyk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIC4uLnJlc3VsdCxcbiAgICAgICAgICAgICAgICBjb250ZW50OiByZXN1bHQuY29udGVudC5tYXAoKGl0ZW0pID0+ICh7XG4gICAgICAgICAgICAgICAgICAgIC4uLml0ZW0sXG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICd0ZXh0JyBhcyBjb25zdCxcbiAgICAgICAgICAgICAgICB9KSksXG4gICAgICAgICAgICB9O1xuICAgICAgICB9LFxuICAgICk7XG4gICAgbWNwU2VydmVyLnRvb2woXG4gICAgICAgICdzdG9wX2RlYnVnX3Nlc3Npb24nLFxuICAgICAgICAnU3RvcCBhbGwgZGVidWcgc2Vzc2lvbnMgdGhhdCBtYXRjaCB0aGUgcHJvdmlkZWQgc2Vzc2lvbiBuYW1lLicsXG4gICAgICAgIHN0b3BEZWJ1Z1Nlc3Npb25TY2hlbWEuc2hhcGUsXG4gICAgICAgIGFzeW5jIChwYXJhbXMpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHN0b3BEZWJ1Z1Nlc3Npb24ocGFyYW1zKTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgLi4ucmVzdWx0LFxuICAgICAgICAgICAgICAgIGNvbnRlbnQ6IHJlc3VsdC5jb250ZW50Lm1hcCgoaXRlbSkgPT4gKHtcbiAgICAgICAgICAgICAgICAgICAgLi4uaXRlbSxcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ3RleHQnIGFzIGNvbnN0LFxuICAgICAgICAgICAgICAgIH0pKSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sXG4gICAgKTtcblxuICAgIC8vIFJlZ2lzdGVyICdjcmVhdGVfdGVybWluYWwnIHRvb2xcbiAgICBtY3BTZXJ2ZXIudG9vbChcbiAgICAgICAgJ2NyZWF0ZV90ZXJtaW5hbCcsXG4gICAgICAgIGRlZGVudGBcbiAgICAgICAgICAgIENyZWF0ZSBhIG5ldyBpbnRlZ3JhdGVkIHRlcm1pbmFsIGluIHRoZSBWU0NvZGUgd29ya3NwYWNlLlxuICAgICAgICAgICAgT3B0aW9uYWxseSBzZXQgYSBuYW1lLCB3b3JraW5nIGRpcmVjdG9yeSwgYW5kIGFuIGluaXRpYWwgY29tbWFuZCB0byBleGVjdXRlLlxuICAgICAgICBgLnRyaW0oKSxcbiAgICAgICAgY3JlYXRlVGVybWluYWxTY2hlbWEuc2hhcGUsXG4gICAgICAgIGFzeW5jIChwYXJhbXMpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNyZWF0ZVRlcm1pbmFsKHBhcmFtcyk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIC4uLnJlc3VsdCxcbiAgICAgICAgICAgICAgICBjb250ZW50OiByZXN1bHQuY29udGVudC5tYXAoKGl0ZW0pID0+ICh7XG4gICAgICAgICAgICAgICAgICAgIC4uLml0ZW0sXG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICd0ZXh0JyBhcyBjb25zdCxcbiAgICAgICAgICAgICAgICB9KSksXG4gICAgICAgICAgICB9O1xuICAgICAgICB9LFxuICAgICk7XG5cbiAgICAvLyBSZWdpc3RlciAnbGlzdF90ZXJtaW5hbHMnIHRvb2xcbiAgICBtY3BTZXJ2ZXIudG9vbChcbiAgICAgICAgJ2xpc3RfdGVybWluYWxzJyxcbiAgICAgICAgJ0xpc3QgYWxsIGFjdGl2ZSB0ZXJtaW5hbHMgaW4gdGhlIHdvcmtzcGFjZS4nLFxuICAgICAgICBsaXN0VGVybWluYWxzU2NoZW1hLnNoYXBlLFxuICAgICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBsaXN0VGVybWluYWxzKCk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIC4uLnJlc3VsdCxcbiAgICAgICAgICAgICAgICBjb250ZW50OiByZXN1bHQuY29udGVudC5tYXAoKGl0ZW0pID0+ICh7IHR5cGU6ICd0ZXh0JywgdGV4dDogSlNPTi5zdHJpbmdpZnkoaXRlbS5qc29uKSB9KSksXG4gICAgICAgICAgICB9O1xuICAgICAgICB9LFxuICAgICk7XG5cbiAgICAvLyBSZWdpc3RlciAnc2VuZF90ZXJtaW5hbF90ZXh0JyB0b29sXG4gICAgbWNwU2VydmVyLnRvb2woXG4gICAgICAgICdzZW5kX3Rlcm1pbmFsX3RleHQnLFxuICAgICAgICBkZWRlbnRgXG4gICAgICAgICAgICBTZW5kIHRleHQgdG8gYW4gZXhpc3RpbmcgdGVybWluYWwgYnkgbmFtZS5cbiAgICAgICAgICAgIFVzZSB0aGlzIHRvIGV4ZWN1dGUgY29tbWFuZHMgb3IgdHlwZSBpbnB1dCBpbiBhIHRlcm1pbmFsIHRoYXQgd2FzIHByZXZpb3VzbHkgY3JlYXRlZC5cbiAgICAgICAgYC50cmltKCksXG4gICAgICAgIHNlbmRUZXJtaW5hbFRleHRTY2hlbWEuc2hhcGUsXG4gICAgICAgIGFzeW5jIChwYXJhbXMpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHNlbmRUZXJtaW5hbFRleHQocGFyYW1zKTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgLi4ucmVzdWx0LFxuICAgICAgICAgICAgICAgIGNvbnRlbnQ6IHJlc3VsdC5jb250ZW50Lm1hcCgoaXRlbSkgPT4gKHtcbiAgICAgICAgICAgICAgICAgICAgLi4uaXRlbSxcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ3RleHQnIGFzIGNvbnN0LFxuICAgICAgICAgICAgICAgIH0pKSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sXG4gICAgKTtcblxuICAgIC8vIFJlZ2lzdGVyICdjbG9zZV90ZXJtaW5hbCcgdG9vbFxuICAgIG1jcFNlcnZlci50b29sKFxuICAgICAgICAnY2xvc2VfdGVybWluYWwnLFxuICAgICAgICAnQ2xvc2UgYW4gYWN0aXZlIHRlcm1pbmFsIGJ5IG5hbWUuJyxcbiAgICAgICAgY2xvc2VUZXJtaW5hbFNjaGVtYS5zaGFwZSxcbiAgICAgICAgYXN5bmMgKHBhcmFtcykgPT4ge1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY2xvc2VUZXJtaW5hbChwYXJhbXMpO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAuLi5yZXN1bHQsXG4gICAgICAgICAgICAgICAgY29udGVudDogcmVzdWx0LmNvbnRlbnQubWFwKChpdGVtKSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICAuLi5pdGVtLFxuICAgICAgICAgICAgICAgICAgICB0eXBlOiAndGV4dCcgYXMgY29uc3QsXG4gICAgICAgICAgICAgICAgfSkpLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSxcbiAgICApO1xuXG4gICAgLy8gUmVnaXN0ZXIgJ2dldF90ZXJtaW5hbF9vdXRwdXQnIHRvb2xcbiAgICBtY3BTZXJ2ZXIudG9vbChcbiAgICAgICAgJ2dldF90ZXJtaW5hbF9vdXRwdXQnLFxuICAgICAgICBkZWRlbnRgXG4gICAgICAgICAgICBSZWFkIGNhcHR1cmVkIGNvbW1hbmQgb3V0cHV0IGZyb20gYSB0ZXJtaW5hbC5cbiAgICAgICAgICAgIE91dHB1dCBpcyBjYXB0dXJlZCBwZXItY29tbWFuZCB2aWEgc2hlbGwgZXhlY3V0aW9uIGV2ZW50cy5cbiAgICAgICAgICAgIFJldHVybnMgY2xlYW4gb3V0cHV0IHdpdGhvdXQgQU5TSSBlc2NhcGUgY29kZXMuXG4gICAgICAgICAgICBSZXF1aXJlcyBWUyBDb2RlIHNoZWxsIGludGVncmF0aW9uIHRvIGJlIGFjdGl2ZSAoZW5hYmxlZCBieSBkZWZhdWx0KS5cbiAgICAgICAgYC50cmltKCksXG4gICAgICAgIGdldFRlcm1pbmFsT3V0cHV0U2NoZW1hLnNoYXBlLFxuICAgICAgICBhc3luYyAocGFyYW1zKSA9PiB7XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBnZXRUZXJtaW5hbE91dHB1dChwYXJhbXMpO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAuLi5yZXN1bHQsXG4gICAgICAgICAgICAgICAgY29udGVudDogcmVzdWx0LmNvbnRlbnQubWFwKChpdGVtKSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICAuLi5pdGVtLFxuICAgICAgICAgICAgICAgICAgICB0eXBlOiAndGV4dCcgYXMgY29uc3QsXG4gICAgICAgICAgICAgICAgfSkpLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSxcbiAgICApO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSB0ZXJtaW5hbCBvdXRwdXQgY2FwdHVyZSAoc2hlbGwgZXhlY3V0aW9uIGV2ZW50cylcbiAgICBpbml0VGVybWluYWxPdXRwdXRDYXB0dXJlKGNvbnRleHQpO1xuXG4gICAgLy8gU2V0IHVwIGFuIEV4cHJlc3MgYXBwIHRvIGhhbmRsZSBTU0UgY29ubmVjdGlvbnNcbiAgICBjb25zdCBhcHAgPSBleHByZXNzKCk7XG4gICAgY29uc3QgbWNwQ29uZmlnID0gdnNjb2RlLndvcmtzcGFjZS5nZXRDb25maWd1cmF0aW9uKCdtY3BTZXJ2ZXInKTtcbiAgICBjb25zdCBwb3J0ID0gYXdhaXQgcmVzb2x2ZVBvcnQobWNwQ29uZmlnLmdldDxudW1iZXI+KCdwb3J0JywgNjAxMCkpO1xuXG4gICAgbGV0IHNzZVRyYW5zcG9ydDogU1NFU2VydmVyVHJhbnNwb3J0IHwgdW5kZWZpbmVkO1xuXG4gICAgLy8gR0VUIC9zc2UgZW5kcG9pbnQ6IHRoZSBleHRlcm5hbCBNQ1AgY2xpZW50IGNvbm5lY3RzIGhlcmUgKFNTRSlcbiAgICBhcHAuZ2V0KCcvc3NlJywgYXN5bmMgKF9yZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UpID0+IHtcbiAgICAgICAgb3V0cHV0Q2hhbm5lbC5hcHBlbmRMaW5lKCdTU0UgY29ubmVjdGlvbiBpbml0aWF0ZWQuLi4nKTtcbiAgICAgICAgc3NlVHJhbnNwb3J0ID0gbmV3IFNTRVNlcnZlclRyYW5zcG9ydCgnL21lc3NhZ2VzJywgcmVzKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IG1jcFNlcnZlci5jb25uZWN0KHNzZVRyYW5zcG9ydCk7XG4gICAgICAgICAgICBvdXRwdXRDaGFubmVsLmFwcGVuZExpbmUoJ01DUCBTZXJ2ZXIgY29ubmVjdGVkIHZpYSBTU0UuJyk7XG4gICAgICAgICAgICBvdXRwdXRDaGFubmVsLmFwcGVuZExpbmUoYFNTRSBUcmFuc3BvcnQgc2Vzc2lvbklkOiAke3NzZVRyYW5zcG9ydC5zZXNzaW9uSWR9YCk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgb3V0cHV0Q2hhbm5lbC5hcHBlbmRMaW5lKCdFcnJvciBjb25uZWN0aW5nIE1DUCBTZXJ2ZXIgdmlhIFNTRTogJyArIGVycik7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIFBPU1QgL21lc3NhZ2VzIGVuZHBvaW50OiB0aGUgZXh0ZXJuYWwgTUNQIGNsaWVudCBzZW5kcyBtZXNzYWdlcyBoZXJlXG4gICAgYXBwLnBvc3QoJy9tZXNzYWdlcycsIGV4cHJlc3MuanNvbigpLCBhc3luYyAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlKSA9PiB7XG4gICAgICAgIC8vIExvZyBpbiBvdXRwdXQgY2hhbm5lbFxuICAgICAgICBvdXRwdXRDaGFubmVsLmFwcGVuZExpbmUoYFBPU1QgL21lc3NhZ2VzOiBQYXlsb2FkIC0gJHtKU09OLnN0cmluZ2lmeShyZXEuYm9keSwgbnVsbCwgMil9YCk7XG5cbiAgICAgICAgaWYgKHNzZVRyYW5zcG9ydCkge1xuICAgICAgICAgICAgLy8gTG9nIHRoZSBzZXNzaW9uIElEIG9mIHRoZSB0cmFuc3BvcnQgdG8gY29uZmlybSBpdHMgaW5pdGlhbGl6YXRpb25cbiAgICAgICAgICAgIG91dHB1dENoYW5uZWwuYXBwZW5kTGluZShgU1NFIFRyYW5zcG9ydCBzZXNzaW9uSWQ6ICR7c3NlVHJhbnNwb3J0LnNlc3Npb25JZH1gKTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgLy8gTm90ZTogUGFzc2luZyByZXEuYm9keSB0byBoYW5kbGVQb3N0TWVzc2FnZSBpcyBjcml0aWNhbCBiZWNhdXNlIGV4cHJlc3MuanNvbigpXG4gICAgICAgICAgICAgICAgLy8gY29uc3VtZXMgdGhlIHJlcXVlc3Qgc3RyZWFtLiBXaXRob3V0IHRoaXMsIGF0dGVtcHRpbmcgdG8gcmUtcmVhZCB0aGUgc3RyZWFtXG4gICAgICAgICAgICAgICAgLy8gd2l0aGluIGhhbmRsZVBvc3RNZXNzYWdlIHdvdWxkIHJlc3VsdCBpbiBhIFwic3RyZWFtIGlzIG5vdCByZWFkYWJsZVwiIGVycm9yLlxuICAgICAgICAgICAgICAgIGF3YWl0IHNzZVRyYW5zcG9ydC5oYW5kbGVQb3N0TWVzc2FnZShyZXEsIHJlcywgcmVxLmJvZHkpO1xuICAgICAgICAgICAgICAgIG91dHB1dENoYW5uZWwuYXBwZW5kTGluZSgnSGFuZGxlZCBQT1NUIC9tZXNzYWdlcyBzdWNjZXNzZnVsbHkuJyk7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICBvdXRwdXRDaGFubmVsLmFwcGVuZExpbmUoJ0Vycm9yIGhhbmRsaW5nIFBPU1QgL21lc3NhZ2VzOiAnICsgZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcy5zdGF0dXMoNTAwKS5zZW5kKCdTU0UgVHJhbnNwb3J0IG5vdCBpbml0aWFsaXplZC4nKTtcbiAgICAgICAgICAgIG91dHB1dENoYW5uZWwuYXBwZW5kTGluZSgnUE9TVCAvbWVzc2FnZXMgZmFpbGVkOiBTU0UgVHJhbnNwb3J0IG5vdCBpbml0aWFsaXplZC4nKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gQ3JlYXRlIGFuZCBzdGFydCB0aGUgSFRUUCBzZXJ2ZXJcbiAgICBjb25zdCBzZXJ2ZXIgPSBodHRwLmNyZWF0ZVNlcnZlcihhcHApO1xuICAgIGZ1bmN0aW9uIHN0YXJ0U2VydmVyKHBvcnQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBzZXJ2ZXIubGlzdGVuKHBvcnQsICgpID0+IHtcbiAgICAgICAgICAgIG91dHB1dENoYW5uZWwuYXBwZW5kTGluZShgTUNQIFNTRSBTZXJ2ZXIgcnVubmluZyBhdCBodHRwOi8vMTI3LjAuMC4xOiR7cG9ydH0vc3NlYCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEFkZCBkaXNwb3NhbCB0byBzaHV0IGRvd24gdGhlIEhUVFAgc2VydmVyIGFuZCBvdXRwdXQgY2hhbm5lbCBvbiBleHRlbnNpb24gZGVhY3RpdmF0aW9uXG4gICAgICAgIGNvbnRleHQuc3Vic2NyaXB0aW9ucy5wdXNoKHtcbiAgICAgICAgICAgIGRpc3Bvc2U6ICgpID0+IHtcbiAgICAgICAgICAgICAgICBzZXJ2ZXIuY2xvc2UoKTtcbiAgICAgICAgICAgICAgICBvdXRwdXRDaGFubmVsLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBjb25zdCBzdGFydE9uQWN0aXZhdGUgPSBtY3BDb25maWcuZ2V0PGJvb2xlYW4+KCdzdGFydE9uQWN0aXZhdGUnLCB0cnVlKTtcbiAgICBpZiAoc3RhcnRPbkFjdGl2YXRlKSB7XG4gICAgICAgIHN0YXJ0U2VydmVyKHBvcnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG91dHB1dENoYW5uZWwuYXBwZW5kTGluZSgnTUNQIFNlcnZlciBzdGFydHVwIGRpc2FibGVkIGJ5IGNvbmZpZ3VyYXRpb24uJyk7XG4gICAgfVxuXG4gICAgLy8gQ09NTUFORCBQQUxFVFRFIENPTU1BTkQ6IFN0b3AgdGhlIE1DUCBTZXJ2ZXJcbiAgICBjb250ZXh0LnN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgICAgdnNjb2RlLmNvbW1hbmRzLnJlZ2lzdGVyQ29tbWFuZCgnbWNwU2VydmVyLnN0b3BTZXJ2ZXInLCAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoIXNlcnZlci5saXN0ZW5pbmcpIHtcbiAgICAgICAgICAgICAgICB2c2NvZGUud2luZG93LnNob3dXYXJuaW5nTWVzc2FnZSgnTUNQIFNlcnZlciBpcyBub3QgcnVubmluZy4nKTtcbiAgICAgICAgICAgICAgICBvdXRwdXRDaGFubmVsLmFwcGVuZExpbmUoJ0F0dGVtcHRlZCB0byBzdG9wIHRoZSBNQ1AgU2VydmVyLCBidXQgaXQgaXMgbm90IHJ1bm5pbmcuJyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VydmVyLmNsb3NlKCgpID0+IHtcbiAgICAgICAgICAgICAgICBvdXRwdXRDaGFubmVsLmFwcGVuZExpbmUoJ01DUCBTZXJ2ZXIgc3RvcHBlZC4nKTtcbiAgICAgICAgICAgICAgICB2c2NvZGUud2luZG93LnNob3dJbmZvcm1hdGlvbk1lc3NhZ2UoJ01DUCBTZXJ2ZXIgc3RvcHBlZC4nKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KSxcbiAgICApO1xuXG4gICAgLy8gQ09NTUFORCBQQUxFVFRFIENPTU1BTkQ6IFN0YXJ0IHRoZSBNQ1AgU2VydmVyXG4gICAgY29udGV4dC5zdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICAgIHZzY29kZS5jb21tYW5kcy5yZWdpc3RlckNvbW1hbmQoJ21jcFNlcnZlci5zdGFydFNlcnZlcicsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGlmIChzZXJ2ZXIubGlzdGVuaW5nKSB7XG4gICAgICAgICAgICAgICAgdnNjb2RlLndpbmRvdy5zaG93V2FybmluZ01lc3NhZ2UoJ01DUCBTZXJ2ZXIgaXMgYWxyZWFkeSBydW5uaW5nLicpO1xuICAgICAgICAgICAgICAgIG91dHB1dENoYW5uZWwuYXBwZW5kTGluZSgnQXR0ZW1wdGVkIHRvIHN0YXJ0IHRoZSBNQ1AgU2VydmVyLCBidXQgaXQgaXMgYWxyZWFkeSBydW5uaW5nLicpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IG5ld1BvcnQgPSBhd2FpdCByZXNvbHZlUG9ydChtY3BDb25maWcuZ2V0PG51bWJlcj4oJ3BvcnQnLCA2MDEwKSk7XG4gICAgICAgICAgICBzdGFydFNlcnZlcihuZXdQb3J0KTtcbiAgICAgICAgICAgIG91dHB1dENoYW5uZWwuYXBwZW5kTGluZShgTUNQIFNlcnZlciBzdGFydGVkIG9uIHBvcnQgJHtuZXdQb3J0fS5gKTtcbiAgICAgICAgICAgIHZzY29kZS53aW5kb3cuc2hvd0luZm9ybWF0aW9uTWVzc2FnZShgTUNQIFNlcnZlciBzdGFydGVkIG9uIHBvcnQgJHtuZXdQb3J0fS5gKTtcbiAgICAgICAgfSksXG4gICAgKTtcblxuICAgIC8vIENPTU1BTkQgUEFMRVRURSBDT01NQU5EOiBTZXQgdGhlIE1DUCBzZXJ2ZXIgcG9ydCBhbmQgcmVzdGFydCB0aGUgc2VydmVyXG4gICAgY29udGV4dC5zdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICAgIHZzY29kZS5jb21tYW5kcy5yZWdpc3RlckNvbW1hbmQoJ21jcFNlcnZlci5zZXRQb3J0JywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgbmV3UG9ydElucHV0ID0gYXdhaXQgdnNjb2RlLndpbmRvdy5zaG93SW5wdXRCb3goe1xuICAgICAgICAgICAgICAgIHByb21wdDogJ0VudGVyIG5ldyBwb3J0IG51bWJlciBmb3IgdGhlIE1DUCBTZXJ2ZXI6JyxcbiAgICAgICAgICAgICAgICB2YWx1ZTogU3RyaW5nKHBvcnQpLFxuICAgICAgICAgICAgICAgIHZhbGlkYXRlSW5wdXQ6IChpbnB1dCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBudW0gPSBOdW1iZXIoaW5wdXQpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNOYU4obnVtKSB8fCBudW0gPCAxIHx8IG51bSA+IDY1NTM1KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1BsZWFzZSBlbnRlciBhIHZhbGlkIHBvcnQgbnVtYmVyICgxLTY1NTM1KS4nO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChuZXdQb3J0SW5wdXQgJiYgbmV3UG9ydElucHV0LnRyaW0oKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbmV3UG9ydCA9IE51bWJlcihuZXdQb3J0SW5wdXQpO1xuICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgY29uZmlndXJhdGlvbiBzbyB0aGF0IHN1YnNlcXVlbnQgc3RhcnR1cHMgdXNlIHRoZSBuZXcgcG9ydFxuICAgICAgICAgICAgICAgIGF3YWl0IHZzY29kZS53b3Jrc3BhY2VcbiAgICAgICAgICAgICAgICAgICAgLmdldENvbmZpZ3VyYXRpb24oJ21jcFNlcnZlcicpXG4gICAgICAgICAgICAgICAgICAgIC51cGRhdGUoJ3BvcnQnLCBuZXdQb3J0LCB2c2NvZGUuQ29uZmlndXJhdGlvblRhcmdldC5HbG9iYWwpO1xuICAgICAgICAgICAgICAgIC8vIFJlc3RhcnQgdGhlIHNlcnZlcjogY2xvc2UgZXhpc3Rpbmcgc2VydmVyIGFuZCBzdGFydCBhIG5ldyBvbmVcbiAgICAgICAgICAgICAgICBzZXJ2ZXIuY2xvc2UoKTtcbiAgICAgICAgICAgICAgICBzdGFydFNlcnZlcihuZXdQb3J0KTtcbiAgICAgICAgICAgICAgICBvdXRwdXRDaGFubmVsLmFwcGVuZExpbmUoYE1DUCBTZXJ2ZXIgcmVzdGFydGVkIG9uIHBvcnQgJHtuZXdQb3J0fWApO1xuICAgICAgICAgICAgICAgIHZzY29kZS53aW5kb3cuc2hvd0luZm9ybWF0aW9uTWVzc2FnZShgTUNQIFNlcnZlciByZXN0YXJ0ZWQgb24gcG9ydCAke25ld1BvcnR9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLFxuICAgICk7XG5cbiAgICBvdXRwdXRDaGFubmVsLmFwcGVuZExpbmUoYCR7ZXh0ZW5zaW9uRGlzcGxheU5hbWV9IGFjdGl2YXRlZC5gKTtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWFjdGl2YXRlKCkge1xuICAgIC8vIENsZWFuLXVwIGlzIG1hbmFnZWQgYnkgdGhlIGRpc3Bvc2FibGVzIGFkZGVkIGluIHRoZSBhY3RpdmF0ZSBtZXRob2QuXG59XG4iXX0= \ No newline at end of file diff --git a/mcp-servers/mcp-server-vscode/out/test/terminal_tools.test.d.ts b/mcp-servers/mcp-server-vscode/out/test/terminal_tools.test.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/mcp-servers/mcp-server-vscode/out/test/terminal_tools.test.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/mcp-servers/mcp-server-vscode/out/test/terminal_tools.test.js b/mcp-servers/mcp-server-vscode/out/test/terminal_tools.test.js new file mode 100644 index 000000000..4410ca744 --- /dev/null +++ b/mcp-servers/mcp-server-vscode/out/test/terminal_tools.test.js @@ -0,0 +1,79 @@ +import * as assert from 'assert'; +import { closeTerminalSchema, createTerminalSchema, getTerminalOutputSchema, listTerminalsSchema, sendTerminalTextSchema, } from '../tools/terminal_tools'; +suite('Terminal Tools Schema Test Suite', () => { + test('createTerminalSchema accepts valid params with all fields', () => { + const result = createTerminalSchema.safeParse({ + name: 'my-terminal', + cwd: '/tmp', + command: 'echo hello', + show: true, + }); + assert.strictEqual(result.success, true); + }); + test('createTerminalSchema accepts empty params (all optional)', () => { + const result = createTerminalSchema.safeParse({}); + assert.strictEqual(result.success, true); + if (result.success) { + assert.strictEqual(result.data.show, true); + } + }); + test('createTerminalSchema rejects invalid show type', () => { + const result = createTerminalSchema.safeParse({ show: 'yes' }); + assert.strictEqual(result.success, false); + }); + test('listTerminalsSchema accepts empty params', () => { + const result = listTerminalsSchema.safeParse({}); + assert.strictEqual(result.success, true); + }); + test('sendTerminalTextSchema requires name and text', () => { + const valid = sendTerminalTextSchema.safeParse({ + name: 'my-terminal', + text: 'ls -la', + }); + assert.strictEqual(valid.success, true); + const missingName = sendTerminalTextSchema.safeParse({ text: 'ls' }); + assert.strictEqual(missingName.success, false); + const missingText = sendTerminalTextSchema.safeParse({ name: 'my-terminal' }); + assert.strictEqual(missingText.success, false); + }); + test('sendTerminalTextSchema defaults addNewLine to true', () => { + const result = sendTerminalTextSchema.safeParse({ + name: 'my-terminal', + text: 'ls', + }); + assert.strictEqual(result.success, true); + if (result.success) { + assert.strictEqual(result.data.addNewLine, true); + } + }); + test('closeTerminalSchema requires name', () => { + const valid = closeTerminalSchema.safeParse({ name: 'my-terminal' }); + assert.strictEqual(valid.success, true); + const missing = closeTerminalSchema.safeParse({}); + assert.strictEqual(missing.success, false); + }); + test('getTerminalOutputSchema accepts name only (defaults applied)', () => { + const result = getTerminalOutputSchema.safeParse({ name: 'my-terminal' }); + assert.strictEqual(result.success, true); + if (result.success) { + assert.strictEqual(result.data.limit, 10); + assert.strictEqual(result.data.commandIndex, undefined); + } + }); + test('getTerminalOutputSchema accepts commandIndex', () => { + const result = getTerminalOutputSchema.safeParse({ name: 'my-terminal', commandIndex: 3 }); + assert.strictEqual(result.success, true); + if (result.success) { + assert.strictEqual(result.data.commandIndex, 3); + } + }); + test('getTerminalOutputSchema rejects limit over 50', () => { + const result = getTerminalOutputSchema.safeParse({ name: 'my-terminal', limit: 100 }); + assert.strictEqual(result.success, false); + }); + test('getTerminalOutputSchema requires name', () => { + const result = getTerminalOutputSchema.safeParse({}); + assert.strictEqual(result.success, false); + }); +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVybWluYWxfdG9vbHMudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0L3Rlcm1pbmFsX3Rvb2xzLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE1BQU0sTUFBTSxRQUFRLENBQUM7QUFDakMsT0FBTyxFQUNILG1CQUFtQixFQUNuQixvQkFBb0IsRUFDcEIsdUJBQXVCLEVBQ3ZCLG1CQUFtQixFQUNuQixzQkFBc0IsR0FDekIsTUFBTSx5QkFBeUIsQ0FBQztBQUVqQyxLQUFLLENBQUMsa0NBQWtDLEVBQUUsR0FBRyxFQUFFO0lBQzNDLElBQUksQ0FBQywyREFBMkQsRUFBRSxHQUFHLEVBQUU7UUFDbkUsTUFBTSxNQUFNLEdBQUcsb0JBQW9CLENBQUMsU0FBUyxDQUFDO1lBQzFDLElBQUksRUFBRSxhQUFhO1lBQ25CLEdBQUcsRUFBRSxNQUFNO1lBQ1gsT0FBTyxFQUFFLFlBQVk7WUFDckIsSUFBSSxFQUFFLElBQUk7U0FDYixDQUFDLENBQUM7UUFDSCxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDN0MsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFJLENBQUMsMERBQTBELEVBQUUsR0FBRyxFQUFFO1FBQ2xFLE1BQU0sTUFBTSxHQUFHLG9CQUFvQixDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNsRCxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDekMsSUFBSSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDakIsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztRQUMvQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFJLENBQUMsZ0RBQWdELEVBQUUsR0FBRyxFQUFFO1FB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QyxJQUFJLENBQUMsWUFBWSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQzVELENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILElBQUksQ0FBQyw4Q0FBOEMsRUFBRSxHQUFHLEVBQUU7UUFDdEQsTUFBTSxNQUFNLEdBQUcsdUJBQXVCLENBQUMsU0FBUyxDQUFDLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxZQUFZLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUMzRixNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDekMsSUFBSSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDakIsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNwRCxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFJLENBQUMsK0NBQStDLEVBQUUsR0FBRyxFQUFFO1FBQ3ZELE1BQU0sTUFBTSxHQUFHLHVCQUF1QixDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDdEYsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQzlDLENBQUMsQ0FBQyxDQUFDO0lBRUgsSUFBSSxDQUFDLHVDQUF1QyxFQUFFLEdBQUcsRUFBRTtRQUMvQyxNQUFNLE1BQU0sR0FBRyx1QkFBdUIsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDckQsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQzlDLENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCB7XG4gICAgY2xvc2VUZXJtaW5hbFNjaGVtYSxcbiAgICBjcmVhdGVUZXJtaW5hbFNjaGVtYSxcbiAgICBnZXRUZXJtaW5hbE91dHB1dFNjaGVtYSxcbiAgICBsaXN0VGVybWluYWxzU2NoZW1hLFxuICAgIHNlbmRUZXJtaW5hbFRleHRTY2hlbWEsXG59IGZyb20gJy4uL3Rvb2xzL3Rlcm1pbmFsX3Rvb2xzJztcblxuc3VpdGUoJ1Rlcm1pbmFsIFRvb2xzIFNjaGVtYSBUZXN0IFN1aXRlJywgKCkgPT4ge1xuICAgIHRlc3QoJ2NyZWF0ZVRlcm1pbmFsU2NoZW1hIGFjY2VwdHMgdmFsaWQgcGFyYW1zIHdpdGggYWxsIGZpZWxkcycsICgpID0+IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gY3JlYXRlVGVybWluYWxTY2hlbWEuc2FmZVBhcnNlKHtcbiAgICAgICAgICAgIG5hbWU6ICdteS10ZXJtaW5hbCcsXG4gICAgICAgICAgICBjd2Q6ICcvdG1wJyxcbiAgICAgICAgICAgIGNvbW1hbmQ6ICdlY2hvIGhlbGxvJyxcbiAgICAgICAgICAgIHNob3c6IHRydWUsXG4gICAgICAgIH0pO1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdWx0LnN1Y2Nlc3MsIHRydWUpO1xuICAgIH0pO1xuXG4gICAgdGVzdCgnY3JlYXRlVGVybWluYWxTY2hlbWEgYWNjZXB0cyBlbXB0eSBwYXJhbXMgKGFsbCBvcHRpb25hbCknLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGNyZWF0ZVRlcm1pbmFsU2NoZW1hLnNhZmVQYXJzZSh7fSk7XG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQuc3VjY2VzcywgdHJ1ZSk7XG4gICAgICAgIGlmIChyZXN1bHQuc3VjY2Vzcykge1xuICAgICAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdC5kYXRhLnNob3csIHRydWUpOyAvLyBkZWZhdWx0IHZhbHVlXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIHRlc3QoJ2NyZWF0ZVRlcm1pbmFsU2NoZW1hIHJlamVjdHMgaW52YWxpZCBzaG93IHR5cGUnLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGNyZWF0ZVRlcm1pbmFsU2NoZW1hLnNhZmVQYXJzZSh7IHNob3c6ICd5ZXMnIH0pO1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdWx0LnN1Y2Nlc3MsIGZhbHNlKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ2xpc3RUZXJtaW5hbHNTY2hlbWEgYWNjZXB0cyBlbXB0eSBwYXJhbXMnLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGxpc3RUZXJtaW5hbHNTY2hlbWEuc2FmZVBhcnNlKHt9KTtcbiAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdC5zdWNjZXNzLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ3NlbmRUZXJtaW5hbFRleHRTY2hlbWEgcmVxdWlyZXMgbmFtZSBhbmQgdGV4dCcsICgpID0+IHtcbiAgICAgICAgY29uc3QgdmFsaWQgPSBzZW5kVGVybWluYWxUZXh0U2NoZW1hLnNhZmVQYXJzZSh7XG4gICAgICAgICAgICBuYW1lOiAnbXktdGVybWluYWwnLFxuICAgICAgICAgICAgdGV4dDogJ2xzIC1sYScsXG4gICAgICAgIH0pO1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodmFsaWQuc3VjY2VzcywgdHJ1ZSk7XG5cbiAgICAgICAgY29uc3QgbWlzc2luZ05hbWUgPSBzZW5kVGVybWluYWxUZXh0U2NoZW1hLnNhZmVQYXJzZSh7IHRleHQ6ICdscycgfSk7XG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChtaXNzaW5nTmFtZS5zdWNjZXNzLCBmYWxzZSk7XG5cbiAgICAgICAgY29uc3QgbWlzc2luZ1RleHQgPSBzZW5kVGVybWluYWxUZXh0U2NoZW1hLnNhZmVQYXJzZSh7IG5hbWU6ICdteS10ZXJtaW5hbCcgfSk7XG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChtaXNzaW5nVGV4dC5zdWNjZXNzLCBmYWxzZSk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdzZW5kVGVybWluYWxUZXh0U2NoZW1hIGRlZmF1bHRzIGFkZE5ld0xpbmUgdG8gdHJ1ZScsICgpID0+IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gc2VuZFRlcm1pbmFsVGV4dFNjaGVtYS5zYWZlUGFyc2Uoe1xuICAgICAgICAgICAgbmFtZTogJ215LXRlcm1pbmFsJyxcbiAgICAgICAgICAgIHRleHQ6ICdscycsXG4gICAgICAgIH0pO1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdWx0LnN1Y2Nlc3MsIHRydWUpO1xuICAgICAgICBpZiAocmVzdWx0LnN1Y2Nlc3MpIHtcbiAgICAgICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQuZGF0YS5hZGROZXdMaW5lLCB0cnVlKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgdGVzdCgnY2xvc2VUZXJtaW5hbFNjaGVtYSByZXF1aXJlcyBuYW1lJywgKCkgPT4ge1xuICAgICAgICBjb25zdCB2YWxpZCA9IGNsb3NlVGVybWluYWxTY2hlbWEuc2FmZVBhcnNlKHsgbmFtZTogJ215LXRlcm1pbmFsJyB9KTtcbiAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHZhbGlkLnN1Y2Nlc3MsIHRydWUpO1xuXG4gICAgICAgIGNvbnN0IG1pc3NpbmcgPSBjbG9zZVRlcm1pbmFsU2NoZW1hLnNhZmVQYXJzZSh7fSk7XG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChtaXNzaW5nLnN1Y2Nlc3MsIGZhbHNlKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ2dldFRlcm1pbmFsT3V0cHV0U2NoZW1hIGFjY2VwdHMgbmFtZSBvbmx5IChkZWZhdWx0cyBhcHBsaWVkKScsICgpID0+IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gZ2V0VGVybWluYWxPdXRwdXRTY2hlbWEuc2FmZVBhcnNlKHsgbmFtZTogJ215LXRlcm1pbmFsJyB9KTtcbiAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdC5zdWNjZXNzLCB0cnVlKTtcbiAgICAgICAgaWYgKHJlc3VsdC5zdWNjZXNzKSB7XG4gICAgICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdWx0LmRhdGEubGltaXQsIDEwKTtcbiAgICAgICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQuZGF0YS5jb21tYW5kSW5kZXgsIHVuZGVmaW5lZCk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIHRlc3QoJ2dldFRlcm1pbmFsT3V0cHV0U2NoZW1hIGFjY2VwdHMgY29tbWFuZEluZGV4JywgKCkgPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBnZXRUZXJtaW5hbE91dHB1dFNjaGVtYS5zYWZlUGFyc2UoeyBuYW1lOiAnbXktdGVybWluYWwnLCBjb21tYW5kSW5kZXg6IDMgfSk7XG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQuc3VjY2VzcywgdHJ1ZSk7XG4gICAgICAgIGlmIChyZXN1bHQuc3VjY2Vzcykge1xuICAgICAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdC5kYXRhLmNvbW1hbmRJbmRleCwgMyk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIHRlc3QoJ2dldFRlcm1pbmFsT3V0cHV0U2NoZW1hIHJlamVjdHMgbGltaXQgb3ZlciA1MCcsICgpID0+IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gZ2V0VGVybWluYWxPdXRwdXRTY2hlbWEuc2FmZVBhcnNlKHsgbmFtZTogJ215LXRlcm1pbmFsJywgbGltaXQ6IDEwMCB9KTtcbiAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdC5zdWNjZXNzLCBmYWxzZSk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdnZXRUZXJtaW5hbE91dHB1dFNjaGVtYSByZXF1aXJlcyBuYW1lJywgKCkgPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBnZXRUZXJtaW5hbE91dHB1dFNjaGVtYS5zYWZlUGFyc2Uoe30pO1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdWx0LnN1Y2Nlc3MsIGZhbHNlKTtcbiAgICB9KTtcbn0pO1xuIl19 \ No newline at end of file diff --git a/mcp-servers/mcp-server-vscode/out/tools/terminal_tools.d.ts b/mcp-servers/mcp-server-vscode/out/tools/terminal_tools.d.ts new file mode 100644 index 000000000..cdf5311a4 --- /dev/null +++ b/mcp-servers/mcp-server-vscode/out/tools/terminal_tools.d.ts @@ -0,0 +1,92 @@ +import { z } from 'zod'; +export declare const createTerminalSchema: z.ZodObject<{ + name: z.ZodOptional; + cwd: z.ZodOptional; + command: z.ZodOptional; + show: z.ZodDefault; +}, "strip", z.ZodTypeAny, { + show: boolean; + name?: string | undefined; + cwd?: string | undefined; + command?: string | undefined; +}, { + name?: string | undefined; + cwd?: string | undefined; + command?: string | undefined; + show?: boolean | undefined; +}>; +export declare const createTerminal: (params: z.infer) => Promise<{ + content: { + type: string; + text: string; + }[]; + isError: boolean; +}>; +export declare const listTerminalsSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>; +export declare const listTerminals: () => { + content: { + type: string; + json: { + terminals: { + index: number; + name: string; + processId: Thenable; + }[]; + }; + }[]; + isError: boolean; +}; +export declare const sendTerminalTextSchema: z.ZodObject<{ + name: z.ZodString; + text: z.ZodString; + addNewLine: z.ZodDefault; +}, "strip", z.ZodTypeAny, { + text: string; + name: string; + addNewLine: boolean; +}, { + text: string; + name: string; + addNewLine?: boolean | undefined; +}>; +export declare const sendTerminalText: (params: z.infer) => Promise<{ + content: { + type: string; + text: string; + }[]; + isError: boolean; +}>; +export declare const closeTerminalSchema: z.ZodObject<{ + name: z.ZodString; +}, "strip", z.ZodTypeAny, { + name: string; +}, { + name: string; +}>; +export declare const getTerminalOutputSchema: z.ZodObject<{ + name: z.ZodString; + commandIndex: z.ZodOptional; + limit: z.ZodDefault; +}, "strip", z.ZodTypeAny, { + name: string; + limit: number; + commandIndex?: number | undefined; +}, { + name: string; + commandIndex?: number | undefined; + limit?: number | undefined; +}>; +export declare const getTerminalOutput: (params: z.infer) => Promise<{ + content: { + type: string; + text: string; + }[]; + isError: boolean; +}>; +export declare const closeTerminal: (params: z.infer) => Promise<{ + content: { + type: string; + text: string; + }[]; + isError: boolean; +}>; diff --git a/mcp-servers/mcp-server-vscode/out/tools/terminal_tools.js b/mcp-servers/mcp-server-vscode/out/tools/terminal_tools.js new file mode 100644 index 000000000..02c0697f5 --- /dev/null +++ b/mcp-servers/mcp-server-vscode/out/tools/terminal_tools.js @@ -0,0 +1,127 @@ +import * as vscode from 'vscode'; +import { z } from 'zod'; +import { getCommandHistory } from '../utils/terminal_output_capture'; +export const createTerminalSchema = z.object({ + name: z.string().optional().describe('Display name for the terminal tab.'), + cwd: z.string().optional().describe('Working directory for the terminal.'), + command: z.string().optional().describe('Command to execute immediately after terminal creation.'), + show: z.boolean().default(true).describe('Whether to focus the terminal after creation.'), +}); +export const createTerminal = async (params) => { + const { name, cwd, command, show } = params; + const terminal = vscode.window.createTerminal({ name, cwd }); + if (show) { + terminal.show(); + } + if (command) { + terminal.sendText(command); + } + const terminalName = terminal.name; + return { + content: [{ type: 'text', text: `Terminal '${terminalName}' created successfully.` }], + isError: false, + }; +}; +export const listTerminalsSchema = z.object({}); +export const listTerminals = () => { + const terminals = vscode.window.terminals.map((terminal, index) => ({ + index, + name: terminal.name, + processId: terminal.processId, + })); + return { + content: [{ type: 'json', json: { terminals } }], + isError: false, + }; +}; +export const sendTerminalTextSchema = z.object({ + name: z.string().describe('Name of the target terminal.'), + text: z.string().describe('Text to send to the terminal.'), + addNewLine: z.boolean().default(true).describe('Whether to append a newline (simulating Enter key).'), +}); +export const sendTerminalText = async (params) => { + const { name, text, addNewLine } = params; + const terminal = vscode.window.terminals.find((t) => t.name === name); + if (!terminal) { + return { + content: [{ type: 'text', text: `No terminal found with name '${name}'.` }], + isError: true, + }; + } + terminal.sendText(text, addNewLine); + terminal.show(); + return { + content: [{ type: 'text', text: `Sent text to terminal '${name}'.` }], + isError: false, + }; +}; +export const closeTerminalSchema = z.object({ + name: z.string().describe('Name of the terminal to close.'), +}); +export const getTerminalOutputSchema = z.object({ + name: z.string().describe('Name of the terminal to read output from.'), + commandIndex: z + .number() + .int() + .optional() + .describe('Index of a specific command to read (0-based, most recent last). Omit to get all recent commands.'), + limit: z + .number() + .int() + .min(1) + .max(50) + .default(10) + .describe('Maximum number of recent commands to return (when commandIndex is not specified).'), +}); +export const getTerminalOutput = async (params) => { + const { name, commandIndex, limit } = params; + const history = getCommandHistory(name); + if (!history || history.length === 0) { + return { + content: [{ type: 'text', text: `No output captured for terminal '${name}'. Shell integration may not be active.` }], + isError: true, + }; + } + if (commandIndex !== undefined) { + if (commandIndex < 0 || commandIndex >= history.length) { + return { + content: [{ type: 'text', text: `Command index ${commandIndex} out of range (0-${history.length - 1}).` }], + isError: true, + }; + } + const record = history[commandIndex]; + return { + content: [{ type: 'text', text: JSON.stringify({ command: record.command, output: record.output, index: commandIndex }) }], + isError: false, + }; + } + const recent = history.slice(-limit); + return { + content: [ + { + type: 'text', + text: JSON.stringify({ + commands: recent.map((r, i) => ({ index: history.length - recent.length + i, command: r.command, output: r.output })), + totalCommands: history.length, + }), + }, + ], + isError: false, + }; +}; +export const closeTerminal = async (params) => { + const { name } = params; + const terminal = vscode.window.terminals.find((t) => t.name === name); + if (!terminal) { + return { + content: [{ type: 'text', text: `No terminal found with name '${name}'.` }], + isError: true, + }; + } + terminal.dispose(); + return { + content: [{ type: 'text', text: `Closed terminal '${name}'.` }], + isError: false, + }; +}; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVybWluYWxfdG9vbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdG9vbHMvdGVybWluYWxfdG9vbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE1BQU0sTUFBTSxRQUFRLENBQUM7QUFDakMsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUN4QixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUdyRSxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDO0lBQ3pDLElBQUksRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxDQUFDLG9DQUFvQyxDQUFDO0lBQzFFLEdBQUcsRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxDQUFDLHFDQUFxQyxDQUFDO0lBQzFFLE9BQU8sRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxDQUFDLHlEQUF5RCxDQUFDO0lBQ2xHLElBQUksRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FBQywrQ0FBK0MsQ0FBQztDQUM1RixDQUFDLENBQUM7QUFHSCxNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUcsS0FBSyxFQUFFLE1BQTRDLEVBQUUsRUFBRTtJQUNqRixNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLEdBQUcsTUFBTSxDQUFDO0lBRTVDLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFFN0QsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUNQLFFBQVEsQ0FBQyxJQUFJLEVB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eEIsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBa0IsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQztJQUV2RixJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDWixPQUFPO1lBQ0gsT0FBTyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxnQ0FBZ0MsSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUMzRSxPQUFPLEVBQUUsSUFBSTtTQUNoQixDQUFDO0lBQ04sQ0FBQztJQUVELFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUVuQixPQUFPO1FBQ0gsT0FBTyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxvQkFBb0IsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUMvRCxPQUFPLEVBQUUsS0FBSztLQUNqQixDQUFDO0FBQ04sQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgdnNjb2RlIGZyb20gJ3ZzY29kZSc7XG5pbXBvcnQgeyB6IH0gZnJvbSAnem9kJztcbmltcG9ydCB7IGdldENvbW1hbmRIaXN0b3J5IH0gZnJvbSAnLi4vdXRpbHMvdGVybWluYWxfb3V0cHV0X2NhcHR1cmUnO1xuXG4vLyBab2Qgc2NoZW1hIGZvciBjcmVhdGVfdGVybWluYWwgcGFyYW1ldGVyc1xuZXhwb3J0IGNvbnN0IGNyZWF0ZVRlcm1pbmFsU2NoZW1hID0gei5vYmplY3Qoe1xuICAgIG5hbWU6IHouc3RyaW5nKCkub3B0aW9uYWwoKS5kZXNjcmliZSgnRGlzcGxheSBuYW1lIGZvciB0aGUgdGVybWluYWwgdGFiLicpLFxuICAgIGN3ZDogei5zdHJpbmcoKS5vcHRpb25hbCgpLmRlc2NyaWJlKCdXb3JraW5nIGRpcmVjdG9yeSBmb3IgdGhlIHRlcm1pbmFsLicpLFxuICAgIGNvbW1hbmQ6IHouc3RyaW5nKCkub3B0aW9uYWwoKS5kZXNjcmliZSgnQ29tbWFuZCB0byBleGVjdXRlIGltbWVkaWF0ZWx5IGFmdGVyIHRlcm1pbmFsIGNyZWF0aW9uLicpLFxuICAgIHNob3c6IHouYm9vbGVhbigpLmRlZmF1bHQodHJ1ZSkuZGVzY3JpYmUoJ1doZXRoZXIgdG8gZm9jdXMgdGhlIHRlcm1pbmFsIGFmdGVyIGNyZWF0aW9uLicpLFxufSk7XG5cbi8qKiBDcmVhdGUgYSBuZXcgdGVybWluYWwgaW4gdGhlIHdvcmtzcGFjZS4gKi9cbmV4cG9ydCBjb25zdCBjcmVhdGVUZXJtaW5hbCA9IGFzeW5jIChwYXJhbXM6IHouaW5mZXI8dHlwZW9mIGNyZWF0ZVRlcm1pbmFsU2NoZW1hPikgPT4ge1xuICAgIGNvbnN0IHsgbmFtZSwgY3dkLCBjb21tYW5kLCBzaG93IH0gPSBwYXJhbXM7XG5cbiAgICBjb25zdCB0ZXJtaW5hbCA9IHZzY29kZS53aW5kb3cuY3JlYXRlVGVybWluYWwoeyBuYW1lLCBjd2QgfSk7XG5cbiAgICBpZiAoc2hvdykge1xuICAgICAgICB0ZXJtaW5hbC5zaG93KCk7XG4gICAgfVxuXG4gICAgaWYgKGNvbW1hbmQpIHtcbiAgICAgICAgdGVybWluYWwuc2VuZFRleHQoY29tbWFuZCk7XG4gICAgfVxuXG4gICAgY29uc3QgdGVybWluYWxOYW1lID0gdGVybWluYWwubmFtZTtcblxuICAgIHJldHVybiB7XG4gICAgICAgIGNvbnRlbnQ6IFt7IHR5cGU6ICd0ZXh0JywgdGV4dDogYFRlcm1pbmFsICcke3Rlcm1pbmFsTmFtZX0nIGNyZWF0ZWQgc3VjY2Vzc2Z1bGx5LmAgfV0sXG4gICAgICAgIGlzRXJyb3I6IGZhbHNlLFxuICAgIH07XG59O1xuXG4vLyBab2Qgc2NoZW1hIGZvciBsaXN0X3Rlcm1pbmFscyAobm8gcGFyYW1ldGVycylcbmV4cG9ydCBjb25zdCBsaXN0VGVybWluYWxzU2NoZW1hID0gei5vYmplY3Qoe30pO1xuXG4vKiogTGlzdCBhbGwgYWN0aXZlIHRlcm1pbmFscyBpbiB0aGUgd29ya3NwYWNlLiAqL1xuZXhwb3J0IGNvbnN0IGxpc3RUZXJtaW5hbHMgPSAoKSA9PiB7XG4gICAgY29uc3QgdGVybWluYWxzID0gdnNjb2RlLndpbmRvdy50ZXJtaW5hbHMubWFwKCh0ZXJtaW5hbDogdnNjb2RlLlRlcm1pbmFsLCBpbmRleDogbnVtYmVyKSA9PiAoe1xuICAgICAgICBpbmRleCxcbiAgICAgICAgbmFtZTogdGVybWluYWwubmFtZSxcbiAgICAgICAgcHJvY2Vzc0lkOiB0ZXJtaW5hbC5wcm9jZXNzSWQsXG4gICAgfSkpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgY29udGVudDogW3sgdHlwZTogJ2pzb24nLCBqc29uOiB7IHRlcm1pbmFscyB9IH1dLFxuICAgICAgICBpc0Vycm9yOiBmYWxzZSxcbiAgICB9O1xufTtcblxuLy8gWm9kIHNjaGVtYSBmb3Igc2VuZF90ZXJtaW5hbF90ZXh0IHBhcmFtZXRlcnNcbmV4cG9ydCBjb25zdCBzZW5kVGVybWluYWxUZXh0U2NoZW1hID0gei5vYmplY3Qoe1xuICAgIG5hbWU6IHouc3RyaW5nKCkuZGVzY3JpYmUoJ05hbWUgb2YgdGhlIHRhcmdldCB0ZXJtaW5hbC4nKSxcbiAgICB0ZXh0OiB6LnN0cmluZygpLmRlc2NyaWJlKCdUZXh0IHRvIHNlbmQgdG8gdGhlIHRlcm1pbmFsLicpLFxuICAgIGFkZE5ld0xpbmU6IHouYm9vbGVhbigpLmRlZmF1bHQodHJ1ZSkuZGVzY3JpYmUoJ1doZXRoZXIgdG8gYXBwZW5kIGEgbmV3bGluZSAoc2ltdWxhdGluZyBFbnRlciBrZXkpLicpLFxufSk7XG5cbi8qKiBTZW5kIHRleHQgdG8gYW4gZXhpc3RpbmcgdGVybWluYWwgYnkgbmFtZS4gKi9cbmV4cG9ydCBjb25zdCBzZW5kVGVybWluYWxUZXh0ID0gYXN5bmMgKHBhcmFtczogei5pbmZlcjx0eXBlb2Ygc2VuZFRlcm1pbmFsVGV4dFNjaGVtYT4pID0+IHtcbiAgICBjb25zdCB7IG5hbWUsIHRleHQsIGFkZE5ld0xpbmUgfSA9IHBhcmFtcztcbiAgICBjb25zdCB0ZXJtaW5hbCA9IHZzY29kZS53aW5kb3cudGVybWluYWxzLmZpbmQoKHQ6IHZzY29kZS5UZXJtaW5hbCkgPT4gdC5uYW1lID09PSBuYW1lKTtcblxuICAgIGlmICghdGVybWluYWwpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGNvbnRlbnQ6IFt7IHR5cGU6ICd0ZXh0JywgdGV4dDogYE5vIHRlcm1pbmFsIGZvdW5kIHdpdGggbmFtZSAnJHtuYW1lfScuYCB9XSxcbiAgICAgICAgICAgIGlzRXJyb3I6IHRydWUsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdGVybWluYWwuc2VuZFRleHQodGV4dCwgYWRkTmV3TGluZSk7XG4gICAgdGVybWluYWwuc2hvdygpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgY29udGVudDogW3sgdHlwZTogJ3RleHQnLCB0ZXh0OiBgU2VudCB0ZXh0IHRvIHRlcm1pbmFsICcke25hbWV9Jy5gIH1dLFxuICAgICAgICBpc0Vycm9yOiBmYWxzZSxcbiAgICB9O1xufTtcblxuLy8gWm9kIHNjaGVtYSBmb3IgY2xvc2VfdGVybWluYWwgcGFyYW1ldGVyc1xuZXhwb3J0IGNvbnN0IGNsb3NlVGVybWluYWxTY2hlbWEgPSB6Lm9iamVjdCh7XG4gICAgbmFtZTogei5zdHJpbmcoKS5kZXNjcmliZSgnTmFtZSBvZiB0aGUgdGVybWluYWwgdG8gY2xvc2UuJyksXG59KTtcblxuLy8gWm9kIHNjaGVtYSBmb3IgZ2V0X3Rlcm1pbmFsX291dHB1dCBwYXJhbWV0ZXJzXG5leHBvcnQgY29uc3QgZ2V0VGVybWluYWxPdXRwdXRTY2hlbWEgPSB6Lm9iamVjdCh7XG4gICAgbmFtZTogei5zdHJpbmcoKS5kZXNjcmliZSgnTmFtZSBvZiB0aGUgdGVybWluYWwgdG8gcmVhZCBvdXRwdXQgZnJvbS4nKSxcbiAgICBjb21tYW5kSW5kZXg6IHpcbiAgICAgICAgLm51bWJlcigpXG4gICAgICAgIC5pbnQoKVxuICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAuZGVzY3JpYmUoJ0luZGV4IG9mIGEgc3BlY2lmaWMgY29tbWFuZCB0byByZWFkICgwLWJhc2VkLCBtb3N0IHJlY2VudCBsYXN0KS4gT21pdCB0byBnZXQgYWxsIHJlY2VudCBjb21tYW5kcy4nKSxcbiAgICBsaW1pdDogelxuICAgICAgICAubnVtYmVyKClcbiAgICAgICAgLmludCgpXG4gICAgICAgIC5taW4oMSlcbiAgICAgICAgLm1heCg1MClcbiAgICAgICAgLmRlZmF1bHQoMTApXG4gICAgICAgIC5kZXNjcmliZSgnTWF4aW11bSBudW1iZXIgb2YgcmVjZW50IGNvbW1hbmRzIHRvIHJldHVybiAod2hlbiBjb21tYW5kSW5kZXggaXMgbm90IHNwZWNpZmllZCkuJyksXG59KTtcblxuLyoqXG4gKiBSZWFkIGNhcHR1cmVkIGNvbW1hbmQgb3V0cHV0IGZyb20gYSB0ZXJtaW5hbC5cbiAqXG4gKiBPdXRwdXQgaXMgY2FwdHVyZWQgcGVyLWNvbW1hbmQgdmlhIHNoZWxsIGV4ZWN1dGlvbiBldmVudHMgKHN0YWJsZSBBUEkgMS45MyspLlxuICogUmV0dXJucyBjbGVhbiBvdXRwdXQgd2l0aG91dCBBTlNJIGVzY2FwZSBjb2Rlcy4gUmVxdWlyZXMgc2hlbGwgaW50ZWdyYXRpb24uXG4gKi9cbmV4cG9ydCBjb25zdCBnZXRUZXJtaW5hbE91dHB1dCA9IGFzeW5jIChwYXJhbXM6IHouaW5mZXI8dHlwZW9mIGdldFRlcm1pbmFsT3V0cHV0U2NoZW1hPikgPT4ge1xuICAgIGNvbnN0IHsgbmFtZSwgY29tbWFuZEluZGV4LCBsaW1pdCB9ID0gcGFyYW1zO1xuICAgIGNvbnN0IGhpc3RvcnkgPSBnZXRDb21tYW5kSGlzdG9yeShuYW1lKTtcblxuICAgIGlmICghaGlzdG9yeSB8fCBoaXN0b3J5Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY29udGVudDogW3sgdHlwZTogJ3RleHQnLCB0ZXh0OiBgTm8gb3V0cHV0IGNhcHR1cmVkIGZvciB0ZXJtaW5hbCAnJHtuYW1lfScuIFNoZWxsIGludGVncmF0aW9uIG1heSBub3QgYmUgYWN0aXZlLmAgfV0sXG4gICAgICAgICAgICBpc0Vycm9yOiB0cnVlLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGlmIChjb21tYW5kSW5kZXggIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpZiAoY29tbWFuZEluZGV4IDwgMCB8fCBjb21tYW5kSW5kZXggPj0gaGlzdG9yeS5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgY29udGVudDogW3sgdHlwZTogJ3RleHQnLCB0ZXh0OiBgQ29tbWFuZCBpbmRleCAke2NvbW1hbmRJbmRleH0gb3V0IG9mIHJhbmdlICgwLSR7aGlzdG9yeS5sZW5ndGggLSAxfSkuYCB9XSxcbiAgICAgICAgICAgICAgICBpc0Vycm9yOiB0cnVlLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCByZWNvcmQgPSBoaXN0b3J5W2NvbW1hbmRJbmRleF07XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBjb250ZW50OiBbeyB0eXBlOiAndGV4dCcsIHRleHQ6IEpTT04uc3RyaW5naWZ5KHsgY29tbWFuZDogcmVjb3JkLmNvbW1hbmQsIG91dHB1dDogcmVjb3JkLm91dHB1dCwgaW5kZXg6IGNvbW1hbmRJbmRleCB9KSB9XSxcbiAgICAgICAgICAgIGlzRXJyb3I6IGZhbHNlLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IHJlY2VudCA9IGhpc3Rvcnkuc2xpY2UoLWxpbWl0KTtcbiAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ3RleHQnLFxuICAgICAgICAgICAgICAgIHRleHQ6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgICAgICAgY29tbWFuZHM6IHJlY2VudC5tYXAoKHIsIGkpID0+ICh7IGluZGV4OiBoaXN0b3J5Lmxlbmd0aCAtIHJlY2VudC5sZW5ndGggKyBpLCBjb21tYW5kOiByLmNvbW1hbmQsIG91dHB1dDogci5vdXRwdXQgfSkpLFxuICAgICAgICAgICAgICAgICAgICB0b3RhbENvbW1hbmRzOiBoaXN0b3J5Lmxlbmd0aCxcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICAgIGlzRXJyb3I6IGZhbHNlLFxuICAgIH07XG59O1xuXG4vKiogQ2xvc2UgYSB0ZXJtaW5hbCBieSBuYW1lLiAqL1xuZXhwb3J0IGNvbnN0IGNsb3NlVGVybWluYWwgPSBhc3luYyAocGFyYW1zOiB6LmluZmVyPHR5cGVvZiBjbG9zZVRlcm1pbmFsU2NoZW1hPikgPT4ge1xuICAgIGNvbnN0IHsgbmFtZSB9ID0gcGFyYW1zO1xuICAgIGNvbnN0IHRlcm1pbmFsID0gdnNjb2RlLndpbmRvdy50ZXJtaW5hbHMuZmluZCgodDogdnNjb2RlLlRlcm1pbmFsKSA9PiB0Lm5hbWUgPT09IG5hbWUpO1xuXG4gICAgaWYgKCF0ZXJtaW5hbCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY29udGVudDogW3sgdHlwZTogJ3RleHQnLCB0ZXh0OiBgTm8gdGVybWluYWwgZm91bmQgd2l0aCBuYW1lICcke25hbWV9Jy5gIH1dLFxuICAgICAgICAgICAgaXNFcnJvcjogdHJ1ZSxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICB0ZXJtaW5hbC5kaXNwb3NlKCk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbeyB0eXBlOiAndGV4dCcsIHRleHQ6IGBDbG9zZWQgdGVybWluYWwgJyR7bmFtZX0nLmAgfV0sXG4gICAgICAgIGlzRXJyb3I6IGZhbHNlLFxuICAgIH07XG59O1xuIl19 \ No newline at end of file diff --git a/mcp-servers/mcp-server-vscode/out/utils/terminal_output_capture.d.ts b/mcp-servers/mcp-server-vscode/out/utils/terminal_output_capture.d.ts new file mode 100644 index 000000000..26b178d42 --- /dev/null +++ b/mcp-servers/mcp-server-vscode/out/utils/terminal_output_capture.d.ts @@ -0,0 +1,8 @@ +import * as vscode from 'vscode'; +interface CommandRecord { + command: string; + output: string; +} +export declare const initTerminalOutputCapture: (context: vscode.ExtensionContext) => void; +export declare const getCommandHistory: (name: string) => CommandRecord[] | undefined; +export {}; diff --git a/mcp-servers/mcp-server-vscode/out/utils/terminal_output_capture.js b/mcp-servers/mcp-server-vscode/out/utils/terminal_output_capture.js new file mode 100644 index 000000000..4aea849db --- /dev/null +++ b/mcp-servers/mcp-server-vscode/out/utils/terminal_output_capture.js @@ -0,0 +1,36 @@ +import * as vscode from 'vscode'; +const commandHistory = new Map(); +const MAX_HISTORY_PER_TERMINAL = 50; +export const initTerminalOutputCapture = (context) => { + const startListener = vscode.window.onDidStartTerminalShellExecution(async (event) => { + const terminalName = event.terminal.name; + const execution = event.execution; + const chunks = []; + for await (const data of execution.read()) { + chunks.push(data); + } + const commandLine = execution.commandLine?.value ?? '(unknown)'; + const record = { + command: commandLine, + output: chunks.join(''), + }; + if (!commandHistory.has(terminalName)) { + commandHistory.set(terminalName, []); + } + const history = commandHistory.get(terminalName); + history.push(record); + if (history.length > MAX_HISTORY_PER_TERMINAL) { + history.splice(0, history.length - MAX_HISTORY_PER_TERMINAL); + } + }); + const closeListener = vscode.window.onDidCloseTerminal((terminal) => { + commandHistory.delete(terminal.name); + }); + context.subscriptions.push(startListener, closeListener, { + dispose: () => { + commandHistory.clear(); + }, + }); +}; +export const getCommandHistory = (name) => commandHistory.get(name); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVybWluYWxfb3V0cHV0X2NhcHR1cmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvdGVybWluYWxfb3V0cHV0X2NhcHR1cmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE1BQU0sTUFBTSxRQUFRLENBQUM7QUFRakMsTUFBTSxjQUFjLEdBQUcsSUFBSSxHQUFHLEVBQTJCLENBQUM7QUFHMUQsTUFBTSx3QkFBd0IsR0FBRyxFQUFFLENBQUM7QUFXcEMsTUFBTSxDQUFDLE1BQU0seUJBQXlCLEdBQUcsQ0FBQyxPQUFnQyxFQUFFLEVBQUU7SUFDMUUsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxnQ0FBZ0MsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUU7UUFDakYsTUFBTSxZQUFZLEdBQUcsS0FBSyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7UUFDekMsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQztRQUNsQyxNQUFNLE1BQU0sR0FBYSxFQUFFLENBQUM7UUFFNUIsSUFBSSxLQUFLLEVBQUUsTUFBTSxJQUFJLElBQUksU0FBUyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUM7WUFDeEMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN0QixDQUFDO1FBRUQsTUFBTSxXQUFXLEdBQUcsU0FBUyxDQUFDLFdBQVcsRUFBRSxLQUFLLElBQUksV0FBVyxDQUFDO1FBQ2hFLE1BQU0sTUFBTSxHQUFrQjtZQUMxQixPQUFPLEVBQUUsV0FBVztZQUNwQixNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7U0FDMUIsQ0FBQztRQUVGLElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7WUFDcEMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDekMsQ0FBQztRQUVELE1BQU0sT0FBTyxHQUFHLGNBQWMsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFFLENBQUM7UUFDbEQsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUdyQixJQUFJLE9BQU8sQ0FBQyxNQUFNLEdBQUcsd0JBQXdCLEVBQUUsQ0FBQztZQUM1QyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsTUFBTSxHQUFHLHdCQUF3QixDQUFDLENBQUM7UUFDakUsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFO1FBQ2hFLGNBQWMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3pDLENBQUMsQ0FBQyxDQUFDO0lBRUgsT0FBTyxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLGFBQWEsRUFBRTtRQUNyRCxPQUFPLEVBQUUsR0FBRyxFQUFFO1lBQ1YsY0FBYyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzNCLENBQUM7S0FDSixDQUFDLENBQUM7QUFDUCxDQUFDLENBQUM7QUFHRixNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLElBQVksRUFBK0IsRUFBRSxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyB2c2NvZGUgZnJvbSAndnNjb2RlJztcblxuaW50ZXJmYWNlIENvbW1hbmRSZWNvcmQge1xuICAgIGNvbW1hbmQ6IHN0cmluZztcbiAgICBvdXRwdXQ6IHN0cmluZztcbn1cblxuLyoqIFRlcm1pbmFsIG5hbWUg4oaSIGFycmF5IG9mIGNvbW1hbmQgcmVjb3JkcyAobW9zdCByZWNlbnQgbGFzdCkgKi9cbmNvbnN0IGNvbW1hbmRIaXN0b3J5ID0gbmV3IE1hcDxzdHJpbmcsIENvbW1hbmRSZWNvcmRbXT4oKTtcblxuLyoqIE1heGltdW0gbnVtYmVyIG9mIGNvbW1hbmQgcmVjb3JkcyB0byBrZWVwIHBlciB0ZXJtaW5hbCAqL1xuY29uc3QgTUFYX0hJU1RPUllfUEVSX1RFUk1JTkFMID0gNTA7XG5cbi8qKlxuICogSW5pdGlhbGl6ZSB0ZXJtaW5hbCBvdXRwdXQgY2FwdHVyZSB1c2luZyBzaGVsbCBleGVjdXRpb24gZXZlbnRzLlxuICpcbiAqIExpc3RlbnMgdG8gYG9uRGlkU3RhcnRUZXJtaW5hbFNoZWxsRXhlY3V0aW9uYCB0byBjYXB0dXJlIHBlci1jb21tYW5kXG4gKiBvdXRwdXQgdmlhIGBUZXJtaW5hbFNoZWxsRXhlY3V0aW9uLnJlYWQoKWAuIFRoaXMgaXMgYSBzdGFibGUgQVBJICgxLjkzKylcbiAqIHRoYXQgcmV0dXJucyBjbGVhbiBvdXRwdXQgd2l0aG91dCBBTlNJIGVzY2FwZSBjb2Rlcy5cbiAqXG4gKiBSZXF1aXJlcyBWUyBDb2RlIHNoZWxsIGludGVncmF0aW9uIHRvIGJlIGFjdGl2ZSAoZW5hYmxlZCBieSBkZWZhdWx0KS5cbiAqL1xuZXhwb3J0IGNvbnN0IGluaXRUZXJtaW5hbE91dHB1dENhcHR1cmUgPSAoY29udGV4dDogdnNjb2RlLkV4dGVuc2lvbkNvbnRleHQpID0+IHtcbiAgICBjb25zdCBzdGFydExpc3RlbmVyID0gdnNjb2RlLndpbmRvdy5vbkRpZFN0YXJ0VGVybWluYWxTaGVsbEV4ZWN1dGlvbihhc3luYyAoZXZlbnQpID0+IHtcbiAgICAgICAgY29uc3QgdGVybWluYWxOYW1lID0gZXZlbnQudGVybWluYWwubmFtZTtcbiAgICAgICAgY29uc3QgZXhlY3V0aW9uID0gZXZlbnQuZXhlY3V0aW9uO1xuICAgICAgICBjb25zdCBjaHVua3M6IHN0cmluZ1tdID0gW107XG5cbiAgICAgICAgZm9yIGF3YWl0IChjb25zdCBkYXRhIG9mIGV4ZWN1dGlvbi5yZWFkKCkpIHtcbiAgICAgICAgICAgIGNodW5rcy5wdXNoKGRhdGEpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY29tbWFuZExpbmUgPSBleGVjdXRpb24uY29tbWFuZExpbmU/LnZhbHVlID8/ICcodW5rbm93biknO1xuICAgICAgICBjb25zdCByZWNvcmQ6IENvbW1hbmRSZWNvcmQgPSB7XG4gICAgICAgICAgICBjb21tYW5kOiBjb21tYW5kTGluZSxcbiAgICAgICAgICAgIG91dHB1dDogY2h1bmtzLmpvaW4oJycpLFxuICAgICAgICB9O1xuXG4gICAgICAgIGlmICghY29tbWFuZEhpc3RvcnkuaGFzKHRlcm1pbmFsTmFtZSkpIHtcbiAgICAgICAgICAgIGNvbW1hbmRIaXN0b3J5LnNldCh0ZXJtaW5hbE5hbWUsIFtdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGhpc3RvcnkgPSBjb21tYW5kSGlzdG9yeS5nZXQodGVybWluYWxOYW1lKSE7XG4gICAgICAgIGhpc3RvcnkucHVzaChyZWNvcmQpO1xuXG4gICAgICAgIC8vIEV2aWN0IG9sZGVzdCByZWNvcmRzIGlmIG92ZXIgbGltaXRcbiAgICAgICAgaWYgKGhpc3RvcnkubGVuZ3RoID4gTUFYX0hJU1RPUllfUEVSX1RFUk1JTkFMKSB7XG4gICAgICAgICAgICBoaXN0b3J5LnNwbGljZSgwLCBoaXN0b3J5Lmxlbmd0aCAtIE1BWF9ISVNUT1JZX1BFUl9URVJNSU5BTCk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIGNvbnN0IGNsb3NlTGlzdGVuZXIgPSB2c2NvZGUud2luZG93Lm9uRGlkQ2xvc2VUZXJtaW5hbCgodGVybWluYWwpID0+IHtcbiAgICAgICAgY29tbWFuZEhpc3RvcnkuZGVsZXRlKHRlcm1pbmFsLm5hbWUpO1xuICAgIH0pO1xuXG4gICAgY29udGV4dC5zdWJzY3JpcHRpb25zLnB1c2goc3RhcnRMaXN0ZW5lciwgY2xvc2VMaXN0ZW5lciwge1xuICAgICAgICBkaXNwb3NlOiAoKSA9PiB7XG4gICAgICAgICAgICBjb21tYW5kSGlzdG9yeS5jbGVhcigpO1xuICAgICAgICB9LFxuICAgIH0pO1xufTtcblxuLyoqIEdldCB0aGUgY29tbWFuZCBoaXN0b3J5IGZvciBhIHRlcm1pbmFsLiAqL1xuZXhwb3J0IGNvbnN0IGdldENvbW1hbmRIaXN0b3J5ID0gKG5hbWU6IHN0cmluZyk6IENvbW1hbmRSZWNvcmRbXSB8IHVuZGVmaW5lZCA9PiBjb21tYW5kSGlzdG9yeS5nZXQobmFtZSk7XG4iXX0= \ No newline at end of file diff --git a/mcp-servers/mcp-server-vscode/src/extension.ts b/mcp-servers/mcp-server-vscode/src/extension.ts index 85a4eb161..fc179f494 100644 --- a/mcp-servers/mcp-server-vscode/src/extension.ts +++ b/mcp-servers/mcp-server-vscode/src/extension.ts @@ -17,7 +17,20 @@ import { stopDebugSessionSchema, } from './tools/debug_tools'; import { focusEditorTool } from './tools/focus_editor'; +import { + closeTerminal, + closeTerminalSchema, + createTerminal, + createTerminalSchema, + getTerminalOutput, + getTerminalOutputSchema, + listTerminals, + listTerminalsSchema, + sendTerminalText, + sendTerminalTextSchema, +} from './tools/terminal_tools'; import { resolvePort } from './utils/port'; +import { initTerminalOutputCapture } from './utils/terminal_output_capture'; const extensionName = 'vscode-mcp-server'; const extensionDisplayName = 'VSCode MCP Server'; @@ -191,6 +204,102 @@ export const activate = async (context: vscode.ExtensionContext) => { }, ); + // Register 'create_terminal' tool + mcpServer.tool( + 'create_terminal', + dedent` + Create a new integrated terminal in the VSCode workspace. + Optionally set a name, working directory, and an initial command to execute. + `.trim(), + createTerminalSchema.shape, + async (params) => { + const result = await createTerminal(params); + return { + ...result, + content: result.content.map((item) => ({ + ...item, + type: 'text' as const, + })), + }; + }, + ); + + // Register 'list_terminals' tool + mcpServer.tool( + 'list_terminals', + 'List all active terminals in the workspace.', + listTerminalsSchema.shape, + async () => { + const result = listTerminals(); + return { + ...result, + content: result.content.map((item) => ({ type: 'text', text: JSON.stringify(item.json) })), + }; + }, + ); + + // Register 'send_terminal_text' tool + mcpServer.tool( + 'send_terminal_text', + dedent` + Send text to an existing terminal by name. + Use this to execute commands or type input in a terminal that was previously created. + `.trim(), + sendTerminalTextSchema.shape, + async (params) => { + const result = await sendTerminalText(params); + return { + ...result, + content: result.content.map((item) => ({ + ...item, + type: 'text' as const, + })), + }; + }, + ); + + // Register 'close_terminal' tool + mcpServer.tool( + 'close_terminal', + 'Close an active terminal by name.', + closeTerminalSchema.shape, + async (params) => { + const result = await closeTerminal(params); + return { + ...result, + content: result.content.map((item) => ({ + ...item, + type: 'text' as const, + })), + }; + }, + ); + + // Register 'get_terminal_output' tool + mcpServer.tool( + 'get_terminal_output', + dedent` + Read captured command output from a terminal. + Output is captured per-command via shell execution events. + Returns clean output without ANSI escape codes. + Requires VS Code shell integration to be active (enabled by default). + `.trim(), + getTerminalOutputSchema.shape, + async (params) => { + const result = await getTerminalOutput(params); + return { + ...result, + content: result.content.map((item) => ({ + ...item, + type: 'text' as const, + })), + }; + }, + ); + + // Initialize terminal output capture (shell execution events) + initTerminalOutputCapture(context); + // Set up an Express app to handle SSE connections const app = express(); const mcpConfig = vscode.workspace.getConfiguration('mcpServer'); diff --git a/mcp-servers/mcp-server-vscode/src/test/terminal_tools.test.d.ts b/mcp-servers/mcp-server-vscode/src/test/terminal_tools.test.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/mcp-servers/mcp-server-vscode/src/test/terminal_tools.test.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/mcp-servers/mcp-server-vscode/src/test/terminal_tools.test.ts b/mcp-servers/mcp-server-vscode/src/test/terminal_tools.test.ts new file mode 100644 index 000000000..32c32d2b5 --- /dev/null +++ b/mcp-servers/mcp-server-vscode/src/test/terminal_tools.test.ts @@ -0,0 +1,98 @@ +import * as assert from 'assert'; +import { + closeTerminalSchema, + createTerminalSchema, + getTerminalOutputSchema, + listTerminalsSchema, + sendTerminalTextSchema, +} from '../tools/terminal_tools'; + +suite('Terminal Tools Schema Test Suite', () => { + test('createTerminalSchema accepts valid params with all fields', () => { + const result = createTerminalSchema.safeParse({ + name: 'my-terminal', + cwd: '/tmp', + command: 'echo hello', + show: true, + }); + assert.strictEqual(result.success, true); + }); + + test('createTerminalSchema accepts empty params (all optional)', () => { + const result = createTerminalSchema.safeParse({}); + assert.strictEqual(result.success, true); + if (result.success) { + assert.strictEqual(result.data.show, true); // default value + } + }); + + test('createTerminalSchema rejects invalid show type', () => { + const result = createTerminalSchema.safeParse({ show: 'yes' }); + assert.strictEqual(result.success, false); + }); + + test('listTerminalsSchema accepts empty params', () => { + const result = listTerminalsSchema.safeParse({}); + assert.strictEqual(result.success, true); + }); + + test('sendTerminalTextSchema requires name and text', () => { + const valid = sendTerminalTextSchema.safeParse({ + name: 'my-terminal', + text: 'ls -la', + }); + assert.strictEqual(valid.success, true); + + const missingName = sendTerminalTextSchema.safeParse({ text: 'ls' }); + assert.strictEqual(missingName.success, false); + + const missingText = sendTerminalTextSchema.safeParse({ name: 'my-terminal' }); + assert.strictEqual(missingText.success, false); + }); + + test('sendTerminalTextSchema defaults addNewLine to true', () => { + const result = sendTerminalTextSchema.safeParse({ + name: 'my-terminal', + text: 'ls', + }); + assert.strictEqual(result.success, true); + if (result.success) { + assert.strictEqual(result.data.addNewLine, true); + } + }); + + test('closeTerminalSchema requires name', () => { + const valid = closeTerminalSchema.safeParse({ name: 'my-terminal' }); + assert.strictEqual(valid.success, true); + + const missing = closeTerminalSchema.safeParse({}); + assert.strictEqual(missing.success, false); + }); + + test('getTerminalOutputSchema accepts name only (defaults applied)', () => { + const result = getTerminalOutputSchema.safeParse({ name: 'my-terminal' }); + assert.strictEqual(result.success, true); + if (result.success) { + assert.strictEqual(result.data.limit, 10); + assert.strictEqual(result.data.commandIndex, undefined); + } + }); + + test('getTerminalOutputSchema accepts commandIndex', () => { + const result = getTerminalOutputSchema.safeParse({ name: 'my-terminal', commandIndex: 3 }); + assert.strictEqual(result.success, true); + if (result.success) { + assert.strictEqual(result.data.commandIndex, 3); + } + }); + + test('getTerminalOutputSchema rejects limit over 50', () => { + const result = getTerminalOutputSchema.safeParse({ name: 'my-terminal', limit: 100 }); + assert.strictEqual(result.success, false); + }); + + test('getTerminalOutputSchema requires name', () => { + const result = getTerminalOutputSchema.safeParse({}); + assert.strictEqual(result.success, false); + }); +}); diff --git a/mcp-servers/mcp-server-vscode/src/tools/terminal_tools.d.ts b/mcp-servers/mcp-server-vscode/src/tools/terminal_tools.d.ts new file mode 100644 index 000000000..ae88f63d7 --- /dev/null +++ b/mcp-servers/mcp-server-vscode/src/tools/terminal_tools.d.ts @@ -0,0 +1,92 @@ +import { z } from 'zod'; +export declare const createTerminalSchema: z.ZodObject<{ + name: z.ZodOptional; + cwd: z.ZodOptional; + command: z.ZodOptional; + show: z.ZodDefault; +}, "strip", z.ZodTypeAny, { + show: boolean; + name?: string | undefined; + cwd?: string | undefined; + command?: string | undefined; +}, { + name?: string | undefined; + cwd?: string | undefined; + command?: string | undefined; + show?: boolean | undefined; +}>; +export declare const createTerminal: (params: z.infer) => Promise<{ + content: { + type: string; + text: string; + }[]; + isError: boolean; +}>; +export declare const listTerminalsSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>; +export declare const listTerminals: () => { + content: { + type: string; + json: { + terminals: { + index: number; + name: string; + processId: Thenable; + }[]; + }; + }[]; + isError: boolean; +}; +export declare const sendTerminalTextSchema: z.ZodObject<{ + name: z.ZodString; + text: z.ZodString; + addNewLine: z.ZodDefault; +}, "strip", z.ZodTypeAny, { + name: string; + text: string; + addNewLine: boolean; +}, { + name: string; + text: string; + addNewLine?: boolean | undefined; +}>; +export declare const sendTerminalText: (params: z.infer) => Promise<{ + content: { + type: string; + text: string; + }[]; + isError: boolean; +}>; +export declare const closeTerminalSchema: z.ZodObject<{ + name: z.ZodString; +}, "strip", z.ZodTypeAny, { + name: string; +}, { + name: string; +}>; +export declare const getTerminalOutputSchema: z.ZodObject<{ + name: z.ZodString; + commandIndex: z.ZodOptional; + limit: z.ZodDefault; +}, "strip", z.ZodTypeAny, { + name: string; + limit: number; + commandIndex?: number | undefined; +}, { + name: string; + commandIndex?: number | undefined; + limit?: number | undefined; +}>; +export declare const getTerminalOutput: (params: z.infer) => Promise<{ + content: { + type: string; + text: string; + }[]; + isError: boolean; +}>; +export declare const closeTerminal: (params: z.infer) => Promise<{ + content: { + type: string; + text: string; + }[]; + isError: boolean; +}>; diff --git a/mcp-servers/mcp-server-vscode/src/tools/terminal_tools.ts b/mcp-servers/mcp-server-vscode/src/tools/terminal_tools.ts new file mode 100644 index 000000000..355023c2a --- /dev/null +++ b/mcp-servers/mcp-server-vscode/src/tools/terminal_tools.ts @@ -0,0 +1,166 @@ +import * as vscode from 'vscode'; +import { z } from 'zod'; +import { getCommandHistory } from '../utils/terminal_output_capture'; + +// Zod schema for create_terminal parameters +export const createTerminalSchema = z.object({ + name: z.string().optional().describe('Display name for the terminal tab.'), + cwd: z.string().optional().describe('Working directory for the terminal.'), + command: z.string().optional().describe('Command to execute immediately after terminal creation.'), + show: z.boolean().default(true).describe('Whether to focus the terminal after creation.'), +}); + +/** Create a new terminal in the workspace. */ +export const createTerminal = async (params: z.infer) => { + const { name, cwd, command, show } = params; + + const terminal = vscode.window.createTerminal({ name, cwd }); + + if (show) { + terminal.show(); + } + + if (command) { + terminal.sendText(command); + } + + const terminalName = terminal.name; + + return { + content: [{ type: 'text', text: `Terminal '${terminalName}' created successfully.` }], + isError: false, + }; +}; + +// Zod schema for list_terminals (no parameters) +export const listTerminalsSchema = z.object({}); + +/** List all active terminals in the workspace. */ +export const listTerminals = () => { + const terminals = vscode.window.terminals.map((terminal: vscode.Terminal, index: number) => ({ + index, + name: terminal.name, + processId: terminal.processId, + })); + + return { + content: [{ type: 'json', json: { terminals } }], + isError: false, + }; +}; + +// Zod schema for send_terminal_text parameters +export const sendTerminalTextSchema = z.object({ + name: z.string().describe('Name of the target terminal.'), + text: z.string().describe('Text to send to the terminal.'), + addNewLine: z.boolean().default(true).describe('Whether to append a newline (simulating Enter key).'), +}); + +/** Send text to an existing terminal by name. */ +export const sendTerminalText = async (params: z.infer) => { + const { name, text, addNewLine } = params; + const terminal = vscode.window.terminals.find((t: vscode.Terminal) => t.name === name); + + if (!terminal) { + return { + content: [{ type: 'text', text: `No terminal found with name '${name}'.` }], + isError: true, + }; + } + + terminal.sendText(text, addNewLine); + terminal.show(); + + return { + content: [{ type: 'text', text: `Sent text to terminal '${name}'.` }], + isError: false, + }; +}; + +// Zod schema for close_terminal parameters +export const closeTerminalSchema = z.object({ + name: z.string().describe('Name of the terminal to close.'), +}); + +// Zod schema for get_terminal_output parameters +export const getTerminalOutputSchema = z.object({ + name: z.string().describe('Name of the terminal to read output from.'), + commandIndex: z + .number() + .int() + .optional() + .describe('Index of a specific command to read (0-based, most recent last). Omit to get all recent commands.'), + limit: z + .number() + .int() + .min(1) + .max(50) + .default(10) + .describe('Maximum number of recent commands to return (when commandIndex is not specified).'), +}); + +/** + * Read captured command output from a terminal. + * + * Output is captured per-command via shell execution events (stable API 1.93+). + * Returns clean output without ANSI escape codes. Requires shell integration. + */ +export const getTerminalOutput = async (params: z.infer) => { + const { name, commandIndex, limit } = params; + const history = getCommandHistory(name); + + if (!history || history.length === 0) { + return { + content: [{ type: 'text', text: `No output captured for terminal '${name}'. Shell integration may not be active.` }], + isError: true, + }; + } + + if (commandIndex !== undefined) { + if (commandIndex < 0 || commandIndex >= history.length) { + return { + content: [{ type: 'text', text: `Command index ${commandIndex} out of range (0-${history.length - 1}).` }], + isError: true, + }; + } + const record = history[commandIndex]; + return { + content: [{ type: 'text', text: JSON.stringify({ command: record.command, output: record.output, index: commandIndex }) }], + isError: false, + }; + } + + const recent = history.slice(-limit); + return { + content: [ + { + type: 'text', + text: JSON.stringify({ + commands: recent.map((r, i) => ({ index: history.length - recent.length + i, command: r.command, output: r.output })), + totalCommands: history.length, + }), + }, + ], + isError: false, + }; +}; + +/** Close a terminal by name. */ +export const closeTerminal = async (params: z.infer) => { + const { name } = params; + const terminal = vscode.window.terminals.find((t: vscode.Terminal) => t.name === name); + + if (!terminal) { + return { + content: [{ type: 'text', text: `No terminal found with name '${name}'.` }], + isError: true, + }; + } + + terminal.dispose(); + + return { + content: [{ type: 'text', text: `Closed terminal '${name}'.` }], + isError: false, + }; +}; diff --git a/mcp-servers/mcp-server-vscode/src/utils/terminal_output_capture.d.ts b/mcp-servers/mcp-server-vscode/src/utils/terminal_output_capture.d.ts new file mode 100644 index 000000000..26b178d42 --- /dev/null +++ b/mcp-servers/mcp-server-vscode/src/utils/terminal_output_capture.d.ts @@ -0,0 +1,8 @@ +import * as vscode from 'vscode'; +interface CommandRecord { + command: string; + output: string; +} +export declare const initTerminalOutputCapture: (context: vscode.ExtensionContext) => void; +export declare const getCommandHistory: (name: string) => CommandRecord[] | undefined; +export {}; diff --git a/mcp-servers/mcp-server-vscode/src/utils/terminal_output_capture.ts b/mcp-servers/mcp-server-vscode/src/utils/terminal_output_capture.ts new file mode 100644 index 000000000..e1ef8df9a --- /dev/null +++ b/mcp-servers/mcp-server-vscode/src/utils/terminal_output_capture.ts @@ -0,0 +1,64 @@ +import * as vscode from 'vscode'; + +interface CommandRecord { + command: string; + output: string; +} + +/** Terminal name → array of command records (most recent last) */ +const commandHistory = new Map(); + +/** Maximum number of command records to keep per terminal */ +const MAX_HISTORY_PER_TERMINAL = 50; + +/** + * Initialize terminal output capture using shell execution events. + * + * Listens to `onDidStartTerminalShellExecution` to capture per-command + * output via `TerminalShellExecution.read()`. This is a stable API (1.93+) + * that returns clean output without ANSI escape codes. + * + * Requires VS Code shell integration to be active (enabled by default). + */ +export const initTerminalOutputCapture = (context: vscode.ExtensionContext) => { + const startListener = vscode.window.onDidStartTerminalShellExecution(async (event) => { + const terminalName = event.terminal.name; + const execution = event.execution; + const chunks: string[] = []; + + for await (const data of execution.read()) { + chunks.push(data); + } + + const commandLine = execution.commandLine?.value ?? '(unknown)'; + const record: CommandRecord = { + command: commandLine, + output: chunks.join(''), + }; + + if (!commandHistory.has(terminalName)) { + commandHistory.set(terminalName, []); + } + + const history = commandHistory.get(terminalName)!; + history.push(record); + + // Evict oldest records if over limit + if (history.length > MAX_HISTORY_PER_TERMINAL) { + history.splice(0, history.length - MAX_HISTORY_PER_TERMINAL); + } + }); + + const closeListener = vscode.window.onDidCloseTerminal((terminal) => { + commandHistory.delete(terminal.name); + }); + + context.subscriptions.push(startListener, closeListener, { + dispose: () => { + commandHistory.clear(); + }, + }); +}; + +/** Get the command history for a terminal. */ +export const getCommandHistory = (name: string): CommandRecord[] | undefined => commandHistory.get(name);