@lydt/geogebra-studio 0.0.0-stage → 0.4.0-rc.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/.agents/plugins/marketplace.json +21 -0
- package/.codex-plugin/plugin.json +21 -0
- package/.mcp.json +18 -0
- package/LICENSE +339 -0
- package/LICENSE-MIT +21 -0
- package/README.md +108 -2
- package/README.zh-CN.md +89 -0
- package/THIRD_PARTY_NOTICES.md +35 -0
- package/dist/cli.d.ts +27 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +234 -0
- package/dist/cli.js.map +1 -0
- package/dist/export/files.d.ts +4 -0
- package/dist/export/files.d.ts.map +1 -0
- package/dist/export/files.js +44 -0
- package/dist/export/files.js.map +1 -0
- package/dist/export/gikz.d.ts +11 -0
- package/dist/export/gikz.d.ts.map +1 -0
- package/dist/export/gikz.js +28 -0
- package/dist/export/gikz.js.map +1 -0
- package/dist/export/html.d.ts +14 -0
- package/dist/export/html.d.ts.map +1 -0
- package/dist/export/html.js +97 -0
- package/dist/export/html.js.map +1 -0
- package/dist/export/semantic.d.ts +43 -0
- package/dist/export/semantic.d.ts.map +1 -0
- package/dist/export/semantic.js +212 -0
- package/dist/export/semantic.js.map +1 -0
- package/dist/export/viewer-themes.d.ts +76 -0
- package/dist/export/viewer-themes.d.ts.map +1 -0
- package/dist/export/viewer-themes.js +169 -0
- package/dist/export/viewer-themes.js.map +1 -0
- package/dist/export/workspace.d.ts +4 -0
- package/dist/export/workspace.d.ts.map +1 -0
- package/dist/export/workspace.js +25 -0
- package/dist/export/workspace.js.map +1 -0
- package/dist/gikz-browser.js +770 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +84 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +35 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +187 -0
- package/dist/server.js.map +1 -0
- package/dist/studio/artifact.d.ts +37 -0
- package/dist/studio/artifact.d.ts.map +1 -0
- package/dist/studio/artifact.js +61 -0
- package/dist/studio/artifact.js.map +1 -0
- package/dist/studio/browser.d.ts +7 -0
- package/dist/studio/browser.d.ts.map +1 -0
- package/dist/studio/browser.js +67 -0
- package/dist/studio/browser.js.map +1 -0
- package/dist/studio/install.d.ts +4 -0
- package/dist/studio/install.d.ts.map +1 -0
- package/dist/studio/install.js +60 -0
- package/dist/studio/install.js.map +1 -0
- package/dist/tools/apps-api-tools.d.ts +4 -0
- package/dist/tools/apps-api-tools.d.ts.map +1 -0
- package/dist/tools/apps-api-tools.js +96 -0
- package/dist/tools/apps-api-tools.js.map +1 -0
- package/dist/tools/educational-templates.d.ts +33 -0
- package/dist/tools/educational-templates.d.ts.map +1 -0
- package/dist/tools/educational-templates.js +261 -0
- package/dist/tools/educational-templates.js.map +1 -0
- package/dist/tools/export-tools.d.ts +3 -0
- package/dist/tools/export-tools.d.ts.map +1 -0
- package/dist/tools/export-tools.js +118 -0
- package/dist/tools/export-tools.js.map +1 -0
- package/dist/tools/geogebra-tools.d.ts +15 -0
- package/dist/tools/geogebra-tools.d.ts.map +1 -0
- package/dist/tools/geogebra-tools.js +3442 -0
- package/dist/tools/geogebra-tools.js.map +1 -0
- package/dist/tools/index.d.ts +43 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +183 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/performance-tools.d.ts +7 -0
- package/dist/tools/performance-tools.d.ts.map +1 -0
- package/dist/tools/performance-tools.js +312 -0
- package/dist/tools/performance-tools.js.map +1 -0
- package/dist/tools/templates/algebra-templates.d.ts +7 -0
- package/dist/tools/templates/algebra-templates.d.ts.map +1 -0
- package/dist/tools/templates/algebra-templates.js +568 -0
- package/dist/tools/templates/algebra-templates.js.map +1 -0
- package/dist/tools/templates/geometry-templates.d.ts +7 -0
- package/dist/tools/templates/geometry-templates.d.ts.map +1 -0
- package/dist/tools/templates/geometry-templates.js +492 -0
- package/dist/tools/templates/geometry-templates.js.map +1 -0
- package/dist/types/geogebra.d.ts +103 -0
- package/dist/types/geogebra.d.ts.map +1 -0
- package/dist/types/geogebra.js +34 -0
- package/dist/types/geogebra.js.map +1 -0
- package/dist/types/mcp.d.ts +125 -0
- package/dist/types/mcp.d.ts.map +1 -0
- package/dist/types/mcp.js +19 -0
- package/dist/types/mcp.js.map +1 -0
- package/dist/utils/app-info.d.ts +12 -0
- package/dist/utils/app-info.d.ts.map +1 -0
- package/dist/utils/app-info.js +30 -0
- package/dist/utils/app-info.js.map +1 -0
- package/dist/utils/errors.d.ts +37 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +72 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/gemini-compatibility.d.ts +39 -0
- package/dist/utils/gemini-compatibility.d.ts.map +1 -0
- package/dist/utils/gemini-compatibility.js +154 -0
- package/dist/utils/gemini-compatibility.js.map +1 -0
- package/dist/utils/geogebra-instance.d.ts +252 -0
- package/dist/utils/geogebra-instance.d.ts.map +1 -0
- package/dist/utils/geogebra-instance.js +1560 -0
- package/dist/utils/geogebra-instance.js.map +1 -0
- package/dist/utils/geogebra-mock.d.ts +172 -0
- package/dist/utils/geogebra-mock.d.ts.map +1 -0
- package/dist/utils/geogebra-mock.js +732 -0
- package/dist/utils/geogebra-mock.js.map +1 -0
- package/dist/utils/logger.d.ts +4 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +46 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/performance/index.d.ts +76 -0
- package/dist/utils/performance/index.d.ts.map +1 -0
- package/dist/utils/performance/index.js +163 -0
- package/dist/utils/performance/index.js.map +1 -0
- package/dist/utils/performance/instance-pool.d.ts +78 -0
- package/dist/utils/performance/instance-pool.d.ts.map +1 -0
- package/dist/utils/performance/instance-pool.js +268 -0
- package/dist/utils/performance/instance-pool.js.map +1 -0
- package/dist/utils/validation.d.ts +92 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +557 -0
- package/dist/utils/validation.js.map +1 -0
- package/dist/widget.html +110 -0
- package/docs/APPS-API-BRIDGE.md +28 -0
- package/docs/MODERNIZATION.md +15 -0
- package/docs/TANGENT-REGRESSION.md +34 -0
- package/docs/VALIDATION.md +26 -0
- package/docs/VISUAL-STANDARD.md +26 -0
- package/docs/images/native-construction.png +0 -0
- package/examples/tangent-construction.json +26 -0
- package/gikz/LICENSE +339 -0
- package/gikz/PROVENANCE.md +8 -0
- package/gikz/browser.cjs +2 -0
- package/gikz/cli.cjs +195 -0
- package/gikz/core.cjs +806 -0
- package/mcp.json +20 -0
- package/package.json +107 -4
- package/plugin.json +35 -0
- package/runtime/package.json +4 -0
- package/scripts/build-plugin.cjs +15 -0
- package/scripts/build-widget.cjs +7 -0
- package/skills/geogebra-construct/SKILL.md +40 -0
- package/skills/geogebra-setup/SKILL.md +37 -0
- package/skills/geometry-export/SKILL.md +31 -0
- package/src/cli.ts +212 -0
- package/src/export/files.ts +26 -0
- package/src/export/gikz.ts +22 -0
- package/src/export/html.ts +108 -0
- package/src/export/semantic.ts +180 -0
- package/src/export/viewer-themes.ts +165 -0
- package/src/export/workspace.ts +15 -0
- package/src/index.ts +71 -0
- package/src/server.ts +168 -0
- package/src/studio/artifact.ts +50 -0
- package/src/studio/browser.ts +38 -0
- package/src/studio/install.ts +43 -0
- package/src/tools/apps-api-tools.ts +96 -0
- package/src/tools/educational-templates.ts +299 -0
- package/src/tools/export-tools.ts +110 -0
- package/src/tools/geogebra-tools.ts +3836 -0
- package/src/tools/index.ts +192 -0
- package/src/tools/performance-tools.ts +322 -0
- package/src/tools/templates/algebra-templates.ts +619 -0
- package/src/tools/templates/geometry-templates.ts +550 -0
- package/src/types/geogebra.ts +140 -0
- package/src/types/global.d.ts +31 -0
- package/src/types/mcp.ts +141 -0
- package/src/utils/app-info.ts +35 -0
- package/src/utils/errors.ts +97 -0
- package/src/utils/gemini-compatibility.ts +193 -0
- package/src/utils/geogebra-instance.ts +1712 -0
- package/src/utils/geogebra-mock.ts +867 -0
- package/src/utils/logger.ts +60 -0
- package/src/utils/performance/index.ts +211 -0
- package/src/utils/performance/instance-pool.ts +323 -0
- package/src/utils/validation.ts +647 -0
- package/tsconfig.json +35 -0
- package/widget/main.ts +12 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { ToolDefinition } from '../types/mcp';
|
|
2
|
+
import { toolRegistry } from './index';
|
|
3
|
+
import logger from '../utils/logger';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Educational Templates for GeoGebra MCP Tool - GEB-8 Implementation
|
|
7
|
+
*
|
|
8
|
+
* Pre-built mathematical scenarios for common educational use cases:
|
|
9
|
+
* - Geometry fundamentals
|
|
10
|
+
* - Algebra visualizations
|
|
11
|
+
* - Calculus demonstrations
|
|
12
|
+
* - Statistics and probability
|
|
13
|
+
* - Mathematical proofs
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
// Check if we're in MCP mode (stdio communication)
|
|
17
|
+
// When piping input, process.stdin.isTTY is undefined, not false
|
|
18
|
+
const isMcpMode = !process.stdin.isTTY;
|
|
19
|
+
|
|
20
|
+
// Template categories
|
|
21
|
+
export type TemplateCategory = 'geometry' | 'algebra' | 'calculus' | 'statistics' | 'proofs';
|
|
22
|
+
|
|
23
|
+
// Template metadata
|
|
24
|
+
export interface EducationalTemplate {
|
|
25
|
+
id: string;
|
|
26
|
+
name: string;
|
|
27
|
+
category: TemplateCategory;
|
|
28
|
+
description: string;
|
|
29
|
+
gradeLevel: string;
|
|
30
|
+
objectives: string[];
|
|
31
|
+
prerequisites: string[];
|
|
32
|
+
estimatedTime: number; // minutes
|
|
33
|
+
setup: () => Promise<any>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Educational template registry
|
|
38
|
+
*/
|
|
39
|
+
export class EducationalTemplateRegistry {
|
|
40
|
+
private templates: Map<string, EducationalTemplate> = new Map();
|
|
41
|
+
|
|
42
|
+
register(template: EducationalTemplate): void {
|
|
43
|
+
this.templates.set(template.id, template);
|
|
44
|
+
if (!isMcpMode) {
|
|
45
|
+
logger.info(`Registered educational template: ${template.id}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
getTemplate(id: string): EducationalTemplate | undefined {
|
|
50
|
+
return this.templates.get(id);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
getTemplatesByCategory(category: TemplateCategory): EducationalTemplate[] {
|
|
54
|
+
return Array.from(this.templates.values()).filter(t => t.category === category);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
getAllTemplates(): EducationalTemplate[] {
|
|
58
|
+
return Array.from(this.templates.values());
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export const templateRegistry = new EducationalTemplateRegistry();
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Core educational template tools
|
|
66
|
+
*/
|
|
67
|
+
export const educationalTemplateTools: ToolDefinition[] = [
|
|
68
|
+
{
|
|
69
|
+
tool: {
|
|
70
|
+
name: 'geogebra_list_educational_templates',
|
|
71
|
+
description: 'List all available educational templates by category',
|
|
72
|
+
inputSchema: {
|
|
73
|
+
type: 'object',
|
|
74
|
+
properties: {
|
|
75
|
+
category: {
|
|
76
|
+
type: 'string',
|
|
77
|
+
enum: ['geometry', 'algebra', 'calculus', 'statistics', 'proofs'],
|
|
78
|
+
description: 'Filter templates by category (optional)'
|
|
79
|
+
},
|
|
80
|
+
gradeLevel: {
|
|
81
|
+
type: 'string',
|
|
82
|
+
description: 'Filter by grade level (e.g., "6-8", "9-12", "college")'
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
required: []
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
handler: async (params: Record<string, unknown>) => {
|
|
89
|
+
const { category, gradeLevel } = params;
|
|
90
|
+
|
|
91
|
+
let templates = templateRegistry.getAllTemplates();
|
|
92
|
+
|
|
93
|
+
if (category) {
|
|
94
|
+
templates = templates.filter(t => t.category === category);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (gradeLevel) {
|
|
98
|
+
templates = templates.filter(t => t.gradeLevel === gradeLevel);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const templateList = templates.map(template => ({
|
|
102
|
+
id: template.id,
|
|
103
|
+
name: template.name,
|
|
104
|
+
category: template.category,
|
|
105
|
+
description: template.description,
|
|
106
|
+
gradeLevel: template.gradeLevel,
|
|
107
|
+
estimatedTime: template.estimatedTime,
|
|
108
|
+
objectives: template.objectives
|
|
109
|
+
}));
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
content: [{
|
|
113
|
+
type: 'text' as const,
|
|
114
|
+
text: JSON.stringify({
|
|
115
|
+
success: true,
|
|
116
|
+
count: templateList.length,
|
|
117
|
+
templates: templateList
|
|
118
|
+
}, null, 2)
|
|
119
|
+
}]
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
{
|
|
125
|
+
tool: {
|
|
126
|
+
name: 'geogebra_load_educational_template',
|
|
127
|
+
description: 'Load and execute a specific educational template',
|
|
128
|
+
inputSchema: {
|
|
129
|
+
type: 'object',
|
|
130
|
+
properties: {
|
|
131
|
+
templateId: {
|
|
132
|
+
type: 'string',
|
|
133
|
+
description: 'The ID of the educational template to load'
|
|
134
|
+
},
|
|
135
|
+
customizations: {
|
|
136
|
+
type: 'object',
|
|
137
|
+
description: 'Optional customizations for the template (colors, parameters, etc.)',
|
|
138
|
+
properties: {
|
|
139
|
+
colors: {
|
|
140
|
+
type: 'object',
|
|
141
|
+
description: 'Custom color scheme'
|
|
142
|
+
},
|
|
143
|
+
parameters: {
|
|
144
|
+
type: 'object',
|
|
145
|
+
description: 'Custom parameter values'
|
|
146
|
+
},
|
|
147
|
+
showLabels: {
|
|
148
|
+
type: 'boolean',
|
|
149
|
+
description: 'Whether to show object labels'
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
required: ['templateId']
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
handler: async (params: Record<string, unknown>) => {
|
|
158
|
+
const { templateId } = params;
|
|
159
|
+
// Note: customizations parameter is accepted but not yet implemented
|
|
160
|
+
// Future enhancement: apply color schemes, parameters, and display options
|
|
161
|
+
// const customizations = params['customizations'] || {};
|
|
162
|
+
|
|
163
|
+
const template = templateRegistry.getTemplate(templateId as string);
|
|
164
|
+
if (!template) {
|
|
165
|
+
throw new Error(`Educational template not found: ${templateId}`);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
logger.info(`Loading educational template: ${template.name}`);
|
|
169
|
+
|
|
170
|
+
// Clear existing construction
|
|
171
|
+
await toolRegistry.executeTool('geogebra_clear_construction', {});
|
|
172
|
+
|
|
173
|
+
// Execute template setup
|
|
174
|
+
const result = await template.setup();
|
|
175
|
+
|
|
176
|
+
return {
|
|
177
|
+
content: [{
|
|
178
|
+
type: 'text' as const,
|
|
179
|
+
text: JSON.stringify({
|
|
180
|
+
success: true,
|
|
181
|
+
template: {
|
|
182
|
+
id: template.id,
|
|
183
|
+
name: template.name,
|
|
184
|
+
category: template.category,
|
|
185
|
+
loaded: true
|
|
186
|
+
},
|
|
187
|
+
objectives: template.objectives,
|
|
188
|
+
instructions: `Template "${template.name}" loaded successfully. Estimated time: ${template.estimatedTime} minutes.`,
|
|
189
|
+
result
|
|
190
|
+
}, null, 2)
|
|
191
|
+
}]
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
|
|
196
|
+
{
|
|
197
|
+
tool: {
|
|
198
|
+
name: 'geogebra_create_lesson_plan',
|
|
199
|
+
description: 'Generate a complete lesson plan using multiple educational templates',
|
|
200
|
+
inputSchema: {
|
|
201
|
+
type: 'object',
|
|
202
|
+
properties: {
|
|
203
|
+
topic: {
|
|
204
|
+
type: 'string',
|
|
205
|
+
description: 'The mathematical topic for the lesson'
|
|
206
|
+
},
|
|
207
|
+
gradeLevel: {
|
|
208
|
+
type: 'string',
|
|
209
|
+
description: 'Target grade level'
|
|
210
|
+
},
|
|
211
|
+
duration: {
|
|
212
|
+
type: 'number',
|
|
213
|
+
description: 'Lesson duration in minutes'
|
|
214
|
+
},
|
|
215
|
+
templateIds: {
|
|
216
|
+
type: 'array',
|
|
217
|
+
items: { type: 'string' },
|
|
218
|
+
description: 'Specific template IDs to include in the lesson'
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
required: ['topic', 'gradeLevel', 'duration']
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
handler: async (params: Record<string, unknown>) => {
|
|
225
|
+
const { topic, gradeLevel, duration, templateIds } = params;
|
|
226
|
+
|
|
227
|
+
// Auto-select templates if not specified
|
|
228
|
+
let selectedTemplates: EducationalTemplate[];
|
|
229
|
+
|
|
230
|
+
if (templateIds && Array.isArray(templateIds)) {
|
|
231
|
+
selectedTemplates = templateIds
|
|
232
|
+
.map(id => templateRegistry.getTemplate(id as string))
|
|
233
|
+
.filter(Boolean) as EducationalTemplate[];
|
|
234
|
+
} else {
|
|
235
|
+
// Auto-select based on topic and grade level
|
|
236
|
+
selectedTemplates = templateRegistry.getAllTemplates()
|
|
237
|
+
.filter(t => t.gradeLevel === gradeLevel)
|
|
238
|
+
.filter(t => t.estimatedTime <= (duration as number))
|
|
239
|
+
.reduce((chosen: EducationalTemplate[],t)=>{if(chosen.length<3&&chosen.reduce((sum,item)=>sum+item.estimatedTime,0)+t.estimatedTime<=(duration as number))chosen.push(t);return chosen;},[]);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const lessonPlan = {
|
|
243
|
+
topic,
|
|
244
|
+
gradeLevel,
|
|
245
|
+
duration,
|
|
246
|
+
templates: selectedTemplates.map(t => ({
|
|
247
|
+
id: t.id,
|
|
248
|
+
name: t.name,
|
|
249
|
+
category: t.category,
|
|
250
|
+
gradeLevel: t.gradeLevel,
|
|
251
|
+
estimatedTime: t.estimatedTime,
|
|
252
|
+
objectives: t.objectives,
|
|
253
|
+
prerequisites: t.prerequisites
|
|
254
|
+
})),
|
|
255
|
+
totalTime: selectedTemplates.reduce((sum, t) => sum + t.estimatedTime, 0),
|
|
256
|
+
structure: {
|
|
257
|
+
introduction: "5 minutes - Review prerequisites and introduce objectives",
|
|
258
|
+
activities: selectedTemplates.map((t, i) =>
|
|
259
|
+
`Activity ${i + 1}: ${t.name} (${t.estimatedTime} min) - ${t.description}`
|
|
260
|
+
),
|
|
261
|
+
conclusion: "5 minutes - Summary and assessment"
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
return {
|
|
266
|
+
content: [{
|
|
267
|
+
type: 'text' as const,
|
|
268
|
+
text: JSON.stringify(lessonPlan, null, 2)
|
|
269
|
+
}]
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
];
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Initialize and register all educational templates
|
|
277
|
+
*/
|
|
278
|
+
export function initializeEducationalTemplates(): void {
|
|
279
|
+
// Import templates from different categories
|
|
280
|
+
const { geometryTemplates } = require('./templates/geometry-templates');
|
|
281
|
+
const { algebraTemplates } = require('./templates/algebra-templates');
|
|
282
|
+
|
|
283
|
+
// Register geometry templates
|
|
284
|
+
geometryTemplates.forEach((template: EducationalTemplate) => {
|
|
285
|
+
templateRegistry.register(template);
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// Register algebra templates
|
|
289
|
+
algebraTemplates.forEach((template: EducationalTemplate) => {
|
|
290
|
+
templateRegistry.register(template);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
if (!isMcpMode) {
|
|
294
|
+
logger.info(`Registered ${templateRegistry.getAllTemplates().length} educational templates`);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Initialize templates when module is loaded
|
|
299
|
+
initializeEducationalTemplates();
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { buildArtifact } from '../studio/artifact';
|
|
2
|
+
import { HtmlOptions } from '../export/html';
|
|
3
|
+
import { ToolDefinition } from '../types/mcp';
|
|
4
|
+
import { constructionHtml } from '../export/html';
|
|
5
|
+
import { sceneFromXML, exportSource, SourceFormat } from '../export/semantic';
|
|
6
|
+
import { cleanWithGikz } from '../export/gikz';
|
|
7
|
+
import { saveText } from '../export/files';
|
|
8
|
+
import { instancePool } from './geogebra-tools';
|
|
9
|
+
|
|
10
|
+
const textResult = (value: Record<string, unknown>) => ({content:[{type:'text' as const,text:JSON.stringify(value)}],structuredContent:value});
|
|
11
|
+
const safe = (handler: ToolDefinition['handler']): ToolDefinition['handler'] => async params => {
|
|
12
|
+
try { return await handler(params); }
|
|
13
|
+
catch(e) { return {...textResult({success:false,error:e instanceof Error?e.message:String(e)}),isError:true}; }
|
|
14
|
+
};
|
|
15
|
+
const scene = async (params: Record<string, unknown>) => sceneFromXML(
|
|
16
|
+
typeof params['xml']==='string' ? params['xml'] : await (await instancePool.getDefaultInstance()).getConstructionXML()
|
|
17
|
+
);
|
|
18
|
+
/** Both named TikZ export and format=tikz use native PGF, then mandatory Gikz.
|
|
19
|
+
* Optional XML is loaded temporarily; restore the shared live construction even on failure.
|
|
20
|
+
*/
|
|
21
|
+
async function nativeCleanedTikz(p: Record<string, unknown>) {
|
|
22
|
+
const engine = await instancePool.getDefaultInstance();
|
|
23
|
+
const xml = typeof p['xml'] === 'string' ? sceneFromXML(p['xml']).xml : undefined;
|
|
24
|
+
const previous = xml ? await engine.getConstructionXML() : undefined;
|
|
25
|
+
let source: string;
|
|
26
|
+
try {
|
|
27
|
+
if (xml) await engine.callAppsApi('setXML', [xml]);
|
|
28
|
+
source = await engine.exportNativeTikZ();
|
|
29
|
+
} finally {
|
|
30
|
+
if (previous) await engine.callAppsApi('setXML', [previous]);
|
|
31
|
+
}
|
|
32
|
+
const code = await cleanWithGikz(source, {standalone: p['standalone'] !== false});
|
|
33
|
+
const saved = await saveText(p['filename'], code);
|
|
34
|
+
return textResult({success:true,format:'tikz',code,backend:'native-pgf+gikz',cleaned:true,
|
|
35
|
+
semantics:'visual-snapshot',complete:false,coordinateFallbacks:[],unsupportedObjects:[],
|
|
36
|
+
warnings:['Native PGF followed by Gikz produces a visual snapshot; construction dependencies are retained in GGB/XML, not guaranteed in TikZ.',
|
|
37
|
+
'Gikz normalizes colors, line widths, labels and coordinate precision. Inspect the printed result.'],
|
|
38
|
+
...(saved ? {filename:saved} : {}),renderVerified:false});
|
|
39
|
+
}
|
|
40
|
+
const filename = {type:'string',description:'Optional new file within workspace; existing files are not overwritten.'};
|
|
41
|
+
export const exportTools: ToolDefinition[] = [
|
|
42
|
+
{
|
|
43
|
+
tool:{name:'geogebra_build_artifact',description:'Default geometry delivery: execute ordered commands in an isolated GeoGebra engine, check visible definitions, embed a packed editable GGB into local HTML, reopen and check equal axes, and return a preview for visual review. Requires Chrome and GeoGebra network access; writes new workspace files only.',
|
|
44
|
+
_meta:{ui:{resourceUri:'ui://geogebra/preview.html'}},
|
|
45
|
+
inputSchema:{type:'object',properties:{
|
|
46
|
+
commands:{type:'array',items:{type:'string',maxLength:10000},maxItems:2000},ggbBase64:{type:'string'},
|
|
47
|
+
title:{type:'string',maxLength:500},filename:{type:'string',description:'New .html file within the workspace; a sibling .preview.png is also created.'},
|
|
48
|
+
width:{type:'integer',minimum:200,maximum:4000},height:{type:'integer',minimum:200,maximum:4000},
|
|
49
|
+
visibleLabels:{type:'array',items:{type:'string'}},captionOverrides:{type:'object',additionalProperties:{type:'string'}}
|
|
50
|
+
},required:['filename'],additionalProperties:false}},
|
|
51
|
+
handler:safe(async p=>buildArtifact(p as unknown as HtmlOptions & {filename:string})),
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
tool:{name:'geogebra_create_html',description:'Generate an unverified command-template GeoGebra HTML; prefer geogebra_build_artifact for default checked delivery. This generates an interactive GeoGebra HTML with current-state GGB, PNG, SVG, Gikz-cleaned native TikZ, PDF, XML and HTML downloads. No Chromium needed to generate; opening requires GeoGebra network access.',
|
|
55
|
+
annotations:{readOnlyHint:false,destructiveHint:false,idempotentHint:false,openWorldHint:false},
|
|
56
|
+
_meta:{ui:{resourceUri:'ui://geogebra/preview.html'}},
|
|
57
|
+
inputSchema:{type:'object',properties:{
|
|
58
|
+
title:{type:'string',maxLength:500},commands:{type:'array',items:{type:'string',maxLength:10000},maxItems:2000},
|
|
59
|
+
ggbBase64:{type:'string',description:'Optional packed GGB; commands run after loading it.'},
|
|
60
|
+
width:{type:'integer',minimum:200,maximum:4000},height:{type:'integer',minimum:200,maximum:4000},
|
|
61
|
+
visibleLabels:{type:'array',items:{type:'string'}},
|
|
62
|
+
captionOverrides:{type:'object',description:'Optional LaTeX or plain-text captions keyed by GeoGebra object name.',additionalProperties:{type:'string'}},
|
|
63
|
+
filename,
|
|
64
|
+
},additionalProperties:false}},
|
|
65
|
+
handler:safe(async p=>{
|
|
66
|
+
if(!p['commands']&&!p['ggbBase64']) throw new Error('Provide commands or ggbBase64');
|
|
67
|
+
const html=constructionHtml(p);
|
|
68
|
+
const saved=await saveText(p['filename'],html);
|
|
69
|
+
return textResult({success:true,format:'html',html,...(saved?{filename:saved}:{}),requiresNetwork:true,renderVerified:false});
|
|
70
|
+
}),
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
tool:{name:'geogebra_export_html',description:'Package the current server-side construction in an interactive HTML, preserving its GGB styling and definitions.',_meta:{ui:{resourceUri:'ui://geogebra/preview.html'}},inputSchema:{type:'object',properties:{title:{type:'string'},filename},additionalProperties:false}},
|
|
74
|
+
handler:safe(async p=>{
|
|
75
|
+
const ggbBase64=await (await instancePool.getDefaultInstance()).exportGGB();
|
|
76
|
+
const html=constructionHtml({title:typeof p['title']==='string'?p['title']:'GeoGebra construction',ggbBase64});
|
|
77
|
+
const saved=await saveText(p['filename'],html);
|
|
78
|
+
return textResult({success:true,format:'html',html,...(saved?{filename:saved}:{}),requiresNetwork:true});
|
|
79
|
+
}),
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
tool:{name:'geogebra_get_semantic_scene',description:'Read the original construction XML, command dependencies, coordinates, visibility, captions, and styles for editable export or AI-assisted reconstruction.',
|
|
83
|
+
inputSchema:{type:'object',properties:{xml:{type:'string',description:'Optional original XML; omit to inspect live GeoGebra.'}},additionalProperties:false}},
|
|
84
|
+
handler:safe(async p=>textResult({success:true,scene:await scene(p)})),
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
tool:{name:'geogebra_export_tikz',description:'Export current GeoGebra native PGF through mandatory Gikz cleanup. Returns a visual snapshot, not editable construction dependencies. No raw fallback.',
|
|
88
|
+
inputSchema:{type:'object',properties:{xml:{type:'string'},standalone:{type:'boolean',default:true},filename},additionalProperties:false}},
|
|
89
|
+
handler:safe(nativeCleanedTikz),
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
tool:{name:'geogebra_export_source',description:'TikZ always uses GeoGebra native PGF followed by mandatory Gikz cleanup (visual snapshot). Asymptote and mixed TSQX/Asymptote use the explicit semantic subset with strict validation; strict applies to those formats only.',
|
|
93
|
+
inputSchema:{type:'object',properties:{format:{type:'string',enum:['tikz','asymptote','tsqx']},xml:{type:'string'},strict:{type:'boolean',default:true},standalone:{type:'boolean',default:true},filename},required:['format'],additionalProperties:false}},
|
|
94
|
+
handler:safe(async p=>{
|
|
95
|
+
if (p['format'] === 'tikz') return nativeCleanedTikz(p);
|
|
96
|
+
const result=exportSource(await scene(p),p['format'] as SourceFormat,p['strict']!==false,p['standalone']!==false);
|
|
97
|
+
const saved=await saveText(p['filename'],result.code);
|
|
98
|
+
return textResult({success:true,...result,...(saved?{filename:saved}:{}),renderVerified:false});
|
|
99
|
+
}),
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
tool:{name:'geogebra_clean_tikz',description:'Clean native GeoGebra TikZ text or convert XML through built-in Gikz. This is visual cleanup, not a guarantee of preserved construction semantics.',
|
|
103
|
+
inputSchema:{type:'object',properties:{source:{type:'string',maxLength:10000000},standalone:{type:'boolean'},points:{type:'boolean'},labels:{type:'boolean'},round:{type:'boolean'},filename},required:['source'],additionalProperties:false}},
|
|
104
|
+
handler:safe(async p=>{
|
|
105
|
+
const code=await cleanWithGikz(p['source'] as string,p);
|
|
106
|
+
const saved=await saveText(p['filename'],code);
|
|
107
|
+
return textResult({success:true,format:'tikz',code,...(saved?{filename:saved}:{}),backend:'built-in-gikz',semantics:'not-guaranteed',renderVerified:false});
|
|
108
|
+
}),
|
|
109
|
+
},
|
|
110
|
+
];
|