@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.
Files changed (189) hide show
  1. package/.agents/plugins/marketplace.json +21 -0
  2. package/.codex-plugin/plugin.json +21 -0
  3. package/.mcp.json +18 -0
  4. package/LICENSE +339 -0
  5. package/LICENSE-MIT +21 -0
  6. package/README.md +108 -2
  7. package/README.zh-CN.md +89 -0
  8. package/THIRD_PARTY_NOTICES.md +35 -0
  9. package/dist/cli.d.ts +27 -0
  10. package/dist/cli.d.ts.map +1 -0
  11. package/dist/cli.js +234 -0
  12. package/dist/cli.js.map +1 -0
  13. package/dist/export/files.d.ts +4 -0
  14. package/dist/export/files.d.ts.map +1 -0
  15. package/dist/export/files.js +44 -0
  16. package/dist/export/files.js.map +1 -0
  17. package/dist/export/gikz.d.ts +11 -0
  18. package/dist/export/gikz.d.ts.map +1 -0
  19. package/dist/export/gikz.js +28 -0
  20. package/dist/export/gikz.js.map +1 -0
  21. package/dist/export/html.d.ts +14 -0
  22. package/dist/export/html.d.ts.map +1 -0
  23. package/dist/export/html.js +97 -0
  24. package/dist/export/html.js.map +1 -0
  25. package/dist/export/semantic.d.ts +43 -0
  26. package/dist/export/semantic.d.ts.map +1 -0
  27. package/dist/export/semantic.js +212 -0
  28. package/dist/export/semantic.js.map +1 -0
  29. package/dist/export/viewer-themes.d.ts +76 -0
  30. package/dist/export/viewer-themes.d.ts.map +1 -0
  31. package/dist/export/viewer-themes.js +169 -0
  32. package/dist/export/viewer-themes.js.map +1 -0
  33. package/dist/export/workspace.d.ts +4 -0
  34. package/dist/export/workspace.d.ts.map +1 -0
  35. package/dist/export/workspace.js +25 -0
  36. package/dist/export/workspace.js.map +1 -0
  37. package/dist/gikz-browser.js +770 -0
  38. package/dist/index.d.ts +5 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +84 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/server.d.ts +35 -0
  43. package/dist/server.d.ts.map +1 -0
  44. package/dist/server.js +187 -0
  45. package/dist/server.js.map +1 -0
  46. package/dist/studio/artifact.d.ts +37 -0
  47. package/dist/studio/artifact.d.ts.map +1 -0
  48. package/dist/studio/artifact.js +61 -0
  49. package/dist/studio/artifact.js.map +1 -0
  50. package/dist/studio/browser.d.ts +7 -0
  51. package/dist/studio/browser.d.ts.map +1 -0
  52. package/dist/studio/browser.js +67 -0
  53. package/dist/studio/browser.js.map +1 -0
  54. package/dist/studio/install.d.ts +4 -0
  55. package/dist/studio/install.d.ts.map +1 -0
  56. package/dist/studio/install.js +60 -0
  57. package/dist/studio/install.js.map +1 -0
  58. package/dist/tools/apps-api-tools.d.ts +4 -0
  59. package/dist/tools/apps-api-tools.d.ts.map +1 -0
  60. package/dist/tools/apps-api-tools.js +96 -0
  61. package/dist/tools/apps-api-tools.js.map +1 -0
  62. package/dist/tools/educational-templates.d.ts +33 -0
  63. package/dist/tools/educational-templates.d.ts.map +1 -0
  64. package/dist/tools/educational-templates.js +261 -0
  65. package/dist/tools/educational-templates.js.map +1 -0
  66. package/dist/tools/export-tools.d.ts +3 -0
  67. package/dist/tools/export-tools.d.ts.map +1 -0
  68. package/dist/tools/export-tools.js +118 -0
  69. package/dist/tools/export-tools.js.map +1 -0
  70. package/dist/tools/geogebra-tools.d.ts +15 -0
  71. package/dist/tools/geogebra-tools.d.ts.map +1 -0
  72. package/dist/tools/geogebra-tools.js +3442 -0
  73. package/dist/tools/geogebra-tools.js.map +1 -0
  74. package/dist/tools/index.d.ts +43 -0
  75. package/dist/tools/index.d.ts.map +1 -0
  76. package/dist/tools/index.js +183 -0
  77. package/dist/tools/index.js.map +1 -0
  78. package/dist/tools/performance-tools.d.ts +7 -0
  79. package/dist/tools/performance-tools.d.ts.map +1 -0
  80. package/dist/tools/performance-tools.js +312 -0
  81. package/dist/tools/performance-tools.js.map +1 -0
  82. package/dist/tools/templates/algebra-templates.d.ts +7 -0
  83. package/dist/tools/templates/algebra-templates.d.ts.map +1 -0
  84. package/dist/tools/templates/algebra-templates.js +568 -0
  85. package/dist/tools/templates/algebra-templates.js.map +1 -0
  86. package/dist/tools/templates/geometry-templates.d.ts +7 -0
  87. package/dist/tools/templates/geometry-templates.d.ts.map +1 -0
  88. package/dist/tools/templates/geometry-templates.js +492 -0
  89. package/dist/tools/templates/geometry-templates.js.map +1 -0
  90. package/dist/types/geogebra.d.ts +103 -0
  91. package/dist/types/geogebra.d.ts.map +1 -0
  92. package/dist/types/geogebra.js +34 -0
  93. package/dist/types/geogebra.js.map +1 -0
  94. package/dist/types/mcp.d.ts +125 -0
  95. package/dist/types/mcp.d.ts.map +1 -0
  96. package/dist/types/mcp.js +19 -0
  97. package/dist/types/mcp.js.map +1 -0
  98. package/dist/utils/app-info.d.ts +12 -0
  99. package/dist/utils/app-info.d.ts.map +1 -0
  100. package/dist/utils/app-info.js +30 -0
  101. package/dist/utils/app-info.js.map +1 -0
  102. package/dist/utils/errors.d.ts +37 -0
  103. package/dist/utils/errors.d.ts.map +1 -0
  104. package/dist/utils/errors.js +72 -0
  105. package/dist/utils/errors.js.map +1 -0
  106. package/dist/utils/gemini-compatibility.d.ts +39 -0
  107. package/dist/utils/gemini-compatibility.d.ts.map +1 -0
  108. package/dist/utils/gemini-compatibility.js +154 -0
  109. package/dist/utils/gemini-compatibility.js.map +1 -0
  110. package/dist/utils/geogebra-instance.d.ts +252 -0
  111. package/dist/utils/geogebra-instance.d.ts.map +1 -0
  112. package/dist/utils/geogebra-instance.js +1560 -0
  113. package/dist/utils/geogebra-instance.js.map +1 -0
  114. package/dist/utils/geogebra-mock.d.ts +172 -0
  115. package/dist/utils/geogebra-mock.d.ts.map +1 -0
  116. package/dist/utils/geogebra-mock.js +732 -0
  117. package/dist/utils/geogebra-mock.js.map +1 -0
  118. package/dist/utils/logger.d.ts +4 -0
  119. package/dist/utils/logger.d.ts.map +1 -0
  120. package/dist/utils/logger.js +46 -0
  121. package/dist/utils/logger.js.map +1 -0
  122. package/dist/utils/performance/index.d.ts +76 -0
  123. package/dist/utils/performance/index.d.ts.map +1 -0
  124. package/dist/utils/performance/index.js +163 -0
  125. package/dist/utils/performance/index.js.map +1 -0
  126. package/dist/utils/performance/instance-pool.d.ts +78 -0
  127. package/dist/utils/performance/instance-pool.d.ts.map +1 -0
  128. package/dist/utils/performance/instance-pool.js +268 -0
  129. package/dist/utils/performance/instance-pool.js.map +1 -0
  130. package/dist/utils/validation.d.ts +92 -0
  131. package/dist/utils/validation.d.ts.map +1 -0
  132. package/dist/utils/validation.js +557 -0
  133. package/dist/utils/validation.js.map +1 -0
  134. package/dist/widget.html +110 -0
  135. package/docs/APPS-API-BRIDGE.md +28 -0
  136. package/docs/MODERNIZATION.md +15 -0
  137. package/docs/TANGENT-REGRESSION.md +34 -0
  138. package/docs/VALIDATION.md +26 -0
  139. package/docs/VISUAL-STANDARD.md +26 -0
  140. package/docs/images/native-construction.png +0 -0
  141. package/examples/tangent-construction.json +26 -0
  142. package/gikz/LICENSE +339 -0
  143. package/gikz/PROVENANCE.md +8 -0
  144. package/gikz/browser.cjs +2 -0
  145. package/gikz/cli.cjs +195 -0
  146. package/gikz/core.cjs +806 -0
  147. package/mcp.json +20 -0
  148. package/package.json +107 -4
  149. package/plugin.json +35 -0
  150. package/runtime/package.json +4 -0
  151. package/scripts/build-plugin.cjs +15 -0
  152. package/scripts/build-widget.cjs +7 -0
  153. package/skills/geogebra-construct/SKILL.md +40 -0
  154. package/skills/geogebra-setup/SKILL.md +37 -0
  155. package/skills/geometry-export/SKILL.md +31 -0
  156. package/src/cli.ts +212 -0
  157. package/src/export/files.ts +26 -0
  158. package/src/export/gikz.ts +22 -0
  159. package/src/export/html.ts +108 -0
  160. package/src/export/semantic.ts +180 -0
  161. package/src/export/viewer-themes.ts +165 -0
  162. package/src/export/workspace.ts +15 -0
  163. package/src/index.ts +71 -0
  164. package/src/server.ts +168 -0
  165. package/src/studio/artifact.ts +50 -0
  166. package/src/studio/browser.ts +38 -0
  167. package/src/studio/install.ts +43 -0
  168. package/src/tools/apps-api-tools.ts +96 -0
  169. package/src/tools/educational-templates.ts +299 -0
  170. package/src/tools/export-tools.ts +110 -0
  171. package/src/tools/geogebra-tools.ts +3836 -0
  172. package/src/tools/index.ts +192 -0
  173. package/src/tools/performance-tools.ts +322 -0
  174. package/src/tools/templates/algebra-templates.ts +619 -0
  175. package/src/tools/templates/geometry-templates.ts +550 -0
  176. package/src/types/geogebra.ts +140 -0
  177. package/src/types/global.d.ts +31 -0
  178. package/src/types/mcp.ts +141 -0
  179. package/src/utils/app-info.ts +35 -0
  180. package/src/utils/errors.ts +97 -0
  181. package/src/utils/gemini-compatibility.ts +193 -0
  182. package/src/utils/geogebra-instance.ts +1712 -0
  183. package/src/utils/geogebra-mock.ts +867 -0
  184. package/src/utils/logger.ts +60 -0
  185. package/src/utils/performance/index.ts +211 -0
  186. package/src/utils/performance/instance-pool.ts +323 -0
  187. package/src/utils/validation.ts +647 -0
  188. package/tsconfig.json +35 -0
  189. package/widget/main.ts +12 -0
