44 type CreateCardInput ,
55 type CreateCardOutput ,
66} from '../types/tools.js' ;
7- import { toCourseElo , NameSpacer } from '@vue-skuilder/common' ;
8- import { getAllDataShapesRaw } from '@vue-skuilder/courseware/backend' ;
7+ import { toCourseElo , NameSpacer , FieldType , type DataShape , type FieldDefinition } from '@vue-skuilder/common' ;
98import {
109 MCP_AGENT_AUTHOR ,
1110 handleToolError ,
@@ -14,6 +13,58 @@ import {
1413 logToolWarning ,
1514} from '../utils/index.js' ;
1615
16+ /**
17+ * Reconstructs a minimal DataShape from course config's serialized JSON Schema
18+ * Only extracts field names and types - no validators or custom logic
19+ */
20+ function reconstructDataShapeFromConfig (
21+ dataShapeName : string ,
22+ serializedSchema : string
23+ ) : DataShape {
24+ const jsonSchema = JSON . parse ( serializedSchema ) ;
25+ const fields : FieldDefinition [ ] = [ ] ;
26+
27+ if ( jsonSchema . properties ) {
28+ for ( const [ fieldName , fieldSchema ] of Object . entries ( jsonSchema . properties ) ) {
29+ const schema = fieldSchema as any ;
30+
31+ // Map JSON Schema types to FieldType enum
32+ let fieldType : FieldType = FieldType . STRING ; // default
33+
34+ if ( schema . type === 'string' ) {
35+ if ( schema . contentEncoding === 'base64' || fieldName . toLowerCase ( ) . includes ( 'image' ) ) {
36+ fieldType = FieldType . IMAGE ;
37+ } else if ( fieldName . toLowerCase ( ) . includes ( 'audio' ) ) {
38+ fieldType = FieldType . AUDIO ;
39+ } else if ( schema . description ?. includes ( 'Markdown' ) || schema . description ?. includes ( 'markdown' ) ) {
40+ fieldType = FieldType . MARKDOWN ;
41+ } else {
42+ fieldType = FieldType . STRING ;
43+ }
44+ } else if ( schema . type === 'number' ) {
45+ fieldType = FieldType . NUMBER ;
46+ } else if ( schema . type === 'integer' ) {
47+ fieldType = FieldType . INT ;
48+ } else if ( schema . type === 'array' ) {
49+ // Check if it's uploads/media
50+ if ( fieldName === 'Uploads' || fieldName . toLowerCase ( ) . includes ( 'upload' ) ) {
51+ fieldType = FieldType . MEDIA_UPLOADS ;
52+ }
53+ }
54+
55+ fields . push ( {
56+ name : fieldName ,
57+ type : fieldType ,
58+ } ) ;
59+ }
60+ }
61+
62+ return {
63+ name : dataShapeName as any , // Cast to DataShapeName - it's just a string at runtime
64+ fields,
65+ } ;
66+ }
67+
1768export async function handleCreateCard (
1869 courseDB : CourseDBInterface ,
1970 input : CreateCardInput
@@ -56,7 +107,7 @@ export async function handleCreateCard(
56107 throw new Error ( errorMsg ) ;
57108 }
58109
59- // Get the complete DataShape definition from course config
110+ // Get the DataShape definition from course config
60111 const matchingDataShape = courseConfig . dataShapes . find (
61112 ( ds ) => ds . name === validatedInput . datashape
62113 ) ;
@@ -66,24 +117,19 @@ export async function handleCreateCard(
66117 throw new Error ( errorMsg ) ;
67118 }
68119
69- // Get runtime DataShape definition from courseware
70- const runtimeDataShape = getAllDataShapesRaw ( )
71- . find ( ( ds ) => ds . name === shapeDescriptor . dataShape ) ;
72-
73- if ( ! runtimeDataShape ) {
74- const errorMsg = `Runtime DataShape not found in courseware: ${ shapeDescriptor . dataShape } ` ;
75- logToolWarning ( TOOL_NAME , errorMsg ) ;
76- throw new Error ( errorMsg ) ;
77- }
120+ // Reconstruct DataShape from course config's serialized schema
121+ // This bypasses the need for runtime courseware loading - we only need
122+ // field names and types, which we can derive from the JSON Schema
123+ const dataShape = reconstructDataShapeFromConfig (
124+ shapeDescriptor . dataShape ,
125+ matchingDataShape . serializedZodSchema !
126+ ) ;
78127
79128 logToolStart (
80129 TOOL_NAME ,
81- `Using runtime DataShape with ${ runtimeDataShape . fields . length } fields`
130+ `Using DataShape with ${ dataShape . fields . length } fields (reconstructed from course config) `
82131 ) ;
83132
84- // Use complete DataShape with field definitions from courseware
85- const dataShape = runtimeDataShape ;
86-
87133 // Create the card via courseDB
88134 const result = await courseDB . addNote (
89135 shapeDescriptor . course , // Use courseware name, not courseID
0 commit comments