cnhkmcp 2.1.2__py3-none-any.whl → 2.1.3__py3-none-any.whl

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 (113) hide show
  1. {cnhkmcp-2.1.2.dist-info → cnhkmcp-2.1.3.dist-info}/METADATA +1 -1
  2. cnhkmcp-2.1.3.dist-info/RECORD +6 -0
  3. cnhkmcp-2.1.3.dist-info/top_level.txt +1 -0
  4. cnhkmcp/__init__.py +0 -125
  5. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/README.md +0 -38
  6. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/ace.log +0 -0
  7. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/config.json +0 -6
  8. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/get_knowledgeBase_tool/ace_lib.py +0 -1510
  9. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/get_knowledgeBase_tool/fetch_all_datasets.py +0 -157
  10. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/get_knowledgeBase_tool/fetch_all_documentation.py +0 -132
  11. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/get_knowledgeBase_tool/fetch_all_operators.py +0 -99
  12. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/get_knowledgeBase_tool/helpful_functions.py +0 -180
  13. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/icon.ico +0 -0
  14. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/icon.png +0 -0
  15. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/knowledge/test.txt +0 -1
  16. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/main.py +0 -576
  17. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/process_knowledge_base.py +0 -281
  18. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/rag_engine.py +0 -408
  19. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/requirements.txt +0 -7
  20. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/run.bat +0 -3
  21. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242//321/211/320/266/320/246/321/206/320/274/320/261/321/210/342/224/220/320/240/321/210/320/261/320/234/321/206/320/231/320/243/321/205/342/225/235/320/220/321/206/320/230/320/241.py +0 -265
  22. cnhkmcp/untracked/APP/.gitignore +0 -32
  23. cnhkmcp/untracked/APP/MODULAR_STRUCTURE.md +0 -112
  24. cnhkmcp/untracked/APP/README.md +0 -309
  25. cnhkmcp/untracked/APP/Tranformer/Transformer.py +0 -4985
  26. cnhkmcp/untracked/APP/Tranformer/ace.log +0 -0
  27. cnhkmcp/untracked/APP/Tranformer/ace_lib.py +0 -1510
  28. cnhkmcp/untracked/APP/Tranformer/helpful_functions.py +0 -180
  29. cnhkmcp/untracked/APP/Tranformer/output/Alpha_candidates.json +0 -2421
  30. cnhkmcp/untracked/APP/Tranformer/output/Alpha_candidates_/321/207/320/264/342/225/221/321/204/342/225/233/320/233.json +0 -654
  31. cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_error.json +0 -1034
  32. cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_success.json +0 -444
  33. cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_/321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/320/237/320/277/321/207/320/253/342/224/244/321/206/320/236/320/265/321/210/342/225/234/342/225/234/321/205/320/225/320/265Machine_lib.json +0 -22
  34. cnhkmcp/untracked/APP/Tranformer/parsetab.py +0 -60
  35. cnhkmcp/untracked/APP/Tranformer/template_summary.txt +0 -3182
  36. cnhkmcp/untracked/APP/Tranformer/transformer_config.json +0 -7
  37. cnhkmcp/untracked/APP/Tranformer/validator.py +0 -889
  38. cnhkmcp/untracked/APP/ace.log +0 -69
  39. cnhkmcp/untracked/APP/ace_lib.py +0 -1510
  40. cnhkmcp/untracked/APP/blueprints/__init__.py +0 -6
  41. cnhkmcp/untracked/APP/blueprints/feature_engineering.py +0 -347
  42. cnhkmcp/untracked/APP/blueprints/idea_house.py +0 -221
  43. cnhkmcp/untracked/APP/blueprints/inspiration_house.py +0 -432
  44. cnhkmcp/untracked/APP/blueprints/paper_analysis.py +0 -570
  45. cnhkmcp/untracked/APP/custom_templates/templates.json +0 -1257
  46. cnhkmcp/untracked/APP/give_me_idea/BRAIN_Alpha_Template_Expert_SystemPrompt.md +0 -400
  47. cnhkmcp/untracked/APP/give_me_idea/ace_lib.py +0 -1510
  48. cnhkmcp/untracked/APP/give_me_idea/alpha_data_specific_template_master.py +0 -252
  49. cnhkmcp/untracked/APP/give_me_idea/fetch_all_datasets.py +0 -157
  50. cnhkmcp/untracked/APP/give_me_idea/fetch_all_operators.py +0 -99
  51. cnhkmcp/untracked/APP/give_me_idea/helpful_functions.py +0 -180
  52. cnhkmcp/untracked/APP/give_me_idea/what_is_Alpha_template.md +0 -11
  53. cnhkmcp/untracked/APP/helpful_functions.py +0 -180
  54. cnhkmcp/untracked/APP/hkSimulator/ace_lib.py +0 -1497
  55. cnhkmcp/untracked/APP/hkSimulator/autosimulator.py +0 -447
  56. cnhkmcp/untracked/APP/hkSimulator/helpful_functions.py +0 -180
  57. cnhkmcp/untracked/APP/mirror_config.txt +0 -20
  58. cnhkmcp/untracked/APP/operaters.csv +0 -129
  59. cnhkmcp/untracked/APP/requirements.txt +0 -53
  60. cnhkmcp/untracked/APP/run_app.bat +0 -28
  61. cnhkmcp/untracked/APP/run_app.sh +0 -34
  62. cnhkmcp/untracked/APP/setup_tsinghua.bat +0 -39
  63. cnhkmcp/untracked/APP/setup_tsinghua.sh +0 -43
  64. cnhkmcp/untracked/APP/simulator/alpha_submitter.py +0 -404
  65. cnhkmcp/untracked/APP/simulator/simulator_wqb.py +0 -618
  66. cnhkmcp/untracked/APP/ssrn-3332513.pdf +6 -109201
  67. cnhkmcp/untracked/APP/static/brain.js +0 -589
  68. cnhkmcp/untracked/APP/static/decoder.js +0 -1540
  69. cnhkmcp/untracked/APP/static/feature_engineering.js +0 -1729
  70. cnhkmcp/untracked/APP/static/idea_house.js +0 -937
  71. cnhkmcp/untracked/APP/static/inspiration.js +0 -465
  72. cnhkmcp/untracked/APP/static/inspiration_house.js +0 -868
  73. cnhkmcp/untracked/APP/static/paper_analysis.js +0 -390
  74. cnhkmcp/untracked/APP/static/script.js +0 -3082
  75. cnhkmcp/untracked/APP/static/simulator.js +0 -597
  76. cnhkmcp/untracked/APP/static/styles.css +0 -3127
  77. cnhkmcp/untracked/APP/static/usage_widget.js +0 -508
  78. cnhkmcp/untracked/APP/templates/alpha_inspector.html +0 -511
  79. cnhkmcp/untracked/APP/templates/feature_engineering.html +0 -960
  80. cnhkmcp/untracked/APP/templates/idea_house.html +0 -564
  81. cnhkmcp/untracked/APP/templates/index.html +0 -932
  82. cnhkmcp/untracked/APP/templates/inspiration_house.html +0 -861
  83. cnhkmcp/untracked/APP/templates/paper_analysis.html +0 -91
  84. cnhkmcp/untracked/APP/templates/simulator.html +0 -343
  85. cnhkmcp/untracked/APP/templates/transformer_web.html +0 -580
  86. cnhkmcp/untracked/APP/usage.md +0 -351
  87. cnhkmcp/untracked/APP//321/207/342/225/235/320/250/321/205/320/230/320/226/321/204/342/225/225/320/220/321/211/320/221/320/243/321/206/320/261/320/265/ace_lib.py +0 -1510
  88. cnhkmcp/untracked/APP//321/207/342/225/235/320/250/321/205/320/230/320/226/321/204/342/225/225/320/220/321/211/320/221/320/243/321/206/320/261/320/265/brain_alpha_inspector.py +0 -712
  89. cnhkmcp/untracked/APP//321/207/342/225/235/320/250/321/205/320/230/320/226/321/204/342/225/225/320/220/321/211/320/221/320/243/321/206/320/261/320/265/helpful_functions.py +0 -180
  90. cnhkmcp/untracked/APP//321/210/342/224/220/320/240/321/210/320/261/320/234/321/206/320/231/320/243/321/205/342/225/235/320/220/321/206/320/230/320/241.py +0 -2456
  91. cnhkmcp/untracked/arXiv_API_Tool_Manual.md +0 -490
  92. cnhkmcp/untracked/arxiv_api.py +0 -229
  93. cnhkmcp/untracked/forum_functions.py +0 -998
  94. cnhkmcp/untracked/mcp/321/206/320/246/320/227/321/204/342/225/227/342/225/242/321/210/320/276/342/225/221/321/205/320/255/320/253/321/207/320/231/320/2302_/321/205/320/266/320/222/321/206/320/256/320/254/321/205/320/236/320/257/321/207/320/231/320/230/321/205/320/240/320/277/321/205/320/232/320/270/321/204/342/225/225/320/235/321/204/342/225/221/320/226/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270/321/205/342/226/221/342/226/222/321/210/320/277/320/245/321/210/342/224/220/320/251/321/204/342/225/225/320/272/forum_functions.py +0 -407
  95. cnhkmcp/untracked/mcp/321/206/320/246/320/227/321/204/342/225/227/342/225/242/321/210/320/276/342/225/221/321/205/320/255/320/253/321/207/320/231/320/2302_/321/205/320/266/320/222/321/206/320/256/320/254/321/205/320/236/320/257/321/207/320/231/320/230/321/205/320/240/320/277/321/205/320/232/320/270/321/204/342/225/225/320/235/321/204/342/225/221/320/226/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270/321/205/342/226/221/342/226/222/321/210/320/277/320/245/321/210/342/224/220/320/251/321/204/342/225/225/320/272/platform_functions.py +0 -2415
  96. cnhkmcp/untracked/mcp/321/206/320/246/320/227/321/204/342/225/227/342/225/242/321/210/320/276/342/225/221/321/205/320/255/320/253/321/207/320/231/320/2302_/321/205/320/266/320/222/321/206/320/256/320/254/321/205/320/236/320/257/321/207/320/231/320/230/321/205/320/240/320/277/321/205/320/232/320/270/321/204/342/225/225/320/235/321/204/342/225/221/320/226/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270/321/205/342/226/221/342/226/222/321/210/320/277/320/245/321/210/342/224/220/320/251/321/204/342/225/225/320/272/user_config.json +0 -31
  97. cnhkmcp/untracked/mcp/321/206/320/246/320/227/321/204/342/225/227/342/225/242/321/210/320/276/342/225/221/321/205/320/255/320/253/321/207/320/231/320/2302_/321/205/320/266/320/222/321/206/320/256/320/254/321/205/320/236/320/257/321/207/320/231/320/230/321/205/320/240/320/277/321/205/320/232/320/270/321/204/342/225/225/320/235/321/204/342/225/221/320/226/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270/321/205/342/226/221/342/226/222/321/210/320/277/320/245/321/210/342/224/220/320/251/321/204/342/225/225/320/272//321/210/320/276/320/271AI/321/210/320/277/342/225/227/321/210/342/224/220/320/251/321/204/342/225/225/320/272/321/206/320/246/320/227/321/206/320/261/320/263/321/206/320/255/320/265/321/205/320/275/320/266/321/204/342/225/235/320/252/321/204/342/225/225/320/233/321/210/342/225/234/342/225/234/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270.md +0 -101
  98. cnhkmcp/untracked/mcp/321/206/320/246/320/227/321/204/342/225/227/342/225/242/321/210/320/276/342/225/221/321/205/320/255/320/253/321/207/320/231/320/2302_/321/205/320/266/320/222/321/206/320/256/320/254/321/205/320/236/320/257/321/207/320/231/320/230/321/205/320/240/320/277/321/205/320/232/320/270/321/204/342/225/225/320/235/321/204/342/225/221/320/226/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270/321/205/342/226/221/342/226/222/321/210/320/277/320/245/321/210/342/224/220/320/251/321/204/342/225/225/320/272//321/211/320/225/320/235/321/207/342/225/234/320/276/321/205/320/231/320/235/321/210/342/224/220/320/240/321/210/320/261/320/234/321/206/320/230/320/241_/321/205/320/276/320/231/321/210/320/263/320/225/321/205/342/224/220/320/225/321/210/320/266/320/221/321/204/342/225/233/320/255/321/210/342/225/241/320/246/321/205/320/234/320/225.py +0 -190
  99. cnhkmcp/untracked/platform_functions.py +0 -2886
  100. cnhkmcp/untracked/sample_mcp_config.json +0 -11
  101. cnhkmcp/untracked/user_config.json +0 -31
  102. cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/320/237/320/222/321/210/320/220/320/223/321/206/320/246/320/227/321/206/320/261/320/263_BRAIN_Alpha_Test_Requirements_and_Tips.md +0 -202
  103. cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/342/225/226/320/265/321/204/342/225/234/320/254/321/206/342/225/241/320/221_Alpha_explaination_workflow.md +0 -56
  104. cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/342/225/226/320/265/321/204/342/225/234/320/254/321/206/342/225/241/320/221_BRAIN_6_Tips_Datafield_Exploration_Guide.md +0 -194
  105. cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/342/225/226/320/265/321/204/342/225/234/320/254/321/206/342/225/241/320/221_BRAIN_Alpha_Improvement_Workflow.md +0 -101
  106. cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/342/225/226/320/265/321/204/342/225/234/320/254/321/206/342/225/241/320/221_Dataset_Exploration_Expert_Manual.md +0 -436
  107. cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/342/225/226/320/265/321/204/342/225/234/320/254/321/206/342/225/241/320/221_daily_report_workflow.md +0 -128
  108. cnhkmcp/untracked//321/211/320/225/320/235/321/207/342/225/234/320/276/321/205/320/231/320/235/321/210/342/224/220/320/240/321/210/320/261/320/234/321/206/320/230/320/241_/321/205/320/276/320/231/321/210/320/263/320/225/321/205/342/224/220/320/225/321/210/320/266/320/221/321/204/342/225/233/320/255/321/210/342/225/241/320/246/321/205/320/234/320/225.py +0 -190
  109. cnhkmcp-2.1.2.dist-info/RECORD +0 -111
  110. cnhkmcp-2.1.2.dist-info/top_level.txt +0 -1
  111. {cnhkmcp-2.1.2.dist-info → cnhkmcp-2.1.3.dist-info}/WHEEL +0 -0
  112. {cnhkmcp-2.1.2.dist-info → cnhkmcp-2.1.3.dist-info}/entry_points.txt +0 -0
  113. {cnhkmcp-2.1.2.dist-info → cnhkmcp-2.1.3.dist-info}/licenses/LICENSE +0 -0
