88Â `;
89
90function generateHtmlShell(sourceUrl: string): string {
91 return `Â
92Â <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Honeydew</title>
473Â <template id="review-task-template"><div class="review-task-item"><input type="text" class="review-task-content" placeholder="Task description" required><input type="date" class="review-task-due-date" title="Due Date"><select class="review-task-load" title="Cognitive Load"><option value="Low">Low</option><option value="Medium" selected>Medium</option><option value="High">High</option></select><button type="button" class="review-task-delete-btn" title="Remove Task">×</button></div></template>Â
474Â <script>Â
475Â (function() {
476Â const API_URL = '${sourceUrl}';Â
477Â const STORE_KEYS = { projects: 'honeydew_projects_v1', tasks: 'honeydew_tasks_v1', theme: 'honeydew_theme_v1' };Â
483Â const genId = () => Date.now().toString(36) + Math.random().toString(36).substr(2, 9);Â
484Â Â
485Â function loadState() {Â
486Â Â projects = getStore(STORE_KEYS.projects);Â
487Â Â tasks = getStore(STORE_KEYS.tasks);Â
492Â }Â
493
494Â function render() {Â
495Â Â renderSidebar();Â
496Â Â renderTaskList();Â
498Â }Â
499
500Â function toggleLoading(btn, show) {Â
501Â Â if (!btn) return;Â
502Â Â btn.disabled = show;Â
504Â }Â
505Â Â
506Â function updateUIElements() {Â
507Â Â const todayStr = new Date().toISOString().split("T")[0];Â
508Â Â const todayTasks = tasks.filter(t => !t.isCompleted && t.dueDate === todayStr);Â
522Â }Â
523
524Â function renderSidebar() {Â
525Â Â const mainViews = [Â
526Â Â Â {id:'today',name:'Today',icon:'M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1z'},Â
531Â }Â
532
533Â function renderTaskList() {Â
534Â Â const container = $("#task-list");Â
535Â Â let filteredTasks = [], title = 'Tasks';Â
561Â }Â
562
563Â function renderChatLog() {Â
564Â Â const log = $("#chat-log");Â
565Â Â log.innerHTML = conversationHistory.map(msg => {Â
632Â };Â
633
634 function executeSingleCommand(command) {
635 if (!command || !command.tool_name) return;
636 if (command.tool_name === 'ask_for_confirmation') {
657 }
658
659 function executeManualCommand(command) {
660 if (Array.isArray(command)) {
661 command.forEach(c => executeSingleCommand(c));
665 }
666
667Â async function handleChatSubmit(e) {Â
668Â Â e.preventDefault();Â
669Â Â const input = $("#chat-input"), userMessage = input.value.trim();Â
713Â }Â
714Â Â
715Â function handleAddTask(e) {Â
716Â Â e.preventDefault();Â
717Â Â const input = $("#new-task-input"), content = input.value.trim();Â
738Â }Â
739
740Â function handleTaskClick(e) {Â
741Â Â const target = e.target, taskItem = target.closest(".task-item");Â
742Â Â if (!taskItem) return;Â
756Â }Â
757
758Â function openEditModal(task) {Â
759Â Â $("#edit-task-id").value = task.id;Â
760Â Â $("#edit-task-content").value = task.content;Â
765Â }Â
766
767Â function handleUpdateTask(e) {Â
768Â Â e.preventDefault();Â
769Â Â const taskId = $("#edit-task-id").value, task = tasks.find(t => t.id === taskId);Â
777Â }Â
778Â Â
779Â async function triggerProjectSynthesisFromButton() {Â
780Â Â const goal = prompt("Describe your new project or goal:", "Plan a launch party for a new product");Â
781Â Â if (!goal) return;Â
794Â }Â
795Â Â
796Â async function triggerDailyRebalance() {Â
797Â Â const todayStr = new Date().toISOString().split("T")[0];Â
798Â Â const todayTasks = tasks.filter(t => !t.isCompleted && t.dueDate === todayStr);Â
820Â }Â
821
822Â function handleOpenChat() {Â
823Â Â const mainInput = $('#new-task-input');Â
824Â Â const text = mainInput.value.trim();Â
833Â }Â
834Â Â
835Â function addReviewTaskRow(taskData = {}) {Â
836Â Â const template = $('#review-task-template');Â
837Â Â const clone = template.content.cloneNode(true);Â
844Â }Â
845
846Â function openProjectReviewModal(data) {Â
847Â Â const { projectName, tasks: aiTasks } = data;Â
848Â Â $('#review-project-name').value = projectName;Â
855Â }Â
856
857Â function handleProjectReviewSubmit(e) {Â
858Â Â e.preventDefault();Â
859Â Â const projectName = $('#review-project-name').value.trim();Â
877Â }Â
878
879 function initTheme() {
880 const themeToggle = $('#theme-toggle');
881 const storedTheme = localStorage.getItem(STORE_KEYS.theme);
897 }
898
899Â function bindEventListeners() {Â
900Â Â document.body.addEventListener('click', e => {Â
901Â Â Â if (e.target.closest('[data-view]')) {Â
953}
954
955export default async function(req: Request): Promise<Response> {
956 const openai = new OpenAI();
957 const url = new URL(req.url);