Spaces:
Sleeping
Sleeping
Rick commited on
Commit ·
11cddd3
1
Parent(s): 1f3568f
HF defaults: start in Advanced mode and auto-open Ethan consultation log
Browse files- app.db +1 -1
- app.py +1 -1
- static/js/crew.js +34 -0
- static/js/main.js +10 -0
- static/js/settings.js +11 -11
- templates/index.html +2 -2
app.db
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
size 45715456
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:502d140bb041a6c6764f5fc385c957da7bcd157fa0b5484dcf9dab3eb6a05959
|
| 3 |
size 45715456
|
app.py
CHANGED
|
@@ -1314,7 +1314,7 @@ def get_defaults():
|
|
| 1314 |
"in_k": 50,
|
| 1315 |
"rep_penalty": 1.1,
|
| 1316 |
"mission_context": "Isolated Medical Station offshore.",
|
| 1317 |
-
"user_mode": "
|
| 1318 |
"db_write_lock": bool(get_db_write_lock()),
|
| 1319 |
"db_write_lock_forced": DB_WRITE_LOCK_FORCED is not None,
|
| 1320 |
"last_prompt_verbatim": "",
|
|
|
|
| 1314 |
"in_k": 50,
|
| 1315 |
"rep_penalty": 1.1,
|
| 1316 |
"mission_context": "Isolated Medical Station offshore.",
|
| 1317 |
+
"user_mode": "advanced",
|
| 1318 |
"db_write_lock": bool(get_db_write_lock()),
|
| 1319 |
"db_write_lock_forced": DB_WRITE_LOCK_FORCED is not None,
|
| 1320 |
"last_prompt_verbatim": "",
|
static/js/crew.js
CHANGED
|
@@ -717,6 +717,39 @@ function renderHistorySection(label, entries, defaultOpen = true) {
|
|
| 717 |
</div>`;
|
| 718 |
}
|
| 719 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 720 |
/**
|
| 721 |
* Retrieve chat history entries for a specific crew member.
|
| 722 |
*
|
|
@@ -1227,6 +1260,7 @@ window.exportHistoryItemById = exportHistoryItemById;
|
|
| 1227 |
window.toggleHistoryEntryEditor = toggleHistoryEntryEditor;
|
| 1228 |
window.saveHistoryItemById = saveHistoryItemById;
|
| 1229 |
window.deleteHistoryItemById = deleteHistoryItemById;
|
|
|
|
| 1230 |
|
| 1231 |
|
| 1232 |
/**
|
|
|
|
| 717 |
</div>`;
|
| 718 |
}
|
| 719 |
|
| 720 |
+
/**
|
| 721 |
+
* Auto-open Ethan Buchan's consultation log section and first entry.
|
| 722 |
+
*
|
| 723 |
+
* This is used for the initial Consultation Log tab experience in demo mode.
|
| 724 |
+
* Returns true when the target section was found (opened or already open).
|
| 725 |
+
*/
|
| 726 |
+
function autoOpenEthanConsultationLog() {
|
| 727 |
+
const medicalContainer = document.getElementById('crew-medical-list');
|
| 728 |
+
if (!medicalContainer) return false;
|
| 729 |
+
|
| 730 |
+
const sectionHeaders = Array.from(medicalContainer.querySelectorAll('.history-item > .col-header'));
|
| 731 |
+
const ethanHeader = sectionHeaders.find((header) => {
|
| 732 |
+
const text = (header.textContent || '').toLowerCase();
|
| 733 |
+
return text.includes('ethan') && text.includes('buchan');
|
| 734 |
+
});
|
| 735 |
+
if (!ethanHeader) return false;
|
| 736 |
+
|
| 737 |
+
const ethanBody = ethanHeader.nextElementSibling;
|
| 738 |
+
if (!ethanBody) return false;
|
| 739 |
+
if (ethanBody.style.display !== 'block') {
|
| 740 |
+
toggleCrewSection(ethanHeader);
|
| 741 |
+
}
|
| 742 |
+
|
| 743 |
+
const firstEntryHeader = ethanBody.querySelector('.collapsible .col-header');
|
| 744 |
+
if (firstEntryHeader) {
|
| 745 |
+
const firstEntryBody = firstEntryHeader.nextElementSibling;
|
| 746 |
+
if (firstEntryBody && firstEntryBody.style.display !== 'block') {
|
| 747 |
+
toggleLogEntry(firstEntryHeader);
|
| 748 |
+
}
|
| 749 |
+
}
|
| 750 |
+
return true;
|
| 751 |
+
}
|
| 752 |
+
|
| 753 |
/**
|
| 754 |
* Retrieve chat history entries for a specific crew member.
|
| 755 |
*
|
|
|
|
| 1260 |
window.toggleHistoryEntryEditor = toggleHistoryEntryEditor;
|
| 1261 |
window.saveHistoryItemById = saveHistoryItemById;
|
| 1262 |
window.deleteHistoryItemById = deleteHistoryItemById;
|
| 1263 |
+
window.autoOpenEthanConsultationLog = autoOpenEthanConsultationLog;
|
| 1264 |
|
| 1265 |
|
| 1266 |
/**
|
static/js/main.js
CHANGED
|
@@ -96,6 +96,7 @@ let crewDataLoaded = false; // Prevent duplicate crew data loads
|
|
| 96 |
let crewDataPromise = null; // Promise for concurrent load protection
|
| 97 |
let loadDataInFlight = null; // Shared promise so concurrent refreshes collapse into one request
|
| 98 |
let cachedPatientsRoster = null; // Last successful /api/data/patients payload for lightweight refreshes
|
|
|
|
| 99 |
const LAST_PATIENT_KEY_MAIN = 'sailingmed:lastPatient';
|
| 100 |
const CREW_OPTIONS_CACHE_KEY = 'sailingmed:crewOptionsCache';
|
| 101 |
const COLLAPSIBLE_PREF_SCHEMA_KEY = 'sailingmed:collapsiblePrefSchema';
|
|
@@ -594,6 +595,15 @@ async function showTab(trigger, n) {
|
|
| 594 |
if (n === 'VesselCrewInfo' && typeof ensureVesselLoaded === 'function') {
|
| 595 |
await ensureVesselLoaded();
|
| 596 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 597 |
} catch (err) {
|
| 598 |
console.warn('Tab load data failed:', err);
|
| 599 |
}
|
|
|
|
| 96 |
let crewDataPromise = null; // Promise for concurrent load protection
|
| 97 |
let loadDataInFlight = null; // Shared promise so concurrent refreshes collapse into one request
|
| 98 |
let cachedPatientsRoster = null; // Last successful /api/data/patients payload for lightweight refreshes
|
| 99 |
+
let consultationLogAutoOpened = false; // One-time auto-open for Ethan consultation log section
|
| 100 |
const LAST_PATIENT_KEY_MAIN = 'sailingmed:lastPatient';
|
| 101 |
const CREW_OPTIONS_CACHE_KEY = 'sailingmed:crewOptionsCache';
|
| 102 |
const COLLAPSIBLE_PREF_SCHEMA_KEY = 'sailingmed:collapsiblePrefSchema';
|
|
|
|
| 595 |
if (n === 'VesselCrewInfo' && typeof ensureVesselLoaded === 'function') {
|
| 596 |
await ensureVesselLoaded();
|
| 597 |
}
|
| 598 |
+
if (n === 'CrewMedical' && !consultationLogAutoOpened && typeof window.autoOpenEthanConsultationLog === 'function') {
|
| 599 |
+
requestAnimationFrame(() => {
|
| 600 |
+
try {
|
| 601 |
+
consultationLogAutoOpened = !!window.autoOpenEthanConsultationLog();
|
| 602 |
+
} catch (err) {
|
| 603 |
+
console.warn('Unable to auto-open Ethan consultation log section:', err);
|
| 604 |
+
}
|
| 605 |
+
});
|
| 606 |
+
}
|
| 607 |
} catch (err) {
|
| 608 |
console.warn('Tab load data failed:', err);
|
| 609 |
}
|
static/js/settings.js
CHANGED
|
@@ -25,12 +25,12 @@ Settings are stored in settings.json on the backend and cached in window.CACHED_
|
|
| 25 |
on the frontend. Auto-save triggers 800ms after user input to minimize write operations.
|
| 26 |
|
| 27 |
User Modes:
|
| 28 |
-
1. USER MODE
|
| 29 |
- Basic prompts visible
|
| 30 |
- Simple status indicators
|
| 31 |
- Essential functionality only
|
| 32 |
|
| 33 |
-
2. ADVANCED MODE: Shows model parameters and detailed configuration
|
| 34 |
- Temperature, token limits, top-p visible
|
| 35 |
- Detailed status with metrics
|
| 36 |
- Import/export features
|
|
@@ -107,7 +107,7 @@ const DEFAULT_SETTINGS = {
|
|
| 107 |
in_k: 50,
|
| 108 |
mission_context: "Isolated Medical Station offshore.",
|
| 109 |
rep_penalty: 1.1,
|
| 110 |
-
user_mode: "
|
| 111 |
last_prompt_verbatim: "",
|
| 112 |
vaccine_types: ["MMR", "DTaP", "HepB", "HepA", "Td/Tdap", "Influenza", "COVID-19"],
|
| 113 |
pharmacy_labels: ["Antibiotic", "Analgesic", "Cardiac", "Respiratory", "Gastrointestinal", "Endocrine", "Emergency"],
|
|
@@ -280,7 +280,7 @@ function updateSettingsMeta(settings = {}) {
|
|
| 280 |
if (consCatEl) consCatEl.textContent = `${consumableCategoryList.length} categories`;
|
| 281 |
// User mode
|
| 282 |
const modeEl = document.getElementById('user-mode-meta');
|
| 283 |
-
if (modeEl) modeEl.textContent = `Mode: ${settings.user_mode || '
|
| 284 |
// Crew creds (updated when crew list loads)
|
| 285 |
// Model params
|
| 286 |
const modelEl = document.getElementById('model-meta');
|
|
@@ -362,7 +362,7 @@ function applySettingsToUI(data = {}) {
|
|
| 362 |
}
|
| 363 |
}
|
| 364 |
setUserMode(merged.user_mode);
|
| 365 |
-
try { localStorage.setItem('user_mode', merged.user_mode || '
|
| 366 |
window.CACHED_SETTINGS = merged;
|
| 367 |
settingsDirty = false;
|
| 368 |
settingsLoaded = true;
|
|
@@ -1519,7 +1519,7 @@ function bindSettingsDirtyTracking() {
|
|
| 1519 |
}
|
| 1520 |
if (el.classList.contains('developer-only')) {
|
| 1521 |
// Keep developer-only components in sync
|
| 1522 |
-
setUserMode(document.getElementById('user_mode')?.value || '
|
| 1523 |
}
|
| 1524 |
updateSettingsMeta(window.CACHED_SETTINGS || {});
|
| 1525 |
});
|
|
@@ -1530,7 +1530,7 @@ function bindSettingsDirtyTracking() {
|
|
| 1530 |
saveSettings(false, 'user-mode-change').catch(() => {});
|
| 1531 |
}
|
| 1532 |
if (el.classList.contains('developer-only')) {
|
| 1533 |
-
setUserMode(document.getElementById('user_mode')?.value || '
|
| 1534 |
}
|
| 1535 |
updateSettingsMeta(window.CACHED_SETTINGS || {});
|
| 1536 |
});
|
|
@@ -1577,7 +1577,7 @@ async function loadSettingsUI() {
|
|
| 1577 |
loadPromptTemplates().catch(() => {});
|
| 1578 |
loadTriagePromptTree().catch(() => {});
|
| 1579 |
loadRuntimeLog().catch(() => {});
|
| 1580 |
-
try { localStorage.setItem('user_mode', s.user_mode || '
|
| 1581 |
if (!offlineInitialized) {
|
| 1582 |
offlineInitialized = true;
|
| 1583 |
runOfflineCheck(false).catch((err) => {
|
|
@@ -1588,7 +1588,7 @@ async function loadSettingsUI() {
|
|
| 1588 |
console.error('Settings load error', err);
|
| 1589 |
alert(`Unable to load settings: ${err.message}`);
|
| 1590 |
const localMode = (() => {
|
| 1591 |
-
try { return localStorage.getItem('user_mode') || '
|
| 1592 |
})();
|
| 1593 |
applySettingsToUI({ ...DEFAULT_SETTINGS, user_mode: localMode });
|
| 1594 |
loadPromptTemplates().catch(() => {});
|
|
@@ -1623,7 +1623,7 @@ function updateSettingsStatus(message, isError = false) {
|
|
| 1623 |
*/
|
| 1624 |
function applyStoredUserMode() {
|
| 1625 |
try {
|
| 1626 |
-
const stored = localStorage.getItem('user_mode') || '
|
| 1627 |
setUserMode(stored);
|
| 1628 |
} catch (err) { /* ignore */ }
|
| 1629 |
}
|
|
@@ -1723,7 +1723,7 @@ async function saveSettings(showAlert = true, reason = 'manual') {
|
|
| 1723 |
pharmacy_labels: s.pharmacy_labels || updated.pharmacy_labels
|
| 1724 |
};
|
| 1725 |
applySettingsToUI(merged);
|
| 1726 |
-
try { localStorage.setItem('user_mode', updated.user_mode || '
|
| 1727 |
settingsDirty = false;
|
| 1728 |
updateSettingsStatus(`Saved at ${new Date().toLocaleTimeString()}`);
|
| 1729 |
if (showAlert) {
|
|
|
|
| 25 |
on the frontend. Auto-save triggers 800ms after user input to minimize write operations.
|
| 26 |
|
| 27 |
User Modes:
|
| 28 |
+
1. USER MODE: Simplified interface, hides advanced configuration
|
| 29 |
- Basic prompts visible
|
| 30 |
- Simple status indicators
|
| 31 |
- Essential functionality only
|
| 32 |
|
| 33 |
+
2. ADVANCED MODE (Default): Shows model parameters and detailed configuration
|
| 34 |
- Temperature, token limits, top-p visible
|
| 35 |
- Detailed status with metrics
|
| 36 |
- Import/export features
|
|
|
|
| 107 |
in_k: 50,
|
| 108 |
mission_context: "Isolated Medical Station offshore.",
|
| 109 |
rep_penalty: 1.1,
|
| 110 |
+
user_mode: "advanced",
|
| 111 |
last_prompt_verbatim: "",
|
| 112 |
vaccine_types: ["MMR", "DTaP", "HepB", "HepA", "Td/Tdap", "Influenza", "COVID-19"],
|
| 113 |
pharmacy_labels: ["Antibiotic", "Analgesic", "Cardiac", "Respiratory", "Gastrointestinal", "Endocrine", "Emergency"],
|
|
|
|
| 280 |
if (consCatEl) consCatEl.textContent = `${consumableCategoryList.length} categories`;
|
| 281 |
// User mode
|
| 282 |
const modeEl = document.getElementById('user-mode-meta');
|
| 283 |
+
if (modeEl) modeEl.textContent = `Mode: ${settings.user_mode || 'advanced'}`;
|
| 284 |
// Crew creds (updated when crew list loads)
|
| 285 |
// Model params
|
| 286 |
const modelEl = document.getElementById('model-meta');
|
|
|
|
| 362 |
}
|
| 363 |
}
|
| 364 |
setUserMode(merged.user_mode);
|
| 365 |
+
try { localStorage.setItem('user_mode', merged.user_mode || 'advanced'); } catch (err) { /* ignore */ }
|
| 366 |
window.CACHED_SETTINGS = merged;
|
| 367 |
settingsDirty = false;
|
| 368 |
settingsLoaded = true;
|
|
|
|
| 1519 |
}
|
| 1520 |
if (el.classList.contains('developer-only')) {
|
| 1521 |
// Keep developer-only components in sync
|
| 1522 |
+
setUserMode(document.getElementById('user_mode')?.value || 'advanced');
|
| 1523 |
}
|
| 1524 |
updateSettingsMeta(window.CACHED_SETTINGS || {});
|
| 1525 |
});
|
|
|
|
| 1530 |
saveSettings(false, 'user-mode-change').catch(() => {});
|
| 1531 |
}
|
| 1532 |
if (el.classList.contains('developer-only')) {
|
| 1533 |
+
setUserMode(document.getElementById('user_mode')?.value || 'advanced');
|
| 1534 |
}
|
| 1535 |
updateSettingsMeta(window.CACHED_SETTINGS || {});
|
| 1536 |
});
|
|
|
|
| 1577 |
loadPromptTemplates().catch(() => {});
|
| 1578 |
loadTriagePromptTree().catch(() => {});
|
| 1579 |
loadRuntimeLog().catch(() => {});
|
| 1580 |
+
try { localStorage.setItem('user_mode', s.user_mode || 'advanced'); } catch (err) { /* ignore */ }
|
| 1581 |
if (!offlineInitialized) {
|
| 1582 |
offlineInitialized = true;
|
| 1583 |
runOfflineCheck(false).catch((err) => {
|
|
|
|
| 1588 |
console.error('Settings load error', err);
|
| 1589 |
alert(`Unable to load settings: ${err.message}`);
|
| 1590 |
const localMode = (() => {
|
| 1591 |
+
try { return localStorage.getItem('user_mode') || 'advanced'; } catch (e) { return 'advanced'; }
|
| 1592 |
})();
|
| 1593 |
applySettingsToUI({ ...DEFAULT_SETTINGS, user_mode: localMode });
|
| 1594 |
loadPromptTemplates().catch(() => {});
|
|
|
|
| 1623 |
*/
|
| 1624 |
function applyStoredUserMode() {
|
| 1625 |
try {
|
| 1626 |
+
const stored = localStorage.getItem('user_mode') || 'advanced';
|
| 1627 |
setUserMode(stored);
|
| 1628 |
} catch (err) { /* ignore */ }
|
| 1629 |
}
|
|
|
|
| 1723 |
pharmacy_labels: s.pharmacy_labels || updated.pharmacy_labels
|
| 1724 |
};
|
| 1725 |
applySettingsToUI(merged);
|
| 1726 |
+
try { localStorage.setItem('user_mode', updated.user_mode || 'advanced'); } catch (err) { /* ignore */ }
|
| 1727 |
settingsDirty = false;
|
| 1728 |
updateSettingsStatus(`Saved at ${new Date().toLocaleTimeString()}`);
|
| 1729 |
if (showAlert) {
|
templates/index.html
CHANGED
|
@@ -335,13 +335,13 @@
|
|
| 335 |
<script>
|
| 336 |
(function primeUserMode() {
|
| 337 |
try {
|
| 338 |
-
const stored = localStorage.getItem('user_mode') || '
|
| 339 |
const cls = `mode-${stored}`;
|
| 340 |
document.documentElement.classList.add(cls);
|
| 341 |
} catch (err) { /* ignore */ }
|
| 342 |
document.addEventListener('DOMContentLoaded', () => {
|
| 343 |
try {
|
| 344 |
-
const stored = localStorage.getItem('user_mode') || '
|
| 345 |
const cls = `mode-${stored}`;
|
| 346 |
document.body.classList.remove('mode-user', 'mode-advanced', 'mode-developer');
|
| 347 |
document.body.classList.add(cls);
|
|
|
|
| 335 |
<script>
|
| 336 |
(function primeUserMode() {
|
| 337 |
try {
|
| 338 |
+
const stored = localStorage.getItem('user_mode') || 'advanced';
|
| 339 |
const cls = `mode-${stored}`;
|
| 340 |
document.documentElement.classList.add(cls);
|
| 341 |
} catch (err) { /* ignore */ }
|
| 342 |
document.addEventListener('DOMContentLoaded', () => {
|
| 343 |
try {
|
| 344 |
+
const stored = localStorage.getItem('user_mode') || 'advanced';
|
| 345 |
const cls = `mode-${stored}`;
|
| 346 |
document.body.classList.remove('mode-user', 'mode-advanced', 'mode-developer');
|
| 347 |
document.body.classList.add(cls);
|