@graspful/cli 0.2.5 → 0.2.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/README.md +44 -19
- package/dist/commands/create-academy.d.ts +3 -0
- package/dist/commands/create-academy.d.ts.map +1 -0
- package/dist/commands/create-academy.js +73 -0
- package/dist/commands/create-academy.js.map +1 -0
- package/dist/commands/create-brand.d.ts +0 -5
- package/dist/commands/create-brand.d.ts.map +1 -1
- package/dist/commands/create-brand.js +5 -64
- package/dist/commands/create-brand.js.map +1 -1
- package/dist/commands/create-course.d.ts +0 -4
- package/dist/commands/create-course.d.ts.map +1 -1
- package/dist/commands/create-course.js +3 -32
- package/dist/commands/create-course.js.map +1 -1
- package/dist/commands/describe.d.ts.map +1 -1
- package/dist/commands/describe.js +9 -86
- package/dist/commands/describe.js.map +1 -1
- package/dist/commands/fill-concept.d.ts.map +1 -1
- package/dist/commands/fill-concept.js +12 -47
- package/dist/commands/fill-concept.js.map +1 -1
- package/dist/commands/import.d.ts.map +1 -1
- package/dist/commands/import.js +79 -14
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +13 -7
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +27 -1
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/register.d.ts.map +1 -1
- package/dist/commands/register.js +3 -0
- package/dist/commands/register.js.map +1 -1
- package/dist/commands/review.d.ts.map +1 -1
- package/dist/commands/review.js +12 -1
- package/dist/commands/review.js.map +1 -1
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +5 -92
- package/dist/commands/validate.js.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/analytics.d.ts +2 -0
- package/dist/lib/analytics.d.ts.map +1 -1
- package/dist/lib/analytics.js +92 -4
- package/dist/lib/analytics.js.map +1 -1
- package/dist/lib/auth.d.ts +2 -1
- package/dist/lib/auth.d.ts.map +1 -1
- package/dist/lib/auth.js +13 -5
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/browser-auth.d.ts +1 -0
- package/dist/lib/browser-auth.d.ts.map +1 -1
- package/dist/lib/browser-auth.js +2 -1
- package/dist/lib/browser-auth.js.map +1 -1
- package/package.json +5 -4
|
@@ -46,7 +46,7 @@ function registerFillConceptCommand(program) {
|
|
|
46
46
|
fill
|
|
47
47
|
.command('concept <file> <conceptId>')
|
|
48
48
|
.description('Add KP stubs to a specific concept')
|
|
49
|
-
.option('--kps <count>', 'Number of KP stubs to add', '
|
|
49
|
+
.option('--kps <count>', 'Number of KP stubs to add (authoring starting point, not a cap)', '3')
|
|
50
50
|
.option('--problems <count>', 'Number of problem stubs per KP', '3')
|
|
51
51
|
.action(async (file, conceptId, opts) => {
|
|
52
52
|
if (!fs.existsSync(file)) {
|
|
@@ -63,55 +63,20 @@ function registerFillConceptCommand(program) {
|
|
|
63
63
|
(0, output_1.outputError)(`YAML parse error: ${msg}`);
|
|
64
64
|
process.exit(1);
|
|
65
65
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
const data = parsed.data;
|
|
72
|
-
const concept = data.concepts.find((c) => c.id === conceptId);
|
|
73
|
-
if (!concept) {
|
|
74
|
-
(0, output_1.outputError)(`Concept "${conceptId}" not found. Available: ${data.concepts.map((c) => c.id).join(', ')}`);
|
|
75
|
-
process.exit(1);
|
|
76
|
-
}
|
|
77
|
-
if (concept.knowledgePoints.length > 0) {
|
|
78
|
-
(0, output_1.output)({ conceptId, existingKps: concept.knowledgePoints.length, action: 'skipped' }, `Concept "${conceptId}" already has ${concept.knowledgePoints.length} KP(s). Use --force to overwrite (not yet implemented).`);
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
const kpCount = parseInt(opts.kps, 10);
|
|
82
|
-
const problemsPerKp = parseInt(opts.problems, 10);
|
|
83
|
-
const newKps = [];
|
|
84
|
-
for (let i = 1; i <= kpCount; i++) {
|
|
85
|
-
const problems = [];
|
|
86
|
-
for (let j = 1; j <= problemsPerKp; j++) {
|
|
87
|
-
problems.push({
|
|
88
|
-
id: `${conceptId}-kp${i}-p${j}`,
|
|
89
|
-
type: 'multiple_choice',
|
|
90
|
-
question: `TODO: Write question ${j} for ${conceptId} KP${i}`,
|
|
91
|
-
options: ['Option A', 'Option B', 'Option C', 'Option D'],
|
|
92
|
-
correct: 0,
|
|
93
|
-
explanation: 'TODO: Explain the correct answer',
|
|
94
|
-
difficulty: Math.min(j + 1, 5),
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
newKps.push({
|
|
98
|
-
id: `${conceptId}-kp${i}`,
|
|
99
|
-
instruction: `TODO: Write instruction for ${concept.name} — knowledge point ${i}`,
|
|
100
|
-
workedExample: `TODO: Write a worked example for ${concept.name} — knowledge point ${i}`,
|
|
101
|
-
problems,
|
|
66
|
+
try {
|
|
67
|
+
const updated = (0, shared_1.fillConceptInRaw)(raw, conceptId, {
|
|
68
|
+
kps: parseInt(opts.kps, 10),
|
|
69
|
+
problemsPerKp: parseInt(opts.problems, 10),
|
|
102
70
|
});
|
|
71
|
+
const updatedYaml = yaml.dump(updated, { lineWidth: 120, noRefs: true, schema: yaml.JSON_SCHEMA });
|
|
72
|
+
fs.writeFileSync(file, updatedYaml);
|
|
73
|
+
(0, analytics_1.cliCapture)('concept filled', { concept_id: conceptId });
|
|
74
|
+
(0, output_1.output)({ conceptId, kpsAdded: parseInt(opts.kps, 10), problemsPerKp: parseInt(opts.problems, 10), file }, `Added ${opts.kps} KP stub(s) with ${opts.problems} problem(s) each to "${conceptId}" in ${file}`);
|
|
103
75
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const targetConcept = concepts.find((c) => c['id'] === conceptId);
|
|
108
|
-
if (targetConcept) {
|
|
109
|
-
targetConcept['knowledgePoints'] = newKps;
|
|
76
|
+
catch (e) {
|
|
77
|
+
(0, output_1.outputError)(e instanceof Error ? e.message : String(e));
|
|
78
|
+
process.exit(1);
|
|
110
79
|
}
|
|
111
|
-
const updatedYaml = yaml.dump(rawObj, { lineWidth: 120, noRefs: true, schema: yaml.JSON_SCHEMA });
|
|
112
|
-
fs.writeFileSync(file, updatedYaml);
|
|
113
|
-
(0, analytics_1.cliCapture)('concept filled', { concept_id: conceptId });
|
|
114
|
-
(0, output_1.output)({ conceptId, kpsAdded: kpCount, problemsPerKp, file }, `Added ${kpCount} KP stub(s) with ${problemsPerKp} problem(s) each to "${conceptId}" in ${file}`);
|
|
115
80
|
});
|
|
116
81
|
return fill;
|
|
117
82
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fill-concept.js","sourceRoot":"","sources":["../../src/commands/fill-concept.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,
|
|
1
|
+
{"version":3,"file":"fill-concept.js","sourceRoot":"","sources":["../../src/commands/fill-concept.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,gEA+CC;AArDD,uCAAyB;AACzB,8CAAgC;AAChC,6CAAoD;AACpD,0CAAoD;AACpD,gDAA8C;AAE9C,SAAgB,0BAA0B,CAAC,OAAgB;IACzD,MAAM,IAAI,GAAG,OAAO;SACjB,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,uBAAuB,CAAC,CAAC;IAExC,IAAI;SACD,OAAO,CAAC,4BAA4B,CAAC;SACrC,WAAW,CAAC,oCAAoC,CAAC;SACjD,MAAM,CAAC,eAAe,EAAE,iEAAiE,EAAE,GAAG,CAAC;SAC/F,MAAM,CAAC,oBAAoB,EAAE,gCAAgC,EAAE,GAAG,CAAC;SACnE,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,SAAiB,EAAE,IAAuC,EAAE,EAAE;QACzF,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,IAAA,oBAAW,EAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC;YACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC/C,IAAI,GAAY,CAAC;QACjB,IAAI,CAAC;YACH,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,GAAG,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACvD,IAAA,oBAAW,EAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;YACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAA,yBAAgB,EAAC,GAAG,EAAE,SAAS,EAAE;gBAC/C,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;gBAC3B,aAAa,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;aAC3C,CAAC,CAAC;YAEH,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;YACnG,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;YAEpC,IAAA,sBAAU,EAAC,gBAAgB,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC;YACxD,IAAA,eAAM,EACJ,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,aAAa,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,EACjG,SAAS,IAAI,CAAC,GAAG,oBAAoB,IAAI,CAAC,QAAQ,wBAAwB,SAAS,QAAQ,IAAI,EAAE,CAClG,CAAC;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAA,oBAAW,EAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../src/commands/import.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../src/commands/import.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,QA4MrD"}
|
package/dist/commands/import.js
CHANGED
|
@@ -35,27 +35,22 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.registerImportCommand = registerImportCommand;
|
|
37
37
|
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
38
39
|
const yaml = __importStar(require("js-yaml"));
|
|
39
40
|
const auth_1 = require("../lib/auth");
|
|
40
41
|
const api_client_1 = require("../lib/api-client");
|
|
41
42
|
const output_1 = require("../lib/output");
|
|
42
43
|
const analytics_1 = require("../lib/analytics");
|
|
43
|
-
|
|
44
|
-
if (typeof data !== 'object' || data === null)
|
|
45
|
-
return null;
|
|
46
|
-
const obj = data;
|
|
47
|
-
if ('course' in obj)
|
|
48
|
-
return 'course';
|
|
49
|
-
if ('brand' in obj)
|
|
50
|
-
return 'brand';
|
|
51
|
-
return null;
|
|
52
|
-
}
|
|
44
|
+
const shared_1 = require("@graspful/shared");
|
|
53
45
|
function registerImportCommand(program) {
|
|
54
46
|
program
|
|
55
47
|
.command('import <file>')
|
|
56
|
-
.description('Import a course or brand YAML into a Graspful instance')
|
|
48
|
+
.description('Import a course, academy, or brand YAML into a Graspful instance')
|
|
57
49
|
.option('--org <slug>', 'Organization slug')
|
|
58
50
|
.option('--publish', 'Publish immediately (runs review gate)', false)
|
|
51
|
+
.option('--replace', 'Replace existing course content on re-import', false)
|
|
52
|
+
.option('--archive-missing', 'Archive concepts/KPs removed from the YAML', false)
|
|
53
|
+
.option('--course-dir <dir>', 'Base directory for academy course files (defaults to the manifest directory)')
|
|
59
54
|
.action(async (file, opts) => {
|
|
60
55
|
if (!fs.existsSync(file)) {
|
|
61
56
|
(0, output_1.outputError)(`File not found: ${file}`);
|
|
@@ -71,9 +66,9 @@ function registerImportCommand(program) {
|
|
|
71
66
|
(0, output_1.outputError)(`YAML parse error: ${msg}`);
|
|
72
67
|
process.exit(1);
|
|
73
68
|
}
|
|
74
|
-
const fileType = detectFileType(raw);
|
|
69
|
+
const fileType = (0, shared_1.detectFileType)(raw);
|
|
75
70
|
if (!fileType) {
|
|
76
|
-
(0, output_1.outputError)('Could not detect file type. Expected top-level key: course or
|
|
71
|
+
(0, output_1.outputError)('Could not detect file type. Expected top-level key: course, brand, or academy');
|
|
77
72
|
process.exit(1);
|
|
78
73
|
}
|
|
79
74
|
const creds = (0, auth_1.requireAuth)();
|
|
@@ -85,7 +80,7 @@ function registerImportCommand(program) {
|
|
|
85
80
|
process.exit(1);
|
|
86
81
|
}
|
|
87
82
|
try {
|
|
88
|
-
const result = await api.post(`/api/v1/orgs/${orgSlug}/courses/import`, { yaml: content, publish: opts.publish });
|
|
83
|
+
const result = await api.post(`/api/v1/orgs/${orgSlug}/courses/import`, { yaml: content, publish: opts.publish, replace: opts.replace, archiveMissing: opts.archiveMissing });
|
|
89
84
|
(0, analytics_1.cliCapture)('course imported', { course_id: result.courseId, org: orgSlug, published: result.published });
|
|
90
85
|
if (opts.publish && result.reviewFailures && result.reviewFailures.length > 0) {
|
|
91
86
|
(0, output_1.output)({ ...result, status: 'imported_but_not_published' }, `Imported course ${result.courseId} but publish failed:\n${result.reviewFailures.map((f) => ` - ${f}`).join('\n')}`);
|
|
@@ -100,6 +95,76 @@ function registerImportCommand(program) {
|
|
|
100
95
|
process.exit(1);
|
|
101
96
|
}
|
|
102
97
|
}
|
|
98
|
+
else if (fileType === 'academy') {
|
|
99
|
+
const orgSlug = opts.org;
|
|
100
|
+
if (!orgSlug) {
|
|
101
|
+
(0, output_1.outputError)('--org is required for academy imports');
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
const parsed = raw;
|
|
106
|
+
const courses = Array.isArray(parsed.courses) ? parsed.courses : [];
|
|
107
|
+
const manifestDir = opts.courseDir
|
|
108
|
+
? path.resolve(opts.courseDir)
|
|
109
|
+
: path.dirname(path.resolve(file));
|
|
110
|
+
const courseYamls = {};
|
|
111
|
+
for (const course of courses) {
|
|
112
|
+
const courseFile = course.file;
|
|
113
|
+
if (typeof courseFile !== 'string' || courseFile.length === 0) {
|
|
114
|
+
(0, output_1.outputError)('Academy manifest contains a course without a valid file path');
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
const resolvedPath = path.resolve(manifestDir, courseFile);
|
|
118
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
119
|
+
(0, output_1.outputError)(`Academy course file not found: ${resolvedPath}`);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
courseYamls[courseFile] = fs.readFileSync(resolvedPath, 'utf-8');
|
|
123
|
+
}
|
|
124
|
+
const result = await api.post(`/api/v1/orgs/${orgSlug}/academies/import`, {
|
|
125
|
+
manifestYaml: content,
|
|
126
|
+
courseYamls,
|
|
127
|
+
replace: opts.replace,
|
|
128
|
+
archiveMissing: opts.archiveMissing,
|
|
129
|
+
});
|
|
130
|
+
const publishedCourseIds = [];
|
|
131
|
+
const publishFailures = [];
|
|
132
|
+
if (opts.publish) {
|
|
133
|
+
for (const courseResult of result.courseResults) {
|
|
134
|
+
try {
|
|
135
|
+
await api.post(`/api/v1/orgs/${orgSlug}/courses/${courseResult.courseId}/publish`, {});
|
|
136
|
+
publishedCourseIds.push(courseResult.courseId);
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
140
|
+
publishFailures.push(`${courseResult.courseId}: ${msg}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const response = {
|
|
145
|
+
...result,
|
|
146
|
+
publishedCourseIds,
|
|
147
|
+
publishFailures,
|
|
148
|
+
};
|
|
149
|
+
(0, analytics_1.cliCapture)('academy imported', {
|
|
150
|
+
academy_id: result.academyId,
|
|
151
|
+
org: orgSlug,
|
|
152
|
+
course_count: result.courseCount,
|
|
153
|
+
published_count: publishedCourseIds.length,
|
|
154
|
+
});
|
|
155
|
+
if (publishFailures.length > 0) {
|
|
156
|
+
(0, output_1.output)(response, `Imported academy ${result.academySlug} (${result.courseCount} courses) but some courses failed to publish:\n${publishFailures.map((failure) => ` - ${failure}`).join('\n')}`);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
(0, output_1.output)(response, `Imported academy: ${result.academySlug}\n Academy ID: ${result.academyId}\n Courses: ${result.courseCount}\n Published courses: ${publishedCourseIds.length}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
catch (e) {
|
|
163
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
164
|
+
(0, output_1.outputError)(`Academy import failed: ${msg}`);
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
103
168
|
else {
|
|
104
169
|
// Brand import — unwrap YAML structure to flat DTO
|
|
105
170
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import.js","sourceRoot":"","sources":["../../src/commands/import.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"import.js","sourceRoot":"","sources":["../../src/commands/import.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4EpC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,QA0EnD"}
|
package/dist/commands/init.js
CHANGED
|
@@ -66,7 +66,7 @@ function detectEditors() {
|
|
|
66
66
|
}
|
|
67
67
|
return editors;
|
|
68
68
|
}
|
|
69
|
-
function writeMcpConfig(configPath, apiKey) {
|
|
69
|
+
function writeMcpConfig(configPath, apiKey, userId) {
|
|
70
70
|
const dir = path.dirname(configPath);
|
|
71
71
|
if (!fs.existsSync(dir)) {
|
|
72
72
|
fs.mkdirSync(dir, { recursive: true });
|
|
@@ -84,7 +84,10 @@ function writeMcpConfig(configPath, apiKey) {
|
|
|
84
84
|
mcpServers['graspful'] = {
|
|
85
85
|
command: 'npx',
|
|
86
86
|
args: ['-y', '@graspful/mcp'],
|
|
87
|
-
env: {
|
|
87
|
+
env: {
|
|
88
|
+
GRASPFUL_API_KEY: apiKey,
|
|
89
|
+
...(userId ? { GRASPFUL_USER_ID: userId } : {}),
|
|
90
|
+
},
|
|
88
91
|
};
|
|
89
92
|
existing.mcpServers = mcpServers;
|
|
90
93
|
fs.writeFileSync(configPath, JSON.stringify(existing, null, 2) + '\n');
|
|
@@ -107,7 +110,7 @@ function registerInitCommand(program) {
|
|
|
107
110
|
console.log('Skipping registration. To re-register, delete ~/.graspful/credentials.json first.');
|
|
108
111
|
// Still configure MCP if requested
|
|
109
112
|
if (opts.mcp) {
|
|
110
|
-
configureMcp(existingCreds.apiKey);
|
|
113
|
+
configureMcp(existingCreds.apiKey, existingCreds.userId);
|
|
111
114
|
}
|
|
112
115
|
(0, output_1.output)({ authenticated: true, baseUrl }, 'Ready. Run graspful create course --topic "Your Topic" to get started.');
|
|
113
116
|
return;
|
|
@@ -128,7 +131,7 @@ function registerInitCommand(program) {
|
|
|
128
131
|
console.log(` API key: ${data.apiKey} (saved to ~/.graspful/credentials.json)`);
|
|
129
132
|
// ── Configure MCP ───────────────────────────────────────────────
|
|
130
133
|
if (opts.mcp) {
|
|
131
|
-
configureMcp(data.apiKey);
|
|
134
|
+
configureMcp(data.apiKey, data.userId);
|
|
132
135
|
}
|
|
133
136
|
(0, output_1.output)({
|
|
134
137
|
userId: data.userId,
|
|
@@ -151,7 +154,7 @@ function registerInitCommand(program) {
|
|
|
151
154
|
}
|
|
152
155
|
});
|
|
153
156
|
}
|
|
154
|
-
function configureMcp(apiKey) {
|
|
157
|
+
function configureMcp(apiKey, userId) {
|
|
155
158
|
const editors = detectEditors();
|
|
156
159
|
if (editors.length === 0) {
|
|
157
160
|
console.log('\nNo supported editors detected. Add MCP manually:');
|
|
@@ -160,14 +163,17 @@ function configureMcp(apiKey) {
|
|
|
160
163
|
graspful: {
|
|
161
164
|
command: 'npx',
|
|
162
165
|
args: ['-y', '@graspful/mcp'],
|
|
163
|
-
env: {
|
|
166
|
+
env: {
|
|
167
|
+
GRASPFUL_API_KEY: apiKey,
|
|
168
|
+
...(userId ? { GRASPFUL_USER_ID: userId } : {}),
|
|
169
|
+
},
|
|
164
170
|
},
|
|
165
171
|
},
|
|
166
172
|
}, null, 2));
|
|
167
173
|
return;
|
|
168
174
|
}
|
|
169
175
|
for (const editor of editors) {
|
|
170
|
-
writeMcpConfig(editor.configPath, apiKey);
|
|
176
|
+
writeMcpConfig(editor.configPath, apiKey, userId);
|
|
171
177
|
(0, analytics_1.cliCapture)('cli initialized', { editor: editor.name });
|
|
172
178
|
console.log(`\nMCP configured for ${editor.name}: ${editor.configPath}`);
|
|
173
179
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,QAgGpD"}
|
package/dist/commands/login.js
CHANGED
|
@@ -11,7 +11,8 @@ function registerLoginCommand(program) {
|
|
|
11
11
|
.description('Authenticate with a Graspful instance')
|
|
12
12
|
.option('--api-url <url>', 'API base URL')
|
|
13
13
|
.option('--token <token>', 'API key or JWT token (skip interactive prompt)')
|
|
14
|
-
.option('--email <email>', '
|
|
14
|
+
.option('--email <email>', 'Email address (use with --password for non-interactive login)')
|
|
15
|
+
.option('--password <password>', 'Password (use with --email for non-interactive login)')
|
|
15
16
|
.option('--no-browser', 'Print the sign-in URL instead of opening it automatically')
|
|
16
17
|
.action(async (opts) => {
|
|
17
18
|
const baseUrl = (opts.apiUrl || (0, auth_1.getBaseUrl)()).replace(/\/$/, '');
|
|
@@ -27,6 +28,30 @@ function registerLoginCommand(program) {
|
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
try {
|
|
31
|
+
// Email + password login: call the backend auth/login endpoint
|
|
32
|
+
if (!token && opts.email && opts.password) {
|
|
33
|
+
const res = await fetch(`${baseUrl}/api/v1/auth/login`, {
|
|
34
|
+
method: 'POST',
|
|
35
|
+
headers: { 'Content-Type': 'application/json' },
|
|
36
|
+
body: JSON.stringify({ email: opts.email, password: opts.password }),
|
|
37
|
+
});
|
|
38
|
+
if (!res.ok) {
|
|
39
|
+
const body = await res.text();
|
|
40
|
+
let message = `Login failed (${res.status})`;
|
|
41
|
+
try {
|
|
42
|
+
const parsed = JSON.parse(body);
|
|
43
|
+
if (parsed.message)
|
|
44
|
+
message = parsed.message;
|
|
45
|
+
}
|
|
46
|
+
catch { }
|
|
47
|
+
throw new Error(message);
|
|
48
|
+
}
|
|
49
|
+
const { apiKey, orgSlug, userId } = await res.json();
|
|
50
|
+
(0, auth_1.saveApiKeyCredentials)(apiKey, baseUrl, userId);
|
|
51
|
+
(0, analytics_1.cliCapture)('cli logged in', { method: 'email-password' });
|
|
52
|
+
(0, output_1.output)({ authenticated: true, baseUrl, tokenType: 'apiKey', orgSlug, userId }, `Authenticated. API key saved for ${baseUrl}`);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
30
55
|
if (!token) {
|
|
31
56
|
const result = await (0, browser_auth_1.runBrowserAuthFlow)({
|
|
32
57
|
apiUrl: baseUrl,
|
|
@@ -34,6 +59,7 @@ function registerLoginCommand(program) {
|
|
|
34
59
|
email: opts.email,
|
|
35
60
|
noBrowser: opts.browser === false,
|
|
36
61
|
});
|
|
62
|
+
(0, analytics_1.cliCapture)('cli logged in', { method: 'browser-auth' });
|
|
37
63
|
(0, output_1.output)({
|
|
38
64
|
authenticated: true,
|
|
39
65
|
baseUrl,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":";;AAMA,
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/commands/register.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/commands/register.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,QAmDvD"}
|
|
@@ -26,13 +26,16 @@ function registerRegisterCommand(program) {
|
|
|
26
26
|
noBrowser: opts.browser === false,
|
|
27
27
|
});
|
|
28
28
|
(0, analytics_1.cliCapture)('cli registered', { method: 'browser-auth' });
|
|
29
|
+
const brandDomain = result.brandDomain ?? `${result.orgSlug}.graspful.ai`;
|
|
29
30
|
(0, output_1.output)({
|
|
30
31
|
userId: result.userId,
|
|
31
32
|
orgSlug: result.orgSlug,
|
|
32
33
|
apiKey: result.apiKey,
|
|
34
|
+
brandDomain,
|
|
33
35
|
baseUrl,
|
|
34
36
|
}, [
|
|
35
37
|
`Created org: ${result.orgSlug}`,
|
|
38
|
+
`Brand: ${brandDomain}`,
|
|
36
39
|
`API key: ${result.apiKey} (saved to ~/.graspful/credentials.json)`,
|
|
37
40
|
'',
|
|
38
41
|
`You're ready. Run: graspful import course.yaml --org ${result.orgSlug}`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/commands/register.ts"],"names":[],"mappings":";;AAMA,
|
|
1
|
+
{"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/commands/register.ts"],"names":[],"mappings":";;AAMA,0DAmDC;AAxDD,sCAAyC;AACzC,sDAAyD;AACzD,0CAAoD;AACpD,gDAA8C;AAE9C,SAAgB,uBAAuB,CAAC,OAAgB;IACtD,OAAO;SACJ,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,iEAAiE,CAAC;SAC9E,MAAM,CAAC,iBAAiB,EAAE,kCAAkC,CAAC;SAC7D,MAAM,CAAC,uBAAuB,EAAE,wDAAwD,CAAC;SACzF,MAAM,CAAC,iBAAiB,EAAE,cAAc,CAAC;SACzC,MAAM,CAAC,cAAc,EAAE,2DAA2D,CAAC;SACnF,MAAM,CAAC,KAAK,EAAE,IAA+E,EAAE,EAAE;QAChG,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,IAAA,iBAAU,GAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAEjE,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClB,OAAO,CAAC,GAAG,CAAC,2FAA2F,CAAC,CAAC;YAC3G,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,IAAA,iCAAkB,EAAC;gBACtC,MAAM,EAAE,OAAO;gBACf,IAAI,EAAE,SAAS;gBACf,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,SAAS,EAAE,IAAI,CAAC,OAAO,KAAK,KAAK;aAClC,CAAC,CAAC;YAEH,IAAA,sBAAU,EAAC,gBAAgB,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;YACzD,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,IAAI,GAAG,MAAM,CAAC,OAAO,cAAc,CAAC;YAC1E,IAAA,eAAM,EACJ;gBACE,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,WAAW;gBACX,OAAO;aACR,EACD;gBACE,gBAAgB,MAAM,CAAC,OAAO,EAAE;gBAChC,UAAU,WAAW,EAAE;gBACvB,YAAY,MAAM,CAAC,MAAM,0CAA0C;gBACnE,EAAE;gBACF,wDAAwD,MAAM,CAAC,OAAO,EAAE;aACzE,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,GAAG,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACvD,IAAI,GAAG,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC9F,IAAA,oBAAW,EAAC,8BAA8B,OAAO,2CAA2C,CAAC,CAAC;YAChG,CAAC;iBAAM,CAAC;gBACN,IAAA,oBAAW,EAAC,wBAAwB,GAAG,EAAE,CAAC,CAAC;YAC7C,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../../src/commands/review.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../../src/commands/review.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,QAqDrD"}
|
package/dist/commands/review.js
CHANGED
|
@@ -70,7 +70,18 @@ function registerReviewCommand(program) {
|
|
|
70
70
|
lines.push(` [FAIL] ${failure.check}: ${failure.details ?? 'no details'}`);
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
|
-
|
|
73
|
+
if (result.warnings.length > 0) {
|
|
74
|
+
lines.push('');
|
|
75
|
+
lines.push('Warnings:');
|
|
76
|
+
for (const warning of result.warnings) {
|
|
77
|
+
lines.push(` [WARN] ${warning.check}: ${warning.details ?? 'no details'}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
(0, analytics_1.cliCapture)('course reviewed', {
|
|
81
|
+
score: result.score,
|
|
82
|
+
passed: result.passed,
|
|
83
|
+
warnings: result.warnings.length,
|
|
84
|
+
});
|
|
74
85
|
(0, output_1.output)(result, lines.join('\n'));
|
|
75
86
|
if (!result.passed) {
|
|
76
87
|
process.exit(1);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review.js","sourceRoot":"","sources":["../../src/commands/review.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,
|
|
1
|
+
{"version":3,"file":"review.js","sourceRoot":"","sources":["../../src/commands/review.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,QAsCvD"}
|
|
@@ -39,52 +39,6 @@ const yaml = __importStar(require("js-yaml"));
|
|
|
39
39
|
const shared_1 = require("@graspful/shared");
|
|
40
40
|
const output_1 = require("../lib/output");
|
|
41
41
|
const analytics_1 = require("../lib/analytics");
|
|
42
|
-
function detectFileType(data) {
|
|
43
|
-
if (typeof data !== 'object' || data === null)
|
|
44
|
-
return null;
|
|
45
|
-
const obj = data;
|
|
46
|
-
if ('course' in obj)
|
|
47
|
-
return 'course';
|
|
48
|
-
if ('brand' in obj)
|
|
49
|
-
return 'brand';
|
|
50
|
-
if ('academy' in obj)
|
|
51
|
-
return 'academy';
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
function detectCycles(concepts) {
|
|
55
|
-
const graph = new Map();
|
|
56
|
-
for (const c of concepts) {
|
|
57
|
-
graph.set(c.id, c.prerequisites);
|
|
58
|
-
}
|
|
59
|
-
const visited = new Set();
|
|
60
|
-
const inStack = new Set();
|
|
61
|
-
const cycles = [];
|
|
62
|
-
function dfs(node, path) {
|
|
63
|
-
if (inStack.has(node)) {
|
|
64
|
-
const cycleStart = path.indexOf(node);
|
|
65
|
-
const cycle = path.slice(cycleStart).concat(node);
|
|
66
|
-
cycles.push(`Cycle: ${cycle.join(' -> ')}`);
|
|
67
|
-
return true;
|
|
68
|
-
}
|
|
69
|
-
if (visited.has(node))
|
|
70
|
-
return false;
|
|
71
|
-
visited.add(node);
|
|
72
|
-
inStack.add(node);
|
|
73
|
-
path.push(node);
|
|
74
|
-
for (const dep of graph.get(node) ?? []) {
|
|
75
|
-
dfs(dep, path);
|
|
76
|
-
}
|
|
77
|
-
path.pop();
|
|
78
|
-
inStack.delete(node);
|
|
79
|
-
return false;
|
|
80
|
-
}
|
|
81
|
-
for (const id of graph.keys()) {
|
|
82
|
-
if (!visited.has(id)) {
|
|
83
|
-
dfs(id, []);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return cycles;
|
|
87
|
-
}
|
|
88
42
|
function registerValidateCommand(program) {
|
|
89
43
|
program
|
|
90
44
|
.command('validate <file>')
|
|
@@ -103,54 +57,13 @@ function registerValidateCommand(program) {
|
|
|
103
57
|
(0, output_1.output)({ valid: false, errors: [`YAML parse error: ${msg}`], stats: {} }, `FAIL YAML parse error: ${msg}`);
|
|
104
58
|
process.exit(1);
|
|
105
59
|
}
|
|
106
|
-
const
|
|
107
|
-
if (!
|
|
108
|
-
(0, output_1.output)({
|
|
109
|
-
process.exit(1);
|
|
110
|
-
}
|
|
111
|
-
const schemaMap = {
|
|
112
|
-
course: shared_1.CourseYamlSchema,
|
|
113
|
-
brand: shared_1.BrandYamlSchema,
|
|
114
|
-
academy: shared_1.AcademyManifestSchema,
|
|
115
|
-
};
|
|
116
|
-
const result = schemaMap[fileType].safeParse(raw);
|
|
117
|
-
if (!result.success) {
|
|
118
|
-
const errors = result.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`);
|
|
119
|
-
(0, output_1.output)({ valid: false, fileType, errors, stats: {} }, `FAIL ${fileType} validation (${errors.length} error${errors.length === 1 ? '' : 's'}):\n${errors.map((e) => ` - ${e}`).join('\n')}`);
|
|
120
|
-
process.exit(1);
|
|
121
|
-
}
|
|
122
|
-
// For courses, also check DAG
|
|
123
|
-
const dagErrors = [];
|
|
124
|
-
let stats = { fileType };
|
|
125
|
-
if (fileType === 'course') {
|
|
126
|
-
const data = result.data;
|
|
127
|
-
const conceptIds = new Set(data.concepts.map((c) => c.id));
|
|
128
|
-
// Check prerequisite references
|
|
129
|
-
for (const concept of data.concepts) {
|
|
130
|
-
for (const prereq of concept.prerequisites) {
|
|
131
|
-
if (!conceptIds.has(prereq)) {
|
|
132
|
-
dagErrors.push(`Concept "${concept.id}" has unknown prerequisite "${prereq}"`);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
// Check for cycles
|
|
137
|
-
const cycles = detectCycles(data.concepts.map((c) => ({ id: c.id, prerequisites: c.prerequisites })));
|
|
138
|
-
dagErrors.push(...cycles);
|
|
139
|
-
const kpCount = data.concepts.reduce((sum, c) => sum + c.knowledgePoints.length, 0);
|
|
140
|
-
const problemCount = data.concepts.reduce((sum, c) => sum + c.knowledgePoints.reduce((s, kp) => s + kp.problems.length, 0), 0);
|
|
141
|
-
stats = {
|
|
142
|
-
fileType,
|
|
143
|
-
concepts: data.concepts.length,
|
|
144
|
-
knowledgePoints: kpCount,
|
|
145
|
-
problems: problemCount,
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
if (dagErrors.length > 0) {
|
|
149
|
-
(0, output_1.output)({ valid: false, fileType, errors: dagErrors, stats }, `FAIL DAG validation (${dagErrors.length} error${dagErrors.length === 1 ? '' : 's'}):\n${dagErrors.map((e) => ` - ${e}`).join('\n')}`);
|
|
60
|
+
const result = (0, shared_1.validateParsedYaml)(raw);
|
|
61
|
+
if (!result.valid) {
|
|
62
|
+
(0, output_1.output)(result, `FAIL ${result.fileType ?? 'unknown'} validation (${result.errors.length} error${result.errors.length === 1 ? '' : 's'}):\n${result.errors.map((e) => ` - ${e}`).join('\n')}`);
|
|
150
63
|
process.exit(1);
|
|
151
64
|
}
|
|
152
|
-
(0, analytics_1.cliCapture)('course validated', { valid: true, error_count: 0, file_type: fileType });
|
|
153
|
-
(0, output_1.output)(
|
|
65
|
+
(0, analytics_1.cliCapture)('course validated', { valid: true, error_count: 0, file_type: result.fileType });
|
|
66
|
+
(0, output_1.output)(result, `PASS ${result.fileType} validation\n${Object.entries(result.stats).map(([k, v]) => ` ${k}: ${v}`).join('\n')}`);
|
|
154
67
|
});
|
|
155
68
|
}
|
|
156
69
|
//# sourceMappingURL=validate.js.map
|