Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
89d056c
chore: updates reqs.txt to take into account pip deps
kalyanoliveira Feb 21, 2026
68a53ac
writes the flask bridge server
kalyanoliveira Feb 21, 2026
7a97d8b
tells nextjs to not bundle large ai deps
kalyanoliveira Feb 21, 2026
1d3cef4
chore: updates package.json and lock to add embeeding deps
kalyanoliveira Feb 21, 2026
949515d
writes api routes for saving and summarizing journal entries
kalyanoliveira Feb 21, 2026
324e7a0
chore: updates requirements.txt
kalyanoliveira Feb 21, 2026
82df968
adds /agent/search http route to bridge.py
kalyanoliveira Feb 21, 2026
40646f9
writes langchain related code for the reasoning agent, archivist agen…
kalyanoliveira Feb 21, 2026
0452f29
writes langchain workflow
kalyanoliveira Feb 21, 2026
a51b76b
writes route.js for /api/therapy/chat
kalyanoliveira Feb 21, 2026
6e51e1c
writes the type for a patient file
kalyanoliveira Feb 21, 2026
ce8b1c2
adds /journal/save_chat POST to bridge.py
kalyanoliveira Feb 21, 2026
c7ab5be
evolves state.py to cover full life cycle of therepy session
kalyanoliveira Feb 21, 2026
6e22785
docs: better documents state.py
kalyanoliveira Feb 21, 2026
15b46d9
updates agents definition for the newer 'schedule appointment' paradigm
kalyanoliveira Feb 21, 2026
f383bd1
writes langchain workflow in new graph.py file
kalyanoliveira Feb 21, 2026
110130f
writes route.js for /api/therapy/start
kalyanoliveira Feb 21, 2026
78043a2
adds a component for exercise list
kalyanoliveira Feb 21, 2026
67ada66
chore: updates reqs.txt
kalyanoliveira Feb 21, 2026
a7bfd49
updates state.py by removing iteration count
kalyanoliveira Feb 21, 2026
94e3c43
misc updates to agents.py
kalyanoliveira Feb 21, 2026
4adec5b
misc updates to graph.py
kalyanoliveira Feb 21, 2026
a6e436d
updates brigde.py by adding /agent/start and /journal/save-session ap…
kalyanoliveira Feb 21, 2026
8fab48c
writes page.js for testing the therapy agent stuff
kalyanoliveira Feb 21, 2026
9a49ec8
updates route.js
kalyanoliveira Feb 21, 2026
e1f4ea7
chore: updates next.config.mjs
kalyanoliveira Feb 21, 2026
cf5ea97
debug: simplifies journal/save/route.js for debug purposes
kalyanoliveira Feb 21, 2026
7bad6d4
writes simple embedder script for backend
kalyanoliveira Feb 21, 2026
81d4f54
updates bridge.py for backend embedding
kalyanoliveira Feb 21, 2026
b139b77
updates agents.py to take into account backend embedding paradigm
kalyanoliveira Feb 21, 2026
aa8b32a
simplies journal save route.js for backend embedding
kalyanoliveira Feb 21, 2026
8bc7cb1
debuggin updates brosky common
kalyanoliveira Feb 21, 2026
8a37c8c
updates /agent/start endpoint in flask bridge to acc execute langchai…
kalyanoliveira Feb 21, 2026
9b6c093
updates bridge.py to take into account the api route names that the f…
kalyanoliveira Feb 21, 2026
f36637c
@app.route('/agent/run_session', methods=['POST'])
kalyanoliveira Feb 21, 2026
e89125c
updates route.js for /api/therapy/chat
kalyanoliveira Feb 21, 2026
8ed41da
adds missing langchain message import to top of bridge.py
kalyanoliveira Feb 21, 2026
bdfcab7
updates run/session in flask bridge to remember previous session (and…
kalyanoliveira Feb 21, 2026
c1ab91c
tries make run_session in flask bridge to remember stuff again
kalyanoliveira Feb 21, 2026
34d7feb
updates agent.py
kalyanoliveira Feb 21, 2026
0d2bfb5
adds /agent/start to flask bridge endpoints
kalyanoliveira Feb 21, 2026
7eb0224
uses correct function to get embedding in agent_search flask endpoint
kalyanoliveira Feb 21, 2026
8578ab2
attempts to fix run_session flask endpoint to not use empty evidences…
kalyanoliveira Feb 21, 2026
26eb8ff
adds journal/save_session endpoint to flask bridge
kalyanoliveira Feb 21, 2026
d04e705
chore removes a swp file
kalyanoliveira Feb 21, 2026
181115f
updates page.js
kalyanoliveira Feb 21, 2026
e408667
updates flask bridge to have end_session endpoint
kalyanoliveira Feb 21, 2026
08ecded
updates page.js to use the therapy components and new api routes prop…
kalyanoliveira Feb 21, 2026
e476e72
updates run_session and start agent endpoint in flask bridge
kalyanoliveira Feb 21, 2026
8fa28b6
removes the entire page.js
kalyanoliveira Feb 21, 2026
29fb701
updates therapy/chat route.js
kalyanoliveira Feb 21, 2026
f3c34b5
updates page.js
kalyanoliveira Feb 21, 2026
67eb50f
removes duplicate route definition in bridge.py
kalyanoliveira Feb 21, 2026
d08302a
writes db.py
kalyanoliveira Feb 21, 2026
1341410
updates agents.py to take into account db.py
kalyanoliveira Feb 21, 2026
29ead7f
updates bridge.py
kalyanoliveira Feb 21, 2026
37d4e6a
so many updates
kalyanoliveira Feb 21, 2026
268c2ce
removes the list-files.sh script
kalyanoliveira Feb 21, 2026
3de1e00
changes to agents.py to use newer gemini models
kalyanoliveira Feb 21, 2026
ba86a9d
updates model to 2.5-flash
kalyanoliveira Feb 21, 2026
200e91e
updates therapy session end route.js
kalyanoliveira Feb 21, 2026
084f956
writes a langchain tool for searching the vector db
kalyanoliveira Feb 21, 2026
a5169f7
docs: adds custom-guidelines workflow
kalyanoliveira Feb 21, 2026
d8866d1
binds langchain llm to new tool
kalyanoliveira Feb 21, 2026
0fdf810
chore: lowers temp of model
kalyanoliveira Feb 21, 2026
507766c
updates therapist_node agent to use tools
kalyanoliveira Feb 22, 2026
d9fb31b
writes a simple debug script for inspecting the vector db
kalyanoliveira Feb 22, 2026
529e50e
writes a fucntion to reset the db
kalyanoliveira Feb 22, 2026
a9adb65
adds logic to flask /init endpoint to also reset vector db
kalyanoliveira Feb 22, 2026
221b3e2
updates reset_db in db.py
kalyanoliveira Feb 22, 2026
0fc4495
updates wrap_up_node fn try except
kalyanoliveira Feb 22, 2026
cc6f468
adds check for object return in therapist node, and handles it properly
kalyanoliveira Feb 22, 2026
ec282bd
better response handling in therapy_node (after tool call)
kalyanoliveira Feb 22, 2026
da25560
ensures every message content is forced to a string in /run_session
kalyanoliveira Feb 22, 2026
5238826
write ensure_text fn in agents.py
kalyanoliveira Feb 22, 2026
0d67ce0
calls ensure_text() where appropriate
kalyanoliveira Feb 22, 2026
9ed8e13
updates agent.py and bridge.py to perform actual chat save under new …
kalyanoliveira Feb 22, 2026
a08b2aa
makes it more explicit to agents what the user id is
kalyanoliveira Feb 22, 2026
a8ed832
updates exercise_prompt to interactive/asynchronous dichotomy
kalyanoliveira Feb 22, 2026
99b4712
updates exercicse list to tkae into account the two different kinds o…
kalyanoliveira Feb 22, 2026
3d07d74
updates frontend to showcase newest func
kalyanoliveira Feb 22, 2026
d6e259b
achieves message streaming
kalyanoliveira Feb 22, 2026
cb1e71b
updates db.py to add keep connection alive logic
kalyanoliveira Feb 22, 2026
656b951
wraps end_session logic in keep connection alive wrapper
kalyanoliveira Feb 22, 2026
7021b8d
feat!: generates agenda in research_node
kalyanoliveira Feb 22, 2026
cd3543a
updates state.py to take into account agenda
kalyanoliveira Feb 22, 2026
97a85bc
updates agent.py to use the new agenda
kalyanoliveira Feb 22, 2026
c127144
Created prompt file
Gustavo-Galvao-e-Silva Feb 22, 2026
4ac8afb
Merge remote-tracking branch 'origin/refactor/streaming-responses' in…
kalyanoliveira Feb 22, 2026
98982da
achieves agenda functionality
kalyanoliveira Feb 22, 2026
156e83e
Tweaked prompts and added to agents.py
Gustavo-Galvao-e-Silva Feb 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions custom-guidelines-pseudocode.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
if session_notes:
custom_guidelines = get_cg("aklsdjfkljasdf", "fasdfasdjf")
else:

custom_guidelines = get_cg("aklsdjfkljasdf")

get_cg(general_guidelines, session_notes = "") -> str:
return custom_guidelines


systemp = f"{custom-guidelines}"
22 changes: 22 additions & 0 deletions src/client/app/api/journal/save/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { NextResponse } from 'next/server';

export async function POST(req) {
try {
const { userId, text, id } = await req.json();

// No vectorization here! Just send the raw text to Python.
const res = await fetch('http://localhost:5001/upsert', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
user_id: userId,
text: text,
id: id
})
});

