@codebakers/cli 1.4.0 ā 1.4.2
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/commands/scaffold.js +306 -8
- package/dist/commands/serve.js +6 -3
- package/dist/commands/setup.js +6 -3
- package/dist/config.d.ts +3 -0
- package/dist/config.js +9 -0
- package/dist/index.js +43 -2
- package/dist/mcp/server.js +380 -0
- package/package.json +1 -1
- package/src/commands/scaffold.ts +330 -9
- package/src/commands/serve.ts +6 -3
- package/src/commands/setup.ts +6 -3
- package/src/config.ts +12 -0
- package/src/index.ts +45 -2
- package/src/mcp/server.ts +429 -1
package/dist/mcp/server.js
CHANGED
|
@@ -41,6 +41,8 @@ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
|
41
41
|
const config_js_1 = require("../config.js");
|
|
42
42
|
const fs = __importStar(require("fs"));
|
|
43
43
|
const path = __importStar(require("path"));
|
|
44
|
+
const child_process_1 = require("child_process");
|
|
45
|
+
const templates = __importStar(require("../templates/nextjs-supabase.js"));
|
|
44
46
|
// Pattern cache to avoid repeated API calls
|
|
45
47
|
const patternCache = new Map();
|
|
46
48
|
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
|
|
@@ -357,6 +359,60 @@ class CodeBakersServer {
|
|
|
357
359
|
required: ['pattern', 'section'],
|
|
358
360
|
},
|
|
359
361
|
},
|
|
362
|
+
{
|
|
363
|
+
name: 'scaffold_project',
|
|
364
|
+
description: 'Create a new project from scratch with Next.js + Supabase + Drizzle. Use this when user wants to build something new and no project exists yet. Creates all files, installs dependencies, and sets up CodeBakers patterns automatically.',
|
|
365
|
+
inputSchema: {
|
|
366
|
+
type: 'object',
|
|
367
|
+
properties: {
|
|
368
|
+
projectName: {
|
|
369
|
+
type: 'string',
|
|
370
|
+
description: 'Name of the project (lowercase, no spaces)',
|
|
371
|
+
},
|
|
372
|
+
description: {
|
|
373
|
+
type: 'string',
|
|
374
|
+
description: 'Brief description of what the project is for (used in PRD.md)',
|
|
375
|
+
},
|
|
376
|
+
},
|
|
377
|
+
required: ['projectName'],
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
name: 'init_project',
|
|
382
|
+
description: 'Add CodeBakers patterns to an existing project. Use this when user has an existing codebase and wants to add AI patterns to it.',
|
|
383
|
+
inputSchema: {
|
|
384
|
+
type: 'object',
|
|
385
|
+
properties: {
|
|
386
|
+
projectName: {
|
|
387
|
+
type: 'string',
|
|
388
|
+
description: 'Name of the project (optional, will be auto-detected from package.json)',
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
},
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
name: 'set_experience_level',
|
|
395
|
+
description: 'Set the user experience level. This affects how detailed explanations are when building features. Use "beginner" for new developers who need more explanations, "intermediate" for developers who know the basics, or "advanced" for experienced developers who want minimal explanations.',
|
|
396
|
+
inputSchema: {
|
|
397
|
+
type: 'object',
|
|
398
|
+
properties: {
|
|
399
|
+
level: {
|
|
400
|
+
type: 'string',
|
|
401
|
+
enum: ['beginner', 'intermediate', 'advanced'],
|
|
402
|
+
description: 'Experience level: beginner (detailed explanations), intermediate (balanced), advanced (minimal explanations)',
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
required: ['level'],
|
|
406
|
+
},
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
name: 'get_experience_level',
|
|
410
|
+
description: 'Get the current user experience level setting. Returns beginner, intermediate, or advanced. Use this at the start of building to know how much detail to include in explanations.',
|
|
411
|
+
inputSchema: {
|
|
412
|
+
type: 'object',
|
|
413
|
+
properties: {},
|
|
414
|
+
},
|
|
415
|
+
},
|
|
360
416
|
],
|
|
361
417
|
}));
|
|
362
418
|
// Handle tool calls
|
|
@@ -378,6 +434,14 @@ class CodeBakersServer {
|
|
|
378
434
|
return this.handleSearchPatterns(args);
|
|
379
435
|
case 'get_pattern_section':
|
|
380
436
|
return this.handleGetPatternSection(args);
|
|
437
|
+
case 'scaffold_project':
|
|
438
|
+
return this.handleScaffoldProject(args);
|
|
439
|
+
case 'init_project':
|
|
440
|
+
return this.handleInitProject(args);
|
|
441
|
+
case 'set_experience_level':
|
|
442
|
+
return this.handleSetExperienceLevel(args);
|
|
443
|
+
case 'get_experience_level':
|
|
444
|
+
return this.handleGetExperienceLevel();
|
|
381
445
|
default:
|
|
382
446
|
throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
383
447
|
}
|
|
@@ -733,6 +797,322 @@ Show the user what their simple request was expanded into, then proceed with the
|
|
|
733
797
|
],
|
|
734
798
|
};
|
|
735
799
|
}
|
|
800
|
+
async handleScaffoldProject(args) {
|
|
801
|
+
const { projectName, description } = args;
|
|
802
|
+
const cwd = process.cwd();
|
|
803
|
+
// Check if directory has files
|
|
804
|
+
const files = fs.readdirSync(cwd);
|
|
805
|
+
const hasFiles = files.filter(f => !f.startsWith('.')).length > 0;
|
|
806
|
+
if (hasFiles) {
|
|
807
|
+
// Check if it's already a CodeBakers project
|
|
808
|
+
if (fs.existsSync(path.join(cwd, 'CLAUDE.md'))) {
|
|
809
|
+
return {
|
|
810
|
+
content: [{
|
|
811
|
+
type: 'text',
|
|
812
|
+
text: `# Project Already Exists\n\nThis directory already has a CodeBakers project. Use the existing project or navigate to an empty directory.`,
|
|
813
|
+
}],
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
const results = [];
|
|
818
|
+
results.push(`# š Creating Project: ${projectName}\n`);
|
|
819
|
+
try {
|
|
820
|
+
// Create directories
|
|
821
|
+
const dirs = [
|
|
822
|
+
'src/app',
|
|
823
|
+
'src/components',
|
|
824
|
+
'src/lib/supabase',
|
|
825
|
+
'src/db',
|
|
826
|
+
'src/db/migrations',
|
|
827
|
+
'src/services',
|
|
828
|
+
'src/types',
|
|
829
|
+
'public',
|
|
830
|
+
];
|
|
831
|
+
for (const dir of dirs) {
|
|
832
|
+
const dirPath = path.join(cwd, dir);
|
|
833
|
+
if (!fs.existsSync(dirPath)) {
|
|
834
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
results.push('ā Created directory structure');
|
|
838
|
+
// Write package.json
|
|
839
|
+
const packageJson = { ...templates.PACKAGE_JSON, name: projectName };
|
|
840
|
+
fs.writeFileSync(path.join(cwd, 'package.json'), JSON.stringify(packageJson, null, 2));
|
|
841
|
+
results.push('ā Created package.json');
|
|
842
|
+
// Write config files
|
|
843
|
+
fs.writeFileSync(path.join(cwd, '.env.example'), templates.ENV_EXAMPLE);
|
|
844
|
+
fs.writeFileSync(path.join(cwd, '.env.local'), templates.ENV_EXAMPLE);
|
|
845
|
+
fs.writeFileSync(path.join(cwd, 'drizzle.config.ts'), templates.DRIZZLE_CONFIG);
|
|
846
|
+
fs.writeFileSync(path.join(cwd, 'tailwind.config.ts'), templates.TAILWIND_CONFIG);
|
|
847
|
+
fs.writeFileSync(path.join(cwd, 'postcss.config.mjs'), templates.POSTCSS_CONFIG);
|
|
848
|
+
fs.writeFileSync(path.join(cwd, 'tsconfig.json'), JSON.stringify(templates.TSCONFIG, null, 2));
|
|
849
|
+
fs.writeFileSync(path.join(cwd, 'next.config.ts'), templates.NEXT_CONFIG);
|
|
850
|
+
fs.writeFileSync(path.join(cwd, '.gitignore'), templates.GITIGNORE);
|
|
851
|
+
results.push('ā Created configuration files');
|
|
852
|
+
// Write source files
|
|
853
|
+
fs.writeFileSync(path.join(cwd, 'src/lib/supabase/server.ts'), templates.SUPABASE_SERVER);
|
|
854
|
+
fs.writeFileSync(path.join(cwd, 'src/lib/supabase/client.ts'), templates.SUPABASE_CLIENT);
|
|
855
|
+
fs.writeFileSync(path.join(cwd, 'src/lib/supabase/middleware.ts'), templates.SUPABASE_MIDDLEWARE);
|
|
856
|
+
fs.writeFileSync(path.join(cwd, 'middleware.ts'), templates.MIDDLEWARE);
|
|
857
|
+
fs.writeFileSync(path.join(cwd, 'src/db/schema.ts'), templates.DB_SCHEMA);
|
|
858
|
+
fs.writeFileSync(path.join(cwd, 'src/db/index.ts'), templates.DB_INDEX);
|
|
859
|
+
fs.writeFileSync(path.join(cwd, 'src/app/globals.css'), templates.GLOBALS_CSS);
|
|
860
|
+
fs.writeFileSync(path.join(cwd, 'src/app/layout.tsx'), templates.LAYOUT_TSX);
|
|
861
|
+
fs.writeFileSync(path.join(cwd, 'src/app/page.tsx'), templates.PAGE_TSX);
|
|
862
|
+
fs.writeFileSync(path.join(cwd, 'src/lib/utils.ts'), templates.UTILS_CN);
|
|
863
|
+
results.push('ā Created source files');
|
|
864
|
+
// Install dependencies
|
|
865
|
+
try {
|
|
866
|
+
(0, child_process_1.execSync)('npm install', { cwd, stdio: 'pipe' });
|
|
867
|
+
results.push('ā Installed npm dependencies');
|
|
868
|
+
}
|
|
869
|
+
catch {
|
|
870
|
+
results.push('ā ļø Could not install dependencies - run `npm install` manually');
|
|
871
|
+
}
|
|
872
|
+
// Now install CodeBakers patterns
|
|
873
|
+
results.push('\n## Installing CodeBakers Patterns...\n');
|
|
874
|
+
const response = await fetch(`${this.apiUrl}/api/content`, {
|
|
875
|
+
method: 'GET',
|
|
876
|
+
headers: { Authorization: `Bearer ${this.apiKey}` },
|
|
877
|
+
});
|
|
878
|
+
if (response.ok) {
|
|
879
|
+
const content = await response.json();
|
|
880
|
+
// Write CLAUDE.md
|
|
881
|
+
if (content.router) {
|
|
882
|
+
fs.writeFileSync(path.join(cwd, 'CLAUDE.md'), content.router);
|
|
883
|
+
results.push('ā Created CLAUDE.md (AI router)');
|
|
884
|
+
}
|
|
885
|
+
// Write pattern modules
|
|
886
|
+
if (content.modules && Object.keys(content.modules).length > 0) {
|
|
887
|
+
const modulesDir = path.join(cwd, '.claude');
|
|
888
|
+
if (!fs.existsSync(modulesDir)) {
|
|
889
|
+
fs.mkdirSync(modulesDir, { recursive: true });
|
|
890
|
+
}
|
|
891
|
+
for (const [name, data] of Object.entries(content.modules)) {
|
|
892
|
+
fs.writeFileSync(path.join(modulesDir, name), data);
|
|
893
|
+
}
|
|
894
|
+
results.push(`ā Installed ${Object.keys(content.modules).length} pattern modules`);
|
|
895
|
+
}
|
|
896
|
+
// Create PRD with description
|
|
897
|
+
const date = new Date().toISOString().split('T')[0];
|
|
898
|
+
const prdContent = `# Product Requirements Document
|
|
899
|
+
# Project: ${projectName}
|
|
900
|
+
# Created: ${date}
|
|
901
|
+
|
|
902
|
+
## Overview
|
|
903
|
+
**One-liner:** ${description || '[Describe this project in one sentence]'}
|
|
904
|
+
|
|
905
|
+
**Problem:** [What problem does this solve?]
|
|
906
|
+
|
|
907
|
+
**Solution:** [How does this solve it?]
|
|
908
|
+
|
|
909
|
+
## Core Features (MVP)
|
|
910
|
+
1. [ ] **Feature 1:** [Description]
|
|
911
|
+
2. [ ] **Feature 2:** [Description]
|
|
912
|
+
3. [ ] **Feature 3:** [Description]
|
|
913
|
+
|
|
914
|
+
## Technical Requirements
|
|
915
|
+
- Framework: Next.js 14 (App Router)
|
|
916
|
+
- Database: PostgreSQL + Drizzle ORM
|
|
917
|
+
- Auth: Supabase Auth
|
|
918
|
+
- UI: Tailwind CSS + shadcn/ui
|
|
919
|
+
|
|
920
|
+
---
|
|
921
|
+
<!-- AI: Reference this PRD when building features -->
|
|
922
|
+
`;
|
|
923
|
+
fs.writeFileSync(path.join(cwd, 'PRD.md'), prdContent);
|
|
924
|
+
results.push('ā Created PRD.md');
|
|
925
|
+
// Create other project files
|
|
926
|
+
fs.writeFileSync(path.join(cwd, 'PROJECT-STATE.md'), `# PROJECT STATE
|
|
927
|
+
# Last Updated: ${date}
|
|
928
|
+
|
|
929
|
+
## Project Info
|
|
930
|
+
name: ${projectName}
|
|
931
|
+
phase: setup
|
|
932
|
+
|
|
933
|
+
## In Progress
|
|
934
|
+
## Completed
|
|
935
|
+
## Next Up
|
|
936
|
+
`);
|
|
937
|
+
results.push('ā Created PROJECT-STATE.md');
|
|
938
|
+
}
|
|
939
|
+
results.push('\n---\n');
|
|
940
|
+
results.push('## ā
Project Created Successfully!\n');
|
|
941
|
+
results.push('### Next Steps:\n');
|
|
942
|
+
results.push('1. **Set up Supabase:** Go to https://supabase.com and create a free project');
|
|
943
|
+
results.push('2. **Add credentials:** Copy your Supabase URL and anon key to `.env.local`');
|
|
944
|
+
results.push('3. **Start building:** Just tell me what features you want!\n');
|
|
945
|
+
results.push('### Example:\n');
|
|
946
|
+
results.push('> "Add user authentication with email/password"');
|
|
947
|
+
results.push('> "Create a dashboard with stats cards"');
|
|
948
|
+
results.push('> "Build a todo list with CRUD operations"');
|
|
949
|
+
}
|
|
950
|
+
catch (error) {
|
|
951
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
952
|
+
results.push(`\nā Error: ${message}`);
|
|
953
|
+
}
|
|
954
|
+
return {
|
|
955
|
+
content: [{
|
|
956
|
+
type: 'text',
|
|
957
|
+
text: results.join('\n'),
|
|
958
|
+
}],
|
|
959
|
+
};
|
|
960
|
+
}
|
|
961
|
+
async handleInitProject(args) {
|
|
962
|
+
const cwd = process.cwd();
|
|
963
|
+
const results = [];
|
|
964
|
+
// Detect project name from package.json
|
|
965
|
+
let projectName = args.projectName || 'my-project';
|
|
966
|
+
try {
|
|
967
|
+
const pkgPath = path.join(cwd, 'package.json');
|
|
968
|
+
if (fs.existsSync(pkgPath)) {
|
|
969
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
970
|
+
projectName = pkg.name || projectName;
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
catch {
|
|
974
|
+
// Use default
|
|
975
|
+
}
|
|
976
|
+
results.push(`# šØ Adding CodeBakers to: ${projectName}\n`);
|
|
977
|
+
// Check if already initialized
|
|
978
|
+
if (fs.existsSync(path.join(cwd, 'CLAUDE.md'))) {
|
|
979
|
+
results.push('ā ļø CLAUDE.md already exists. Updating patterns...\n');
|
|
980
|
+
}
|
|
981
|
+
try {
|
|
982
|
+
const response = await fetch(`${this.apiUrl}/api/content`, {
|
|
983
|
+
method: 'GET',
|
|
984
|
+
headers: { Authorization: `Bearer ${this.apiKey}` },
|
|
985
|
+
});
|
|
986
|
+
if (!response.ok) {
|
|
987
|
+
throw new Error('Failed to fetch patterns from API');
|
|
988
|
+
}
|
|
989
|
+
const content = await response.json();
|
|
990
|
+
// Write CLAUDE.md
|
|
991
|
+
if (content.router) {
|
|
992
|
+
fs.writeFileSync(path.join(cwd, 'CLAUDE.md'), content.router);
|
|
993
|
+
results.push('ā Created/Updated CLAUDE.md');
|
|
994
|
+
}
|
|
995
|
+
// Write pattern modules
|
|
996
|
+
if (content.modules && Object.keys(content.modules).length > 0) {
|
|
997
|
+
const modulesDir = path.join(cwd, '.claude');
|
|
998
|
+
if (!fs.existsSync(modulesDir)) {
|
|
999
|
+
fs.mkdirSync(modulesDir, { recursive: true });
|
|
1000
|
+
}
|
|
1001
|
+
for (const [name, data] of Object.entries(content.modules)) {
|
|
1002
|
+
fs.writeFileSync(path.join(modulesDir, name), data);
|
|
1003
|
+
}
|
|
1004
|
+
results.push(`ā Installed ${Object.keys(content.modules).length} pattern modules (v${content.version})`);
|
|
1005
|
+
}
|
|
1006
|
+
// Create PRD if doesn't exist
|
|
1007
|
+
const date = new Date().toISOString().split('T')[0];
|
|
1008
|
+
const prdPath = path.join(cwd, 'PRD.md');
|
|
1009
|
+
if (!fs.existsSync(prdPath)) {
|
|
1010
|
+
fs.writeFileSync(prdPath, `# Product Requirements Document
|
|
1011
|
+
# Project: ${projectName}
|
|
1012
|
+
# Created: ${date}
|
|
1013
|
+
|
|
1014
|
+
## Overview
|
|
1015
|
+
**One-liner:** [Describe this project]
|
|
1016
|
+
|
|
1017
|
+
## Core Features (MVP)
|
|
1018
|
+
1. [ ] **Feature 1:** [Description]
|
|
1019
|
+
2. [ ] **Feature 2:** [Description]
|
|
1020
|
+
`);
|
|
1021
|
+
results.push('ā Created PRD.md template');
|
|
1022
|
+
}
|
|
1023
|
+
// Create PROJECT-STATE if doesn't exist
|
|
1024
|
+
const statePath = path.join(cwd, 'PROJECT-STATE.md');
|
|
1025
|
+
if (!fs.existsSync(statePath)) {
|
|
1026
|
+
fs.writeFileSync(statePath, `# PROJECT STATE
|
|
1027
|
+
# Last Updated: ${date}
|
|
1028
|
+
|
|
1029
|
+
## Project Info
|
|
1030
|
+
name: ${projectName}
|
|
1031
|
+
phase: development
|
|
1032
|
+
|
|
1033
|
+
## In Progress
|
|
1034
|
+
## Completed
|
|
1035
|
+
## Next Up
|
|
1036
|
+
`);
|
|
1037
|
+
results.push('ā Created PROJECT-STATE.md');
|
|
1038
|
+
}
|
|
1039
|
+
// Update .gitignore
|
|
1040
|
+
const gitignorePath = path.join(cwd, '.gitignore');
|
|
1041
|
+
if (fs.existsSync(gitignorePath)) {
|
|
1042
|
+
const gitignore = fs.readFileSync(gitignorePath, 'utf-8');
|
|
1043
|
+
if (!gitignore.includes('.claude/')) {
|
|
1044
|
+
fs.writeFileSync(gitignorePath, gitignore + '\n# CodeBakers\n.claude/\n');
|
|
1045
|
+
results.push('ā Updated .gitignore');
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
results.push('\n---\n');
|
|
1049
|
+
results.push('## ā
CodeBakers Patterns Installed!\n');
|
|
1050
|
+
results.push('The AI now has access to production patterns for:');
|
|
1051
|
+
results.push('- Authentication, Database, API design');
|
|
1052
|
+
results.push('- Frontend components, Forms, Validation');
|
|
1053
|
+
results.push('- Payments, Email, Real-time features');
|
|
1054
|
+
results.push('- And 30+ more specialized patterns\n');
|
|
1055
|
+
results.push('Just describe what you want to build!');
|
|
1056
|
+
}
|
|
1057
|
+
catch (error) {
|
|
1058
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
1059
|
+
results.push(`\nā Error: ${message}`);
|
|
1060
|
+
}
|
|
1061
|
+
return {
|
|
1062
|
+
content: [{
|
|
1063
|
+
type: 'text',
|
|
1064
|
+
text: results.join('\n'),
|
|
1065
|
+
}],
|
|
1066
|
+
};
|
|
1067
|
+
}
|
|
1068
|
+
handleSetExperienceLevel(args) {
|
|
1069
|
+
const { level } = args;
|
|
1070
|
+
// Validate level
|
|
1071
|
+
if (!['beginner', 'intermediate', 'advanced'].includes(level)) {
|
|
1072
|
+
return {
|
|
1073
|
+
content: [{
|
|
1074
|
+
type: 'text',
|
|
1075
|
+
text: `ā Invalid experience level: "${level}". Must be: beginner, intermediate, or advanced.`,
|
|
1076
|
+
}],
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
1079
|
+
(0, config_js_1.setExperienceLevel)(level);
|
|
1080
|
+
const descriptions = {
|
|
1081
|
+
beginner: 'š **Beginner Mode**\n\nI will:\n- Explain concepts as I go\n- Break down complex steps\n- Provide more context about what each piece of code does\n- Suggest learning resources when relevant',
|
|
1082
|
+
intermediate: 'ā” **Intermediate Mode**\n\nI will:\n- Provide balanced explanations\n- Focus on the "why" behind decisions\n- Skip basic explanations you already know',
|
|
1083
|
+
advanced: 'š **Advanced Mode**\n\nI will:\n- Skip explanations, just build\n- Focus on efficiency and best practices\n- Assume you know the fundamentals\n- Get straight to the code',
|
|
1084
|
+
};
|
|
1085
|
+
return {
|
|
1086
|
+
content: [{
|
|
1087
|
+
type: 'text',
|
|
1088
|
+
text: `ā
Experience level set to: **${level}**\n\n${descriptions[level]}`,
|
|
1089
|
+
}],
|
|
1090
|
+
};
|
|
1091
|
+
}
|
|
1092
|
+
handleGetExperienceLevel() {
|
|
1093
|
+
const level = (0, config_js_1.getExperienceLevel)();
|
|
1094
|
+
const modeInfo = {
|
|
1095
|
+
beginner: {
|
|
1096
|
+
emoji: 'š',
|
|
1097
|
+
description: 'Detailed explanations, step-by-step guidance'
|
|
1098
|
+
},
|
|
1099
|
+
intermediate: {
|
|
1100
|
+
emoji: 'ā”',
|
|
1101
|
+
description: 'Balanced explanations, focus on decisions'
|
|
1102
|
+
},
|
|
1103
|
+
advanced: {
|
|
1104
|
+
emoji: 'š',
|
|
1105
|
+
description: 'Minimal explanations, straight to code'
|
|
1106
|
+
},
|
|
1107
|
+
};
|
|
1108
|
+
const info = modeInfo[level];
|
|
1109
|
+
return {
|
|
1110
|
+
content: [{
|
|
1111
|
+
type: 'text',
|
|
1112
|
+
text: `# Current Experience Level\n\n${info.emoji} **${level.charAt(0).toUpperCase() + level.slice(1)}**\n${info.description}\n\n---\n\nTo change, use: \`set_experience_level\` with "beginner", "intermediate", or "advanced"`,
|
|
1113
|
+
}],
|
|
1114
|
+
};
|
|
1115
|
+
}
|
|
736
1116
|
async run() {
|
|
737
1117
|
const transport = new stdio_js_1.StdioServerTransport();
|
|
738
1118
|
await this.server.connect(transport);
|