@codebakers/cli 1.4.1 → 1.4.3
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/install-hook.js +5 -2
- package/dist/commands/mcp-config.js +5 -3
- package/dist/commands/scaffold.js +306 -8
- package/dist/commands/serve.js +6 -3
- package/dist/commands/setup.js +7 -4
- package/dist/config.d.ts +3 -0
- package/dist/config.js +9 -0
- package/dist/index.js +1 -1
- package/dist/mcp/server.js +380 -0
- package/package.json +2 -3
- package/src/commands/install-hook.ts +5 -2
- package/src/commands/mcp-config.ts +5 -3
- package/src/commands/scaffold.ts +330 -9
- package/src/commands/serve.ts +6 -3
- package/src/commands/setup.ts +7 -4
- package/src/config.ts +12 -0
- package/src/index.ts +1 -1
- package/src/mcp/server.ts +429 -1
package/src/mcp/server.ts
CHANGED
|
@@ -8,9 +8,11 @@ import {
|
|
|
8
8
|
ErrorCode,
|
|
9
9
|
McpError,
|
|
10
10
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
11
|
-
import { getApiKey, getApiUrl } from '../config.js';
|
|
11
|
+
import { getApiKey, getApiUrl, getExperienceLevel, setExperienceLevel, type ExperienceLevel } from '../config.js';
|
|
12
12
|
import * as fs from 'fs';
|
|
13
13
|
import * as path from 'path';
|
|
14
|
+
import { execSync } from 'child_process';
|
|
15
|
+
import * as templates from '../templates/nextjs-supabase.js';
|
|
14
16
|
|
|
15
17
|
// Pattern cache to avoid repeated API calls
|
|
16
18
|
const patternCache = new Map<string, { content: string; timestamp: number }>();
|
|
@@ -377,6 +379,64 @@ class CodeBakersServer {
|
|
|
377
379
|
required: ['pattern', 'section'],
|
|
378
380
|
},
|
|
379
381
|
},
|
|
382
|
+
{
|
|
383
|
+
name: 'scaffold_project',
|
|
384
|
+
description:
|
|
385
|
+
'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.',
|
|
386
|
+
inputSchema: {
|
|
387
|
+
type: 'object' as const,
|
|
388
|
+
properties: {
|
|
389
|
+
projectName: {
|
|
390
|
+
type: 'string',
|
|
391
|
+
description: 'Name of the project (lowercase, no spaces)',
|
|
392
|
+
},
|
|
393
|
+
description: {
|
|
394
|
+
type: 'string',
|
|
395
|
+
description: 'Brief description of what the project is for (used in PRD.md)',
|
|
396
|
+
},
|
|
397
|
+
},
|
|
398
|
+
required: ['projectName'],
|
|
399
|
+
},
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
name: 'init_project',
|
|
403
|
+
description:
|
|
404
|
+
'Add CodeBakers patterns to an existing project. Use this when user has an existing codebase and wants to add AI patterns to it.',
|
|
405
|
+
inputSchema: {
|
|
406
|
+
type: 'object' as const,
|
|
407
|
+
properties: {
|
|
408
|
+
projectName: {
|
|
409
|
+
type: 'string',
|
|
410
|
+
description: 'Name of the project (optional, will be auto-detected from package.json)',
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
name: 'set_experience_level',
|
|
417
|
+
description:
|
|
418
|
+
'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.',
|
|
419
|
+
inputSchema: {
|
|
420
|
+
type: 'object' as const,
|
|
421
|
+
properties: {
|
|
422
|
+
level: {
|
|
423
|
+
type: 'string',
|
|
424
|
+
enum: ['beginner', 'intermediate', 'advanced'],
|
|
425
|
+
description: 'Experience level: beginner (detailed explanations), intermediate (balanced), advanced (minimal explanations)',
|
|
426
|
+
},
|
|
427
|
+
},
|
|
428
|
+
required: ['level'],
|
|
429
|
+
},
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
name: 'get_experience_level',
|
|
433
|
+
description:
|
|
434
|
+
'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.',
|
|
435
|
+
inputSchema: {
|
|
436
|
+
type: 'object' as const,
|
|
437
|
+
properties: {},
|
|
438
|
+
},
|
|
439
|
+
},
|
|
380
440
|
],
|
|
381
441
|
}));
|
|
382
442
|
|
|
@@ -410,6 +470,18 @@ class CodeBakersServer {
|
|
|
410
470
|
case 'get_pattern_section':
|
|
411
471
|
return this.handleGetPatternSection(args as { pattern: string; section: string });
|
|
412
472
|
|
|
473
|
+
case 'scaffold_project':
|
|
474
|
+
return this.handleScaffoldProject(args as { projectName: string; description?: string });
|
|
475
|
+
|
|
476
|
+
case 'init_project':
|
|
477
|
+
return this.handleInitProject(args as { projectName?: string });
|
|
478
|
+
|
|
479
|
+
case 'set_experience_level':
|
|
480
|
+
return this.handleSetExperienceLevel(args as { level: ExperienceLevel });
|
|
481
|
+
|
|
482
|
+
case 'get_experience_level':
|
|
483
|
+
return this.handleGetExperienceLevel();
|
|
484
|
+
|
|
413
485
|
default:
|
|
414
486
|
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
415
487
|
}
|
|
@@ -836,6 +908,362 @@ Show the user what their simple request was expanded into, then proceed with the
|
|
|
836
908
|
};
|
|
837
909
|
}
|
|
838
910
|
|
|
911
|
+
private async handleScaffoldProject(args: { projectName: string; description?: string }) {
|
|
912
|
+
const { projectName, description } = args;
|
|
913
|
+
const cwd = process.cwd();
|
|
914
|
+
|
|
915
|
+
// Check if directory has files
|
|
916
|
+
const files = fs.readdirSync(cwd);
|
|
917
|
+
const hasFiles = files.filter(f => !f.startsWith('.')).length > 0;
|
|
918
|
+
|
|
919
|
+
if (hasFiles) {
|
|
920
|
+
// Check if it's already a CodeBakers project
|
|
921
|
+
if (fs.existsSync(path.join(cwd, 'CLAUDE.md'))) {
|
|
922
|
+
return {
|
|
923
|
+
content: [{
|
|
924
|
+
type: 'text' as const,
|
|
925
|
+
text: `# Project Already Exists\n\nThis directory already has a CodeBakers project. Use the existing project or navigate to an empty directory.`,
|
|
926
|
+
}],
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
const results: string[] = [];
|
|
932
|
+
results.push(`# 🚀 Creating Project: ${projectName}\n`);
|
|
933
|
+
|
|
934
|
+
try {
|
|
935
|
+
// Create directories
|
|
936
|
+
const dirs = [
|
|
937
|
+
'src/app',
|
|
938
|
+
'src/components',
|
|
939
|
+
'src/lib/supabase',
|
|
940
|
+
'src/db',
|
|
941
|
+
'src/db/migrations',
|
|
942
|
+
'src/services',
|
|
943
|
+
'src/types',
|
|
944
|
+
'public',
|
|
945
|
+
];
|
|
946
|
+
|
|
947
|
+
for (const dir of dirs) {
|
|
948
|
+
const dirPath = path.join(cwd, dir);
|
|
949
|
+
if (!fs.existsSync(dirPath)) {
|
|
950
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
results.push('✓ Created directory structure');
|
|
954
|
+
|
|
955
|
+
// Write package.json
|
|
956
|
+
const packageJson = { ...templates.PACKAGE_JSON, name: projectName };
|
|
957
|
+
fs.writeFileSync(path.join(cwd, 'package.json'), JSON.stringify(packageJson, null, 2));
|
|
958
|
+
results.push('✓ Created package.json');
|
|
959
|
+
|
|
960
|
+
// Write config files
|
|
961
|
+
fs.writeFileSync(path.join(cwd, '.env.example'), templates.ENV_EXAMPLE);
|
|
962
|
+
fs.writeFileSync(path.join(cwd, '.env.local'), templates.ENV_EXAMPLE);
|
|
963
|
+
fs.writeFileSync(path.join(cwd, 'drizzle.config.ts'), templates.DRIZZLE_CONFIG);
|
|
964
|
+
fs.writeFileSync(path.join(cwd, 'tailwind.config.ts'), templates.TAILWIND_CONFIG);
|
|
965
|
+
fs.writeFileSync(path.join(cwd, 'postcss.config.mjs'), templates.POSTCSS_CONFIG);
|
|
966
|
+
fs.writeFileSync(path.join(cwd, 'tsconfig.json'), JSON.stringify(templates.TSCONFIG, null, 2));
|
|
967
|
+
fs.writeFileSync(path.join(cwd, 'next.config.ts'), templates.NEXT_CONFIG);
|
|
968
|
+
fs.writeFileSync(path.join(cwd, '.gitignore'), templates.GITIGNORE);
|
|
969
|
+
results.push('✓ Created configuration files');
|
|
970
|
+
|
|
971
|
+
// Write source files
|
|
972
|
+
fs.writeFileSync(path.join(cwd, 'src/lib/supabase/server.ts'), templates.SUPABASE_SERVER);
|
|
973
|
+
fs.writeFileSync(path.join(cwd, 'src/lib/supabase/client.ts'), templates.SUPABASE_CLIENT);
|
|
974
|
+
fs.writeFileSync(path.join(cwd, 'src/lib/supabase/middleware.ts'), templates.SUPABASE_MIDDLEWARE);
|
|
975
|
+
fs.writeFileSync(path.join(cwd, 'middleware.ts'), templates.MIDDLEWARE);
|
|
976
|
+
fs.writeFileSync(path.join(cwd, 'src/db/schema.ts'), templates.DB_SCHEMA);
|
|
977
|
+
fs.writeFileSync(path.join(cwd, 'src/db/index.ts'), templates.DB_INDEX);
|
|
978
|
+
fs.writeFileSync(path.join(cwd, 'src/app/globals.css'), templates.GLOBALS_CSS);
|
|
979
|
+
fs.writeFileSync(path.join(cwd, 'src/app/layout.tsx'), templates.LAYOUT_TSX);
|
|
980
|
+
fs.writeFileSync(path.join(cwd, 'src/app/page.tsx'), templates.PAGE_TSX);
|
|
981
|
+
fs.writeFileSync(path.join(cwd, 'src/lib/utils.ts'), templates.UTILS_CN);
|
|
982
|
+
results.push('✓ Created source files');
|
|
983
|
+
|
|
984
|
+
// Install dependencies
|
|
985
|
+
try {
|
|
986
|
+
execSync('npm install', { cwd, stdio: 'pipe' });
|
|
987
|
+
results.push('✓ Installed npm dependencies');
|
|
988
|
+
} catch {
|
|
989
|
+
results.push('⚠️ Could not install dependencies - run `npm install` manually');
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
// Now install CodeBakers patterns
|
|
993
|
+
results.push('\n## Installing CodeBakers Patterns...\n');
|
|
994
|
+
|
|
995
|
+
const response = await fetch(`${this.apiUrl}/api/content`, {
|
|
996
|
+
method: 'GET',
|
|
997
|
+
headers: { Authorization: `Bearer ${this.apiKey}` },
|
|
998
|
+
});
|
|
999
|
+
|
|
1000
|
+
if (response.ok) {
|
|
1001
|
+
const content = await response.json();
|
|
1002
|
+
|
|
1003
|
+
// Write CLAUDE.md
|
|
1004
|
+
if (content.router) {
|
|
1005
|
+
fs.writeFileSync(path.join(cwd, 'CLAUDE.md'), content.router);
|
|
1006
|
+
results.push('✓ Created CLAUDE.md (AI router)');
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
// Write pattern modules
|
|
1010
|
+
if (content.modules && Object.keys(content.modules).length > 0) {
|
|
1011
|
+
const modulesDir = path.join(cwd, '.claude');
|
|
1012
|
+
if (!fs.existsSync(modulesDir)) {
|
|
1013
|
+
fs.mkdirSync(modulesDir, { recursive: true });
|
|
1014
|
+
}
|
|
1015
|
+
for (const [name, data] of Object.entries(content.modules)) {
|
|
1016
|
+
fs.writeFileSync(path.join(modulesDir, name), data as string);
|
|
1017
|
+
}
|
|
1018
|
+
results.push(`✓ Installed ${Object.keys(content.modules).length} pattern modules`);
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
// Create PRD with description
|
|
1022
|
+
const date = new Date().toISOString().split('T')[0];
|
|
1023
|
+
const prdContent = `# Product Requirements Document
|
|
1024
|
+
# Project: ${projectName}
|
|
1025
|
+
# Created: ${date}
|
|
1026
|
+
|
|
1027
|
+
## Overview
|
|
1028
|
+
**One-liner:** ${description || '[Describe this project in one sentence]'}
|
|
1029
|
+
|
|
1030
|
+
**Problem:** [What problem does this solve?]
|
|
1031
|
+
|
|
1032
|
+
**Solution:** [How does this solve it?]
|
|
1033
|
+
|
|
1034
|
+
## Core Features (MVP)
|
|
1035
|
+
1. [ ] **Feature 1:** [Description]
|
|
1036
|
+
2. [ ] **Feature 2:** [Description]
|
|
1037
|
+
3. [ ] **Feature 3:** [Description]
|
|
1038
|
+
|
|
1039
|
+
## Technical Requirements
|
|
1040
|
+
- Framework: Next.js 14 (App Router)
|
|
1041
|
+
- Database: PostgreSQL + Drizzle ORM
|
|
1042
|
+
- Auth: Supabase Auth
|
|
1043
|
+
- UI: Tailwind CSS + shadcn/ui
|
|
1044
|
+
|
|
1045
|
+
---
|
|
1046
|
+
<!-- AI: Reference this PRD when building features -->
|
|
1047
|
+
`;
|
|
1048
|
+
fs.writeFileSync(path.join(cwd, 'PRD.md'), prdContent);
|
|
1049
|
+
results.push('✓ Created PRD.md');
|
|
1050
|
+
|
|
1051
|
+
// Create other project files
|
|
1052
|
+
fs.writeFileSync(path.join(cwd, 'PROJECT-STATE.md'), `# PROJECT STATE
|
|
1053
|
+
# Last Updated: ${date}
|
|
1054
|
+
|
|
1055
|
+
## Project Info
|
|
1056
|
+
name: ${projectName}
|
|
1057
|
+
phase: setup
|
|
1058
|
+
|
|
1059
|
+
## In Progress
|
|
1060
|
+
## Completed
|
|
1061
|
+
## Next Up
|
|
1062
|
+
`);
|
|
1063
|
+
results.push('✓ Created PROJECT-STATE.md');
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
results.push('\n---\n');
|
|
1067
|
+
results.push('## ✅ Project Created Successfully!\n');
|
|
1068
|
+
results.push('### Next Steps:\n');
|
|
1069
|
+
results.push('1. **Set up Supabase:** Go to https://supabase.com and create a free project');
|
|
1070
|
+
results.push('2. **Add credentials:** Copy your Supabase URL and anon key to `.env.local`');
|
|
1071
|
+
results.push('3. **Start building:** Just tell me what features you want!\n');
|
|
1072
|
+
results.push('### Example:\n');
|
|
1073
|
+
results.push('> "Add user authentication with email/password"');
|
|
1074
|
+
results.push('> "Create a dashboard with stats cards"');
|
|
1075
|
+
results.push('> "Build a todo list with CRUD operations"');
|
|
1076
|
+
|
|
1077
|
+
} catch (error) {
|
|
1078
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
1079
|
+
results.push(`\n❌ Error: ${message}`);
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
return {
|
|
1083
|
+
content: [{
|
|
1084
|
+
type: 'text' as const,
|
|
1085
|
+
text: results.join('\n'),
|
|
1086
|
+
}],
|
|
1087
|
+
};
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
private async handleInitProject(args: { projectName?: string }) {
|
|
1091
|
+
const cwd = process.cwd();
|
|
1092
|
+
const results: string[] = [];
|
|
1093
|
+
|
|
1094
|
+
// Detect project name from package.json
|
|
1095
|
+
let projectName = args.projectName || 'my-project';
|
|
1096
|
+
try {
|
|
1097
|
+
const pkgPath = path.join(cwd, 'package.json');
|
|
1098
|
+
if (fs.existsSync(pkgPath)) {
|
|
1099
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
1100
|
+
projectName = pkg.name || projectName;
|
|
1101
|
+
}
|
|
1102
|
+
} catch {
|
|
1103
|
+
// Use default
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
results.push(`# 🎨 Adding CodeBakers to: ${projectName}\n`);
|
|
1107
|
+
|
|
1108
|
+
// Check if already initialized
|
|
1109
|
+
if (fs.existsSync(path.join(cwd, 'CLAUDE.md'))) {
|
|
1110
|
+
results.push('⚠️ CLAUDE.md already exists. Updating patterns...\n');
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
try {
|
|
1114
|
+
const response = await fetch(`${this.apiUrl}/api/content`, {
|
|
1115
|
+
method: 'GET',
|
|
1116
|
+
headers: { Authorization: `Bearer ${this.apiKey}` },
|
|
1117
|
+
});
|
|
1118
|
+
|
|
1119
|
+
if (!response.ok) {
|
|
1120
|
+
throw new Error('Failed to fetch patterns from API');
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
const content = await response.json();
|
|
1124
|
+
|
|
1125
|
+
// Write CLAUDE.md
|
|
1126
|
+
if (content.router) {
|
|
1127
|
+
fs.writeFileSync(path.join(cwd, 'CLAUDE.md'), content.router);
|
|
1128
|
+
results.push('✓ Created/Updated CLAUDE.md');
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
// Write pattern modules
|
|
1132
|
+
if (content.modules && Object.keys(content.modules).length > 0) {
|
|
1133
|
+
const modulesDir = path.join(cwd, '.claude');
|
|
1134
|
+
if (!fs.existsSync(modulesDir)) {
|
|
1135
|
+
fs.mkdirSync(modulesDir, { recursive: true });
|
|
1136
|
+
}
|
|
1137
|
+
for (const [name, data] of Object.entries(content.modules)) {
|
|
1138
|
+
fs.writeFileSync(path.join(modulesDir, name), data as string);
|
|
1139
|
+
}
|
|
1140
|
+
results.push(`✓ Installed ${Object.keys(content.modules).length} pattern modules (v${content.version})`);
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
// Create PRD if doesn't exist
|
|
1144
|
+
const date = new Date().toISOString().split('T')[0];
|
|
1145
|
+
const prdPath = path.join(cwd, 'PRD.md');
|
|
1146
|
+
if (!fs.existsSync(prdPath)) {
|
|
1147
|
+
fs.writeFileSync(prdPath, `# Product Requirements Document
|
|
1148
|
+
# Project: ${projectName}
|
|
1149
|
+
# Created: ${date}
|
|
1150
|
+
|
|
1151
|
+
## Overview
|
|
1152
|
+
**One-liner:** [Describe this project]
|
|
1153
|
+
|
|
1154
|
+
## Core Features (MVP)
|
|
1155
|
+
1. [ ] **Feature 1:** [Description]
|
|
1156
|
+
2. [ ] **Feature 2:** [Description]
|
|
1157
|
+
`);
|
|
1158
|
+
results.push('✓ Created PRD.md template');
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
// Create PROJECT-STATE if doesn't exist
|
|
1162
|
+
const statePath = path.join(cwd, 'PROJECT-STATE.md');
|
|
1163
|
+
if (!fs.existsSync(statePath)) {
|
|
1164
|
+
fs.writeFileSync(statePath, `# PROJECT STATE
|
|
1165
|
+
# Last Updated: ${date}
|
|
1166
|
+
|
|
1167
|
+
## Project Info
|
|
1168
|
+
name: ${projectName}
|
|
1169
|
+
phase: development
|
|
1170
|
+
|
|
1171
|
+
## In Progress
|
|
1172
|
+
## Completed
|
|
1173
|
+
## Next Up
|
|
1174
|
+
`);
|
|
1175
|
+
results.push('✓ Created PROJECT-STATE.md');
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
// Update .gitignore
|
|
1179
|
+
const gitignorePath = path.join(cwd, '.gitignore');
|
|
1180
|
+
if (fs.existsSync(gitignorePath)) {
|
|
1181
|
+
const gitignore = fs.readFileSync(gitignorePath, 'utf-8');
|
|
1182
|
+
if (!gitignore.includes('.claude/')) {
|
|
1183
|
+
fs.writeFileSync(gitignorePath, gitignore + '\n# CodeBakers\n.claude/\n');
|
|
1184
|
+
results.push('✓ Updated .gitignore');
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
results.push('\n---\n');
|
|
1189
|
+
results.push('## ✅ CodeBakers Patterns Installed!\n');
|
|
1190
|
+
results.push('The AI now has access to production patterns for:');
|
|
1191
|
+
results.push('- Authentication, Database, API design');
|
|
1192
|
+
results.push('- Frontend components, Forms, Validation');
|
|
1193
|
+
results.push('- Payments, Email, Real-time features');
|
|
1194
|
+
results.push('- And 30+ more specialized patterns\n');
|
|
1195
|
+
results.push('Just describe what you want to build!');
|
|
1196
|
+
|
|
1197
|
+
} catch (error) {
|
|
1198
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
1199
|
+
results.push(`\n❌ Error: ${message}`);
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
return {
|
|
1203
|
+
content: [{
|
|
1204
|
+
type: 'text' as const,
|
|
1205
|
+
text: results.join('\n'),
|
|
1206
|
+
}],
|
|
1207
|
+
};
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
private handleSetExperienceLevel(args: { level: ExperienceLevel }) {
|
|
1211
|
+
const { level } = args;
|
|
1212
|
+
|
|
1213
|
+
// Validate level
|
|
1214
|
+
if (!['beginner', 'intermediate', 'advanced'].includes(level)) {
|
|
1215
|
+
return {
|
|
1216
|
+
content: [{
|
|
1217
|
+
type: 'text' as const,
|
|
1218
|
+
text: `❌ Invalid experience level: "${level}". Must be: beginner, intermediate, or advanced.`,
|
|
1219
|
+
}],
|
|
1220
|
+
};
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
setExperienceLevel(level);
|
|
1224
|
+
|
|
1225
|
+
const descriptions: Record<ExperienceLevel, string> = {
|
|
1226
|
+
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',
|
|
1227
|
+
intermediate: '⚡ **Intermediate Mode**\n\nI will:\n- Provide balanced explanations\n- Focus on the "why" behind decisions\n- Skip basic explanations you already know',
|
|
1228
|
+
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',
|
|
1229
|
+
};
|
|
1230
|
+
|
|
1231
|
+
return {
|
|
1232
|
+
content: [{
|
|
1233
|
+
type: 'text' as const,
|
|
1234
|
+
text: `✅ Experience level set to: **${level}**\n\n${descriptions[level]}`,
|
|
1235
|
+
}],
|
|
1236
|
+
};
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
private handleGetExperienceLevel() {
|
|
1240
|
+
const level = getExperienceLevel();
|
|
1241
|
+
|
|
1242
|
+
const modeInfo: Record<ExperienceLevel, { emoji: string; description: string }> = {
|
|
1243
|
+
beginner: {
|
|
1244
|
+
emoji: '🎓',
|
|
1245
|
+
description: 'Detailed explanations, step-by-step guidance'
|
|
1246
|
+
},
|
|
1247
|
+
intermediate: {
|
|
1248
|
+
emoji: '⚡',
|
|
1249
|
+
description: 'Balanced explanations, focus on decisions'
|
|
1250
|
+
},
|
|
1251
|
+
advanced: {
|
|
1252
|
+
emoji: '🚀',
|
|
1253
|
+
description: 'Minimal explanations, straight to code'
|
|
1254
|
+
},
|
|
1255
|
+
};
|
|
1256
|
+
|
|
1257
|
+
const info = modeInfo[level];
|
|
1258
|
+
|
|
1259
|
+
return {
|
|
1260
|
+
content: [{
|
|
1261
|
+
type: 'text' as const,
|
|
1262
|
+
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"`,
|
|
1263
|
+
}],
|
|
1264
|
+
};
|
|
1265
|
+
}
|
|
1266
|
+
|
|
839
1267
|
async run(): Promise<void> {
|
|
840
1268
|
const transport = new StdioServerTransport();
|
|
841
1269
|
await this.server.connect(transport);
|