return NextResponse.json(await res.json());
} catch (err) {
return NextResponse.json({ error: err.message }, { status: 500 });
}
}
50 changes: 50 additions & 0 deletions src/client/app/api/journal/summary/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { NextResponse } from 'next/server';
import { pipeline } from '@xenova/transformers';

export async function POST(req) {
try {
const { userId, topic } = await req.json();

// 1. Generate the Vector locally on your CPU
const pipe = await pipeline('feature-extraction', 'Xenova/all-MiniLM-L6-v2');
const output = await pipe(topic, { pooling: 'mean', normalize: true });
const vector = Array.from(output.data);

// 2. Fetch relevant entries from your Python Bridge
const actianRes = await fetch('http://localhost:5001/search', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
vector: vector,
user_id: userId
}),
});

const entries = await actianRes.json();

// Combine the retrieved logs into one "context" string
const context = entries.map(e => e.text).join("\n---\n");

// 3. Send to Ollama for the final summary
const ollamaRes = await fetch('http://localhost:11434/api/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: "llama3",
prompt: `Based on these journal entries:\n${context}\n\nSummarize the user's day regarding "${topic}" in one concise sentence.`,
stream: false
}),
});

const final = await ollamaRes.json();

return NextResponse.json({
summary: final.response,
rawContext: context
});

} catch (error) {
console.error("Pipeline Error:", error);
return NextResponse.json({ error: "Check if Bridge and Ollama are running" }, { status: 500 });
}
}
23 changes: 23 additions & 0 deletions src/client/app/api/therapy/chat/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export async function POST(req) {
const { userId, message, transcript, evidence, agenda } = await req.json();

const res = await fetch('http://localhost:5001/agent/run_session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
user_id: userId,
message: message,
transcript: transcript, // Pass history back to Python
evidence: evidence, // Pass evidence back to Python
agenda: agenda
})
});

