import thisHtml from './thinking-log.html';
import thisCss from './thinking-log.css';
import rootCss from '../root.css';
import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
const logalot = true;
let thinkingLogOverlay: HTMLElement | null = null;
let thinkingLogContainer: HTMLElement | null = null;
let thinkingLogEntries: HTMLElement | null = null;
let thinkingLogCloseBtn: HTMLButtonElement | null = null;
let thinkingLogEntryTemplate: HTMLTemplateElement | null = null;
interface ThinkingEntry {
id: string;
messages: string[]; // Changed from message: string
isComplete: boolean;
isError: boolean;
element: HTMLElement;
}
let thinkingEntries: ThinkingEntry[] = [];
let thinkingLogInitialized = false;
export function initializeThinkingLog(): void {
const lc = `[${initializeThinkingLog.name}]`;
try {
if (logalot) { console.log(`${lc} starting... (I: e5f4b950bf68f4f88a0fff880256d925)`); }
if (thinkingLogInitialized) {
if (logalot) { console.log(`${lc} thinkingLog already initialized (I: 1cf918b81a28eaa30344063d711b5e25)`); }
return; /* <<<< returns early */
} else {
thinkingLogInitialized = true;
}
if (thinkingLogOverlay) {
if (logalot) { console.log(`${lc} thinkingLogOverlay already truthy (I: e020082c2ab822257831c17894ea8825)`); }
return; /* <<<< returns early */
}
document.body.insertAdjacentHTML('beforeend', thisHtml);
const styleSheet = new CSSStyleSheet();
styleSheet.replaceSync(rootCss + '\n' + thisCss);
document.adoptedStyleSheets = [...document.adoptedStyleSheets, styleSheet];
thinkingLogOverlay = document.getElementById('thinking-log-overlay');
thinkingLogContainer = document.getElementById('thinking-log-container');
thinkingLogEntries = document.getElementById('thinking-log-entries');
thinkingLogCloseBtn = document.getElementById('thinking-log-close-btn') as HTMLButtonElement;
thinkingLogEntryTemplate = document.getElementById('thinking-log-entry-template') as HTMLTemplateElement;
if (!thinkingLogOverlay || !thinkingLogContainer || !thinkingLogEntries || !thinkingLogCloseBtn || !thinkingLogEntryTemplate) {
console.error(`${lc} Failed to find all required thinking log elements.`);
return;
}
thinkingLogCloseBtn.addEventListener('click', () => hideThinkingLog());
thinkingLogOverlay.addEventListener('click', (e) => {
if (e.target === thinkingLogOverlay) {
hideThinkingLog();
}
});
} catch (error) {
thinkingLogInitialized = false;
console.error(`${lc} ${extractErrorMsg(error)}`);
throw error;
} finally {
if (logalot) { console.log(`${lc} complete.`); }
}
}
export function showThinkingLog() {
initializeThinkingLog();
if (thinkingLogOverlay) {
thinkingLogOverlay.classList.remove('collapsed');
}
}
export function hideThinkingLog() {
if (thinkingLogOverlay) {
thinkingLogOverlay.classList.add('collapsed');
}
}
export function addThinkingEntry(message: string, thinkingId?: string): string {
const lc = `[addThinkingEntry]`;
if (logalot) { console.log(`${lc} adding entry: ${message}`); }
if (!thinkingLogEntryTemplate || !thinkingLogEntries) {
initializeThinkingLog();
}
if (!thinkingLogEntryTemplate || !thinkingLogEntries) {
console.error(`${lc} Thinking log not properly initialized even after calling initializeThinkingLog. (E: 9b25bd72eb56d94e889cd7a49c88b125)`);
return '';
}
const newEntryId = thinkingId ?? `thinking-entry-${Date.now()}`;
const newEntryFragment = thinkingLogEntryTemplate.content.cloneNode(true) as DocumentFragment;
const newEntryElement = newEntryFragment.firstElementChild as HTMLElement;
if (!newEntryElement) { return ''; }
newEntryElement.id = newEntryId;
const messagesContainer = newEntryElement.querySelector('.thinking-log-messages');
if (messagesContainer) {
const p = document.createElement('p');
p.textContent = message;
messagesContainer.appendChild(p);
}
thinkingLogEntries.prepend(newEntryElement); // prepend to show newest first
const entryData: ThinkingEntry = {
id: newEntryId,
messages: [message],
isComplete: false,
isError: false,
element: newEntryElement,
};
thinkingEntries.push(entryData);
// showThinkingLog();
return newEntryId;
}
/**
*
* todo: refactor this darn function to use named args so it's not all magic
* throughout
*/
export function updateThinkingEntry(id: string, message: string, isComplete: boolean = false, isError: boolean = false) {
const lc = `[updateThinkingEntry]`;
const entry = thinkingEntries.find(e => e.id === id);
if (entry) {
if (logalot) { console.log(`${lc} updating entry ${id}: ${message}`); }
entry.messages.push(message);
entry.isComplete = isComplete;
entry.isError = isError;
const messagesContainer = entry.element.querySelector('.thinking-log-messages');
if (messagesContainer) {
const p = document.createElement('p');
p.textContent = message;
messagesContainer.appendChild(p);
}
if (isComplete) {
const spinner = entry.element.querySelector('.thinking-log-spinner');
if (spinner) { spinner.classList.add('collapsed'); }
}
if (isError) {
entry.element.classList.add('error');
}
} else {
console.warn(`${lc} Could not find thinking entry with id: ${id}`);
}
}