@pie-players/pie-assessment-toolkit 0.3.56 → 0.3.57

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.
@@ -6099,7 +6099,7 @@ class DesmosToolProvider {
6099
6099
  providerId = "desmos-calculator";
6100
6100
  providerName = "Desmos Calculator";
6101
6101
  category = "calculator";
6102
- version = "1.10";
6102
+ version = "1.12";
6103
6103
  requiresAuth = true;
6104
6104
  desmosProvider = null;
6105
6105
  config = null;
@@ -17956,7 +17956,7 @@ class DesmosToolProvider {
17956
17956
  providerId = "desmos-calculator";
17957
17957
  providerName = "Desmos Calculator";
17958
17958
  category = "calculator";
17959
- version = "1.10";
17959
+ version = "1.12";
17960
17960
  requiresAuth = true;
17961
17961
  desmosProvider = null;
17962
17962
  config = null;
@@ -10294,7 +10294,7 @@ class DesmosToolProvider {
10294
10294
  providerId = "desmos-calculator";
10295
10295
  providerName = "Desmos Calculator";
10296
10296
  category = "calculator";
10297
- version = "1.10";
10297
+ version = "1.12";
10298
10298
  requiresAuth = true;
10299
10299
  desmosProvider = null;
10300
10300
  config = null;
@@ -62,7 +62,7 @@ export declare class DesmosToolProvider implements ToolProviderApi<DesmosToolPro
62
62
  readonly providerId = "desmos-calculator";
63
63
  readonly providerName = "Desmos Calculator";
64
64
  readonly category: "calculator";
65
- readonly version = "1.10";
65
+ readonly version = "1.12";
66
66
  readonly requiresAuth = true;
67
67
  private desmosProvider;
68
68
  private config;
@@ -32,7 +32,7 @@ export class DesmosToolProvider {
32
32
  providerId = "desmos-calculator";
33
33
  providerName = "Desmos Calculator";
34
34
  category = "calculator";
35
- version = "1.10";
35
+ version = "1.12";
36
36
  requiresAuth = true;
37
37
  desmosProvider = null;
38
38
  config = null;
@@ -1 +1 @@
1
- {"version":3,"file":"DesmosToolProvider.js","sourceRoot":"","sources":["../../../src/services/tool-providers/DesmosToolProvider.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Desmos Calculator Tool Provider\n *\n * Provides Desmos calculators (basic, scientific, graphing)\n * with authentication and proxy support.\n *\n * SECURITY BEST PRACTICE:\n * - Development: Pass apiKey directly for local testing\n * - Production: Use proxyEndpoint or authFetcher to keep API key server-side\n *\n * Part of PIE Assessment Toolkit.\n */\n\nimport type {\n\tCalculatorProvider,\n\tDesmosCalculatorConfig,\n} from \"@pie-players/pie-calculator\";\nimport type {\n\tToolProviderApi,\n\tToolProviderCapabilities,\n} from \"./ToolProviderApi.js\";\n\n/**\n * Desmos tool provider configuration\n */\nexport interface DesmosToolProviderConfig {\n\t/**\n\t * Desmos API key (DEVELOPMENT ONLY)\n\t * Never expose in production client code!\n\t *\n\t * Obtain from: https://www.desmos.com/api\n\t */\n\tapiKey?: string;\n\n\t/**\n\t * Server proxy endpoint (PRODUCTION RECOMMENDED)\n\t * Backend handles API key securely\n\t *\n\t * @example '/api/desmos/token'\n\t * @example 'https://api.myapp.com/tools/desmos/auth'\n\t */\n\tproxyEndpoint?: string;\n\n\t/**\n\t * Default calculator configuration applied to all instances\n\t */\n\tdefaultConfig?: DesmosCalculatorConfig;\n\n\t/**\n\t * Optional telemetry callback for tool/backend instrumentation.\n\t */\n\tonTelemetry?: (\n\t\teventName: string,\n\t\tpayload?: Record<string, unknown>,\n\t) => void | Promise<void>;\n}\n\n/**\n * Desmos Calculator Tool Provider\n *\n * Wraps DesmosCalculatorProvider with the ToolProviderApi interface\n * for use in the ToolProviderRegistry.\n *\n * @example\n * ```typescript\n * const provider = new DesmosToolProvider();\n *\n * await provider.initialize({\n * apiKey: 'your-api-key', // Development only\n * proxyEndpoint: '/api/desmos/token', // Production\n * });\n *\n * const calculatorProvider = await provider.createInstance();\n * ```\n */\nexport class DesmosToolProvider\n\timplements ToolProviderApi<DesmosToolProviderConfig, CalculatorProvider>\n{\n\treadonly providerId = \"desmos-calculator\";\n\treadonly providerName = \"Desmos Calculator\";\n\treadonly category = \"calculator\" as const;\n\treadonly version = \"1.10\";\n\treadonly requiresAuth = true;\n\n\tprivate desmosProvider:\n\t\t| (CalculatorProvider & {\n\t\t\t\tinitialize(config: {\n\t\t\t\t\tapiKey?: string;\n\t\t\t\t\tproxyEndpoint?: string;\n\t\t\t\t\tonTelemetry?: (\n\t\t\t\t\t\teventName: string,\n\t\t\t\t\t\tpayload?: Record<string, unknown>,\n\t\t\t\t\t) => void | Promise<void>;\n\t\t\t\t}): Promise<void>;\n\t\t })\n\t\t| null = null;\n\tprivate config: DesmosToolProviderConfig | null = null;\n\n\tprivate async emitTelemetry(\n\t\teventName: string,\n\t\tpayload?: Record<string, unknown>,\n\t): Promise<void> {\n\t\ttry {\n\t\t\tawait this.config?.onTelemetry?.(eventName, payload);\n\t\t} catch (error) {\n\t\t\tconsole.warn(\"[DesmosToolProvider] telemetry callback failed:\", error);\n\t\t}\n\t}\n\n\t/**\n\t * Initialize Desmos calculator provider\n\t *\n\t * Loads the Desmos API library and authenticates with provided credentials.\n\t *\n\t * @param config Configuration with API key or proxy endpoint\n\t * @throws Error if initialization fails\n\t */\n\tasync initialize(config: DesmosToolProviderConfig): Promise<void> {\n\t\tif (this.desmosProvider) {\n\t\t\tconsole.warn(\n\t\t\t\t\"[DesmosToolProvider] Already initialized, skipping reinitialization\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.config = config;\n\t\tconst moduleLoadStartedAt = Date.now();\n\t\tawait this.emitTelemetry(\"pie-tool-library-load-start\", {\n\t\t\ttoolId: \"calculator\",\n\t\t\toperation: \"desmos-provider-module-import\",\n\t\t\tbackend: \"desmos\",\n\t\t});\n\t\tconst desmosModule = await (async () => {\n\t\t\ttry {\n\t\t\t\tconst loaded = (await import(\"@pie-players/pie-calculator-desmos\")) as {\n\t\t\t\t\tDesmosCalculatorProvider: new () => CalculatorProvider & {\n\t\t\t\t\t\tinitialize(config: {\n\t\t\t\t\t\t\tapiKey?: string;\n\t\t\t\t\t\t\tproxyEndpoint?: string;\n\t\t\t\t\t\t\tonTelemetry?: (\n\t\t\t\t\t\t\t\teventName: string,\n\t\t\t\t\t\t\t\tpayload?: Record<string, unknown>,\n\t\t\t\t\t\t\t) => void | Promise<void>;\n\t\t\t\t\t\t}): Promise<void>;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t\tawait this.emitTelemetry(\"pie-tool-library-load-success\", {\n\t\t\t\t\ttoolId: \"calculator\",\n\t\t\t\t\toperation: \"desmos-provider-module-import\",\n\t\t\t\t\tbackend: \"desmos\",\n\t\t\t\t\tduration: Date.now() - moduleLoadStartedAt,\n\t\t\t\t});\n\t\t\t\treturn loaded;\n\t\t\t} catch (error) {\n\t\t\t\tawait this.emitTelemetry(\"pie-tool-library-load-error\", {\n\t\t\t\t\ttoolId: \"calculator\",\n\t\t\t\t\toperation: \"desmos-provider-module-import\",\n\t\t\t\t\tbackend: \"desmos\",\n\t\t\t\t\tduration: Date.now() - moduleLoadStartedAt,\n\t\t\t\t\terrorType: \"ToolLibraryLoadError\",\n\t\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t\t});\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t})();\n\t\tthis.desmosProvider = new desmosModule.DesmosCalculatorProvider();\n\n\t\t// Initialize with API key or proxy\n\t\ttry {\n\t\t\tawait this.desmosProvider.initialize({\n\t\t\t\tapiKey: config.apiKey,\n\t\t\t\tproxyEndpoint: config.proxyEndpoint,\n\t\t\t\tonTelemetry: config.onTelemetry,\n\t\t\t});\n\n\t\t\tconsole.log(\n\t\t\t\t`[DesmosToolProvider] Initialized successfully ${\n\t\t\t\t\tconfig.proxyEndpoint\n\t\t\t\t\t\t? \"(using proxy)\"\n\t\t\t\t\t\t: config.apiKey\n\t\t\t\t\t\t\t? \"(direct API key)\"\n\t\t\t\t\t\t\t: \"(no auth)\"\n\t\t\t\t}`,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tconsole.error(\"[DesmosToolProvider] Initialization failed:\", error);\n\t\t\tthrow new Error(\n\t\t\t\t\"Failed to initialize Desmos calculator provider. Check API key or proxy endpoint.\",\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Create a calculator provider instance\n\t *\n\t * Returns the initialized Desmos calculator provider.\n\t *\n\t * @param config Optional instance-specific configuration (currently unused)\n\t * @returns Desmos calculator provider\n\t * @throws Error if provider not initialized\n\t */\n\tasync createInstance(\n\t\tconfig?: Partial<DesmosToolProviderConfig>,\n\t): Promise<CalculatorProvider> {\n\t\tif (!this.desmosProvider) {\n\t\t\tthrow new Error(\n\t\t\t\t\"[DesmosToolProvider] Provider not initialized. Call initialize() first.\",\n\t\t\t);\n\t\t}\n\n\t\treturn this.desmosProvider;\n\t}\n\n\t/**\n\t * Get provider capabilities\n\t *\n\t * @returns Desmos calculator capabilities\n\t */\n\tgetCapabilities(): ToolProviderCapabilities {\n\t\treturn {\n\t\t\tsupportsOffline: false, // Requires Desmos CDN\n\t\t\trequiresAuth: true,\n\t\t\tmaxInstances: null, // Unlimited calculator instances\n\t\t\tfeatures: {\n\t\t\t\tbasic: true,\n\t\t\t\tscientific: true,\n\t\t\t\tgraphing: true,\n\t\t\t\tfourFunction: true,\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * Check if provider is ready\n\t *\n\t * @returns true if provider is initialized\n\t */\n\tisReady(): boolean {\n\t\treturn this.desmosProvider !== null;\n\t}\n\n\t/**\n\t * Clean up provider resources\n\t *\n\t * Destroys the Desmos calculator provider and releases resources.\n\t */\n\tdestroy(): void {\n\t\tif (this.desmosProvider) {\n\t\t\tthis.desmosProvider.destroy();\n\t\t\tthis.desmosProvider = null;\n\t\t}\n\t\tthis.config = null;\n\t\tconsole.log(\"[DesmosToolProvider] Destroyed\");\n\t}\n}\n"]}
1
+ {"version":3,"file":"DesmosToolProvider.js","sourceRoot":"","sources":["../../../src/services/tool-providers/DesmosToolProvider.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Desmos Calculator Tool Provider\n *\n * Provides Desmos calculators (basic, scientific, graphing)\n * with authentication and proxy support.\n *\n * SECURITY BEST PRACTICE:\n * - Development: Pass apiKey directly for local testing\n * - Production: Use proxyEndpoint or authFetcher to keep API key server-side\n *\n * Part of PIE Assessment Toolkit.\n */\n\nimport type {\n\tCalculatorProvider,\n\tDesmosCalculatorConfig,\n} from \"@pie-players/pie-calculator\";\nimport type {\n\tToolProviderApi,\n\tToolProviderCapabilities,\n} from \"./ToolProviderApi.js\";\n\n/**\n * Desmos tool provider configuration\n */\nexport interface DesmosToolProviderConfig {\n\t/**\n\t * Desmos API key (DEVELOPMENT ONLY)\n\t * Never expose in production client code!\n\t *\n\t * Obtain from: https://www.desmos.com/api\n\t */\n\tapiKey?: string;\n\n\t/**\n\t * Server proxy endpoint (PRODUCTION RECOMMENDED)\n\t * Backend handles API key securely\n\t *\n\t * @example '/api/desmos/token'\n\t * @example 'https://api.myapp.com/tools/desmos/auth'\n\t */\n\tproxyEndpoint?: string;\n\n\t/**\n\t * Default calculator configuration applied to all instances\n\t */\n\tdefaultConfig?: DesmosCalculatorConfig;\n\n\t/**\n\t * Optional telemetry callback for tool/backend instrumentation.\n\t */\n\tonTelemetry?: (\n\t\teventName: string,\n\t\tpayload?: Record<string, unknown>,\n\t) => void | Promise<void>;\n}\n\n/**\n * Desmos Calculator Tool Provider\n *\n * Wraps DesmosCalculatorProvider with the ToolProviderApi interface\n * for use in the ToolProviderRegistry.\n *\n * @example\n * ```typescript\n * const provider = new DesmosToolProvider();\n *\n * await provider.initialize({\n * apiKey: 'your-api-key', // Development only\n * proxyEndpoint: '/api/desmos/token', // Production\n * });\n *\n * const calculatorProvider = await provider.createInstance();\n * ```\n */\nexport class DesmosToolProvider\n\timplements ToolProviderApi<DesmosToolProviderConfig, CalculatorProvider>\n{\n\treadonly providerId = \"desmos-calculator\";\n\treadonly providerName = \"Desmos Calculator\";\n\treadonly category = \"calculator\" as const;\n\treadonly version = \"1.12\";\n\treadonly requiresAuth = true;\n\n\tprivate desmosProvider:\n\t\t| (CalculatorProvider & {\n\t\t\t\tinitialize(config: {\n\t\t\t\t\tapiKey?: string;\n\t\t\t\t\tproxyEndpoint?: string;\n\t\t\t\t\tonTelemetry?: (\n\t\t\t\t\t\teventName: string,\n\t\t\t\t\t\tpayload?: Record<string, unknown>,\n\t\t\t\t\t) => void | Promise<void>;\n\t\t\t\t}): Promise<void>;\n\t\t })\n\t\t| null = null;\n\tprivate config: DesmosToolProviderConfig | null = null;\n\n\tprivate async emitTelemetry(\n\t\teventName: string,\n\t\tpayload?: Record<string, unknown>,\n\t): Promise<void> {\n\t\ttry {\n\t\t\tawait this.config?.onTelemetry?.(eventName, payload);\n\t\t} catch (error) {\n\t\t\tconsole.warn(\"[DesmosToolProvider] telemetry callback failed:\", error);\n\t\t}\n\t}\n\n\t/**\n\t * Initialize Desmos calculator provider\n\t *\n\t * Loads the Desmos API library and authenticates with provided credentials.\n\t *\n\t * @param config Configuration with API key or proxy endpoint\n\t * @throws Error if initialization fails\n\t */\n\tasync initialize(config: DesmosToolProviderConfig): Promise<void> {\n\t\tif (this.desmosProvider) {\n\t\t\tconsole.warn(\n\t\t\t\t\"[DesmosToolProvider] Already initialized, skipping reinitialization\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.config = config;\n\t\tconst moduleLoadStartedAt = Date.now();\n\t\tawait this.emitTelemetry(\"pie-tool-library-load-start\", {\n\t\t\ttoolId: \"calculator\",\n\t\t\toperation: \"desmos-provider-module-import\",\n\t\t\tbackend: \"desmos\",\n\t\t});\n\t\tconst desmosModule = await (async () => {\n\t\t\ttry {\n\t\t\t\tconst loaded = (await import(\"@pie-players/pie-calculator-desmos\")) as {\n\t\t\t\t\tDesmosCalculatorProvider: new () => CalculatorProvider & {\n\t\t\t\t\t\tinitialize(config: {\n\t\t\t\t\t\t\tapiKey?: string;\n\t\t\t\t\t\t\tproxyEndpoint?: string;\n\t\t\t\t\t\t\tonTelemetry?: (\n\t\t\t\t\t\t\t\teventName: string,\n\t\t\t\t\t\t\t\tpayload?: Record<string, unknown>,\n\t\t\t\t\t\t\t) => void | Promise<void>;\n\t\t\t\t\t\t}): Promise<void>;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t\tawait this.emitTelemetry(\"pie-tool-library-load-success\", {\n\t\t\t\t\ttoolId: \"calculator\",\n\t\t\t\t\toperation: \"desmos-provider-module-import\",\n\t\t\t\t\tbackend: \"desmos\",\n\t\t\t\t\tduration: Date.now() - moduleLoadStartedAt,\n\t\t\t\t});\n\t\t\t\treturn loaded;\n\t\t\t} catch (error) {\n\t\t\t\tawait this.emitTelemetry(\"pie-tool-library-load-error\", {\n\t\t\t\t\ttoolId: \"calculator\",\n\t\t\t\t\toperation: \"desmos-provider-module-import\",\n\t\t\t\t\tbackend: \"desmos\",\n\t\t\t\t\tduration: Date.now() - moduleLoadStartedAt,\n\t\t\t\t\terrorType: \"ToolLibraryLoadError\",\n\t\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t\t});\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t})();\n\t\tthis.desmosProvider = new desmosModule.DesmosCalculatorProvider();\n\n\t\t// Initialize with API key or proxy\n\t\ttry {\n\t\t\tawait this.desmosProvider.initialize({\n\t\t\t\tapiKey: config.apiKey,\n\t\t\t\tproxyEndpoint: config.proxyEndpoint,\n\t\t\t\tonTelemetry: config.onTelemetry,\n\t\t\t});\n\n\t\t\tconsole.log(\n\t\t\t\t`[DesmosToolProvider] Initialized successfully ${\n\t\t\t\t\tconfig.proxyEndpoint\n\t\t\t\t\t\t? \"(using proxy)\"\n\t\t\t\t\t\t: config.apiKey\n\t\t\t\t\t\t\t? \"(direct API key)\"\n\t\t\t\t\t\t\t: \"(no auth)\"\n\t\t\t\t}`,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tconsole.error(\"[DesmosToolProvider] Initialization failed:\", error);\n\t\t\tthrow new Error(\n\t\t\t\t\"Failed to initialize Desmos calculator provider. Check API key or proxy endpoint.\",\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Create a calculator provider instance\n\t *\n\t * Returns the initialized Desmos calculator provider.\n\t *\n\t * @param config Optional instance-specific configuration (currently unused)\n\t * @returns Desmos calculator provider\n\t * @throws Error if provider not initialized\n\t */\n\tasync createInstance(\n\t\tconfig?: Partial<DesmosToolProviderConfig>,\n\t): Promise<CalculatorProvider> {\n\t\tif (!this.desmosProvider) {\n\t\t\tthrow new Error(\n\t\t\t\t\"[DesmosToolProvider] Provider not initialized. Call initialize() first.\",\n\t\t\t);\n\t\t}\n\n\t\treturn this.desmosProvider;\n\t}\n\n\t/**\n\t * Get provider capabilities\n\t *\n\t * @returns Desmos calculator capabilities\n\t */\n\tgetCapabilities(): ToolProviderCapabilities {\n\t\treturn {\n\t\t\tsupportsOffline: false, // Requires Desmos CDN\n\t\t\trequiresAuth: true,\n\t\t\tmaxInstances: null, // Unlimited calculator instances\n\t\t\tfeatures: {\n\t\t\t\tbasic: true,\n\t\t\t\tscientific: true,\n\t\t\t\tgraphing: true,\n\t\t\t\tfourFunction: true,\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * Check if provider is ready\n\t *\n\t * @returns true if provider is initialized\n\t */\n\tisReady(): boolean {\n\t\treturn this.desmosProvider !== null;\n\t}\n\n\t/**\n\t * Clean up provider resources\n\t *\n\t * Destroys the Desmos calculator provider and releases resources.\n\t */\n\tdestroy(): void {\n\t\tif (this.desmosProvider) {\n\t\t\tthis.desmosProvider.destroy();\n\t\t\tthis.desmosProvider = null;\n\t\t}\n\t\tthis.config = null;\n\t\tconsole.log(\"[DesmosToolProvider] Destroyed\");\n\t}\n}\n"]}
@@ -3,7 +3,7 @@
3
3
  * Implementation of CalculatorProvider for Desmos calculators
4
4
  *
5
5
  * Supports: Basic, Scientific, and Graphing calculators
6
- * Based on Desmos API v1.10+
6
+ * Based on Desmos API v1.12+
7
7
  */
8
8
  import type { Calculator, CalculatorProvider, CalculatorProviderCapabilities, CalculatorProviderConfig, CalculatorType } from "@pie-players/pie-calculator";
9
9
  /**
@@ -13,7 +13,7 @@ export declare class DesmosCalculatorProvider implements CalculatorProvider {
13
13
  readonly providerId = "desmos";
14
14
  readonly providerName = "Desmos";
15
15
  readonly supportedTypes: CalculatorType[];
16
- readonly version = "1.10";
16
+ readonly version = "1.12";
17
17
  private initialized;
18
18
  private apiKey?;
19
19
  /**
@@ -3,7 +3,7 @@
3
3
  * Implementation of CalculatorProvider for Desmos calculators
4
4
  *
5
5
  * Supports: Basic, Scientific, and Graphing calculators
6
- * Based on Desmos API v1.10+
6
+ * Based on Desmos API v1.12+
7
7
  */
8
8
  import { COMMON_LIBRARIES, libraryLoader } from "../library-loader.js";
9
9
  /**
@@ -17,7 +17,7 @@ export class DesmosCalculatorProvider {
17
17
  "scientific",
18
18
  "graphing",
19
19
  ];
20
- version = "1.10";
20
+ version = "1.12";
21
21
  initialized = false;
22
22
  apiKey;
23
23
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"desmos-provider.js","sourceRoot":"","sources":["../../../src/tools/calculators/desmos-provider.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Desmos Calculator Provider\n * Implementation of CalculatorProvider for Desmos calculators\n *\n * Supports: Basic, Scientific, and Graphing calculators\n * Based on Desmos API v1.10+\n */\n\nimport type {\n\tCalculationHistoryEntry,\n\tCalculator,\n\tCalculatorProvider,\n\tCalculatorProviderCapabilities,\n\tCalculatorProviderConfig,\n\tCalculatorState,\n\tCalculatorType,\n\tDesmosCalculatorConfig,\n} from \"@pie-players/pie-calculator\";\nimport { COMMON_LIBRARIES, libraryLoader } from \"../library-loader.js\";\n\n/**\n * Desmos Calculator Provider Implementation\n */\nexport class DesmosCalculatorProvider implements CalculatorProvider {\n\treadonly providerId = \"desmos\";\n\treadonly providerName = \"Desmos\";\n\treadonly supportedTypes: CalculatorType[] = [\n\t\t\"basic\",\n\t\t\"scientific\",\n\t\t\"graphing\",\n\t];\n\treadonly version = \"1.10\";\n\n\tprivate initialized = false;\n\tprivate apiKey?: string;\n\n\t/**\n\t * Get the configured API key\n\t */\n\tgetApiKey(): string | undefined {\n\t\treturn this.apiKey;\n\t}\n\n\t/**\n\t * Initialize Desmos library\n\t * @param config Optional configuration including API key\n\t */\n\tasync initialize(config?: { apiKey?: string }): Promise<void> {\n\t\tif (this.initialized) return;\n\n\t\t// SSR guard: Desmos calculators should NEVER run on the server\n\t\tif (typeof window === \"undefined\") {\n\t\t\tthrow new Error(\n\t\t\t\t\"Desmos calculators can only be initialized in the browser\",\n\t\t\t);\n\t\t}\n\n\t\t// Store API key from config, environment variable, or global\n\t\tthis.apiKey =\n\t\t\tconfig?.apiKey ||\n\t\t\t(typeof process !== \"undefined\" && process.env?.DESMOS_API_KEY) ||\n\t\t\t(typeof window !== \"undefined\" && (window as any).PIE_DESMOS_API_KEY);\n\n\t\t// Warn if no API key is provided (production usage requires it)\n\t\tif (!this.apiKey) {\n\t\t\tconsole.warn(\n\t\t\t\t\"[DesmosProvider] No API key provided. Production usage requires a Desmos API key. \" +\n\t\t\t\t\t\"Obtain one from https://www.desmos.com/api or contact partnerships@desmos.com\",\n\t\t\t);\n\t\t}\n\n\t\t// Load Desmos library\n\t\tawait libraryLoader.loadScript(COMMON_LIBRARIES.desmos);\n\n\t\t// Verify Desmos API is available\n\t\tif (!(window as any).Desmos) {\n\t\t\tthrow new Error(\"Desmos API not loaded\");\n\t\t}\n\n\t\tthis.initialized = true;\n\t\tconsole.log(\n\t\t\t`[DesmosProvider] Initialized successfully${this.apiKey ? \" with API key\" : \" (no API key)\"}`,\n\t\t);\n\t}\n\n\t/**\n\t * Create a calculator instance\n\t */\n\tasync createCalculator(\n\t\ttype: CalculatorType,\n\t\tcontainer: HTMLElement,\n\t\tconfig?: CalculatorProviderConfig,\n\t): Promise<Calculator> {\n\t\tif (!this.initialized) {\n\t\t\tawait this.initialize();\n\t\t}\n\n\t\tif (!this.supportsType(type)) {\n\t\t\tthrow new Error(`Desmos does not support calculator type: ${type}`);\n\t\t}\n\n\t\treturn new DesmosCalculator(this, type, container, config);\n\t}\n\n\t/**\n\t * Check if type is supported\n\t */\n\tsupportsType(type: CalculatorType): boolean {\n\t\treturn this.supportedTypes.includes(type);\n\t}\n\n\t/**\n\t * Cleanup (no-op for Desmos)\n\t */\n\tdestroy(): void {\n\t\t// Desmos doesn't require global cleanup\n\t\tthis.initialized = false;\n\t}\n\n\t/**\n\t * Get provider capabilities\n\t */\n\tgetCapabilities(): CalculatorProviderCapabilities {\n\t\treturn {\n\t\t\tsupportsHistory: true,\n\t\t\tsupportsGraphing: true,\n\t\t\tsupportsExpressions: true,\n\t\t\tcanExport: true,\n\t\t\tmaxPrecision: 15, // JavaScript number precision\n\t\t\tinputMethods: [\"keyboard\", \"mouse\", \"touch\"],\n\t\t};\n\t}\n}\n\n/**\n * Desmos Calculator Instance\n */\nclass DesmosCalculator implements Calculator {\n\treadonly provider: CalculatorProvider;\n\treadonly type: CalculatorType;\n\n\tprivate desmosCalculator: any;\n\tprivate container: HTMLElement;\n\tprivate config?: CalculatorProviderConfig;\n\n\tconstructor(\n\t\tprovider: CalculatorProvider,\n\t\ttype: CalculatorType,\n\t\tcontainer: HTMLElement,\n\t\tconfig?: CalculatorProviderConfig,\n\t) {\n\t\tthis.provider = provider;\n\t\tthis.type = type;\n\t\tthis.container = container;\n\t\tthis.config = config;\n\n\t\tthis._initializeCalculator();\n\t}\n\n\t/**\n\t * Initialize Desmos calculator instance\n\t * Based on production implementation patterns\n\t */\n\tprivate _initializeCalculator(): void {\n\t\tconst Desmos = (window as any).Desmos;\n\n\t\t// Get Desmos-specific config or empty object\n\t\tconst desmosConfig = this.config?.desmos || {};\n\n\t\t// Determine API key (config overrides provider-level)\n\t\tconst apiKey =\n\t\t\tdesmosConfig.apiKey ||\n\t\t\t(this.provider as DesmosCalculatorProvider).getApiKey();\n\n\t\t// Apply restricted mode defaults if enabled\n\t\tconst restrictedDefaults = this._getRestrictedModeDefaults();\n\n\t\t// Merge order: type-specific defaults < restricted mode defaults < explicit config\n\t\t// This ensures explicit config can override restricted mode when needed\n\t\tconst options = {\n\t\t\t...this._getTypeSpecificDefaults(),\n\t\t\t...restrictedDefaults,\n\t\t\t...desmosConfig,\n\t\t\t...this._mapConfigToDesmos(this.config),\n\t\t};\n\n\t\t// Add API key if available\n\t\tif (apiKey) {\n\t\t\toptions.apiKey = apiKey;\n\t\t}\n\n\t\t// Create appropriate calculator type\n\t\tswitch (this.type) {\n\t\t\tcase \"basic\":\n\t\t\t\tthis.desmosCalculator = Desmos.FourFunctionCalculator(\n\t\t\t\t\tthis.container,\n\t\t\t\t\toptions,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"scientific\":\n\t\t\t\tthis.desmosCalculator = Desmos.ScientificCalculator(\n\t\t\t\t\tthis.container,\n\t\t\t\t\toptions,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"graphing\":\n\t\t\t\tthis.desmosCalculator = Desmos.GraphingCalculator(\n\t\t\t\t\tthis.container,\n\t\t\t\t\toptions,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unknown Desmos calculator type: ${this.type}`);\n\t\t}\n\n\t\tconsole.log(\n\t\t\t`[DesmosCalculator] Created ${this.type} calculator with options:`,\n\t\t\toptions,\n\t\t);\n\t}\n\n\t/**\n\t * Get type-specific default options\n\t */\n\tprivate _getTypeSpecificDefaults(): any {\n\t\tconst defaults: any = {\n\t\t\tborder: false, // No border around calculator (production implementation pattern)\n\t\t};\n\n\t\tswitch (this.type) {\n\t\t\tcase \"basic\":\n\t\t\t\t// Basic calculator: no keypad, no graph paper (just the calculator itself)\n\t\t\t\t// Matches production FourFunctionCalculator setup\n\t\t\t\tdefaults.keypad = false;\n\t\t\t\tdefaults.graphpaper = false;\n\t\t\t\tbreak;\n\t\t\tcase \"scientific\":\n\t\t\t\t// Scientific calculator: minimal defaults, mostly controlled by config\n\t\t\t\tbreak;\n\t\t\tcase \"graphing\":\n\t\t\t\t// Graphing calculator: enable expressions, zoom buttons, topbar by default\n\t\t\t\tdefaults.expressions = true;\n\t\t\t\tdefaults.zoomButtons = true;\n\t\t\t\tdefaults.expressionsTopbar = true;\n\t\t\t\tdefaults.settingsMenu = true;\n\t\t\t\tdefaults.notes = true;\n\t\t\t\tdefaults.folders = true;\n\t\t\t\tdefaults.images = false; // Images disabled by default (production pattern)\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn defaults;\n\t}\n\n\t/**\n\t * Get restricted mode defaults (test mode options)\n\t * Based on production test mode configuration\n\t */\n\tprivate _getRestrictedModeDefaults(): any {\n\t\tif (!this.config?.restrictedMode) {\n\t\t\treturn {};\n\t\t}\n\n\t\t// Restricted mode defaults based on production test mode settings\n\t\tconst restricted: any = {\n\t\t\tborder: false,\n\t\t\tlinks: false,\n\t\t\tqwertyKeyboard: true,\n\t\t\tdegreeMode: true,\n\t\t\tdecimalToFraction: true,\n\t\t};\n\n\t\t// Type-specific restricted mode options\n\t\tif (this.type === \"graphing\") {\n\t\t\tObject.assign(restricted, {\n\t\t\t\timages: false,\n\t\t\t\tfolders: false,\n\t\t\t\tnotes: false,\n\t\t\t\trestrictedFunctions: true,\n\t\t\t\tplotSingleVariableImplicitEquations: false,\n\t\t\t\tplotImplicits: false,\n\t\t\t\tplotInequalities: false,\n\t\t\t\tsliders: false,\n\t\t\t\tsettingsMenu: false,\n\t\t\t\tzoomButtons: false,\n\t\t\t\tgeometryComputationFunctions: true,\n\t\t\t\tdistributions: true,\n\t\t\t});\n\t\t} else if (this.type === \"scientific\") {\n\t\t\tObject.assign(restricted, {\n\t\t\t\tfunctionDefinition: false,\n\t\t\t\tbrailleExpressionDownload: false,\n\t\t\t});\n\t\t}\n\n\t\treturn restricted;\n\t}\n\n\t/**\n\t * Map provider config to Desmos options\n\t */\n\tprivate _mapConfigToDesmos(config?: CalculatorProviderConfig): any {\n\t\tif (!config) return {};\n\n\t\tconst desmosOptions: any = {};\n\n\t\t// Map locale to Desmos language option\n\t\tif (config.locale) {\n\t\t\tdesmosOptions.language = config.locale;\n\t\t}\n\n\t\t// Theme mapping (Desmos may support this via CSS, not API)\n\t\t// Note: Desmos doesn't have a theme option in the API, but we keep this\n\t\t// for potential future use or CSS-based theming\n\n\t\treturn desmosOptions;\n\t}\n\n\t/**\n\t * Get current value/expression\n\t */\n\tgetValue(): string {\n\t\t// For graphing calculator, get all expressions\n\t\tif (this.type === \"graphing\") {\n\t\t\tconst state = this.desmosCalculator.getState();\n\t\t\treturn JSON.stringify(state.expressions.list);\n\t\t}\n\n\t\t// For basic/scientific, get current expression\n\t\tconst state = this.desmosCalculator.getState();\n\t\treturn state.expression || \"\";\n\t}\n\n\t/**\n\t * Set value/expression\n\t */\n\tsetValue(value: string): void {\n\t\tif (this.type === \"graphing\") {\n\t\t\ttry {\n\t\t\t\tconst expressions = JSON.parse(value);\n\t\t\t\tthis.desmosCalculator.setState({ expressions: { list: expressions } });\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"[DesmosCalculator] Invalid expression format:\", error);\n\t\t\t}\n\t\t} else {\n\t\t\t// Basic/Scientific calculators\n\t\t\tthis.desmosCalculator.setExpression({ latex: value });\n\t\t}\n\t}\n\n\t/**\n\t * Clear calculator\n\t */\n\tclear(): void {\n\t\tif (this.type === \"graphing\") {\n\t\t\tthis.desmosCalculator.setBlank();\n\t\t} else {\n\t\t\tthis.setValue(\"\");\n\t\t}\n\t}\n\n\t/**\n\t * Get calculation history (not natively supported by Desmos)\n\t */\n\tgetHistory(): CalculationHistoryEntry[] {\n\t\t// Desmos doesn't provide history natively\n\t\t// Would need to implement custom tracking\n\t\treturn [];\n\t}\n\n\t/**\n\t * Clear history\n\t */\n\tclearHistory(): void {\n\t\t// No-op - Desmos doesn't have history\n\t}\n\n\t/**\n\t * Resize calculator when container dimensions change\n\t * Matches production pattern: calculatorInstance.resize()\n\t */\n\tresize(): void {\n\t\tif (\n\t\t\tthis.desmosCalculator &&\n\t\t\ttypeof this.desmosCalculator.resize === \"function\"\n\t\t) {\n\t\t\tthis.desmosCalculator.resize();\n\t\t}\n\t}\n\n\t/**\n\t * Move keyboard focus to the primary input/expression field so keyboard\n\t * users can begin typing immediately after the calculator opens.\n\t */\n\tfocus(): void {\n\t\ttry {\n\t\t\tif (\n\t\t\t\tthis.type === \"graphing\" &&\n\t\t\t\ttypeof this.desmosCalculator?.focusFirstExpression === \"function\"\n\t\t\t) {\n\t\t\t\tthis.desmosCalculator.focusFirstExpression();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst target = this.container.querySelector<HTMLElement>(\n\t\t\t\t'.dcg-mq-editable-field[tabindex=\"0\"], textarea, [contenteditable=\"true\"], [tabindex]:not([tabindex=\"-1\"])',\n\t\t\t);\n\t\t\ttarget?.focus();\n\t\t} catch (error) {\n\t\t\tconsole.warn(\"[DesmosCalculator] focus() failed:\", error);\n\t\t}\n\t}\n\n\t/**\n\t * Evaluate expression (for graphing calculator)\n\t */\n\tasync evaluate(expression: string): Promise<string> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\ttry {\n\t\t\t\t// Set expression and wait for computation\n\t\t\t\tthis.desmosCalculator.setExpression({ latex: expression });\n\n\t\t\t\t// For basic math, Desmos evaluates automatically\n\t\t\t\t// Get the result from state\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tconst result = this.getValue();\n\t\t\t\t\tresolve(result);\n\t\t\t\t}, 100); // Small delay for Desmos to compute\n\t\t\t} catch (error) {\n\t\t\t\treject(error);\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Export calculator state\n\t */\n\texportState(): CalculatorState {\n\t\tconst state = this.desmosCalculator.getState();\n\n\t\treturn {\n\t\t\ttype: this.type,\n\t\t\tprovider: \"desmos\",\n\t\t\tvalue: this.getValue(),\n\t\t\tproviderState: state,\n\t\t};\n\t}\n\n\t/**\n\t * Import calculator state\n\t */\n\timportState(state: CalculatorState): void {\n\t\tif (state.provider !== \"desmos\") {\n\t\t\tthrow new Error(`Cannot import state from provider: ${state.provider}`);\n\t\t}\n\n\t\tif (state.providerState) {\n\t\t\tthis.desmosCalculator.setState(state.providerState);\n\t\t} else if (state.value) {\n\t\t\tthis.setValue(state.value);\n\t\t}\n\t}\n\n\t/**\n\t * Destroy calculator\n\t */\n\tdestroy(): void {\n\t\tif (this.desmosCalculator) {\n\t\t\ttry {\n\t\t\t\tthis.desmosCalculator.destroy();\n\t\t\t} catch (error) {\n\t\t\t\tconsole.warn(\"[DesmosCalculator] Error during destroy:\", error);\n\t\t\t}\n\t\t\tthis.desmosCalculator = null;\n\t\t}\n\n\t\t// Clear the container to ensure Desmos releases all references\n\t\tif (this.container) {\n\t\t\t// Remove any Desmos-specific attributes\n\t\t\tthis.container.removeAttribute(\"data-desmos-id\");\n\n\t\t\t// Use modern API - more efficient and cleaner\n\t\t\tthis.container.replaceChildren();\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"desmos-provider.js","sourceRoot":"","sources":["../../../src/tools/calculators/desmos-provider.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Desmos Calculator Provider\n * Implementation of CalculatorProvider for Desmos calculators\n *\n * Supports: Basic, Scientific, and Graphing calculators\n * Based on Desmos API v1.12+\n */\n\nimport type {\n\tCalculationHistoryEntry,\n\tCalculator,\n\tCalculatorProvider,\n\tCalculatorProviderCapabilities,\n\tCalculatorProviderConfig,\n\tCalculatorState,\n\tCalculatorType,\n\tDesmosCalculatorConfig,\n} from \"@pie-players/pie-calculator\";\nimport { COMMON_LIBRARIES, libraryLoader } from \"../library-loader.js\";\n\n/**\n * Desmos Calculator Provider Implementation\n */\nexport class DesmosCalculatorProvider implements CalculatorProvider {\n\treadonly providerId = \"desmos\";\n\treadonly providerName = \"Desmos\";\n\treadonly supportedTypes: CalculatorType[] = [\n\t\t\"basic\",\n\t\t\"scientific\",\n\t\t\"graphing\",\n\t];\n\treadonly version = \"1.12\";\n\n\tprivate initialized = false;\n\tprivate apiKey?: string;\n\n\t/**\n\t * Get the configured API key\n\t */\n\tgetApiKey(): string | undefined {\n\t\treturn this.apiKey;\n\t}\n\n\t/**\n\t * Initialize Desmos library\n\t * @param config Optional configuration including API key\n\t */\n\tasync initialize(config?: { apiKey?: string }): Promise<void> {\n\t\tif (this.initialized) return;\n\n\t\t// SSR guard: Desmos calculators should NEVER run on the server\n\t\tif (typeof window === \"undefined\") {\n\t\t\tthrow new Error(\n\t\t\t\t\"Desmos calculators can only be initialized in the browser\",\n\t\t\t);\n\t\t}\n\n\t\t// Store API key from config, environment variable, or global\n\t\tthis.apiKey =\n\t\t\tconfig?.apiKey ||\n\t\t\t(typeof process !== \"undefined\" && process.env?.DESMOS_API_KEY) ||\n\t\t\t(typeof window !== \"undefined\" && (window as any).PIE_DESMOS_API_KEY);\n\n\t\t// Warn if no API key is provided (production usage requires it)\n\t\tif (!this.apiKey) {\n\t\t\tconsole.warn(\n\t\t\t\t\"[DesmosProvider] No API key provided. Production usage requires a Desmos API key. \" +\n\t\t\t\t\t\"Obtain one from https://www.desmos.com/api or contact partnerships@desmos.com\",\n\t\t\t);\n\t\t}\n\n\t\t// Load Desmos library\n\t\tawait libraryLoader.loadScript(COMMON_LIBRARIES.desmos);\n\n\t\t// Verify Desmos API is available\n\t\tif (!(window as any).Desmos) {\n\t\t\tthrow new Error(\"Desmos API not loaded\");\n\t\t}\n\n\t\tthis.initialized = true;\n\t\tconsole.log(\n\t\t\t`[DesmosProvider] Initialized successfully${this.apiKey ? \" with API key\" : \" (no API key)\"}`,\n\t\t);\n\t}\n\n\t/**\n\t * Create a calculator instance\n\t */\n\tasync createCalculator(\n\t\ttype: CalculatorType,\n\t\tcontainer: HTMLElement,\n\t\tconfig?: CalculatorProviderConfig,\n\t): Promise<Calculator> {\n\t\tif (!this.initialized) {\n\t\t\tawait this.initialize();\n\t\t}\n\n\t\tif (!this.supportsType(type)) {\n\t\t\tthrow new Error(`Desmos does not support calculator type: ${type}`);\n\t\t}\n\n\t\treturn new DesmosCalculator(this, type, container, config);\n\t}\n\n\t/**\n\t * Check if type is supported\n\t */\n\tsupportsType(type: CalculatorType): boolean {\n\t\treturn this.supportedTypes.includes(type);\n\t}\n\n\t/**\n\t * Cleanup (no-op for Desmos)\n\t */\n\tdestroy(): void {\n\t\t// Desmos doesn't require global cleanup\n\t\tthis.initialized = false;\n\t}\n\n\t/**\n\t * Get provider capabilities\n\t */\n\tgetCapabilities(): CalculatorProviderCapabilities {\n\t\treturn {\n\t\t\tsupportsHistory: true,\n\t\t\tsupportsGraphing: true,\n\t\t\tsupportsExpressions: true,\n\t\t\tcanExport: true,\n\t\t\tmaxPrecision: 15, // JavaScript number precision\n\t\t\tinputMethods: [\"keyboard\", \"mouse\", \"touch\"],\n\t\t};\n\t}\n}\n\n/**\n * Desmos Calculator Instance\n */\nclass DesmosCalculator implements Calculator {\n\treadonly provider: CalculatorProvider;\n\treadonly type: CalculatorType;\n\n\tprivate desmosCalculator: any;\n\tprivate container: HTMLElement;\n\tprivate config?: CalculatorProviderConfig;\n\n\tconstructor(\n\t\tprovider: CalculatorProvider,\n\t\ttype: CalculatorType,\n\t\tcontainer: HTMLElement,\n\t\tconfig?: CalculatorProviderConfig,\n\t) {\n\t\tthis.provider = provider;\n\t\tthis.type = type;\n\t\tthis.container = container;\n\t\tthis.config = config;\n\n\t\tthis._initializeCalculator();\n\t}\n\n\t/**\n\t * Initialize Desmos calculator instance\n\t * Based on production implementation patterns\n\t */\n\tprivate _initializeCalculator(): void {\n\t\tconst Desmos = (window as any).Desmos;\n\n\t\t// Get Desmos-specific config or empty object\n\t\tconst desmosConfig = this.config?.desmos || {};\n\n\t\t// Determine API key (config overrides provider-level)\n\t\tconst apiKey =\n\t\t\tdesmosConfig.apiKey ||\n\t\t\t(this.provider as DesmosCalculatorProvider).getApiKey();\n\n\t\t// Apply restricted mode defaults if enabled\n\t\tconst restrictedDefaults = this._getRestrictedModeDefaults();\n\n\t\t// Merge order: type-specific defaults < restricted mode defaults < explicit config\n\t\t// This ensures explicit config can override restricted mode when needed\n\t\tconst options = {\n\t\t\t...this._getTypeSpecificDefaults(),\n\t\t\t...restrictedDefaults,\n\t\t\t...desmosConfig,\n\t\t\t...this._mapConfigToDesmos(this.config),\n\t\t};\n\n\t\t// Add API key if available\n\t\tif (apiKey) {\n\t\t\toptions.apiKey = apiKey;\n\t\t}\n\n\t\t// Create appropriate calculator type\n\t\tswitch (this.type) {\n\t\t\tcase \"basic\":\n\t\t\t\tthis.desmosCalculator = Desmos.FourFunctionCalculator(\n\t\t\t\t\tthis.container,\n\t\t\t\t\toptions,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"scientific\":\n\t\t\t\tthis.desmosCalculator = Desmos.ScientificCalculator(\n\t\t\t\t\tthis.container,\n\t\t\t\t\toptions,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"graphing\":\n\t\t\t\tthis.desmosCalculator = Desmos.GraphingCalculator(\n\t\t\t\t\tthis.container,\n\t\t\t\t\toptions,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unknown Desmos calculator type: ${this.type}`);\n\t\t}\n\n\t\tconsole.log(\n\t\t\t`[DesmosCalculator] Created ${this.type} calculator with options:`,\n\t\t\toptions,\n\t\t);\n\t}\n\n\t/**\n\t * Get type-specific default options\n\t */\n\tprivate _getTypeSpecificDefaults(): any {\n\t\tconst defaults: any = {\n\t\t\tborder: false, // No border around calculator (production implementation pattern)\n\t\t};\n\n\t\tswitch (this.type) {\n\t\t\tcase \"basic\":\n\t\t\t\t// Basic calculator: no keypad, no graph paper (just the calculator itself)\n\t\t\t\t// Matches production FourFunctionCalculator setup\n\t\t\t\tdefaults.keypad = false;\n\t\t\t\tdefaults.graphpaper = false;\n\t\t\t\tbreak;\n\t\t\tcase \"scientific\":\n\t\t\t\t// Scientific calculator: minimal defaults, mostly controlled by config\n\t\t\t\tbreak;\n\t\t\tcase \"graphing\":\n\t\t\t\t// Graphing calculator: enable expressions, zoom buttons, topbar by default\n\t\t\t\tdefaults.expressions = true;\n\t\t\t\tdefaults.zoomButtons = true;\n\t\t\t\tdefaults.expressionsTopbar = true;\n\t\t\t\tdefaults.settingsMenu = true;\n\t\t\t\tdefaults.notes = true;\n\t\t\t\tdefaults.folders = true;\n\t\t\t\tdefaults.images = false; // Images disabled by default (production pattern)\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn defaults;\n\t}\n\n\t/**\n\t * Get restricted mode defaults (test mode options)\n\t * Based on production test mode configuration\n\t */\n\tprivate _getRestrictedModeDefaults(): any {\n\t\tif (!this.config?.restrictedMode) {\n\t\t\treturn {};\n\t\t}\n\n\t\t// Restricted mode defaults based on production test mode settings\n\t\tconst restricted: any = {\n\t\t\tborder: false,\n\t\t\tlinks: false,\n\t\t\tqwertyKeyboard: true,\n\t\t\tdegreeMode: true,\n\t\t\tdecimalToFraction: true,\n\t\t};\n\n\t\t// Type-specific restricted mode options\n\t\tif (this.type === \"graphing\") {\n\t\t\tObject.assign(restricted, {\n\t\t\t\timages: false,\n\t\t\t\tfolders: false,\n\t\t\t\tnotes: false,\n\t\t\t\trestrictedFunctions: true,\n\t\t\t\tplotSingleVariableImplicitEquations: false,\n\t\t\t\tplotImplicits: false,\n\t\t\t\tplotInequalities: false,\n\t\t\t\tsliders: false,\n\t\t\t\tsettingsMenu: false,\n\t\t\t\tzoomButtons: false,\n\t\t\t\tgeometryComputationFunctions: true,\n\t\t\t\tdistributions: true,\n\t\t\t});\n\t\t} else if (this.type === \"scientific\") {\n\t\t\tObject.assign(restricted, {\n\t\t\t\tfunctionDefinition: false,\n\t\t\t\tbrailleExpressionDownload: false,\n\t\t\t});\n\t\t}\n\n\t\treturn restricted;\n\t}\n\n\t/**\n\t * Map provider config to Desmos options\n\t */\n\tprivate _mapConfigToDesmos(config?: CalculatorProviderConfig): any {\n\t\tif (!config) return {};\n\n\t\tconst desmosOptions: any = {};\n\n\t\t// Map locale to Desmos language option\n\t\tif (config.locale) {\n\t\t\tdesmosOptions.language = config.locale;\n\t\t}\n\n\t\t// Theme mapping (Desmos may support this via CSS, not API)\n\t\t// Note: Desmos doesn't have a theme option in the API, but we keep this\n\t\t// for potential future use or CSS-based theming\n\n\t\treturn desmosOptions;\n\t}\n\n\t/**\n\t * Get current value/expression\n\t */\n\tgetValue(): string {\n\t\t// For graphing calculator, get all expressions\n\t\tif (this.type === \"graphing\") {\n\t\t\tconst state = this.desmosCalculator.getState();\n\t\t\treturn JSON.stringify(state.expressions.list);\n\t\t}\n\n\t\t// For basic/scientific, get current expression\n\t\tconst state = this.desmosCalculator.getState();\n\t\treturn state.expression || \"\";\n\t}\n\n\t/**\n\t * Set value/expression\n\t */\n\tsetValue(value: string): void {\n\t\tif (this.type === \"graphing\") {\n\t\t\ttry {\n\t\t\t\tconst expressions = JSON.parse(value);\n\t\t\t\tthis.desmosCalculator.setState({ expressions: { list: expressions } });\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"[DesmosCalculator] Invalid expression format:\", error);\n\t\t\t}\n\t\t} else {\n\t\t\t// Basic/Scientific calculators\n\t\t\tthis.desmosCalculator.setExpression({ latex: value });\n\t\t}\n\t}\n\n\t/**\n\t * Clear calculator\n\t */\n\tclear(): void {\n\t\tif (this.type === \"graphing\") {\n\t\t\tthis.desmosCalculator.setBlank();\n\t\t} else {\n\t\t\tthis.setValue(\"\");\n\t\t}\n\t}\n\n\t/**\n\t * Get calculation history (not natively supported by Desmos)\n\t */\n\tgetHistory(): CalculationHistoryEntry[] {\n\t\t// Desmos doesn't provide history natively\n\t\t// Would need to implement custom tracking\n\t\treturn [];\n\t}\n\n\t/**\n\t * Clear history\n\t */\n\tclearHistory(): void {\n\t\t// No-op - Desmos doesn't have history\n\t}\n\n\t/**\n\t * Resize calculator when container dimensions change\n\t * Matches production pattern: calculatorInstance.resize()\n\t */\n\tresize(): void {\n\t\tif (\n\t\t\tthis.desmosCalculator &&\n\t\t\ttypeof this.desmosCalculator.resize === \"function\"\n\t\t) {\n\t\t\tthis.desmosCalculator.resize();\n\t\t}\n\t}\n\n\t/**\n\t * Move keyboard focus to the primary input/expression field so keyboard\n\t * users can begin typing immediately after the calculator opens.\n\t */\n\tfocus(): void {\n\t\ttry {\n\t\t\tif (\n\t\t\t\tthis.type === \"graphing\" &&\n\t\t\t\ttypeof this.desmosCalculator?.focusFirstExpression === \"function\"\n\t\t\t) {\n\t\t\t\tthis.desmosCalculator.focusFirstExpression();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst target = this.container.querySelector<HTMLElement>(\n\t\t\t\t'.dcg-mq-editable-field[tabindex=\"0\"], textarea, [contenteditable=\"true\"], [tabindex]:not([tabindex=\"-1\"])',\n\t\t\t);\n\t\t\ttarget?.focus();\n\t\t} catch (error) {\n\t\t\tconsole.warn(\"[DesmosCalculator] focus() failed:\", error);\n\t\t}\n\t}\n\n\t/**\n\t * Evaluate expression (for graphing calculator)\n\t */\n\tasync evaluate(expression: string): Promise<string> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\ttry {\n\t\t\t\t// Set expression and wait for computation\n\t\t\t\tthis.desmosCalculator.setExpression({ latex: expression });\n\n\t\t\t\t// For basic math, Desmos evaluates automatically\n\t\t\t\t// Get the result from state\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tconst result = this.getValue();\n\t\t\t\t\tresolve(result);\n\t\t\t\t}, 100); // Small delay for Desmos to compute\n\t\t\t} catch (error) {\n\t\t\t\treject(error);\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Export calculator state\n\t */\n\texportState(): CalculatorState {\n\t\tconst state = this.desmosCalculator.getState();\n\n\t\treturn {\n\t\t\ttype: this.type,\n\t\t\tprovider: \"desmos\",\n\t\t\tvalue: this.getValue(),\n\t\t\tproviderState: state,\n\t\t};\n\t}\n\n\t/**\n\t * Import calculator state\n\t */\n\timportState(state: CalculatorState): void {\n\t\tif (state.provider !== \"desmos\") {\n\t\t\tthrow new Error(`Cannot import state from provider: ${state.provider}`);\n\t\t}\n\n\t\tif (state.providerState) {\n\t\t\tthis.desmosCalculator.setState(state.providerState);\n\t\t} else if (state.value) {\n\t\t\tthis.setValue(state.value);\n\t\t}\n\t}\n\n\t/**\n\t * Destroy calculator\n\t */\n\tdestroy(): void {\n\t\tif (this.desmosCalculator) {\n\t\t\ttry {\n\t\t\t\tthis.desmosCalculator.destroy();\n\t\t\t} catch (error) {\n\t\t\t\tconsole.warn(\"[DesmosCalculator] Error during destroy:\", error);\n\t\t\t}\n\t\t\tthis.desmosCalculator = null;\n\t\t}\n\n\t\t// Clear the container to ensure Desmos releases all references\n\t\tif (this.container) {\n\t\t\t// Remove any Desmos-specific attributes\n\t\t\tthis.container.removeAttribute(\"data-desmos-id\");\n\n\t\t\t// Use modern API - more efficient and cleaner\n\t\t\tthis.container.replaceChildren();\n\t\t}\n\t}\n}\n"]}
@@ -220,7 +220,7 @@ export const libraryLoader = new LibraryLoaderImpl();
220
220
  * Desmos library version (matches the version in calculator.js)
221
221
  * Update this when upgrading to a new version
222
222
  */
223
- const DESMOS_VERSION = "v1.10.1";
223
+ const DESMOS_VERSION = "v1.12";
224
224
  /**
225
225
  * Common library configurations
226
226
  * Based on industry best practices and platform analyses
@@ -230,8 +230,8 @@ export const COMMON_LIBRARIES = {
230
230
  id: "desmos",
231
231
  url: `/lib/desmos/${DESMOS_VERSION}/calculator.js`, // Self-hosted (prioritized) - versioned for better cache control
232
232
  fallbackUrls: [
233
- "https://www.desmos.com/api/v1.10/calculator.js",
234
- "https://cdn.jsdelivr.net/npm/desmos@1.10/dist/calculator.js",
233
+ "https://www.desmos.com/api/v1.12/calculator.js",
234
+ "https://cdn.jsdelivr.net/npm/desmos@1.12/dist/calculator.js",
235
235
  ],
236
236
  globalVar: "Desmos",
237
237
  timeout: 10000,
@@ -1 +1 @@
1
- {"version":3,"file":"library-loader.js","sourceRoot":"","sources":["../../src/tools/library-loader.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Library Loader Service\n * Dynamically loads external JavaScript libraries with retry logic and fallback URLs\n *\n * Based on architectural enhancements from renaissance-tool-analyses.md\n * Supports both static and dynamic library loading\n */\n\nimport type { LibraryConfig, LibraryLoader, LoaderStats } from \"./types.js\";\n\n/**\n * Implementation of LibraryLoader service\n */\nexport class LibraryLoaderImpl implements LibraryLoader {\n\tprivate loadedLibraries = new Set<string>();\n\tprivate pendingLoads = new Map<string, Promise<void>>();\n\tprivate failedLibraries = new Map<string, Error>();\n\tprivate stats: LoaderStats = {\n\t\tloaded: [],\n\t\tfailed: [],\n\t\tpending: [],\n\t\tcacheHits: 0,\n\t\tcacheMisses: 0,\n\t\ttotalLoadTime: 0,\n\t};\n\n\t/**\n\t * Load a JavaScript library\n\t */\n\tasync loadScript(library: LibraryConfig): Promise<void> {\n\t\t// SSR guard: Library loading should NEVER run on the server\n\t\tif (typeof window === \"undefined\" || typeof document === \"undefined\") {\n\t\t\tthrow new Error(\"Library loader can only be used in the browser\");\n\t\t}\n\n\t\tconst startTime = performance.now();\n\n\t\t// Check if already loaded\n\t\tif (this.isLoaded(library.id)) {\n\t\t\tthis.stats.cacheHits++;\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if already pending\n\t\tconst pending = this.pendingLoads.get(library.id);\n\t\tif (pending) {\n\t\t\treturn pending;\n\t\t}\n\n\t\tthis.stats.cacheMisses++;\n\n\t\t// Start loading\n\t\tconst loadPromise = this._loadScriptWithRetry(library);\n\t\tthis.pendingLoads.set(library.id, loadPromise);\n\t\tthis.stats.pending.push(library.id);\n\n\t\ttry {\n\t\t\tawait loadPromise;\n\t\t\tthis.loadedLibraries.add(library.id);\n\t\t\tthis.stats.loaded.push(library.id);\n\n\t\t\tconst loadTime = performance.now() - startTime;\n\t\t\tthis.stats.totalLoadTime += loadTime;\n\n\t\t\tconsole.log(\n\t\t\t\t`[LibraryLoader] Successfully loaded ${library.id} in ${loadTime.toFixed(2)}ms`,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tthis.failedLibraries.set(library.id, error as Error);\n\t\t\tthis.stats.failed.push(library.id);\n\t\t\tconsole.error(`[LibraryLoader] Failed to load ${library.id}:`, error);\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\tthis.pendingLoads.delete(library.id);\n\t\t\tconst pendingIndex = this.stats.pending.indexOf(library.id);\n\t\t\tif (pendingIndex !== -1) {\n\t\t\t\tthis.stats.pending.splice(pendingIndex, 1);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Load a stylesheet\n\t */\n\tasync loadStylesheet(\n\t\turl: string,\n\t\ttargetRoot?: Document | ShadowRoot,\n\t): Promise<void> {\n\t\t// SSR guard: Stylesheet loading should NEVER run on the server\n\t\tif (typeof window === \"undefined\" || typeof document === \"undefined\") {\n\t\t\tthrow new Error(\"Stylesheet loader can only be used in the browser\");\n\t\t}\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst root = targetRoot ?? document;\n\n\t\t\t// Check if already loaded\n\t\t\tconst existing = root.querySelector(`link[href=\"${url}\"]`);\n\t\t\tif (existing) {\n\t\t\t\tresolve();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst link = document.createElement(\"link\");\n\t\t\tlink.rel = \"stylesheet\";\n\t\t\tlink.href = url;\n\n\t\t\tlink.onload = () => resolve();\n\t\t\tlink.onerror = () =>\n\t\t\t\treject(new Error(`Failed to load stylesheet: ${url}`));\n\n\t\t\tif (root instanceof ShadowRoot) {\n\t\t\t\troot.appendChild(link);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdocument.head.appendChild(link);\n\t\t});\n\t}\n\n\t/**\n\t * Check if a library is already loaded\n\t */\n\tisLoaded(libraryId: string): boolean {\n\t\treturn this.loadedLibraries.has(libraryId);\n\t}\n\n\t/**\n\t * Preload multiple libraries in parallel\n\t */\n\tasync preload(libraries: LibraryConfig[]): Promise<void> {\n\t\tconst promises = libraries.map((lib) => this.loadScript(lib));\n\t\tawait Promise.all(promises);\n\t}\n\n\t/**\n\t * Unload a library (remove script tag)\n\t */\n\tunload(libraryId: string): void {\n\t\tconst script = document.querySelector(\n\t\t\t`script[data-library-id=\"${libraryId}\"]`,\n\t\t);\n\t\tif (script) {\n\t\t\tscript.remove();\n\t\t\tthis.loadedLibraries.delete(libraryId);\n\n\t\t\t// Remove from stats\n\t\t\tconst loadedIndex = this.stats.loaded.indexOf(libraryId);\n\t\t\tif (loadedIndex !== -1) {\n\t\t\t\tthis.stats.loaded.splice(loadedIndex, 1);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Get loader statistics\n\t */\n\tgetStats(): LoaderStats {\n\t\treturn { ...this.stats };\n\t}\n\n\t/**\n\t * Load script with retry logic\n\t */\n\tprivate async _loadScriptWithRetry(library: LibraryConfig): Promise<void> {\n\t\tconst urls = [library.url, ...(library.fallbackUrls || [])];\n\t\tconst maxAttempts = library.retry?.maxAttempts || 3;\n\t\tconst delay = library.retry?.delay || 1000;\n\t\tconst backoffMultiplier = library.retry?.backoffMultiplier || 2;\n\n\t\tlet lastError: Error | null = null;\n\n\t\tfor (const url of urls) {\n\t\t\tfor (let attempt = 1; attempt <= maxAttempts; attempt++) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this._loadScriptFromUrl(url, library);\n\n\t\t\t\t\t// Verify library loaded if globalVar specified\n\t\t\t\t\tif (library.globalVar) {\n\t\t\t\t\t\tif (!(library.globalVar in window)) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`Library ${library.id} loaded but global ${library.globalVar} not found`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn; // Success\n\t\t\t\t} catch (error) {\n\t\t\t\t\tlastError = error as Error;\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`[LibraryLoader] Attempt ${attempt}/${maxAttempts} failed for ${url}:`,\n\t\t\t\t\t\terror,\n\t\t\t\t\t);\n\n\t\t\t\t\t// Wait before retry (exponential backoff)\n\t\t\t\t\tif (attempt < maxAttempts) {\n\t\t\t\t\t\tconst waitTime = delay * Math.pow(backoffMultiplier, attempt - 1);\n\t\t\t\t\t\tawait this._sleep(waitTime);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t`Failed to load library ${library.id} after trying all URLs: ${lastError?.message}`,\n\t\t);\n\t}\n\n\t/**\n\t * Load script from a specific URL\n\t */\n\tprivate _loadScriptFromUrl(\n\t\turl: string,\n\t\tlibrary: LibraryConfig,\n\t): Promise<void> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst script = document.createElement(\"script\");\n\t\t\tscript.src = url;\n\t\t\tscript.dataset.libraryId = library.id;\n\n\t\t\tif (library.async) script.async = true;\n\t\t\tif (library.defer) script.defer = true;\n\t\t\tif (library.integrity) script.integrity = library.integrity;\n\t\t\tif (library.crossorigin) script.crossOrigin = library.crossorigin;\n\n\t\t\tlet timeoutId: number | undefined;\n\n\t\t\tconst cleanup = () => {\n\t\t\t\tif (timeoutId) clearTimeout(timeoutId);\n\t\t\t\tscript.onload = null;\n\t\t\t\tscript.onerror = null;\n\t\t\t};\n\n\t\t\tscript.onload = () => {\n\t\t\t\tcleanup();\n\t\t\t\tresolve();\n\t\t\t};\n\n\t\t\tscript.onerror = (error) => {\n\t\t\t\tcleanup();\n\t\t\t\tscript.remove();\n\t\t\t\treject(new Error(`Script load error for ${url}: ${error}`));\n\t\t\t};\n\n\t\t\t// Timeout handling\n\t\t\tif (library.timeout) {\n\t\t\t\ttimeoutId = window.setTimeout(() => {\n\t\t\t\t\tcleanup();\n\t\t\t\t\tscript.remove();\n\t\t\t\t\treject(\n\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t`Script load timeout for ${url} after ${library.timeout}ms`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}, library.timeout);\n\t\t\t}\n\n\t\t\tdocument.head.appendChild(script);\n\t\t});\n\t}\n\n\t/**\n\t * Sleep utility for retry delays\n\t */\n\tprivate _sleep(ms: number): Promise<void> {\n\t\treturn new Promise((resolve) => setTimeout(resolve, ms));\n\t}\n}\n\n/**\n * Singleton instance\n */\nexport const libraryLoader = new LibraryLoaderImpl();\n\n/**\n * Desmos library version (matches the version in calculator.js)\n * Update this when upgrading to a new version\n */\nconst DESMOS_VERSION = \"v1.10.1\";\n\n/**\n * Common library configurations\n * Based on industry best practices and platform analyses\n */\nexport const COMMON_LIBRARIES: Record<string, LibraryConfig> = {\n\tdesmos: {\n\t\tid: \"desmos\",\n\t\turl: `/lib/desmos/${DESMOS_VERSION}/calculator.js`, // Self-hosted (prioritized) - versioned for better cache control\n\t\tfallbackUrls: [\n\t\t\t\"https://www.desmos.com/api/v1.10/calculator.js\",\n\t\t\t\"https://cdn.jsdelivr.net/npm/desmos@1.10/dist/calculator.js\",\n\t\t],\n\t\tglobalVar: \"Desmos\",\n\t\ttimeout: 10000,\n\t\tretry: { maxAttempts: 3, delay: 1000, backoffMultiplier: 2 },\n\t},\n\n\tmathjax: {\n\t\tid: \"mathjax\",\n\t\turl: \"https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js\",\n\t\tfallbackUrls: [\n\t\t\t\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-mml-chtml.min.js\",\n\t\t\t\"/static/lib/mathjax/tex-mml-chtml.js\",\n\t\t],\n\t\tglobalVar: \"MathJax\",\n\t\tasync: true,\n\t\tretry: { maxAttempts: 2, delay: 1500 },\n\t},\n\n\tkatex: {\n\t\tid: \"katex\",\n\t\turl: \"https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js\",\n\t\tfallbackUrls: [\n\t\t\t\"https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/katex.min.js\",\n\t\t\t\"/static/lib/katex/katex.min.js\",\n\t\t],\n\t\tglobalVar: \"katex\",\n\t\ttimeout: 5000,\n\t},\n};\n"]}
1
+ {"version":3,"file":"library-loader.js","sourceRoot":"","sources":["../../src/tools/library-loader.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Library Loader Service\n * Dynamically loads external JavaScript libraries with retry logic and fallback URLs\n *\n * Based on architectural enhancements from renaissance-tool-analyses.md\n * Supports both static and dynamic library loading\n */\n\nimport type { LibraryConfig, LibraryLoader, LoaderStats } from \"./types.js\";\n\n/**\n * Implementation of LibraryLoader service\n */\nexport class LibraryLoaderImpl implements LibraryLoader {\n\tprivate loadedLibraries = new Set<string>();\n\tprivate pendingLoads = new Map<string, Promise<void>>();\n\tprivate failedLibraries = new Map<string, Error>();\n\tprivate stats: LoaderStats = {\n\t\tloaded: [],\n\t\tfailed: [],\n\t\tpending: [],\n\t\tcacheHits: 0,\n\t\tcacheMisses: 0,\n\t\ttotalLoadTime: 0,\n\t};\n\n\t/**\n\t * Load a JavaScript library\n\t */\n\tasync loadScript(library: LibraryConfig): Promise<void> {\n\t\t// SSR guard: Library loading should NEVER run on the server\n\t\tif (typeof window === \"undefined\" || typeof document === \"undefined\") {\n\t\t\tthrow new Error(\"Library loader can only be used in the browser\");\n\t\t}\n\n\t\tconst startTime = performance.now();\n\n\t\t// Check if already loaded\n\t\tif (this.isLoaded(library.id)) {\n\t\t\tthis.stats.cacheHits++;\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if already pending\n\t\tconst pending = this.pendingLoads.get(library.id);\n\t\tif (pending) {\n\t\t\treturn pending;\n\t\t}\n\n\t\tthis.stats.cacheMisses++;\n\n\t\t// Start loading\n\t\tconst loadPromise = this._loadScriptWithRetry(library);\n\t\tthis.pendingLoads.set(library.id, loadPromise);\n\t\tthis.stats.pending.push(library.id);\n\n\t\ttry {\n\t\t\tawait loadPromise;\n\t\t\tthis.loadedLibraries.add(library.id);\n\t\t\tthis.stats.loaded.push(library.id);\n\n\t\t\tconst loadTime = performance.now() - startTime;\n\t\t\tthis.stats.totalLoadTime += loadTime;\n\n\t\t\tconsole.log(\n\t\t\t\t`[LibraryLoader] Successfully loaded ${library.id} in ${loadTime.toFixed(2)}ms`,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tthis.failedLibraries.set(library.id, error as Error);\n\t\t\tthis.stats.failed.push(library.id);\n\t\t\tconsole.error(`[LibraryLoader] Failed to load ${library.id}:`, error);\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\tthis.pendingLoads.delete(library.id);\n\t\t\tconst pendingIndex = this.stats.pending.indexOf(library.id);\n\t\t\tif (pendingIndex !== -1) {\n\t\t\t\tthis.stats.pending.splice(pendingIndex, 1);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Load a stylesheet\n\t */\n\tasync loadStylesheet(\n\t\turl: string,\n\t\ttargetRoot?: Document | ShadowRoot,\n\t): Promise<void> {\n\t\t// SSR guard: Stylesheet loading should NEVER run on the server\n\t\tif (typeof window === \"undefined\" || typeof document === \"undefined\") {\n\t\t\tthrow new Error(\"Stylesheet loader can only be used in the browser\");\n\t\t}\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst root = targetRoot ?? document;\n\n\t\t\t// Check if already loaded\n\t\t\tconst existing = root.querySelector(`link[href=\"${url}\"]`);\n\t\t\tif (existing) {\n\t\t\t\tresolve();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst link = document.createElement(\"link\");\n\t\t\tlink.rel = \"stylesheet\";\n\t\t\tlink.href = url;\n\n\t\t\tlink.onload = () => resolve();\n\t\t\tlink.onerror = () =>\n\t\t\t\treject(new Error(`Failed to load stylesheet: ${url}`));\n\n\t\t\tif (root instanceof ShadowRoot) {\n\t\t\t\troot.appendChild(link);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdocument.head.appendChild(link);\n\t\t});\n\t}\n\n\t/**\n\t * Check if a library is already loaded\n\t */\n\tisLoaded(libraryId: string): boolean {\n\t\treturn this.loadedLibraries.has(libraryId);\n\t}\n\n\t/**\n\t * Preload multiple libraries in parallel\n\t */\n\tasync preload(libraries: LibraryConfig[]): Promise<void> {\n\t\tconst promises = libraries.map((lib) => this.loadScript(lib));\n\t\tawait Promise.all(promises);\n\t}\n\n\t/**\n\t * Unload a library (remove script tag)\n\t */\n\tunload(libraryId: string): void {\n\t\tconst script = document.querySelector(\n\t\t\t`script[data-library-id=\"${libraryId}\"]`,\n\t\t);\n\t\tif (script) {\n\t\t\tscript.remove();\n\t\t\tthis.loadedLibraries.delete(libraryId);\n\n\t\t\t// Remove from stats\n\t\t\tconst loadedIndex = this.stats.loaded.indexOf(libraryId);\n\t\t\tif (loadedIndex !== -1) {\n\t\t\t\tthis.stats.loaded.splice(loadedIndex, 1);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Get loader statistics\n\t */\n\tgetStats(): LoaderStats {\n\t\treturn { ...this.stats };\n\t}\n\n\t/**\n\t * Load script with retry logic\n\t */\n\tprivate async _loadScriptWithRetry(library: LibraryConfig): Promise<void> {\n\t\tconst urls = [library.url, ...(library.fallbackUrls || [])];\n\t\tconst maxAttempts = library.retry?.maxAttempts || 3;\n\t\tconst delay = library.retry?.delay || 1000;\n\t\tconst backoffMultiplier = library.retry?.backoffMultiplier || 2;\n\n\t\tlet lastError: Error | null = null;\n\n\t\tfor (const url of urls) {\n\t\t\tfor (let attempt = 1; attempt <= maxAttempts; attempt++) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this._loadScriptFromUrl(url, library);\n\n\t\t\t\t\t// Verify library loaded if globalVar specified\n\t\t\t\t\tif (library.globalVar) {\n\t\t\t\t\t\tif (!(library.globalVar in window)) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`Library ${library.id} loaded but global ${library.globalVar} not found`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn; // Success\n\t\t\t\t} catch (error) {\n\t\t\t\t\tlastError = error as Error;\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`[LibraryLoader] Attempt ${attempt}/${maxAttempts} failed for ${url}:`,\n\t\t\t\t\t\terror,\n\t\t\t\t\t);\n\n\t\t\t\t\t// Wait before retry (exponential backoff)\n\t\t\t\t\tif (attempt < maxAttempts) {\n\t\t\t\t\t\tconst waitTime = delay * Math.pow(backoffMultiplier, attempt - 1);\n\t\t\t\t\t\tawait this._sleep(waitTime);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t`Failed to load library ${library.id} after trying all URLs: ${lastError?.message}`,\n\t\t);\n\t}\n\n\t/**\n\t * Load script from a specific URL\n\t */\n\tprivate _loadScriptFromUrl(\n\t\turl: string,\n\t\tlibrary: LibraryConfig,\n\t): Promise<void> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst script = document.createElement(\"script\");\n\t\t\tscript.src = url;\n\t\t\tscript.dataset.libraryId = library.id;\n\n\t\t\tif (library.async) script.async = true;\n\t\t\tif (library.defer) script.defer = true;\n\t\t\tif (library.integrity) script.integrity = library.integrity;\n\t\t\tif (library.crossorigin) script.crossOrigin = library.crossorigin;\n\n\t\t\tlet timeoutId: number | undefined;\n\n\t\t\tconst cleanup = () => {\n\t\t\t\tif (timeoutId) clearTimeout(timeoutId);\n\t\t\t\tscript.onload = null;\n\t\t\t\tscript.onerror = null;\n\t\t\t};\n\n\t\t\tscript.onload = () => {\n\t\t\t\tcleanup();\n\t\t\t\tresolve();\n\t\t\t};\n\n\t\t\tscript.onerror = (error) => {\n\t\t\t\tcleanup();\n\t\t\t\tscript.remove();\n\t\t\t\treject(new Error(`Script load error for ${url}: ${error}`));\n\t\t\t};\n\n\t\t\t// Timeout handling\n\t\t\tif (library.timeout) {\n\t\t\t\ttimeoutId = window.setTimeout(() => {\n\t\t\t\t\tcleanup();\n\t\t\t\t\tscript.remove();\n\t\t\t\t\treject(\n\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t`Script load timeout for ${url} after ${library.timeout}ms`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}, library.timeout);\n\t\t\t}\n\n\t\t\tdocument.head.appendChild(script);\n\t\t});\n\t}\n\n\t/**\n\t * Sleep utility for retry delays\n\t */\n\tprivate _sleep(ms: number): Promise<void> {\n\t\treturn new Promise((resolve) => setTimeout(resolve, ms));\n\t}\n}\n\n/**\n * Singleton instance\n */\nexport const libraryLoader = new LibraryLoaderImpl();\n\n/**\n * Desmos library version (matches the version in calculator.js)\n * Update this when upgrading to a new version\n */\nconst DESMOS_VERSION = \"v1.12\";\n\n/**\n * Common library configurations\n * Based on industry best practices and platform analyses\n */\nexport const COMMON_LIBRARIES: Record<string, LibraryConfig> = {\n\tdesmos: {\n\t\tid: \"desmos\",\n\t\turl: `/lib/desmos/${DESMOS_VERSION}/calculator.js`, // Self-hosted (prioritized) - versioned for better cache control\n\t\tfallbackUrls: [\n\t\t\t\"https://www.desmos.com/api/v1.12/calculator.js\",\n\t\t\t\"https://cdn.jsdelivr.net/npm/desmos@1.12/dist/calculator.js\",\n\t\t],\n\t\tglobalVar: \"Desmos\",\n\t\ttimeout: 10000,\n\t\tretry: { maxAttempts: 3, delay: 1000, backoffMultiplier: 2 },\n\t},\n\n\tmathjax: {\n\t\tid: \"mathjax\",\n\t\turl: \"https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js\",\n\t\tfallbackUrls: [\n\t\t\t\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-mml-chtml.min.js\",\n\t\t\t\"/static/lib/mathjax/tex-mml-chtml.js\",\n\t\t],\n\t\tglobalVar: \"MathJax\",\n\t\tasync: true,\n\t\tretry: { maxAttempts: 2, delay: 1500 },\n\t},\n\n\tkatex: {\n\t\tid: \"katex\",\n\t\turl: \"https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js\",\n\t\tfallbackUrls: [\n\t\t\t\"https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/katex.min.js\",\n\t\t\t\"/static/lib/katex/katex.min.js\",\n\t\t],\n\t\tglobalVar: \"katex\",\n\t\ttimeout: 5000,\n\t},\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pie-players/pie-assessment-toolkit",
3
- "version": "0.3.56",
3
+ "version": "0.3.57",
4
4
  "type": "module",
5
5
  "description": "PIE assessment toolkit: composable services + reference implementation for assessment players and tool coordination",
6
6
  "license": "MIT",
@@ -75,15 +75,15 @@
75
75
  "test": "bun test"
76
76
  },
77
77
  "dependencies": {
78
- "@pie-players/pie-calculator": "0.3.56",
79
- "@pie-players/pie-context": "0.3.56",
80
- "@pie-players/pie-players-shared": "0.3.56",
81
- "@pie-players/pie-tts": "0.3.56",
78
+ "@pie-players/pie-calculator": "0.3.57",
79
+ "@pie-players/pie-context": "0.3.57",
80
+ "@pie-players/pie-players-shared": "0.3.57",
81
+ "@pie-players/pie-tts": "0.3.57",
82
82
  "speech-rule-engine": "^5.0.0-rc.1"
83
83
  },
84
84
  "peerDependencies": {
85
- "@pie-players/pie-calculator-desmos": "0.3.56",
86
- "@pie-players/tts-client-server": "0.3.56"
85
+ "@pie-players/pie-calculator-desmos": "0.3.57",
86
+ "@pie-players/tts-client-server": "0.3.57"
87
87
  },
88
88
  "peerDependenciesMeta": {
89
89
  "@pie-players/pie-calculator-desmos": {