if (!res.ok) throw new Error("Bridge failed");

const data = await res.json();
return Response.json({
reply: data.therapy_response,
fullTranscript: data.full_transcript
});
}
19 changes: 19 additions & 0 deletions src/client/app/api/therapy/chat_stream/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export async function POST(req) {
const body = await req.json();

const res = await fetch('http://localhost:5001/agent/chat_stream', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});

if (!res.ok) return new Response("Bridge Connection Failed", { status: 500 });

return new Response(res.body, {
headers: {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
},
});
}
23 changes: 23 additions & 0 deletions src/client/app/api/therapy/end/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export async function POST(req) {
try {
const body = await req.json();

const res = await fetch('http://localhost:5001/agent/end_session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
user_id: body.userId,
transcript: body.transcript,
evidence: body.evidence,
agenda: body.agenda
})
});

if (!res.ok) throw new Error("Bridge failed");

const data = await res.json();
return Response.json(data);
} catch (err) {
return Response.json({ error: err.message }, { status: 500 });
}
}
21 changes: 21 additions & 0 deletions src/client/app/api/therapy/start/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { NextResponse } from 'next/server';

export async function POST(req) {
const { userId, userNotes } = await req.json(); // Capture userNotes

const res = await fetch('http://localhost:5001/agent/start', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
user_id: userId,
user_notes: userNotes // Pass it to Flask
})
});

