eraz3r commited on
Commit
4f94c64
Β·
verified Β·
1 Parent(s): 6351a26

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +24 -23
app.py CHANGED
@@ -420,22 +420,23 @@ def _parse_ids(text, valid_ids):
420
  import re as _re
421
  return [int(n) for n in _re.findall(r'\b(\d+)\b', text) if int(n) in valid_ids]
422
 
423
- def _chat_msg(role, text):
424
- """Return a (user_msg, assistant_msg) tuple for Gradio Chatbot (non-messages mode)."""
425
- if role == "assistant":
426
- return (None, text)
427
- else:
428
- return (text, None)
 
429
 
430
  def handle_start_journal(user_id):
431
  blank_outputs = ([], [], False,
432
  gr.update(interactive=False), gr.update(interactive=False), gr.update(interactive=False),
433
  [], "marking", "")
434
  if not user_id:
435
- return ([(None, "\u26a0 Please sign in first.")],) + blank_outputs[1:]
436
  tasks = get_tasks(user_id, only_today=True)
437
  if not tasks:
438
- return ([(None, "No tasks scheduled for today. Add and schedule tasks first, then come back to reflect!")],) + blank_outputs[1:]
439
 
440
  tasks_state = [{
441
  "task_id": t["id"], "title": t["title"], "life_area": t.get("life_area",""),
@@ -460,7 +461,7 @@ def handle_start_journal(user_id):
460
  f"Done: **{completed}/{total}**. Still open: {inc_str}. "
461
  f"Tell me if you finished any more, or say **skip** to reflect.")
462
 
463
- chat = [(None, opener)]
464
  hist = [{"role": "assistant", "content": opener, "focus": "task_review"}]
465
  return (
466
  chat, hist, True,
@@ -478,14 +479,14 @@ def handle_journal_message(user_id, user_text, audio_path, chat, hist, tasks_sta
478
  user_text = transcribed
479
  voice_used = True
480
  except Exception as e:
481
- chat = list(chat) + [(None, f"\u26a0 Transcription error: {e}. Please type instead.")]
482
  return chat, hist, "", None, tasks_state, active, phase, ""
483
 
484
  if not active or not user_text.strip():
485
  return list(chat), hist, "", None, tasks_state, active, phase, ""
486
 
487
  display_text = f"\U0001f3a4 *{user_text}*" if voice_used else user_text
488
- chat = list(chat) + [(display_text, None)]
489
  hist = list(hist) + [{"role": "user", "content": user_text}]
490
 
491
  # Phase: marking tasks
@@ -509,14 +510,14 @@ def handle_journal_message(user_id, user_text, audio_path, chat, hist, tasks_sta
509
  ctx = _ensure_context(user_id)
510
  opening = build_opening_question(ctx, tasks_state)
511
  bridge = confirm + opening["question"]
512
- chat = list(chat) + [(None, bridge)]
513
  hist.append({"role": "assistant", "content": bridge, "focus": opening["question_focus"]})
514
  return chat, hist, "", None, tasks_state, active, "reflecting", ""
515
  else:
516
  remaining = [t for t in tasks_state if not t["completed"]]
517
  rem_str = " | ".join(f"#{t['task_id']} {t['title']}" for t in remaining[:5])
518
  follow = confirm + f"Still pending: {rem_str}\n\nAnything else done? Or say **skip** to start reflecting."
519
- chat = list(chat) + [(None, follow)]
520
  hist.append({"role": "assistant", "content": follow, "focus": "task_marking"})
521
  return chat, hist, "", None, tasks_state, active, "marking", ""
522
 
@@ -526,34 +527,34 @@ def handle_journal_message(user_id, user_text, audio_path, chat, hist, tasks_sta
526
  ctx = _ensure_context(user_id)
527
  result = get_next_journal_question(ctx, tasks_state, hist)
528
  except Exception as e:
529
- chat = list(chat) + [(None, f"\u26a0 AI error: {e}. Try again.")]
530
  return chat, hist, "", None, tasks_state, active, phase, ""
531
 
532
  if result.get("session_complete"):
533
  closing = "That's a solid reflection \u2014 I have plenty to work with. \U0001f9e0 Hit **Finish & Save** to lock in your insights!"
534
- chat = list(chat) + [(None, closing)]
535
  hist.append({"role": "assistant", "content": closing, "focus": "complete"})
536
  return chat, hist, "", None, tasks_state, active, "done", _ok("Session complete \u2014 click Finish & Save")
537
 
538
  next_q = result.get("question") or "Anything else you'd like to reflect on?"
539
- chat = list(chat) + [(None, next_q)]
540
  hist.append({"role": "assistant", "content": next_q, "focus": result.get("question_focus","")})
541
  return chat, hist, "", None, tasks_state, active, "reflecting", ""
542
 
543
  # Phase: done
544
- chat = list(chat) + [(None, "Session complete! Click **Finish & Save** to save your insights.")]
545
  return chat, hist, "", None, tasks_state, active, "done", ""
546
 
547
 
548
  def handle_finish_journal(user_id, chat, hist, tasks_state):
549
  if not user_id or not hist:
550
- return list(chat) + [(None, "\u26a0 Nothing to save yet.")], ""
551
  try:
552
  ctx = _ensure_context(user_id)
553
  updated = synthesize_journal(ctx, tasks_state, hist)
554
  save_user_context(user_id, updated)
555
  except Exception as e:
556
- return list(chat) + [(None, f"\u26a0 Save failed: {e}")], _err("Save failed")
557
  total = len(tasks_state)
558
  done = sum(1 for t in tasks_state if t.get("completed"))
559
  rate = round(done / total * 100) if total else 0
@@ -562,7 +563,7 @@ def handle_finish_journal(user_id, chat, hist, tasks_state):
562
  summary = (f"\u2705 **Insights saved!** {done}/{total} tasks ({rate}%) complete today.\n\n"
563
  f"**What I learned:**\n{notes_md}\n\n"
564
  f"I'll use this to make tomorrow's scheduling smarter. Great work! \U0001f319")
565
- return list(chat) + [(None, summary)], _ok(f"Saved! {done}/{total} tasks ({rate}%)")
566
 
567
  def handle_restart_journal():
568
  return [], [], False, gr.update(interactive=False), gr.update(interactive=False), gr.update(interactive=False), [], "marking", ""
@@ -864,7 +865,7 @@ with gr.Blocks(title="\U0001f9e0 Second Brain") as demo:
864
  gr.HTML('<p style="color:#475569;font-size:12px;margin:0 0 10px">Deadline is auto-extracted from your text. Date will be assigned by the AI scheduler.</p>')
865
  with gr.Row():
866
  f_title = gr.Textbox(label="Title", scale=3)
867
- f_area = gr.Dropdown(label="Life Area", choices=["Work","Health","Finance","Learning","Personal","Family","Other"], scale=1)
868
  with gr.Row():
869
  f_urgency = gr.Dropdown(label="Urgency", choices=["Urgent","Not Urgent","Habit"], value="Not Urgent")
870
  f_importance = gr.Dropdown(label="Importance", choices=["Move the Needle","Important","Not Important"], value="Important")
@@ -900,7 +901,7 @@ with gr.Blocks(title="\U0001f9e0 Second Brain") as demo:
900
  gr.HTML('<div class="sec-label" style="margin-top:12px">Review & Confirm</div>')
901
  with gr.Row():
902
  vf_title = gr.Textbox(label="Title", scale=3)
903
- vf_area = gr.Dropdown(label="Life Area", choices=["Work","Health","Finance","Learning","Personal","Family","Other"], scale=1)
904
  with gr.Row():
905
  vf_urgency = gr.Dropdown(label="Urgency", choices=["Urgent","Not Urgent","Habit"], value="Not Urgent")
906
  vf_importance = gr.Dropdown(label="Importance", choices=["Move the Needle","Important","Not Important"], value="Important")
@@ -969,7 +970,7 @@ with gr.Blocks(title="\U0001f9e0 Second Brain") as demo:
969
  # ── TAB 3: JOURNAL ────────────────────────────────────────────
970
  with gr.Tab("\U0001f4d3 Journal"):
971
  gr.HTML('<p style="color:#475569;font-size:13px;margin-bottom:12px">End-of-day reflection. Chat naturally \u2014 AI marks tasks, asks questions, updates your profile.</p>')
972
- journal_chatbot = gr.Chatbot(label="", height=440)
973
  with gr.Row():
974
  j_answer = gr.Textbox(label="", placeholder="Type or use the mic\u2026", lines=1, scale=5, interactive=False, show_label=False)
975
  j_audio_in = gr.Audio(sources=["microphone"], type="filepath", label="\U0001f3a4", scale=1, interactive=False)
 
420
  import re as _re
421
  return [int(n) for n in _re.findall(r'\b(\d+)\b', text) if int(n) in valid_ids]
422
 
423
+ def _bot(text):
424
+ """Return assistant message dict for Gradio Chatbot type='messages'."""
425
+ return {"role": "assistant", "content": text}
426
+
427
+ def _usr(text):
428
+ """Return user message dict for Gradio Chatbot type='messages'."""
429
+ return {"role": "user", "content": text}
430
 
431
  def handle_start_journal(user_id):
432
  blank_outputs = ([], [], False,
433
  gr.update(interactive=False), gr.update(interactive=False), gr.update(interactive=False),
434
  [], "marking", "")
435
  if not user_id:
436
+ return ([_bot("\u26a0 Please sign in first.")],) + blank_outputs[1:]
437
  tasks = get_tasks(user_id, only_today=True)
438
  if not tasks:
439
+ return ([_bot("No tasks scheduled for today. Add and schedule tasks first, then come back to reflect!")],) + blank_outputs[1:]
440
 
441
  tasks_state = [{
442
  "task_id": t["id"], "title": t["title"], "life_area": t.get("life_area",""),
 
461
  f"Done: **{completed}/{total}**. Still open: {inc_str}. "
462
  f"Tell me if you finished any more, or say **skip** to reflect.")
463
 
464
+ chat = [_bot(opener)]
465
  hist = [{"role": "assistant", "content": opener, "focus": "task_review"}]
466
  return (
467
  chat, hist, True,
 
479
  user_text = transcribed
480
  voice_used = True
481
  except Exception as e:
482
+ chat = list(chat) + [_bot(f"\u26a0 Transcription error: {e}. Please type instead.")]
483
  return chat, hist, "", None, tasks_state, active, phase, ""
484
 
485
  if not active or not user_text.strip():
486
  return list(chat), hist, "", None, tasks_state, active, phase, ""
487
 
488
  display_text = f"\U0001f3a4 *{user_text}*" if voice_used else user_text
489
+ chat = list(chat) + [_usr(display_text)]
490
  hist = list(hist) + [{"role": "user", "content": user_text}]
491
 
492
  # Phase: marking tasks
 
510
  ctx = _ensure_context(user_id)
511
  opening = build_opening_question(ctx, tasks_state)
512
  bridge = confirm + opening["question"]
513
+ chat = list(chat) + [_bot(bridge)]
514
  hist.append({"role": "assistant", "content": bridge, "focus": opening["question_focus"]})
515
  return chat, hist, "", None, tasks_state, active, "reflecting", ""
516
  else:
517
  remaining = [t for t in tasks_state if not t["completed"]]
518
  rem_str = " | ".join(f"#{t['task_id']} {t['title']}" for t in remaining[:5])
519
  follow = confirm + f"Still pending: {rem_str}\n\nAnything else done? Or say **skip** to start reflecting."
520
+ chat = list(chat) + [_bot(follow)]
521
  hist.append({"role": "assistant", "content": follow, "focus": "task_marking"})
522
  return chat, hist, "", None, tasks_state, active, "marking", ""
523
 
 
527
  ctx = _ensure_context(user_id)
528
  result = get_next_journal_question(ctx, tasks_state, hist)
529
  except Exception as e:
530
+ chat = list(chat) + [_bot(f"\u26a0 AI error: {e}. Try again.")]
531
  return chat, hist, "", None, tasks_state, active, phase, ""
532
 
533
  if result.get("session_complete"):
534
  closing = "That's a solid reflection \u2014 I have plenty to work with. \U0001f9e0 Hit **Finish & Save** to lock in your insights!"
535
+ chat = list(chat) + [_bot(closing)]
536
  hist.append({"role": "assistant", "content": closing, "focus": "complete"})
537
  return chat, hist, "", None, tasks_state, active, "done", _ok("Session complete \u2014 click Finish & Save")
538
 
539
  next_q = result.get("question") or "Anything else you'd like to reflect on?"
540
+ chat = list(chat) + [_bot(next_q)]
541
  hist.append({"role": "assistant", "content": next_q, "focus": result.get("question_focus","")})
542
  return chat, hist, "", None, tasks_state, active, "reflecting", ""
543
 
544
  # Phase: done
545
+ chat = list(chat) + [_bot("Session complete! Click **Finish & Save** to save your insights.")]
546
  return chat, hist, "", None, tasks_state, active, "done", ""
547
 
548
 
549
  def handle_finish_journal(user_id, chat, hist, tasks_state):
550
  if not user_id or not hist:
551
+ return list(chat) + [_bot("\u26a0 Nothing to save yet.")], ""
552
  try:
553
  ctx = _ensure_context(user_id)
554
  updated = synthesize_journal(ctx, tasks_state, hist)
555
  save_user_context(user_id, updated)
556
  except Exception as e:
557
+ return list(chat) + [_bot(f"\u26a0 Save failed: {e}")], _err("Save failed")
558
  total = len(tasks_state)
559
  done = sum(1 for t in tasks_state if t.get("completed"))
560
  rate = round(done / total * 100) if total else 0
 
563
  summary = (f"\u2705 **Insights saved!** {done}/{total} tasks ({rate}%) complete today.\n\n"
564
  f"**What I learned:**\n{notes_md}\n\n"
565
  f"I'll use this to make tomorrow's scheduling smarter. Great work! \U0001f319")
566
+ return list(chat) + [_bot(summary)], _ok(f"Saved! {done}/{total} tasks ({rate}%)")
567
 
568
  def handle_restart_journal():
569
  return [], [], False, gr.update(interactive=False), gr.update(interactive=False), gr.update(interactive=False), [], "marking", ""
 
865
  gr.HTML('<p style="color:#475569;font-size:12px;margin:0 0 10px">Deadline is auto-extracted from your text. Date will be assigned by the AI scheduler.</p>')
866
  with gr.Row():
867
  f_title = gr.Textbox(label="Title", scale=3)
868
+ f_area = gr.Dropdown(label="Life Area", choices=["Work","Health","Finance","Learning","Personal","Family","Other"], scale=1, allow_custom_value=True)
869
  with gr.Row():
870
  f_urgency = gr.Dropdown(label="Urgency", choices=["Urgent","Not Urgent","Habit"], value="Not Urgent")
871
  f_importance = gr.Dropdown(label="Importance", choices=["Move the Needle","Important","Not Important"], value="Important")
 
901
  gr.HTML('<div class="sec-label" style="margin-top:12px">Review & Confirm</div>')
902
  with gr.Row():
903
  vf_title = gr.Textbox(label="Title", scale=3)
904
+ vf_area = gr.Dropdown(label="Life Area", choices=["Work","Health","Finance","Learning","Personal","Family","Other"], scale=1, allow_custom_value=True)
905
  with gr.Row():
906
  vf_urgency = gr.Dropdown(label="Urgency", choices=["Urgent","Not Urgent","Habit"], value="Not Urgent")
907
  vf_importance = gr.Dropdown(label="Importance", choices=["Move the Needle","Important","Not Important"], value="Important")
 
970
  # ── TAB 3: JOURNAL ────────────────────────────────────────────
971
  with gr.Tab("\U0001f4d3 Journal"):
972
  gr.HTML('<p style="color:#475569;font-size:13px;margin-bottom:12px">End-of-day reflection. Chat naturally \u2014 AI marks tasks, asks questions, updates your profile.</p>')
973
+ journal_chatbot = gr.Chatbot(label="", height=440, type="messages")
974
  with gr.Row():
975
  j_answer = gr.Textbox(label="", placeholder="Type or use the mic\u2026", lines=1, scale=5, interactive=False, show_label=False)
976
  j_audio_in = gr.Audio(sources=["microphone"], type="filepath", label="\U0001f3a4", scale=1, interactive=False)