@@ -1,868 +0,0 @@
1
- // Inspiration House JavaScript
2
-
3
- // Store API key and state in session storage
4
- let apiKey = sessionStorage.getItem('deepseekApiKey');
5
- let modelProvider = sessionStorage.getItem('inspirationHouseProvider') || 'deepseek';
6
- let modelName = sessionStorage.getItem('inspirationHouseModelName') || 'deepseek-chat';
7
- let researchTarget = sessionStorage.getItem('inspirationHouseTarget') || '';
8
- let currentExpression = sessionStorage.getItem('inspirationHouseExpression') || '';
9
- let expressionContext = sessionStorage.getItem('inspirationHouseContext') || '';
10
- let evaluationResults = JSON.parse(sessionStorage.getItem('inspirationHouseResults')) || [];
11
- let operatorsList = JSON.parse(sessionStorage.getItem('brainOperators')) || [];
12
- let isEvaluating = false;
13
- let evaluationProgress = 0;
14
- let totalOperators = 0;
15
- let batchSize = parseInt(sessionStorage.getItem('inspirationHouseBatchSize')) || 100; // Configurable batch size
16
-
17
- // DOM Elements
18
- const modelProviderSelect = document.getElementById('modelProvider');
19
- const apiKeyInput = document.getElementById('apiKey');
20
- const modelNameInput = document.getElementById('modelName');
21
- const batchSizeInput = document.getElementById('batchSize');
22
- const saveApiKeyBtn = document.getElementById('saveApiKey');
23
- const apiConfigSection = document.getElementById('apiConfigSection');
24
- const showApiConfigSection = document.getElementById('showApiConfigSection');
25
- const showApiConfigBtn = document.getElementById('showApiConfig');
26
- const editTargetBtn = document.getElementById('editTarget');
27
- const targetDisplay = document.getElementById('targetDisplay');
28
- const targetText = document.getElementById('targetText');
29
- const targetInputGroup = document.getElementById('targetInputGroup');
30
- const researchTargetInput = document.getElementById('researchTarget');
31
- const saveTargetBtn = document.getElementById('saveTarget');
32
- const cancelTargetBtn = document.getElementById('cancelTarget');
33
- const currentExpressionInput = document.getElementById('currentExpression');
34
- const expressionContextInput = document.getElementById('expressionContext');
35
- const loadFromBRAINBtn = document.getElementById('loadFromBRAIN');
36
- const startEvaluationBtn = document.getElementById('startEvaluation');
37
- const refreshEvaluationBtn = document.getElementById('refreshEvaluation');
38
- const exportResultsBtn = document.getElementById('exportResults');
39
- const clearResultsBtn = document.getElementById('clearResults');
40
- const evaluationTableBody = document.getElementById('evaluationTableBody');
41
- const progressSection = document.getElementById('progressSection');
42
- const progressFill = document.getElementById('progressFill');
43
- const progressText = document.getElementById('progressText');
44
- const progressCount = document.getElementById('progressCount');
45
- const summaryStats = document.getElementById('summaryStats');
46
- const highScoreCount = document.getElementById('highScoreCount');
47
- const mediumScoreCount = document.getElementById('mediumScoreCount');
48
- const lowScoreCount = document.getElementById('lowScoreCount');
49
- const totalEvaluated = document.getElementById('totalEvaluated');
50
- const minScoreFilter = document.getElementById('minScoreFilter');
51
- const maxScoreFilter = document.getElementById('maxScoreFilter');
52
- const minScoreValue = document.getElementById('minScoreValue');
53
- const maxScoreValue = document.getElementById('maxScoreValue');
54
- const showHighScores = document.getElementById('showHighScores');
55
- const showMediumScores = document.getElementById('showMediumScores');
56
- const showLowScores = document.getElementById('showLowScores');
57
- const exportHighScoresBtn = document.getElementById('exportHighScores');
58
- const exportAllResultsBtn = document.getElementById('exportAllResults');
59
- const exportCSVBtn = document.getElementById('exportCSV');
60
- const currentBatchSizeSpan = document.getElementById('currentBatchSize');
61
-
62
- // Initialize API key if exists
63
- if (apiKey) {
64
- apiKeyInput.value = apiKey;
65
- }
66
-
67
- // Initialize model provider and name
68
- modelProviderSelect.value = modelProvider;
69
- modelNameInput.value = modelName;
70
-
71
- // Initialize batch size
72
- batchSizeInput.value = batchSize;
73
- currentBatchSizeSpan.textContent = operatorsList.length;
74
-
75
- // Update model name placeholder based on provider
76
- function updateModelNamePlaceholder() {
77
- const provider = modelProviderSelect.value;
78
- if (provider === 'kimi') {
79
- modelNameInput.placeholder = 'e.g., kimi-k2-0711-preview';
80
- if (modelNameInput.value === 'deepseek-chat') {
81
- modelNameInput.value = 'kimi-k2-0711-preview';
82
- }
83
- } else {
84
- modelNameInput.placeholder = 'e.g., deepseek-chat, deepseek-coder';
85
- if (modelNameInput.value === 'kimi-k2-0711-preview') {
86
- modelNameInput.value = 'deepseek-chat';
87
- }
88
- }
89
- }
90
-
91
- // Model provider change handler
92
- modelProviderSelect.addEventListener('change', () => {
93
- modelProvider = modelProviderSelect.value;
94
- sessionStorage.setItem('inspirationHouseProvider', modelProvider);
95
- updateModelNamePlaceholder();
96
- });
97
-
98
- // Model name change handler
99
- modelNameInput.addEventListener('input', () => {
100
- modelName = modelNameInput.value;
101
- sessionStorage.setItem('inspirationHouseModelName', modelName);
102
- });
103
-
104
- // Save batch size when changed
105
- batchSizeInput.addEventListener('change', () => {
106
- batchSize = parseInt(batchSizeInput.value) || 100;
107
- sessionStorage.setItem('inspirationHouseBatchSize', batchSize.toString());
108
- console.log(`Batch size updated to: ${batchSize}`);
109
- });
110
-
111
- // Initialize placeholder on page load
112
- updateModelNamePlaceholder();
113
-
114
- // Check if API is already configured and hide config section if so
115
- function checkApiConfigStatus() {
116
- if (apiKey && modelProvider && modelName) {
117
- apiConfigSection.style.display = 'none';
118
- showApiConfigSection.style.display = 'block';
119
- } else {
120
- apiConfigSection.style.display = 'block';
121
- showApiConfigSection.style.display = 'none';
122
- }
123
- }
124
-
125
- // Show API Config button event listener
126
- showApiConfigBtn.addEventListener('click', () => {
127
- apiConfigSection.style.display = 'block';
128
- showApiConfigSection.style.display = 'none';
129
- });
130
-
131
- // Load existing state on page load
132
- window.addEventListener('DOMContentLoaded', () => {
133
- console.log('Loading Inspiration House state...');
134
- console.log('Research target:', researchTarget);
135
- console.log('Current expression:', currentExpression);
136
- console.log('Evaluation results:', evaluationResults);
137
- console.log('Operators list length:', operatorsList.length);
138
-
139
- // Check API config status
140
- checkApiConfigStatus();
141
-
142
- // Load saved state
143
- if (researchTarget) {
144
- targetText.textContent = researchTarget;
145
- }
146
-
147
- if (currentExpression) {
148
- currentExpressionInput.value = currentExpression;
149
- }
150
-
151
- if (expressionContext) {
152
- expressionContextInput.value = expressionContext;
153
- }
154
-
155
- // Check for operators in sessionStorage (from brain.js)
156
- refreshOperatorsFromSessionStorage();
157
-
158
- // Update operator count display
159
- currentBatchSizeSpan.textContent = operatorsList.length;
160
-
161
- // Load operators if not already loaded
162
- if (operatorsList.length === 0) {
163
- loadOperatorsFromBRAIN();
164
- }
165
-
166
- // Add a fallback message if no operators are available
167
- if (operatorsList.length === 0) {
168
- console.log('No operators loaded yet. Will load when BRAIN is connected.');
169
- }
170
-
171
- // Display existing results
172
- if (evaluationResults.length > 0) {
173
- displayEvaluationResults();
174
- updateSummaryStats();
175
- }
176
-
177
- // Setup filter event listeners
178
- setupFilters();
179
- });
180
-
181
- // Function to refresh operators from sessionStorage (called after BRAIN login)
182
- function refreshOperatorsFromSessionStorage() {
183
- const storedOperators = sessionStorage.getItem('brainOperators');
184
- if (storedOperators) {
185
- try {
186
- operatorsList = JSON.parse(storedOperators);
187
- currentBatchSizeSpan.textContent = operatorsList.length;
188
- console.log(`Refreshed ${operatorsList.length} operators from sessionStorage`);
189
- } catch (error) {
190
- console.error('Error parsing operators from sessionStorage:', error);
191
- }
192
- }
193
- }
194
-
195
- // Save API Key and Test Connection
196
- saveApiKeyBtn.addEventListener('click', async () => {
197
- const newApiKey = apiKeyInput.value.trim();
198
- const newProvider = modelProviderSelect.value;
199
- const newModelName = modelNameInput.value.trim();
200
-
201
- if (!newApiKey) {
202
- showNotification('Please enter a valid API key', 'error');
203
- return;
204
- }
205
-
206
- if (!newModelName) {
207
- showNotification('Please enter a model name', 'error');
208
- return;
209
- }
210
-
211
- try {
212
- showLoading('Testing API connection...');
213
-
214
- const response = await fetch('/inspiration-house/api/test-deepseek', {
215
- method: 'POST',
216
- headers: {
217
- 'X-API-Key': newApiKey,
218
- 'Content-Type': 'application/json'
219
- },
220
- body: JSON.stringify({
221
- provider: newProvider,
222
- model_name: newModelName
223
- })
224
- });
225
-
226
- const data = await response.json();
227
-
228
- if (response.ok && data.success) {
229
- sessionStorage.setItem('deepseekApiKey', newApiKey);
230
- sessionStorage.setItem('inspirationHouseProvider', newProvider);
231
- sessionStorage.setItem('inspirationHouseModelName', newModelName);
232
- apiKey = newApiKey;
233
- modelProvider = newProvider;
234
- modelName = newModelName;
235
- showNotification(`${newProvider.charAt(0).toUpperCase() + newProvider.slice(1)} API connection successful`, 'success');
236
-
237
- // Hide API config section after successful configuration
238
- apiConfigSection.style.display = 'none';
239
- showApiConfigSection.style.display = 'block';
240
- } else {
241
- showNotification(`API Error: ${data.error || 'Unknown error'}`, 'error');
242
- console.error('API Error Details:', data);
243
-
244
- // Provide specific guidance for Kimi API issues
245
- if (newProvider === 'kimi' && data.error) {
246
- console.log('Kimi API troubleshooting tips:');
247
- console.log('1. Make sure you have a valid Kimi API key');
248
- console.log('2. Check if your Kimi account has API access enabled');
249
- console.log('3. Verify the model name is correct (e.g., kimi-k2-0711-preview)');
250
- console.log('4. Ensure you have sufficient API credits/quota');
251
- }
252
- }
253
- } catch (error) {
254
- showNotification('Error testing API connection: ' + error.message, 'error');
255
- console.error('API Test Error:', error);
256
- } finally {
257
- hideLoading();
258
- }
259
- });
260
-
261
- // Target Management
262
- editTargetBtn.addEventListener('click', () => {
263
- targetDisplay.style.display = 'none';
264
- targetInputGroup.style.display = 'block';
265
- researchTargetInput.value = researchTarget;
266
- researchTargetInput.focus();
267
- });
268
-
269
- saveTargetBtn.addEventListener('click', () => {
270
- const newTarget = researchTargetInput.value.trim();
271
- if (!newTarget) {
272
- showNotification('Please enter a research target', 'error');
273
- return;
274
- }
275
-
276
- researchTarget = newTarget;
277
- targetText.textContent = researchTarget;
278
- sessionStorage.setItem('inspirationHouseTarget', researchTarget);
279
-
280
- targetDisplay.style.display = 'block';
281
- targetInputGroup.style.display = 'none';
282
-
283
- showNotification('Research target saved successfully', 'success');
284
- });
285
-
286
- cancelTargetBtn.addEventListener('click', () => {
287
- targetDisplay.style.display = 'block';
288
- targetInputGroup.style.display = 'none';
289
- researchTargetInput.value = researchTarget;
290
- });
291
-
292
- // Expression Management
293
- currentExpressionInput.addEventListener('input', () => {
294
- currentExpression = currentExpressionInput.value;
295
- sessionStorage.setItem('inspirationHouseExpression', currentExpression);
296
- });
297
-
298
- expressionContextInput.addEventListener('input', () => {
299
- expressionContext = expressionContextInput.value;
300
- sessionStorage.setItem('inspirationHouseContext', expressionContext);
301
- });
302
-
303
- // Load from BRAIN
304
- loadFromBRAINBtn.addEventListener('click', () => {
305
- if (!sessionStorage.getItem('brain_session_id')) {
306
- // Use the same login modal as the main page
307
- if (window.brainAPI && window.brainAPI.openBrainLoginModal) {
308
- window.brainAPI.openBrainLoginModal();
309
- } else {
310
- showNotification('BRAIN login not available. Please go to the main page to connect to BRAIN.', 'error');
311
- return;
312
- }
313
-
314
- // Set up a listener for when operators are loaded (after successful login)
315
- const checkOperatorsInterval = setInterval(() => {
316
- const storedOperators = sessionStorage.getItem('brainOperators');
317
- if (storedOperators) {
318
- clearInterval(checkOperatorsInterval);
319
- refreshOperatorsFromSessionStorage();
320
- showNotification(`Loaded ${operatorsList.length} operators from BRAIN`, 'success');
321
- }
322
- }, 1000);
323
-
324
- // Stop checking after 30 seconds
325
- setTimeout(() => {
326
- clearInterval(checkOperatorsInterval);
327
- }, 30000);
328
- } else {
329
- // Load current expression from BRAIN (placeholder for now)
330
- showNotification('Loading from BRAIN...', 'warning');
331
- // TODO: Implement BRAIN expression loading
332
- }
333
- });
334
-
335
- // Start AI Evaluation
336
- startEvaluationBtn.addEventListener('click', async () => {
337
- if (!apiKey) {
338
- showNotification('Please configure your Deepseek API key first', 'error');
339
- return;
340
- }
341
-
342
- if (!researchTarget) {
343
- showNotification('Please set a research target first', 'error');
344
- return;
345
- }
346
-
347
- if (!currentExpression) {
348
- showNotification('Please enter your current expression', 'error');
349
- return;
350
- }
351
-
352
- if (operatorsList.length === 0) {
353
- showNotification('No operators available. Please connect to BRAIN first to load operators.', 'warning');
354
- return;
355
- }
356
-
357
- if (isEvaluating) {
358
- showNotification('Evaluation already in progress', 'warning');
359
- return;
360
- }
361
-
362
- try {
363
- isEvaluating = true;
364
- startEvaluationBtn.disabled = true;
365
- startEvaluationBtn.textContent = 'Evaluating...';
366
-
367
- showProgressSection();
368
- evaluationResults = [];
369
-
370
- // Update progress to show batch processing
371
- progressText.textContent = `Evaluating ${totalOperators} operators with batch size ${batchSize}...`;
372
- progressCount.textContent = `0 / ${totalOperators}`;
373
- progressFill.style.width = '0%';
374
- progressFill.textContent = 'Starting...';
375
-
376
- await evaluateAllOperators();
377
-
378
- // Update progress to show completion
379
- progressFill.style.width = '100%';
380
- progressFill.textContent = '100%';
381
- progressCount.textContent = `${totalOperators} / ${totalOperators}`;
382
- progressText.textContent = 'Evaluation completed!';
383
-
384
- showNotification('Evaluation completed successfully', 'success');
385
- } catch (error) {
386
- showNotification('Error during evaluation: ' + error.message, 'error');
387
- console.error('Evaluation Error:', error);
388
- } finally {
389
- isEvaluating = false;
390
- startEvaluationBtn.disabled = false;
391
- startEvaluationBtn.textContent = 'Start AI Evaluation';
392
- hideProgressSection();
393
- }
394
- });
395
-
396
- // Evaluate all operators using multithreading
397
- async function evaluateAllOperators() {
398
- totalOperators = operatorsList.length;
399
- evaluationProgress = 0;
400
-
401
- console.log(`Starting evaluation of ${totalOperators} operators with ${totalOperators} workers...`);
402
-
403
- // Use the new batch evaluation endpoint for better performance
404
- try {
405
- const response = await fetch('/inspiration-house/api/batch-evaluate', {
406
- method: 'POST',
407
- headers: {
408
- 'X-API-Key': apiKey,
409
- 'Content-Type': 'application/json'
410
- },
411
- body: JSON.stringify({
412
- operators: operatorsList,
413
- research_target: researchTarget,
414
- current_expression: currentExpression,
415
- expression_context: expressionContext,
416
- batch_size: batchSize,
417
- provider: modelProvider,
418
- model_name: modelName
419
- })
420
- });
421
-
422
- const data = await response.json();
423
-
424
- if (response.ok && data.success) {
425
- evaluationResults = data.results;
426
- console.log(`Batch evaluation completed. Processed ${evaluationResults.length} operators with ${data.workers_used} workers`);
427
- showNotification(`Evaluation completed! Processed ${evaluationResults.length} operators using ${data.workers_used} parallel workers`, 'success');
428
- } else {
429
- console.error('Batch evaluation failed:', data.error);
430
- showNotification(`Evaluation failed: ${data.error}`, 'error');
431
- return;
432
- }
433
- } catch (error) {
434
- console.error('Error in batch evaluation:', error);
435
- showNotification(`Evaluation error: ${error.message}`, 'error');
436
- return;
437
- }
438
-
439
- // Save results
440
- saveEvaluationResults();
441
-
442
- // Display results
443
- displayEvaluationResults();
444
- updateSummaryStats();
445
-
446
- console.log(`Evaluation completed. Processed ${evaluationResults.length} operators.`);
447
- }
448
-
449
- // Evaluate a single operator
450
- async function evaluateSingleOperator(operator) {
451
- try {
452
- const response = await fetch('/inspiration-house/api/evaluate-operator', {
453
- method: 'POST',
454
- headers: {
455
- 'X-API-Key': apiKey,
456
- 'Content-Type': 'application/json'
457
- },
458
- body: JSON.stringify({
459
- operator: operator,
460
- research_target: researchTarget,
461
- current_expression: currentExpression,
462
- expression_context: expressionContext,
463
- provider: modelProvider,
464
- model_name: modelName
465
- })
466
- });
467
-
468
- const data = await response.json();
469
-
470
- if (response.ok && data.success) {
471
- return {
472
- operator: operator.name,
473
- category: operator.category || 'Unknown',
474
- score: data.score,
475
- reason: data.reason,
476
- timestamp: new Date().toISOString()
477
- };
478
- } else {
479
- console.error(`API Error for operator ${operator.name}:`, data.error);
480
- return {
481
- operator: operator.name,
482
- category: operator.category || 'Unknown',
483
- score: 0,
484
- reason: `Error: ${data.error || 'Unknown error'}`,
485
- timestamp: new Date().toISOString()
486
- };
487
- }
488
- } catch (error) {
489
- console.error(`Network error for operator ${operator.name}:`, error);
490
- return {
491
- operator: operator.name,
492
- category: operator.category || 'Unknown',
493
- score: 0,
494
- reason: `Network error: ${error.message}`,
495
- timestamp: new Date().toISOString()
496
- };
497
- }
498
- }
499
-
500
- // Load operators from BRAIN
501
- async function loadOperatorsFromBRAIN() {
502
- try {
503
- const response = await fetch('/api/operators');
504
- const data = await response.json();
505
-
506
- if (response.ok && Array.isArray(data)) {
507
- operatorsList = data;
508
- sessionStorage.setItem('brainOperators', JSON.stringify(operatorsList));
509
- currentBatchSizeSpan.textContent = operatorsList.length;
510
- console.log(`Loaded ${operatorsList.length} operators from BRAIN`);
511
- showNotification(`Loaded ${operatorsList.length} operators from BRAIN`, 'success');
512
- } else {
513
- console.error('Failed to load operators:', data.error);
514
- if (data.error && data.error.includes('Invalid or expired session')) {
515
- showNotification('Please connect to BRAIN first to load operators', 'warning');
516
- } else {
517
- showNotification('Failed to load operators from BRAIN', 'error');
518
- }
519
- }
520
- } catch (error) {
521
- console.error('Error loading operators:', error);
522
- showNotification('Error connecting to BRAIN API', 'error');
523
- }
524
- }
525
-
526
- // Convert markdown to HTML for better display
527
- function convertMarkdownToHTML(text) {
528
- if (!text) return '';
529
-
530
- return text
531
- // Bold text: **text** -> <strong>text</strong>
532
- .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
533
- // Italic text: *text* -> <em>text</em>
534
- .replace(/\*(.*?)\*/g, '<em>$1</em>')
535
- // Code: `text` -> <code>text</code>
536
- .replace(/`(.*?)`/g, '<code>$1</code>')
537
- // Headers: ### text -> <h4>text</h4>
538
- .replace(/^### (.+)$/gm, '<h4>$1</h4>')
539
- .replace(/^## (.+)$/gm, '<h3>$1</h3>')
540
- .replace(/^# (.+)$/gm, '<h2>$1</h2>')
541
- // Lists: - item -> <li>item</li>
542
- .replace(/^- (.+)$/gm, '<li>$1</li>')
543
- // Numbered lists: 1. item -> <li>item</li>
544
- .replace(/^(\d+)\. (.+)$/gm, '<li>$2</li>')
545
- // Line breaks: \n -> <br>
546
- .replace(/\n/g, '<br>')
547
- // Escape HTML characters
548
- .replace(/&/g, '&amp;')
549
- .replace(/</g, '&lt;')
550
- .replace(/>/g, '&gt;')
551
- // Restore our HTML tags
552
- .replace(/&lt;strong&gt;/g, '<strong>')
553
- .replace(/&lt;\/strong&gt;/g, '</strong>')
554
- .replace(/&lt;em&gt;/g, '<em>')
555
- .replace(/&lt;\/em&gt;/g, '</em>')
556
- .replace(/&lt;code&gt;/g, '<code>')
557
- .replace(/&lt;\/code&gt;/g, '</code>')
558
- .replace(/&lt;br&gt;/g, '<br>')
559
- .replace(/&lt;h[234]&gt;/g, '<$1>')
560
- .replace(/&lt;\/h[234]&gt;/g, '</$1>')
561
- .replace(/&lt;li&gt;/g, '<li>')
562
- .replace(/&lt;\/li&gt;/g, '</li>');
563
- }
564
-
565
- // Display evaluation results
566
- function displayEvaluationResults() {
567
- if (evaluationResults.length === 0) {
568
- evaluationTableBody.innerHTML = `
569
- <tr>
570
- <td colspan="5" style="text-align: center; color: #7f8c8d; font-style: italic; padding: 40px;">
571
- No evaluations yet. Set your target and expression, then click "Start AI Evaluation".
572
- </td>
573
- </tr>
574
- `;
575
- return;
576
- }
577
-
578
- // Apply filters
579
- const filteredResults = applyFilters(evaluationResults);
580
-
581
- // Sort by score (highest first)
582
- filteredResults.sort((a, b) => b.score - a.score);
583
-
584
- evaluationTableBody.innerHTML = filteredResults.map(result => {
585
- // Find the operator details from the operators list
586
- const operatorDetails = operatorsList.find(op => op.name === result.operator);
587
- const description = operatorDetails ? operatorDetails.description || '' : '';
588
- const definition = operatorDetails ? operatorDetails.definition || '' : '';
589
-
590
- return `
591
- <tr>
592
- <td>
593
- <div class="operator-name">${result.operator}</div>
594
- <div class="operator-category">${result.category}</div>
595
- ${description ? `<div class="operator-description">${convertMarkdownToHTML(description)}</div>` : ''}
596
- ${definition ? `<div class="operator-definition"><strong>Definition:</strong> ${convertMarkdownToHTML(definition)}</div>` : ''}
597
- </td>
598
- <td>${result.category}</td>
599
- <td class="score-cell ${getScoreClass(result.score)}">${result.score}/10</td>
600
- <td>
601
- <div class="reason-text">${convertMarkdownToHTML(result.reason)}</div>
602
- </td>
603
- <td>
604
- <button class="btn btn-small" onclick="reevaluateOperator('${result.operator}')">Re-evaluate</button>
605
- </td>
606
- </tr>
607
- `;
608
- }).join('');
609
- }
610
-
611
- // Apply filters to results
612
- function applyFilters(results) {
613
- const minScore = parseInt(minScoreFilter.value);
614
- const maxScore = parseInt(maxScoreFilter.value);
615
-
616
- return results.filter(result => {
617
- const score = result.score;
618
-
619
- // Score range filter
620
- if (score < minScore || score > maxScore) {
621
- return false;
622
- }
623
-
624
- // Score category filters
625
- if (score >= 8 && !showHighScores.checked) return false;
626
- if (score >= 4 && score < 8 && !showMediumScores.checked) return false;
627
- if (score < 4 && !showLowScores.checked) return false;
628
-
629
- return true;
630
- });
631
- }
632
-
633
- // Get CSS class for score
634
- function getScoreClass(score) {
635
- if (score >= 8) return 'score-high';
636
- if (score >= 4) return 'score-medium';
637
- return 'score-low';
638
- }
639
-
640
- // Setup filter event listeners
641
- function setupFilters() {
642
- minScoreFilter.addEventListener('input', () => {
643
- minScoreValue.textContent = minScoreFilter.value;
644
- displayEvaluationResults();
645
- });
646
-
647
- maxScoreFilter.addEventListener('input', () => {
648
- maxScoreValue.textContent = maxScoreFilter.value;
649
- displayEvaluationResults();
650
- });
651
-
652
- showHighScores.addEventListener('change', displayEvaluationResults);
653
- showMediumScores.addEventListener('change', displayEvaluationResults);
654
- showLowScores.addEventListener('change', displayEvaluationResults);
655
- }
656
-
657
- // Update progress display
658
- function updateProgress() {
659
- const percentage = Math.round((evaluationProgress / totalOperators) * 100);
660
- progressFill.style.width = `${percentage}%`;
661
- progressFill.textContent = `${percentage}%`;
662
- progressCount.textContent = `${evaluationProgress} / ${totalOperators}`;
663
- progressText.textContent = `Evaluating operators with ${totalOperators} parallel workers... (${percentage}% complete)`;
664
- }
665
-
666
- // Show/hide progress section
667
- function showProgressSection() {
668
- progressSection.style.display = 'block';
669
- }
670
-
671
- function hideProgressSection() {
672
- progressSection.style.display = 'none';
673
- }
674
-
675
- // Update summary statistics
676
- function updateSummaryStats() {
677
- if (evaluationResults.length === 0) {
678
- summaryStats.style.display = 'none';
679
- return;
680
- }
681
-
682
- const highScores = evaluationResults.filter(r => r.score >= 8).length;
683
- const mediumScores = evaluationResults.filter(r => r.score >= 4 && r.score < 8).length;
684
- const lowScores = evaluationResults.filter(r => r.score < 4).length;
685
-
686
- highScoreCount.textContent = highScores;
687
- mediumScoreCount.textContent = mediumScores;
688
- lowScoreCount.textContent = lowScores;
689
- totalEvaluated.textContent = evaluationResults.length;
690
-
691
- summaryStats.style.display = 'grid';
692
- }
693
-
694
- // Save evaluation results
695
- function saveEvaluationResults() {
696
- sessionStorage.setItem('inspirationHouseResults', JSON.stringify(evaluationResults));
697
- }
698
-
699
- // Refresh evaluation results
700
- refreshEvaluationBtn.addEventListener('click', () => {
701
- displayEvaluationResults();
702
- updateSummaryStats();
703
- });
704
-
705
- // Clear results
706
- clearResultsBtn.addEventListener('click', () => {
707
- if (confirm('Are you sure you want to clear all evaluation results?')) {
708
- evaluationResults = [];
709
- sessionStorage.removeItem('inspirationHouseResults');
710
- displayEvaluationResults();
711
- updateSummaryStats();
712
- showNotification('Results cleared', 'success');
713
- }
714
- });
715
-
716
- // Export functions
717
- exportResultsBtn.addEventListener('click', () => {
718
- exportResults('all');
719
- });
720
-
721
- exportHighScoresBtn.addEventListener('click', () => {
722
- exportResults('high');
723
- });
724
-
725
- exportAllResultsBtn.addEventListener('click', () => {
726
- exportResults('all');
727
- });
728
-
729
- exportCSVBtn.addEventListener('click', () => {
730
- exportResults('csv');
731
- });
732
-
733
- function exportResults(type) {
734
- let dataToExport = evaluationResults;
735
-
736
- if (type === 'high') {
737
- dataToExport = evaluationResults.filter(r => r.score >= 8);
738
- }
739
-
740
- if (dataToExport.length === 0) {
741
- showNotification('No results to export', 'warning');
742
- return;
743
- }
744
-
745
- if (type === 'csv') {
746
- exportAsCSV(dataToExport);
747
- } else {
748
- exportAsJSON(dataToExport);
749
- }
750
- }
751
-
752
- function exportAsJSON(data) {
753
- const exportData = {
754
- timestamp: new Date().toISOString(),
755
- research_target: researchTarget,
756
- current_expression: currentExpression,
757
- expression_context: expressionContext,
758
- results: data
759
- };
760
-
761
- const blob = new Blob([JSON.stringify(exportData, null, 2)], { type: 'application/json' });
762
- const url = URL.createObjectURL(blob);
763
- const a = document.createElement('a');
764
- a.href = url;
765
- a.download = `inspiration_house_results_${new Date().toISOString().split('T')[0]}.json`;
766
- document.body.appendChild(a);
767
- a.click();
768
- document.body.removeChild(a);
769
- URL.revokeObjectURL(url);
770
-
771
- showNotification('Results exported as JSON', 'success');
772
- }
773
-
774
- function exportAsCSV(data) {
775
- const headers = ['Operator', 'Category', 'Score', 'Reason', 'Timestamp'];
776
- const csvContent = [
777
- headers.join(','),
778
- ...data.map(result => [
779
- `"${result.operator}"`,
780
- `"${result.category}"`,
781
- result.score,
782
- `"${result.reason.replace(/"/g, '""')}"`,
783
- `"${result.timestamp}"`
784
- ].join(','))
785
- ].join('\n');
786
-
787
- const blob = new Blob([csvContent], { type: 'text/csv' });
788
- const url = URL.createObjectURL(blob);
789
- const a = document.createElement('a');
790
- a.href = url;
791
- a.download = `inspiration_house_results_${new Date().toISOString().split('T')[0]}.csv`;
792
- document.body.appendChild(a);
793
- a.click();
794
- document.body.removeChild(a);
795
- URL.revokeObjectURL(url);
796
-
797
- showNotification('Results exported as CSV', 'success');
798
- }
799
-
800
- // Re-evaluate a single operator
801
- async function reevaluateOperator(operatorName) {
802
- const operator = operatorsList.find(op => op.name === operatorName);
803
- if (!operator) {
804
- showNotification('Operator not found', 'error');
805
- return;
806
- }
807
-
808
- try {
809
- showLoading(`Re-evaluating ${operatorName}...`);
810
-
811
- const result = await evaluateSingleOperator(operator);
812
-
813
- // Update existing result
814
- const index = evaluationResults.findIndex(r => r.operator === operatorName);
815
- if (index !== -1) {
816
- evaluationResults[index] = result;
817
- } else {
818
- evaluationResults.push(result);
819
- }
820
-
821
- saveEvaluationResults();
822
- displayEvaluationResults();
823
- updateSummaryStats();
824
-
825
- showNotification(`${operatorName} re-evaluated successfully`, 'success');
826
- } catch (error) {
827
- showNotification(`Error re-evaluating ${operatorName}: ${error.message}`, 'error');
828
- } finally {
829
- hideLoading();
830
- }
831
- }
832
-
833
- // Make function global
834
- window.reevaluateOperator = reevaluateOperator;
835
-
836
- // Utility Functions
837
- function showNotification(message, type) {
838
- const notification = document.createElement('div');
839
- notification.className = `notification ${type}`;
840
- notification.textContent = message;
841
- document.body.appendChild(notification);
842
-
843
- setTimeout(() => {
844
- notification.remove();
845
- }, 8000);
846
- }
847
-
848
- let loadingElement = null;
849
-
850
- function showLoading(message) {
851
- loadingElement = document.createElement('div');
852
- loadingElement.className = 'loading-overlay';
853
- loadingElement.innerHTML = `
854
- <div class="loading-spinner"></div>
855
- <div class="loading-message">${message}</div>
856
- `;
857
- document.body.appendChild(loadingElement);
858
- }
859
-
860
- function hideLoading() {
861
- if (loadingElement) {
862
- loadingElement.remove();
863
- loadingElement = null;
864
- }
865
- }
866
-
867
- // BRAIN Login Modal Functions are now handled by brain.js
868
- // The modal and authentication functions are accessed via window.brainAPI