const data = await res.json();
return NextResponse.json({
openingMessage: data.food_for_thought,
evidenceFound: data.evidence,
agenda: data.agenda // Pass the generated agenda back to the frontend
});
}
42 changes: 42 additions & 0 deletions src/client/app/components/ExerciseList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"use client";
import { useState } from 'react';
import GuidedExercise from './GuidedExercise';

export default function ExerciseList({ exercises }) {
const [activeExercise, setActiveExercise] = useState(null);

if (activeExercise) {
return (
<GuidedExercise
title={activeExercise.title}
script={activeExercise.content}
onExit={() => setActiveExercise(null)}
/>
);
}

return (
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
{exercises.map((ex, i) => (
<div key={i} className="p-6 border rounded-2xl bg-white shadow-sm hover:shadow-md transition-shadow flex flex-col justify-between">
<div>
<span className={`text-xs font-bold px-2 py-1 rounded-full ${
ex.type === 'interactive' ? "bg-purple-100 text-purple-600" : "bg-blue-100 text-blue-600"
}`}>
{ex.type}
</span>
<h3 className="text-xl font-bold mt-4">{ex.title}</h3>
<p className="text-gray-600 mt-2 text-sm line-clamp-3">{ex.content}</p>
</div>

<button
onClick={() => ex.type === 'interactive' ? setActiveExercise(ex) : alert(ex.content)}
className="mt-6 w-full py-3 rounded-xl font-bold bg-gray-900 text-white hover:bg-black transition-colors"
>
{ex.type === 'interactive' ? "Start Guided Session" : "View Instructions"}
</button>
</div>
))}
</div>
);
}
68 changes: 68 additions & 0 deletions src/client/app/components/GuidedExercise.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
"use client";
import { useState, useEffect } from 'react';

export default function GuidedExercise({ title, script, onExit }) {
// Split the script by our special token
const sentences = script.split("[BREAK]").map(s => s.trim()).filter(s => s);
const [index, setIndex] = useState(0);
const [isPlaying, setIsPlaying] = useState(false);

const speak = (text) => {
// Stop any existing speech
window.speechSynthesis.cancel();

const utterance = new SpeechSynthesisUtterance(text);
utterance.rate = 0.9; // Slightly slower for therapy

utterance.onend = () => {
setIsPlaying(false);
// Auto-advance the index so the UI highlights the next sentence
if (index < sentences.length - 1) {
setIndex(prev => prev + 1);
}
};

window.speechSynthesis.speak(utterance);
setIsPlaying(true);
};

return (
<div className="fixed inset-0 bg-white z-50 flex flex-col items-center justify-center p-6">
<button onClick={onExit} className="absolute top-6 right-6 text-gray-400 hover:text-black">✕ Close</button>

<div className="max-w-2xl w-full text-center">
<span className="text-blue-500 font-bold uppercase tracking-widest text-xs">Guided Session</span>
<h2 className="text-3xl font-bold mt-2 mb-12">{title}</h2>

{/* The Karaoke Display */}
<div className="space-y-6 mb-12 text-2xl leading-relaxed">
{sentences.map((s, i) => (
<p key={i} className={`transition-all duration-500 ${
i === index ? "text-black font-medium scale-105" : "text-gray-200"
}`}>
{s}
</p>
))}
</div>

{/* Control Button */}
<button
onClick={() => isPlaying ? window.speechSynthesis.cancel() : speak(sentences[index])}
className={`w-20 h-20 rounded-full flex items-center justify-center shadow-xl transition-all ${
isPlaying ? "bg-red-500" : "bg-green-600 hover:scale-110"
} text-white`}
>
{isPlaying ? (
<div className="flex gap-1"><div className="w-2 h-6 bg-white"></div><div className="w-2 h-6 bg-white"></div></div>
) : (
<span className="text-3xl ml-1">▶</span>
)}
</button>

<p className="mt-6 text-gray-400 text-sm italic">
{index === sentences.length - 1 && !isPlaying ? "Exercise Complete" : "Press play to continue"}
</p>
</div>
</div>
);
}
Loading