@epic-web/workshop-mcp 6.47.6 → 6.47.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -0
- package/dist/{esm/index.js → index.js} +3 -4
- package/dist/{esm/prompts.d.ts → prompts.d.ts} +0 -1
- package/dist/{esm/prompts.js → prompts.js} +2 -3
- package/dist/{esm/resources.d.ts → resources.d.ts} +1 -2
- package/dist/{esm/resources.js → resources.js} +1 -2
- package/dist/{esm/tools.d.ts → tools.d.ts} +0 -1
- package/dist/{esm/tools.js → tools.js} +3 -5
- package/dist/{esm/utils.d.ts → utils.d.ts} +0 -1
- package/dist/{esm/utils.js → utils.js} +0 -1
- package/package.json +16 -15
- package/dist/esm/index.d.ts +0 -3
- package/dist/esm/index.d.ts.map +0 -1
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/package.json +0 -3
- package/dist/esm/prompts.d.ts.map +0 -1
- package/dist/esm/prompts.js.map +0 -1
- package/dist/esm/resources.d.ts.map +0 -1
- package/dist/esm/resources.js.map +0 -1
- package/dist/esm/tools.d.ts.map +0 -1
- package/dist/esm/tools.js.map +0 -1
- package/dist/esm/utils.d.ts.map +0 -1
- package/dist/esm/utils.js.map +0 -1
- package/dist/esm/utils.test.d.ts +0 -2
- package/dist/esm/utils.test.d.ts.map +0 -1
- package/dist/esm/utils.test.js +0 -63
- package/dist/esm/utils.test.js.map +0 -1
package/dist/index.d.ts
ADDED
|
@@ -3,9 +3,9 @@ import { getEnv } from '@epic-web/workshop-utils/init-env';
|
|
|
3
3
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
4
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
5
5
|
import * as Sentry from '@sentry/node';
|
|
6
|
-
import { initPrompts } from
|
|
7
|
-
import { initResources } from
|
|
8
|
-
import { initPromptTools, initResourceTools, initTools } from
|
|
6
|
+
import { initPrompts } from "./prompts.js";
|
|
7
|
+
import { initResources } from "./resources.js";
|
|
8
|
+
import { initPromptTools, initResourceTools, initTools } from "./tools.js";
|
|
9
9
|
// Get environment variables
|
|
10
10
|
const env = getEnv();
|
|
11
11
|
// Initialize Sentry if published and DSN is available
|
|
@@ -56,4 +56,3 @@ main().catch((error) => {
|
|
|
56
56
|
console.error('Fatal error in main():', error);
|
|
57
57
|
process.exit(1);
|
|
58
58
|
});
|
|
59
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { getExercises } from '@epic-web/workshop-utils/apps.server';
|
|
2
2
|
import { getWorkshopConfig } from '@epic-web/workshop-utils/config.server';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { exerciseContextResource } from
|
|
5
|
-
import { handleWorkshopDirectory, workshopDirectoryInputSchema, } from
|
|
4
|
+
import { exerciseContextResource } from "./resources.js";
|
|
5
|
+
import { handleWorkshopDirectory, workshopDirectoryInputSchema, } from "./utils.js";
|
|
6
6
|
export const quizMeInputSchema = {
|
|
7
7
|
workshopDirectory: workshopDirectoryInputSchema,
|
|
8
8
|
exerciseNumber: z
|
|
@@ -54,4 +54,3 @@ export function initPrompts(server) {
|
|
|
54
54
|
argsSchema: quizMeInputSchema,
|
|
55
55
|
}, quizMe);
|
|
56
56
|
}
|
|
57
|
-
//# sourceMappingURL=prompts.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import { type ReadResourceResult } from '@modelcontextprotocol/sdk/types.js';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { type InputSchemaType } from
|
|
4
|
+
import { type InputSchemaType } from "./utils.js";
|
|
5
5
|
export declare const getWorkshopContextInputSchema: {
|
|
6
6
|
workshopDirectory: z.ZodString;
|
|
7
7
|
};
|
|
@@ -160,4 +160,3 @@ export declare const userProgressResource: {
|
|
|
160
160
|
};
|
|
161
161
|
export declare function initResources(server: McpServer): void;
|
|
162
162
|
export {};
|
|
163
|
-
//# sourceMappingURL=resources.d.ts.map
|
|
@@ -5,7 +5,7 @@ import { getAuthInfo } from '@epic-web/workshop-utils/db.server';
|
|
|
5
5
|
import { getEpicVideoInfos, userHasAccessToWorkshop, getUserInfo, getProgress, } from '@epic-web/workshop-utils/epic-api.server';
|
|
6
6
|
import { ResourceTemplate, } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
7
7
|
import { z } from 'zod';
|
|
8
|
-
import { handleWorkshopDirectory, readInWorkshop, safeReadFile, workshopDirectoryInputSchema, } from
|
|
8
|
+
import { handleWorkshopDirectory, readInWorkshop, safeReadFile, workshopDirectoryInputSchema, } from "./utils.js";
|
|
9
9
|
export const getWorkshopContextInputSchema = {
|
|
10
10
|
workshopDirectory: workshopDirectoryInputSchema,
|
|
11
11
|
};
|
|
@@ -602,4 +602,3 @@ export function initResources(server) {
|
|
|
602
602
|
};
|
|
603
603
|
});
|
|
604
604
|
}
|
|
605
|
-
//# sourceMappingURL=resources.js.map
|
|
@@ -2,4 +2,3 @@ import { type McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
2
2
|
export declare function initTools(server: McpServer): void;
|
|
3
3
|
export declare function initResourceTools(server: McpServer): void;
|
|
4
4
|
export declare function initPromptTools(server: McpServer): void;
|
|
5
|
-
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -7,13 +7,12 @@ import { getAuthInfo, logout, setAuthInfo, } from '@epic-web/workshop-utils/db.s
|
|
|
7
7
|
import { getDiffFiles } from '@epic-web/workshop-utils/diff.server';
|
|
8
8
|
import { getProgress, getUserInfo, updateProgress, } from '@epic-web/workshop-utils/epic-api.server';
|
|
9
9
|
import { launchEditor } from '@epic-web/workshop-utils/launch-editor.server';
|
|
10
|
-
// @ts-ignore 🤷♂️ tshy doesn't like this
|
|
11
10
|
import { createUIResource } from '@mcp-ui/server';
|
|
12
11
|
import * as client from 'openid-client';
|
|
13
12
|
import { z } from 'zod';
|
|
14
|
-
import { quizMe, quizMeInputSchema } from
|
|
15
|
-
import { diffBetweenAppsResource, exerciseContextResource, exerciseStepContextResource, exerciseStepProgressDiffResource, userAccessResource, userInfoResource, userProgressResource, workshopContextResource, } from
|
|
16
|
-
import { handleWorkshopDirectory, readInWorkshop, safeReadFile, workshopDirectoryInputSchema, } from
|
|
13
|
+
import { quizMe, quizMeInputSchema } from "./prompts.js";
|
|
14
|
+
import { diffBetweenAppsResource, exerciseContextResource, exerciseStepContextResource, exerciseStepProgressDiffResource, userAccessResource, userInfoResource, userProgressResource, workshopContextResource, } from "./resources.js";
|
|
15
|
+
import { handleWorkshopDirectory, readInWorkshop, safeReadFile, workshopDirectoryInputSchema, } from "./utils.js";
|
|
17
16
|
// not enough support for this yet
|
|
18
17
|
const clientSupportsEmbeddedResources = false;
|
|
19
18
|
export function initTools(server) {
|
|
@@ -802,4 +801,3 @@ to get the instructions for the current exercise step to help explain the
|
|
|
802
801
|
significance of changes.
|
|
803
802
|
`.trim();
|
|
804
803
|
}
|
|
805
|
-
//# sourceMappingURL=tools.js.map
|
package/package.json
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@epic-web/workshop-mcp",
|
|
3
|
-
"version": "6.47.
|
|
3
|
+
"version": "6.47.7",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
|
-
"bin": "./dist/
|
|
7
|
+
"bin": "./dist/index.js",
|
|
8
8
|
"type": "module",
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"dialects": [
|
|
12
|
-
"esm"
|
|
13
|
-
],
|
|
9
|
+
"zshy": {
|
|
10
|
+
"cjs": false,
|
|
14
11
|
"exports": {
|
|
15
12
|
"./package.json": "./package.json",
|
|
16
|
-
".": "./
|
|
17
|
-
}
|
|
13
|
+
".": "./src/index.ts"
|
|
14
|
+
},
|
|
15
|
+
"bin": "./src/index.ts"
|
|
18
16
|
},
|
|
19
17
|
"exports": {
|
|
20
18
|
"./package.json": "./package.json",
|
|
21
|
-
".":
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"import": "./dist/index.js"
|
|
22
|
+
}
|
|
22
23
|
},
|
|
23
24
|
"files": [
|
|
24
25
|
"dist"
|
|
@@ -28,13 +29,13 @@
|
|
|
28
29
|
"test:watch": "vitest",
|
|
29
30
|
"dev": "tsx src/index.ts",
|
|
30
31
|
"typecheck": "tsc --noEmit",
|
|
31
|
-
"build": "
|
|
32
|
+
"build": "zshy",
|
|
32
33
|
"inspect": "mcp-inspector",
|
|
33
34
|
"build:watch": "nx watch --projects=@epic-web/workshop-mcp -- nx run \\$NX_PROJECT_NAME:build"
|
|
34
35
|
},
|
|
35
36
|
"dependencies": {
|
|
36
37
|
"@epic-web/invariant": "^1.0.0",
|
|
37
|
-
"@epic-web/workshop-utils": "6.47.
|
|
38
|
+
"@epic-web/workshop-utils": "6.47.7",
|
|
38
39
|
"@mcp-ui/server": "^5.13.1",
|
|
39
40
|
"@modelcontextprotocol/sdk": "^1.21.1",
|
|
40
41
|
"@sentry/node": "^10.25.0",
|
|
@@ -44,7 +45,7 @@
|
|
|
44
45
|
"devDependencies": {
|
|
45
46
|
"@modelcontextprotocol/inspector": "^0.17.2",
|
|
46
47
|
"@types/node": "^24.10.0",
|
|
47
|
-
"
|
|
48
|
+
"zshy": "^0.3.0",
|
|
48
49
|
"tsx": "^4.20.6",
|
|
49
50
|
"typescript": "^5.9.3",
|
|
50
51
|
"vitest": "^4.0.8"
|
|
@@ -54,6 +55,6 @@
|
|
|
54
55
|
"url": "https://github.com/epicweb-dev/epicshop.git",
|
|
55
56
|
"directory": "packages/workshop-mcp"
|
|
56
57
|
},
|
|
57
|
-
"
|
|
58
|
-
"
|
|
58
|
+
"module": "./dist/index.js",
|
|
59
|
+
"types": "./dist/index.d.ts"
|
|
59
60
|
}
|
package/dist/esm/index.d.ts
DELETED
package/dist/esm/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":""}
|
package/dist/esm/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAA;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAChF,OAAO,KAAK,MAAM,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE1E,4BAA4B;AAC5B,MAAM,GAAG,GAAG,MAAM,EAAE,CAAA;AAEpB,sDAAsD;AACtD,IAAI,GAAG,CAAC,qBAAqB,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;IACjD,MAAM,CAAC,IAAI,CAAC;QACX,GAAG,EAAE,GAAG,CAAC,UAAU;QACnB,cAAc,EAAE,IAAI;QACpB,WAAW,EAAE,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa;QACrE,gBAAgB,EAAE,GAAG;KACrB,CAAC,CAAA;AACH,CAAC;AAED,yBAAyB;AACzB,MAAM,MAAM,GAAG,IAAI,SAAS,CAC3B;IACC,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,OAAO;IAChB,YAAY,EAAE;QACb,KAAK,EAAE,EAAE;KACT;CACD;AACD,sDAAsD;AACtD;IACC,YAAY,EAAE;;;;;;;;;GASb,CAAC,IAAI,EAAE;CACR,CACD,CAAA;AAED,8BAA8B;AAC9B,MAAM,eAAe,GACpB,GAAG,CAAC,qBAAqB,IAAI,GAAG,CAAC,UAAU;IAC1C,CAAC,CAAC,MAAM,CAAC,uBAAuB,CAAC,MAAM,CAAC;IACxC,CAAC,CAAC,MAAM,CAAA;AAEV,SAAS,CAAC,eAAe,CAAC,CAAA;AAC1B,iBAAiB,CAAC,eAAe,CAAC,CAAA;AAClC,aAAa,CAAC,eAAe,CAAC,CAAA;AAC9B,WAAW,CAAC,eAAe,CAAC,CAAA;AAC5B,eAAe,CAAC,eAAe,CAAC,CAAA;AAEhC,KAAK,UAAU,IAAI;IAClB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAA;IAC5C,MAAM,eAAe,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IACxC,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAA;AACtD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACtB,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAA;IAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AAChB,CAAC,CAAC,CAAA","sourcesContent":["#!/usr/bin/env node\n\nimport { getEnv } from '@epic-web/workshop-utils/init-env'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport * as Sentry from '@sentry/node'\nimport { initPrompts } from './prompts.js'\nimport { initResources } from './resources.js'\nimport { initPromptTools, initResourceTools, initTools } from './tools.js'\n\n// Get environment variables\nconst env = getEnv()\n\n// Initialize Sentry if published and DSN is available\nif (env.EPICSHOP_IS_PUBLISHED && env.SENTRY_DSN) {\n\tSentry.init({\n\t\tdsn: env.SENTRY_DSN,\n\t\tsendDefaultPii: true,\n\t\tenvironment: env.EPICSHOP_IS_PUBLISHED ? 'production' : 'development',\n\t\ttracesSampleRate: 1.0,\n\t})\n}\n\n// Create server instance\nconst server = new McpServer(\n\t{\n\t\tname: 'epicshop',\n\t\tversion: '1.0.0',\n\t\tcapabilities: {\n\t\t\ttools: {},\n\t\t},\n\t},\n\t// TODO: add some common workflows to the instructions\n\t{\n\t\tinstructions: `\nThis is intended to be used within a workshop using the Epic Workshop App\n(@epic-web/workshop-app) to help learners in the process of completing the\nworkshop exercises and understanding the learning outcomes.\n\nThe user's work in progress is in the \\`playground\\` directory. Any changes they\nask you to make should be in this directory.\n\nMost of the time you should use the \\`get_what_is_next\\` tool to get the next step the user needs to complete.\n\t\t`.trim(),\n\t},\n)\n\n// Wrap with Sentry if enabled\nconst monitoredServer =\n\tenv.EPICSHOP_IS_PUBLISHED && env.SENTRY_DSN\n\t\t? Sentry.wrapMcpServerWithSentry(server)\n\t\t: server\n\ninitTools(monitoredServer)\ninitResourceTools(monitoredServer)\ninitResources(monitoredServer)\ninitPrompts(monitoredServer)\ninitPromptTools(monitoredServer)\n\nasync function main() {\n\tconst transport = new StdioServerTransport()\n\tawait monitoredServer.connect(transport)\n\tconsole.error('epicshop MCP Server running on stdio')\n}\n\nmain().catch((error) => {\n\tconsole.error('Fatal error in main():', error)\n\tprocess.exit(1)\n})\n"]}
|
package/dist/esm/package.json
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/prompts.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACxE,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,oCAAoC,CAAA;AACzE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAOvB,eAAO,MAAM,iBAAiB;;;CAQ7B,CAAA;AAED,wBAAsB,MAAM,CAAC,EAC5B,iBAAiB,EACjB,cAAc,EAAE,sBAAsB,GACtC,EAAE;IACF,iBAAiB,EAAE,MAAM,CAAA;IACzB,cAAc,CAAC,EAAE,MAAM,CAAA;CACvB,GAAG,OAAO,CAAC,eAAe,CAAC,CAqC3B;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,QAW5C"}
|
package/dist/esm/prompts.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAA;AAG1E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AACxD,OAAO,EACN,uBAAuB,EACvB,4BAA4B,GAC5B,MAAM,YAAY,CAAA;AAEnB,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAChC,iBAAiB,EAAE,4BAA4B;IAC/C,cAAc,EAAE,CAAC;SACf,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACR,yFAAyF,CACzF;CACF,CAAA;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,EAC5B,iBAAiB,EACjB,cAAc,EAAE,sBAAsB,GAItC;IACA,MAAM,YAAY,GAAG,MAAM,uBAAuB,CAAC,iBAAiB,CAAC,CAAA;IACrE,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAA;IAClC,IAAI,cAAc,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAA;IACnD,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAC7B,MAAM,SAAS,GAAG,MAAM,YAAY,EAAE,CAAA;QACtC,MAAM,cAAc,GACnB,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAA;QACxD,cAAc,GAAG,cAAc,EAAE,cAAc,IAAI,CAAC,CAAA;IACrD,CAAC;IACD,OAAO;QACN,QAAQ,EAAE;YACT;gBACC,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE;;;kCAGuB,cAAc,4BAA4B,MAAM,CAAC,KAAK,iBAAiB,MAAM,CAAC,QAAQ,eAAe,YAAY;;;QAG3I,CAAC,IAAI,EAAE;iBACV;aACD;YACD;gBACC,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE;oBACR,IAAI,EAAE,UAAU;oBAChB,QAAQ,EAAE,MAAM,uBAAuB,CAAC,WAAW,CAAC;wBACnD,iBAAiB;wBACjB,cAAc;qBACd,CAAC;iBACF;aACD;SACD;KACD,CAAA;AACF,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAiB;IAC5C,MAAM,CAAC,cAAc,CACpB,SAAS,EACT;QACC,KAAK,EAAE,SAAS;QAChB,WAAW,EACV,6DAA6D;QAC9D,UAAU,EAAE,iBAAiB;KAC7B,EACD,MAAM,CACN,CAAA;AACF,CAAC","sourcesContent":["import { getExercises } from '@epic-web/workshop-utils/apps.server'\nimport { getWorkshopConfig } from '@epic-web/workshop-utils/config.server'\nimport { type McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { type GetPromptResult } from '@modelcontextprotocol/sdk/types.js'\nimport { z } from 'zod'\nimport { exerciseContextResource } from './resources.js'\nimport {\n\thandleWorkshopDirectory,\n\tworkshopDirectoryInputSchema,\n} from './utils.js'\n\nexport const quizMeInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n\texerciseNumber: z\n\t\t.string()\n\t\t.optional()\n\t\t.describe(\n\t\t\t`The exercise number to get quizzed on (e.g., \\`4\\`). Leave blank for a random exercise.`,\n\t\t),\n}\n\nexport async function quizMe({\n\tworkshopDirectory,\n\texerciseNumber: providedExerciseNumber,\n}: {\n\tworkshopDirectory: string\n\texerciseNumber?: string\n}): Promise<GetPromptResult> {\n\tconst workshopRoot = await handleWorkshopDirectory(workshopDirectory)\n\tconst config = getWorkshopConfig()\n\tlet exerciseNumber = Number(providedExerciseNumber)\n\tif (!providedExerciseNumber) {\n\t\tconst exercises = await getExercises()\n\t\tconst randomExercise =\n\t\t\texercises[Math.floor(Math.random() * exercises.length)]\n\t\texerciseNumber = randomExercise?.exerciseNumber ?? 0\n\t}\n\treturn {\n\t\tmessages: [\n\t\t\t{\n\t\t\t\trole: 'user',\n\t\t\t\tcontent: {\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\ttext: `\nYou are an expert teacher.\n\nBelow is context about exercise ${exerciseNumber} in the workshop titled \"${config.title}\" (subtitled \"${config.subtitle}\") found at ${workshopRoot}.\n\nPlease use this context to provide quiz questions, one at a time, to me to help me solidify my understanding of this material. Ask me the question, I will provide a response, you will either congratulate my correct understanding and move on or guide me to the correct answer with follow-up questions and hints until I either ask you to tell me the answer or ask you to continue to the next question.\n\t\t\t\t\t\t\t`.trim(),\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\trole: 'user',\n\t\t\t\tcontent: {\n\t\t\t\t\ttype: 'resource',\n\t\t\t\t\tresource: await exerciseContextResource.getResource({\n\t\t\t\t\t\tworkshopDirectory,\n\t\t\t\t\t\texerciseNumber,\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t}\n}\n\nexport function initPrompts(server: McpServer) {\n\tserver.registerPrompt(\n\t\t'quiz_me',\n\t\t{\n\t\t\ttitle: 'Quiz Me',\n\t\t\tdescription:\n\t\t\t\t'Have the LLM quiz you on topics from the workshop exercises',\n\t\t\targsSchema: quizMeInputSchema,\n\t\t},\n\t\tquizMe,\n\t)\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../src/resources.ts"],"names":[],"mappings":"AAoBA,OAAO,EACN,KAAK,SAAS,EACd,gBAAgB,EAChB,MAAM,yCAAyC,CAAA;AAChD,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,oCAAoC,CAAA;AAC5E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAEN,KAAK,eAAe,EAIpB,MAAM,YAAY,CAAA;AAEnB,eAAO,MAAM,6BAA6B;;CAEzC,CAAA;AAED,wBAAsB,kBAAkB,CAAC,EACxC,iBAAiB,GACjB,EAAE,eAAe,CAAC,OAAO,6BAA6B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAmBrC,KAAK,CAAC,GAAG,CAAC;GA0D5B;AAOD,wBAAsB,0BAA0B,CAAC,EAChD,iBAAiB,GACjB,EAAE,eAAe,CAAC,OAAO,6BAA6B,CAAC,GAAG,OAAO,CACjE,kBAAkB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CACtC,CAQA;AAED,eAAO,MAAM,uBAAuB;;;;;;;;CAMnC,CAAA;AAgJD,iBAAe,0BAA0B,CAAC,EACzC,iBAAiB,EACjB,cAAc,GACd,EAAE;IACF,iBAAiB,EAAE,MAAM,CAAA;IACzB,cAAc,CAAC,EAAE,MAAM,CAAA;CACvB,GAAG,OAAO,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,CAalD;AAED,eAAO,MAAM,uBAAuB;;;;;;;;;CAMnC,CAAA;AAiFD,QAAA,MAAM,iCAAiC;;;;CAQtC,CAAA;AAkGD,iBAAe,8BAA8B,CAAC,EAC7C,iBAAiB,EACjB,cAAc,EACd,UAAU,GACV,EAAE,eAAe,CAAC,OAAO,iCAAiC,CAAC,GAAG,OAAO,CACrE,kBAAkB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CACtC,CAeA;AAED,eAAO,MAAM,2BAA2B;;;;;;;;;;CAMvC,CAAA;AAED,QAAA,MAAM,0BAA0B;;;;CAI/B,CAAA;AA4CD,iBAAe,0BAA0B,CAAC,EACzC,iBAAiB,EACjB,IAAI,EACJ,IAAI,GACJ,EAAE,eAAe,CAAC,OAAO,0BAA0B,CAAC,GAAG,OAAO,CAC9D,kBAAkB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CACtC,CAYA;AAOD,eAAO,MAAM,uBAAuB;;;;;;;;;;CAMnC,CAAA;AAED,QAAA,MAAM,sCAAsC;;CAE3C,CAAA;AAoCD,iBAAe,mCAAmC,CAAC,EAClD,iBAAiB,GACjB,EAAE,eAAe,CAAC,OAAO,sCAAsC,CAAC,GAAG,OAAO,CAC1E,kBAAkB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CACtC,CAUA;AAED,eAAO,MAAM,gCAAgC;;;;;;;;CAM5C,CAAA;AAED,QAAA,MAAM,sBAAsB;;CAE3B,CAAA;AAOD,iBAAe,mBAAmB,CAAC,EAClC,iBAAiB,GACjB,EAAE,eAAe,CAAC,OAAO,sBAAsB,CAAC;;;;GAShD;AAED,eAAO,MAAM,gBAAgB;;;;;;;;CAM5B,CAAA;AAED,QAAA,MAAM,wBAAwB;;CAE7B,CAAA;AAOD,iBAAe,qBAAqB,CAAC,EACpC,iBAAiB,GACjB,EAAE,eAAe,CAAC,OAAO,wBAAwB,CAAC;;;;GASlD;AAED,eAAO,MAAM,kBAAkB;;;;;;;;CAM9B,CAAA;AAED,QAAA,MAAM,uBAAuB;;CAE5B,CAAA;AAOD,iBAAe,uBAAuB,CAAC,EACtC,iBAAiB,GACjB,EAAE,eAAe,CAAC,OAAO,uBAAuB,CAAC;;;;GASjD;AAED,eAAO,MAAM,oBAAoB;;;;;;;;CAMhC,CAAA;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,QAiM9C"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../../src/resources.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path'\nimport { invariant } from '@epic-web/invariant'\nimport {\n\textractNumbersAndTypeFromAppNameOrPath,\n\tfindSolutionDir,\n\tgetApps,\n\tgetExercise,\n\tgetExercises,\n\tgetFullPathFromAppName,\n\tgetPlaygroundApp,\n\tisExerciseStepApp,\n\tisPlaygroundApp,\n} from '@epic-web/workshop-utils/apps.server'\nimport { getAuthInfo } from '@epic-web/workshop-utils/db.server'\nimport {\n\tgetEpicVideoInfos,\n\tuserHasAccessToWorkshop,\n\tgetUserInfo,\n\tgetProgress,\n} from '@epic-web/workshop-utils/epic-api.server'\nimport {\n\ttype McpServer,\n\tResourceTemplate,\n} from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { type ReadResourceResult } from '@modelcontextprotocol/sdk/types.js'\nimport { z } from 'zod'\nimport {\n\thandleWorkshopDirectory,\n\ttype InputSchemaType,\n\treadInWorkshop,\n\tsafeReadFile,\n\tworkshopDirectoryInputSchema,\n} from './utils.js'\n\nexport const getWorkshopContextInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n}\n\nexport async function getWorkshopContext({\n\tworkshopDirectory,\n}: InputSchemaType<typeof getWorkshopContextInputSchema>) {\n\tawait handleWorkshopDirectory(workshopDirectory)\n\tconst progress = await getProgress()\n\n\tconst output = {\n\t\tmeta: {\n\t\t\t'README.md': await readInWorkshop('README.md'),\n\t\t\tconfig: (\n\t\t\t\tJSON.parse((await readInWorkshop('package.json')) || '{}') as any\n\t\t\t).epicshop,\n\t\t\tinstructions: {\n\t\t\t\tcontent: await readInWorkshop('exercises', 'README.mdx'),\n\t\t\t\tprogress: progress.find((p) => p.type === 'instructions'),\n\t\t\t},\n\t\t\tfinishedInstructions: {\n\t\t\t\tcontent: await readInWorkshop('exercises', 'FINISHED.mdx'),\n\t\t\t\tprogress: progress.find((p) => p.type === 'finished'),\n\t\t\t},\n\t\t},\n\t\texercises: [] as Array<any>,\n\t}\n\n\tconst exercises = await getExercises()\n\tfor (const exercise of exercises) {\n\t\tconst exerciseInfo = {\n\t\t\tfullPath: exercise.fullPath,\n\t\t\texerciseNumber: exercise.exerciseNumber,\n\t\t\ttitle: exercise.title,\n\t\t\tinstructions: {\n\t\t\t\tcontent: await safeReadFile(path.join(exercise.fullPath, 'README.mdx')),\n\t\t\t\tprogress: progress.find(\n\t\t\t\t\t(p) =>\n\t\t\t\t\t\tp.type === 'instructions' &&\n\t\t\t\t\t\tp.exerciseNumber === exercise.exerciseNumber,\n\t\t\t\t),\n\t\t\t},\n\t\t\tfinishedInstructions: {\n\t\t\t\tcontent: await safeReadFile(\n\t\t\t\t\tpath.join(exercise.fullPath, 'FINISHED.mdx'),\n\t\t\t\t),\n\t\t\t\tprogress: progress.find(\n\t\t\t\t\t(p) =>\n\t\t\t\t\t\tp.type === 'finished' &&\n\t\t\t\t\t\tp.exerciseNumber === exercise.exerciseNumber,\n\t\t\t\t),\n\t\t\t},\n\t\t\tsteps: exercise.steps.map((step) => {\n\t\t\t\treturn {\n\t\t\t\t\tstepNumber: step.stepNumber,\n\t\t\t\t\tprogress: progress.find(\n\t\t\t\t\t\t(p) =>\n\t\t\t\t\t\t\tp.type === 'step' &&\n\t\t\t\t\t\t\tp.exerciseNumber === exercise.exerciseNumber &&\n\t\t\t\t\t\t\tp.stepNumber === step.stepNumber,\n\t\t\t\t\t),\n\t\t\t\t\ttitle: step.problem?.title ?? step.solution?.title ?? null,\n\t\t\t\t\tproblem: step.problem\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tfullPath: step.problem.fullPath,\n\t\t\t\t\t\t\t\ttestConfig: step.problem.test,\n\t\t\t\t\t\t\t\tdevConfig: step.problem.dev,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: 'No problem app',\n\t\t\t\t\tsolution: step.solution\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tfullPath: step.solution.fullPath,\n\t\t\t\t\t\t\t\ttestConfig: step.solution.test,\n\t\t\t\t\t\t\t\tdevConfig: step.solution.dev,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: 'No solution app',\n\t\t\t\t}\n\t\t\t}),\n\t\t}\n\t\toutput.exercises.push(exerciseInfo)\n\t}\n\n\treturn output\n}\n\nconst workshopContextUriTemplate = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/workshop-context',\n\t{ list: undefined },\n)\n\nexport async function getWorkshopContextResource({\n\tworkshopDirectory,\n}: InputSchemaType<typeof getWorkshopContextInputSchema>): Promise<\n\tReadResourceResult['contents'][number]\n> {\n\treturn {\n\t\turi: workshopContextUriTemplate.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify(await getWorkshopContext({ workshopDirectory })),\n\t}\n}\n\nexport const workshopContextResource = {\n\tname: 'workshop_context',\n\tdescription: 'The context of the workshop',\n\turiTemplate: workshopContextUriTemplate,\n\tgetResource: getWorkshopContextResource,\n\tinputSchema: getWorkshopContextInputSchema,\n}\n\nconst getExerciseContextInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n\texerciseNumber: z.coerce\n\t\t.number()\n\t\t.optional()\n\t\t.describe(\n\t\t\t`The exercise number to get the context for (defaults to the exercise number the playground is currently set to)`,\n\t\t),\n}\n\nasync function getExerciseContext({\n\tworkshopDirectory,\n\texerciseNumber,\n}: {\n\tworkshopDirectory: string\n\texerciseNumber?: number\n}) {\n\tconst { userHasAccess, authInfo, progress, numbers } =\n\t\tawait getCommonContextData(workshopDirectory)\n\n\tlet stepNumber = 1\n\tconst isCurrentExercise =\n\t\texerciseNumber === undefined ||\n\t\texerciseNumber === Number(numbers?.exerciseNumber)\n\tif (exerciseNumber === undefined) {\n\t\tinvariant(numbers, 'No numbers found in playground app name')\n\t\texerciseNumber = Number(numbers.exerciseNumber)\n\t\tstepNumber = Number(numbers.stepNumber)\n\t}\n\tconst exercise = await getExercise(exerciseNumber)\n\tinvariant(exercise, `No exercise found for exercise number ${exerciseNumber}`)\n\n\tconst videoInfos = await getEpicVideoInfos([\n\t\t...(exercise.instructionsEpicVideoEmbeds ?? []),\n\t\t...exercise.steps.flatMap((s) => s.problem?.epicVideoEmbeds ?? []),\n\t\t...exercise.steps.flatMap((s) => s.solution?.epicVideoEmbeds ?? []),\n\t\t...(exercise.finishedEpicVideoEmbeds ?? []),\n\t])\n\n\tconst context = {\n\t\tcurrentContext: {\n\t\t\tuser: {\n\t\t\t\thasAccess: userHasAccess,\n\t\t\t\tisAuthenticated: Boolean(authInfo),\n\t\t\t\temail: authInfo?.email,\n\t\t\t},\n\t\t\tplayground: isCurrentExercise\n\t\t\t\t? {\n\t\t\t\t\t\texerciseNumber,\n\t\t\t\t\t\tstepNumber,\n\t\t\t\t\t}\n\t\t\t\t: 'currently set to a different exercise',\n\t\t},\n\t\texerciseInfo: {\n\t\t\tnumber: exerciseNumber,\n\t\t\tintro: {\n\t\t\t\tcontent: await getFileContent(\n\t\t\t\t\tpath.join(exercise.fullPath, 'README.mdx'),\n\t\t\t\t),\n\t\t\t\ttranscripts: getTranscripts(\n\t\t\t\t\texercise.instructionsEpicVideoEmbeds,\n\t\t\t\t\tvideoInfos,\n\t\t\t\t\tuserHasAccess,\n\t\t\t\t),\n\t\t\t\tprogress: progress.find(\n\t\t\t\t\t(p) =>\n\t\t\t\t\t\tp.type === 'instructions' && p.exerciseNumber === exerciseNumber,\n\t\t\t\t),\n\t\t\t},\n\t\t\toutro: {\n\t\t\t\tcontent: await getFileContent(\n\t\t\t\t\tpath.join(exercise.fullPath, 'FINISHED.mdx'),\n\t\t\t\t),\n\t\t\t\ttranscripts: getTranscripts(\n\t\t\t\t\texercise.finishedEpicVideoEmbeds,\n\t\t\t\t\tvideoInfos,\n\t\t\t\t\tuserHasAccess,\n\t\t\t\t),\n\t\t\t\tprogress: progress.find(\n\t\t\t\t\t(p) => p.type === 'finished' && p.exerciseNumber === exerciseNumber,\n\t\t\t\t),\n\t\t\t},\n\t\t},\n\t\tsteps: exercise.steps\n\t\t\t? await Promise.all(\n\t\t\t\t\texercise.steps.map(async (app) => ({\n\t\t\t\t\t\tnumber: app.stepNumber,\n\t\t\t\t\t\tisCurrent: isCurrentExercise && app.stepNumber === stepNumber,\n\t\t\t\t\t\tprogress: progress.find(\n\t\t\t\t\t\t\t(p) =>\n\t\t\t\t\t\t\t\tp.type === 'step' &&\n\t\t\t\t\t\t\t\tp.exerciseNumber === exerciseNumber &&\n\t\t\t\t\t\t\t\tp.stepNumber === app.stepNumber,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tproblem: {\n\t\t\t\t\t\t\tcontent: app.problem\n\t\t\t\t\t\t\t\t? await getFileContent(\n\t\t\t\t\t\t\t\t\t\tpath.join(app.problem.fullPath, 'README.mdx'),\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t: 'No problem found',\n\t\t\t\t\t\t\ttranscripts: getTranscripts(\n\t\t\t\t\t\t\t\tapp.problem?.epicVideoEmbeds,\n\t\t\t\t\t\t\t\tvideoInfos,\n\t\t\t\t\t\t\t\tuserHasAccess,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsolution: {\n\t\t\t\t\t\t\tcontent: app.solution\n\t\t\t\t\t\t\t\t? await getFileContent(\n\t\t\t\t\t\t\t\t\t\tpath.join(app.solution.fullPath, 'README.mdx'),\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t: 'No solution found',\n\t\t\t\t\t\t\ttranscripts: getTranscripts(\n\t\t\t\t\t\t\t\tapp.solution?.epicVideoEmbeds,\n\t\t\t\t\t\t\t\tvideoInfos,\n\t\t\t\t\t\t\t\tuserHasAccess,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t},\n\t\t\t\t\t})),\n\t\t\t\t)\n\t\t\t: [],\n\t\tnotes: [] as Array<string>,\n\t}\n\n\tif (exercise.steps) {\n\t\tif (isCurrentExercise) {\n\t\t\tcontext.notes.push(\n\t\t\t\t`Reminder, the current step is ${stepNumber} of ${exercise.steps.length + 1}. The most relevant information will be in the context above within the current step.`,\n\t\t\t)\n\t\t}\n\t} else {\n\t\tcontext.notes.push('Unusually, this exercise has no steps.')\n\t}\n\n\treturn context\n}\n\nconst exerciseContextUriTemplate = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/exercise/{exerciseNumber}',\n\t{ list: undefined },\n)\n\nasync function getExerciseContextResource({\n\tworkshopDirectory,\n\texerciseNumber,\n}: {\n\tworkshopDirectory: string\n\texerciseNumber?: number\n}): Promise<ReadResourceResult['contents'][number]> {\n\tconst context = await getExerciseContext({\n\t\tworkshopDirectory,\n\t\texerciseNumber,\n\t})\n\treturn {\n\t\turi: exerciseContextUriTemplate.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t\texerciseNumber: String(context.exerciseInfo.number),\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify(context),\n\t}\n}\n\nexport const exerciseContextResource = {\n\tname: 'exercise_context',\n\tdescription: 'The context of the exercise',\n\turiTemplate: exerciseContextUriTemplate,\n\tgetResource: getExerciseContextResource,\n\tinputSchema: getExerciseContextInputSchema,\n}\n\n// Common helper functions extracted from getExerciseContext\nasync function getCommonContextData(workshopDirectory: string) {\n\tawait handleWorkshopDirectory(workshopDirectory)\n\tconst userHasAccess = await userHasAccessToWorkshop()\n\tconst authInfo = await getAuthInfo()\n\tconst progress = await getProgress()\n\tconst playgroundApp = await getPlaygroundApp()\n\tconst numbers = playgroundApp\n\t\t? extractNumbersAndTypeFromAppNameOrPath(playgroundApp.appName)\n\t\t: null\n\n\treturn {\n\t\tuserHasAccess,\n\t\tauthInfo,\n\t\tprogress,\n\t\tplaygroundApp,\n\t\tnumbers,\n\t}\n}\n\nfunction getTranscripts(\n\tembeds: Array<string> | undefined,\n\tvideoInfos: Record<string, any>,\n\tuserHasAccess: boolean,\n) {\n\tif (!embeds) return []\n\tif (!userHasAccess && embeds.length) {\n\t\treturn [\n\t\t\t{\n\t\t\t\tmessage: `User must upgrade before they can get access to ${embeds.length} transcript${embeds.length === 1 ? '' : 's'}.`,\n\t\t\t},\n\t\t]\n\t}\n\treturn embeds.map((embed) => {\n\t\tconst info = videoInfos[embed]\n\t\tif (info) {\n\t\t\tif (info.status === 'error') {\n\t\t\t\tif (info.type === 'region-restricted') {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tembed,\n\t\t\t\t\t\tstatus: 'error',\n\t\t\t\t\t\ttype: info.type,\n\t\t\t\t\t\trequestedCountry: info.requestCountry,\n\t\t\t\t\t\trestrictedCountry: info.restrictedCountry,\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tembed,\n\t\t\t\t\t\tstatus: 'error',\n\t\t\t\t\t\ttype: info.type,\n\t\t\t\t\t\tstatusCode: info.statusCode,\n\t\t\t\t\t\tstatusText: info.statusText,\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn {\n\t\t\t\t\tembed,\n\t\t\t\t\tstatus: 'success',\n\t\t\t\t\ttranscript: info.transcript,\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tembed,\n\t\t\t\tstatus: 'error',\n\t\t\t\ttype: 'not-found',\n\t\t\t\tmessage: 'No transcript found',\n\t\t\t}\n\t\t}\n\t})\n}\n\nasync function getFileContent(filePath: string) {\n\treturn {\n\t\tpath: filePath,\n\t\tcontent: (await safeReadFile(filePath)) ?? 'None found',\n\t}\n}\n\nconst getExerciseStepContextInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n\texerciseNumber: z.coerce\n\t\t.number()\n\t\t.describe('The exercise number to get the context for'),\n\tstepNumber: z.coerce\n\t\t.number()\n\t\t.describe('The step number to get the context for'),\n}\n\nasync function getExerciseStepContext({\n\tworkshopDirectory,\n\texerciseNumber,\n\tstepNumber,\n}: {\n\tworkshopDirectory: string\n\texerciseNumber: number\n\tstepNumber: number\n}) {\n\tconst { userHasAccess, authInfo, progress, numbers } =\n\t\tawait getCommonContextData(workshopDirectory)\n\n\tconst isCurrentExercise =\n\t\texerciseNumber === Number(numbers?.exerciseNumber) &&\n\t\tstepNumber === Number(numbers?.stepNumber)\n\n\tconst exercise = await getExercise(exerciseNumber)\n\tinvariant(exercise, `No exercise found for exercise number ${exerciseNumber}`)\n\n\tconst step = exercise.steps.find((s) => s.stepNumber === stepNumber)\n\tinvariant(\n\t\tstep,\n\t\t`No step found for exercise ${exerciseNumber}, step ${stepNumber}`,\n\t)\n\n\tconst videoInfos = await getEpicVideoInfos([\n\t\t...(step.problem?.epicVideoEmbeds ?? []),\n\t\t...(step.solution?.epicVideoEmbeds ?? []),\n\t])\n\n\tconst context = {\n\t\tcurrentContext: {\n\t\t\tuser: {\n\t\t\t\thasAccess: userHasAccess,\n\t\t\t\tisAuthenticated: Boolean(authInfo),\n\t\t\t\temail: authInfo?.email,\n\t\t\t},\n\t\t\tplayground: isCurrentExercise\n\t\t\t\t? {\n\t\t\t\t\t\texerciseNumber,\n\t\t\t\t\t\tstepNumber,\n\t\t\t\t\t}\n\t\t\t\t: 'currently set to a different exercise step',\n\t\t},\n\t\texerciseInfo: {\n\t\t\tnumber: exerciseNumber,\n\t\t\ttitle: exercise.title,\n\t\t},\n\t\tstepInfo: {\n\t\t\tnumber: stepNumber,\n\t\t\tisCurrent: isCurrentExercise,\n\t\t\tprogress: progress.find(\n\t\t\t\t(p) =>\n\t\t\t\t\tp.type === 'step' &&\n\t\t\t\t\tp.exerciseNumber === exerciseNumber &&\n\t\t\t\t\tp.stepNumber === stepNumber,\n\t\t\t),\n\t\t\ttitle: step.problem?.title ?? step.solution?.title ?? null,\n\t\t},\n\t\tproblem: {\n\t\t\tcontent: step.problem\n\t\t\t\t? await getFileContent(path.join(step.problem.fullPath, 'README.mdx'))\n\t\t\t\t: 'No problem found',\n\t\t\ttranscripts: getTranscripts(\n\t\t\t\tstep.problem?.epicVideoEmbeds,\n\t\t\t\tvideoInfos,\n\t\t\t\tuserHasAccess,\n\t\t\t),\n\t\t},\n\t\tsolution: {\n\t\t\tcontent: step.solution\n\t\t\t\t? await getFileContent(path.join(step.solution.fullPath, 'README.mdx'))\n\t\t\t\t: 'No solution found',\n\t\t\ttranscripts: getTranscripts(\n\t\t\t\tstep.solution?.epicVideoEmbeds,\n\t\t\t\tvideoInfos,\n\t\t\t\tuserHasAccess,\n\t\t\t),\n\t\t},\n\t\tnotes: [] as Array<string>,\n\t}\n\n\tif (isCurrentExercise) {\n\t\tcontext.notes.push(\n\t\t\t`This is the current step the user is working on. The playground is set to exercise ${exerciseNumber}, step ${stepNumber}.`,\n\t\t)\n\t}\n\n\treturn context\n}\n\nconst exerciseStepContextUriTemplate = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/exercise/{exerciseNumber}/{stepNumber}',\n\t{ list: undefined },\n)\n\nasync function getExerciseStepContextResource({\n\tworkshopDirectory,\n\texerciseNumber,\n\tstepNumber,\n}: InputSchemaType<typeof getExerciseStepContextInputSchema>): Promise<\n\tReadResourceResult['contents'][number]\n> {\n\tconst context = await getExerciseStepContext({\n\t\tworkshopDirectory,\n\t\texerciseNumber,\n\t\tstepNumber,\n\t})\n\treturn {\n\t\turi: exerciseStepContextUriTemplate.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t\texerciseNumber: String(exerciseNumber),\n\t\t\tstepNumber: String(stepNumber),\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify(context),\n\t}\n}\n\nexport const exerciseStepContextResource = {\n\tname: 'exercise_step_context',\n\tdescription: 'The context of a specific exercise step',\n\turiTemplate: exerciseStepContextUriTemplate,\n\tgetResource: getExerciseStepContextResource,\n\tinputSchema: getExerciseStepContextInputSchema,\n}\n\nconst diffBetweenAppsInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n\tapp1: z.string().describe('The ID of the first app'),\n\tapp2: z.string().describe('The ID of the second app'),\n}\n\nasync function getDiffBetweenApps({\n\tworkshopDirectory,\n\tapp1,\n\tapp2,\n}: InputSchemaType<typeof diffBetweenAppsInputSchema>) {\n\tawait handleWorkshopDirectory(workshopDirectory)\n\n\tconst { getDiffOutputWithRelativePaths } = await import(\n\t\t'@epic-web/workshop-utils/diff.server'\n\t)\n\n\tconst app1Name = extractNumbersAndTypeFromAppNameOrPath(app1)\n\tconst app2Name = extractNumbersAndTypeFromAppNameOrPath(app2)\n\n\tconst apps = await getApps()\n\tconst app1App = apps\n\t\t.filter(isExerciseStepApp)\n\t\t.find(\n\t\t\t(a) =>\n\t\t\t\ta.exerciseNumber === Number(app1Name?.exerciseNumber) &&\n\t\t\t\ta.stepNumber === Number(app1Name?.stepNumber) &&\n\t\t\t\ta.type === app1Name?.type,\n\t\t)\n\tconst app2App = apps\n\t\t.filter(isExerciseStepApp)\n\t\t.find(\n\t\t\t(a) =>\n\t\t\t\ta.exerciseNumber === Number(app2Name?.exerciseNumber) &&\n\t\t\t\ta.stepNumber === Number(app2Name?.stepNumber) &&\n\t\t\t\ta.type === app2Name?.type,\n\t\t)\n\n\tinvariant(app1App, `No app found for ${app1}`)\n\tinvariant(app2App, `No app found for ${app2}`)\n\n\tconst diffCode = await getDiffOutputWithRelativePaths(app1App, app2App)\n\n\tif (!diffCode) return 'No changes'\n\n\treturn diffCode\n}\n\nasync function getDiffBetweenAppsResource({\n\tworkshopDirectory,\n\tapp1,\n\tapp2,\n}: InputSchemaType<typeof diffBetweenAppsInputSchema>): Promise<\n\tReadResourceResult['contents'][number]\n> {\n\treturn {\n\t\turi: diffBetweenAppsUriTemplate.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t\tapp1,\n\t\t\tapp2,\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify(\n\t\t\tawait getDiffBetweenApps({ workshopDirectory, app1, app2 }),\n\t\t),\n\t}\n}\n\nconst diffBetweenAppsUriTemplate = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/diff-between-apps/{app1}__vs___{app2}',\n\t{ list: undefined },\n)\n\nexport const diffBetweenAppsResource = {\n\tname: 'diff_between_apps',\n\tdescription: 'The diff between two apps',\n\turiTemplate: diffBetweenAppsUriTemplate,\n\tgetResource: getDiffBetweenAppsResource,\n\tinputSchema: diffBetweenAppsInputSchema,\n}\n\nconst getExerciseStepProgressDiffInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n}\n\nasync function getExerciseStepProgressDiff({\n\tworkshopDirectory,\n}: InputSchemaType<typeof getExerciseStepProgressDiffInputSchema>) {\n\tawait handleWorkshopDirectory(workshopDirectory)\n\n\tconst { getDiffOutputWithRelativePaths } = await import(\n\t\t'@epic-web/workshop-utils/diff.server'\n\t)\n\n\tconst apps = await getApps()\n\tconst playgroundApp = apps.find(isPlaygroundApp)\n\n\tinvariant(playgroundApp, 'No playground app found')\n\n\tconst baseApp = playgroundApp\n\tconst solutionDir = await findSolutionDir({\n\t\tfullPath: await getFullPathFromAppName(playgroundApp.appName),\n\t})\n\tconst headApp = apps.find((a) => a.fullPath === solutionDir)\n\n\tinvariant(headApp, 'No playground solution app found')\n\n\tconst diffCode = await getDiffOutputWithRelativePaths(baseApp, headApp)\n\n\tif (!diffCode) return 'No changes'\n\n\treturn diffCode\n}\n\nconst exerciseStepProgressDiffUriTemplate = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/exercise-step-progress-diff',\n\t{ list: undefined },\n)\n\nasync function getExerciseStepProgressDiffResource({\n\tworkshopDirectory,\n}: InputSchemaType<typeof getExerciseStepProgressDiffInputSchema>): Promise<\n\tReadResourceResult['contents'][number]\n> {\n\treturn {\n\t\turi: exerciseStepProgressDiffUriTemplate.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify(\n\t\t\tawait getExerciseStepProgressDiff({ workshopDirectory }),\n\t\t),\n\t}\n}\n\nexport const exerciseStepProgressDiffResource = {\n\tname: 'exercise_step_progress_diff',\n\tdescription: 'The diff between the current exercise step and the solution',\n\turiTemplate: exerciseStepProgressDiffUriTemplate,\n\tgetResource: getExerciseStepProgressDiffResource,\n\tinputSchema: getExerciseStepProgressDiffInputSchema,\n}\n\nconst getUserInfoInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n}\n\nconst userInfoUri = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/user/info',\n\t{ list: undefined },\n)\n\nasync function getUserInfoResource({\n\tworkshopDirectory,\n}: InputSchemaType<typeof getUserInfoInputSchema>) {\n\tconst userInfo = await getUserInfo()\n\treturn {\n\t\turi: userInfoUri.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify(userInfo),\n\t}\n}\n\nexport const userInfoResource = {\n\tname: 'user_info',\n\tdescription: 'Information about the current user',\n\turiTemplate: userInfoUri,\n\tgetResource: getUserInfoResource,\n\tinputSchema: getUserInfoInputSchema,\n}\n\nconst getUserAccessInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n}\n\nconst userAccessUriTemplate = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/user/access',\n\t{ list: undefined },\n)\n\nasync function getUserAccessResource({\n\tworkshopDirectory,\n}: InputSchemaType<typeof getUserAccessInputSchema>) {\n\tconst userHasAccess = await userHasAccessToWorkshop()\n\treturn {\n\t\turi: userAccessUriTemplate.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify({ userHasAccess }),\n\t}\n}\n\nexport const userAccessResource = {\n\tname: 'user_access',\n\tdescription: 'Whether the current user has access to the workshop',\n\turiTemplate: userAccessUriTemplate,\n\tgetResource: getUserAccessResource,\n\tinputSchema: getUserAccessInputSchema,\n}\n\nconst userProgressInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n}\n\nconst userProgressUriTemplate = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/user/progress',\n\t{ list: undefined },\n)\n\nasync function getUserProgressResource({\n\tworkshopDirectory,\n}: InputSchemaType<typeof userProgressInputSchema>) {\n\tconst userProgress = await getProgress()\n\treturn {\n\t\turi: userProgressUriTemplate.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify(userProgress),\n\t}\n}\n\nexport const userProgressResource = {\n\tname: 'user_progress',\n\tdescription: 'The progress of the current user',\n\turiTemplate: userProgressUriTemplate,\n\tgetResource: getUserProgressResource,\n\tinputSchema: userProgressInputSchema,\n}\n\nexport function initResources(server: McpServer) {\n\tserver.registerResource(\n\t\tworkshopContextResource.name,\n\t\tworkshopContextResource.uriTemplate,\n\t\t{ description: workshopContextResource.description },\n\t\tasync (_uri, { workshopDirectory }) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\tconst resource = await workshopContextResource.getResource({\n\t\t\t\tworkshopDirectory,\n\t\t\t})\n\t\t\treturn { contents: [resource] }\n\t\t},\n\t)\n\n\tserver.registerResource(\n\t\texerciseContextResource.name,\n\t\texerciseContextResource.uriTemplate,\n\t\t{ description: exerciseContextResource.description },\n\t\tasync (\n\t\t\t_uri,\n\t\t\t{ workshopDirectory, exerciseNumber: providedExerciseNumber },\n\t\t) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\tinvariant(\n\t\t\t\ttypeof providedExerciseNumber === 'string',\n\t\t\t\t'A single exerciseNumber is required',\n\t\t\t)\n\t\t\tconst exerciseNumber = Number(providedExerciseNumber)\n\t\t\tinvariant(!isNaN(exerciseNumber), 'exerciseNumber must be a number')\n\t\t\tinvariant(\n\t\t\t\texerciseNumber >= 0,\n\t\t\t\t'exerciseNumber must be greater than or equal to 0',\n\t\t\t)\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\treturn {\n\t\t\t\tcontents: [\n\t\t\t\t\tawait exerciseContextResource.getResource({\n\t\t\t\t\t\tworkshopDirectory,\n\t\t\t\t\t\texerciseNumber,\n\t\t\t\t\t}),\n\t\t\t\t],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerResource(\n\t\texerciseStepContextResource.name,\n\t\texerciseStepContextResource.uriTemplate,\n\t\t{ description: exerciseStepContextResource.description },\n\t\tasync (\n\t\t\t_uri,\n\t\t\t{\n\t\t\t\tworkshopDirectory,\n\t\t\t\texerciseNumber: providedExerciseNumber,\n\t\t\t\tstepNumber: providedStepNumber,\n\t\t\t},\n\t\t) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\tinvariant(\n\t\t\t\ttypeof providedExerciseNumber === 'string',\n\t\t\t\t'A single exerciseNumber is required',\n\t\t\t)\n\t\t\tinvariant(\n\t\t\t\ttypeof providedStepNumber === 'string',\n\t\t\t\t'A single stepNumber is required',\n\t\t\t)\n\t\t\tconst exerciseNumber = Number(providedExerciseNumber)\n\t\t\tconst stepNumber = Number(providedStepNumber)\n\t\t\tinvariant(!isNaN(exerciseNumber), 'exerciseNumber must be a number')\n\t\t\tinvariant(!isNaN(stepNumber), 'stepNumber must be a number')\n\t\t\tinvariant(\n\t\t\t\texerciseNumber >= 0,\n\t\t\t\t'exerciseNumber must be greater than or equal to 0',\n\t\t\t)\n\t\t\tinvariant(\n\t\t\t\tstepNumber >= 0,\n\t\t\t\t'stepNumber must be greater than or equal to 0',\n\t\t\t)\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\treturn {\n\t\t\t\tcontents: [\n\t\t\t\t\tawait exerciseStepContextResource.getResource({\n\t\t\t\t\t\tworkshopDirectory,\n\t\t\t\t\t\texerciseNumber,\n\t\t\t\t\t\tstepNumber,\n\t\t\t\t\t}),\n\t\t\t\t],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerResource(\n\t\tdiffBetweenAppsResource.name,\n\t\tdiffBetweenAppsResource.uriTemplate,\n\t\t{ description: diffBetweenAppsResource.description },\n\t\tasync (_uri, { workshopDirectory, app1, app2 }) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\tinvariant(typeof app1 === 'string', 'A single app1 is required')\n\t\t\tinvariant(typeof app2 === 'string', 'A single app2 is required')\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\treturn {\n\t\t\t\tcontents: [\n\t\t\t\t\tawait diffBetweenAppsResource.getResource({\n\t\t\t\t\t\tworkshopDirectory,\n\t\t\t\t\t\tapp1,\n\t\t\t\t\t\tapp2,\n\t\t\t\t\t}),\n\t\t\t\t],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerResource(\n\t\texerciseStepProgressDiffResource.name,\n\t\texerciseStepProgressDiffResource.uriTemplate,\n\t\t{ description: exerciseStepProgressDiffResource.description },\n\t\tasync (_uri, { workshopDirectory }) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\treturn {\n\t\t\t\tcontents: [\n\t\t\t\t\tawait exerciseStepProgressDiffResource.getResource({\n\t\t\t\t\t\tworkshopDirectory,\n\t\t\t\t\t}),\n\t\t\t\t],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerResource(\n\t\tuserInfoResource.name,\n\t\tuserInfoResource.uriTemplate,\n\t\t{ description: userInfoResource.description },\n\t\tasync (_uri, { workshopDirectory }) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\treturn {\n\t\t\t\tcontents: [await userInfoResource.getResource({ workshopDirectory })],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerResource(\n\t\tuserAccessResource.name,\n\t\tuserAccessResource.uriTemplate,\n\t\t{ description: userAccessResource.description },\n\t\tasync (_uri, { workshopDirectory }) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\treturn {\n\t\t\t\tcontents: [await userAccessResource.getResource({ workshopDirectory })],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerResource(\n\t\tuserProgressResource.name,\n\t\tuserProgressResource.uriTemplate,\n\t\t{ description: userProgressResource.description },\n\t\tasync (_uri, { workshopDirectory }) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\treturn {\n\t\t\t\tcontents: [\n\t\t\t\t\tawait userProgressResource.getResource({ workshopDirectory }),\n\t\t\t\t],\n\t\t\t}\n\t\t},\n\t)\n}\n"]}
|
package/dist/esm/tools.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/tools.ts"],"names":[],"mappings":"AA+BA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,yCAAyC,CAAA;AA4BxE,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,QAyU1C;AAKD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,QA2SlD;AAGD,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,QAkQhD"}
|
package/dist/esm/tools.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC/C,OAAO,EACN,YAAY,EACZ,OAAO,EACP,WAAW,EACX,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,aAAa,GAEb,MAAM,sCAAsC,CAAA;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAA;AAC1E,OAAO,EACN,WAAW,EACX,MAAM,EACN,WAAW,GACX,MAAM,oCAAoC,CAAA;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAA;AACnE,OAAO,EACN,WAAW,EACX,WAAW,EACX,cAAc,GACd,MAAM,0CAA0C,CAAA;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,+CAA+C,CAAA;AAC5E,0CAA0C;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAMjD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EACN,uBAAuB,EACvB,uBAAuB,EACvB,2BAA2B,EAC3B,gCAAgC,EAChC,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,uBAAuB,GACvB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACN,uBAAuB,EACvB,cAAc,EACd,YAAY,EACZ,4BAA4B,GAC5B,MAAM,YAAY,CAAA;AAEnB,kCAAkC;AAClC,MAAM,+BAA+B,GAAG,KAAK,CAAA;AAE7C,MAAM,UAAU,SAAS,CAAC,MAAiB;IAC1C,MAAM,CAAC,YAAY,CAClB,OAAO,EACP;QACC,WAAW,EACV,4DAA4D,CAAC,IAAI,EAAE;QACpE,WAAW,EAAE;YACZ,iBAAiB,EAAE,4BAA4B;SAC/C;KACD,EACD,KAAK,EAAE,EAAE,iBAAiB,EAAE,EAAE,EAAE;QAC/B,MAAM,uBAAuB,CAAC,iBAAiB,CAAC,CAAA;QAChD,MAAM,EACL,OAAO,EAAE,EAAE,IAAI,EAAE,GACjB,GAAG,iBAAiB,EAAE,CAAA;QACvB,MAAM,MAAM,GAAG,WAAW,IAAI,QAAQ,CAAA;QACtC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC,CAAA;QACtE,MAAM,cAAc,GAAG,MAAM,MAAM,CAAC,2BAA2B,CAC9D,MAAM,EACN,EAAE,CACF,CAAA;QAED,KAAK,cAAc,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAErC,OAAO;YACN,OAAO,EAAE;gBACR;oBACC,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,gBAAgB,cAAc,CAAC,yBAAyB,qCAAqC,cAAc,CAAC,SAAS,aAAa;iBACxI;aACD;SACD,CAAA;QAED,KAAK,UAAU,cAAc;YAC5B,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;gBAC/B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;gBACd,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;gBACjB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;aACtC,CAAC,CAAA;YAEF,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC/B,KAAK,MAAM,CAAC,MAAM;qBAChB,YAAY,CAAC;oBACb,MAAM,EAAE,cAAc;oBACtB,MAAM,EAAE;wBACP,OAAO,EAAE,gCAAgC;qBACzC;iBACD,CAAC;qBACD,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;YAClB,CAAC,EAAE,cAAc,CAAC,UAAU,GAAG,IAAI,CAAC,CAAA;YAEpC,IAAI,CAAC;gBACJ,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,4BAA4B,CACzD,MAAM,EACN,cAAc,CACd,CAAA;gBACD,YAAY,CAAC,OAAO,CAAC,CAAA;gBAErB,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACf,MAAM,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;wBAChC,MAAM,EAAE,cAAc;wBACtB,MAAM,EAAE;4BACP,OAAO,EAAE,cAAc;yBACvB;qBACD,CAAC,CAAA;oBACF,OAAM;gBACP,CAAC;gBAED,MAAM,yBAAyB,GAAG,MAAM,MAAM,CAAC,sBAAsB,CACpE,MAAM,EACN,QAAQ,CAAC,YAAY,EACrB,IAAI,GAAG,CAAC,GAAG,MAAM,WAAW,CAAC,EAC7B,KAAK,CACL,CAAA;gBACD,MAAM,WAAW,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,CAAA;gBAC1D,MAAM,cAAc,GAAG,cAAc,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;gBAC5D,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC;oBAC7B,MAAM,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;wBAChC,MAAM,EAAE,cAAc;wBACtB,MAAM,EAAE;4BACP,OAAO,EAAE,8BAA8B,cAAc,CAAC,KAAK,CAAC,OAAO,EAAE;yBACrE;qBACD,CAAC,CAAA;oBACF,OAAM;gBACP,CAAC;gBACD,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAA;gBAEpC,MAAM,WAAW,CAAC;oBACjB,EAAE,EAAE,QAAQ,CAAC,EAAE;oBACf,QAAQ;oBACR,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,IAAI,EAAE,QAAQ,CAAC,IAAI;iBACnB,CAAC,CAAA;gBAEF,MAAM,WAAW,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAA;gBAEvC,MAAM,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;oBAChC,MAAM,EAAE,cAAc;oBACtB,MAAM,EAAE;wBACP,OAAO,EAAE,2BAA2B;qBACpC;iBACD,CAAC,CAAA;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,YAAY,CAAC,OAAO,CAAC,CAAA;gBACrB,MAAM,KAAK,CAAA;YACZ,CAAC;QACF,CAAC;IACF,CAAC,CACD,CAAA;IAED,MAAM,CAAC,YAAY,CAClB,QAAQ,EACR;QACC,WAAW,EAAE,gGAAgG;QAC7G,WAAW,EAAE;YACZ,iBAAiB,EAAE,4BAA4B;SAC/C;KACD,EACD,KAAK,EAAE,EAAE,iBAAiB,EAAE,EAAE,EAAE;QAC/B,MAAM,uBAAuB,CAAC,iBAAiB,CAAC,CAAA;QAChD,MAAM,MAAM,EAAE,CAAA;QACd,MAAM,WAAW,EAAE,CAAA;QACnB,OAAO;YACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;SAC/C,CAAA;IACF,CAAC,CACD,CAAA;IAED,MAAM,CAAC,YAAY,CAClB,gBAAgB,EAChB;QACC,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6Bd,CAAC,IAAI,EAAE;QACN,WAAW,EAAE;YACZ,iBAAiB,EAAE,4BAA4B;YAC/C,cAAc,EAAE,CAAC,CAAC,MAAM;iBACtB,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,8CAA8C,CAAC;YAC1D,UAAU,EAAE,CAAC,CAAC,MAAM;iBAClB,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,0CAA0C,CAAC;YACtD,IAAI,EAAE,CAAC;iBACL,IAAI,CAAC,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;iBAC7B,QAAQ,EAAE;iBACV,QAAQ,CAAC,0CAA0C,CAAC;SACtD;KACD,EACD,KAAK,EAAE,EAAE,iBAAiB,EAAE,cAAc,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,EAAE;QACjE,MAAM,uBAAuB,CAAC,iBAAiB,CAAC,CAAA;QAChD,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAA;QAEpC,IAAI,CAAC,cAAc,EAAE,CAAC;YACrB,IAAI,QAAQ,EAAE,CAAC;gBACd,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAA;gBACpC,MAAM,aAAa,GAAG,CAAC,CAA4B,EAAE,EAAE;oBACtD,IAAI,CAAC,CAAC,IAAI,KAAK,uBAAuB;wBAAE,OAAO,CAAC,CAAA;oBAChD,IAAI,CAAC,CAAC,IAAI,KAAK,mBAAmB;wBAAE,OAAO,KAAK,CAAA;oBAChD,IAAI,CAAC,CAAC,IAAI,KAAK,cAAc;wBAAE,OAAO,CAAC,CAAC,cAAc,GAAG,GAAG,CAAA;oBAC5D,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM;wBAAE,OAAO,CAAC,CAAC,cAAc,GAAG,GAAG,GAAG,CAAC,CAAC,UAAU,CAAA;oBACnE,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU;wBAAE,OAAO,CAAC,CAAC,cAAc,GAAG,GAAG,GAAG,GAAG,CAAA;oBAE9D,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS;wBAAE,OAAO,MAAM,CAAA;oBACvC,OAAO,CAAC,CAAC,CAAA;gBACV,CAAC,CAAA;gBACD,MAAM,cAAc,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;oBAC7C,OAAO,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAA;gBAC3C,CAAC,CAAC,CAAA;gBACF,MAAM,YAAY,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAA;gBACnE,IAAI,YAAY,EAAE,CAAC;oBAClB,IAAI,YAAY,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;wBAClC,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC;4BACxC,cAAc,EAAE,YAAY,CAAC,cAAc,CAAC,QAAQ,EAAE;4BACtD,UAAU,EAAE,YAAY,CAAC,UAAU,CAAC,QAAQ,EAAE;4BAC9C,IAAI,EAAE,SAAS;yBACf,CAAC,CAAA;wBACF,SAAS,CAAC,WAAW,EAAE,uBAAuB,CAAC,CAAA;wBAC/C,MAAM,aAAa,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAA;wBACzC,OAAO;4BACN,OAAO,EAAE;gCACR;oCACC,IAAI,EAAE,MAAM;oCACZ,IAAI,EAAE,qBAAqB,WAAW,CAAC,cAAc,IAAI,WAAW,CAAC,UAAU,IAAI,WAAW,CAAC,IAAI,EAAE;iCACrG;6BACD;yBACD,CAAA;oBACF,CAAC;oBAED,IACC,YAAY,CAAC,IAAI,KAAK,cAAc;wBACpC,YAAY,CAAC,IAAI,KAAK,UAAU,EAC/B,CAAC;wBACF,MAAM,IAAI,KAAK,CACd,8BAA8B,YAAY,CAAC,cAAc,IAAI,YAAY,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,UAAU,uEAAuE,YAAY,CAAC,aAAa,6BAA6B,CAC7P,CAAA;oBACF,CAAC;oBACD,IACC,YAAY,CAAC,IAAI,KAAK,uBAAuB;wBAC7C,YAAY,CAAC,IAAI,KAAK,mBAAmB,EACxC,CAAC;wBACF,MAAM,IAAI,KAAK,CACd,8BAA8B,YAAY,CAAC,cAAc,IAAI,YAAY,CAAC,IAAI,KAAK,uBAAuB,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,mBAAmB,uEAAuE,YAAY,CAAC,aAAa,6BAA6B,CACxR,CAAA;oBACF,CAAC;oBAED,MAAM,IAAI,KAAK,CACd,0BAA0B,YAAY,CAAC,cAAc,uEAAuE,YAAY,CAAC,aAAa,6BAA6B,CACnL,CAAA;gBACF,CAAC;YACF,CAAC;QACF,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,OAAO,EAAE,CAAA;QAC5B,MAAM,gBAAgB,GAAG,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAA;QAEvD,MAAM,iBAAiB,GAAG,MAAM,oBAAoB,EAAE,CAAA;QACtD,MAAM,2BAA2B,GAAG,gBAAgB,CAAC,SAAS,CAC7D,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,iBAAiB,CACnC,CAAA;QAED,IAAI,UAAuC,CAAA;QAC3C,4DAA4D;QAC5D,MAAM,mBAAmB,GAAG,CAAC,cAAc,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAA;QACnE,IAAI,mBAAmB,EAAE,CAAC;YACzB,UAAU,GAAG,gBAAgB;iBAC3B,KAAK,CAAC,2BAA2B,GAAG,CAAC,CAAC;iBACtC,IAAI,CAAC,YAAY,CAAC,CAAA;YACpB,SAAS,CAAC,UAAU,EAAE,gDAAgD,CAAC,CAAA;QACxE,CAAC;aAAM,CAAC;YACP,MAAM,sBAAsB,GAC3B,gBAAgB,CAAC,2BAA2B,CAAC,CAAA;YAE9C,oEAAoE;YACpE,cAAc,KAAK,sBAAsB,EAAE,cAAc,CAAA;YACzD,UAAU,KAAK,sBAAsB,EAAE,UAAU,CAAA;YACjD,IAAI,KAAK,sBAAsB,EAAE,IAAI,CAAA;YAErC,UAAU,GAAG,gBAAgB,CAAC,IAAI,CACjC,CAAC,CAAC,EAAE,EAAE,CACL,CAAC,CAAC,cAAc,KAAK,cAAc;gBACnC,CAAC,CAAC,UAAU,KAAK,UAAU;gBAC3B,CAAC,CAAC,IAAI,KAAK,IAAI,CAChB,CAAA;QACF,CAAC;QAED,SAAS,CACR,UAAU,EACV,qDAAqD,cAAc,IAAI,UAAU,IAAI,IAAI,EAAE,CAC3F,CAAA;QACD,MAAM,aAAa,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAA;QACxC,OAAO;YACN,OAAO,EAAE;gBACR;oBACC,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,qBAAqB,UAAU,CAAC,IAAI,GAAG;iBAC7C;aACD;SACD,CAAA;IACF,CAAC,CACD,CAAA;IAED,MAAM,CAAC,YAAY,CAClB,iBAAiB,EACjB;QACC,WAAW,EAAE;;;;GAIb,CAAC,IAAI,EAAE;QACP,WAAW,EAAE;YACZ,iBAAiB,EAAE,4BAA4B;YAC/C,cAAc,EAAE,CAAC;iBACf,MAAM,EAAE;iBACR,QAAQ,CACR,4IAA4I,CAC5I;YACF,QAAQ,EAAE,CAAC;iBACT,OAAO,EAAE;iBACT,QAAQ,EAAE;iBACV,OAAO,CAAC,IAAI,CAAC;iBACb,QAAQ,CACR,yEAAyE,CACzE;SACF;KACD,EACD,KAAK,EAAE,EAAE,iBAAiB,EAAE,cAAc,EAAE,QAAQ,EAAE,EAAE,EAAE;QACzD,MAAM,uBAAuB,CAAC,iBAAiB,CAAC,CAAA;QAChD,MAAM,cAAc,CAAC,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,CAAA;QAC9D,OAAO;YACN,OAAO,EAAE;gBACR;oBACC,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,oBAAoB,cAAc,cAAc,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,EAAE;iBAC5F;aACD;SACD,CAAA;IACF,CAAC,CACD,CAAA;IAED,gEAAgE;AACjE,CAAC;AAED,uEAAuE;AACvE,gFAAgF;AAChF,uBAAuB;AACvB,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IAClD,MAAM,CAAC,YAAY,CAClB,sBAAsB,EACtB;QACC,WAAW,EAAE;;;;;GAKb,CAAC,IAAI,EAAE;QACP,WAAW,EAAE,uBAAuB,CAAC,WAAW;KAChD,EACD,KAAK,EAAE,EAAE,iBAAiB,EAAE,EAAE,EAAE;QAC/B,iBAAiB,GAAG,MAAM,uBAAuB,CAAC,iBAAiB,CAAC,CAAA;QACpE,MAAM,QAAQ,GAAG,MAAM,uBAAuB,CAAC,WAAW,CAAC;YAC1D,iBAAiB;SACjB,CAAC,CAAA;QACF,OAAO;YACN,OAAO,EAAE,CAAC,0BAA0B,CAAC,QAAQ,CAAC,CAAC;SAC/C,CAAA;IACF,CAAC,CACD,CAAA;IAED,MAAM,CAAC,YAAY,CAClB,sBAAsB,EACtB;QACC,WAAW,EAAE;;;;;;;;;;;;;;GAcb,CAAC,IAAI,EAAE;QACP,WAAW,EAAE,uBAAuB,CAAC,WAAW;KAChD,EACD,KAAK,EAAE,EAAE,iBAAiB,EAAE,cAAc,EAAE,EAAE,EAAE;QAC/C,iBAAiB,GAAG,MAAM,uBAAuB,CAAC,iBAAiB,CAAC,CAAA;QACpE,MAAM,QAAQ,GAAG,MAAM,uBAAuB,CAAC,WAAW,CAAC;YAC1D,iBAAiB;YACjB,cAAc;SACd,CAAC,CAAA;QACF,OAAO;YACN,OAAO,EAAE,CAAC,0BAA0B,CAAC,QAAQ,CAAC,CAAC;SAC/C,CAAA;IACF,CAAC,CACD,CAAA;IAED,MAAM,CAAC,YAAY,CAClB,uBAAuB,EACvB;QACC,WAAW,EAAE;;;;;;;;;;;;GAYb;QACA,WAAW,EAAE,uBAAuB,CAAC,WAAW;KAChD,EACD,KAAK,EAAE,EAAE,iBAAiB,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE;QAC3C,iBAAiB,GAAG,MAAM,uBAAuB,CAAC,iBAAiB,CAAC,CAAA;QACpE,MAAM,QAAQ,GAAG,MAAM,uBAAuB,CAAC,WAAW,CAAC;YAC1D,iBAAiB;YACjB,IAAI;YACJ,IAAI;SACJ,CAAC,CAAA;QACF,OAAO;YACN,OAAO,EAAE,CAAC,0BAA0B,CAAC,QAAQ,CAAC,CAAC;SAC/C,CAAA;IACF,CAAC,CACD,CAAA;IAED,MAAM,CAAC,YAAY,CAClB,iCAAiC,EACjC;QACC,WAAW,EAAE;;GAEb,CAAC,IAAI,EAAE;QACP,WAAW,EAAE,gCAAgC,CAAC,WAAW;KACzD,EACD,KAAK,EAAE,EAAE,iBAAiB,EAAE,EAAE,EAAE;QAC/B,iBAAiB,GAAG,MAAM,uBAAuB,CAAC,iBAAiB,CAAC,CAAA;QACpE,MAAM,QAAQ,GAAG,MAAM,gCAAgC,CAAC,WAAW,CAAC;YACnE,iBAAiB;SACjB,CAAC,CAAA;QACF,OAAO;YACN,OAAO,EAAE;gBACR,UAAU,CAAC,sBAAsB,EAAE,CAAC;gBACpC,0BAA0B,CAAC,QAAQ,CAAC;aACpC;SACD,CAAA;IACF,CAAC,CACD,CAAA;IAED,MAAM,CAAC,YAAY,CAClB,2BAA2B,EAC3B;QACC,WAAW,EAAE;;;;;;;;;;;;;;GAcb,CAAC,IAAI,EAAE;QACP,WAAW,EAAE,2BAA2B,CAAC,WAAW;KACpD,EACD,KAAK,EAAE,EAAE,iBAAiB,EAAE,cAAc,EAAE,UAAU,EAAE,EAAE,EAAE;QAC3D,iBAAiB,GAAG,MAAM,uBAAuB,CAAC,iBAAiB,CAAC,CAAA;QACpE,MAAM,QAAQ,GAAG,MAAM,2BAA2B,CAAC,WAAW,CAAC;YAC9D,iBAAiB;YACjB,cAAc;YACd,UAAU;SACV,CAAC,CAAA;QACF,OAAO;YACN,OAAO,EAAE,CAAC,0BAA0B,CAAC,QAAQ,CAAC,CAAC;SAC/C,CAAA;IACF,CAAC,CACD,CAAA;IAED,MAAM,CAAC,YAAY,CAClB,YAAY,EACZ;QACC,WAAW,EAAE;;;;GAIb,CAAC,IAAI,EAAE;QACP,WAAW,EAAE;YACZ,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAC5B;;OAEE,CAAC,IAAI,EAAE,CACT;SACD;KACD,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QACtB,MAAM,GAAG,GAAQ,IAAI,GAAG,CAAC,mBAAmB,EAAE,uBAAuB,CAAC,CAAA;QACtE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;QACrC,OAAO;YACN,OAAO,EAAE;gBACR,gBAAgB,CAAC;oBAChB,OAAO,EAAE;wBACR,IAAI,EAAE,aAAa;wBACnB,SAAS,EAAE,GAAG,CAAC,QAAQ,EAAE;qBACzB;oBACD,GAAG,EAAE,4BAA4B,QAAQ,CAAC,QAAQ,EAAE,EAAE;oBACtD,QAAQ,EAAE,MAAM;iBAChB,CAAC;aACF;SACD,CAAA;IACF,CAAC,CACD,CAAA;IAED,MAAM,CAAC,YAAY,CAClB,0BAA0B,EAC1B;QACC,KAAK,EAAE,0BAA0B;QACjC,WAAW,EAAE;;GAEb,CAAC,IAAI,EAAE;QACP,WAAW,EAAE;YACZ,iBAAiB,EAAE,4BAA4B;SAC/C;KACD,EACD,KAAK,EAAE,EAAE,iBAAiB,EAAE,EAAE,EAAE;QAC/B,MAAM,uBAAuB,CAAC,iBAAiB,CAAC,CAAA;QAChD,MAAM,aAAa,GAAG,MAAM,gBAAgB,EAAE,CAAA;QAC9C,SAAS,CACR,aAAa,EACb,mHAAmH,CACnH,CAAA;QACD,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;QAC5D,SAAS,CACR,UAAU,EACV,kJAAkJ,CAClJ,CAAA;QACD,SAAS,CACR,YAAY,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,YAAY,EACnD,0IAA0I,CAC1I,CAAA;QACD,MAAM,WAAW,GAAG,MAAM,YAAY,CAAC,UAAU,CAAC,YAAY,CAAC,CAAA;QAC/D,SAAS,CACR,WAAW,EACX,oIAAoI,CACpI,CAAA;QACD,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,UAAU,EAAE,WAAW,CAAC,CAAA;QAC7D,SAAS,CACR,SAAS,EACT,qEAAqE,CACrE,CAAA;QACD,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;YAC7D,MAAM,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;QACxC,CAAC;QACD,OAAO;YACN,OAAO,EAAE;gBACR;oBACC,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,UAAU,SAAS,CAAC,MAAM,QAAQ,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;iBAChJ;aACD;SACD,CAAA;IACF,CAAC,CACD,CAAA;IAED,MAAM,CAAC,YAAY,CAClB,eAAe,EACf;QACC,WAAW,EAAE;;;;;;;GAOb,CAAC,IAAI,EAAE;QACP,WAAW,EAAE,gBAAgB,CAAC,WAAW;KACzC,EACD,KAAK,EAAE,EAAE,iBAAiB,EAAE,EAAE,EAAE;QAC/B,iBAAiB,GAAG,MAAM,uBAAuB,CAAC,iBAAiB,CAAC,CAAA;QACpE,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,WAAW,CAAC,EAAE,iBAAiB,EAAE,CAAC,CAAA;QAC1E,OAAO;YACN,OAAO,EAAE,CAAC,0BAA0B,CAAC,QAAQ,CAAC,CAAC;SAC/C,CAAA;IACF,CAAC,CACD,CAAA;IAED,MAAM,CAAC,YAAY,CAClB,iBAAiB,EACjB;QACC,WAAW,EAAE;;;;;;;;;;;;GAYb,CAAC,IAAI,EAAE;QACP,WAAW,EAAE,kBAAkB,CAAC,WAAW;KAC3C,EACD,KAAK,EAAE,EAAE,iBAAiB,EAAE,EAAE,EAAE;QAC/B,iBAAiB,GAAG,MAAM,uBAAuB,CAAC,iBAAiB,CAAC,CAAA;QACpE,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,WAAW,CAAC;YACrD,iBAAiB;SACjB,CAAC,CAAA;QACF,OAAO;YACN,OAAO,EAAE,CAAC,0BAA0B,CAAC,QAAQ,CAAC,CAAC;SAC/C,CAAA;IACF,CAAC,CACD,CAAA;IAED,MAAM,CAAC,YAAY,CAClB,mBAAmB,EACnB;QACC,WAAW,EAAE;;;;;GAKb,CAAC,IAAI,EAAE;QACP,WAAW,EAAE,oBAAoB,CAAC,WAAW;KAC7C,EACD,KAAK,EAAE,EAAE,iBAAiB,EAAE,EAAE,EAAE;QAC/B,iBAAiB,GAAG,MAAM,uBAAuB,CAAC,iBAAiB,CAAC,CAAA;QACpE,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,WAAW,CAAC;YACvD,iBAAiB;SACjB,CAAC,CAAA;QACF,OAAO;YACN,OAAO,EAAE,CAAC,0BAA0B,CAAC,QAAQ,CAAC,CAAC;SAC/C,CAAA;IACF,CAAC,CACD,CAAA;AACF,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,eAAe,CAAC,MAAiB;IAChD,MAAM,CAAC,YAAY,CAClB,uBAAuB,EACvB;QACC,WAAW,EAAE;;;;;;;GAOb,CAAC,IAAI,EAAE;QACP,WAAW,EAAE,iBAAiB;KAC9B,EACD,KAAK,EAAE,EAAE,iBAAiB,EAAE,cAAc,EAAE,EAAE,EAAE;QAC/C,iBAAiB,GAAG,MAAM,uBAAuB,CAAC,iBAAiB,CAAC,CAAA;QACpE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,EAAE,iBAAiB,EAAE,cAAc,EAAE,CAAC,CAAA;QAClE,OAAO;YACN,4EAA4E;YAC5E,4EAA4E;YAC5E,kCAAkC;YAClC,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBAClC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;oBACnC,OAAO,0BAA0B,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;gBACtD,CAAC;gBACD,OAAO,CAAC,CAAC,OAAO,CAAA;YACjB,CAAC,CAAC;SACF,CAAA;IACF,CAAC,CACD,CAAA;IAED,MAAM,CAAC,YAAY,CAClB,kBAAkB,EAClB;QACC,KAAK,EAAE,kBAAkB;QACzB,WAAW,EAAE;;;;;;IAMZ,CAAC,IAAI,EAAE;QACR,WAAW,EAAE;YACZ,iBAAiB,EAAE,4BAA4B;SAC/C;KACD,EACD,KAAK,EAAE,EAAE,iBAAiB,EAAE,EAAE,EAAE;QAC/B,MAAM,uBAAuB,CAAC,iBAAiB,CAAC,CAAA;QAEhD,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAA;QACpC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,OAAO;gBACN,OAAO,EAAE;oBACR;wBACC,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,oEAAoE;qBAC1E;iBACD;aACD,CAAA;QACF,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAA;QAEpC,MAAM,aAAa,GAAG,CAAC,CAA4B,EAAE,EAAE;YACtD,IAAI,CAAC,CAAC,IAAI,KAAK,uBAAuB;gBAAE,OAAO,CAAC,CAAA;YAChD,IAAI,CAAC,CAAC,IAAI,KAAK,mBAAmB;gBAAE,OAAO,KAAK,CAAA;YAChD,IAAI,CAAC,CAAC,IAAI,KAAK,cAAc;gBAAE,OAAO,CAAC,CAAC,cAAc,GAAG,GAAG,CAAA;YAC5D,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM;gBAAE,OAAO,CAAC,CAAC,cAAc,GAAG,GAAG,GAAG,CAAC,CAAC,UAAU,CAAA;YACnE,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU;gBAAE,OAAO,CAAC,CAAC,cAAc,GAAG,GAAG,GAAG,GAAG,CAAA;YAE9D,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS;gBAAE,OAAO,MAAM,CAAA;YACvC,OAAO,CAAC,CAAC,CAAA;QACV,CAAC,CAAA;QACD,MAAM,cAAc,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAC7C,OAAO,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAA;QAC3C,CAAC,CAAC,CAAA;QACF,MAAM,YAAY,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAA;QACnE,IAAI,CAAC,YAAY,EAAE,CAAC;YACnB,OAAO;gBACN,OAAO,EAAE;oBACR;wBACC,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,4KAA4K;qBAClL;oBACD,UAAU,CAAC,MAAM,qBAAqB,EAAE,CAAC;iBACzC;aACD,CAAA;QACF,CAAC;QAED,SAAS,CACR,YAAY,CAAC,IAAI,KAAK,SAAS,EAC/B,iIAAiI,MAAM,qBAAqB,EAAE,EAAE,CAChK,CAAA;QAED,IAAI,YAAY,CAAC,IAAI,KAAK,uBAAuB,EAAE,CAAC;YACnD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,mBAAmB,EAAE,uBAAuB,CAAC,CAAA;YACtE,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,YAAY,CAAC,aAAa,CAAC,CAAA;YAC5D,OAAO;gBACN,OAAO,EAAE;oBACR,UAAU,CACT,oPAAoP,YAAY,CAAC,cAAc,0FAA0F,CACzW;oBACD,UAAU,CAAC,MAAM,qBAAqB,EAAE,CAAC;oBACzC,UAAU,CACT,kBAAkB,MAAM,cAAc,CAAC,WAAW,EAAE,YAAY,CAAC,EAAE,CACnE;oBACD,gBAAgB,CAAC;wBAChB,GAAG,EAAE,4BAA4B,YAAY,CAAC,aAAa,EAAE;wBAC7D,QAAQ,EAAE,MAAM;wBAChB,OAAO,EAAE;4BACR,IAAI,EAAE,aAAa;4BACnB,SAAS,EAAE,QAAQ,CAAC,QAAQ,EAAE;yBAC9B;qBACD,CAAC;iBACF;aACD,CAAA;QACF,CAAC;QAED,IAAI,YAAY,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;YAC/C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,mBAAmB,EAAE,uBAAuB,CAAC,CAAA;YACtE,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,YAAY,CAAC,aAAa,CAAC,CAAA;YAC5D,OAAO;gBACN,OAAO,EAAE;oBACR,UAAU,CACT,iRAAiR,YAAY,CAAC,cAAc,0FAA0F,CACtY;oBACD,UAAU,CACT,2BAA2B,MAAM,cAAc,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE,CAC9E;oBACD,gBAAgB,CAAC;wBAChB,GAAG,EAAE,4BAA4B,YAAY,CAAC,aAAa,EAAE;wBAC7D,QAAQ,EAAE,MAAM;wBAChB,OAAO,EAAE;4BACR,IAAI,EAAE,aAAa;4BACnB,SAAS,EAAE,QAAQ,CAAC,QAAQ,EAAE;yBAC9B;qBACD,CAAC;iBACF;aACD,CAAA;QACF,CAAC;QAED,MAAM,EAAE,GAAG,YAAY,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;QAClE,IAAI,YAAY,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YAC1C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,mBAAmB,EAAE,uBAAuB,CAAC,CAAA;YACtE,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,YAAY,CAAC,aAAa,CAAC,CAAA;YAC5D,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,cAAc,CAAC,CAAA;YAC/D,OAAO;gBACN,OAAO,EAAE;oBACR,UAAU,CACT,qDAAqD,EAAE,gIAAgI,YAAY,CAAC,cAAc,0FAA0F,CAC5S;oBACD,UAAU,CACT,2BAA2B,MAAM,UAAU,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CACjE;oBACD,gBAAgB,CAAC;wBAChB,GAAG,EAAE,4BAA4B,YAAY,CAAC,aAAa,EAAE;wBAC7D,QAAQ,EAAE,MAAM;wBAChB,OAAO,EAAE;4BACR,IAAI,EAAE,aAAa;4BACnB,SAAS,EAAE,QAAQ,CAAC,QAAQ,EAAE;yBAC9B;qBACD,CAAC;iBACF;aACD,CAAA;QACF,CAAC;QACD,IAAI,YAAY,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YACtC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,mBAAmB,EAAE,uBAAuB,CAAC,CAAA;YACtE,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,YAAY,CAAC,aAAa,CAAC,CAAA;YAC5D,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,cAAc,CAAC,CAAA;YAC/D,OAAO;gBACN,OAAO,EAAE;oBACR,UAAU,CACT,6CAA6C,EAAE,kDAAkD,EAAE,2BAA2B,CAC9H;oBACD,UAAU,CACT,oCAAoC,MAAM,UAAU,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAC1E;oBACD,gBAAgB,CAAC;wBAChB,GAAG,EAAE,4BAA4B,YAAY,CAAC,aAAa,EAAE;wBAC7D,QAAQ,EAAE,MAAM;wBAChB,OAAO,EAAE;4BACR,IAAI,EAAE,aAAa;4BACnB,SAAS,EAAE,QAAQ,CAAC,QAAQ,EAAE;yBAC9B;qBACD,CAAC;iBACF;aACD,CAAA;QACF,CAAC;QAED,MAAM,EAAE,GAAG,YAAY,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;QAC9D,IAAI,YAAY,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAClC,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,cAAc,CAAC,CAAA;YAC/D,MAAM,eAAe,GAAG,IAAI,GAAG,CAC9B,mBAAmB,EACnB,uBAAuB,CACvB,CAAA;YACD,eAAe,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,YAAY,CAAC,aAAa,CAAC,CAAA;YACnE,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAC/B,mBAAmB,EACnB,uBAAuB,CACvB,CAAA;YACD,gBAAgB,CAAC,YAAY,CAAC,GAAG,CAChC,KAAK,EACL,GAAG,YAAY,CAAC,aAAa,WAAW,CACxC,CAAA;YACD,MAAM,IAAI,GAAG,QAAQ,EAAE,KAAK,CAAC,IAAI,CAChC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,YAAY,CAAC,UAAU,CAC/C,CAAA;YACD,SAAS,CACR,IAAI,EACJ,8BAA8B,YAAY,CAAC,cAAc,SAAS,YAAY,CAAC,UAAU,EAAE,CAC3F,CAAA;YACD,OAAO;gBACN,OAAO,EAAE;oBACR,UAAU,CACT;sBACe,EAAE,gBAAgB,EAAE;;;;;;;;oGAQ0D,YAAY,CAAC,cAAc;;;QAGvH,CAAC,IAAI,EAAE,CACR;oBACD,UAAU,CACT,wCAAwC,MAAM,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,CAClF;oBACD,UAAU,CACT,yCAAyC,MAAM,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CACpF;oBACD,gBAAgB,CAAC;wBAChB,GAAG,EAAE,4BAA4B,YAAY,CAAC,aAAa,EAAE;wBAC7D,QAAQ,EAAE,MAAM;wBAChB,OAAO,EAAE;4BACR,IAAI,EAAE,aAAa;4BACnB,SAAS,EAAE,eAAe,CAAC,QAAQ,EAAE;yBACrC;qBACD,CAAC;oBACF,gBAAgB,CAAC;wBAChB,GAAG,EAAE,4BAA4B,YAAY,CAAC,aAAa,WAAW;wBACtE,QAAQ,EAAE,MAAM;wBAChB,OAAO,EAAE;4BACR,IAAI,EAAE,aAAa;4BACnB,SAAS,EAAE,gBAAgB,CAAC,QAAQ,EAAE;yBACtC;qBACD,CAAC;iBACF;aACD,CAAA;QACF,CAAC;QACD,MAAM,IAAI,KAAK,CACd,kFAAkF,CAClF,CAAA;IACF,CAAC,CACD,CAAA;AACF,CAAC;AAED,SAAS,0BAA0B,CAClC,QAAgD;IAEhD,IAAI,+BAA+B,EAAE,CAAC;QACrC,OAAO;YACN,IAAI,EAAE,UAAmB;YACzB,QAAQ;SACR,CAAA;IACF,CAAC;SAAM,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC9C,OAAO;YACN,IAAI,EAAE,MAAe;YACrB,IAAI,EAAE,QAAQ,CAAC,IAAI;SACnB,CAAA;IACF,CAAC;SAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACd,0BAA0B,QAAQ,CAAC,IAAI,QAAQ,QAAQ,CAAC,GAAG,EAAE,CAC7D,CAAA;IACF,CAAC;AACF,CAAC;AAED,SAAS,UAAU,CAAC,IAAa;IAChC,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA;IAC9B,CAAC;SAAM,CAAC;QACP,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAA;IACpD,CAAC;AACF,CAAC;AAED,KAAK,UAAU,qBAAqB;IACnC,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAA;IAClC,MAAM,SAAS,GAAG,MAAM,YAAY,EAAE,CAAA;IACtC,IAAI,OAAO,GAAG,KAAK,MAAM,CAAC,KAAK;;EAE9B,MAAM,CAAC,QAAQ;;;CAGhB,CAAA;IACA,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QAClC,OAAO,IAAI;EACX,QAAQ,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,QAAQ,CAAC,KAAK;EACtE,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,KAAK,IAAI,CAAC,CAAC,QAAQ,EAAE,KAAK,IAAI,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAA;IAChJ,CAAC;IACD,OAAO,OAAO,CAAA;AACf,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,OAAgB;IACzC,OAAO,CACN,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACvE,iBAAiB,CACjB,CAAA;AACF,CAAC;AAED,SAAS,sBAAsB;IAC9B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgCN,CAAC,IAAI,EAAE,CAAA;AACT,CAAC","sourcesContent":["import path from 'node:path'\nimport { invariant } from '@epic-web/invariant'\nimport {\n\tgetAppByName,\n\tgetApps,\n\tgetExercise,\n\tgetExerciseApp,\n\tgetExercises,\n\tgetPlaygroundApp,\n\tgetPlaygroundAppName,\n\tisExerciseStepApp,\n\tisProblemApp,\n\tsetPlayground,\n\ttype ExerciseStepApp,\n} from '@epic-web/workshop-utils/apps.server'\nimport { deleteCache } from '@epic-web/workshop-utils/cache.server'\nimport { getWorkshopConfig } from '@epic-web/workshop-utils/config.server'\nimport {\n\tgetAuthInfo,\n\tlogout,\n\tsetAuthInfo,\n} from '@epic-web/workshop-utils/db.server'\nimport { getDiffFiles } from '@epic-web/workshop-utils/diff.server'\nimport {\n\tgetProgress,\n\tgetUserInfo,\n\tupdateProgress,\n} from '@epic-web/workshop-utils/epic-api.server'\nimport { launchEditor } from '@epic-web/workshop-utils/launch-editor.server'\n// @ts-ignore 🤷♂️ tshy doesn't like this\nimport { createUIResource } from '@mcp-ui/server'\nimport { type McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport {\n\ttype CallToolResult,\n\ttype ReadResourceResult,\n} from '@modelcontextprotocol/sdk/types.js'\nimport * as client from 'openid-client'\nimport { z } from 'zod'\nimport { quizMe, quizMeInputSchema } from './prompts.js'\nimport {\n\tdiffBetweenAppsResource,\n\texerciseContextResource,\n\texerciseStepContextResource,\n\texerciseStepProgressDiffResource,\n\tuserAccessResource,\n\tuserInfoResource,\n\tuserProgressResource,\n\tworkshopContextResource,\n} from './resources.js'\nimport {\n\thandleWorkshopDirectory,\n\treadInWorkshop,\n\tsafeReadFile,\n\tworkshopDirectoryInputSchema,\n} from './utils.js'\n\n// not enough support for this yet\nconst clientSupportsEmbeddedResources = false\n\nexport function initTools(server: McpServer) {\n\tserver.registerTool(\n\t\t'login',\n\t\t{\n\t\t\tdescription:\n\t\t\t\t`Allow the user to login (or sign up) to the epic workshop.`.trim(),\n\t\t\tinputSchema: {\n\t\t\t\tworkshopDirectory: workshopDirectoryInputSchema,\n\t\t\t},\n\t\t},\n\t\tasync ({ workshopDirectory }) => {\n\t\t\tawait handleWorkshopDirectory(workshopDirectory)\n\t\t\tconst {\n\t\t\t\tproduct: { host },\n\t\t\t} = getWorkshopConfig()\n\t\t\tconst ISSUER = `https://${host}/oauth`\n\t\t\tconst config = await client.discovery(new URL(ISSUER), 'EPICSHOP_APP')\n\t\t\tconst deviceResponse = await client.initiateDeviceAuthorization(\n\t\t\t\tconfig,\n\t\t\t\t{},\n\t\t\t)\n\n\t\t\tvoid handleAuthFlow().catch(() => {})\n\n\t\t\treturn {\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\ttext: `Please go to ${deviceResponse.verification_uri_complete}. Verify the code on the page is \"${deviceResponse.user_code}\" to login.`,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t}\n\n\t\t\tasync function handleAuthFlow() {\n\t\t\t\tconst UserInfoSchema = z.object({\n\t\t\t\t\tid: z.string(),\n\t\t\t\t\temail: z.string(),\n\t\t\t\t\tname: z.string().nullable().optional(),\n\t\t\t\t})\n\n\t\t\t\tconst timeout = setTimeout(() => {\n\t\t\t\t\tvoid server.server\n\t\t\t\t\t\t.notification({\n\t\t\t\t\t\t\tmethod: 'notification',\n\t\t\t\t\t\t\tparams: {\n\t\t\t\t\t\t\t\tmessage: 'Device authorization timed out',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.catch(() => {})\n\t\t\t\t}, deviceResponse.expires_in * 1000)\n\n\t\t\t\ttry {\n\t\t\t\t\tconst tokenSet = await client.pollDeviceAuthorizationGrant(\n\t\t\t\t\t\tconfig,\n\t\t\t\t\t\tdeviceResponse,\n\t\t\t\t\t)\n\t\t\t\t\tclearTimeout(timeout)\n\n\t\t\t\t\tif (!tokenSet) {\n\t\t\t\t\t\tawait server.server.notification({\n\t\t\t\t\t\t\tmethod: 'notification',\n\t\t\t\t\t\t\tparams: {\n\t\t\t\t\t\t\t\tmessage: 'No token set',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\tconst protectedResourceResponse = await client.fetchProtectedResource(\n\t\t\t\t\t\tconfig,\n\t\t\t\t\t\ttokenSet.access_token,\n\t\t\t\t\t\tnew URL(`${ISSUER}/userinfo`),\n\t\t\t\t\t\t'GET',\n\t\t\t\t\t)\n\t\t\t\t\tconst userinfoRaw = await protectedResourceResponse.json()\n\t\t\t\t\tconst userinfoResult = UserInfoSchema.safeParse(userinfoRaw)\n\t\t\t\t\tif (!userinfoResult.success) {\n\t\t\t\t\t\tawait server.server.notification({\n\t\t\t\t\t\t\tmethod: 'notification',\n\t\t\t\t\t\t\tparams: {\n\t\t\t\t\t\t\t\tmessage: `Failed to parse user info: ${userinfoResult.error.message}`,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tconst userinfo = userinfoResult.data\n\n\t\t\t\t\tawait setAuthInfo({\n\t\t\t\t\t\tid: userinfo.id,\n\t\t\t\t\t\ttokenSet,\n\t\t\t\t\t\temail: userinfo.email,\n\t\t\t\t\t\tname: userinfo.name,\n\t\t\t\t\t})\n\n\t\t\t\t\tawait getUserInfo({ forceFresh: true })\n\n\t\t\t\t\tawait server.server.notification({\n\t\t\t\t\t\tmethod: 'notification',\n\t\t\t\t\t\tparams: {\n\t\t\t\t\t\t\tmessage: 'Authentication successful',\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t} catch (error) {\n\t\t\t\t\tclearTimeout(timeout)\n\t\t\t\t\tthrow error\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerTool(\n\t\t'logout',\n\t\t{\n\t\t\tdescription: `Allow the user to logout of the workshop (based on the workshop's host) and delete cache data.`,\n\t\t\tinputSchema: {\n\t\t\t\tworkshopDirectory: workshopDirectoryInputSchema,\n\t\t\t},\n\t\t},\n\t\tasync ({ workshopDirectory }) => {\n\t\t\tawait handleWorkshopDirectory(workshopDirectory)\n\t\t\tawait logout()\n\t\t\tawait deleteCache()\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: 'text', text: 'Logged out' }],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerTool(\n\t\t'set_playground',\n\t\t{\n\t\t\tdescription: `\nSets the playground environment so the user can continue to that exercise or see\nwhat that step looks like in their playground environment.\n\nNOTE: this will override their current exercise step work in the playground!\n\nGenerally, it is better to not provide an exerciseNumber, stepNumber, and type\nand let the user continue to the next exercise. Only provide these arguments if\nthe user explicitely asks to go to a specific exercise or step. If the user asks\nto start an exercise, specify stepNumber 1 and type 'problem' unless otherwise\ndirected.\n\nArgument examples:\nA. If logged in and there is an incomplete exercise step, set to next incomplete exercise step based on the user's progress - Most common\n\t- [No arguments]\nB. If not logged in or all exercises are complete, set to next exercise step from current (or first if there is none)\n\t- [No arguments]\nC. Set to a specific exercise step\n\t- exerciseNumber: 1\n\t- stepNumber: 1\n\t- type: 'solution'\nD. Set to the solution of the current exercise step\n\t- type: 'solution'\nE. Set to the second step problem of the current exercise\n\t- stepNumber: 2\nF. Set to the first step problem of the fifth exercise\n\t- exerciseNumber: 5\n\nAn error will be returned if no app is found for the given arguments.\n\t`.trim(),\n\t\t\tinputSchema: {\n\t\t\t\tworkshopDirectory: workshopDirectoryInputSchema,\n\t\t\t\texerciseNumber: z.coerce\n\t\t\t\t\t.number()\n\t\t\t\t\t.optional()\n\t\t\t\t\t.describe('The exercise number to set the playground to'),\n\t\t\t\tstepNumber: z.coerce\n\t\t\t\t\t.number()\n\t\t\t\t\t.optional()\n\t\t\t\t\t.describe('The step number to set the playground to'),\n\t\t\t\ttype: z\n\t\t\t\t\t.enum(['problem', 'solution'])\n\t\t\t\t\t.optional()\n\t\t\t\t\t.describe('The type of app to set the playground to'),\n\t\t\t},\n\t\t},\n\t\tasync ({ workshopDirectory, exerciseNumber, stepNumber, type }) => {\n\t\t\tawait handleWorkshopDirectory(workshopDirectory)\n\t\t\tconst authInfo = await getAuthInfo()\n\n\t\t\tif (!exerciseNumber) {\n\t\t\t\tif (authInfo) {\n\t\t\t\t\tconst progress = await getProgress()\n\t\t\t\t\tconst scoreProgress = (a: (typeof progress)[number]) => {\n\t\t\t\t\t\tif (a.type === 'workshop-instructions') return 0\n\t\t\t\t\t\tif (a.type === 'workshop-finished') return 10000\n\t\t\t\t\t\tif (a.type === 'instructions') return a.exerciseNumber * 100\n\t\t\t\t\t\tif (a.type === 'step') return a.exerciseNumber * 100 + a.stepNumber\n\t\t\t\t\t\tif (a.type === 'finished') return a.exerciseNumber * 100 + 100\n\n\t\t\t\t\t\tif (a.type === 'unknown') return 100000\n\t\t\t\t\t\treturn -1\n\t\t\t\t\t}\n\t\t\t\t\tconst sortedProgress = progress.sort((a, b) => {\n\t\t\t\t\t\treturn scoreProgress(a) - scoreProgress(b)\n\t\t\t\t\t})\n\t\t\t\t\tconst nextProgress = sortedProgress.find((p) => !p.epicCompletedAt)\n\t\t\t\t\tif (nextProgress) {\n\t\t\t\t\t\tif (nextProgress.type === 'step') {\n\t\t\t\t\t\t\tconst exerciseApp = await getExerciseApp({\n\t\t\t\t\t\t\t\texerciseNumber: nextProgress.exerciseNumber.toString(),\n\t\t\t\t\t\t\t\tstepNumber: nextProgress.stepNumber.toString(),\n\t\t\t\t\t\t\t\ttype: 'problem',\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\tinvariant(exerciseApp, 'No exercise app found')\n\t\t\t\t\t\t\tawait setPlayground(exerciseApp.fullPath)\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\t\t\t\t\ttext: `Playground set to ${exerciseApp.exerciseNumber}.${exerciseApp.stepNumber}.${exerciseApp.type}`,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tnextProgress.type === 'instructions' ||\n\t\t\t\t\t\t\tnextProgress.type === 'finished'\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`The user needs to mark the ${nextProgress.exerciseNumber} ${nextProgress.type === 'instructions' ? 'instructions' : 'finished'} as complete before they can continue. Have them watch the video at ${nextProgress.epicLessonUrl}, then mark it as complete.`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tnextProgress.type === 'workshop-instructions' ||\n\t\t\t\t\t\t\tnextProgress.type === 'workshop-finished'\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`The user needs to mark the ${nextProgress.exerciseNumber} ${nextProgress.type === 'workshop-instructions' ? 'Workshop instructions' : 'Workshop finished'} as complete before they can continue. Have them watch the video at ${nextProgress.epicLessonUrl}, then mark it as complete.`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`The user needs to mark ${nextProgress.epicLessonSlug} as complete before they can continue. Have them watch the video at ${nextProgress.epicLessonUrl}, then mark it as complete.`,\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst apps = await getApps()\n\t\t\tconst exerciseStepApps = apps.filter(isExerciseStepApp)\n\n\t\t\tconst playgroundAppName = await getPlaygroundAppName()\n\t\t\tconst currentExerciseStepAppIndex = exerciseStepApps.findIndex(\n\t\t\t\t(a) => a.name === playgroundAppName,\n\t\t\t)\n\n\t\t\tlet desiredApp: ExerciseStepApp | undefined\n\t\t\t// if nothing was provided, set to the next step problem app\n\t\t\tconst noArgumentsProvided = !exerciseNumber && !stepNumber && !type\n\t\t\tif (noArgumentsProvided) {\n\t\t\t\tdesiredApp = exerciseStepApps\n\t\t\t\t\t.slice(currentExerciseStepAppIndex + 1)\n\t\t\t\t\t.find(isProblemApp)\n\t\t\t\tinvariant(desiredApp, 'No next problem app found to set playground to')\n\t\t\t} else {\n\t\t\t\tconst currentExerciseStepApp =\n\t\t\t\t\texerciseStepApps[currentExerciseStepAppIndex]\n\n\t\t\t\t// otherwise, default to the current exercise step app for arguments\n\t\t\t\texerciseNumber ??= currentExerciseStepApp?.exerciseNumber\n\t\t\t\tstepNumber ??= currentExerciseStepApp?.stepNumber\n\t\t\t\ttype ??= currentExerciseStepApp?.type\n\n\t\t\t\tdesiredApp = exerciseStepApps.find(\n\t\t\t\t\t(a) =>\n\t\t\t\t\t\ta.exerciseNumber === exerciseNumber &&\n\t\t\t\t\t\ta.stepNumber === stepNumber &&\n\t\t\t\t\t\ta.type === type,\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tinvariant(\n\t\t\t\tdesiredApp,\n\t\t\t\t`No app found for values derived by the arguments: ${exerciseNumber}.${stepNumber}.${type}`,\n\t\t\t)\n\t\t\tawait setPlayground(desiredApp.fullPath)\n\t\t\treturn {\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\ttext: `Playground set to ${desiredApp.name}.`,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerTool(\n\t\t'update_progress',\n\t\t{\n\t\t\tdescription: `\nIntended to help you mark an Epic lesson as complete or incomplete.\n\nThis will mark the Epic lesson as complete or incomplete and update the user's progress (get updated progress with the \\`get_user_progress\\` tool, the \\`get_exercise_context\\` tool, or the \\`get_workshop_context\\` tool).\n\t\t`.trim(),\n\t\t\tinputSchema: {\n\t\t\t\tworkshopDirectory: workshopDirectoryInputSchema,\n\t\t\t\tepicLessonSlug: z\n\t\t\t\t\t.string()\n\t\t\t\t\t.describe(\n\t\t\t\t\t\t'The slug of the Epic lesson to mark as complete (can be retrieved from the `get_exercise_context` tool or the `get_workshop_context` tool)',\n\t\t\t\t\t),\n\t\t\t\tcomplete: z\n\t\t\t\t\t.boolean()\n\t\t\t\t\t.optional()\n\t\t\t\t\t.default(true)\n\t\t\t\t\t.describe(\n\t\t\t\t\t\t'Whether to mark the lesson as complete or incomplete (defaults to true)',\n\t\t\t\t\t),\n\t\t\t},\n\t\t},\n\t\tasync ({ workshopDirectory, epicLessonSlug, complete }) => {\n\t\t\tawait handleWorkshopDirectory(workshopDirectory)\n\t\t\tawait updateProgress({ lessonSlug: epicLessonSlug, complete })\n\t\t\treturn {\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\ttext: `Lesson with slug ${epicLessonSlug} marked as ${complete ? 'complete' : 'incomplete'}`,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t}\n\t\t},\n\t)\n\n\t// TODO: add a tool to run the dev/test script for the given app\n}\n\n// These are tools that retrieve resources. Not all resources should be\n// accessible via tools, but allowing the LLM to access them on demand is useful\n// for some situations.\nexport function initResourceTools(server: McpServer) {\n\tserver.registerTool(\n\t\t'get_workshop_context',\n\t\t{\n\t\t\tdescription: `\nIndended to help you get wholistic context of the topics covered in this\nworkshop. This doesn't go into as much detail per exercise as the\n\\`get_exercise_context\\` tool, but it is a good starting point to orient\nyourself on the workshop as a whole.\n\t\t`.trim(),\n\t\t\tinputSchema: workshopContextResource.inputSchema,\n\t\t},\n\t\tasync ({ workshopDirectory }) => {\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\tconst resource = await workshopContextResource.getResource({\n\t\t\t\tworkshopDirectory,\n\t\t\t})\n\t\t\treturn {\n\t\t\t\tcontent: [getEmbeddedResourceContent(resource)],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerTool(\n\t\t'get_exercise_context',\n\t\t{\n\t\t\tdescription: `\nIntended to help a student understand what they need to do for the current\nexercise step.\n\nThis returns the instructions MDX content for the current exercise and each\nexercise step. If the user is has the paid version of the workshop, it will also\ninclude the transcript from each of the videos as well.\n\nThe output for this will rarely change, so it's unnecessary to call this tool\nmore than once.\n\n\\`get_exercise_context\\` is often best when used with the\n\\`get_exercise_step_progress_diff\\` tool to help a student understand what\nwork they still need to do and answer any questions about the exercise.\n\t\t`.trim(),\n\t\t\tinputSchema: exerciseContextResource.inputSchema,\n\t\t},\n\t\tasync ({ workshopDirectory, exerciseNumber }) => {\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\tconst resource = await exerciseContextResource.getResource({\n\t\t\t\tworkshopDirectory,\n\t\t\t\texerciseNumber,\n\t\t\t})\n\t\t\treturn {\n\t\t\t\tcontent: [getEmbeddedResourceContent(resource)],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerTool(\n\t\t'get_diff_between_apps',\n\t\t{\n\t\t\tdescription: `\nIntended to give context about the changes between two apps.\n\nThe output is a git diff of the playground directory as BASE (their work in\nprogress) against the solution directory as HEAD (the final state they're trying\nto achieve).\n\nThe output is formatted as a git diff.\n\nApp IDs are formatted as \\`{exerciseNumber}.{stepNumber}.{type}\\`.\n\nIf the user asks for the diff for 2.3, then use 02.03.problem for app1 and 02.03.solution for app2.\n\t\t`,\n\t\t\tinputSchema: diffBetweenAppsResource.inputSchema,\n\t\t},\n\t\tasync ({ workshopDirectory, app1, app2 }) => {\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\tconst resource = await diffBetweenAppsResource.getResource({\n\t\t\t\tworkshopDirectory,\n\t\t\t\tapp1,\n\t\t\t\tapp2,\n\t\t\t})\n\t\t\treturn {\n\t\t\t\tcontent: [getEmbeddedResourceContent(resource)],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerTool(\n\t\t'get_exercise_step_progress_diff',\n\t\t{\n\t\t\tdescription: `\nIntended to help a student understand what work they still have to complete.\n\t\t`.trim(),\n\t\t\tinputSchema: exerciseStepProgressDiffResource.inputSchema,\n\t\t},\n\t\tasync ({ workshopDirectory }) => {\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\tconst resource = await exerciseStepProgressDiffResource.getResource({\n\t\t\t\tworkshopDirectory,\n\t\t\t})\n\t\t\treturn {\n\t\t\t\tcontent: [\n\t\t\t\t\tcreateText(getDiffInstructionText()),\n\t\t\t\t\tgetEmbeddedResourceContent(resource),\n\t\t\t\t],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerTool(\n\t\t'get_exercise_step_context',\n\t\t{\n\t\t\tdescription: `\nIntended to help a student understand what they need to do for a specific\nexercise step.\n\nThis returns the instructions MDX content for the specified exercise step's\nproblem and solution. If the user has the paid version of the workshop, it will also\ninclude the transcript from each of the videos as well.\n\nThe output for this will rarely change, so it's unnecessary to call this tool\nmore than once for the same exercise step.\n\n\\`get_exercise_step_context\\` is often best when used with the\n\\`get_exercise_step_progress_diff\\` tool to help a student understand what\nwork they still need to do and answer any questions about the exercise step.\n\t\t`.trim(),\n\t\t\tinputSchema: exerciseStepContextResource.inputSchema,\n\t\t},\n\t\tasync ({ workshopDirectory, exerciseNumber, stepNumber }) => {\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\tconst resource = await exerciseStepContextResource.getResource({\n\t\t\t\tworkshopDirectory,\n\t\t\t\texerciseNumber,\n\t\t\t\tstepNumber,\n\t\t\t})\n\t\t\treturn {\n\t\t\t\tcontent: [getEmbeddedResourceContent(resource)],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerTool(\n\t\t'view_video',\n\t\t{\n\t\t\tdescription: `\nIntended to help a student view a video.\n\nIf the user ever asks you to show them a video, use this tool to do so.\n\t\t`.trim(),\n\t\t\tinputSchema: {\n\t\t\t\tvideoUrl: z.string().describe(\n\t\t\t\t\t`\nThe URL of the video to view. If you don't know the URL to use already, you can get this from the \\`get_exercise_step_context\\` tool or the \\`get_exercise_context\\` tool depending on whether you're trying to show the exercise intro/outro video or a specific step's problem/solution video. If you use the \\`get_what_is_next\\` tool, this will be handled automatically.\n\t\t\t\t\t\t`.trim(),\n\t\t\t\t),\n\t\t\t},\n\t\t},\n\t\tasync ({ videoUrl }) => {\n\t\t\tconst url: URL = new URL('mcp-ui/epic-video', 'http://localhost:5639')\n\t\t\turl.searchParams.set('url', videoUrl)\n\t\t\treturn {\n\t\t\t\tcontent: [\n\t\t\t\t\tcreateUIResource({\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\ttype: 'externalUrl',\n\t\t\t\t\t\t\tiframeUrl: url.toString(),\n\t\t\t\t\t\t},\n\t\t\t\t\t\turi: `ui://epicshop/epic-video/${videoUrl.toString()}`,\n\t\t\t\t\t\tencoding: 'text',\n\t\t\t\t\t}),\n\t\t\t\t],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerTool(\n\t\t'open_exercise_step_files',\n\t\t{\n\t\t\ttitle: 'Open Exercise Step Files',\n\t\t\tdescription: `\nCall this to open the files for the exercise step the playground is currently set to.\n\t\t`.trim(),\n\t\t\tinputSchema: {\n\t\t\t\tworkshopDirectory: workshopDirectoryInputSchema,\n\t\t\t},\n\t\t},\n\t\tasync ({ workshopDirectory }) => {\n\t\t\tawait handleWorkshopDirectory(workshopDirectory)\n\t\t\tconst playgroundApp = await getPlaygroundApp()\n\t\t\tinvariant(\n\t\t\t\tplaygroundApp,\n\t\t\t\t'The playground app is not currently set. Use the `set_playground` tool to set the playground to an exercise step.',\n\t\t\t)\n\t\t\tconst problemApp = await getAppByName(playgroundApp.appName)\n\t\t\tinvariant(\n\t\t\t\tproblemApp,\n\t\t\t\t'Cannot find the problem app for the playground app. This is unexpected. The playground app may need to be reset using the `set_playground` tool.',\n\t\t\t)\n\t\t\tinvariant(\n\t\t\t\tisProblemApp(problemApp) && problemApp.solutionName,\n\t\t\t\t'The playground app is not set to a problem app with a solution. The playground app may need to be reset using the `set_playground` tool.',\n\t\t\t)\n\t\t\tconst solutionApp = await getAppByName(problemApp.solutionName)\n\t\t\tinvariant(\n\t\t\t\tsolutionApp,\n\t\t\t\t'Cannot find the solution app for the problem app. Cannot open the files for a step that does not have both a problem and solution.',\n\t\t\t)\n\t\t\tconst diffFiles = await getDiffFiles(problemApp, solutionApp)\n\t\t\tinvariant(\n\t\t\t\tdiffFiles,\n\t\t\t\t'There was a problem generating the diff. Check the terminal output.',\n\t\t\t)\n\t\t\tfor (const file of diffFiles) {\n\t\t\t\tconst fullPath = path.join(playgroundApp.fullPath, file.path)\n\t\t\t\tawait launchEditor(fullPath, file.line)\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\ttext: `Opened ${diffFiles.length} file${diffFiles.length === 1 ? '' : 's'}:\\n${diffFiles.map((file) => `${file.path}:${file.line}`).join('\\n')}`,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerTool(\n\t\t'get_user_info',\n\t\t{\n\t\t\tdescription: `\nIntended to help you get information about the current user.\n\nThis includes the user's name, email, etc. It's mostly useful to determine\nwhether the user is logged in and know who they are.\n\nIf the user is not logged in, tell them to log in by running the \\`login\\` tool.\n\t\t`.trim(),\n\t\t\tinputSchema: userInfoResource.inputSchema,\n\t\t},\n\t\tasync ({ workshopDirectory }) => {\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\tconst resource = await userInfoResource.getResource({ workshopDirectory })\n\t\t\treturn {\n\t\t\t\tcontent: [getEmbeddedResourceContent(resource)],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerTool(\n\t\t'get_user_access',\n\t\t{\n\t\t\tdescription: `\nWill tell you whether the user has access to the paid features of the workshop.\n\nPaid features include:\n- Transcripts\n- Progress tracking\n- Access to videos\n- Access to the discord chat\n- Test tab support\n- Diff tab support\n\nEncourage the user to upgrade if they need access to the paid features.\n\t\t`.trim(),\n\t\t\tinputSchema: userAccessResource.inputSchema,\n\t\t},\n\t\tasync ({ workshopDirectory }) => {\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\tconst resource = await userAccessResource.getResource({\n\t\t\t\tworkshopDirectory,\n\t\t\t})\n\t\t\treturn {\n\t\t\t\tcontent: [getEmbeddedResourceContent(resource)],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerTool(\n\t\t'get_user_progress',\n\t\t{\n\t\t\tdescription: `\nIntended to help you get the progress of the current user. Can often be helpful\nto know what the next step that needs to be completed is. Make sure to provide\nthe user with the URL of relevant incomplete lessons so they can watch them and\nthen mark them as complete.\n\t\t`.trim(),\n\t\t\tinputSchema: userProgressResource.inputSchema,\n\t\t},\n\t\tasync ({ workshopDirectory }) => {\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\tconst resource = await userProgressResource.getResource({\n\t\t\t\tworkshopDirectory,\n\t\t\t})\n\t\t\treturn {\n\t\t\t\tcontent: [getEmbeddedResourceContent(resource)],\n\t\t\t}\n\t\t},\n\t)\n}\n\n// Sometimes the user will ask the LLM to select a prompt to use so they don't have to.\nexport function initPromptTools(server: McpServer) {\n\tserver.registerTool(\n\t\t'get_quiz_instructions',\n\t\t{\n\t\t\tdescription: `\nIf the user asks you to quiz them on a topic from the workshop, use this tool to\nretrieve the instructions for how to do so.\n\n- If the user asks for a specific exercise, supply that exercise number.\n- If they ask for a specific exericse, supply that exercise number.\n- If they ask for a topic and you don't know which exercise that topic is in, use \\`get_workshop_context\\` to get the list of exercises and their topics and then supply the appropriate exercise number.\n\t\t`.trim(),\n\t\t\tinputSchema: quizMeInputSchema,\n\t\t},\n\t\tasync ({ workshopDirectory, exerciseNumber }) => {\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\tconst result = await quizMe({ workshopDirectory, exerciseNumber })\n\t\t\treturn {\n\t\t\t\t// QUESTION: will a prompt ever return messages that have role: 'assistant'?\n\t\t\t\t// if so, this may be a little confusing for the LLM, but I can't think of a\n\t\t\t\t// good use case for that so 🤷♂️\n\t\t\t\tcontent: result.messages.map((m) => {\n\t\t\t\t\tif (m.content.type === 'resource') {\n\t\t\t\t\t\treturn getEmbeddedResourceContent(m.content.resource)\n\t\t\t\t\t}\n\t\t\t\t\treturn m.content\n\t\t\t\t}),\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerTool(\n\t\t'get_what_is_next',\n\t\t{\n\t\t\ttitle: 'Get What Is Next',\n\t\t\tdescription: `\nIntended to help you get the next step that the user needs to complete.\n\nThis is often useful to know what the user should do next to continue their learning.\n\nThis could be that they need to login, watch a video, complete an exercise, etc.\n\t\t\t`.trim(),\n\t\t\tinputSchema: {\n\t\t\t\tworkshopDirectory: workshopDirectoryInputSchema,\n\t\t\t},\n\t\t},\n\t\tasync ({ workshopDirectory }) => {\n\t\t\tawait handleWorkshopDirectory(workshopDirectory)\n\n\t\t\tconst authInfo = await getAuthInfo()\n\t\t\tif (!authInfo) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\t\ttext: 'The user is not logged in. Use the `login` tool to login the user.',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst progress = await getProgress()\n\n\t\t\tconst scoreProgress = (a: (typeof progress)[number]) => {\n\t\t\t\tif (a.type === 'workshop-instructions') return 0\n\t\t\t\tif (a.type === 'workshop-finished') return 10000\n\t\t\t\tif (a.type === 'instructions') return a.exerciseNumber * 100\n\t\t\t\tif (a.type === 'step') return a.exerciseNumber * 100 + a.stepNumber\n\t\t\t\tif (a.type === 'finished') return a.exerciseNumber * 100 + 100\n\n\t\t\t\tif (a.type === 'unknown') return 100000\n\t\t\t\treturn -1\n\t\t\t}\n\t\t\tconst sortedProgress = progress.sort((a, b) => {\n\t\t\t\treturn scoreProgress(a) - scoreProgress(b)\n\t\t\t})\n\t\t\tconst nextProgress = sortedProgress.find((p) => !p.epicCompletedAt)\n\t\t\tif (!nextProgress) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\t\ttext: `The user has completed the workshop. Congratulate them and invite them to ask you to quiz them on their understanding of the material. A summary of the material is below:`,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcreateText(await createWorkshopSummary()),\n\t\t\t\t\t],\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tinvariant(\n\t\t\t\tnextProgress.type !== 'unknown',\n\t\t\t\t`Next progress type is unknown. This is unexpected. Sorry, we don't know what to do here. Here's a summary of the workshop:\\n\\n${await createWorkshopSummary()}`,\n\t\t\t)\n\n\t\t\tif (nextProgress.type === 'workshop-instructions') {\n\t\t\t\tconst embedUrl = new URL('mcp-ui/epic-video', 'http://localhost:5639')\n\t\t\t\tembedUrl.searchParams.set('url', nextProgress.epicLessonUrl)\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\tcreateText(\n\t\t\t\t\t\t\t`The user has just begun! They need to watch the workshop instructions video and read the instructions to get started. When they say they're done or ready for what's next, mark it as complete using the \\`update_progress\\` tool with the slug \"${nextProgress.epicLessonSlug}\" and then call \\`get_what_is_next\\` again to get the next step. Relevant info is below:`,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tcreateText(await createWorkshopSummary()),\n\t\t\t\t\t\tcreateText(\n\t\t\t\t\t\t\t`Instructions:\\n${await readInWorkshop('exercises', 'README.mdx')}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tcreateUIResource({\n\t\t\t\t\t\t\turi: `ui://epicshop/epic-video/${nextProgress.epicLessonUrl}`,\n\t\t\t\t\t\t\tencoding: 'text',\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\ttype: 'externalUrl',\n\t\t\t\t\t\t\t\tiframeUrl: embedUrl.toString(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t],\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (nextProgress.type === 'workshop-finished') {\n\t\t\t\tconst embedUrl = new URL('mcp-ui/epic-video', 'http://localhost:5639')\n\t\t\t\tembedUrl.searchParams.set('url', nextProgress.epicLessonUrl)\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\tcreateText(\n\t\t\t\t\t\t\t`The user has almost completed the workshop. They just need to watch the workshop finished video and read the finished instructions to get started. When they say they're done or ready for what's next, mark it as complete using the \\`update_progress\\` tool with the slug \"${nextProgress.epicLessonSlug}\" and then call \\`get_what_is_next\\` again to get the next step. Relevant info is below:`,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tcreateText(\n\t\t\t\t\t\t\t`Finished instructions:\\n${await readInWorkshop('exercises', 'FINISHED.mdx')}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tcreateUIResource({\n\t\t\t\t\t\t\turi: `ui://epicshop/epic-video/${nextProgress.epicLessonUrl}`,\n\t\t\t\t\t\t\tencoding: 'text',\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\ttype: 'externalUrl',\n\t\t\t\t\t\t\t\tiframeUrl: embedUrl.toString(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t],\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst ex = nextProgress.exerciseNumber.toString().padStart(2, '0')\n\t\t\tif (nextProgress.type === 'instructions') {\n\t\t\t\tconst embedUrl = new URL('mcp-ui/epic-video', 'http://localhost:5639')\n\t\t\t\tembedUrl.searchParams.set('url', nextProgress.epicLessonUrl)\n\t\t\t\tconst exercise = await getExercise(nextProgress.exerciseNumber)\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\tcreateText(\n\t\t\t\t\t\t\t`The user needs to complete the intro for exercise ${ex}. When they say they're done or ready for what's next, mark it as complete using the \\`update_progress\\` tool with the slug \"${nextProgress.epicLessonSlug}\" and then call \\`get_what_is_next\\` again to get the next step. Relevant info is below:`,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tcreateText(\n\t\t\t\t\t\t\t`Exercise instructions:\\n${await readReadme(exercise?.fullPath)}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tcreateUIResource({\n\t\t\t\t\t\t\turi: `ui://epicshop/epic-video/${nextProgress.epicLessonUrl}`,\n\t\t\t\t\t\t\tencoding: 'text',\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\ttype: 'externalUrl',\n\t\t\t\t\t\t\t\tiframeUrl: embedUrl.toString(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t],\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (nextProgress.type === 'finished') {\n\t\t\t\tconst embedUrl = new URL('mcp-ui/epic-video', 'http://localhost:5639')\n\t\t\t\tembedUrl.searchParams.set('url', nextProgress.epicLessonUrl)\n\t\t\t\tconst exercise = await getExercise(nextProgress.exerciseNumber)\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\tcreateText(\n\t\t\t\t\t\t\t`The user is almost finished with exercise ${ex}. They need to complete the outro for exercise ${ex}. Relevant info is below:`,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tcreateText(\n\t\t\t\t\t\t\t`Exercise finished instructions:\\n${await readReadme(exercise?.fullPath)}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tcreateUIResource({\n\t\t\t\t\t\t\turi: `ui://epicshop/epic-video/${nextProgress.epicLessonUrl}`,\n\t\t\t\t\t\t\tencoding: 'text',\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\ttype: 'externalUrl',\n\t\t\t\t\t\t\t\tiframeUrl: embedUrl.toString(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t],\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst st = nextProgress.stepNumber.toString().padStart(2, '0')\n\t\t\tif (nextProgress.type === 'step') {\n\t\t\t\tconst exercise = await getExercise(nextProgress.exerciseNumber)\n\t\t\t\tconst problemEmbedUrl = new URL(\n\t\t\t\t\t'mcp-ui/epic-video',\n\t\t\t\t\t'http://localhost:5639',\n\t\t\t\t)\n\t\t\t\tproblemEmbedUrl.searchParams.set('url', nextProgress.epicLessonUrl)\n\t\t\t\tconst solutionEmbedUrl = new URL(\n\t\t\t\t\t'mcp-ui/epic-video',\n\t\t\t\t\t'http://localhost:5639',\n\t\t\t\t)\n\t\t\t\tsolutionEmbedUrl.searchParams.set(\n\t\t\t\t\t'url',\n\t\t\t\t\t`${nextProgress.epicLessonUrl}/solution`,\n\t\t\t\t)\n\t\t\t\tconst step = exercise?.steps.find(\n\t\t\t\t\t(s) => s.stepNumber === nextProgress.stepNumber,\n\t\t\t\t)\n\t\t\t\tinvariant(\n\t\t\t\t\tstep,\n\t\t\t\t\t`No step found for exercise ${nextProgress.exerciseNumber} step ${nextProgress.stepNumber}`,\n\t\t\t\t)\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\tcreateText(\n\t\t\t\t\t\t\t`\nThe user is on step ${st} of exercise ${ex}. To complete this step they need to:\n1. Watch the problem video\n2. Review the problem instructions (you can summarize these from the info below)\n3. Set the playground to the problem app (you can help them using the \\`set_playground\\` tool)\n4. Open the relevant files in their playground environment (you can help them using the \\`open_exercise_step_files\\` tool)\n5. Run the tests and dev server to validate their work (no tools for this are available yet, but you can use the \\`get_exercise_step_progress_diff\\` tool to help them understand what work they still need to do as they go)\n6. Watch the solution video\n7. Review the solution instructions (you can summarize these from the info below)\n8. Mark the step as complete (you can help them using the \\`update_progress\\` tool with the slug \"${nextProgress.epicLessonSlug}\")\n\nThen you can call \\`get_what_is_next\\` again to get the next step.\n\t\t\t\t\t\t\t`.trim(),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tcreateText(\n\t\t\t\t\t\t\t`Exercise step problem instructions:\\n${await readReadme(step.problem?.fullPath)}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tcreateText(\n\t\t\t\t\t\t\t`Exercise step solution instructions:\\n${await readReadme(step.solution?.fullPath)}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tcreateUIResource({\n\t\t\t\t\t\t\turi: `ui://epicshop/epic-video/${nextProgress.epicLessonUrl}`,\n\t\t\t\t\t\t\tencoding: 'text',\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\ttype: 'externalUrl',\n\t\t\t\t\t\t\t\tiframeUrl: problemEmbedUrl.toString(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tcreateUIResource({\n\t\t\t\t\t\t\turi: `ui://epicshop/epic-video/${nextProgress.epicLessonUrl}/solution`,\n\t\t\t\t\t\t\tencoding: 'text',\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\ttype: 'externalUrl',\n\t\t\t\t\t\t\t\tiframeUrl: solutionEmbedUrl.toString(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t],\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new Error(\n\t\t\t\t`This is unexpected, but I do not know what the next step for the user is. Sorry!`,\n\t\t\t)\n\t\t},\n\t)\n}\n\nfunction getEmbeddedResourceContent(\n\tresource: ReadResourceResult['contents'][number],\n) {\n\tif (clientSupportsEmbeddedResources) {\n\t\treturn {\n\t\t\ttype: 'resource' as const,\n\t\t\tresource,\n\t\t}\n\t} else if (typeof resource.text === 'string') {\n\t\treturn {\n\t\t\ttype: 'text' as const,\n\t\t\ttext: resource.text,\n\t\t}\n\t} else {\n\t\tthrow new Error(\n\t\t\t`Unknown resource type: ${resource.type} for ${resource.uri}`,\n\t\t)\n\t}\n}\n\nfunction createText(text: unknown): CallToolResult['content'][number] {\n\tif (typeof text === 'string') {\n\t\treturn { type: 'text', text }\n\t} else {\n\t\treturn { type: 'text', text: JSON.stringify(text) }\n\t}\n}\n\nasync function createWorkshopSummary() {\n\tconst config = getWorkshopConfig()\n\tconst exercises = await getExercises()\n\tlet summary = `# ${config.title}\n\n${config.subtitle}\n\n## Exercises\n`\n\tfor (const exercise of exercises) {\n\t\tsummary += `\n${exercise.exerciseNumber.toString().padStart(2, '0')}. ${exercise.title}\n${exercise.steps.map((s) => ` ${s.stepNumber.toString().padStart(2, '0')}. ${s.problem?.title ?? s.solution?.title ?? 'No title'}`).join('\\n')}`\n\t}\n\treturn summary\n}\n\nasync function readReadme(dirPath?: string) {\n\treturn (\n\t\t(dirPath ? await safeReadFile(path.join(dirPath, 'README.mdx')) : null) ??\n\t\t'No instructions'\n\t)\n}\n\nfunction getDiffInstructionText() {\n\treturn `\nBelow is the diff between the user's work in progress and the solution.\nLines starting with \\`-\\` show code that needs to be removed from the user's solution.\nLines starting with \\`+\\` show code that needs to be added to the user's solution.\n\nIf there are significant differences, the user's work is incomplete.\n\nHere's an example of the output you can expect:\n\n--------\n\ndiff --git ./example.ts ./example.ts\nindex e05035d..a70eb4b 100644\n--- ./example.ts\n+++ ./example.ts\n@@ -236,14 +236,27 @@ export async function sayHello(name?: string) {\n+\tif (name) {\n+\t\treturn \\`Hello, \\${name}!\\`\n+\t}\n-\tawait new Promise((resolve) => setTimeout(resolve, 1000))\n \treturn 'Hello, World!'\n }\n\n--------\n\nIn this example, you should tell the user they still need to:\n- add the if statement to return the name if it's provided\n- remove the await promise that resolves after 1 second\n\nFor additional context, you can use the \\`get_exercise_instructions\\` tool\nto get the instructions for the current exercise step to help explain the\nsignificance of changes.\n\t`.trim()\n}\n"]}
|
package/dist/esm/utils.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,4BAA4B,aAIvC,CAAA;AAyBF,wBAAsB,uBAAuB,CAAC,iBAAiB,EAAE,MAAM,mBAuBtE;AAED,eAAO,MAAM,UAAU,GAAI,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,WACX,CAAA;AACnC,eAAO,MAAM,cAAc,GAAI,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,2BACnB,CAAA;AAE/B,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,0BAMlD;AAED,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS;IAAE,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,CAAA;CAAE,IAAI;KAClE,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAC7B,CAAA"}
|
package/dist/esm/utils.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport {\n\tgetWorkshopRoot,\n\tinit as initApps,\n} from '@epic-web/workshop-utils/apps.server'\nimport { z } from 'zod'\n\nexport const workshopDirectoryInputSchema = z\n\t.string()\n\t.describe(\n\t\t'The workshop directory (the root directory of the workshop repo). This should be an absolute path.',\n\t)\n\nasync function isWorkshopDirectory(workshopDirectory: string) {\n\tconsole.error('isWorkshopDirectory', workshopDirectory)\n\tconst packageJson = await safeReadFile(\n\t\tpath.join(workshopDirectory, 'package.json'),\n\t)\n\tif (!packageJson) return false\n\n\tlet pkgJson: any\n\ttry {\n\t\tpkgJson = JSON.parse(packageJson)\n\t} catch (error) {\n\t\tif (error instanceof SyntaxError) {\n\t\t\tthrow new Error(\n\t\t\t\t`Syntax error in package.json in \"${workshopDirectory}\": ${error.message}`,\n\t\t\t)\n\t\t}\n\t\tthrow error\n\t}\n\tconsole.error('isWorkshopDirectory', Boolean(pkgJson.epicshop))\n\n\treturn Boolean(pkgJson.epicshop)\n}\n\nexport async function handleWorkshopDirectory(workshopDirectory: string) {\n\tworkshopDirectory = workshopDirectory.trim()\n\n\tif (!workshopDirectory) throw new Error('The workshop directory is required')\n\n\tif (!path.isAbsolute(workshopDirectory)) {\n\t\tthrow new Error('The workshop directory must be an absolute path')\n\t}\n\n\tif (workshopDirectory.endsWith(`${path.sep}playground`)) {\n\t\tworkshopDirectory = path.join(workshopDirectory, '..')\n\t}\n\n\twhile (true) {\n\t\tif (await isWorkshopDirectory(workshopDirectory)) break\n\t\tif (workshopDirectory === path.dirname(workshopDirectory)) {\n\t\t\tthrow new Error(`No workshop directory found in \"${workshopDirectory}\"`)\n\t\t}\n\t\tworkshopDirectory = path.dirname(workshopDirectory)\n\t}\n\n\tawait initApps(workshopDirectory)\n\treturn workshopDirectory\n}\n\nexport const inWorkshop = (...d: Array<string>) =>\n\tpath.join(getWorkshopRoot(), ...d)\nexport const readInWorkshop = (...d: Array<string>) =>\n\tsafeReadFile(inWorkshop(...d))\n\nexport async function safeReadFile(filePath: string) {\n\ttry {\n\t\treturn await fs.readFile(filePath, 'utf-8')\n\t} catch {\n\t\treturn null\n\t}\n}\n\nexport type InputSchemaType<T extends { [K: string]: z.ZodType }> = {\n\t[K in keyof T]: z.infer<T[K]>\n}\n"]}
|
package/dist/esm/utils.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.test.d.ts","sourceRoot":"","sources":["../../src/utils.test.ts"],"names":[],"mappings":""}
|
package/dist/esm/utils.test.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { test, expect } from 'vitest';
|
|
2
|
-
import { workshopDirectoryInputSchema } from './utils.js';
|
|
3
|
-
test('workshopDirectoryInputSchema should validate valid string', () => {
|
|
4
|
-
const validInput = '/path/to/workshop';
|
|
5
|
-
const result = workshopDirectoryInputSchema.safeParse(validInput);
|
|
6
|
-
expect(result.success).toBe(true);
|
|
7
|
-
if (result.success) {
|
|
8
|
-
expect(result.data).toBe(validInput);
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
test('workshopDirectoryInputSchema should reject non-string input', () => {
|
|
12
|
-
const invalidInputs = [123, true, null, undefined, {}];
|
|
13
|
-
invalidInputs.forEach((input) => {
|
|
14
|
-
const result = workshopDirectoryInputSchema.safeParse(input);
|
|
15
|
-
expect(result.success).toBe(false);
|
|
16
|
-
});
|
|
17
|
-
});
|
|
18
|
-
test('workshopDirectoryInputSchema should accept empty string', () => {
|
|
19
|
-
const emptyString = '';
|
|
20
|
-
const result = workshopDirectoryInputSchema.safeParse(emptyString);
|
|
21
|
-
expect(result.success).toBe(true);
|
|
22
|
-
if (result.success) {
|
|
23
|
-
expect(result.data).toBe(emptyString);
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
test('workshopDirectoryInputSchema should accept string with spaces', () => {
|
|
27
|
-
const inputWithSpaces = ' /path/with/spaces ';
|
|
28
|
-
const result = workshopDirectoryInputSchema.safeParse(inputWithSpaces);
|
|
29
|
-
expect(result.success).toBe(true);
|
|
30
|
-
if (result.success) {
|
|
31
|
-
expect(result.data).toBe(inputWithSpaces);
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
test('workshopDirectoryInputSchema should accept absolute paths', () => {
|
|
35
|
-
const absolutePaths = [
|
|
36
|
-
'/Users/username/projects/workshop',
|
|
37
|
-
'C:\\Users\\username\\projects\\workshop',
|
|
38
|
-
'/home/user/workshop',
|
|
39
|
-
];
|
|
40
|
-
absolutePaths.forEach((path) => {
|
|
41
|
-
const result = workshopDirectoryInputSchema.safeParse(path);
|
|
42
|
-
expect(result.success).toBe(true);
|
|
43
|
-
if (result.success) {
|
|
44
|
-
expect(result.data).toBe(path);
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
test('workshopDirectoryInputSchema should accept relative paths', () => {
|
|
49
|
-
const relativePaths = [
|
|
50
|
-
'./workshop',
|
|
51
|
-
'../workshop',
|
|
52
|
-
'../../workshop',
|
|
53
|
-
'workshop',
|
|
54
|
-
];
|
|
55
|
-
relativePaths.forEach((path) => {
|
|
56
|
-
const result = workshopDirectoryInputSchema.safeParse(path);
|
|
57
|
-
expect(result.success).toBe(true);
|
|
58
|
-
if (result.success) {
|
|
59
|
-
expect(result.data).toBe(path);
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
//# sourceMappingURL=utils.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../src/utils.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { test, expect } from 'vitest'\nimport { workshopDirectoryInputSchema } from './utils.js'\n\ntest('workshopDirectoryInputSchema should validate valid string', () => {\n\tconst validInput = '/path/to/workshop'\n\tconst result = workshopDirectoryInputSchema.safeParse(validInput)\n\n\texpect(result.success).toBe(true)\n\tif (result.success) {\n\t\texpect(result.data).toBe(validInput)\n\t}\n})\n\ntest('workshopDirectoryInputSchema should reject non-string input', () => {\n\tconst invalidInputs = [123, true, null, undefined, {}]\n\n\tinvalidInputs.forEach((input) => {\n\t\tconst result = workshopDirectoryInputSchema.safeParse(input)\n\t\texpect(result.success).toBe(false)\n\t})\n})\n\ntest('workshopDirectoryInputSchema should accept empty string', () => {\n\tconst emptyString = ''\n\tconst result = workshopDirectoryInputSchema.safeParse(emptyString)\n\n\texpect(result.success).toBe(true)\n\tif (result.success) {\n\t\texpect(result.data).toBe(emptyString)\n\t}\n})\n\ntest('workshopDirectoryInputSchema should accept string with spaces', () => {\n\tconst inputWithSpaces = ' /path/with/spaces '\n\tconst result = workshopDirectoryInputSchema.safeParse(inputWithSpaces)\n\n\texpect(result.success).toBe(true)\n\tif (result.success) {\n\t\texpect(result.data).toBe(inputWithSpaces)\n\t}\n})\n\ntest('workshopDirectoryInputSchema should accept absolute paths', () => {\n\tconst absolutePaths = [\n\t\t'/Users/username/projects/workshop',\n\t\t'C:\\\\Users\\\\username\\\\projects\\\\workshop',\n\t\t'/home/user/workshop',\n\t]\n\n\tabsolutePaths.forEach((path) => {\n\t\tconst result = workshopDirectoryInputSchema.safeParse(path)\n\t\texpect(result.success).toBe(true)\n\t\tif (result.success) {\n\t\t\texpect(result.data).toBe(path)\n\t\t}\n\t})\n})\n\ntest('workshopDirectoryInputSchema should accept relative paths', () => {\n\tconst relativePaths = [\n\t\t'./workshop',\n\t\t'../workshop',\n\t\t'../../workshop',\n\t\t'workshop',\n\t]\n\n\trelativePaths.forEach((path) => {\n\t\tconst result = workshopDirectoryInputSchema.safeParse(path)\n\t\texpect(result.success).toBe(true)\n\t\tif (result.success) {\n\t\t\texpect(result.data).toBe(path)\n\t\t}\n\t})\n})\n"]}
|