local-deep-research 0.4.4__py3-none-any.whl → 0.5.0__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.
- local_deep_research/__init__.py +7 -0
- local_deep_research/__version__.py +1 -1
- local_deep_research/advanced_search_system/answer_decoding/__init__.py +5 -0
- local_deep_research/advanced_search_system/answer_decoding/browsecomp_answer_decoder.py +421 -0
- local_deep_research/advanced_search_system/candidate_exploration/README.md +219 -0
- local_deep_research/advanced_search_system/candidate_exploration/__init__.py +25 -0
- local_deep_research/advanced_search_system/candidate_exploration/adaptive_explorer.py +329 -0
- local_deep_research/advanced_search_system/candidate_exploration/base_explorer.py +341 -0
- local_deep_research/advanced_search_system/candidate_exploration/constraint_guided_explorer.py +436 -0
- local_deep_research/advanced_search_system/candidate_exploration/diversity_explorer.py +457 -0
- local_deep_research/advanced_search_system/candidate_exploration/parallel_explorer.py +250 -0
- local_deep_research/advanced_search_system/candidate_exploration/progressive_explorer.py +255 -0
- local_deep_research/advanced_search_system/candidates/__init__.py +5 -0
- local_deep_research/advanced_search_system/candidates/base_candidate.py +59 -0
- local_deep_research/advanced_search_system/constraint_checking/README.md +150 -0
- local_deep_research/advanced_search_system/constraint_checking/__init__.py +35 -0
- local_deep_research/advanced_search_system/constraint_checking/base_constraint_checker.py +122 -0
- local_deep_research/advanced_search_system/constraint_checking/constraint_checker.py +223 -0
- local_deep_research/advanced_search_system/constraint_checking/constraint_satisfaction_tracker.py +387 -0
- local_deep_research/advanced_search_system/constraint_checking/dual_confidence_checker.py +424 -0
- local_deep_research/advanced_search_system/constraint_checking/evidence_analyzer.py +174 -0
- local_deep_research/advanced_search_system/constraint_checking/intelligent_constraint_relaxer.py +503 -0
- local_deep_research/advanced_search_system/constraint_checking/rejection_engine.py +143 -0
- local_deep_research/advanced_search_system/constraint_checking/strict_checker.py +259 -0
- local_deep_research/advanced_search_system/constraint_checking/threshold_checker.py +213 -0
- local_deep_research/advanced_search_system/constraints/__init__.py +6 -0
- local_deep_research/advanced_search_system/constraints/base_constraint.py +58 -0
- local_deep_research/advanced_search_system/constraints/constraint_analyzer.py +143 -0
- local_deep_research/advanced_search_system/evidence/__init__.py +12 -0
- local_deep_research/advanced_search_system/evidence/base_evidence.py +57 -0
- local_deep_research/advanced_search_system/evidence/evaluator.py +159 -0
- local_deep_research/advanced_search_system/evidence/requirements.py +122 -0
- local_deep_research/advanced_search_system/filters/base_filter.py +3 -1
- local_deep_research/advanced_search_system/filters/cross_engine_filter.py +8 -2
- local_deep_research/advanced_search_system/filters/journal_reputation_filter.py +43 -29
- local_deep_research/advanced_search_system/findings/repository.py +54 -17
- local_deep_research/advanced_search_system/knowledge/standard_knowledge.py +3 -1
- local_deep_research/advanced_search_system/query_generation/adaptive_query_generator.py +405 -0
- local_deep_research/advanced_search_system/questions/__init__.py +16 -0
- local_deep_research/advanced_search_system/questions/atomic_fact_question.py +171 -0
- local_deep_research/advanced_search_system/questions/browsecomp_question.py +287 -0
- local_deep_research/advanced_search_system/questions/decomposition_question.py +13 -4
- local_deep_research/advanced_search_system/questions/entity_aware_question.py +184 -0
- local_deep_research/advanced_search_system/questions/standard_question.py +9 -3
- local_deep_research/advanced_search_system/search_optimization/cross_constraint_manager.py +624 -0
- local_deep_research/advanced_search_system/source_management/diversity_manager.py +613 -0
- local_deep_research/advanced_search_system/strategies/__init__.py +42 -0
- local_deep_research/advanced_search_system/strategies/adaptive_decomposition_strategy.py +564 -0
- local_deep_research/advanced_search_system/strategies/base_strategy.py +4 -4
- local_deep_research/advanced_search_system/strategies/browsecomp_entity_strategy.py +1031 -0
- local_deep_research/advanced_search_system/strategies/browsecomp_optimized_strategy.py +778 -0
- local_deep_research/advanced_search_system/strategies/concurrent_dual_confidence_strategy.py +446 -0
- local_deep_research/advanced_search_system/strategies/constrained_search_strategy.py +1348 -0
- local_deep_research/advanced_search_system/strategies/constraint_parallel_strategy.py +522 -0
- local_deep_research/advanced_search_system/strategies/direct_search_strategy.py +217 -0
- local_deep_research/advanced_search_system/strategies/dual_confidence_strategy.py +320 -0
- local_deep_research/advanced_search_system/strategies/dual_confidence_with_rejection.py +219 -0
- local_deep_research/advanced_search_system/strategies/early_stop_constrained_strategy.py +369 -0
- local_deep_research/advanced_search_system/strategies/entity_aware_source_strategy.py +140 -0
- local_deep_research/advanced_search_system/strategies/evidence_based_strategy.py +1248 -0
- local_deep_research/advanced_search_system/strategies/evidence_based_strategy_v2.py +1337 -0
- local_deep_research/advanced_search_system/strategies/focused_iteration_strategy.py +537 -0
- local_deep_research/advanced_search_system/strategies/improved_evidence_based_strategy.py +782 -0
- local_deep_research/advanced_search_system/strategies/iterative_reasoning_strategy.py +760 -0
- local_deep_research/advanced_search_system/strategies/iterdrag_strategy.py +55 -21
- local_deep_research/advanced_search_system/strategies/llm_driven_modular_strategy.py +865 -0
- local_deep_research/advanced_search_system/strategies/modular_strategy.py +1142 -0
- local_deep_research/advanced_search_system/strategies/parallel_constrained_strategy.py +506 -0
- local_deep_research/advanced_search_system/strategies/parallel_search_strategy.py +34 -16
- local_deep_research/advanced_search_system/strategies/rapid_search_strategy.py +29 -9
- local_deep_research/advanced_search_system/strategies/recursive_decomposition_strategy.py +492 -0
- local_deep_research/advanced_search_system/strategies/smart_decomposition_strategy.py +284 -0
- local_deep_research/advanced_search_system/strategies/smart_query_strategy.py +515 -0
- local_deep_research/advanced_search_system/strategies/source_based_strategy.py +48 -24
- local_deep_research/advanced_search_system/strategies/standard_strategy.py +34 -14
- local_deep_research/advanced_search_system/tools/base_tool.py +7 -2
- local_deep_research/api/benchmark_functions.py +6 -2
- local_deep_research/api/research_functions.py +10 -4
- local_deep_research/benchmarks/__init__.py +9 -7
- local_deep_research/benchmarks/benchmark_functions.py +6 -2
- local_deep_research/benchmarks/cli/benchmark_commands.py +27 -10
- local_deep_research/benchmarks/cli.py +38 -13
- local_deep_research/benchmarks/comparison/__init__.py +4 -2
- local_deep_research/benchmarks/comparison/evaluator.py +316 -239
- local_deep_research/benchmarks/datasets/__init__.py +1 -1
- local_deep_research/benchmarks/datasets/base.py +91 -72
- local_deep_research/benchmarks/datasets/browsecomp.py +54 -33
- local_deep_research/benchmarks/datasets/custom_dataset_template.py +19 -19
- local_deep_research/benchmarks/datasets/simpleqa.py +14 -14
- local_deep_research/benchmarks/datasets/utils.py +48 -29
- local_deep_research/benchmarks/datasets.py +4 -11
- local_deep_research/benchmarks/efficiency/__init__.py +8 -4
- local_deep_research/benchmarks/efficiency/resource_monitor.py +223 -171
- local_deep_research/benchmarks/efficiency/speed_profiler.py +62 -48
- local_deep_research/benchmarks/evaluators/browsecomp.py +3 -1
- local_deep_research/benchmarks/evaluators/composite.py +6 -2
- local_deep_research/benchmarks/evaluators/simpleqa.py +36 -13
- local_deep_research/benchmarks/graders.py +32 -10
- local_deep_research/benchmarks/metrics/README.md +1 -1
- local_deep_research/benchmarks/metrics/calculation.py +25 -10
- local_deep_research/benchmarks/metrics/reporting.py +7 -3
- local_deep_research/benchmarks/metrics/visualization.py +42 -23
- local_deep_research/benchmarks/metrics.py +1 -1
- local_deep_research/benchmarks/optimization/__init__.py +3 -1
- local_deep_research/benchmarks/optimization/api.py +7 -1
- local_deep_research/benchmarks/optimization/optuna_optimizer.py +75 -26
- local_deep_research/benchmarks/runners.py +48 -15
- local_deep_research/citation_handler.py +65 -92
- local_deep_research/citation_handlers/__init__.py +15 -0
- local_deep_research/citation_handlers/base_citation_handler.py +70 -0
- local_deep_research/citation_handlers/forced_answer_citation_handler.py +179 -0
- local_deep_research/citation_handlers/precision_extraction_handler.py +550 -0
- local_deep_research/citation_handlers/standard_citation_handler.py +80 -0
- local_deep_research/config/llm_config.py +271 -169
- local_deep_research/config/search_config.py +14 -5
- local_deep_research/defaults/__init__.py +0 -1
- local_deep_research/metrics/__init__.py +13 -0
- local_deep_research/metrics/database.py +58 -0
- local_deep_research/metrics/db_models.py +115 -0
- local_deep_research/metrics/migrate_add_provider_to_token_usage.py +148 -0
- local_deep_research/metrics/migrate_call_stack_tracking.py +105 -0
- local_deep_research/metrics/migrate_enhanced_tracking.py +75 -0
- local_deep_research/metrics/migrate_research_ratings.py +31 -0
- local_deep_research/metrics/models.py +61 -0
- local_deep_research/metrics/pricing/__init__.py +12 -0
- local_deep_research/metrics/pricing/cost_calculator.py +237 -0
- local_deep_research/metrics/pricing/pricing_cache.py +143 -0
- local_deep_research/metrics/pricing/pricing_fetcher.py +240 -0
- local_deep_research/metrics/query_utils.py +51 -0
- local_deep_research/metrics/search_tracker.py +380 -0
- local_deep_research/metrics/token_counter.py +1078 -0
- local_deep_research/migrate_db.py +3 -1
- local_deep_research/report_generator.py +22 -8
- local_deep_research/search_system.py +390 -9
- local_deep_research/test_migration.py +15 -5
- local_deep_research/utilities/db_utils.py +7 -4
- local_deep_research/utilities/es_utils.py +115 -104
- local_deep_research/utilities/llm_utils.py +15 -5
- local_deep_research/utilities/log_utils.py +151 -0
- local_deep_research/utilities/search_cache.py +387 -0
- local_deep_research/utilities/search_utilities.py +14 -6
- local_deep_research/utilities/threading_utils.py +92 -0
- local_deep_research/utilities/url_utils.py +6 -0
- local_deep_research/web/api.py +347 -0
- local_deep_research/web/app.py +13 -17
- local_deep_research/web/app_factory.py +71 -66
- local_deep_research/web/database/migrate_to_ldr_db.py +12 -4
- local_deep_research/web/database/migrations.py +5 -3
- local_deep_research/web/database/models.py +51 -2
- local_deep_research/web/database/schema_upgrade.py +49 -29
- local_deep_research/web/models/database.py +51 -61
- local_deep_research/web/routes/api_routes.py +56 -22
- local_deep_research/web/routes/benchmark_routes.py +4 -1
- local_deep_research/web/routes/globals.py +22 -0
- local_deep_research/web/routes/history_routes.py +71 -46
- local_deep_research/web/routes/metrics_routes.py +1155 -0
- local_deep_research/web/routes/research_routes.py +227 -41
- local_deep_research/web/routes/settings_routes.py +156 -55
- local_deep_research/web/services/research_service.py +310 -103
- local_deep_research/web/services/resource_service.py +36 -11
- local_deep_research/web/services/settings_manager.py +55 -17
- local_deep_research/web/services/settings_service.py +12 -4
- local_deep_research/web/services/socket_service.py +295 -188
- local_deep_research/web/static/css/custom_dropdown.css +180 -0
- local_deep_research/web/static/css/styles.css +39 -1
- local_deep_research/web/static/js/components/detail.js +633 -267
- local_deep_research/web/static/js/components/details.js +751 -0
- local_deep_research/web/static/js/components/fallback/formatting.js +11 -11
- local_deep_research/web/static/js/components/fallback/ui.js +23 -23
- local_deep_research/web/static/js/components/history.js +76 -76
- local_deep_research/web/static/js/components/logpanel.js +61 -13
- local_deep_research/web/static/js/components/progress.js +13 -2
- local_deep_research/web/static/js/components/research.js +99 -12
- local_deep_research/web/static/js/components/results.js +239 -106
- local_deep_research/web/static/js/main.js +40 -40
- local_deep_research/web/static/js/services/audio.js +1 -1
- local_deep_research/web/static/js/services/formatting.js +11 -11
- local_deep_research/web/static/js/services/keyboard.js +157 -0
- local_deep_research/web/static/js/services/pdf.js +80 -80
- local_deep_research/web/static/sounds/README.md +1 -1
- local_deep_research/web/templates/base.html +1 -0
- local_deep_research/web/templates/components/log_panel.html +7 -1
- local_deep_research/web/templates/components/mobile_nav.html +1 -1
- local_deep_research/web/templates/components/sidebar.html +3 -0
- local_deep_research/web/templates/pages/cost_analytics.html +1245 -0
- local_deep_research/web/templates/pages/details.html +325 -24
- local_deep_research/web/templates/pages/history.html +1 -1
- local_deep_research/web/templates/pages/metrics.html +1929 -0
- local_deep_research/web/templates/pages/progress.html +2 -2
- local_deep_research/web/templates/pages/research.html +53 -17
- local_deep_research/web/templates/pages/results.html +12 -1
- local_deep_research/web/templates/pages/star_reviews.html +803 -0
- local_deep_research/web/utils/formatters.py +9 -3
- local_deep_research/web_search_engines/default_search_engines.py +5 -3
- local_deep_research/web_search_engines/engines/full_search.py +8 -2
- local_deep_research/web_search_engines/engines/meta_search_engine.py +59 -20
- local_deep_research/web_search_engines/engines/search_engine_arxiv.py +19 -6
- local_deep_research/web_search_engines/engines/search_engine_brave.py +6 -2
- local_deep_research/web_search_engines/engines/search_engine_ddg.py +3 -1
- local_deep_research/web_search_engines/engines/search_engine_elasticsearch.py +81 -58
- local_deep_research/web_search_engines/engines/search_engine_github.py +46 -15
- local_deep_research/web_search_engines/engines/search_engine_google_pse.py +16 -6
- local_deep_research/web_search_engines/engines/search_engine_guardian.py +39 -15
- local_deep_research/web_search_engines/engines/search_engine_local.py +58 -25
- local_deep_research/web_search_engines/engines/search_engine_local_all.py +15 -5
- local_deep_research/web_search_engines/engines/search_engine_pubmed.py +63 -21
- local_deep_research/web_search_engines/engines/search_engine_searxng.py +37 -11
- local_deep_research/web_search_engines/engines/search_engine_semantic_scholar.py +27 -9
- local_deep_research/web_search_engines/engines/search_engine_serpapi.py +12 -4
- local_deep_research/web_search_engines/engines/search_engine_wayback.py +31 -10
- local_deep_research/web_search_engines/engines/search_engine_wikipedia.py +12 -3
- local_deep_research/web_search_engines/search_engine_base.py +83 -35
- local_deep_research/web_search_engines/search_engine_factory.py +25 -8
- local_deep_research/web_search_engines/search_engines_config.py +9 -3
- {local_deep_research-0.4.4.dist-info → local_deep_research-0.5.0.dist-info}/METADATA +7 -1
- local_deep_research-0.5.0.dist-info/RECORD +265 -0
- local_deep_research-0.4.4.dist-info/RECORD +0 -177
- {local_deep_research-0.4.4.dist-info → local_deep_research-0.5.0.dist-info}/WHEEL +0 -0
- {local_deep_research-0.4.4.dist-info → local_deep_research-0.5.0.dist-info}/entry_points.txt +0 -0
- {local_deep_research-0.4.4.dist-info → local_deep_research-0.5.0.dist-info}/licenses/LICENSE +0 -0
@@ -8,18 +8,18 @@
|
|
8
8
|
let searchInput = null;
|
9
9
|
let clearHistoryBtn = null;
|
10
10
|
let historyEmptyMessage = null;
|
11
|
-
|
11
|
+
|
12
12
|
// Component state
|
13
13
|
let historyItems = [];
|
14
14
|
let filteredItems = [];
|
15
|
-
|
15
|
+
|
16
16
|
// Fallback UI utilities in case main UI utils aren't loaded
|
17
17
|
const uiUtils = {
|
18
18
|
showSpinner: function(container, message) {
|
19
19
|
if (window.ui && window.ui.showSpinner) {
|
20
20
|
return window.ui.showSpinner(container, message);
|
21
21
|
}
|
22
|
-
|
22
|
+
|
23
23
|
// Fallback implementation
|
24
24
|
if (!container) container = document.body;
|
25
25
|
const spinnerHtml = `
|
@@ -30,12 +30,12 @@
|
|
30
30
|
`;
|
31
31
|
container.innerHTML = spinnerHtml;
|
32
32
|
},
|
33
|
-
|
33
|
+
|
34
34
|
hideSpinner: function(container) {
|
35
35
|
if (window.ui && window.ui.hideSpinner) {
|
36
36
|
return window.ui.hideSpinner(container);
|
37
37
|
}
|
38
|
-
|
38
|
+
|
39
39
|
// Fallback implementation
|
40
40
|
if (!container) container = document.body;
|
41
41
|
const spinner = container.querySelector('.loading-spinner');
|
@@ -43,35 +43,35 @@
|
|
43
43
|
spinner.remove();
|
44
44
|
}
|
45
45
|
},
|
46
|
-
|
46
|
+
|
47
47
|
showError: function(message) {
|
48
48
|
if (window.ui && window.ui.showError) {
|
49
49
|
return window.ui.showError(message);
|
50
50
|
}
|
51
|
-
|
51
|
+
|
52
52
|
// Fallback implementation
|
53
53
|
console.error(message);
|
54
54
|
alert(message);
|
55
55
|
},
|
56
|
-
|
56
|
+
|
57
57
|
showMessage: function(message) {
|
58
58
|
if (window.ui && window.ui.showMessage) {
|
59
59
|
return window.ui.showMessage(message);
|
60
60
|
}
|
61
|
-
|
61
|
+
|
62
62
|
// Fallback implementation
|
63
63
|
console.log(message);
|
64
64
|
alert(message);
|
65
65
|
}
|
66
66
|
};
|
67
|
-
|
67
|
+
|
68
68
|
// Fallback API utilities
|
69
69
|
const apiUtils = {
|
70
70
|
getResearchHistory: async function() {
|
71
71
|
if (window.api && window.api.getResearchHistory) {
|
72
72
|
return window.api.getResearchHistory();
|
73
73
|
}
|
74
|
-
|
74
|
+
|
75
75
|
// Fallback implementation
|
76
76
|
try {
|
77
77
|
const response = await fetch('/research/api/history');
|
@@ -84,12 +84,12 @@
|
|
84
84
|
throw error;
|
85
85
|
}
|
86
86
|
},
|
87
|
-
|
87
|
+
|
88
88
|
deleteResearch: async function(researchId) {
|
89
89
|
if (window.api && window.api.deleteResearch) {
|
90
90
|
return window.api.deleteResearch(researchId);
|
91
91
|
}
|
92
|
-
|
92
|
+
|
93
93
|
// Fallback implementation
|
94
94
|
try {
|
95
95
|
const response = await fetch(`/research/api/delete/${researchId}`, {
|
@@ -104,12 +104,12 @@
|
|
104
104
|
throw error;
|
105
105
|
}
|
106
106
|
},
|
107
|
-
|
107
|
+
|
108
108
|
clearResearchHistory: async function() {
|
109
109
|
if (window.api && window.api.clearResearchHistory) {
|
110
110
|
return window.api.clearResearchHistory();
|
111
111
|
}
|
112
|
-
|
112
|
+
|
113
113
|
// Fallback implementation
|
114
114
|
try {
|
115
115
|
const response = await fetch('/research/api/clear_history', {
|
@@ -129,7 +129,7 @@
|
|
129
129
|
}
|
130
130
|
}
|
131
131
|
};
|
132
|
-
|
132
|
+
|
133
133
|
/**
|
134
134
|
* Initialize the history component
|
135
135
|
*/
|
@@ -139,21 +139,21 @@
|
|
139
139
|
searchInput = document.getElementById('history-search');
|
140
140
|
clearHistoryBtn = document.getElementById('clear-history-btn');
|
141
141
|
historyEmptyMessage = document.getElementById('history-empty-message');
|
142
|
-
|
142
|
+
|
143
143
|
if (!historyContainer) {
|
144
144
|
console.error('Required DOM elements not found for history component');
|
145
145
|
return;
|
146
146
|
}
|
147
|
-
|
147
|
+
|
148
148
|
// Set up event listeners
|
149
149
|
setupEventListeners();
|
150
|
-
|
150
|
+
|
151
151
|
// Load history data
|
152
152
|
loadHistoryData();
|
153
|
-
|
153
|
+
|
154
154
|
console.log('History component initialized');
|
155
155
|
}
|
156
|
-
|
156
|
+
|
157
157
|
/**
|
158
158
|
* Set up event listeners
|
159
159
|
*/
|
@@ -162,12 +162,12 @@
|
|
162
162
|
if (searchInput) {
|
163
163
|
searchInput.addEventListener('input', handleSearchInput);
|
164
164
|
}
|
165
|
-
|
165
|
+
|
166
166
|
// Clear history button
|
167
167
|
if (clearHistoryBtn) {
|
168
168
|
clearHistoryBtn.addEventListener('click', handleClearHistory);
|
169
169
|
}
|
170
|
-
|
170
|
+
|
171
171
|
// Delegation for history item clicks
|
172
172
|
if (historyContainer) {
|
173
173
|
historyContainer.addEventListener('click', function(e) {
|
@@ -179,22 +179,22 @@
|
|
179
179
|
});
|
180
180
|
}
|
181
181
|
}
|
182
|
-
|
182
|
+
|
183
183
|
/**
|
184
184
|
* Load history data from API
|
185
185
|
*/
|
186
186
|
async function loadHistoryData() {
|
187
187
|
// Show loading state
|
188
188
|
uiUtils.showSpinner(historyContainer, 'Loading research history...');
|
189
|
-
|
189
|
+
|
190
190
|
try {
|
191
191
|
// Get history items
|
192
192
|
const response = await apiUtils.getResearchHistory();
|
193
|
-
|
193
|
+
|
194
194
|
if (response && Array.isArray(response.items)) {
|
195
195
|
historyItems = response.items;
|
196
196
|
filteredItems = [...historyItems];
|
197
|
-
|
197
|
+
|
198
198
|
// Render history items
|
199
199
|
renderHistoryItems();
|
200
200
|
} else {
|
@@ -206,17 +206,17 @@
|
|
206
206
|
uiUtils.showError('Error loading history: ' + error.message);
|
207
207
|
}
|
208
208
|
}
|
209
|
-
|
209
|
+
|
210
210
|
/**
|
211
211
|
* Render history items
|
212
212
|
*/
|
213
213
|
function renderHistoryItems() {
|
214
214
|
// Hide spinner
|
215
215
|
uiUtils.hideSpinner(historyContainer);
|
216
|
-
|
216
|
+
|
217
217
|
// Clear container
|
218
218
|
historyContainer.innerHTML = '';
|
219
|
-
|
219
|
+
|
220
220
|
// Show empty message if no items
|
221
221
|
if (filteredItems.length === 0) {
|
222
222
|
if (historyEmptyMessage) {
|
@@ -230,30 +230,30 @@
|
|
230
230
|
</div>
|
231
231
|
`;
|
232
232
|
}
|
233
|
-
|
233
|
+
|
234
234
|
if (clearHistoryBtn) {
|
235
235
|
clearHistoryBtn.style.display = 'none';
|
236
236
|
}
|
237
237
|
return;
|
238
238
|
}
|
239
|
-
|
239
|
+
|
240
240
|
// Hide empty message
|
241
241
|
if (historyEmptyMessage) {
|
242
242
|
historyEmptyMessage.style.display = 'none';
|
243
243
|
}
|
244
|
-
|
244
|
+
|
245
245
|
// Show clear button
|
246
246
|
if (clearHistoryBtn) {
|
247
247
|
clearHistoryBtn.style.display = 'inline-block';
|
248
248
|
}
|
249
|
-
|
249
|
+
|
250
250
|
// Create items
|
251
251
|
filteredItems.forEach(item => {
|
252
252
|
const itemElement = createHistoryItemElement(item);
|
253
253
|
historyContainer.appendChild(itemElement);
|
254
254
|
});
|
255
255
|
}
|
256
|
-
|
256
|
+
|
257
257
|
/**
|
258
258
|
* Format date safely using the formatter if available
|
259
259
|
*/
|
@@ -261,7 +261,7 @@
|
|
261
261
|
if (window.formatting && window.formatting.formatDate) {
|
262
262
|
return window.formatting.formatDate(dateStr);
|
263
263
|
}
|
264
|
-
|
264
|
+
|
265
265
|
// Simple fallback date formatting
|
266
266
|
try {
|
267
267
|
const date = new Date(dateStr);
|
@@ -270,7 +270,7 @@
|
|
270
270
|
return dateStr;
|
271
271
|
}
|
272
272
|
}
|
273
|
-
|
273
|
+
|
274
274
|
/**
|
275
275
|
* Format status safely using the formatter if available
|
276
276
|
*/
|
@@ -278,7 +278,7 @@
|
|
278
278
|
if (window.formatting && window.formatting.formatStatus) {
|
279
279
|
return window.formatting.formatStatus(status);
|
280
280
|
}
|
281
|
-
|
281
|
+
|
282
282
|
// Simple fallback formatting
|
283
283
|
const statusMap = {
|
284
284
|
'in_progress': 'In Progress',
|
@@ -286,10 +286,10 @@
|
|
286
286
|
'failed': 'Failed',
|
287
287
|
'suspended': 'Suspended'
|
288
288
|
};
|
289
|
-
|
289
|
+
|
290
290
|
return statusMap[status] || status;
|
291
291
|
}
|
292
|
-
|
292
|
+
|
293
293
|
/**
|
294
294
|
* Format mode safely using the formatter if available
|
295
295
|
*/
|
@@ -297,16 +297,16 @@
|
|
297
297
|
if (window.formatting && window.formatting.formatMode) {
|
298
298
|
return window.formatting.formatMode(mode);
|
299
299
|
}
|
300
|
-
|
300
|
+
|
301
301
|
// Simple fallback formatting
|
302
302
|
const modeMap = {
|
303
303
|
'quick': 'Quick Summary',
|
304
304
|
'detailed': 'Detailed Report'
|
305
305
|
};
|
306
|
-
|
306
|
+
|
307
307
|
return modeMap[mode] || mode;
|
308
308
|
}
|
309
|
-
|
309
|
+
|
310
310
|
/**
|
311
311
|
* Create a history item element
|
312
312
|
* @param {Object} item - The history item data
|
@@ -316,16 +316,16 @@
|
|
316
316
|
const itemEl = document.createElement('div');
|
317
317
|
itemEl.className = 'history-item';
|
318
318
|
itemEl.dataset.id = item.id;
|
319
|
-
|
319
|
+
|
320
320
|
// Format date
|
321
321
|
const formattedDate = formatDate(item.created_at);
|
322
|
-
|
322
|
+
|
323
323
|
// Get a display title (use query if title is not available)
|
324
324
|
const displayTitle = item.title || formatTitleFromQuery(item.query);
|
325
|
-
|
325
|
+
|
326
326
|
// Status class - convert in_progress to in-progress for CSS
|
327
327
|
const statusClass = item.status ? item.status.replace('_', '-') : '';
|
328
|
-
|
328
|
+
|
329
329
|
// Create the HTML content
|
330
330
|
itemEl.innerHTML = `
|
331
331
|
<div class="history-item-header">
|
@@ -337,7 +337,7 @@
|
|
337
337
|
<div class="history-item-mode">${formatMode(item.mode)}</div>
|
338
338
|
</div>
|
339
339
|
<div class="history-item-actions">
|
340
|
-
${item.status === 'completed' ?
|
340
|
+
${item.status === 'completed' ?
|
341
341
|
`<button class="btn btn-sm btn-outline view-btn">
|
342
342
|
<i class="fas fa-eye"></i> View
|
343
343
|
</button>` : ''}
|
@@ -346,7 +346,7 @@
|
|
346
346
|
</button>
|
347
347
|
</div>
|
348
348
|
`;
|
349
|
-
|
349
|
+
|
350
350
|
// Add event listeners
|
351
351
|
const viewBtn = itemEl.querySelector('.view-btn');
|
352
352
|
if (viewBtn) {
|
@@ -355,7 +355,7 @@
|
|
355
355
|
window.location.href = `/research/results/${item.id}`;
|
356
356
|
});
|
357
357
|
}
|
358
|
-
|
358
|
+
|
359
359
|
const deleteBtn = itemEl.querySelector('.delete-item-btn');
|
360
360
|
if (deleteBtn) {
|
361
361
|
deleteBtn.addEventListener('click', (e) => {
|
@@ -363,7 +363,7 @@
|
|
363
363
|
handleDeleteItem(item.id);
|
364
364
|
});
|
365
365
|
}
|
366
|
-
|
366
|
+
|
367
367
|
// Add click event to the whole item
|
368
368
|
itemEl.addEventListener('click', () => {
|
369
369
|
if (item.status === 'completed') {
|
@@ -372,10 +372,10 @@
|
|
372
372
|
window.location.href = `/research/progress/${item.id}`;
|
373
373
|
}
|
374
374
|
});
|
375
|
-
|
375
|
+
|
376
376
|
return itemEl;
|
377
377
|
}
|
378
|
-
|
378
|
+
|
379
379
|
/**
|
380
380
|
* Format a title from a query string
|
381
381
|
* Truncates long queries and adds ellipsis
|
@@ -384,21 +384,21 @@
|
|
384
384
|
*/
|
385
385
|
function formatTitleFromQuery(query) {
|
386
386
|
if (!query) return 'Untitled Research';
|
387
|
-
|
387
|
+
|
388
388
|
// Truncate long queries
|
389
389
|
if (query.length > 60) {
|
390
390
|
return query.substring(0, 57) + '...';
|
391
391
|
}
|
392
|
-
|
392
|
+
|
393
393
|
return query;
|
394
394
|
}
|
395
|
-
|
395
|
+
|
396
396
|
/**
|
397
397
|
* Handle search input
|
398
398
|
*/
|
399
399
|
function handleSearchInput() {
|
400
400
|
const searchTerm = searchInput.value.trim().toLowerCase();
|
401
|
-
|
401
|
+
|
402
402
|
if (!searchTerm) {
|
403
403
|
// Reset to show all items
|
404
404
|
filteredItems = [...historyItems];
|
@@ -406,23 +406,23 @@
|
|
406
406
|
// Filter items based on search term
|
407
407
|
filteredItems = historyItems.filter(item => {
|
408
408
|
// Search in title if available, otherwise in query
|
409
|
-
const titleMatch = item.title ?
|
410
|
-
item.title.toLowerCase().includes(searchTerm) :
|
409
|
+
const titleMatch = item.title ?
|
410
|
+
item.title.toLowerCase().includes(searchTerm) :
|
411
411
|
false;
|
412
|
-
|
412
|
+
|
413
413
|
// Always search in query
|
414
|
-
const queryMatch = item.query ?
|
415
|
-
item.query.toLowerCase().includes(searchTerm) :
|
414
|
+
const queryMatch = item.query ?
|
415
|
+
item.query.toLowerCase().includes(searchTerm) :
|
416
416
|
false;
|
417
|
-
|
417
|
+
|
418
418
|
return titleMatch || queryMatch;
|
419
419
|
});
|
420
420
|
}
|
421
|
-
|
421
|
+
|
422
422
|
// Render filtered items
|
423
423
|
renderHistoryItems();
|
424
424
|
}
|
425
|
-
|
425
|
+
|
426
426
|
/**
|
427
427
|
* Handle delete item
|
428
428
|
* @param {string} itemId - The item ID to delete
|
@@ -431,18 +431,18 @@
|
|
431
431
|
if (!confirm('Are you sure you want to delete this research? This action cannot be undone.')) {
|
432
432
|
return;
|
433
433
|
}
|
434
|
-
|
434
|
+
|
435
435
|
try {
|
436
436
|
// Delete item via API
|
437
437
|
await apiUtils.deleteResearch(itemId);
|
438
|
-
|
438
|
+
|
439
439
|
// Remove from arrays
|
440
440
|
historyItems = historyItems.filter(item => item.id != itemId);
|
441
441
|
filteredItems = filteredItems.filter(item => item.id != itemId);
|
442
|
-
|
442
|
+
|
443
443
|
// Show success message
|
444
444
|
uiUtils.showMessage('Research deleted successfully');
|
445
|
-
|
445
|
+
|
446
446
|
// Re-render history items
|
447
447
|
renderHistoryItems();
|
448
448
|
} catch (error) {
|
@@ -450,7 +450,7 @@
|
|
450
450
|
uiUtils.showError('Error deleting research: ' + error.message);
|
451
451
|
}
|
452
452
|
}
|
453
|
-
|
453
|
+
|
454
454
|
/**
|
455
455
|
* Handle clear history
|
456
456
|
*/
|
@@ -458,18 +458,18 @@
|
|
458
458
|
if (!confirm('Are you sure you want to clear all research history? This action cannot be undone.')) {
|
459
459
|
return;
|
460
460
|
}
|
461
|
-
|
461
|
+
|
462
462
|
try {
|
463
463
|
// Clear history via API
|
464
464
|
await apiUtils.clearResearchHistory();
|
465
|
-
|
465
|
+
|
466
466
|
// Clear arrays
|
467
467
|
historyItems = [];
|
468
468
|
filteredItems = [];
|
469
|
-
|
469
|
+
|
470
470
|
// Show success message
|
471
471
|
uiUtils.showMessage('Research history cleared successfully');
|
472
|
-
|
472
|
+
|
473
473
|
// Re-render history items
|
474
474
|
renderHistoryItems();
|
475
475
|
} catch (error) {
|
@@ -477,11 +477,11 @@
|
|
477
477
|
uiUtils.showError('Error clearing history: ' + error.message);
|
478
478
|
}
|
479
479
|
}
|
480
|
-
|
480
|
+
|
481
481
|
// Initialize on DOM content loaded
|
482
482
|
if (document.readyState === 'loading') {
|
483
483
|
document.addEventListener('DOMContentLoaded', initializeHistory);
|
484
484
|
} else {
|
485
485
|
initializeHistory();
|
486
486
|
}
|
487
|
-
})();
|
487
|
+
})();
|
@@ -32,6 +32,12 @@
|
|
32
32
|
// If the research ID has changed, we'll update our connection
|
33
33
|
console.log('Research ID changed from', window._logPanelState.connectedResearchId, 'to', researchId);
|
34
34
|
window._logPanelState.connectedResearchId = researchId;
|
35
|
+
} else {
|
36
|
+
// Add callback for log download button.
|
37
|
+
const downloadButton = document.getElementById('log-download-button');
|
38
|
+
if (downloadButton) {
|
39
|
+
downloadButton.addEventListener('click', downloadLogs);
|
40
|
+
}
|
35
41
|
}
|
36
42
|
|
37
43
|
console.log('Initializing shared log panel, research ID:', researchId);
|
@@ -191,6 +197,23 @@
|
|
191
197
|
logIndicators.forEach(indicator => {
|
192
198
|
indicator.textContent = '0';
|
193
199
|
});
|
200
|
+
|
201
|
+
// Fetch the log count from the API and update the indicators
|
202
|
+
fetch(`/research/api/log_count/${researchId}`)
|
203
|
+
.then(response => response.json())
|
204
|
+
.then(data => {
|
205
|
+
console.log('Log count data:', data);
|
206
|
+
if (data && typeof data.total_logs === 'number') {
|
207
|
+
logIndicators.forEach(indicator => {
|
208
|
+
indicator.textContent = data.total_logs;
|
209
|
+
});
|
210
|
+
} else {
|
211
|
+
console.error('Invalid log count data received from API');
|
212
|
+
}
|
213
|
+
})
|
214
|
+
.catch(error => {
|
215
|
+
console.error('Error fetching log count:', error);
|
216
|
+
});
|
194
217
|
} else {
|
195
218
|
console.warn('No log indicators found for initialization');
|
196
219
|
}
|
@@ -269,6 +292,17 @@
|
|
269
292
|
console.log('Log panel initialized');
|
270
293
|
}
|
271
294
|
|
295
|
+
/**
|
296
|
+
* @brief Fetches all the logs for a research instance from the API.
|
297
|
+
* @param researchId The ID of the research instance.
|
298
|
+
* @returns {Promise<any>} The logs.
|
299
|
+
*/
|
300
|
+
async function fetchLogsForResearch(researchId) {
|
301
|
+
// Fetch logs from API
|
302
|
+
const response = await fetch(`/research/api/logs/${researchId}`);
|
303
|
+
return await response.json();
|
304
|
+
}
|
305
|
+
|
272
306
|
/**
|
273
307
|
* Load logs for a specific research
|
274
308
|
* @param {string} researchId - The research ID to load logs for
|
@@ -283,10 +317,7 @@
|
|
283
317
|
|
284
318
|
console.log('Loading logs for research ID:', researchId);
|
285
319
|
|
286
|
-
|
287
|
-
const response = await fetch(`/research/api/logs/${researchId}`);
|
288
|
-
const data = await response.json();
|
289
|
-
|
320
|
+
const data = await fetchLogsForResearch(researchId);
|
290
321
|
console.log('Logs API response:', data);
|
291
322
|
|
292
323
|
// Initialize array to hold all logs from different sources
|
@@ -714,14 +745,6 @@
|
|
714
745
|
logLevel = logEntry.type;
|
715
746
|
} else if (logEntry.metadata && logEntry.metadata.type) {
|
716
747
|
logLevel = logEntry.metadata.type;
|
717
|
-
} else if (logEntry.metadata && logEntry.metadata.phase) {
|
718
|
-
if (logEntry.metadata.phase === 'complete' ||
|
719
|
-
logEntry.metadata.phase === 'iteration_complete' ||
|
720
|
-
logEntry.metadata.phase === 'report_complete') {
|
721
|
-
logLevel = 'milestone';
|
722
|
-
} else if (logEntry.metadata.phase === 'error') {
|
723
|
-
logLevel = 'error';
|
724
|
-
}
|
725
748
|
} else if (logEntry.level) {
|
726
749
|
logLevel = logEntry.level;
|
727
750
|
}
|
@@ -842,10 +865,13 @@
|
|
842
865
|
case 'all':
|
843
866
|
return true;
|
844
867
|
case 'info':
|
845
|
-
return logType === 'info';
|
868
|
+
return logType === 'info' || logType === 'warning' || logType === 'milestone' || logType === 'error';
|
846
869
|
case 'milestone':
|
847
870
|
case 'milestones': // Handle plural form too
|
848
871
|
return logType === 'milestone';
|
872
|
+
case 'warning':
|
873
|
+
case 'warnings':
|
874
|
+
return logType === 'warning' || logType === 'error';
|
849
875
|
case 'error':
|
850
876
|
case 'errors': // Handle plural form too
|
851
877
|
return logType === 'error';
|
@@ -910,6 +936,28 @@
|
|
910
936
|
}
|
911
937
|
}
|
912
938
|
|
939
|
+
/**
|
940
|
+
* @brief Handler for the log download button which downloads all the
|
941
|
+
* saved logs to the user's computer.
|
942
|
+
*/
|
943
|
+
function downloadLogs() {
|
944
|
+
const researchId = window._logPanelState.connectedResearchId;
|
945
|
+
fetchLogsForResearch(researchId).then((logData) => {
|
946
|
+
// Create a blob with the logs data
|
947
|
+
const blob = new Blob([JSON.stringify(logData, null, 2)], { type: 'application/json' });
|
948
|
+
|
949
|
+
// Create a link element and trigger download
|
950
|
+
const url = URL.createObjectURL(blob);
|
951
|
+
const a = document.createElement('a');
|
952
|
+
a.href = url;
|
953
|
+
a.download = `research_logs_${researchId}.json`;
|
954
|
+
document.body.appendChild(a);
|
955
|
+
a.click();
|
956
|
+
document.body.removeChild(a);
|
957
|
+
URL.revokeObjectURL(url);
|
958
|
+
});
|
959
|
+
}
|
960
|
+
|
913
961
|
// Expose public API
|
914
962
|
window.logPanel = {
|
915
963
|
initialize: initializeLogPanel,
|
@@ -8,6 +8,9 @@
|
|
8
8
|
let pollInterval = null;
|
9
9
|
let isCompleted = false;
|
10
10
|
let socketErrorShown = false;
|
11
|
+
// Keeps track of whether we've set a specific progress message or just
|
12
|
+
// a generic one based on the status.
|
13
|
+
let specificProgressMessage = false;
|
11
14
|
|
12
15
|
// DOM Elements
|
13
16
|
let progressBar = null;
|
@@ -78,6 +81,9 @@
|
|
78
81
|
cancelButton.addEventListener('click', handleCancelResearch);
|
79
82
|
}
|
80
83
|
|
84
|
+
// Keyboard navigation is now handled by the global keyboard service
|
85
|
+
// The Enter key shortcut for viewing results is automatically registered
|
86
|
+
|
81
87
|
// Note: Log panel is now automatically initialized by logpanel.js
|
82
88
|
// No need to manually initialize it here
|
83
89
|
|
@@ -492,6 +498,7 @@
|
|
492
498
|
for (let i = progressLogs.length - 1; i >= 0; i--) {
|
493
499
|
if (progressLogs[i].message && progressLogs[i].message.trim() !== '') {
|
494
500
|
taskMessage = progressLogs[i].message;
|
501
|
+
specificProgressMessage = true;
|
495
502
|
break;
|
496
503
|
}
|
497
504
|
}
|
@@ -503,6 +510,7 @@
|
|
503
510
|
|
504
511
|
// Check various fields that might contain the current task message
|
505
512
|
if (!taskMessage) {
|
513
|
+
specificProgressMessage = true;
|
506
514
|
if (data.current_task) {
|
507
515
|
taskMessage = data.current_task;
|
508
516
|
} else if (data.message) {
|
@@ -513,8 +521,10 @@
|
|
513
521
|
taskMessage = data.step;
|
514
522
|
} else if (data.phase) {
|
515
523
|
taskMessage = `Phase: ${data.phase}`;
|
516
|
-
} else if (data.log_entry && data.log_entry.message) {
|
524
|
+
} else if (data.log_entry && data.log_entry.message && data.log_entry.type == "milestone") {
|
517
525
|
taskMessage = data.log_entry.message;
|
526
|
+
} else {
|
527
|
+
specificProgressMessage = false;
|
518
528
|
}
|
519
529
|
}
|
520
530
|
|
@@ -528,7 +538,7 @@
|
|
528
538
|
|
529
539
|
// If no message but we have a status, generate a more descriptive message
|
530
540
|
// BUT ONLY if we don't already have a meaningful message displayed
|
531
|
-
if (!
|
541
|
+
if (!specificProgressMessage && data.status && (!currentTaskText.dataset.lastMessage || currentTaskText.textContent === 'In Progress')) {
|
532
542
|
let statusMsg;
|
533
543
|
switch (data.status) {
|
534
544
|
case 'starting':
|
@@ -641,6 +651,7 @@
|
|
641
651
|
}
|
642
652
|
}
|
643
653
|
|
654
|
+
|
644
655
|
/**
|
645
656
|
* Handle research cancellation
|
646
657
|
*/
|