@@ -0,0 +1,5 @@
1
+ import 'dotenv/config';
2
+ export { McpServer } from './server';
3
+ export { toolRegistry } from './tools';
4
+ export * from './types/mcp';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AAoEvB,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,cAAc,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ var __importDefault = (this && this.__importDefault) || function (mod) {
17
+ return (mod && mod.__esModule) ? mod : { "default": mod };
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.toolRegistry = exports.McpServer = void 0;
21
+ require("dotenv/config");
22
+ const server_1 = require("./server");
23
+ const logger_1 = __importDefault(require("./utils/logger"));
24
+ const app_info_1 = require("./utils/app-info");
25
+ /**
26
+ * Main entry point for the GeoGebra Studio server
27
+ */
28
+ async function main() {
29
+ try {
30
+ const appInfo = (0, app_info_1.getAppInfo)();
31
+ // Server configuration
32
+ const config = {
33
+ name: 'GeoGebra Studio',
34
+ version: appInfo.version,
35
+ description: appInfo.description,
36
+ logLevel: process.env['LOG_LEVEL'] || 'info'
37
+ };
38
+ // Create and start the MCP server
39
+ const server = new server_1.McpServer(config);
40
+ // Set up graceful shutdown
41
+ const shutdown = async (signal) => {
42
+ logger_1.default.info(`Received ${signal}, shutting down gracefully...`);
43
+ try {
44
+ await server.stop();
45
+ process.exit(0);
46
+ }
47
+ catch (error) {
48
+ logger_1.default.error('Error during shutdown:', error);
49
+ process.exit(1);
50
+ }
51
+ };
52
+ // Handle shutdown signals
53
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
54
+ process.on('SIGINT', () => shutdown('SIGINT'));
55
+ // Handle uncaught exceptions
56
+ process.on('uncaughtException', (error) => {
57
+ logger_1.default.error('Uncaught exception:', error);
58
+ process.exit(1);
59
+ });
60
+ process.on('unhandledRejection', (reason, promise) => {
61
+ logger_1.default.error('Unhandled rejection at:', promise, 'reason:', reason);
62
+ process.exit(1);
63
+ });
64
+ // Start the server
65
+ await server.start();
66
+ }
67
+ catch (error) {
68
+ logger_1.default.error('Failed to start server:', error);
69
+ process.exit(1);
70
+ }
71
+ }
72
+ // Start the application
73
+ if (require.main === module) {
74
+ main().catch((error) => {
75
+ logger_1.default.error('Application startup failed:', error);
76
+ process.exit(1);
77
+ });
78
+ }
79
+ var server_2 = require("./server");
80
+ Object.defineProperty(exports, "McpServer", { enumerable: true, get: function () { return server_2.McpServer; } });
81
+ var tools_1 = require("./tools");
82
+ Object.defineProperty(exports, "toolRegistry", { enumerable: true, get: function () { return tools_1.toolRegistry; } });
83
+ __exportStar(require("./types/mcp"), exports);
84
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,yBAAuB;AACvB,qCAAqC;AAErC,4DAAoC;AACpC,+CAA8C;AAE9C;;GAEG;AACH,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAA,qBAAU,GAAE,CAAC;QAE7B,uBAAuB;QACvB,MAAM,MAAM,GAAoB;YAC9B,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,QAAQ,EAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAyC,IAAI,MAAM;SACtF,CAAC;QAEF,kCAAkC;QAClC,MAAM,MAAM,GAAG,IAAI,kBAAS,CAAC,MAAM,CAAC,CAAC;QAErC,2BAA2B;QAC3B,MAAM,QAAQ,GAAG,KAAK,EAAE,MAAc,EAAE,EAAE;YACxC,gBAAM,CAAC,IAAI,CAAC,YAAY,MAAM,+BAA+B,CAAC,CAAC;YAC/D,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBACpB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,gBAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;gBAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC,CAAC;QAEF,0BAA0B;QAC1B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;QACjD,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;QAE/C,6BAA6B;QAC7B,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,KAAK,EAAE,EAAE;YACxC,gBAAM,CAAC,KAAK,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;YAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;YACnD,gBAAM,CAAC,KAAK,CAAC,yBAAyB,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;YACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;QAEH,mBAAmB;QACnB,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IAEvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,gBAAM,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;QAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,wBAAwB;AACxB,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;IAC5B,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QACrB,gBAAM,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,mCAAqC;AAA5B,mGAAA,SAAS,OAAA;AAClB,iCAAuC;AAA9B,qGAAA,YAAY,OAAA;AACrB,8CAA4B"}
@@ -0,0 +1,35 @@
1
+ import { EventEmitter } from 'events';
2
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
+ import { McpServerConfig } from './types/mcp';
4
+ /** Official SDK owns framing, negotiation, notifications, and transport lifecycle. */
5
+ export declare class McpServer extends EventEmitter {
6
+ private config;
7
+ private sdk?;
8
+ private http?;
9
+ private connections;
10
+ private running;
11
+ private queue;
12
+ constructor(config: McpServerConfig);
13
+ createProtocolServer(): Server;
14
+ start(): Promise<void>;
15
+ /** Loopback-only, single-user HTTP. Deploy behind HTTPS + authentication for remote use. */
16
+ startHttp(port: number): Promise<void>;
17
+ stop(): Promise<void>;
18
+ getStatus(): {
19
+ isRunning: boolean;
20
+ toolCount: number;
21
+ uptime: number;
22
+ name: string;
23
+ version: string;
24
+ description: string;
25
+ logLevel?: "error" | "warn" | "info" | "debug";
26
+ };
27
+ getConfig(): {
28
+ name: string;
29
+ version: string;
30
+ description: string;
31
+ logLevel?: "error" | "warn" | "info" | "debug";
32
+ };
33
+ isServerRunning(): boolean;
34
+ }
35
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAMtC,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAWnE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAY9C,sFAAsF;AACtF,qBAAa,SAAU,SAAQ,YAAY;IAM7B,OAAO,CAAC,MAAM;IAL1B,OAAO,CAAC,GAAG,CAAC,CAAS;IACrB,OAAO,CAAC,IAAI,CAAC,CAAa;IAC1B,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAAuC;gBAChC,MAAM,EAAE,eAAe;IAE3C,oBAAoB,IAAI,MAAM;IA6ExB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B,4FAA4F;IACtF,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BtC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B,SAAS;;;;;;;;;IACT,SAAS;;;;;;IACT,eAAe;CAChB"}
package/dist/server.js ADDED
@@ -0,0 +1,187 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.McpServer = void 0;
7
+ const events_1 = require("events");
8
+ const fs_1 = require("fs");
9
+ const path_1 = __importDefault(require("path"));
10
+ const url_1 = require("url");
11
+ const workspace_1 = require("./export/workspace");
12
+ const http_1 = require("http");
13
+ const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
14
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
15
+ const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
16
+ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
17
+ const ajv_1 = __importDefault(require("ajv"));
18
+ const tools_1 = require("./tools");
19
+ const geogebra_tools_1 = require("./tools/geogebra-tools");
20
+ const instance_pool_1 = require("./utils/performance/instance-pool");
21
+ const guidance = 'Use geogebra_build_artifact by default to produce a checked local HTML with a packed editable GGB and preview. geogebra_create_html is an unverified command-template alternative. ' +
22
+ 'When saving files, pass workspace as the absolute user project directory; never use the installed plugin cache as the output directory. MCP roots are used when available. ' +
23
+ 'For server-side work use geogebra_eval_commands, then native exports. ' +
24
+ 'All TikZ exports use native PGF followed by Gikz; never return raw PGF as a final export. ' +
25
+ 'Use geogebra_get_semantic_scene before semantic export; report unsupported objects and coordinate fallbacks. ' +
26
+ 'Use geogebra_api_list_methods and geogebra_api_call for public Apps API methods not covered by focused tools. ' +
27
+ 'All server-side tools share one construction. Do not interleave independent diagrams.';
28
+ /** Official SDK owns framing, negotiation, notifications, and transport lifecycle. */
29
+ class McpServer extends events_1.EventEmitter {
30
+ config;
31
+ sdk;
32
+ http;
33
+ connections = new Set();
34
+ running = false;
35
+ queue = Promise.resolve();
36
+ constructor(config) {
37
+ super();
38
+ this.config = config;
39
+ }
40
+ createProtocolServer() {
41
+ const sdk = new index_js_1.Server({ name: this.config.name, version: this.config.version }, {
42
+ capabilities: { tools: {}, resources: {}, prompts: {} }, instructions: guidance,
43
+ });
44
+ const ajv = new ajv_1.default({ strict: false, allErrors: true });
45
+ const core = new Set(['geogebra_build_artifact', 'server_info', 'geogebra_eval_commands', 'geogebra_clear_construction',
46
+ 'geogebra_get_objects', 'geogebra_instance_status', 'geogebra_auto_zoom', 'geogebra_load_ggb',
47
+ 'geogebra_export_ggb', 'geogebra_export_png', 'geogebra_export_svg', 'geogebra_export_pdf',
48
+ 'geogebra_create_html', 'geogebra_export_html', 'geogebra_get_semantic_scene',
49
+ 'geogebra_export_source', 'geogebra_export_tikz', 'geogebra_clean_tikz', 'geogebra_api_list_methods', 'geogebra_api_call', 'geogebra_api_get_callback_events']);
50
+ const tools = tools_1.toolRegistry.getTools().filter(t => process.env['GEOGEBRA_TOOL_PROFILE'] !== 'core' || core.has(t.name))
51
+ .map(tool => tool.inputSchema.properties['filename'] ? { ...tool, inputSchema: { ...tool.inputSchema, properties: { ...tool.inputSchema.properties, workspace: { type: 'string', description: 'Absolute user workspace directory for saved files. Pass this when the client does not provide MCP roots; never use the plugin cache directory.' } } } } : tool)
52
+ .sort((a, b) => a.name.localeCompare(b.name));
53
+ const validators = new Map(tools.map(t => [t.name, ajv.compile(t.inputSchema)]));
54
+ sdk.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({ tools }));
55
+ sdk.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
56
+ const { name, arguments: args = {} } = request.params;
57
+ const validate = validators.get(name);
58
+ if (!validate)
59
+ throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, `Unknown tool: ${name}`);
60
+ if (!validate(args))
61
+ throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, ajv.errorsText(validate.errors));
62
+ // Queue the entire operation, including export, to avoid cross-request mutation races.
63
+ const operation = this.queue.then(async () => {
64
+ try {
65
+ let workspace = args['workspace'];
66
+ if (args['filename'] !== undefined && !workspace && sdk.getClientCapabilities()?.roots) {
67
+ const roots = await sdk.listRoots({}, { timeout: 5000 });
68
+ const folders = roots.roots.filter(root => root.uri.startsWith('file:')).map(root => (0, url_1.fileURLToPath)(root.uri));
69
+ workspace = folders.length === 1 ? folders[0] : folders.find(root => typeof args['filename'] === 'string' && path_1.default.isAbsolute(args['filename']) && args['filename'].startsWith(root + path_1.default.sep));
70
+ }
71
+ if (args['filename'] !== undefined && !workspace && process.env['GEOGEBRA_PLUGIN_RUNTIME'] === '1' && !process.env['VSCODE_WORKSPACE_FOLDER'])
72
+ throw new Error('Provide workspace as the absolute user project directory. The plugin cache is not an output workspace.');
73
+ const result = await (0, workspace_1.inWorkspace)(workspace, () => tools_1.toolRegistry.executeTool(name, args));
74
+ if (!result.structuredContent && result.content.length === 1 && result.content[0]?.text) {
75
+ try {
76
+ const value = JSON.parse(result.content[0].text);
77
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
78
+ return { ...result, structuredContent: value };
79
+ }
80
+ }
81
+ catch { /* Existing plain text tools remain valid. */ }
82
+ }
83
+ return result;
84
+ }
85
+ catch (error) {
86
+ return { content: [{ type: 'text', text: error instanceof Error ? error.message : String(error) }], isError: true };
87
+ }
88
+ });
89
+ this.queue = operation.catch(() => undefined);
90
+ return operation;
91
+ });
92
+ sdk.setRequestHandler(types_js_1.ListResourcesRequestSchema, async () => ({ resources: [{
93
+ uri: 'geogebra://guide', name: 'GeoGebra construction and export guide', mimeType: 'text/plain',
94
+ }, { uri: 'ui://geogebra/preview.html', name: 'GeoGebra preview', mimeType: 'text/html;profile=mcp-app' }] }));
95
+ sdk.setRequestHandler(types_js_1.ReadResourceRequestSchema, async (request) => {
96
+ if (request.params.uri === 'ui://geogebra/preview.html')
97
+ return { contents: [{
98
+ uri: request.params.uri, mimeType: 'text/html;profile=mcp-app',
99
+ text: (0, fs_1.readFileSync)(path_1.default.join(__dirname, 'widget.html'), 'utf8'),
100
+ _meta: { ui: { csp: {
101
+ resourceDomains: ['https://www.geogebra.org', 'https://geogebra.org', 'https://cdn.geogebra.org'],
102
+ connectDomains: ['https://www.geogebra.org', 'https://geogebra.org', 'https://cdn.geogebra.org'],
103
+ } } },
104
+ }] };
105
+ if (request.params.uri !== 'geogebra://guide')
106
+ throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, 'Unknown resource');
107
+ return { contents: [{ uri: 'geogebra://guide', mimeType: 'text/plain', text: guidance }] };
108
+ });
109
+ sdk.setRequestHandler(types_js_1.ListPromptsRequestSchema, async () => ({ prompts: [{
110
+ name: 'construct-geometry', description: 'Build an editable, print-style GeoGebra construction',
111
+ arguments: [{ name: 'problem', description: 'Geometry definitions and target exports', required: true }],
112
+ }] }));
113
+ sdk.setRequestHandler(types_js_1.GetPromptRequestSchema, async (request) => {
114
+ if (request.params.name !== 'construct-geometry' || !request.params.arguments?.['problem']) {
115
+ throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, 'construct-geometry requires problem');
116
+ }
117
+ return { messages: [{ role: 'user', content: { type: 'text',
118
+ text: `${guidance}\n\n${request.params.arguments['problem']}` } }] };
119
+ });
120
+ return sdk;
121
+ }
122
+ async start() {
123
+ if (this.running)
124
+ return;
125
+ this.sdk = this.createProtocolServer();
126
+ this.sdk.onclose = () => { if (this.running)
127
+ void this.stop(); };
128
+ await this.sdk.connect(new stdio_js_1.StdioServerTransport());
129
+ this.running = true;
130
+ this.emit('started');
131
+ }
132
+ /** Loopback-only, single-user HTTP. Deploy behind HTTPS + authentication for remote use. */
133
+ async startHttp(port) {
134
+ if (!Number.isInteger(port) || port < 1 || port > 65535)
135
+ throw new Error('Invalid HTTP port');
136
+ this.http = (0, http_1.createServer)(async (req, res) => {
137
+ if (req.url !== '/mcp') {
138
+ res.writeHead(404).end();
139
+ return;
140
+ }
141
+ if (req.headers.origin && ![`http://localhost:${port}`, `http://127.0.0.1:${port}`].includes(req.headers.origin)) {
142
+ res.writeHead(403).end('Origin forbidden');
143
+ return;
144
+ }
145
+ const host = req.headers.host;
146
+ if (!host || ![`localhost:${port}`, `127.0.0.1:${port}`].includes(host)) {
147
+ res.writeHead(403).end('Host forbidden');
148
+ return;
149
+ }
150
+ const sdk = this.createProtocolServer();
151
+ const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({ enableJsonResponse: true });
152
+ this.connections.add(sdk);
153
+ res.on('close', () => { void sdk.close(); this.connections.delete(sdk); });
154
+ try {
155
+ await sdk.connect(transport);
156
+ await transport.handleRequest(req, res);
157
+ }
158
+ catch {
159
+ if (!res.headersSent)
160
+ res.writeHead(500).end('MCP request failed');
161
+ }
162
+ });
163
+ await new Promise((resolve, reject) => {
164
+ this.http.once('error', reject);
165
+ this.http.listen(port, '127.0.0.1', resolve);
166
+ });
167
+ this.running = true;
168
+ this.emit('started');
169
+ }
170
+ async stop() {
171
+ this.running = false;
172
+ await this.queue;
173
+ await this.sdk?.close();
174
+ await Promise.all([...this.connections].map(s => s.close()));
175
+ if (this.http)
176
+ await new Promise((resolve, reject) => this.http.close(e => e ? reject(e) : resolve()));
177
+ await geogebra_tools_1.instancePool.cleanup();
178
+ await instance_pool_1.optimizedInstancePool.cleanup();
179
+ this.running = false;
180
+ this.emit('stopped');
181
+ }
182
+ getStatus() { return { ...this.config, isRunning: this.running, toolCount: tools_1.toolRegistry.getToolCount(), uptime: this.running ? process.uptime() : 0 }; }
183
+ getConfig() { return { ...this.config }; }
184
+ isServerRunning() { return this.running; }
185
+ }
186
+ exports.McpServer = McpServer;
187
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { HtmlOptions } from '../export/html';
2
+ /** Isolated native execution → packed GGB → reopen final viewer → save, never a shared pool reset. */
3
+ export declare function buildArtifact(options: HtmlOptions & {
4
+ filename: string;
5
+ }): Promise<{
6
+ content: ({
7
+ type: "text";
8
+ text: string;
9
+ mimeType?: never;
10
+ data?: never;
11
+ } | {
12
+ type: "image";
13
+ mimeType: string;
14
+ data: string;
15
+ text?: never;
16
+ })[];
17
+ structuredContent: {
18
+ success: boolean;
19
+ format: string;
20
+ filename: string;
21
+ previewFilename: string | undefined;
22
+ html: string;
23
+ engineVerified: boolean;
24
+ packedGgbVerified: boolean;
25
+ layoutChecks: {
26
+ loaded: boolean;
27
+ equalAxes: true;
28
+ viewWidth: number;
29
+ viewHeight: number;
30
+ };
31
+ renderVerified: boolean;
32
+ requiresNetwork: boolean;
33
+ objectCount: number;
34
+ note: string;
35
+ };
36
+ }>;
37
+ //# sourceMappingURL=artifact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact.d.ts","sourceRoot":"","sources":["../../src/studio/artifact.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoB,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE/D,sGAAsG;AACtG,wBAAsB,aAAa,CAAC,OAAO,EAAC,WAAW,GAAG;IAAC,QAAQ,EAAC,MAAM,CAAA;CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2C1E"}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildArtifact = buildArtifact;
4
+ const promises_1 = require("fs/promises");
5
+ const geogebra_instance_1 = require("../utils/geogebra-instance");
6
+ const html_1 = require("../export/html");
7
+ const files_1 = require("../export/files");
8
+ /** Isolated native execution → packed GGB → reopen final viewer → save, never a shared pool reset. */
9
+ async function buildArtifact(options) {
10
+ if (!/\.html$/i.test(options.filename))
11
+ throw new Error('filename must end in .html');
12
+ if (!options.ggbBase64 && !options.commands?.length)
13
+ throw new Error('Provide nonempty commands or a packed ggbBase64');
14
+ const engine = new geogebra_instance_1.GeoGebraInstance({ width: options.width || 1000, height: options.height || 800 });
15
+ let filename;
16
+ let previewFilename;
17
+ let committed = false;
18
+ try {
19
+ await engine.initialize();
20
+ await engine.renderHtml((0, html_1.constructionHtml)(options));
21
+ const checks = await engine.debugEvaluate(() => {
22
+ const api = window.ggbApplet, names = api.getAllObjectNames();
23
+ return { objects: names.length, undefinedVisibleObjects: names.filter((name) => api.getVisible(name) && !api.isDefined(name)) };
24
+ });
25
+ if (checks.undefinedVisibleObjects.length)
26
+ throw new Error('Undefined visible objects: ' + checks.undefinedVisibleObjects.join(', '));
27
+ const ggbBase64 = await engine.exportGGB();
28
+ const html = (0, html_1.constructionHtml)({ ...options, commands: [], ggbBase64 });
29
+ filename = await (0, files_1.saveText)(options.filename, html);
30
+ if (!filename)
31
+ throw new Error('Unable to save the final HTML artifact');
32
+ // Reopen the exact bytes written to disk so the preview and verification describe
33
+ // the delivered file, including its packed GGB payload.
34
+ await engine.renderHtml(await (0, promises_1.readFile)(filename, 'utf8'));
35
+ const layout = await engine.debugEvaluate(() => {
36
+ const api = window.ggbApplet, view = JSON.parse(api.getViewProperties(1));
37
+ return { ready: window.ggbReady === true, error: window.ggbError || null,
38
+ equalAxes: Math.abs(view.invXscale / view.invYscale - 1) < 1e-6, viewWidth: view.width, viewHeight: view.height };
39
+ });
40
+ if (!layout.ready || layout.error || !layout.equalAxes || layout.viewWidth <= 0 || layout.viewHeight <= 0)
41
+ throw new Error('Final HTML viewer verification failed: ' + JSON.stringify(layout));
42
+ const packedObjects = await engine.getAllObjectNames();
43
+ if (packedObjects.length !== checks.objects)
44
+ throw new Error('Packed GGB round trip changed object count');
45
+ const preview = await engine.capturePreview();
46
+ previewFilename = await (0, files_1.saveFile)(options.filename.replace(/\.html$/i, '.preview.png'), preview);
47
+ committed = true;
48
+ const data = { success: true, format: 'html', filename, previewFilename, html, engineVerified: true, packedGgbVerified: true,
49
+ layoutChecks: { loaded: true, equalAxes: layout.equalAxes, viewWidth: layout.viewWidth, viewHeight: layout.viewHeight }, renderVerified: true, requiresNetwork: true, objectCount: checks.objects,
50
+ note: 'Native execution, saved HTML reopen, packed GGB, equal axes and preview capture passed. Inspect the attached preview for visual quality.' };
51
+ return { content: [{ type: 'text', text: JSON.stringify(data) }, { type: 'image', mimeType: 'image/png', data: Buffer.from(preview).toString('base64') }], structuredContent: data };
52
+ }
53
+ finally {
54
+ if (!committed && previewFilename)
55
+ await (0, promises_1.unlink)(previewFilename);
56
+ if (!committed && filename)
57
+ await (0, promises_1.unlink)(filename);
58
+ await engine.cleanup();
59
+ }
60
+ }
61
+ //# sourceMappingURL=artifact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact.js","sourceRoot":"","sources":["../../src/studio/artifact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export declare const browserCache: () => string;
2
+ export declare const managedBrowserPath: () => string;
3
+ export declare function browserCandidates(): string[];
4
+ /** Runtime lookup is cheap; installation/doctor additionally probes launch compatibility. */
5
+ export declare function resolveBrowser(): string;
6
+ export declare function prepareBrowser(download?: boolean): Promise<string>;
7
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/studio/browser.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,YAAY,cAAwH,CAAC;AAClJ,eAAO,MAAM,kBAAkB,cAAmH,CAAC;AACnJ,wBAAgB,iBAAiB,IAAI,MAAM,EAAE,CAS5C;AACD,6FAA6F;AAC7F,wBAAgB,cAAc,IAAI,MAAM,CAKvC;AAED,wBAAsB,cAAc,CAAC,QAAQ,UAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAUpE"}
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.managedBrowserPath = exports.browserCache = void 0;
7
+ exports.browserCandidates = browserCandidates;
8
+ exports.resolveBrowser = resolveBrowser;
9
+ exports.prepareBrowser = prepareBrowser;
10
+ const path_1 = __importDefault(require("path"));
11
+ const os_1 = __importDefault(require("os"));
12
+ const fs_1 = require("fs");
13
+ const promises_1 = require("fs/promises");
14
+ const puppeteer_core_1 = __importDefault(require("puppeteer-core"));
15
+ const { PUPPETEER_REVISIONS } = require('puppeteer-core');
16
+ const browsers_1 = require("@puppeteer/browsers");
17
+ const browserCache = () => path_1.default.join(process.env['GEOGEBRA_STUDIO_HOME'] || path_1.default.join(os_1.default.homedir(), '.cache', 'geogebra-studio'), 'browsers');
18
+ exports.browserCache = browserCache;
19
+ const managedBrowserPath = () => (0, browsers_1.computeExecutablePath)({ cacheDir: (0, exports.browserCache)(), browser: browsers_1.Browser.CHROME, buildId: PUPPETEER_REVISIONS.chrome });
20
+ exports.managedBrowserPath = managedBrowserPath;
21
+ function browserCandidates() {
22
+ const explicit = process.env['PUPPETEER_EXECUTABLE_PATH'];
23
+ if (explicit)
24
+ return [explicit];
25
+ return [
26
+ ...(process.platform === 'darwin' ? ['/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', path_1.default.join(os_1.default.homedir(), 'Applications/Google Chrome.app/Contents/MacOS/Google Chrome')] : []),
27
+ ...(process.platform === 'win32' ? [process.env['PROGRAMFILES'], process.env['PROGRAMFILES(X86)'], process.env['LOCALAPPDATA']].filter((v) => !!v).map(v => path_1.default.join(v, 'Google', 'Chrome', 'Application', 'chrome.exe')) : []),
28
+ ...(process.platform === 'linux' ? ['/usr/bin/google-chrome', '/usr/bin/google-chrome-stable', '/usr/bin/chromium', '/usr/bin/chromium-browser'] : []),
29
+ (0, exports.managedBrowserPath)(),
30
+ ].filter((value, index, all) => all.indexOf(value) === index);
31
+ }
32
+ /** Runtime lookup is cheap; installation/doctor additionally probes launch compatibility. */
33
+ function resolveBrowser() {
34
+ if (!process.env['PUPPETEER_EXECUTABLE_PATH']) {
35
+ try {
36
+ const selected = (0, fs_1.readFileSync)(path_1.default.join((0, exports.browserCache)(), 'selected.txt'), 'utf8').trim();
37
+ if ((0, fs_1.existsSync)(selected))
38
+ return selected;
39
+ }
40
+ catch { /* No prepared runtime yet. */ }
41
+ }
42
+ const executable = browserCandidates().find(file => (0, fs_1.existsSync)(file));
43
+ if (!executable)
44
+ throw new Error('Chrome is unavailable. Run: npx @lydt/geogebra-studio browser install');
45
+ return executable;
46
+ }
47
+ async function rememberBrowser(file) { await (0, promises_1.mkdir)((0, exports.browserCache)(), { recursive: true }); await (0, promises_1.writeFile)(path_1.default.join((0, exports.browserCache)(), 'selected.txt'), file, 'utf8'); return file; }
48
+ async function prepareBrowser(download = false) {
49
+ const failures = [];
50
+ for (const file of browserCandidates().filter(file => (0, fs_1.existsSync)(file))) {
51
+ try {
52
+ const browser = await puppeteer_core_1.default.launch({ executablePath: file, headless: true, timeout: 15000 });
53
+ await browser.close();
54
+ return rememberBrowser(file);
55
+ }
56
+ catch (error) {
57
+ failures.push(`${file}: ${error instanceof Error ? error.message : String(error)}`);
58
+ }
59
+ }
60
+ if (!download)
61
+ throw new Error('No usable Chrome. Run: npx @lydt/geogebra-studio browser install. ' + failures.join('; '));
62
+ const installed = await (0, browsers_1.install)({ browser: browsers_1.Browser.CHROME, buildId: PUPPETEER_REVISIONS.chrome, cacheDir: (0, exports.browserCache)() });
63
+ const browser = await puppeteer_core_1.default.launch({ executablePath: installed.executablePath, headless: true, timeout: 15000 });
64
+ await browser.close();
65
+ return rememberBrowser(installed.executablePath);
66
+ }
67
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/studio/browser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function run(command: string, args: string[], cwd?: string): Promise<void>;
2
+ /** A persistent catalog uses an npm source, never the temporary npx package directory. */
3
+ export declare function installPlugin(local?: boolean): Promise<void>;
4
+ //# sourceMappingURL=install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/studio/install.ts"],"names":[],"mappings":"AAKA,wBAAsB,GAAG,CAAC,OAAO,EAAC,MAAM,EAAC,IAAI,EAAC,MAAM,EAAE,EAAC,GAAG,CAAC,EAAC,MAAM,GAAE,OAAO,CAAC,IAAI,CAAC,CAKhF;AACD,0FAA0F;AAC1F,wBAAsB,aAAa,CAAC,KAAK,UAAM,GAAE,OAAO,CAAC,IAAI,CAAC,CA8B7D"}
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.run = run;
7
+ exports.installPlugin = installPlugin;
8
+ const path_1 = __importDefault(require("path"));
9
+ const os_1 = __importDefault(require("os"));
10
+ const promises_1 = require("fs/promises");
11
+ const child_process_1 = require("child_process");
12
+ const browser_1 = require("./browser");
13
+ async function run(command, args, cwd) {
14
+ await new Promise((resolve, reject) => {
15
+ const child = (0, child_process_1.spawn)(command, args, { stdio: 'inherit', shell: false, ...(cwd ? { cwd } : {}) });
16
+ child.once('error', reject);
17
+ child.once('close', code => code === 0 ? resolve() : reject(new Error(`${command} exited with ${code}`)));
18
+ });
19
+ }
20
+ /** A persistent catalog uses an npm source, never the temporary npx package directory. */
21
+ async function installPlugin(local = false) {
22
+ const metadata = JSON.parse(await (0, promises_1.readFile)(path_1.default.join(__dirname, '../../package.json'), 'utf8'));
23
+ const home = process.env['CODEX_HOME'] || path_1.default.join(os_1.default.homedir(), '.codex');
24
+ const root = path_1.default.join(home, 'geogebra-studio', 'marketplace');
25
+ await (0, promises_1.mkdir)(path_1.default.join(root, '.agents', 'plugins'), { recursive: true });
26
+ let source = { source: 'npm', package: metadata.name, version: metadata.version };
27
+ if (local) {
28
+ // Explicit authoring mode copies release files to a stable location and installs runtime deps.
29
+ const target = path_1.default.join(root, 'plugin');
30
+ try {
31
+ await (0, promises_1.access)(path_1.default.join(target, 'package.json'));
32
+ throw new Error(`Local package already exists: ${target}. Use a fresh CODEX_HOME for a clean test.`);
33
+ }
34
+ catch (error) {
35
+ if (error.code !== 'ENOENT')
36
+ throw error;
37
+ }
38
+ await (0, promises_1.mkdir)(target, { recursive: true });
39
+ const packageRoot = path_1.default.join(__dirname, '../..');
40
+ for (const entry of ['dist', 'runtime', 'gikz', 'skills', 'docs', 'plugin.json', 'mcp.json', '.codex-plugin', '.mcp.json', 'package.json', 'LICENSE', 'LICENSE-MIT', 'THIRD_PARTY_NOTICES.md'])
41
+ await (0, promises_1.cp)(path_1.default.join(packageRoot, entry), path_1.default.join(target, entry), { recursive: true });
42
+ const localPackagePath = path_1.default.join(target, 'package.json');
43
+ const localPackage = JSON.parse(await (0, promises_1.readFile)(localPackagePath, 'utf8'));
44
+ delete localPackage.devDependencies;
45
+ await (0, promises_1.writeFile)(localPackagePath, JSON.stringify(localPackage, null, 2) + '\n');
46
+ await run(process.platform === 'win32' ? 'npm.cmd' : 'npm', ['install', '--omit=dev', '--ignore-scripts', '--no-audit', '--no-fund'], target);
47
+ // Authoring mode tests the CLI installed at this stable path. Keep its command
48
+ // portable and resolve the entry point from the plugin root.
49
+ const localServer = { command: 'node', args: ['dist/cli.js', 'mcp'], cwd: './', env: { GEOGEBRA_TOOL_PROFILE: 'core', GEOGEBRA_PLUGIN_RUNTIME: '1' } };
50
+ await (0, promises_1.writeFile)(path_1.default.join(target, 'mcp.json'), JSON.stringify({ $schema: 'https://agent-plugins.org/schemas/1.0.0/mcp.schema.json', mcpServers: { geogebra: { type: 'stdio', ...localServer } } }, null, 2) + '\n');
51
+ await (0, promises_1.writeFile)(path_1.default.join(target, '.mcp.json'), JSON.stringify({ mcpServers: { geogebra: localServer } }, null, 2) + '\n');
52
+ source = { source: 'local', path: './plugin' };
53
+ }
54
+ await (0, promises_1.writeFile)(path_1.default.join(root, '.agents/plugins/marketplace.json'), JSON.stringify({ name: 'geogebra-studio', interface: { displayName: 'GeoGebra Studio' }, plugins: [{ name: 'geogebra-studio', source, policy: { installation: 'AVAILABLE', authentication: 'ON_INSTALL' }, category: 'Education' }] }, null, 2) + '\n');
55
+ await run('codex', ['plugin', 'marketplace', 'add', root]);
56
+ await run('codex', ['plugin', 'add', 'geogebra-studio@geogebra-studio']);
57
+ const executable = await (0, browser_1.prepareBrowser)(true);
58
+ console.log(`GeoGebra Studio ${metadata.version} installed. Browser: ${executable}\nStart a new Codex session and invoke @geogebra-studio. Existing geogebra-geometry installations were not removed.`);
59
+ }
60
+ //# sourceMappingURL=install.js.map